From 93af0830cec3ac603838d06cb527f07075c7af08 Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Sat, 27 Nov 2021 09:02:27 -0600 Subject: [PATCH 01/40] Expand and refactor ailment treatment --- code/modules/organs/ailments/_ailment.dm | 38 +++++++++++-------- .../organs/ailments/ailments_medical.dm | 22 ++++++----- code/modules/organs/ailments/faults/_fault.dm | 4 +- code/modules/organs/organ.dm | 26 +++++-------- 4 files changed, 46 insertions(+), 44 deletions(-) diff --git a/code/modules/organs/ailments/_ailment.dm b/code/modules/organs/ailments/_ailment.dm index 0439d84f672..0d5c501b7ec 100644 --- a/code/modules/organs/ailments/_ailment.dm +++ b/code/modules/organs/ailments/_ailment.dm @@ -3,7 +3,7 @@ var/timer_id // Current timer waiting to proc next symptom message. var/min_time = 2 MINUTES // Minimum time between symptom messages. var/max_time = 5 MINUTES // Maximum time between symptom messages. - var/category = /datum/ailment // Used similar to heirarchies, if category == type then the + var/category = /datum/ailment // Used similar to hierarchies, if category == type then the // ailment is a category and won't be applied to organs. var/obj/item/organ/organ // Organ associated with the ailment (ailment is in organ.ailments list). @@ -13,16 +13,18 @@ var/specific_organ_subtype = /obj/item/organ/external // What organ subtype, if any, does the ailment apply to? // Treatment types - var/treated_by_item_type // What item type can be used in physical interaction to cure the ailment? - var/treated_by_item_cost = 1 // If treated_by_item_type is a stack, how many should be used? - var/treated_by_reagent_type // What reagent type cures this ailment when metabolized? - var/treated_by_reagent_dosage = 1 // What is the minimum dosage for a reagent to cure this ailment? + var/treated_by_item_type // What item type can be used in physical interaction to cure the ailment? + var/treated_by_item_cost = 1 // If treated_by_item_type is a stack, how many should be used? + var/treated_by_reagent_type // What reagent type cures this ailment when metabolized? + var/treated_by_reagent_dosage = 1 // What is the minimum dosage for a reagent to cure this ailment? + var/treated_by_chem_effect // What chemical effect cures this ailment? + var/treated_by_chem_effect_strength = 1 // How strong must the chemical effect be to cure this ailment? // Fluff strings var/initial_ailment_message = "Your $ORGAN$ doesn't feel quite right..." // Shown in New() - var/third_person_treatement_message = "$USER$ treats $TARGET$'s ailment with $ITEM$." // Shown when treating other with an item. - var/self_treatement_message = "$USER$ treats $USER_HIS$ ailment with $ITEM$." // Shown when treating self with an item. - var/medication_treatment_message = "Your ailment abates." // Shown when treated by a metabolized reagent. + var/third_person_treatment_message = "$USER$ treats $TARGET$'s ailment with $ITEM$." // Shown when treating other with an item. + var/self_treatment_message = "$USER$ treats $USER_HIS$ ailment with $ITEM$." // Shown when treating self with an item. + var/medication_treatment_message = "Your ailment abates." // Shown when treated by a metabolized reagent or CE_X effect. var/manual_diagnosis_string /* ex: "$USER_HIS$ $ORGAN$ has something wrong with it" */ // Shown when grab-diagnosed by a doctor. Leave null to be undiagnosable. var/scanner_diagnosis_string /* ex: "Significant swelling" */ // Shown on the handheld and body scanners. Leave null to be undiagnosable. @@ -31,7 +33,7 @@ if(_organ) organ = _organ if(organ.owner) - to_chat(organ.owner, SPAN_WARNING(capitalize(replacetext(initial_ailment_message, "$ORGAN$", organ.name)))) + to_chat(organ.owner, SPAN_WARNING(replace_tokens(initial_ailment_message))) begin_ailment_event() /datum/ailment/proc/can_apply_to(var/obj/item/organ/_organ) @@ -83,13 +85,13 @@ /datum/ailment/proc/was_treated_by_item(var/obj/item/treatment, var/mob/user, var/mob/target) var/show_message - if(user == target && self_treatement_message) - show_message = self_treatement_message + if(user == target && self_treatment_message) + show_message = self_treatment_message else - show_message = third_person_treatement_message + show_message = third_person_treatment_message if(!show_message) return - + user.visible_message(SPAN_NOTICE(replace_tokens(show_message, treatment, user, target))) if(istype(treatment, /obj/item/stack)) @@ -100,7 +102,11 @@ /datum/ailment/proc/treated_by_medication(var/decl/material/reagent, var/dosage) return treated_by_reagent_type && istype(reagent, treated_by_reagent_type) && dosage >= treated_by_reagent_dosage -/datum/ailment/proc/was_treated_by_medication(var/datum/reagents/dose) - dose.remove_reagent(treated_by_reagent_type, treated_by_reagent_dosage) - to_chat(organ.owner, SPAN_NOTICE(capitalize(replacetext(medication_treatment_message, "$ORGAN$", organ.name)))) +/datum/ailment/proc/was_treated_by_medication(var/datum/reagents/source, var/reagent_type) + source.remove_reagent(reagent_type, treated_by_reagent_dosage) + to_chat(organ.owner, SPAN_NOTICE(replace_tokens(medication_treatment_message))) + qdel(src) + +/datum/ailment/proc/was_treated_by_chem_effect() + to_chat(organ.owner, SPAN_NOTICE(replace_tokens(medication_treatment_message))) qdel(src) diff --git a/code/modules/organs/ailments/ailments_medical.dm b/code/modules/organs/ailments/ailments_medical.dm index f4c3d091ec9..dfad9fe167e 100644 --- a/code/modules/organs/ailments/ailments_medical.dm +++ b/code/modules/organs/ailments/ailments_medical.dm @@ -4,8 +4,8 @@ /datum/ailment/head/headache name = "headache" - treated_by_reagent_type = /decl/material/liquid/painkillers - treated_by_reagent_dosage = 1 + treated_by_chem_effect = CE_PAINKILLER + treated_by_chem_effect_strength = 25 medication_treatment_message = "Your headache grudgingly fades away." /datum/ailment/head/headache/on_ailment_event() @@ -55,8 +55,8 @@ name = "sprained limb" applies_to_organ = list(BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND, BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT) treated_by_item_type = /obj/item/stack/medical/bruise_pack - third_person_treatement_message = "$USER$ wraps $TARGET$'s sprained $ORGAN$ in $ITEM$." - self_treatement_message = "$USER$ wraps $USER_HIS$ sprained $ORGAN$ in $ITEM$." + third_person_treatment_message = "$USER$ wraps $TARGET$'s sprained $ORGAN$ in $ITEM$." + self_treatment_message = "$USER$ wraps $USER_HIS$ sprained $ORGAN$ in $ITEM$." manual_diagnosis_string = "$USER_HIS$ $ORGAN$ is visibly swollen." /datum/ailment/sprain/on_ailment_event() @@ -69,14 +69,14 @@ /datum/ailment/rash name = "rash" treated_by_item_type = /obj/item/stack/medical/ointment - third_person_treatement_message = "$USER$ salves $TARGET$'s rash-stricken $ORGAN$ with $ITEM$." - self_treatement_message = "$USER$ salves $USER_HIS$ rash-stricken $ORGAN$ with $ITEM$." + third_person_treatment_message = "$USER$ salves $TARGET$'s rash-stricken $ORGAN$ with $ITEM$." + self_treatment_message = "$USER$ salves $USER_HIS$ rash-stricken $ORGAN$ with $ITEM$." manual_diagnosis_string = "$USER_HIS$ $ORGAN$ is covered in a bumpy red rash." /datum/ailment/rash/on_ailment_event() to_chat(organ.owner, SPAN_DANGER("A bright red rash on your [organ.name] itches distractingly.")) organ.owner.setClickCooldown(3) - + /datum/ailment/coughing name = "coughing" specific_organ_subtype = /obj/item/organ/internal/lungs @@ -97,7 +97,8 @@ /datum/ailment/sore_joint name = "sore joint" - treated_by_reagent_type = /decl/material/liquid/painkillers + treated_by_chem_effect = CE_PAINKILLER + treated_by_chem_effect_strength = 25 medication_treatment_message = "The dull pulse of pain in your $ORGAN$ fades away." manual_diagnosis_string = "$USER_HIS$ $ORGAN$ is visibly swollen." @@ -115,7 +116,8 @@ /datum/ailment/sore_back name = "sore back" applies_to_organ = list(BP_CHEST) - treated_by_reagent_type = /decl/material/liquid/painkillers + treated_by_chem_effect = CE_PAINKILLER + treated_by_chem_effect_strength = 25 medication_treatment_message = "You straighten, finding that your back is no longer hurting." /datum/ailment/sore_back/on_ailment_event() @@ -135,7 +137,7 @@ /datum/ailment/cramps name = "cramps" - treated_by_reagent_type = /decl/material/liquid/painkillers + treated_by_reagent_type = /decl/material/liquid/sedatives // in lieu of muscle relaxants medication_treatment_message = "The painful cramping in your $ORGAN$ relaxes." /datum/ailment/cramps/on_ailment_event() diff --git a/code/modules/organs/ailments/faults/_fault.dm b/code/modules/organs/ailments/faults/_fault.dm index 563948419c3..589d3759664 100644 --- a/code/modules/organs/ailments/faults/_fault.dm +++ b/code/modules/organs/ailments/faults/_fault.dm @@ -3,6 +3,6 @@ category = /datum/ailment/fault treated_by_item_type = /obj/item/stack/nanopaste treated_by_item_cost = 3 - third_person_treatement_message = "$USER$ patches $TARGET$'s faulty $ORGAN$ with $ITEM$." - self_treatement_message = "$USER$ patches $USER_HIS$'s faulty $ORGAN$ with $ITEM$." + third_person_treatment_message = "$USER$ patches $TARGET$'s faulty $ORGAN$ with $ITEM$." + self_treatment_message = "$USER$ patches $USER_HIS$'s faulty $ORGAN$ with $ITEM$." initial_ailment_message = "Damage to your $ORGAN$ has caused a fault..." diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index b3f3d4bda15..fda1ea81048 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -145,22 +145,16 @@ handle_germ_effects() if(owner && length(ailments)) - for(var/datum/ailment/ailment in ailments) - if(!ailment.treated_by_reagent_type) - continue - var/treated - var/datum/reagents/bloodstr_reagents = owner.get_injected_reagents() - if(bloodstr_reagents) - if(REAGENT_VOLUME(bloodstr_reagents, ailment.treated_by_reagent_type) >= ailment.treated_by_reagent_dosage) - treated = bloodstr_reagents - else if(REAGENT_VOLUME(owner.reagents, ailment.treated_by_reagent_type) >= ailment.treated_by_reagent_dosage) - treated = owner.reagents - else - var/datum/reagents/ingested = owner.get_ingested_reagents() - if(ingested && REAGENT_VOLUME(ingested, ailment.treated_by_reagent_type) >= ailment.treated_by_reagent_dosage) - treated = ingested - if(treated) - ailment.was_treated_by_medication(treated) + ailment_loop: + for(var/datum/ailment/ailment in ailments) + if(ailment.treated_by_reagent_type) + for(var/datum/reagents/source in list(owner.get_injected_reagents(), owner.reagents, owner.get_ingested_reagents())) + for(var/reagent_type in source.reagent_volumes) + if(ailment.treated_by_medication(source.reagent_volumes[reagent_type])) + ailment.was_treated_by_medication(source, reagent_type) + continue ailment_loop + if(ailment.treated_by_chem_effect && owner.has_chemical_effect(ailment.treated_by_chem_effect, ailment.treated_by_chem_effect_strength)) + ailment.was_treated_by_chem_effect() //check if we've hit max_damage if(damage >= max_damage) From 54e792c50355dc12807989f85ff36913a9686547 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 7 Dec 2021 13:05:16 +1100 Subject: [PATCH 02/40] Allows cosmosharks to update icon properly. --- code/modules/mob/living/simple_animal/hostile/carp.dm | 7 ++++--- maps/away/errant_pisces/errant_pisces.dm | 4 ---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index 12563ab518e..6a03420ecf4 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -45,9 +45,10 @@ /mob/living/simple_animal/hostile/carp/on_update_icon() . = ..() color = carp_color - var/image/I = image(icon, "[icon_state]-eyes") - I.appearance_flags |= RESET_COLOR - add_overlay(I) + if(check_state_in_icon("[icon_state]-eyes", icon)) + var/image/I = image(icon, "[icon_state]-eyes") + I.appearance_flags |= RESET_COLOR + add_overlay(I) /mob/living/simple_animal/hostile/carp/Process_Spacemove() return 1 //No drifting in space for space carp! //original comments do not steal diff --git a/maps/away/errant_pisces/errant_pisces.dm b/maps/away/errant_pisces/errant_pisces.dm index f8a1c0ebde1..ac9a4f49733 100644 --- a/maps/away/errant_pisces/errant_pisces.dm +++ b/maps/away/errant_pisces/errant_pisces.dm @@ -34,10 +34,6 @@ /mob/living/simple_animal/hostile/carp/shark/carp_randomify() return -/mob/living/simple_animal/hostile/carp/shark/on_update_icon() - SHOULD_CALL_PARENT(FALSE) - return - /mob/living/simple_animal/hostile/carp/shark/death() ..() var/datum/gas_mixture/environment = loc.return_air() From d949031f3eb6dbd004cef6ff6d9770a5e49256b5 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 7 Dec 2021 13:10:55 +1100 Subject: [PATCH 03/40] Expanded text entry field for mind read, added sanitization. --- mods/content/psionics/system/psionics/faculties/coercion.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/content/psionics/system/psionics/faculties/coercion.dm b/mods/content/psionics/system/psionics/faculties/coercion.dm index 6d650952725..f509fb29631 100644 --- a/mods/content/psionics/system/psionics/faculties/coercion.dm +++ b/mods/content/psionics/system/psionics/faculties/coercion.dm @@ -78,7 +78,7 @@ to_chat(user, SPAN_NOTICE("You dip your mentality into the surface layer of \the [target]'s mind, seeking an answer: [question]")) to_chat(target, SPAN_NOTICE("Your mind is compelled to answer: [question]")) - var/answer = input(target, question, "Read Mind") as null|text + var/answer = sanitize((input(target, question, "Read Mind") as null|message), MAX_MESSAGE_LEN) if(!answer || world.time > started_mindread + 60 SECONDS || user.stat != CONSCIOUS || target.stat == DEAD) to_chat(user, SPAN_NOTICE("You receive nothing useful from \the [target].")) else From d75a86fc20d134d3e1a7582baa2f7376b02ae204 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 7 Dec 2021 13:13:26 +1100 Subject: [PATCH 04/40] Cans and bottles now opt out of desc/name customization based on contents. --- code/modules/reagents/reagent_containers/drinks/bottle.dm | 3 +++ code/modules/reagents/reagent_containers/drinks/cans.dm | 3 +++ 2 files changed, 6 insertions(+) diff --git a/code/modules/reagents/reagent_containers/drinks/bottle.dm b/code/modules/reagents/reagent_containers/drinks/bottle.dm index 6fecaaec658..b9fc59a144f 100644 --- a/code/modules/reagents/reagent_containers/drinks/bottle.dm +++ b/code/modules/reagents/reagent_containers/drinks/bottle.dm @@ -30,6 +30,9 @@ rag = null return ..() +/obj/item/chems/drinks/bottle/on_reagent_change() + return + //when thrown on impact, bottles smash and spill their contents /obj/item/chems/drinks/bottle/throw_impact(atom/hit_atom, var/datum/thrownthing/TT) ..() diff --git a/code/modules/reagents/reagent_containers/drinks/cans.dm b/code/modules/reagents/reagent_containers/drinks/cans.dm index 8e8cd9acaf5..170ed67a755 100644 --- a/code/modules/reagents/reagent_containers/drinks/cans.dm +++ b/code/modules/reagents/reagent_containers/drinks/cans.dm @@ -4,6 +4,9 @@ atom_flags = 0 //starts closed material = /decl/material/solid/metal/aluminium +/obj/item/chems/drinks/cans/on_reagent_change() + return + //DRINKS /obj/item/chems/drinks/cans/cola From aa6979b8498a0025c85ffdd388126da9bbb96c5d Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 7 Dec 2021 13:16:21 +1100 Subject: [PATCH 05/40] Brain damage text is no longer twice the maximum size. --- code/modules/organs/internal/brain.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index 643a2ee62fa..be8614a0c3d 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -211,7 +211,7 @@ /obj/item/organ/internal/brain/proc/brain_damage_callback(var/damage) //Confuse them as a somewhat uncommon aftershock. Side note: Only here so a spawn isn't used. Also, for the sake of a unique timer. if(!QDELETED(owner)) - to_chat(owner, SPAN_NOTICE("I can't remember which way is forward...")) + to_chat(owner, SPAN_NOTICE(FONT_HUGE("I can't remember which way is forward..."))) ADJ_STATUS(owner, STAT_CONFUSE, damage) /obj/item/organ/internal/brain/proc/handle_disabilities() From ee2c02be16b3592fb33ccd89dbd8f7225a3e40d2 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 7 Dec 2021 13:28:20 +1100 Subject: [PATCH 06/40] Wind effects are no longer applied to turfs with no atmosphere. --- code/__defines/misc.dm | 3 +++ code/game/turfs/turf.dm | 2 +- code/modules/weather/weather_effects.dm | 4 ++-- code/modules/weather/weather_wind.dm | 16 ++++++++++------ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 1d7dab5188e..40cdeb0b782 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -286,3 +286,6 @@ #define WRITTEN_SKIP 0 #define WRITTEN_PHYSICAL 1 #define WRITTEN_DIGITAL 2 + +// arbitrary low pressure bound for wind weather effects +#define MIN_WIND_PRESSURE 10 diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 1fc5d75afe0..6ae6ef97ce5 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -130,7 +130,7 @@ /turf/proc/get_movement_delay(var/travel_dir) . = get_base_movement_delay() if(weather) - . += weather.get_movement_delay(travel_dir) + . += weather.get_movement_delay(return_air(), travel_dir) /turf/attack_hand(mob/user) user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) diff --git a/code/modules/weather/weather_effects.dm b/code/modules/weather/weather_effects.dm index d12aad152d7..8499824ddce 100644 --- a/code/modules/weather/weather_effects.dm +++ b/code/modules/weather/weather_effects.dm @@ -1,7 +1,7 @@ -/obj/abstract/weather_system/proc/get_movement_delay(var/travel_dir) +/obj/abstract/weather_system/proc/get_movement_delay(var/datum/gas_mixture/env, var/travel_dir) // It's quiet. Too quiet. - if(!wind_direction || !base_wind_delay || !travel_dir) + if(!wind_direction || !base_wind_delay || !travel_dir || !env || env.return_pressure() < MIN_WIND_PRESSURE) return 0 // May the wind be always at your back! diff --git a/code/modules/weather/weather_wind.dm b/code/modules/weather/weather_wind.dm index 12add656a2f..2453fe06fdf 100644 --- a/code/modules/weather/weather_wind.dm +++ b/code/modules/weather/weather_wind.dm @@ -26,9 +26,13 @@ if(mob_shown_wind[mob_ref]) return FALSE mob_shown_wind[weakref(M)] = TRUE - var/absolute_strength = abs(wind_strength) - if(absolute_strength <= 0.5 || !wind_direction) - to_chat(M, SPAN_NOTICE("The wind is calm.")) - else - to_chat(M, SPAN_NOTICE("The wind is blowing[absolute_strength > 2 ? " strongly" : ""] towards the [dir2text(wind_direction)].")) - return TRUE + . = TRUE + var/turf/T = get_turf(M) + if(istype(T)) + var/datum/gas_mixture/environment = T.return_air() + if(environment && environment.return_pressure() >= MIN_WIND_PRESSURE) // Arbitrary low pressure bound. + var/absolute_strength = abs(wind_strength) + if(absolute_strength <= 0.5 || !wind_direction) + to_chat(M, SPAN_NOTICE("The wind is calm.")) + else + to_chat(M, SPAN_NOTICE("The wind is blowing[absolute_strength > 2 ? " strongly" : ""] towards the [dir2text(wind_direction)].")) From 8eac4c15e77d0f593f08bd16bdefc11297a039f7 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 7 Dec 2021 13:33:12 +1100 Subject: [PATCH 07/40] Cleans up some uses of the wrong tape type, clarifies taperoll vs tape_roll. --- code/datums/supplypacks/operations.dm | 2 +- code/datums/uplink/devices and tools.dm | 2 +- code/game/machinery/vending/engineering.dm | 2 +- code/game/objects/items/stacks/rods.dm | 2 +- .../game/objects/items/weapons/storage/belt.dm | 18 ++++++++---------- code/game/objects/items/weapons/tape.dm | 8 ++++---- code/game/objects/random/random.dm | 2 +- code/game/objects/structures/inflatable.dm | 2 +- code/modules/clothing/spacesuits/breaches.dm | 2 +- code/modules/crafting/_crafting_stage.dm | 2 +- .../designs/general/designs_general.dm | 4 ++-- code/modules/paperwork/paper.dm | 4 ++-- code/modules/paperwork/paper_bundle.dm | 2 +- code/modules/supermatter/supermatter.dm | 2 +- code/modules/surgery/organs_internal.dm | 2 +- maps/antag_spawn/ert/ert_base.dmm | 8 ++++---- maps/away/bearcat/bearcat-1.dmm | 6 +++--- maps/away/bearcat/bearcat-2.dmm | 2 +- maps/away/errant_pisces/errant_pisces.dmm | 2 +- maps/exodus/exodus-2.dmm | 16 ++++++++-------- .../exoplanet_ruins/playablecolony/colony.dmm | 4 ++-- maps/tradeship/tradeship-1.dmm | 6 +++--- maps/tradeship/tradeship-2.dmm | 2 +- 23 files changed, 50 insertions(+), 52 deletions(-) diff --git a/code/datums/supplypacks/operations.dm b/code/datums/supplypacks/operations.dm index 59e82647bbc..cb594f257ea 100644 --- a/code/datums/supplypacks/operations.dm +++ b/code/datums/supplypacks/operations.dm @@ -90,7 +90,7 @@ /obj/item/folder/red, /obj/item/folder/yellow, /obj/item/hand_labeler, - /obj/item/tape_roll, + /obj/item/ducttape, /obj/structure/filingcabinet/chestdrawer, /obj/item/paper_bin) name = "Office supplies" diff --git a/code/datums/uplink/devices and tools.dm b/code/datums/uplink/devices and tools.dm index eb05d6d9a28..788163c0a5c 100644 --- a/code/datums/uplink/devices and tools.dm +++ b/code/datums/uplink/devices and tools.dm @@ -15,7 +15,7 @@ name = "Duct Tape" desc = "A roll of duct tape. changes \"HELP\" into sexy \"mmm\"." item_cost = 2 - path = /obj/item/tape_roll + path = /obj/item/ducttape /datum/uplink_item/item/tools/money name = "Operations Funding" diff --git a/code/game/machinery/vending/engineering.dm b/code/game/machinery/vending/engineering.dm index 18d7cd188a9..d09812099b9 100644 --- a/code/game/machinery/vending/engineering.dm +++ b/code/game/machinery/vending/engineering.dm @@ -18,7 +18,7 @@ /obj/item/screwdriver = 5, /obj/item/flashlight/flare/glowstick = 3, /obj/item/flashlight/flare/glowstick/red = 3, - /obj/item/tape_roll = 8, + /obj/item/ducttape = 8, /obj/item/clothing/gloves/insulated/cheap = 2 ) contraband = list( diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 4108969fc3c..e4a7e7d4612 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -70,7 +70,7 @@ use(2) return - if (istype(W, /obj/item/tape_roll)) + if (istype(W, /obj/item/ducttape)) var/obj/item/stack/medical/splint/ghetto/new_splint = new(user.loc) new_splint.dropInto(loc) new_splint.add_fingerprint(user) diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index b43147828a6..7b1daf03593 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -265,9 +265,9 @@ /obj/item/radio/headset, /obj/item/megaphone, /obj/item/taperoll, + /obj/item/magnetic_tape, /obj/item/holowarrant, /obj/item/radio, - /obj/item/tape, /obj/item/pen, /obj/item/stamp, /obj/item/stack/package_wrap, @@ -310,6 +310,8 @@ /obj/item/flash, /obj/item/telebaton, /obj/item/taperecorder, + /obj/item/magnetic_tape, + /obj/item/taperoll, /obj/item/folder, /obj/item/paper, /obj/item/clipboard, @@ -319,10 +321,8 @@ /obj/item/modular_computer/pda, /obj/item/radio/headset, /obj/item/megaphone, - /obj/item/taperoll, /obj/item/holowarrant, /obj/item/radio, - /obj/item/tape, /obj/item/pen, /obj/item/stamp, /obj/item/stack/package_wrap, @@ -351,16 +351,14 @@ /obj/item/forensics/sample/print, /obj/item/forensics/sample/fibers, /obj/item/taperecorder, - /obj/item/tape, + /obj/item/magnetic_tape, /obj/item/clothing/gloves/latex, /obj/item/clothing/gloves/forensic, /obj/item/folder, /obj/item/paper, /obj/item/forensics/sample_kit, - /obj/item/camera, - /obj/item/taperecorder, - /obj/item/tape - ) + /obj/item/camera + ) /obj/item/storage/belt/holster/machete name = "machete belt" @@ -386,9 +384,9 @@ /obj/item/radio/beacon, /obj/item/pinpointer/radio, /obj/item/taperecorder, - /obj/item/tape, + /obj/item/magnetic_tape, /obj/item/scanner/gas - ) + ) can_holster = list(/obj/item/hatchet/machete) sound_in = 'sound/effects/holster/sheathin.ogg' sound_out = 'sound/effects/holster/sheathout.ogg' diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm index dfd5709968c..dfc32c4a9b5 100644 --- a/code/game/objects/items/weapons/tape.dm +++ b/code/game/objects/items/weapons/tape.dm @@ -1,18 +1,18 @@ -/obj/item/tape_roll +/obj/item/ducttape name = "duct tape" desc = "A roll of sticky tape. Possibly for taping ducks... or was that ducts?" icon = 'icons/obj/bureaucracy.dmi' icon_state = "taperoll" w_class = ITEM_SIZE_SMALL -/obj/item/tape_roll/Initialize() +/obj/item/ducttape/Initialize() . = ..() set_extension(src, /datum/extension/tool, list( TOOL_BONE_GEL = TOOL_QUALITY_MEDIOCRE, TOOL_SUTURES = TOOL_QUALITY_BAD )) -/obj/item/tape_roll/attack(var/mob/living/carbon/human/H, var/mob/user) +/obj/item/ducttape/attack(var/mob/living/carbon/human/H, var/mob/user) if(istype(H)) if(user.zone_sel.selecting == BP_EYES) @@ -83,7 +83,7 @@ return ..() return 1 -/obj/item/tape_roll/proc/stick(var/obj/item/W, mob/user) +/obj/item/ducttape/proc/stick(var/obj/item/W, mob/user) if(!istype(W, /obj/item/paper) || istype(W, /obj/item/paper/sticky) || !user.unEquip(W)) return var/obj/item/ducttape/tape = new(get_turf(src)) diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm index 910d6d2a0d7..940481e935c 100644 --- a/code/game/objects/random/random.dm +++ b/code/game/objects/random/random.dm @@ -131,7 +131,7 @@ /obj/item/storage/belt/utility = 2, /obj/item/storage/belt/utility/atmostech = 1, /obj/random/tool = 5, - /obj/item/tape_roll = 2) + /obj/item/ducttape = 2) /obj/random/medical name = "Random Medical equipment" diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index 7d4e77ed72f..ac733e29dab 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -120,7 +120,7 @@ add_fingerprint(user) /obj/structure/inflatable/can_repair_with(obj/item/tool) - . = istype(tool, /obj/item/tape_roll) && (health < maxhealth) + . = istype(tool, /obj/item/ducttape) && (health < maxhealth) /obj/structure/inflatable/handle_repair(mob/user, obj/item/tool) if(taped) diff --git a/code/modules/clothing/spacesuits/breaches.dm b/code/modules/clothing/spacesuits/breaches.dm index 292bc8ffe73..9dfa71691f7 100644 --- a/code/modules/clothing/spacesuits/breaches.dm +++ b/code/modules/clothing/spacesuits/breaches.dm @@ -228,7 +228,7 @@ repair_breaches(BRUTE, 3, user) return - else if(istype(W, /obj/item/tape_roll)) + else if(istype(W, /obj/item/ducttape)) var/datum/breach/target_breach //Target the largest unpatched breach. for(var/datum/breach/B in breaches) if(B.patched) diff --git a/code/modules/crafting/_crafting_stage.dm b/code/modules/crafting/_crafting_stage.dm index 6469b0f6a77..e2283ad694a 100644 --- a/code/modules/crafting/_crafting_stage.dm +++ b/code/modules/crafting/_crafting_stage.dm @@ -92,7 +92,7 @@ /decl/crafting_stage/tape consume_completion_trigger = FALSE - completion_trigger_type = /obj/item/tape_roll + completion_trigger_type = /obj/item/ducttape /decl/crafting_stage/pipe completion_trigger_type = /obj/item/pipe diff --git a/code/modules/fabrication/designs/general/designs_general.dm b/code/modules/fabrication/designs/general/designs_general.dm index 7f9234ca2ad..a0c6cbbf25d 100644 --- a/code/modules/fabrication/designs/general/designs_general.dm +++ b/code/modules/fabrication/designs/general/designs_general.dm @@ -34,8 +34,8 @@ /datum/fabricator_recipe/taperecorder path = /obj/item/taperecorder/empty -/datum/fabricator_recipe/tape - path = /obj/item/tape +/datum/fabricator_recipe/taperecorder_tape + path = /obj/item/magnetic_tape /datum/fabricator_recipe/tube/large path = /obj/item/light/tube/large diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 0e6e2e69309..2a6d5550df1 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -360,8 +360,8 @@ if(user.mind && (user.mind.assigned_role == "Clown")) clown = 1 - if(istype(P, /obj/item/tape_roll)) - var/obj/item/tape_roll/tape = P + if(istype(P, /obj/item/ducttape)) + var/obj/item/ducttape/tape = P tape.stick(src, user) return diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index 1d15d3728e4..70eca22bc09 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -46,7 +46,7 @@ to_chat(user, "You add \the [W.name] to [(src.name == "paper bundle") ? "the paper bundle" : src.name].") qdel(W) else - if(istype(W, /obj/item/tape_roll)) + if(istype(W, /obj/item/ducttape)) return 0 if(istype(W, /obj/item/pen)) show_browser(user, "", "window=[name]") //Closes the dialog diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index 7813d66b1d6..e49d5db6643 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -621,7 +621,7 @@ var/global/list/supermatter_delam_accent_sounds = list( /obj/machinery/power/supermatter/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/tape_roll)) + if(istype(W, /obj/item/ducttape)) to_chat(user, "You repair some of the damage to \the [src] with \the [W].") damage = max(damage -10, 0) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 6fccc384d4e..dc39514ae32 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -19,7 +19,7 @@ allowed_tools = list( /obj/item/stack/medical/advanced/bruise_pack = 100, /obj/item/stack/medical/bruise_pack = 40, - /obj/item/tape_roll = 20 + /obj/item/ducttape = 20 ) min_duration = 70 max_duration = 90 diff --git a/maps/antag_spawn/ert/ert_base.dmm b/maps/antag_spawn/ert/ert_base.dmm index 8e145da026c..b75508d2d58 100644 --- a/maps/antag_spawn/ert/ert_base.dmm +++ b/maps/antag_spawn/ert/ert_base.dmm @@ -2225,10 +2225,10 @@ /obj/item/taperoll/atmos, /obj/item/multitool, /obj/item/multitool, -/obj/item/tape_roll, -/obj/item/tape_roll, -/obj/item/tape_roll, -/obj/item/tape_roll, +/obj/item/ducttape, +/obj/item/ducttape, +/obj/item/ducttape, +/obj/item/ducttape, /obj/item/cell/high, /obj/item/cell/high, /obj/item/cell/high, diff --git a/maps/away/bearcat/bearcat-1.dmm b/maps/away/bearcat/bearcat-1.dmm index 753b25390c2..1b32339b73e 100644 --- a/maps/away/bearcat/bearcat-1.dmm +++ b/maps/away/bearcat/bearcat-1.dmm @@ -1938,7 +1938,7 @@ pixel_y = 32; req_access = newlist() }, -/obj/item/tape_roll, +/obj/item/ducttape, /obj/machinery/light_switch{ pixel_x = -24 }, @@ -2406,7 +2406,7 @@ /turf/simulated/floor/tiled/usedup, /area/ship/scrap/maintenance/storage) "eS" = ( -/obj/item/tape_roll, +/obj/item/ducttape, /obj/item/stack/material/reinforced/mapped/plasteel/fifty, /obj/item/stack/material/ingot/mapped/copper/fifty, /obj/item/stack/material/rods/fifty, @@ -2423,7 +2423,7 @@ "eT" = ( /obj/item/clothing/head/welding, /obj/item/radio, -/obj/item/tape_roll, +/obj/item/ducttape, /obj/structure/table, /obj/item/radio/intercom{ pixel_y = -32 diff --git a/maps/away/bearcat/bearcat-2.dmm b/maps/away/bearcat/bearcat-2.dmm index 36494e1aa25..6b5e412df31 100644 --- a/maps/away/bearcat/bearcat-2.dmm +++ b/maps/away/bearcat/bearcat-2.dmm @@ -2515,7 +2515,7 @@ /obj/structure/closet/medical_wall/filled{ pixel_y = -32 }, -/obj/item/tape_roll, +/obj/item/ducttape, /obj/item/retractor, /obj/item/scalpel, /turf/simulated/floor/tiled/white, diff --git a/maps/away/errant_pisces/errant_pisces.dmm b/maps/away/errant_pisces/errant_pisces.dmm index a316c6ea4f5..36f3fd925c3 100644 --- a/maps/away/errant_pisces/errant_pisces.dmm +++ b/maps/away/errant_pisces/errant_pisces.dmm @@ -4196,7 +4196,7 @@ /area/errant_pisces/science_wing) "lx" = ( /obj/structure/table, -/obj/item/tape_roll, +/obj/item/ducttape, /turf/simulated/floor/tiled, /area/errant_pisces/science_wing) "ly" = ( diff --git a/maps/exodus/exodus-2.dmm b/maps/exodus/exodus-2.dmm index ecc10372127..560bc4a9c7a 100644 --- a/maps/exodus/exodus-2.dmm +++ b/maps/exodus/exodus-2.dmm @@ -5899,7 +5899,7 @@ }, /obj/item/clipboard, /obj/item/hand_labeler, -/obj/item/tape_roll, +/obj/item/ducttape, /turf/simulated/floor/tiled/dark, /area/exodus/lawoffice) "amt" = ( @@ -8644,7 +8644,7 @@ /obj/structure/table/reinforced, /obj/item/clipboard, /obj/item/hand_labeler, -/obj/item/tape_roll, +/obj/item/ducttape, /turf/simulated/floor/tiled/dark, /area/exodus/lawoffice) "arR" = ( @@ -14517,7 +14517,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/obj/item/tape_roll, +/obj/item/ducttape, /turf/simulated/floor/wood/walnut, /area/exodus/library) "aEG" = ( @@ -23878,7 +23878,7 @@ }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/item/tape_roll, +/obj/item/ducttape, /obj/structure/table, /turf/simulated/floor/tiled/steel_grid, /area/exodus/crew_quarters/locker) @@ -31905,7 +31905,7 @@ pixel_x = -27; pixel_y = 1 }, -/obj/item/tape_roll, +/obj/item/ducttape, /obj/structure/table{ name = "plastic table frame" }, @@ -54949,7 +54949,7 @@ }, /obj/item/paper_bin, /obj/item/pen, -/obj/item/tape_roll, +/obj/item/ducttape, /turf/simulated/floor/tiled/white, /area/exodus/research/xenobiology/xenoflora) "cjD" = ( @@ -55628,7 +55628,7 @@ "clf" = ( /obj/structure/table/reinforced, /obj/item/clipboard, -/obj/item/tape_roll, +/obj/item/ducttape, /turf/simulated/floor/tiled/steel_grid, /area/exodus/engineering/foyer) "clg" = ( @@ -59192,7 +59192,7 @@ }, /obj/item/paper_bin, /obj/item/pen, -/obj/item/tape_roll, +/obj/item/ducttape, /turf/simulated/floor/tiled/white, /area/exodus/research/xenobiology) "ctX" = ( diff --git a/maps/random_ruins/exoplanet_ruins/playablecolony/colony.dmm b/maps/random_ruins/exoplanet_ruins/playablecolony/colony.dmm index 45568b92731..2ac110bcad6 100644 --- a/maps/random_ruins/exoplanet_ruins/playablecolony/colony.dmm +++ b/maps/random_ruins/exoplanet_ruins/playablecolony/colony.dmm @@ -2362,8 +2362,8 @@ "fd" = ( /obj/structure/table/steel_reinforced, /obj/item/storage/toolbox/syndicate, -/obj/item/tape_roll, -/obj/item/tape_roll, +/obj/item/ducttape, +/obj/item/ducttape, /obj/item/crowbar/brace_jack, /obj/item/clothing/head/hardhat/white, /obj/item/grenade/chem_grenade/metalfoam, diff --git a/maps/tradeship/tradeship-1.dmm b/maps/tradeship/tradeship-1.dmm index 5f21c31f545..da4b13a7af9 100644 --- a/maps/tradeship/tradeship-1.dmm +++ b/maps/tradeship/tradeship-1.dmm @@ -3263,7 +3263,7 @@ /turf/simulated/wall/r_wall/hull, /area/ship/trade/crew/dorms2) "Vm" = ( -/obj/item/tape_roll, +/obj/item/ducttape, /obj/item/stack/material/reinforced/mapped/plasteel/fifty, /obj/item/stack/material/ingot/mapped/copper/fifty, /obj/item/stack/material/rods/fifty, @@ -3277,7 +3277,7 @@ /obj/item/stack/material/reinforced/mapped/fiberglass/fifty, /obj/item/clothing/head/welding, /obj/item/stack/material/cardstock/mapped/cardboard/fifty, -/obj/item/tape_roll, +/obj/item/ducttape, /obj/item/taperoll/engineering, /turf/simulated/floor/tiled/techfloor, /area/ship/trade/maintenance/techstorage) @@ -3337,7 +3337,7 @@ }, /obj/item/t_scanner, /obj/item/cell/high, -/obj/item/tape_roll, +/obj/item/ducttape, /obj/item/stock_parts/circuitboard/air_alarm, /obj/item/stock_parts/circuitboard/airlock_electronics, /obj/item/stock_parts/circuitboard/airlock_electronics, diff --git a/maps/tradeship/tradeship-2.dmm b/maps/tradeship/tradeship-2.dmm index 07b59f4f7f6..afa8025c30a 100644 --- a/maps/tradeship/tradeship-2.dmm +++ b/maps/tradeship/tradeship-2.dmm @@ -6514,7 +6514,7 @@ /obj/structure/closet/medical_wall/filled{ pixel_y = -32 }, -/obj/item/tape_roll, +/obj/item/ducttape, /obj/item/storage/firstaid/surgery, /turf/simulated/floor/tiled/white, /area/ship/trade/crew/medbay) From a46f7737cd1787c4e42e7abe65d15b302e8b6d05 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 7 Dec 2021 13:47:58 +1100 Subject: [PATCH 08/40] APCs should play their failure sound only on first failure. --- code/modules/power/apc.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index e909f5752e2..9f06dcb7842 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -226,8 +226,9 @@ var/global/list/all_apcs = list() /obj/machinery/power/apc/proc/energy_fail(var/duration) if(emp_hardened) return + if(!failure_timer && duration) + playsound(src, 'sound/machines/apc_nopower.ogg', 75, 0) failure_timer = max(failure_timer, round(duration)) - playsound(src, 'sound/machines/apc_nopower.ogg', 75, 0) /obj/machinery/power/apc/proc/init_round_start() var/obj/item/stock_parts/power/terminal/term = get_component_of_type(/obj/item/stock_parts/power/terminal) From 8fbe132b402b9f9fc0492c8a741abd68f0f756f0 Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Thu, 9 Dec 2021 20:48:32 -0600 Subject: [PATCH 09/40] Remove continue-to-label in ailment handling --- code/modules/organs/organ.dm | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index fda1ea81048..d483c13e2b4 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -145,21 +145,23 @@ handle_germ_effects() if(owner && length(ailments)) - ailment_loop: - for(var/datum/ailment/ailment in ailments) - if(ailment.treated_by_reagent_type) - for(var/datum/reagents/source in list(owner.get_injected_reagents(), owner.reagents, owner.get_ingested_reagents())) - for(var/reagent_type in source.reagent_volumes) - if(ailment.treated_by_medication(source.reagent_volumes[reagent_type])) - ailment.was_treated_by_medication(source, reagent_type) - continue ailment_loop - if(ailment.treated_by_chem_effect && owner.has_chemical_effect(ailment.treated_by_chem_effect, ailment.treated_by_chem_effect_strength)) - ailment.was_treated_by_chem_effect() + for(var/datum/ailment/ailment in ailments) + handle_ailment(ailment) //check if we've hit max_damage if(damage >= max_damage) die() +/obj/item/organ/proc/handle_ailment(var/datum/ailment/ailment) + if(ailment.treated_by_reagent_type) + for(var/datum/reagents/source in list(owner.get_injected_reagents(), owner.reagents, owner.get_ingested_reagents())) + for(var/reagent_type in source.reagent_volumes) + if(ailment.treated_by_medication(source.reagent_volumes[reagent_type])) + ailment.was_treated_by_medication(source, reagent_type) + return + if(ailment.treated_by_chem_effect && owner.has_chemical_effect(ailment.treated_by_chem_effect, ailment.treated_by_chem_effect_strength)) + ailment.was_treated_by_chem_effect() + /obj/item/organ/proc/is_preserved() if(istype(loc,/obj/item/organ)) var/obj/item/organ/O = loc From d1b546e4200678e5c3a3d23d18fe17297a9380bc Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Sat, 11 Dec 2021 18:03:02 +0300 Subject: [PATCH 10/40] keybind: fixes move-upwards fixes: https://github.com/NebulaSS13/Nebula/issues/2138 --- code/modules/keybindings/mob.dm | 4 ++-- code/modules/multiz/movement.dm | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/code/modules/keybindings/mob.dm b/code/modules/keybindings/mob.dm index cb66eeb935d..5e19e0f97ad 100644 --- a/code/modules/keybindings/mob.dm +++ b/code/modules/keybindings/mob.dm @@ -137,6 +137,6 @@ full_name = "Move Down" description = "Makes you go down" -/datum/keybinding/mob/move_up/down(client/user) +/datum/keybinding/mob/move_down/down(client/user) var/mob/M = user.mob - M.SelfMove(DOWN) + M.move_down() diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index f63402c8eab..e003543788e 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -8,11 +8,14 @@ set name = "Move Down" set category = "IC" - SelfMove(DOWN) + move_down() /mob/proc/move_up() SelfMove(UP) +/mob/proc/move_down() + SelfMove(DOWN) + /mob/living/carbon/human/move_up() var/turf/old_loc = loc ..() From afa84f7512eb128ba3d11e6192219c8cb385af08 Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Sat, 11 Dec 2021 18:07:32 +0300 Subject: [PATCH 11/40] doors: fixes empty icon_state on spawn fixes: https://github.com/NebulaSS13/Nebula/issues/2250 --- code/game/objects/structures/doors/_door.dm | 36 ++++++++------------ code/modules/materials/_materials.dm | 2 +- icons/obj/doors/material_doors.dmi | Bin 32125 -> 32276 bytes 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/code/game/objects/structures/doors/_door.dm b/code/game/objects/structures/doors/_door.dm index 219260cb900..ffdaa951296 100644 --- a/code/game/objects/structures/doors/_door.dm +++ b/code/game/objects/structures/doors/_door.dm @@ -1,19 +1,20 @@ -#define MATERIAL_DOOR_SOUND_VOLUME 25 /obj/structure/door name = "door" icon = 'icons/obj/doors/material_doors.dmi' icon_state = "metal" hitsound = 'sound/weapons/genhit.ogg' - material_alteration = MAT_FLAG_ALTERATION_NAME | MAT_FLAG_ALTERATION_COLOR | MAT_FLAG_ALTERATION_COLOR + material_alteration = MAT_FLAG_ALTERATION_NAME | MAT_FLAG_ALTERATION_DESC | MAT_FLAG_ALTERATION_COLOR maxhealth = 50 density = TRUE anchored = TRUE opacity = TRUE + var/datum/lock/lock + var/has_window = FALSE var/changing_state = FALSE var/icon_base - var/datum/lock/lock + var/door_sound_volume = 25 /obj/structure/door/Initialize() . = ..() @@ -23,15 +24,11 @@ lock = new /datum/lock(src, lock) if(!icon_base) icon_base = material.door_icon_base - changing_state = FALSE - update_nearby_tiles(need_rebuild=TRUE) - - if(material.luminescence) + update_icon() + update_nearby_tiles(need_rebuild = TRUE) + if(material?.luminescence) set_light(material.luminescence, 0.5, material.color) - if(material.opacity < 0.5) - alpha = 180 - /obj/structure/door/Destroy() update_nearby_tiles() QDEL_NULL(lock) @@ -42,25 +39,22 @@ /obj/structure/door/on_update_icon() ..() - if(density) - icon_state = "[icon_base]" - else - icon_state = "[icon_base]open" + icon_state = "[icon_base][!density ? "open" : ""]" /obj/structure/door/proc/post_change_state() update_nearby_tiles() update_icon() changing_state = FALSE -/obj/structure/door/attack_hand(var/mob/user) +/obj/structure/door/attack_hand(mob/user) return density ? open() : close() /obj/structure/door/proc/close() set waitfor = 0 if(!can_close()) return FALSE - flick("[icon_base]closing", src) - playsound(src.loc, material.dooropen_noise, MATERIAL_DOOR_SOUND_VOLUME, 1) + flick("[icon_base]_closing", src) + playsound(src, material.dooropen_noise, door_sound_volume, 1) changing_state = TRUE sleep(1 SECOND) @@ -73,8 +67,8 @@ set waitfor = 0 if(!can_open()) return FALSE - flick("[icon_base]opening", src) - playsound(src.loc, material.dooropen_noise, MATERIAL_DOOR_SOUND_VOLUME, 1) + flick("[icon_base]_opening", src) + playsound(src, material.dooropen_noise, door_sound_volume, 1) changing_state = TRUE sleep(1 SECOND) @@ -112,7 +106,6 @@ return FALSE /obj/structure/door/attackby(obj/item/I, mob/user) - add_fingerprint(user, 0, I) if((user.a_intent == I_HURT && I.force) || istype(I, /obj/item/stack/material)) @@ -149,7 +142,7 @@ return !opacity return !density -/obj/structure/door/CanFluidPass(var/coming_from) +/obj/structure/door/CanFluidPass(coming_from) return !density /obj/structure/door/Bumped(atom/AM) @@ -212,4 +205,3 @@ /obj/structure/door/shuttle material = /decl/material/solid/metal/steel -#undef MATERIAL_DOOR_SOUND_VOLUME \ No newline at end of file diff --git a/code/modules/materials/_materials.dm b/code/modules/materials/_materials.dm index afeb65d91e5..469e071924e 100644 --- a/code/modules/materials/_materials.dm +++ b/code/modules/materials/_materials.dm @@ -48,7 +48,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay) DOORS stone metal - resin + plastic wood */ diff --git a/icons/obj/doors/material_doors.dmi b/icons/obj/doors/material_doors.dmi index 5f90312aac86f5dfc7de5108a132fc7857c1b8f9..0ccd106e2d095ef0e087c21ae106499543eccb77 100644 GIT binary patch literal 32276 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 literal 32125 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 From 996fd1c2f04df5ee0cab82285c376edf194af2e3 Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Wed, 15 Dec 2021 07:10:25 +0300 Subject: [PATCH 12/40] rack: fixes unanchored state --- code/game/objects/structures/racks.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/objects/structures/racks.dm b/code/game/objects/structures/racks.dm index 138f4111329..750f3a95a2d 100644 --- a/code/game/objects/structures/racks.dm +++ b/code/game/objects/structures/racks.dm @@ -12,6 +12,7 @@ parts_amount = 2 parts_type = /obj/item/stack/material/strut density = TRUE + anchored = TRUE /obj/structure/rack/Initialize() ..() From dc42eca24b70e4e6eb81a2d38ce53a9b04392bec Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Wed, 15 Dec 2021 08:14:02 +0300 Subject: [PATCH 13/40] sstimer: fix potential bucket corruption in timer reset_buckets --- code/controllers/subsystems/timer.dm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/code/controllers/subsystems/timer.dm b/code/controllers/subsystems/timer.dm index c329651a5bc..5204ff7f7b4 100644 --- a/code/controllers/subsystems/timer.dm +++ b/code/controllers/subsystems/timer.dm @@ -259,6 +259,12 @@ SUBSYSTEM_DEF(timer) // Add all timed events from the secondary queue as well alltimers += second_queue + for (var/datum/timedevent/t in alltimers) + t.bucket_joined = FALSE + t.bucket_pos = -1 + t.prev = null + t.next = null + // If there are no timers being tracked by the subsystem, // there is no need to do any further rebuilding if (!length(alltimers)) @@ -302,6 +308,7 @@ SUBSYSTEM_DEF(timer) new_bucket_count++ var/bucket_pos = BUCKET_POS(timer) timer.bucket_pos = bucket_pos + timer.bucket_joined = TRUE var/datum/timedevent/bucket_head = bucket_list[bucket_pos] if (!bucket_head) From d0f9f9eb9d7c7d563a253fd6ffb98cc631c1bdfc Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Mon, 5 Jul 2021 03:07:01 +0300 Subject: [PATCH 14/40] sanitizing: ports sanitize updates from Tau Ceti Station --- code/_global_vars/lists/names.dm | 4 +- code/_helpers/text.dm | 133 ++++++++++++------ code/_helpers/unsorted.dm | 2 +- code/controllers/subsystems/statistics.dm | 14 +- code/datums/vote/custom.dm | 2 +- code/game/machinery/atmo_control.dm | 16 +-- code/game/machinery/newscaster.dm | 4 +- code/game/machinery/portable_turret.dm | 2 +- code/game/objects/items/bodybag.dm | 2 +- code/game/objects/items/books/_book.dm | 2 +- code/game/objects/items/books/skill_book.dm | 2 +- .../objects/items/devices/taperecorder.dm | 2 +- code/game/objects/items/robot/robot_frame.dm | 2 +- .../objects/items/robot/robot_upgrades.dm | 2 +- code/game/objects/items/weapons/cards_ids.dm | 2 +- .../items/weapons/cards_ids_syndicate.dm | 6 +- .../items/weapons/implants/implantcase.dm | 2 +- .../objects/items/weapons/storage/bible.dm | 2 +- code/game/objects/structures/bookcase.dm | 2 +- code/game/objects/structures/crematorium.dm | 2 +- code/game/objects/structures/door_assembly.dm | 2 +- code/game/objects/structures/morgue.dm | 2 +- code/game/objects/structures/window.dm | 6 +- code/modules/admin/admin_verbs.dm | 2 +- code/modules/admin/ticket.dm | 2 +- code/modules/admin/topic.dm | 4 +- code/modules/admin/verbs/adminhelp.dm | 2 +- code/modules/admin/verbs/adminpm.dm | 2 +- code/modules/admin/verbs/debug.dm | 2 +- code/modules/admin/verbs/randomverbs.dm | 2 +- .../preference_setup/background/02_culture.dm | 2 +- .../preference_setup/general/01_basic.dm | 2 +- .../client/preference_setup/global/03_pai.dm | 2 +- .../clothing/spacesuits/rig/suits/light.dm | 4 +- code/modules/crafting/_crafting_holder.dm | 2 +- code/modules/culture_descriptor/_culture.dm | 4 +- .../culture/cultures_human.dm | 4 +- code/modules/ghosttrap/trap.dm | 2 +- .../integrated_electronics/core/assemblies.dm | 2 +- .../core/integrated_circuit.dm | 2 +- .../core/saved_circuits.dm | 4 +- .../modules/mob/living/silicon/pai/recruit.dm | 4 +- .../modules/mob/living/silicon/robot/robot.dm | 2 +- .../mob/living/silicon/robot/robot_items.dm | 2 +- .../hostile/retaliate/exoplanet.dm | 2 +- .../mob/observer/eye/blueprints_eye.dm | 4 +- .../file_system/programs/command/card.dm | 2 +- .../programs/generic/ntnrc_client.dm | 2 +- code/modules/organs/external/head.dm | 2 +- code/modules/paperwork/folders.dm | 2 +- code/modules/paperwork/handlabeler.dm | 2 +- code/modules/paperwork/paper.dm | 2 +- code/modules/paperwork/paper_bundle.dm | 2 +- code/modules/paperwork/paper_sticky.dm | 2 +- code/modules/paperwork/photography.dm | 2 +- code/modules/projectiles/ammunition.dm | 2 +- code/modules/reagents/Chemistry-Machinery.dm | 4 +- code/modules/reagents/reagent_containers.dm | 2 +- .../reagents/reagent_containers/condiment.dm | 2 +- code/modules/recycling/sortingmachinery.dm | 4 +- code/procs/announce.dm | 2 +- mods/species/adherent/datum/culture.dm | 4 +- .../adherent/organs/organs_internal.dm | 2 +- mods/species/vox/datum/antagonism.dm | 2 +- 64 files changed, 185 insertions(+), 132 deletions(-) diff --git a/code/_global_vars/lists/names.dm b/code/_global_vars/lists/names.dm index 5eb78e06c32..d9f4bec71f7 100644 --- a/code/_global_vars/lists/names.dm +++ b/code/_global_vars/lists/names.dm @@ -1,3 +1,5 @@ +// All variables here use double quotes to able load information on every startup. + var/global/list/ai_names = file2list("config/names/ai.txt") var/global/list/wizard_first = file2list("config/names/wizardfirst.txt") var/global/list/wizard_second = file2list("config/names/wizardsecond.txt") @@ -11,5 +13,3 @@ var/global/list/clown_names = file2list("config/names/clown.txt") var/global/list/verbs = file2list("config/names/verbs.txt") var/global/list/adjectives = file2list("config/names/adjectives.txt") -//loaded on startup because of " -//would include in rsc if ' was used diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm index dac307ef4ad..bbdeed16f80 100644 --- a/code/_helpers/text.dm +++ b/code/_helpers/text.dm @@ -14,9 +14,9 @@ */ // Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts. -/proc/sanitizeSQL(var/t as text) - var/sqltext = dbcon.Quote(t); - return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that +/proc/sanitize_sql(t) + var/sqltext = dbcon.Quote("[t]") // http://www.byond.com/forum/post/2218538 + return copytext(sqltext, 2, -1) /* * Text sanitization @@ -24,7 +24,7 @@ //Used for preprocessing entered text //Added in an additional check to alert players if input is too long -/proc/sanitize(var/input, var/max_length = MAX_MESSAGE_LEN, var/encode = 1, var/trim = 1, var/extra = 1) +/proc/sanitize(input, max_length = MAX_MESSAGE_LEN, encode = TRUE, trim = TRUE, extra = TRUE, ascii_only = FALSE) if(!input) return @@ -33,47 +33,68 @@ if(input_length > max_length) to_chat(usr, SPAN_WARNING("Your message is too long by [input_length - max_length] character\s.")) return - input = copytext_char(input, 1, max_length + 1) + input = copytext_char(input, 1, max_length) if(extra) input = replace_characters(input, list("\n"=" ","\t"=" ")) + if(ascii_only) + // Some procs work differently depending on unicode/ascii string + // You should always consider this with any text processing work + // More: http://www.byond.com/docs/ref/info.html#/{notes}/Unicode + // http://www.byond.com/forum/post/2520672 + input = strip_non_ascii(input) + else + // Strip Unicode control/space-like chars here exept for line endings (\n,\r) and normal space (0x20) + // codes from https://www.compart.com/en/unicode/category/ + // https://en.wikipedia.org/wiki/Whitespace_character#Unicode + var/static/regex/unicode_control_chars = regex(@"[\u0001-\u0009\u000B\u000C\u000E-\u001F\u007F\u0080-\u009F\u00A0\u1680\u180E\u2000-\u200D\u2028\u2029\u202F\u205F\u2060\u3000\uFEFF]", "g") + input = unicode_control_chars.Replace(input, "") + if(encode) - // The below \ escapes have a space inserted to attempt to enable unit testing of span class usage. Please do not remove the space. - //In addition to processing html, html_encode removes byond formatting codes like "\ red", "\ i" and other. - //It is important to avoid double-encode text, it can "break" quotes and some other characters. - //Also, keep in mind that escaped characters don't work in the interface (window titles, lower left corner of the main window, etc.) + // In addition to processing html, html_encode removes byond formatting codes like "\red", "\i" and other. + // It is important to avoid double-encode text, it can "break" quotes and some other characters. + // Also, keep in mind that escaped characters don't work in the interface (window titles, lower left corner of the main window, etc.) input = html_encode(input) else - //If not need encode text, simply remove < and > - //note: we can also remove here byond formatting codes: 0xFF + next byte + // If not need encode text, simply remove < and > + // note: we can also remove here byond formatting codes: 0xFF + next byte input = replace_characters(input, list("<"=" ", ">"=" ")) if(trim) - //Maybe, we need trim text twice? Here and before copytext? input = trim(input) return input -//Run sanitize(), but remove <, >, " first to prevent displaying them as > < &34; in some places, after html_encode(). +//Run sanitize(), but remove <, >, " first to prevent displaying them as > < &34; in some places after html_encode(). //Best used for sanitize object names, window titles. //If you have a problem with sanitize() in chat, when quotes and >, < are displayed as html entites - -//this is a problem of double-encode(when & becomes &), use sanitize() with encode=0, but not the sanitizeSafe()! -/proc/sanitizeSafe(var/input, var/max_length = MAX_MESSAGE_LEN, var/encode = 1, var/trim = 1, var/extra = 1) - return sanitize(replace_characters(input, list(">"=" ","<"=" ", "\""="'")), max_length, encode, trim, extra) +//this is a problem of double-encode(when & becomes &), use sanitize() with encode=0, but not the sanitize_safe()! +/proc/sanitize_safe(input, max_length = MAX_MESSAGE_LEN, encode = TRUE, trim = TRUE, extra = TRUE, ascii_only = FALSE) + return sanitize(replace_characters(input, list(">"=" ","<"=" ", "\""="'")), max_length, encode, trim, extra, ascii_only) + +/proc/paranoid_sanitize(t) + var/regex/alphanum_only = regex("\[^a-zA-Z0-9# ,.?!:;()]", "g") + return alphanum_only.Replace(t, "#") //Filters out undesirable characters from names -/proc/sanitizeName(var/input, var/max_length = MAX_NAME_LEN, var/allow_numbers = 0, var/force_first_letter_uppercase = TRUE) - if(!input || length(input) > max_length) +/proc/sanitize_name(input, max_length = MAX_NAME_LEN, allow_numbers = 0, force_first_letter_uppercase = TRUE) + if(!input || length_char(input) > max_length) return //Rejects the input if it is null or if it is longer then the max length allowed var/number_of_alphanumeric = 0 var/last_char_group = 0 var/output = "" - for(var/i=1, i<=length(input), i++) - var/ascii_char = text2ascii(input,i) - switch(ascii_char) + var/char = "" + var/bytes_length = length(input) + var/ascii_char + for(var/i = 1, i <= bytes_length, i += length(char)) + char = input[i] + + ascii_char = text2ascii(char) + + switch(ascii_char) //todo: unicode names? // A .. Z if(65 to 90) //Uppercase Letters output += ascii2text(ascii_char) @@ -121,10 +142,7 @@ if(number_of_alphanumeric < 2) return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '" if(last_char_group == 1) - output = copytext(output,1,length(output)) //removes the last character (in this case a space) - - for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai","plating")) //prevents these common metagamey names - if(cmptext(output,bad_name)) return //(not case sensitive) + output = copytext(output, 1, -1) //removes the last character (in this case a space) return output @@ -213,11 +231,16 @@ * Text modification */ -/proc/replace_characters(var/t,var/list/repl_chars) +/proc/replace_characters(t, list/repl_chars) for(var/char in repl_chars) t = replacetext(t, char, repl_chars[char]) return t +/proc/random_string(length, list/characters) + . = "" + for (var/i in 1 to length) + . += pick(characters) + //Adds 'u' number of zeros ahead of the text 't' /proc/add_zero(t, u) return pad_left(t, u, "0") @@ -233,13 +256,13 @@ // Adds the required amount of 'character' in front of 'text' to extend the lengh to 'desired_length', if it is shorter // No consideration are made for a multi-character 'character' input /proc/pad_left(text, desired_length, character) - var/padding = generate_padding(length(text), desired_length, character) + var/padding = generate_padding(length_char(text), desired_length, character) return length(padding) ? "[padding][text]" : text // Adds the required amount of 'character' after 'text' to extend the lengh to 'desired_length', if it is shorter // No consideration are made for a multi-character 'character' input /proc/pad_right(text, desired_length, character) - var/padding = generate_padding(length(text), desired_length, character) + var/padding = generate_padding(length_char(text), desired_length, character) return length(padding) ? "[text][padding]" : text /proc/generate_padding(current_length, desired_length, character) @@ -250,32 +273,59 @@ characters += character return JOINTEXT(characters) - -//Returns a string with reserved characters and spaces before the first letter removed +// Returns a string with reserved characters and spaces before the first letter removed +// not work for unicode spaces - you should cleanup them first with sanitize() /proc/trim_left(text) for (var/i = 1 to length(text)) if (text2ascii(text, i) > 32) return copytext(text, i) return "" -//Returns a string with reserved characters and spaces after the last letter removed +// Returns a string with reserved characters and spaces after the last letter removed +// not work for unicode spaces - you should cleanup them first with sanitize() /proc/trim_right(text) for (var/i = length(text), i > 0, i--) if (text2ascii(text, i) > 32) return copytext(text, 1, i + 1) + return "" -//Returns a string with reserved characters and spaces before the first word and after the last word removed. +// Returns a string with reserved characters and spaces before the first word and after the last word removed. +// not work for unicode spaces - you should cleanup them first with sanitize() /proc/trim(text) return trim_left(trim_right(text)) //Returns a string with the first element of the string capitalized. -/proc/capitalize(var/t as text) - return uppertext(copytext_char(t, 1, 2)) + copytext_char(t, 2) +/proc/capitalize(text) + if(text) + text = uppertext(text[1]) + copytext(text, 1 + length(text[1])) + return text + +//Returns a string with the first element of the every word of the string capitalized. +/proc/capitalize_words(text) + var/list/S = splittext(text, " ") + var/list/M = list() + for (var/w in S) + M += capitalize(w) + return jointext(M, " ") + +/proc/strip_non_ascii(text) + var/static/regex/non_ascii_regex = regex(@"[^\x00-\x7F]+", "g") + return non_ascii_regex.Replace(text, "") + +/proc/strip_html_simple(t, limit = MAX_MESSAGE_LEN) + var/list/strip_chars = list("<",">") + t = copytext(t,1,limit) + for(var/char in strip_chars) + var/index = findtext(t, char) + while(index) + t = copytext(t, 1, index) + copytext(t, index+1) + index = findtext(t, char) + return t //This proc strips html properly, remove < > and all text between //for complete text sanitizing should be used sanitize() -/proc/strip_html_properly(var/input) +/proc/strip_html_properly(input) if(!input) return var/opentag = 1 //These store the position of < and > respectively. @@ -301,7 +351,7 @@ //This proc fills in all spaces with the "replace" var (* by default) with whatever //is in the other string at the same spot (assuming it is not a replace char). //This is used for fingerprints -/proc/stringmerge(var/text,var/compare,replace = "*") +/proc/stringmerge_ascii(text, compare,replace = "*") var/newtext = text if(length(text) != length(compare)) return 0 @@ -321,7 +371,7 @@ //This proc returns the number of chars of the string that is the character //This is used for detective work to determine fingerprint completion. -/proc/stringpercent(var/text,character = "*") +/proc/stringpercent_ascii(text,character = "*") if(!text || !character) return 0 var/count = 0 @@ -331,10 +381,13 @@ count++ return count -/proc/reverse_text(var/text = "") +/proc/reverse_text(text = "") var/new_text = "" - for(var/i = length(text); i > 0; i--) - new_text += copytext(text, i, i+1) + var/bytes_length = length(text) + var/letter = "" + for(var/i = 1, i <= bytes_length, i += length(letter)) + letter = text[i] + new_text = letter + new_text return new_text //Used in preferences' SetFlavorText and human's set_flavor verb diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 1a9c5f8eb8a..8f38ebb0a3e 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -303,7 +303,7 @@ Turf and target are seperate in case you want to teleport some distance from a t newname = input(src,"You are \a [role]. Would you like to change your name to something else?", "Name change",oldname) as text if((world.time-time_passed) > 5 MINUTES) return //took too long - newname = sanitizeName(newname, ,allow_numbers) //returns null if the name doesn't meet some basic requirements. Tidies up a few other things like bad-characters. + newname = sanitize_name(newname, ,allow_numbers) //returns null if the name doesn't meet some basic requirements. Tidies up a few other things like bad-characters. for(var/mob/living/M in global.player_list) if(M == src) continue diff --git a/code/controllers/subsystems/statistics.dm b/code/controllers/subsystems/statistics.dm index 263e9f8d7ac..c6931d5ba1e 100644 --- a/code/controllers/subsystems/statistics.dm +++ b/code/controllers/subsystems/statistics.dm @@ -146,14 +146,14 @@ SUBSYSTEM_DEF(statistics) var/datum/death/death = new var/area/placeofdeath = get_area(dead) death.place_of_death = placeofdeath ? placeofdeath.name : "Unknown area" - death.place_of_death = sanitizeSQL(death.place_of_death) - death.name = sanitizeSQL(dead.real_name) - death.key = sanitizeSQL(dead.key) - death.special_role = sanitizeSQL(dead.mind.get_special_role_name()) - death.job = sanitizeSQL(dead.mind.assigned_role) + death.place_of_death = sanitize_sql(death.place_of_death) + death.name = sanitize_sql(dead.real_name) + death.key = sanitize_sql(dead.key) + death.special_role = sanitize_sql(dead.mind.get_special_role_name()) + death.job = sanitize_sql(dead.mind.assigned_role) if(dead.last_attacker_) - death.last_attacker_name = sanitizeSQL(dead.last_attacker_.name) - death.last_attacker_key = sanitizeSQL(dead.last_attacker_.client.key) + death.last_attacker_name = sanitize_sql(dead.last_attacker_.name) + death.last_attacker_key = sanitize_sql(dead.last_attacker_.client.key) death.gender = dead.gender death.time_of_death = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") death.coords = "[dead.x], [dead.y], [dead.z]" diff --git a/code/datums/vote/custom.dm b/code/datums/vote/custom.dm index b783c749dea..ba32ded269e 100644 --- a/code/datums/vote/custom.dm +++ b/code/datums/vote/custom.dm @@ -12,7 +12,7 @@ return ..() /datum/vote/custom/setup_vote(mob/creator, automatic) - question = sanitizeSafe(input(creator,"What is the vote for?") as text|null) + question = sanitize_safe(input(creator,"What is the vote for?") as text|null) if(!question) abort = 1 return diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index 93fe942d7a0..235be870e8a 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -222,32 +222,32 @@ return TOPIC_REFRESH if(href_list["set_input_tag"]) - var/t = sanitizeSafe(input(usr, "Enter the input ID tag.", src.name, src.input_tag), MAX_NAME_LEN) - t = sanitizeSafe(t, MAX_NAME_LEN) + var/t = sanitize_safe(input(usr, "Enter the input ID tag.", src.name, src.input_tag), MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if (t) src.input_tag = t set_frequency(frequency) return TOPIC_REFRESH if(href_list["set_output_tag"]) - var/t = sanitizeSafe(input(usr, "Enter the output ID tag.", src.name, src.output_tag), MAX_NAME_LEN) - t = sanitizeSafe(t, MAX_NAME_LEN) + var/t = sanitize_safe(input(usr, "Enter the output ID tag.", src.name, src.output_tag), MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if (t) src.output_tag = t set_frequency(frequency) return TOPIC_REFRESH if(href_list["set_sensor_tag"]) - var/t = sanitizeSafe(input(usr, "Enter the sensor ID tag.", src.name, src.sensor_tag)) - t = sanitizeSafe(t, MAX_NAME_LEN) + var/t = sanitize_safe(input(usr, "Enter the sensor ID tag.", src.name, src.sensor_tag)) + t = sanitize_safe(t, MAX_NAME_LEN) if(t) src.sensor_tag = t set_frequency(frequency) return TOPIC_REFRESH if(href_list["set_sensor_name"]) - var/t = sanitizeSafe(input(usr, "Enter the sensor name.", src.name, src.sensor_name)) - t = sanitizeSafe(t, MAX_NAME_LEN) + var/t = sanitize_safe(input(usr, "Enter the sensor name.", src.name, src.sensor_name)) + t = sanitize_safe(t, MAX_NAME_LEN) if(t) src.sensor_name = t return TOPIC_REFRESH diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 30fb38ec304..ab0a95dfe61 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -457,7 +457,7 @@ var/global/list/allCasters = list() //Global list that will contain reference to if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && isturf(src.loc))) || (istype(usr, /mob/living/silicon))) usr.set_machine(src) if(href_list["set_channel_name"]) - src.channel_name = sanitizeSafe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""), MAX_LNAME_LEN) + src.channel_name = sanitize_safe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""), MAX_LNAME_LEN) src.updateUsrDialog() //src.update_icon() @@ -560,7 +560,7 @@ var/global/list/allCasters = list() //Global list that will contain reference to src.updateUsrDialog() else if(href_list["set_wanted_name"]) - src.channel_name = sanitizeSafe(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""), MAX_LNAME_LEN) + src.channel_name = sanitize_safe(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""), MAX_LNAME_LEN) src.updateUsrDialog() else if(href_list["set_wanted_desc"]) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 45655481ebb..0bdec2de426 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -798,7 +798,7 @@ var/global/list/turret_icons return if(istype(I, /obj/item/pen)) //you can rename turrets like bots! - var/t = sanitizeSafe(input(user, "Enter new turret name", name, finish_name) as text, MAX_NAME_LEN) + var/t = sanitize_safe(input(user, "Enter new turret name", name, finish_name) as text, MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && loc != usr) diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index b01b245ded0..cb99a477dd2 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -49,7 +49,7 @@ return if (!in_range(src, user) && src.loc != user) return - t = sanitizeSafe(t, MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if (t) src.SetName("body bag - ") src.name += t diff --git a/code/game/objects/items/books/_book.dm b/code/game/objects/items/books/_book.dm index dd0c5921c13..4652e19a142 100644 --- a/code/game/objects/items/books/_book.dm +++ b/code/game/objects/items/books/_book.dm @@ -75,7 +75,7 @@ var/choice = input("What would you like to change?") in list("Title", "Contents", "Author", "Cancel") switch(choice) if("Title") - var/newtitle = reject_bad_text(sanitizeSafe(input("Write a new title:"))) + var/newtitle = reject_bad_text(sanitize_safe(input("Write a new title:"))) if(!newtitle) to_chat(usr, "The title is invalid.") return diff --git a/code/game/objects/items/books/skill_book.dm b/code/game/objects/items/books/skill_book.dm index c49dc07331b..c9b67b52726 100644 --- a/code/game/objects/items/books/skill_book.dm +++ b/code/game/objects/items/books/skill_book.dm @@ -734,7 +734,7 @@ MEDICAL return FALSE /obj/item/book/skill/custom/proc/edit_title(var/obj/item/pen, var/mob/user) - var/newtitle = reject_bad_text(sanitizeSafe(input(user, "Write a new title:"))) + var/newtitle = reject_bad_text(sanitize_safe(input(user, "Write a new title:"))) if(!can_write(pen,user)) return if(!newtitle) diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 18d0b84c917..0487e0c630e 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -454,7 +454,7 @@ if(loc == user) var/new_name = input(user, "What would you like to label the tape?", "Tape labeling") as null|text if(isnull(new_name)) return - new_name = sanitizeSafe(new_name) + new_name = sanitize_safe(new_name) if(new_name) SetName("tape - '[new_name]'") to_chat(user, "You label the tape '[new_name]'.") diff --git a/code/game/objects/items/robot/robot_frame.dm b/code/game/objects/items/robot/robot_frame.dm index 0ca8db0428c..34cd2723f1c 100644 --- a/code/game/objects/items/robot/robot_frame.dm +++ b/code/game/objects/items/robot/robot_frame.dm @@ -138,7 +138,7 @@ qdel(src) else if(istype(W, /obj/item/pen)) - var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN) + var/t = sanitize_safe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN) if(t && (in_range(src, user) || loc == user)) created_name = t else diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index c264c004195..6220bb4f6e5 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -71,7 +71,7 @@ var/heldname = "default name" /obj/item/borg/upgrade/rename/attack_self(mob/user) - heldname = sanitizeSafe(input(user, "Enter new robot name", "Robot Reclassification", heldname), MAX_NAME_LEN) + heldname = sanitize_safe(input(user, "Enter new robot name", "Robot Reclassification", heldname), MAX_NAME_LEN) /obj/item/borg/upgrade/rename/action(var/mob/living/silicon/robot/R) if(..()) return 0 diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 1a18081f94f..1617f2e0543 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -39,7 +39,7 @@ if(signed_by) to_chat(user, SPAN_WARNING("\The [src] has already been signed.")) else - var/signature = sanitizeSafe(input("What do you want to sign the card as?", "Union Card") as text, MAX_NAME_LEN) + var/signature = sanitize_safe(input("What do you want to sign the card as?", "Union Card") as text, MAX_NAME_LEN) if(signature && !signed_by && !user.incapacitated() && Adjacent(user)) signed_by = signature user.visible_message(SPAN_NOTICE("\The [user] signs \the [src] with a flourish.")) diff --git a/code/game/objects/items/weapons/cards_ids_syndicate.dm b/code/game/objects/items/weapons/cards_ids_syndicate.dm index 351db1c3965..3b1bd79d618 100644 --- a/code/game/objects/items/weapons/cards_ids_syndicate.dm +++ b/code/game/objects/items/weapons/cards_ids_syndicate.dm @@ -110,13 +110,13 @@ to_chat(user, "Age has been set to '[age]'.") . = 1 if("Prefix") - var/new_prefix = sanitizeSafe(input(user,"What title prefix would you like to put on this card?","Agent Card Prefix", age) as text, MAX_NAME_LEN) + var/new_prefix = sanitize_safe(input(user,"What title prefix would you like to put on this card?","Agent Card Prefix", age) as text, MAX_NAME_LEN) if(!isnull(new_prefix) && CanUseTopic(user, state)) formal_name_prefix = new_prefix to_chat(user, "Title prefix has been set to '[formal_name_prefix]'.") . = 1 if("Suffix") - var/new_suffix = sanitizeSafe(input(user,"What title suffix would you like to put on this card?","Agent Card Suffix", age) as text, MAX_NAME_LEN) + var/new_suffix = sanitize_safe(input(user,"What title suffix would you like to put on this card?","Agent Card Suffix", age) as text, MAX_NAME_LEN) if(!isnull(new_suffix) && CanUseTopic(user, state)) formal_name_suffix = new_suffix to_chat(user, "Title suffix has been set to '[formal_name_suffix]'.") @@ -172,7 +172,7 @@ to_chat(user, "Fingerprint hash changed to '[new_fingerprint_hash]'.") . = 1 if("Name") - var/new_name = sanitizeName(input(user,"What name would you like to put on this card?","Agent Card Name", registered_name) as null|text, allow_numbers=TRUE) + var/new_name = sanitize_name(input(user,"What name would you like to put on this card?","Agent Card Name", registered_name) as null|text, allow_numbers=TRUE) if(!isnull(new_name) && CanUseTopic(user, state)) src.registered_name = new_name to_chat(user, "Name changed to '[new_name]'.") diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm index bda5fb96f1d..964674d2738 100644 --- a/code/game/objects/items/weapons/implants/implantcase.dm +++ b/code/game/objects/items/weapons/implants/implantcase.dm @@ -46,7 +46,7 @@ return if((!in_range(src, usr) && loc != user)) return - t = sanitizeSafe(t, MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if(t) SetName("glass case - '[t]'") desc = "A case containing \a [t] implant." diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index 741361d5696..4a0dda00b01 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -108,7 +108,7 @@ set desc = "Click to rename your bible." if(!renamed) - var/input = sanitizeSafe(input("What do you want to rename your bible to? You can only do this once.", ,""), MAX_NAME_LEN) + var/input = sanitize_safe(input("What do you want to rename your bible to? You can only do this once.", ,""), MAX_NAME_LEN) var/mob/M = usr if(src && input && !M.stat && in_range(M,src)) diff --git a/code/game/objects/structures/bookcase.dm b/code/game/objects/structures/bookcase.dm index 6a465b62d40..311ec958699 100644 --- a/code/game/objects/structures/bookcase.dm +++ b/code/game/objects/structures/bookcase.dm @@ -34,7 +34,7 @@ var/global/list/station_bookcases = list() if(istype(O, /obj/item/book) && user.unEquip(O, src)) update_icon() else if(istype(O, /obj/item/pen)) - var/newname = sanitizeSafe(input("What would you like to title this bookshelf?"), MAX_NAME_LEN) + var/newname = sanitize_safe(input("What would you like to title this bookshelf?"), MAX_NAME_LEN) if(!newname) return else diff --git a/code/game/objects/structures/crematorium.dm b/code/game/objects/structures/crematorium.dm index 3b41a43dcc7..1ea52f85486 100644 --- a/code/game/objects/structures/crematorium.dm +++ b/code/game/objects/structures/crematorium.dm @@ -92,7 +92,7 @@ /obj/structure/crematorium/attackby(P, mob/user) if(istype(P, /obj/item/pen)) - var/new_label = sanitizeSafe(input(user, "What would you like the label to be?", capitalize(name), null) as text|null, MAX_NAME_LEN) + var/new_label = sanitize_safe(input(user, "What would you like the label to be?", capitalize(name), null) as text|null, MAX_NAME_LEN) if((!Adjacent(user) || loc == user)) return diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 583b8ed67ca..8c9d6830f27 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -103,7 +103,7 @@ /obj/structure/door_assembly/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/pen)) - var/t = sanitizeSafe(input(user, "Enter the name for the door.", src.name, src.created_name), MAX_NAME_LEN) + var/t = sanitize_safe(input(user, "Enter the name for the door.", src.name, src.created_name), MAX_NAME_LEN) if(!t) return if(!in_range(src, usr) && src.loc != usr) return created_name = t diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index e025bcef129..32954e5304d 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -82,7 +82,7 @@ /obj/structure/morgue/attackby(P, mob/user) if(istype(P, /obj/item/pen)) - var/new_label = sanitizeSafe(input(user, "What would you like the label to be?", capitalize(name), null) as text|null, MAX_NAME_LEN) + var/new_label = sanitize_safe(input(user, "What would you like the label to be?", capitalize(name), null) as text|null, MAX_NAME_LEN) if((!Adjacent(user) || loc == user)) return diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index b581bd99b64..972ddb3732b 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -255,7 +255,7 @@ var/response = input(user, "New Window ID:", name, id) as null | text if (isnull(response) || user.incapacitated() || !user.Adjacent(src) || user.get_active_hand() != W) return - id = sanitizeSafe(response, MAX_NAME_LEN) + id = sanitize_safe(response, MAX_NAME_LEN) to_chat(user, SPAN_NOTICE("The new ID of \the [src] is [id].")) return else if(istype(W, /obj/item/gun/energy/plasmacutter) && anchored) @@ -568,10 +568,10 @@ /obj/machinery/button/windowtint/attackby(obj/item/W, mob/user) if(isMultitool(W)) - var/t = sanitizeSafe(input(user, "Enter the ID for the button.", name, id_tag), MAX_NAME_LEN) + var/t = sanitize_safe(input(user, "Enter the ID for the button.", name, id_tag), MAX_NAME_LEN) if(!CanPhysicallyInteract(user)) return TRUE - t = sanitizeSafe(t, MAX_NAME_LEN) + t = sanitize_safe(t, MAX_NAME_LEN) if (t) id_tag = t to_chat(user, SPAN_NOTICE("The new ID of the button is '[id_tag]'.")) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 5b92362faf2..a4ba1459fb4 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -661,7 +661,7 @@ var/global/list/admin_verbs_mod = list( var/mob/living/silicon/S = input("Select silicon.", "Rename Silicon.") as null|anything in global.silicon_mob_list if(!S) return - var/new_name = sanitizeSafe(input(src, "Enter new name. Leave blank or as is to cancel.", "[S.real_name] - Enter new silicon name", S.real_name)) + var/new_name = sanitize_safe(input(src, "Enter new name. Leave blank or as is to cancel.", "[S.real_name] - Enter new silicon name", S.real_name)) if(new_name && new_name != S.real_name) log_and_message_admins("has renamed the silicon '[S.real_name]' to '[new_name]'") S.fully_replace_character_name(new_name) diff --git a/code/modules/admin/ticket.dm b/code/modules/admin/ticket.dm index 7bf115e2a6c..fa3df76106d 100644 --- a/code/modules/admin/ticket.dm +++ b/code/modules/admin/ticket.dm @@ -19,7 +19,7 @@ var/global/list/ticket_panels = list() id = tickets.len opened_time = world.time if(establish_db_connection()) - var/sql_ckey = sanitizeSQL(owner.ckey) + var/sql_ckey = sanitize_sql(owner.ckey) var/DBQuery/ticket_query = dbcon.NewQuery("INSERT INTO `erro_admin_tickets`(`ckey`, `round`, `inround_id`, `status`, `open_date`) VALUES ('[sql_ckey]', '[game_id]', [src.id], 'OPEN', NOW());") ticket_query.Execute() addtimer(CALLBACK(src, .proc/timeoutcheck), 5 MINUTES) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index bbbbbbcd74b..1d517ffd923 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1293,7 +1293,7 @@ src.access_news_network() else if(href_list["ac_set_channel_name"]) - src.admincaster_feed_channel.channel_name = sanitizeSafe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) + src.admincaster_feed_channel.channel_name = sanitize_safe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) src.access_news_network() else if(href_list["ac_set_channel_lock"]) @@ -1321,7 +1321,7 @@ var/list/available_channels = list() for(var/datum/feed_channel/F in news_network.network_channels) available_channels += F.channel_name - src.admincaster_feed_channel.channel_name = sanitizeSafe(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) + src.admincaster_feed_channel.channel_name = sanitize_safe(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) src.access_news_network() else if(href_list["ac_set_new_message"]) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 311001f84fc..981cae52c3c 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -111,7 +111,7 @@ var/global/list/adminhelp_ignored_words = list("unknown","the","a","an","of","mo update_ticket_panels() if(establish_db_connection()) - var/sql_text = "HELP [src.ckey]: [sanitizeSQL(original_msg)]\n" + var/sql_text = "HELP [src.ckey]: [sanitize_sql(original_msg)]\n" var/DBQuery/ticket_text = dbcon.NewQuery("UPDATE `erro_admin_tickets` SET `text` = '[sql_text]' WHERE `round` = '[game_id]' AND `inround_id` = '[ticket.id]';") ticket_text.Execute() diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index cc865fd9490..da9195800ca 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -153,7 +153,7 @@ update_ticket_panels() if(establish_db_connection()) - var/sql_text = "[src.ckey] -> [C.ckey]: [sanitizeSQL(msg)]\n" + var/sql_text = "[src.ckey] -> [C.ckey]: [sanitize_sql(msg)]\n" var/DBQuery/ticket_text = dbcon.NewQuery("UPDATE `erro_admin_tickets` SET `text` = CONCAT(COALESCE(text,''), '[sql_text]') WHERE `round` = '[game_id]' AND `inround_id` = '[ticket.id]';") ticket_text.Execute() diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index cc89531a4e8..93de1928dce 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -92,7 +92,7 @@ return 0 var/obj/item/paicard/card = new(T) var/mob/living/silicon/pai/pai = new(card) - pai.SetName(sanitizeSafe(input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text)) + pai.SetName(sanitize_safe(input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text)) pai.real_name = pai.name pai.key = choice.key card.setPersonality(pai) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 992d4840c11..0bb545ff9c6 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -561,7 +561,7 @@ Traitors and the like can also be revived with the previous role mostly intact. to_chat(src, "Only administrators may use this command.") return var/input = sanitize(input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null, extra = 0) - var/customname = sanitizeSafe(input(usr, "Pick a title for the report.", "Title") as text|null) + var/customname = sanitize_safe(input(usr, "Pick a title for the report.", "Title") as text|null) if(!input) return if(!customname) diff --git a/code/modules/client/preference_setup/background/02_culture.dm b/code/modules/client/preference_setup/background/02_culture.dm index c40f9dff1be..852a634db24 100644 --- a/code/modules/client/preference_setup/background/02_culture.dm +++ b/code/modules/client/preference_setup/background/02_culture.dm @@ -62,7 +62,7 @@ if(pref.cultural_info[TAG_CULTURE]) var/decl/cultural_info/check = GET_DECL(pref.cultural_info[TAG_CULTURE]) if(check) - pref.real_name = check.sanitize_name(pref.real_name, pref.species) + pref.real_name = check.sanitize_cultural_name(pref.real_name, pref.species) if(!pref.real_name) pref.real_name = check.get_random_name(preference_mob(), pref.gender) diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index 5aeea735ff5..eb256a0d4bf 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -95,7 +95,7 @@ if (!isnull(raw_name) && CanUseTopic(user)) var/decl/cultural_info/check = GET_DECL(pref.cultural_info[TAG_CULTURE]) - var/new_name = check.sanitize_name(raw_name, pref.species) + var/new_name = check.sanitize_cultural_name(raw_name, pref.species) if(filter_block_message(user, new_name)) return TOPIC_NOACTION diff --git a/code/modules/client/preference_setup/global/03_pai.dm b/code/modules/client/preference_setup/global/03_pai.dm index 9c2541558a4..86bccf57f94 100644 --- a/code/modules/client/preference_setup/global/03_pai.dm +++ b/code/modules/client/preference_setup/global/03_pai.dm @@ -52,7 +52,7 @@ . = TOPIC_REFRESH switch(href_list["option"]) if("name") - t = sanitizeName(input(user, "Enter a name for your pAI", "Global Preference", candidate.name) as text|null, MAX_NAME_LEN, 1) + t = sanitize_name(input(user, "Enter a name for your pAI", "Global Preference", candidate.name) as text|null, MAX_NAME_LEN, 1) if(t && CanUseTopic(user)) candidate.name = t if("desc") diff --git a/code/modules/clothing/spacesuits/rig/suits/light.dm b/code/modules/clothing/spacesuits/rig/suits/light.dm index 7cb2acf9d08..d328b7af5d6 100644 --- a/code/modules/clothing/spacesuits/rig/suits/light.dm +++ b/code/modules/clothing/spacesuits/rig/suits/light.dm @@ -130,7 +130,7 @@ var/mob/M = usr if(!M.mind) return 0 if(M.incapacitated()) return 0 - var/input = sanitizeSafe(input("What do you want to name your suit?", "Rename suit"), MAX_NAME_LEN) + var/input = sanitize_safe(input("What do you want to name your suit?", "Rename suit"), MAX_NAME_LEN) if(src && input && !M.incapacitated() && in_range(M,src)) if(!findtext(input, "the", 1, 4)) input = "\improper [input]" @@ -147,7 +147,7 @@ var/mob/M = usr if(!M.mind) return 0 if(M.incapacitated()) return 0 - var/input = sanitizeSafe(input("Please describe your voidsuit in 128 letters or less.", "write description"), MAX_DESC_LEN) + var/input = sanitize_safe(input("Please describe your voidsuit in 128 letters or less.", "write description"), MAX_DESC_LEN) if(src && input && !M.incapacitated() && in_range(M,src)) desc = input to_chat(M, "Suit description succesful!") diff --git a/code/modules/crafting/_crafting_holder.dm b/code/modules/crafting/_crafting_holder.dm index 4e86dc9980d..5af8fd51747 100644 --- a/code/modules/crafting/_crafting_holder.dm +++ b/code/modules/crafting/_crafting_holder.dm @@ -45,7 +45,7 @@ /obj/item/crafting_holder/attackby(var/obj/item/W, var/mob/user) if(istype(W, /obj/item/pen)) - var/new_label = sanitizeSafe(input(user, "What do you wish to label this assembly?", "Assembly Labelling", label_name), MAX_NAME_LEN) + var/new_label = sanitize_safe(input(user, "What do you wish to label this assembly?", "Assembly Labelling", label_name), MAX_NAME_LEN) if(new_label && !user.incapacitated() && W.loc == user && user.Adjacent(src) && !QDELETED(src)) to_chat(user, SPAN_NOTICE("You label \the [src] with '[new_label]'.")) label_name = new_label diff --git a/code/modules/culture_descriptor/_culture.dm b/code/modules/culture_descriptor/_culture.dm index 7690b7ac453..d3d46b64bf2 100644 --- a/code/modules/culture_descriptor/_culture.dm +++ b/code/modules/culture_descriptor/_culture.dm @@ -51,8 +51,8 @@ return _language.get_random_name(gender) return capitalize(pick(gender==FEMALE ? global.first_names_female : global.first_names_male)) + " " + capitalize(pick(global.last_names)) -/decl/cultural_info/proc/sanitize_name(var/new_name) - return sanitizeName(new_name) +/decl/cultural_info/proc/sanitize_cultural_name(new_name) + return sanitize_name(new_name) /decl/cultural_info/proc/get_description(var/verbose = TRUE) LAZYSET(., "details", jointext(get_text_details(), "
")) diff --git a/code/modules/culture_descriptor/culture/cultures_human.dm b/code/modules/culture_descriptor/culture/cultures_human.dm index 14176a7ed69..9c70a00a896 100644 --- a/code/modules/culture_descriptor/culture/cultures_human.dm +++ b/code/modules/culture_descriptor/culture/cultures_human.dm @@ -23,5 +23,5 @@ /decl/language/sign ) -/decl/cultural_info/culture/synthetic/sanitize_name(new_name) - return sanitizeName(new_name, allow_numbers = TRUE) +/decl/cultural_info/culture/synthetic/sanitize_cultural_name(new_name) + return sanitize_name(new_name, allow_numbers = TRUE) diff --git a/code/modules/ghosttrap/trap.dm b/code/modules/ghosttrap/trap.dm index ef0b95ebc14..2728becaa1c 100644 --- a/code/modules/ghosttrap/trap.dm +++ b/code/modules/ghosttrap/trap.dm @@ -89,7 +89,7 @@ if(!can_set_own_name) return - var/newname = sanitizeSafe(input(target,"Enter a name, or leave blank for the default name.", "Name change",target.real_name) as text, MAX_NAME_LEN) + var/newname = sanitize_safe(input(target,"Enter a name, or leave blank for the default name.", "Name change",target.real_name) as text, MAX_NAME_LEN) if (newname && newname != "") target.real_name = newname target.SetName(target.real_name) diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index e32bf103579..fdf0eab8016 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -273,7 +273,7 @@ if(!check_interactivity(M)) return var/input = input("What do you want to name this?", "Rename", src.name) as null|text - input = sanitizeName(input,allow_numbers = 1) + input = sanitize_name(input,allow_numbers = 1) if(!check_interactivity(M)) return if(!QDELETED(src) && input) diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm index 1a9ae6f0f0a..f40b4a26518 100644 --- a/code/modules/integrated_electronics/core/integrated_circuit.dm +++ b/code/modules/integrated_electronics/core/integrated_circuit.dm @@ -112,7 +112,7 @@ a creative player the means to solve many problems. Circuits are held inside an if(!check_interactivity(M)) return - var/input = sanitizeName(input(M, "What do you want to name this?", "Rename", name) as null|text, allow_numbers = TRUE) + var/input = sanitize_name(input(M, "What do you want to name this?", "Rename", name) as null|text, allow_numbers = TRUE) if(check_interactivity(M)) if(!input) input = name diff --git a/code/modules/integrated_electronics/core/saved_circuits.dm b/code/modules/integrated_electronics/core/saved_circuits.dm index 33cd4d38c3f..8954b3217e5 100644 --- a/code/modules/integrated_electronics/core/saved_circuits.dm +++ b/code/modules/integrated_electronics/core/saved_circuits.dm @@ -52,7 +52,7 @@ var/init_name = initial(name) // Validate name if(component_params["name"]) - sanitizeName(component_params["name"],allow_numbers=TRUE) + sanitize_name(component_params["name"],allow_numbers=TRUE) // Validate input values if(component_params["inputs"]) var/list/loaded_inputs = component_params["inputs"] @@ -138,7 +138,7 @@ /obj/item/electronic_assembly/proc/verify_save(list/assembly_params) // Validate name and color if(assembly_params["name"]) - if(sanitizeName(assembly_params["name"], allow_numbers = TRUE) != assembly_params["name"]) + if(sanitize_name(assembly_params["name"], allow_numbers = TRUE) != assembly_params["name"]) return "Bad assembly name." if(assembly_params["desc"]) if(sanitize(assembly_params["desc"]) != assembly_params["desc"]) diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index ad11c22e560..da9259ba3f4 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -65,7 +65,7 @@ var/global/datum/paiController/paiController // Global handler for pAI candida switch(option) if("name") - t = sanitizeSafe(input("Enter a name for your pAI", "pAI Name", candidate.name) as text, MAX_NAME_LEN) + t = sanitize_safe(input("Enter a name for your pAI", "pAI Name", candidate.name) as text, MAX_NAME_LEN) if(t) candidate.name = t if("desc") @@ -94,7 +94,7 @@ var/global/datum/paiController/paiController // Global handler for pAI candida candidate.savefile_load(usr) //In case people have saved unsanitized stuff. if(candidate.name) - candidate.name = sanitizeSafe(candidate.name, MAX_NAME_LEN) + candidate.name = sanitize_safe(candidate.name, MAX_NAME_LEN) if(candidate.description) candidate.description = sanitize(candidate.description) if(candidate.role) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 716e49ae3cb..6a5c8735375 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -326,7 +326,7 @@ spawn(0) var/newname - newname = sanitizeName(input(src,"You are a robot. Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN, allow_numbers = 1) + newname = sanitize_name(input(src,"You are a robot. Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN, allow_numbers = 1) if (newname) custom_name = newname diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm index 2ee77af149c..31261bd5f2d 100644 --- a/code/modules/mob/living/silicon/robot/robot_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_items.dm @@ -206,7 +206,7 @@ /obj/item/pen/robopen/proc/RenamePaper(mob/user, obj/item/paper/paper) if ( !user || !paper ) return - var/n_name = sanitizeSafe(input(user, "What would you like to label the paper?", "Paper Labelling", null) as text, 32) + var/n_name = sanitize_safe(input(user, "What would you like to label the paper?", "Paper Labelling", null) as text, 32) if ( !user || !paper ) return diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/exoplanet.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/exoplanet.dm index cdedbc02ef3..24614b53cdf 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/exoplanet.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/exoplanet.dm @@ -54,7 +54,7 @@ for(var/obj/effect/overmap/visitable/sector/exoplanet/E) if(src in E.animals) var/newname = input("What do you want to name this species?", "Species naming", E.get_random_species_name()) as text|null - newname = sanitizeName(newname, allow_numbers = TRUE, force_first_letter_uppercase = FALSE) + newname = sanitize_name(newname, allow_numbers = TRUE, force_first_letter_uppercase = FALSE) if(newname && CanInteract(usr, global.conscious_topic_state)) if(E.rename_species(type, newname)) to_chat(usr,"This species will be known from now on as '[newname]'.") diff --git a/code/modules/mob/observer/eye/blueprints_eye.dm b/code/modules/mob/observer/eye/blueprints_eye.dm index ffbb8715edc..9bbd541ac19 100644 --- a/code/modules/mob/observer/eye/blueprints_eye.dm +++ b/code/modules/mob/observer/eye/blueprints_eye.dm @@ -52,7 +52,7 @@ . = ..() /mob/observer/eye/blueprints/proc/create_area() - var/area_name = sanitizeSafe(input("New area name:","Area Creation", ""), MAX_NAME_LEN) + var/area_name = sanitize_safe(input("New area name:","Area Creation", ""), MAX_NAME_LEN) if(!area_name || !length(area_name)) return if(length(area_name) > 50) @@ -89,7 +89,7 @@ if(!check_modification_validity()) return var/prevname = A.name - var/new_area_name = sanitizeSafe(input("Edit area name:","Area Editing", prevname), MAX_NAME_LEN) + var/new_area_name = sanitize_safe(input("Edit area name:","Area Editing", prevname), MAX_NAME_LEN) if(!new_area_name || !LAZYLEN(new_area_name) || new_area_name==prevname) return if(length(new_area_name) > 50) diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm index d47d9727888..ee2d1ae7109 100644 --- a/code/modules/modular_computers/file_system/programs/command/card.dm +++ b/code/modules/modular_computers/file_system/programs/command/card.dm @@ -206,7 +206,7 @@ if(computer && can_run(user, 1)) var/static/regex/hash_check = regex(@"^[0-9a-fA-F]{32}$") if(href_list["name"]) - var/temp_name = sanitizeName(input("Enter name.", "Name", id_card.registered_name),allow_numbers=TRUE) + var/temp_name = sanitize_name(input("Enter name.", "Name", id_card.registered_name),allow_numbers=TRUE) if(temp_name && CanUseTopic(user)) id_card.registered_name = temp_name id_card.formal_name_suffix = initial(id_card.formal_name_suffix) diff --git a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm index b046ffd5b01..995e5504edf 100644 --- a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm @@ -70,7 +70,7 @@ if(href_list["PRG_newchannel"]) . = 1 var/mob/living/user = usr - var/channel_title = sanitizeSafe(input(user,"Enter channel name or leave blank to cancel:"), 64) + var/channel_title = sanitize_safe(input(user,"Enter channel name or leave blank to cancel:"), 64) if(!channel_title) return var/datum/chat_conversation/C = new/datum/chat_conversation(network) diff --git a/code/modules/organs/external/head.dm b/code/modules/organs/external/head.dm index df089d2b120..68d285a4d98 100644 --- a/code/modules/organs/external/head.dm +++ b/code/modules/organs/external/head.dm @@ -52,7 +52,7 @@ to_chat(penman, "There is no room left to write on [head_name]!") return - var/graffiti = sanitizeSafe(input(penman, "Enter a message to write on [head_name]:") as text|null, MAX_NAME_LEN) + var/graffiti = sanitize_safe(input(penman, "Enter a message to write on [head_name]:") as text|null, MAX_NAME_LEN) if(graffiti) if(!target.Adjacent(penman)) to_chat(penman, "[head_name] is too far away.") diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index d353b49915a..aa0c0e51a54 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -36,7 +36,7 @@ to_chat(user, "You put the [W] into \the [src].") update_icon() else if(istype(W, /obj/item/pen)) - var/n_name = sanitizeSafe(input(usr, "What would you like to label the folder?", "Folder Labelling", null) as text, MAX_NAME_LEN) + var/n_name = sanitize_safe(input(usr, "What would you like to label the folder?", "Folder Labelling", null) as text, MAX_NAME_LEN) if((loc == usr && usr.stat == 0)) SetName("folder[(n_name ? text("- '[n_name]'") : null)]") return diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index c91a77a0645..6210655fa26 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -56,7 +56,7 @@ if(mode) to_chat(user, "You turn on \the [src].") //Now let them chose the text. - var/str = sanitizeSafe(input(user,"Label text?","Set label",""), MAX_LNAME_LEN) + var/str = sanitize_safe(input(user,"Label text?","Set label",""), MAX_LNAME_LEN) if(!str || !length(str)) to_chat(user, "Invalid text.") return diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 0e6e2e69309..9d44b016b00 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -105,7 +105,7 @@ if((MUTATION_CLUMSY in usr.mutations) && prob(50)) to_chat(usr, "You cut yourself on the paper.") return - var/n_name = sanitizeSafe(input(usr, "What would you like to label the paper?", "Paper Labelling", null) as text, MAX_NAME_LEN) + var/n_name = sanitize_safe(input(usr, "What would you like to label the paper?", "Paper Labelling", null) as text, MAX_NAME_LEN) // We check loc one level up, so we can rename in clipboards and such. See also: /obj/item/photo/rename() if(!n_name || !CanInteract(usr, global.deep_inventory_topic_state)) diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index 1d15d3728e4..39accad26d6 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -185,7 +185,7 @@ set category = "Object" set src in usr - var/n_name = sanitizeSafe(input(usr, "What would you like to label the bundle?", "Bundle Labelling", null) as text, MAX_NAME_LEN) + var/n_name = sanitize_safe(input(usr, "What would you like to label the bundle?", "Bundle Labelling", null) as text, MAX_NAME_LEN) if((loc == usr || loc.loc && loc.loc == usr) && usr.stat == 0) SetName("[(n_name ? text("[n_name]") : "paper")]") add_fingerprint(usr) diff --git a/code/modules/paperwork/paper_sticky.dm b/code/modules/paperwork/paper_sticky.dm index 2756fc1412b..ea745dc6064 100644 --- a/code/modules/paperwork/paper_sticky.dm +++ b/code/modules/paperwork/paper_sticky.dm @@ -42,7 +42,7 @@ if(writing_space <= 0) to_chat(user, SPAN_WARNING("There is no room left on \the [src].")) return - var/text = sanitizeSafe(input("What would you like to write?") as text, writing_space) + var/text = sanitize_safe(input("What would you like to write?") as text, writing_space) if(!text || thing.loc != user || (!Adjacent(user) && loc != user) || user.incapacitated()) return user.visible_message(SPAN_NOTICE("\The [user] jots a note down on \the [src].")) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index c6da65ce65a..1631ff94409 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -92,7 +92,7 @@ var/global/photo_count = 0 set category = "Object" set src in usr - var/n_name = sanitizeSafe(input(usr, "What would you like to label the photo?", "Photo Labelling", null) as text, MAX_NAME_LEN) + var/n_name = sanitize_safe(input(usr, "What would you like to label the photo?", "Photo Labelling", null) as text, MAX_NAME_LEN) //loc.loc check is for making possible renaming photos in clipboards if(!n_name || !CanInteract(usr, global.deep_inventory_topic_state)) return diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index c1d944b6199..b51ba41107c 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -87,7 +87,7 @@ return var/tmp_label = "" - var/label_text = sanitizeSafe(input(user, "Inscribe some text into \the [initial(BB.name)]","Inscription",tmp_label), MAX_NAME_LEN) + var/label_text = sanitize_safe(input(user, "Inscribe some text into \the [initial(BB.name)]","Inscription",tmp_label), MAX_NAME_LEN) if(length(label_text) > 20) to_chat(user, "The inscription can be at most 20 characters long.") else if(!label_text) diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 357c5182e4d..be35db04849 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -167,7 +167,7 @@ var/amount_per_pill = reagents.total_volume/count if (amount_per_pill > 30) amount_per_pill = 30 - var/name = sanitizeSafe(input(usr,"Name:","Name your pill!","[reagents.get_primary_reagent_name()] ([amount_per_pill]u)"), MAX_NAME_LEN) + var/name = sanitize_safe(input(usr,"Name:","Name your pill!","[reagents.get_primary_reagent_name()] ([amount_per_pill]u)"), MAX_NAME_LEN) if(!CanInteract(user, state)) return @@ -226,7 +226,7 @@ . = JOINTEXT(.) /obj/machinery/chem_master/proc/create_bottle(mob/user) - var/name = sanitizeSafe(input(usr,"Name:","Name your bottle!",reagents.get_primary_reagent_name()), MAX_NAME_LEN) + var/name = sanitize_safe(input(usr,"Name:","Name your bottle!",reagents.get_primary_reagent_name()), MAX_NAME_LEN) var/obj/item/chems/glass/bottle/P = new/obj/item/chems/glass/bottle(loc) if(!name) name = reagents.get_primary_reagent_name() diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 7db9020a940..c52b7a48641 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -60,7 +60,7 @@ /obj/item/chems/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/pen) || istype(W, /obj/item/flashlight/pen)) - var/tmp_label = sanitizeSafe(input(user, "Enter a label for [name]", "Label", label_text), MAX_NAME_LEN) + var/tmp_label = sanitize_safe(input(user, "Enter a label for [name]", "Label", label_text), MAX_NAME_LEN) if(length(tmp_label) > 10) to_chat(user, "The label can be at most 10 characters long.") else diff --git a/code/modules/reagents/reagent_containers/condiment.dm b/code/modules/reagents/reagent_containers/condiment.dm index 30256ef845d..ed346a004c8 100644 --- a/code/modules/reagents/reagent_containers/condiment.dm +++ b/code/modules/reagents/reagent_containers/condiment.dm @@ -33,7 +33,7 @@ /obj/item/chems/condiment/attackby(var/obj/item/W, var/mob/user) if(istype(W, /obj/item/pen) || istype(W, /obj/item/flashlight/pen)) - var/tmp_label = sanitizeSafe(input(user, "Enter a label for [name]", "Label", label_text), MAX_NAME_LEN) + var/tmp_label = sanitize_safe(input(user, "Enter a label for [name]", "Label", label_text), MAX_NAME_LEN) if(tmp_label == label_text) return if(length(tmp_label) > 10) diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 41d463f4278..1f01aadd845 100644 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -44,7 +44,7 @@ else if(istype(W, /obj/item/pen)) switch(alert("What would you like to alter?",,"Title","Description", "Cancel")) if("Title") - var/str = sanitizeSafe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN) + var/str = sanitize_safe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN) if(!str || !length(str)) to_chat(usr, " Invalid text.") return @@ -169,7 +169,7 @@ else if(istype(W, /obj/item/pen)) switch(alert("What would you like to alter?",,"Title","Description", "Cancel")) if("Title") - var/str = sanitizeSafe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN) + var/str = sanitize_safe(input(usr,"Label text?","Set label",""), MAX_NAME_LEN) if(!str || !length(str)) to_chat(usr, " Invalid text.") return diff --git a/code/procs/announce.dm b/code/procs/announce.dm index 94d174eb61d..1ce2db213a6 100644 --- a/code/procs/announce.dm +++ b/code/procs/announce.dm @@ -47,7 +47,7 @@ var/global/datum/announcement/minor/minor_announcement = new(new_sound = 'sound/ if(!msg_sanitized) message = sanitize(message, extra = 0) - message_title = sanitizeSafe(message_title) + message_title = sanitize_safe(message_title) var/msg = FormMessage(message, message_title) for(var/mob/M in global.player_list) diff --git a/mods/species/adherent/datum/culture.dm b/mods/species/adherent/datum/culture.dm index 01dbe64bd9a..c3643adbb09 100644 --- a/mods/species/adherent/datum/culture.dm +++ b/mods/species/adherent/datum/culture.dm @@ -14,5 +14,5 @@ /decl/cultural_info/culture/adherent/get_random_name(gender) return "[uppertext("[pick(global.full_alphabet)][pick(global.full_alphabet)]-[pick(global.full_alphabet)] [rand(1000,9999)]")]" -/decl/cultural_info/culture/adherent/sanitize_name(name) - return sanitizeName(name, allow_numbers = TRUE) +/decl/cultural_info/culture/adherent/sanitize_cultural_name(name) + return sanitize_name(name, allow_numbers = TRUE) diff --git a/mods/species/adherent/organs/organs_internal.dm b/mods/species/adherent/organs/organs_internal.dm index b17fd5c6a53..34a47a0c54c 100644 --- a/mods/species/adherent/organs/organs_internal.dm +++ b/mods/species/adherent/organs/organs_internal.dm @@ -32,7 +32,7 @@ to_chat(user, "Nonstandard names are not subject to real-time modification under [PROTOCOL_ARTICLE].") return - var/newname = sanitizeSafe(input(user, "Enter a new ident.", "Reset Ident") as text, MAX_NAME_LEN) + var/newname = sanitize_safe(input(user, "Enter a new ident.", "Reset Ident") as text, MAX_NAME_LEN) if(newname) var/confirm = input(user, "Are you sure you wish your name to become [newname] [res]?","Reset Ident") as anything in list("No", "Yes") if(confirm == "Yes" && owner && user == owner && !owner.incapacitated() && world.time >= next_rename) diff --git a/mods/species/vox/datum/antagonism.dm b/mods/species/vox/datum/antagonism.dm index 19896c8cbb3..8449c937553 100644 --- a/mods/species/vox/datum/antagonism.dm +++ b/mods/species/vox/datum/antagonism.dm @@ -49,7 +49,7 @@ addtimer(CALLBACK(src, .proc/do_post_voxifying, vox), 1) /obj/item/storage/mirror/raider/proc/do_post_voxifying(var/mob/living/carbon/human/vox) - var/newname = sanitizeSafe(input(vox,"Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN) + var/newname = sanitize_safe(input(vox,"Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN) if(!newname || newname == "") var/decl/cultural_info/voxculture = GET_DECL(/decl/cultural_info/culture/vox/raider) newname = voxculture.get_random_name() From 156bd3c8d11675b47a62034c3e8ddc1354cfb379 Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Thu, 16 Dec 2021 06:01:44 +0300 Subject: [PATCH 15/40] paper: replaces find and copy text procs with char variant --- code/modules/paperwork/paper.dm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 0e6e2e69309..913df332915 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -165,9 +165,9 @@ while(locid < MAX_FIELDS) var/istart = 0 if(links) - istart = findtext(info_links, "", laststart) + istart = findtext_char(info_links, "", laststart) else - istart = findtext(info, "", laststart) + istart = findtext_char(info, "", laststart) if(istart==0) return // No field found with matching id @@ -177,20 +177,20 @@ if(locid == id) var/iend = 1 if(links) - iend = findtext(info_links, "", istart) + iend = findtext_char(info_links, "", istart) else - iend = findtext(info, "", istart) + iend = findtext_char(info, "", istart) textindex = iend break if(links) - var/before = copytext(info_links, 1, textindex) - var/after = copytext(info_links, textindex) + var/before = copytext_char(info_links, 1, textindex) + var/after = copytext_char(info_links, textindex) info_links = before + text + after else - var/before = copytext(info, 1, textindex) - var/after = copytext(info, textindex) + var/before = copytext_char(info, 1, textindex) + var/after = copytext_char(info, textindex) info = before + text + after updateinfolinks() From 54f6f3786f96c5c906019ae6f375654b6d493918 Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Sat, 18 Dec 2021 09:25:24 +0300 Subject: [PATCH 16/40] test.yml: SpacemanDMM suite 1.7.1 and BYOND 514.1572 --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bf52f761a5e..0e6e97f873c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,8 +15,8 @@ on: env: BYOND_MAJOR: "514" - BYOND_MINOR: "1566" - SPACEMAN_DMM_VERSION: suite-1.7 + BYOND_MINOR: "1572" + SPACEMAN_DMM_VERSION: suite-1.7.1 jobs: DreamChecker: From 8d5dc12eb32a359f766641ef49d9bde8a905575a Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Sat, 18 Dec 2021 09:57:16 +0300 Subject: [PATCH 17/40] pr-template: cut empty lines, author name override comment --- .github/PULL_REQUEST_TEMPLATE.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 00b0aaf434a..c720132d1b5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,31 +1,26 @@ + - - - + ## Description of changes - ## Why and what will this PR improve - ## Authorship - ## Changelog - + :cl: prefix: /:cl: From 0a37f6c18f49c5acd59a30668709ec1f4a70e496 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Sun, 19 Dec 2021 00:30:26 +0000 Subject: [PATCH 18/40] Automatic changelog generation [ci skip] --- html/changelog.html | 7 ------- 1 file changed, 7 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 8f396269e96..ea0d5e0500b 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -187,13 +187,6 @@

MistakeNot4892 updated:

  • Species information is now found in the codex rather than primarily in character preferences.
- -

17 October 2021

-

CrimsonShrike updated:

-
    -
  • Adds a number of exosuit modules
  • -
  • Resprites exosuits
  • -
From e79d90a5b0199502125924bb771f96aeb5ae4109 Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Sat, 18 Dec 2021 12:35:27 +0300 Subject: [PATCH 19/40] screen-movable: fixes loc offset on assign --- code/_onclick/hud/movable_screen_objects.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index fc9120c4dfd..8d024420c4e 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -8,4 +8,4 @@ var/list/screen_loc_params = splittext(PM["screen-loc"], ",") var/list/x_data = splittext(screen_loc_params[1], ":") var/list/y_data = splittext(screen_loc_params[2], ":") - screen_loc = "LEFT+[x_data[1]]:[text2num(x_data[2])-16],BOTTOM+[y_data[1]]:[text2num(y_data[2])-16]" + screen_loc = "LEFT+[x_data[1]]:[text2num(x_data[2])-(1.5 * world.icon_size)],BOTTOM+[y_data[1]]:[text2num(y_data[2])-(1.5 * world.icon_size)]" From 9d13c6876f0d31a55cdff6b788bf736495034168 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Tue, 21 Dec 2021 00:30:42 +0000 Subject: [PATCH 20/40] Automatic changelog generation [ci skip] --- html/changelog.html | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index ea0d5e0500b..d36a60f531a 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -172,21 +172,6 @@

NataKilar updated:

  • Robots now properly work as cameras for the purpose of AI vision
  • TV cameras can now have their network settings adjusted as intended.
  • - -

    19 October 2021

    -

    CrimsonShrike updated:

    -
      -
    • Exosuit radios work again.
    • -
    • Intercom shortcut is not usable for exosuits too
    • -
    -

    CrimsonShrike & Azlan updated:

    -
      -
    • Adds exosuit cameras
    • -
    -

    MistakeNot4892 updated:

    -
      -
    • Species information is now found in the codex rather than primarily in character preferences.
    • -
    From 20b5f2e6cf5dd003206dee96b8622fb17b5d250d Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Wed, 22 Dec 2021 00:29:36 +0000 Subject: [PATCH 21/40] Automatic changelog generation [ci skip] --- html/changelog.html | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index d36a60f531a..d39f6db91f8 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -161,17 +161,6 @@

    MistakeNot4892 updated:

  • Brute and burn meds no longer stack with regenerative serum.
  • Light tubes and floodlights are higher range.
  • - -

    20 October 2021

    -

    CrimsonShrike updated:

    -
      -
    • Swimming.
    • -
    -

    NataKilar updated:

    -
      -
    • Robots now properly work as cameras for the purpose of AI vision
    • -
    • TV cameras can now have their network settings adjusted as intended.
    • -
    From 6715e55acb01d2778d1d8702f5f0ad23adfa61a4 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Thu, 23 Dec 2021 00:28:46 +0000 Subject: [PATCH 22/40] Automatic changelog generation [ci skip] --- html/changelog.html | 7 ------- 1 file changed, 7 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index d39f6db91f8..d6990c8715d 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -154,13 +154,6 @@

    lolman360 updated:

    • plasmacutters now cut mineral walls
    - -

    21 October 2021

    -

    MistakeNot4892 updated:

    -
      -
    • Brute and burn meds no longer stack with regenerative serum.
    • -
    • Light tubes and floodlights are higher range.
    • -
    From 65351a592500a1253b53e736133322ac2ee926e7 Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Thu, 23 Dec 2021 15:51:12 +0300 Subject: [PATCH 23/40] sstimer: adds as anything for loop --- code/controllers/subsystems/timer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/controllers/subsystems/timer.dm b/code/controllers/subsystems/timer.dm index 5204ff7f7b4..d62ad0af676 100644 --- a/code/controllers/subsystems/timer.dm +++ b/code/controllers/subsystems/timer.dm @@ -259,7 +259,7 @@ SUBSYSTEM_DEF(timer) // Add all timed events from the secondary queue as well alltimers += second_queue - for (var/datum/timedevent/t in alltimers) + for (var/datum/timedevent/t as anything in alltimers) t.bucket_joined = FALSE t.bucket_pos = -1 t.prev = null From 4284572d9714b437662cd5f028682cf8c2d1e9b6 Mon Sep 17 00:00:00 2001 From: vallat Date: Fri, 24 Dec 2021 10:44:33 +0400 Subject: [PATCH 24/40] working wide-screen parallax --- code/_onclick/hud/skybox.dm | 73 ++++++++++--------- code/game/atoms.dm | 6 +- .../mob/living/carbon/human/update_icons.dm | 6 +- code/modules/mob/login.dm | 4 +- interface/skin.dmf | 1 + 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/code/_onclick/hud/skybox.dm b/code/_onclick/hud/skybox.dm index fb5546c5a29..81605748f91 100644 --- a/code/_onclick/hud/skybox.dm +++ b/code/_onclick/hud/skybox.dm @@ -1,5 +1,4 @@ -#define SKYBOX_MAX_BOUND 736 - +var/global/const/SKYBOX_DIMENSION = 736 // Largest measurement for icon sides, used for offsets/scaling /obj/skybox name = "skybox" mouse_opacity = 0 @@ -7,13 +6,14 @@ simulated = FALSE plane = SKYBOX_PLANE blend_mode = BLEND_MULTIPLY - var/base_x_dim = 7 - var/base_y_dim = 7 - var/base_offset_x = -224 // -(world.view x dimension * world.icon_size) - var/base_offset_y = -224 // -(world.view y dimension * world.icon_size) + screen_loc = "CENTER,CENTER" + transform_animate_time = 0 + var/static/max_view_dim + var/static/const/parallax_bleed_percent = 0.2 // 20% parallax offset when going from x=1 to x=max /obj/skybox/Initialize() - screen_loc = "CENTER:[base_offset_x],CENTER:[base_offset_y]" + if(!max_view_dim) + max_view_dim = CEILING(SKYBOX_DIMENSION / world.icon_size) . = ..() /client @@ -22,35 +22,44 @@ /client/proc/set_skybox_offsets(var/x_dim, var/y_dim) if(!skybox) update_skybox() - if(skybox) - skybox.base_x_dim = x_dim - skybox.base_y_dim = y_dim - skybox.base_offset_x = -((world.icon_size * skybox.base_x_dim)/2) - skybox.base_offset_y = -((world.icon_size * skybox.base_y_dim)/2) - - // Check if the skybox needs to be scaled to fit large displays. - var/new_max_tile_bound = max(skybox.base_x_dim, skybox.base_y_dim) - var/old_max_tile_bound = SKYBOX_MAX_BOUND/world.icon_size - if(new_max_tile_bound > old_max_tile_bound) - var/matrix/M = matrix() - M.Scale(1 + (new_max_tile_bound/old_max_tile_bound)) - skybox.transform = M - else - skybox.transform = null - update_skybox() + var/scale_value = 1 + if(isnum(view)) + var/target_icon_size = min(view*2, skybox.max_view_dim) * world.icon_size + scale_value = skybox.parallax_bleed_percent + max((target_icon_size / SKYBOX_DIMENSION), 1) + skybox.screen_loc = "CENTER:-[view * world.icon_size],CENTER:-[view * world.icon_size]" + else + var/target_icon_size = max(x_dim, y_dim) * world.icon_size + scale_value = skybox.parallax_bleed_percent + max((target_icon_size / SKYBOX_DIMENSION), 1) + skybox.screen_loc = "CENTER:-[round(SKYBOX_DIMENSION * scale_value / 2)],CENTER:-[round(SKYBOX_DIMENSION * scale_value / 2)]" + skybox.set_scale(scale_value) + update_skybox() /client/proc/update_skybox(rebuild) + + var/turf/T = get_turf(eye) + if(!T) + return + if(!skybox) skybox = new() screen += skybox - rebuild = 1 - var/turf/T = get_turf(eye) - if(T) - if(rebuild) - skybox.overlays.Cut() - skybox.overlays += SSskybox.get_skybox(T.z) - screen |= skybox - skybox.screen_loc = "CENTER:[skybox.base_offset_x - T.x],CENTER:[skybox.base_offset_y - T.y]" + rebuild = TRUE + + if(rebuild) + skybox.overlays.Cut() + var/image/I = SSskybox.get_skybox(T.z) + I.appearance_flags |= PIXEL_SCALE + skybox.overlays += I + screen |= skybox + set_skybox_offsets(last_view_x_dim, last_view_y_dim) + return + + if(skybox.parallax_bleed_percent > 0) + var/matrix/M = skybox.update_transform() || matrix() + var/x_translate = -((T.x/world.maxx)-0.5) * skybox.parallax_bleed_percent * SKYBOX_DIMENSION + var/y_translate = -((T.y/world.maxy)-0.5) * skybox.parallax_bleed_percent * SKYBOX_DIMENSION + M.Translate(x_translate, y_translate) + skybox.transform = M /mob/Move() var/old_z = get_z(src) @@ -63,5 +72,3 @@ . = ..() if(. && client) client.update_skybox(old_z != get_z(src)) - -#undef SKYBOX_MAX_BOUND \ No newline at end of file diff --git a/code/game/atoms.dm b/code/game/atoms.dm index c9c7f3a672e..8542a650d98 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -580,7 +580,11 @@ its easier to just keep the beam vertical. var/matrix/M = matrix() M.Scale(icon_scale_x, icon_scale_y) M.Turn(icon_rotation) - animate(src, transform = M, transform_animate_time) + if(transform_animate_time) + animate(src, transform = M, transform_animate_time) + else + transform = M + return transform // Walks up the loc tree until it finds a loc of the given loc_type /atom/get_recursive_loc_of_type(var/loc_type) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index e51ac679a09..b4e70e70177 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -244,7 +244,11 @@ Please contact me on #coderbus IRC. ~Carn x else M.Scale(desired_scale_x, desired_scale_y) M.Translate(0, 16*(desired_scale_y-1)) - animate(src, transform = M, time = transform_animate_time) + if(transform_animate_time) + animate(src, transform = M, time = transform_animate_time) + else + transform = M + return transform var/global/list/damage_icon_parts = list() diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 7909b011cfa..73e9a16cdb4 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -85,10 +85,12 @@ if(eyeobj) eyeobj.possess(src) - client.update_skybox(1) events_repository.raise_event(/decl/observ/logged_in, src) hud_reset(TRUE) + + client.update_skybox(1) + if(machine) machine.on_user_login(src) diff --git a/interface/skin.dmf b/interface/skin.dmf index e1a1b114cae..50e68f4ec05 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -129,6 +129,7 @@ window "mainwindow" anchor1 = none anchor2 = none is-default = true + background-color = #000000 saved-params = "pos;size;is-minimized;is-maximized" on-size = "OnResize" is-maximized = true From 8fa5fdab5e578d704d0eef4e9822caa4f09b0ee1 Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Fri, 24 Dec 2021 11:05:07 +0300 Subject: [PATCH 25/40] dbban: adds database based ban panel to verbs list --- code/modules/admin/admin_verbs.dm | 1 + code/modules/admin/{DB ban => dbban}/functions.dm | 2 +- nebula.dme | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename code/modules/admin/{DB ban => dbban}/functions.dm (99%) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 5b92362faf2..1ea11acce87 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -94,6 +94,7 @@ var/global/list/admin_verbs_admin = list( /datum/admins/proc/show_aspects ) var/global/list/admin_verbs_ban = list( + /client/proc/DB_ban_panel, /client/proc/unban_panel, /client/proc/jobbans ) diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/dbban/functions.dm similarity index 99% rename from code/modules/admin/DB ban/functions.dm rename to code/modules/admin/dbban/functions.dm index 5cde2396817..ee761246959 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/dbban/functions.dm @@ -294,7 +294,7 @@ /client/proc/DB_ban_panel() set category = "Admin" set name = "Banning Panel" - set desc = "Edit admin permissions" + set desc = "Allow edit existing bans or create new ones." if(!holder) return diff --git a/nebula.dme b/nebula.dme index 33b0c1342d4..e0b48cf399f 100644 --- a/nebula.dme +++ b/nebula.dme @@ -1386,7 +1386,7 @@ #include "code\modules\admin\buildmode\room_builder.dm" #include "code\modules\admin\buildmode\throw_at.dm" #include "code\modules\admin\callproc\callproc.dm" -#include "code\modules\admin\DB ban\functions.dm" +#include "code\modules\admin\dbban\functions.dm" #include "code\modules\admin\permissionverbs\permissionedit.dm" #include "code\modules\admin\secrets\admin_secrets\admin_logs.dm" #include "code\modules\admin\secrets\admin_secrets\bombing_list.dm" From 9e59884c225e84e2443492eef3d9e19bc91398db Mon Sep 17 00:00:00 2001 From: Vallat Date: Fri, 24 Dec 2021 14:19:18 +0400 Subject: [PATCH 26/40] Update code/_onclick/hud/skybox.dm --- code/_onclick/hud/skybox.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/_onclick/hud/skybox.dm b/code/_onclick/hud/skybox.dm index 81605748f91..0feef319fd3 100644 --- a/code/_onclick/hud/skybox.dm +++ b/code/_onclick/hud/skybox.dm @@ -24,7 +24,7 @@ var/global/const/SKYBOX_DIMENSION = 736 // Largest measurement for icon sides, u update_skybox() var/scale_value = 1 if(isnum(view)) - var/target_icon_size = min(view*2, skybox.max_view_dim) * world.icon_size + var/target_icon_size = (view * 2 + 1) * world.icon_size scale_value = skybox.parallax_bleed_percent + max((target_icon_size / SKYBOX_DIMENSION), 1) skybox.screen_loc = "CENTER:-[view * world.icon_size],CENTER:-[view * world.icon_size]" else From f17161845852b695b523b023deacd3065fc7e6e0 Mon Sep 17 00:00:00 2001 From: vallat Date: Fri, 24 Dec 2021 21:14:48 +0400 Subject: [PATCH 27/40] weird runtime error fix --- code/_onclick/hud/skybox.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/_onclick/hud/skybox.dm b/code/_onclick/hud/skybox.dm index 0feef319fd3..9bd447bf94b 100644 --- a/code/_onclick/hud/skybox.dm +++ b/code/_onclick/hud/skybox.dm @@ -21,7 +21,8 @@ var/global/const/SKYBOX_DIMENSION = 736 // Largest measurement for icon sides, u /client/proc/set_skybox_offsets(var/x_dim, var/y_dim) if(!skybox) - update_skybox() + update_skybox(TRUE) + return var/scale_value = 1 if(isnum(view)) var/target_icon_size = (view * 2 + 1) * world.icon_size From 342111f80485f73a106517b440ac9d01a289293b Mon Sep 17 00:00:00 2001 From: quardbreak <44920739+quardbreak@users.noreply.github.com> Date: Mon, 27 Dec 2021 14:23:21 +0300 Subject: [PATCH 28/40] ventcrawl: diagonal direction no longer breaks movement --- code/__defines/directions.dm | 2 ++ code/modules/keybindings/bindings_atom.dm | 6 ++---- code/modules/ventcrawl/ventcrawl_atmospherics.dm | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/code/__defines/directions.dm b/code/__defines/directions.dm index bb6252cb3e6..b4524560447 100644 --- a/code/__defines/directions.dm +++ b/code/__defines/directions.dm @@ -16,6 +16,8 @@ #define CORNER_EASTWEST CORNER_COUNTERCLOCKWISE #define CORNER_NORTHSOUTH CORNER_CLOCKWISE +#define FIRST_DIR(X) ((X) & -(X)) + /* turn() is weird: turn(icon, angle) turns icon by angle degrees clockwise diff --git a/code/modules/keybindings/bindings_atom.dm b/code/modules/keybindings/bindings_atom.dm index 3e83eeb0be4..527e5a11598 100644 --- a/code/modules/keybindings/bindings_atom.dm +++ b/code/modules/keybindings/bindings_atom.dm @@ -18,10 +18,8 @@ if(!config.allow_diagonal_movement) if(movement_dir & user.last_move_dir_pressed) movement_dir = user.last_move_dir_pressed - else if (movement_dir == NORTHEAST || movement_dir == NORTHWEST) - movement_dir = NORTH - else if (movement_dir == SOUTHEAST || movement_dir == SOUTHWEST) - movement_dir = SOUTH + else + movement_dir = FIRST_DIR(movement_dir) if(movement_dir) //If we're not moving, don't compensate, as byond will auto-fill dir otherwise movement_dir = turn(movement_dir, -dir2angle(user.dir)) //By doing this we ensure that our input direction is offset by the client (camera) direction diff --git a/code/modules/ventcrawl/ventcrawl_atmospherics.dm b/code/modules/ventcrawl/ventcrawl_atmospherics.dm index 6097e15ca43..a12184e78e3 100644 --- a/code/modules/ventcrawl/ventcrawl_atmospherics.dm +++ b/code/modules/ventcrawl/ventcrawl_atmospherics.dm @@ -15,7 +15,10 @@ /obj/machinery/atmospherics/relaymove(mob/living/user, direction) if(user.loc != src || !(direction & initialize_directions)) //can't go in a way we aren't connecting to return - ventcrawl_to(user,findConnecting(direction),direction) + + // Only cardinals allowed. + direction = FIRST_DIR(direction) + ventcrawl_to(user,findConnecting(direction), direction) /obj/machinery/atmospherics/proc/ventcrawl_to(var/mob/living/user, var/obj/machinery/atmospherics/target_move, var/direction) if(target_move) From 6de043c673fc57f0e48055610eb135733f130c7a Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Sun, 2 Jan 2022 00:30:10 +0000 Subject: [PATCH 29/40] Automatic changelog generation [ci skip] --- html/changelog.html | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index d6990c8715d..109e674275b 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -140,20 +140,6 @@

    MistakeNot4892 updated:

    • Painkillers will now apply their additional effects at much lower cumulative dosage.
    - -

    31 October 2021

    -

    Kaksisilma updated:

    -
      -
    • Ion Thruster density is now set to 1.
    • -
    -

    PsyCommando updated:

    -
      -
    • Fix cryopods without control computers from runtiming during init.
    • -
    -

    lolman360 updated:

    -
      -
    • plasmacutters now cut mineral walls
    • -
    From cd49155efb3befad01ae382e18d7d04ab25e5932 Mon Sep 17 00:00:00 2001 From: Gaxeer Date: Fri, 31 Dec 2021 03:07:15 +0200 Subject: [PATCH 30/40] fix: fix looping APC sound --- code/modules/power/apc.dm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 625fd3c8ec7..98a72f48766 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -99,7 +99,7 @@ var/global/list/all_apcs = list() initial_access = list(access_engine_equip) clicksound = "switch" layer = ABOVE_WINDOW_LAYER - var/needs_powerdown_sound + var/powered_down = FALSE var/area/area var/areastring = null var/shorted = 0 @@ -612,12 +612,13 @@ var/global/list/all_apcs = list() area.power_change() var/obj/item/cell/cell = get_cell() - if(!cell || cell.charge <= 0) - if(needs_powerdown_sound == TRUE) + if(!powered_down) + if(!cell || cell.charge <= 0) playsound(src, 'sound/machines/apc_nopower.ogg', 75, 0) - needs_powerdown_sound = FALSE - else - needs_powerdown_sound = TRUE + powered_down = TRUE + + else if(cell?.charge > 0) + powered_down = FALSE /obj/machinery/power/apc/proc/isWireCut(var/wireIndex) return wires.IsIndexCut(wireIndex) From 4ae9cc8bb6c43e5082caf79491906cfeec1b55e9 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Sun, 2 Jan 2022 12:37:38 +1100 Subject: [PATCH 31/40] Automatic changelog generation for PR #2272 [ci skip] --- html/changelogs/AutoChangeLog-pr-2272.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2272.yml diff --git a/html/changelogs/AutoChangeLog-pr-2272.yml b/html/changelogs/AutoChangeLog-pr-2272.yml new file mode 100644 index 00000000000..0dbfc5fae18 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2272.yml @@ -0,0 +1,4 @@ +author: tag if you want to specify another name or several people. --> +delete-after: true +changes: + - bugfix: fix looping APC power down sound From 2f10b57c9983a2bf2c233a0f63076cf0c2e9f607 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Mon, 3 Jan 2022 00:28:58 +0000 Subject: [PATCH 32/40] Automatic changelog generation [ci skip] --- html/changelog.html | 12 ++++++------ html/changelogs/.all_changelog.yml | 3 +++ html/changelogs/AutoChangeLog-pr-2272.yml | 4 ---- 3 files changed, 9 insertions(+), 10 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-2272.yml diff --git a/html/changelog.html b/html/changelog.html index 109e674275b..ebfdcd77e2c 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -52,6 +52,12 @@ -->
    +

    03 January 2022

    +

    tag if you want to specify another name or several people. --> updated:

    +
      +
    • fix looping APC power down sound
    • +
    +

    04 December 2021

    MistakeNot4892 updated:

      @@ -134,12 +140,6 @@

      anconfuzedrock updated:

      • graphite is now spawnable and orderable.
      - -

      01 November 2021

      -

      MistakeNot4892 updated:

      -
        -
      • Painkillers will now apply their additional effects at much lower cumulative dosage.
      • -
    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index e9d514fe60c..71addecfb04 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -14064,3 +14064,6 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. MistakeNot4892: - tweak: Utility frames, Kharmaani and adherent now bleed exciting new colours. - tweak: Human subtypes can now share blood without triggering a rejection. +2022-01-03: + tag if you want to specify another name or several people. -->: + - bugfix: fix looping APC power down sound diff --git a/html/changelogs/AutoChangeLog-pr-2272.yml b/html/changelogs/AutoChangeLog-pr-2272.yml deleted file mode 100644 index 0dbfc5fae18..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2272.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: tag if you want to specify another name or several people. --> -delete-after: true -changes: - - bugfix: fix looping APC power down sound From 6cf5819aab40409d0e10336dd3a6744ab99160d8 Mon Sep 17 00:00:00 2001 From: Gaxeer Date: Mon, 3 Jan 2022 21:33:24 +0200 Subject: [PATCH 33/40] fix: grabbed dead mobs now able to move after the grabber --- code/datums/movement/mob.dm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/code/datums/movement/mob.dm b/code/datums/movement/mob.dm index 3bd328bdcb3..d31a94d6e22 100644 --- a/code/datums/movement/mob.dm +++ b/code/datums/movement/mob.dm @@ -13,12 +13,15 @@ control_object.set_dir(direction) // Death handling -/datum/movement_handler/mob/death/DoMove() - if(mob.stat != DEAD) +/datum/movement_handler/mob/death/DoMove(var/direction, var/mob/mover) + if(mob != mover || mob.stat != DEAD) return + . = MOVEMENT_HANDLED + if(!mob.client) return + mob.ghostize() // Incorporeal/Ghost movement From 8643dbc09c6c0a8a05bf436b63ff4424c312cc84 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Tue, 4 Jan 2022 00:29:13 +0000 Subject: [PATCH 34/40] Automatic changelog generation [ci skip] --- html/changelog.html | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index ebfdcd77e2c..7388c0810cb 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -129,17 +129,6 @@

    NataKilar updated:

    • Fixes a bug with blueprint and shuttle landing vision causing mobs to see blackness.
    - -

    02 November 2021

    -

    PsyCommando updated:

    -
      -
    • Fixed runtime on autosetting airlocks placed outside an area.
    • -
    • Fixed runtime on building an external airlock outside an area.
    • -
    -

    anconfuzedrock updated:

    -
      -
    • graphite is now spawnable and orderable.
    • -
    From 7ad0fae69513bd070da4788ca91fae48b4760409 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Wed, 5 Jan 2022 00:30:53 +0000 Subject: [PATCH 35/40] Automatic changelog generation [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 7388c0810cb..6cb25f5f8c7 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -123,12 +123,6 @@

    MistakeNot4892 updated:

    • Added behavior for reloadable energy weapons.
    - -

    03 November 2021

    -

    NataKilar updated:

    -
      -
    • Fixes a bug with blueprint and shuttle landing vision causing mobs to see blackness.
    • -
    From 6ce17304ad435b3f7749a49f11b23a5e2182e18c Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Sun, 9 Jan 2022 00:30:49 +0000 Subject: [PATCH 36/40] Automatic changelog generation [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index 6cb25f5f8c7..91f187fb958 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -117,12 +117,6 @@

    MistakeNot4892 updated:

    • There is now a weather system on exoplanets. Take your umbrella.
    - -

    07 November 2021

    -

    MistakeNot4892 updated:

    -
      -
    • Added behavior for reloadable energy weapons.
    • -
    From 53845af210d7615cccf2cd6c44a7beebe4f3d8a7 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Mon, 10 Jan 2022 12:41:14 +1100 Subject: [PATCH 37/40] Automatic changelog generation for PR #2273 [ci skip] --- html/changelogs/AutoChangeLog-pr-2273.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-2273.yml diff --git a/html/changelogs/AutoChangeLog-pr-2273.yml b/html/changelogs/AutoChangeLog-pr-2273.yml new file mode 100644 index 00000000000..4934c8ff2b4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2273.yml @@ -0,0 +1,4 @@ +author: Gaxeer +delete-after: true +changes: + - bugfix: fix the bug with grab-moving dead mob From c347d684a06b99f0eb739ef32077679c51bfb2ed Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Tue, 11 Jan 2022 00:31:07 +0000 Subject: [PATCH 38/40] Automatic changelog generation [ci skip] --- html/changelog.html | 17 ++++++----------- html/changelogs/.all_changelog.yml | 3 +++ html/changelogs/AutoChangeLog-pr-2273.yml | 4 ---- 3 files changed, 9 insertions(+), 15 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-2273.yml diff --git a/html/changelog.html b/html/changelog.html index 91f187fb958..ac19151450f 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -52,6 +52,12 @@ -->
    +

    11 January 2022

    +

    Gaxeer updated:

    +
      +
    • fix the bug with grab-moving dead mob
    • +
    +

    03 January 2022

    tag if you want to specify another name or several people. --> updated:

      @@ -106,17 +112,6 @@

      Kaksisilma updated:

      • painkillers now have a number of modular vars for use in the creation of subtypes.
      - -

      09 November 2021

      -

      Andromeda-K22 updated:

      -
        -
      • machines no longer directly check brainloss, but instead rely fully on dexterity checks.
      • -
      • dexterity is influenced by brain damage, starting at 30 brainloss (configurable). Dexterity loss is on a sliding scale.
      • -
      -

      MistakeNot4892 updated:

      -
        -
      • There is now a weather system on exoplanets. Take your umbrella.
      • -
    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 71addecfb04..3819fcc8613 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -14067,3 +14067,6 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. 2022-01-03: tag if you want to specify another name or several people. -->: - bugfix: fix looping APC power down sound +2022-01-11: + Gaxeer: + - bugfix: fix the bug with grab-moving dead mob diff --git a/html/changelogs/AutoChangeLog-pr-2273.yml b/html/changelogs/AutoChangeLog-pr-2273.yml deleted file mode 100644 index 4934c8ff2b4..00000000000 --- a/html/changelogs/AutoChangeLog-pr-2273.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Gaxeer -delete-after: true -changes: - - bugfix: fix the bug with grab-moving dead mob From ca83420935ccd5068d7c71673017c8abd5e7a101 Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Sun, 16 Jan 2022 00:31:18 +0000 Subject: [PATCH 39/40] Automatic changelog generation [ci skip] --- html/changelog.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/html/changelog.html b/html/changelog.html index ac19151450f..09fe9e12597 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -106,12 +106,6 @@

    SolatK updated:

    • Russian radio keys work again.
    - -

    14 November 2021

    -

    Kaksisilma updated:

    -
      -
    • painkillers now have a number of modular vars for use in the creation of subtypes.
    • -
    From 0a301ffc6945bc08890b8f4fcaff4ad99a889330 Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Sat, 15 Jan 2022 19:15:27 -0600 Subject: [PATCH 40/40] Fix air alarm sensor settings --- code/game/machinery/alarm.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 23f8ce81acb..f6a826505bb 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -85,7 +85,7 @@ var/datum/radio_frequency/radio_connection - var/list/TLV = list() + var/list/TLV = list() // stands for Threshold Limit Value, since it handles exposure amounts var/list/trace_gas = list() //list of other gases that this air alarm is able to detect var/danger_level = 0 @@ -596,6 +596,8 @@ var/decl/material/mat = GET_DECL(g) thresholds[++thresholds.len] = list("name" = (mat?.gas_symbol_html || "Other"), "settings" = list()) selected = TLV[g] + if(!selected) + continue for(var/i = 1, i <= 4, i++) thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = i, "selected" = selected[i]))