diff --git a/README.md b/README.md index ef5fbb7b5db..8a2c2e44328 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ * **Website:** https://www.tgstation13.org * **Code:** https://github.com/tgstation/tgstation -* **Wiki** https://tgstation13.org/wiki/Main_Page +* **Wiki:** https://tgstation13.org/wiki/Main_Page * **Codedocs:** https://codedocs.tgstation13.org/ * **/tg/station Discord:** https://tgstation13.org/phpBB/viewforum.php?f=60 * **Coderbus Discord:** https://discord.gg/Vh8TJp9 diff --git a/_maps/RandomRuins/SpaceRuins/kinggoatarena.dmm b/_maps/RandomRuins/SpaceRuins/kinggoatarena.dmm index b16e7f6769b..323fe4a5594 100644 --- a/_maps/RandomRuins/SpaceRuins/kinggoatarena.dmm +++ b/_maps/RandomRuins/SpaceRuins/kinggoatarena.dmm @@ -15,10 +15,8 @@ /turf/open/indestructible/diamond, /area/ruin/powered/kinggoat_arena) "e" = ( -/obj/effect/portal/permanent/one_way/destroy{ - id = "king goat arena"; - name = "king goat arena portal"; - teleport_channel = "free" +/obj/effect/landmark/portal_exit{ + id = "king goat arena" }, /turf/open/indestructible/diamond, /area/ruin/powered/kinggoat_arena) @@ -51,7 +49,7 @@ /turf/open/indestructible/gold, /area/ruin/powered/kinggoat_arena) "j" = ( -/obj/effect/portal/permanent/one_way/keep{ +/obj/effect/portal/permanent/one_way{ id = "king goat arena"; name = "king goat arena portal"; teleport_channel = "free" diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index 153a3ca27e4..2f6d0af8bde 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -2178,8 +2178,7 @@ /area/awaymission/moonoutpost19/research) "ex" = ( /obj/machinery/atmospherics/pipe/manifold{ - dir = 4; - level = 2 + dir = 4 }, /obj/structure/cable, /turf/open/floor/plasteel/white, diff --git a/_maps/RandomZLevels/undergroundoutpost45.dmm b/_maps/RandomZLevels/undergroundoutpost45.dmm index b58ef84501e..4215651a728 100644 --- a/_maps/RandomZLevels/undergroundoutpost45.dmm +++ b/_maps/RandomZLevels/undergroundoutpost45.dmm @@ -1184,7 +1184,6 @@ "cM" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5; - level = 2 }, /turf/open/floor/plating{ heat_capacity = 1e+006 @@ -3873,7 +3872,6 @@ "hU" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4; - level = 2 }, /obj/structure/table, /obj/item/book/manual/chef_recipes, @@ -3886,7 +3884,6 @@ /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4; - level = 2 }, /turf/open/floor/plating{ heat_capacity = 1e+006 @@ -9399,7 +9396,6 @@ }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4; - level = 2 }, /obj/machinery/door/airlock/maintenance{ name = "Research Maintenance"; @@ -11265,7 +11261,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/computer/atmos_control{ dir = 4; - level = 3; name = "Distribution and Waste Monitor"; sensors = list("UO45_air_sensor" = "Mixed Air Supply Tank", "UO45_distro_meter" = "Distribution Loop", "UO45_waste_meter" = "Waste Loop") }, diff --git a/_maps/map_files/Donutstation/Donutstation.dmm b/_maps/map_files/Donutstation/Donutstation.dmm index 62cb0418801..28f0e98755e 100644 --- a/_maps/map_files/Donutstation/Donutstation.dmm +++ b/_maps/map_files/Donutstation/Donutstation.dmm @@ -13663,7 +13663,7 @@ "aFi" = ( /obj/machinery/door/window/eastleft{ name = "Armory"; - req_access_txt = "2" + req_access_txt = "3" }, /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -22989,7 +22989,7 @@ }, /obj/machinery/door/window/eastright{ name = "Armory"; - req_access_txt = "2" + req_access_txt = "3" }, /obj/effect/turf_decal/stripes/line{ dir = 8 diff --git a/_maps/map_files/Donutstation/Donutstation_LVL2.dmm b/_maps/map_files/Donutstation/Donutstation_LVL2.dmm index 7df9733021f..c42949bfd3a 100644 --- a/_maps/map_files/Donutstation/Donutstation_LVL2.dmm +++ b/_maps/map_files/Donutstation/Donutstation_LVL2.dmm @@ -1994,7 +1994,7 @@ /obj/machinery/door/firedoor, /obj/machinery/door/window/eastleft{ name = "Armory"; - req_access_txt = "2" + req_access_txt = "3" }, /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory/upper) @@ -2755,7 +2755,7 @@ dir = 8 }, /obj/structure/lattice/catwalk, -/turf/open/space/basic, +/turf/open/openspace, /area/maintenance/central) "gp" = ( /obj/effect/turf_decal/trimline/white/filled/corner{ @@ -5734,7 +5734,7 @@ dir = 8 }, /obj/structure/lattice/catwalk, -/turf/open/space/basic, +/turf/open/openspace, /area/maintenance/central) "mn" = ( /obj/structure/chair/stool, @@ -5890,7 +5890,7 @@ dir = 8 }, /obj/structure/lattice/catwalk, -/turf/open/space/basic, +/turf/open/openspace, /area/maintenance/central) "mH" = ( /obj/effect/turf_decal/tile/neutral{ @@ -6117,7 +6117,7 @@ dir = 8 }, /obj/structure/lattice/catwalk, -/turf/open/space/basic, +/turf/open/openspace, /area/maintenance/central) "nf" = ( /obj/effect/turf_decal/tile/red{ @@ -16798,7 +16798,7 @@ /obj/structure/railing/corner, /obj/machinery/door/window/eastright{ name = "Armory"; - req_access_txt = "2" + req_access_txt = "3" }, /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory/upper) diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 27a98bf59d7..bedaeea6087 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -11012,11 +11012,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/machinery/button/flasher{ - id = "holdingflash"; - pixel_y = -26; - req_access_txt = "1" - }, /turf/open/floor/plasteel, /area/security/brig) "axp" = ( diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 46c75d05b93..b4f95f407b8 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -248,6 +248,7 @@ #define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled) #define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value) #define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" //from base of code/game/machinery +#define COMSIG_OBJ_HIDE "obj_hide" //from base of /turf/proc/levelupdate(). (intact) true to hide and false to unhide // /obj/machinery signals #define COMSIG_MACHINERY_BROKEN "machinery_broken" //from /obj/machinery/obj_break(damage_flag): (damage_flag) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 2dc7aa59607..2b1252eb504 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -113,6 +113,10 @@ #define FACING_EACHOTHER 2 #define FACING_INIT_FACING_TARGET_TARGET_FACING_PERPENDICULAR 3 //Do I win the most informative but also most stupid define award? +//stages of shoe tying-ness +#define SHOES_UNTIED 0 +#define SHOES_TIED 1 +#define SHOES_KNOTTED 2 //Cache of bloody footprint images //Key: @@ -482,3 +486,6 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE))) #define ALIGNMENT_GOOD "good" #define ALIGNMENT_NEUT "neutral" #define ALIGNMENT_EVIL "evil" + +// The alpha we give to stuff under tiles, if they want it +#define ALPHA_UNDERTILE 128 diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm index ae2a753f1c6..6b8ef7bd567 100644 --- a/code/__DEFINES/movespeed_modification.dm +++ b/code/__DEFINES/movespeed_modification.dm @@ -1,12 +1,3 @@ -#define MOVESPEED_DATA_INDEX_PRIORITY 1 -#define MOVESPEED_DATA_INDEX_FLAGS 2 -#define MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN 3 -#define MOVESPEED_DATA_INDEX_MOVETYPE 4 -#define MOVESPEED_DATA_INDEX_BL_MOVETYPE 5 -#define MOVESPEED_DATA_INDEX_CONFLICT 6 - -#define MOVESPEED_DATA_INDEX_MAX 6 - //flags #define IGNORE_NOSLOW (1 << 0) @@ -15,67 +6,7 @@ #define MOVE_CONFLICT_JETPACK "JETPACK" //ids +#define MOVESPEED_ID_SANITY "sanity_component" -#define MOVESPEED_ID_MOB_WALK_RUN_CONFIG_SPEED "MOB_WALK_RUN" -#define MOVESPEED_ID_MOB_GRAB_STATE "MOB_GRAB_STATE" -#define MOVESPEED_ID_MOB_EQUIPMENT "MOB_EQUIPMENT" -#define MOVESPEED_ID_MOB_GRAVITY "MOB_GRAVITY" -#define MOVESPEED_ID_CONFIG_SPEEDMOD "MOB_CONFIG_MODIFIER" - -#define MOVESPEED_ID_SLIME_REAGENTMOD "SLIME_REAGENT_MODIFIER" -#define MOVESPEED_ID_SLIME_HEALTHMOD "SLIME_HEALTH_MODIFIER" -#define MOVESPEED_ID_SLIME_TEMPMOD "SLIME_TEMPERATURE_MODIFIER" - -#define MOVESPEED_ID_SLIME_STATUS "SLIME_STATUS" - -#define MOVESPEED_ID_TARANTULA_WEB "TARANTULA_WEB" - -#define MOVESPEED_ID_LIVING_TURF_SPEEDMOD "LIVING_TURF_SPEEDMOD" -#define MOVESPEED_ID_LIVING_LIMBLESS "LIVING_LIMBLESS" - -#define MOVESPEED_ID_CARBON_SOFTCRIT "CARBON_SOFTCRIT" -#define MOVESPEED_ID_CARBON_OLDSPEED "CARBON_DEPRECATED_SPEED" -#define MOVESPEED_ID_CARBON_CRAWLING "CARBON_CRAWLING" - -#define MOVESPEED_ID_DNA_VAULT "DNA_VAULT" - -#define MOVESPEED_ID_YELLOW_ORB "YELLOW_ORB" - -#define MOVESPEED_ID_TARFOOT "TARFOOT" - -#define MOVESPEED_ID_SEPIA "SEPIA" - -#define MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD "MONKEY_REAGENT_SPEEDMOD" -#define MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD "MONKEY_TEMPERATURE_SPEEDMOD" -#define MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD "MONKEY_HEALTH_SPEEDMOD" - -#define MOVESPEED_ID_CHANGELING_MUSCLES "CHANGELING_MUSCLES" - -#define MOVESPEED_ID_SIMPLEMOB_VARSPEED "SIMPLEMOB_VARSPEED_MODIFIER" -#define MOVESPEED_ID_ADMIN_VAREDIT "ADMIN_VAREDIT_MODIFIER" - -#define MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD "PAI_SPACEWALK_MODIFIER" - -#define MOVESPEED_ID_SANITY "MOOD_SANITY" - -#define MOVESPEED_ID_SPECIES "SPECIES_SPEED_MOD" -#define MOVESPEED_ID_SNAIL_CRAWL "SNAIL_CRAWL_SPEED_MOD" - -#define MOVESPEED_ID_CYBER_THRUSTER "CYBER_IMPLANT_THRUSTER" -#define MOVESPEED_ID_JETPACK "JETPACK" - -#define MOVESPEED_ID_SLAUGHTER "SLAUGHTER" -#define MOVESPEED_ID_DIE_OF_FATE "DIE_OF_FATE" - -#define MOVESPEED_ID_SHOVE "SHOVE" -#define MOVESPEED_ID_BULKY_DRAGGING "BULKY_DRAG" -#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY" -#define MOVESPEED_ID_SHRINK_RAY "SHRUNKEN_SPEED_MODIFIER" -#define MOVESPEED_ID_PEPPER_SPRAY "PEPPER_SPRAYED" -#define MOVESPEED_ID_FAT "FAT" -#define MOVESPEED_ID_COLD "COLD" -#define MOVESPEED_ID_HUNGRY "HUNGRY" -#define MOVESPEED_ID_DAMAGE_SLOWDOWN "DAMAGE" -#define MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING "FLYING" -#define MOVESPEED_ID_LENTURI "LENTURI_SLOWDOWN" - +#define MOVESPEED_ID_MOB_GRAB_STATE "mob_grab_state" +#define MOVESPEED_ID_MOB_WALK_RUN "mob_walk_run" diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 72435141903..2ecafc1b41a 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -4,7 +4,6 @@ #define SOUND_MIDI (1<<1) #define SOUND_AMBIENCE (1<<2) #define SOUND_LOBBY (1<<3) -#define SOUND_ENDOFROUND (1<<20) #define MEMBER_PUBLIC (1<<4) #define INTENT_STYLE (1<<5) #define MIDROUND_ANTAG (1<<6) @@ -16,12 +15,12 @@ #define DISABLE_DEATHRATTLE (1<<12) #define DISABLE_ARRIVALRATTLE (1<<13) #define COMBOHUD_LIGHTING (1<<14) - #define DEADMIN_ALWAYS (1<<15) #define DEADMIN_ANTAGONIST (1<<16) #define DEADMIN_POSITION_HEAD (1<<17) #define DEADMIN_POSITION_SECURITY (1<<18) #define DEADMIN_POSITION_SILICON (1<<19) +#define SOUND_ENDOFROUND (1<<20) #define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|SOUND_ENDOFROUND|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS) diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index ea11de883de..ee34f958d27 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -36,6 +36,7 @@ #define ROLE_DEATHSQUAD "Deathsquad" #define ROLE_LAVALAND "Lavaland" #define ROLE_INTERNAL_AFFAIRS "Internal Affairs Agent" +#define ROLE_FAMILIES "Familes Antagonists" //Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. //The gamemode specific ones are just so the gamemodes can query whether a player is old enough @@ -59,7 +60,8 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_ABDUCTOR, ROLE_DEVIL = /datum/game_mode/devil, ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs, - ROLE_SENTIENCE + ROLE_SENTIENCE, + ROLE_FAMILIES = /datum/game_mode/gang )) //Job defines for what happens when you fail to qualify for any job during job selection diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 3f5dcb4db80..daa1fb27f78 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -159,6 +159,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_OIL_FRIED "oil_fried" #define TRAIT_MEDICAL_HUD "med_hud" #define TRAIT_SECURITY_HUD "sec_hud" +#define TRAIT_DIAGNOSTIC_HUD "diag_hud" //for something granting you a diagnostic hud #define TRAIT_MEDIBOTCOMINGTHROUGH "medbot" //Is a medbot healing you #define TRAIT_PASSTABLE "passtable" #define TRAIT_NOFLASH "noflash" //Makes you immune to flashes @@ -167,9 +168,11 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_PRIMITIVE "primitive" #define TRAIT_GUNFLIP "gunflip" #define TRAIT_BLOODCRAWL_EAT "bloodcrawl_eat" -#define TRAIT_GAMERGOD "gamer-god" //double arcade prizes +#define TRAIT_SPACEWALK "spacewalk" +#define TRAIT_GAMERGOD "gamer-god" //double arcade prizes #define TRAIT_GIANT "giant" #define TRAIT_DWARF "dwarf" +#define TRAIT_SILENT_FOOTSTEPS "silent_footsteps" //makes your footsteps completely silent //non-mob traits #define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it @@ -231,6 +234,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define STATUS_EFFECT_TRAIT "status-effect" #define CLOTHING_TRAIT "clothing" #define HELMET_TRAIT "helmet" +#define MASK_TRAIT "mask" //inherited from the mask +#define SHOES_TRAIT "shoes" //inherited from your sweet kicks #define GLASSES_TRAIT "glasses" #define VEHICLE_TRAIT "vehicle" // inherited from riding vehicles #define INNATE_TRAIT "innate" diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index 7c5715e1bb7..527ab1abad9 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -4,7 +4,7 @@ GLOBAL_DATUM(revdata, /datum/getrev) GLOBAL_VAR(host) GLOBAL_VAR(station_name) -GLOBAL_VAR_INIT(game_version, "/tg/ Station 13") +GLOBAL_VAR_INIT(game_version, "/tg/Station 13") GLOBAL_VAR_INIT(changelog_hash, "") GLOBAL_VAR_INIT(hub_visibility, FALSE) diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 3e624226aa3..587ecaf5608 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -94,6 +94,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_OIL_FRIED" = TRAIT_OIL_FRIED, "TRAIT_MEDICAL_HUD" = TRAIT_MEDICAL_HUD, "TRAIT_SECURITY_HUD" = TRAIT_SECURITY_HUD, + "TRAIT_DIAGNOSTIC_HUD" = TRAIT_DIAGNOSTIC_HUD, "TRAIT_PASSTABLE" = TRAIT_PASSTABLE, "TRAIT_NOFLASH" = TRAIT_NOFLASH, "TRAIT_XENO_IMMUNE" = TRAIT_XENO_IMMUNE, @@ -101,8 +102,11 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_PRIMITIVE" = TRAIT_PRIMITIVE, //unable to use mechs. Given to Ash Walkers "TRAIT_GUNFLIP" = TRAIT_GUNFLIP, "TRAIT_BLOODCRAWL_EAT" = TRAIT_BLOODCRAWL_EAT, + "TRAIT_SPACEWALK" = TRAIT_SPACEWALK, + "TRAIT_GAMERGOD" = TRAIT_GAMERGOD, "TRAIT_DWARF" = TRAIT_DWARF, - "TRAIT_GIANT" = TRAIT_GIANT + "TRAIT_GIANT" = TRAIT_GIANT, + "TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS ), /obj/item/bodypart = list( "TRAIT_PARALYSIS" = TRAIT_PARALYSIS diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 61bc30a8352..c77880555e5 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -584,6 +584,23 @@ so as to remain in compliance with the most up-to-date laws." if(L.last_special <= world.time) return L.resist_buckle() +/obj/screen/alert/shoes/untied + name = "Untied Shoes" + desc = "Your shoes are untied! Click the alert or your shoes to tie them." + icon_state = "shoealert" + +/obj/screen/alert/shoes/knotted + name = "Knotted Shoes" + desc = "Someone tied your shoelaces together! Click the alert or your shoes to undo the knot." + icon_state = "shoealert" + +/obj/screen/alert/shoes/Click() + var/mob/living/carbon/C = usr + if(!istype(C) || !C.can_resist() || C != owner || !C.shoes) + return + C.changeNext_move(CLICK_CD_RESIST) + C.shoes.handle_tying(C) + // PRIVATE = only edit, use, or override these if you're editing the system as a whole // Re-render all alerts - also called in /datum/hud/show_hud() because it's needed there diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 41eaba33c61..1ec0829c701 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -243,9 +243,19 @@ /datum/config_entry/number/movedelay/run_delay integer = FALSE +/datum/config_entry/number/movedelay/run_delay/ValidateAndSet() + . = ..() + var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/run) + M.sync() + /datum/config_entry/number/movedelay/walk_delay integer = FALSE +/datum/config_entry/number/movedelay/walk_delay/ValidateAndSet() + . = ..() + var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/walk) + M.sync() + /////////////////////////////////////////////////Outdated move delay /datum/config_entry/number/outdated_movedelay deprecated_by = /datum/config_entry/keyed_list/multiplicative_movespeed diff --git a/code/controllers/subsystem/minor_mapping.dm b/code/controllers/subsystem/minor_mapping.dm index 8f471e40dce..08cd08780b8 100644 --- a/code/controllers/subsystem/minor_mapping.dm +++ b/code/controllers/subsystem/minor_mapping.dm @@ -29,10 +29,10 @@ SUBSYSTEM_DEF(minor_mapping) while(turfs.len && amount > 0) var/turf/T = pick_n_take(turfs) - var/obj/item/storage/backpack/satchel/flat/S = new(T) - S.hide(intact=TRUE) - amount-- + var/obj/item/storage/backpack/satchel/flat/F = new(T) + SEND_SIGNAL(F, COMSIG_OBJ_HIDE, T.intact) + amount-- /proc/find_exposed_wires() var/list/exposed_wires = list() diff --git a/code/datums/components/footstep.dm b/code/datums/components/footstep.dm index 75720c89771..1ab97cea544 100644 --- a/code/datums/components/footstep.dm +++ b/code/datums/components/footstep.dm @@ -87,6 +87,8 @@ playsound(T, pick(footstep_sounds[turf_footstep][1]), footstep_sounds[turf_footstep][2] * volume, TRUE, footstep_sounds[turf_footstep][3] + e_range) /datum/component/footstep/proc/play_humanstep() + if(HAS_TRAIT(parent, TRAIT_SILENT_FOOTSTEPS)) + return var/turf/open/T = prepare_step() if(!T) return diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index afdc2821a95..c3e46d289e2 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -205,27 +205,27 @@ switch(sanity) if(SANITY_INSANE to SANITY_CRAZY) setInsanityEffect(MAJOR_INSANITY_PEN) - master.add_movespeed_modifier(MOVESPEED_ID_SANITY, TRUE, 100, override=TRUE, multiplicative_slowdown=1, movetypes=(~FLYING)) + master.add_movespeed_modifier(/datum/movespeed_modifier/sanity/insane) sanity_level = 6 if(SANITY_CRAZY to SANITY_UNSTABLE) setInsanityEffect(MINOR_INSANITY_PEN) - master.add_movespeed_modifier(MOVESPEED_ID_SANITY, TRUE, 100, override=TRUE, multiplicative_slowdown=0.5, movetypes=(~FLYING)) + master.add_movespeed_modifier(/datum/movespeed_modifier/sanity/crazy) sanity_level = 5 if(SANITY_UNSTABLE to SANITY_DISTURBED) setInsanityEffect(0) - master.add_movespeed_modifier(MOVESPEED_ID_SANITY, TRUE, 100, override=TRUE, multiplicative_slowdown=0.25, movetypes=(~FLYING)) + master.add_movespeed_modifier(/datum/movespeed_modifier/sanity/disturbed) sanity_level = 4 if(SANITY_DISTURBED to SANITY_NEUTRAL) setInsanityEffect(0) - master.remove_movespeed_modifier(MOVESPEED_ID_SANITY, TRUE) + master.remove_movespeed_modifier(MOVESPEED_ID_SANITY) sanity_level = 3 if(SANITY_NEUTRAL+1 to SANITY_GREAT+1) //shitty hack but +1 to prevent it from responding to super small differences setInsanityEffect(0) - master.remove_movespeed_modifier(MOVESPEED_ID_SANITY, TRUE) + master.remove_movespeed_modifier(MOVESPEED_ID_SANITY) sanity_level = 2 if(SANITY_GREAT+1 to INFINITY) setInsanityEffect(0) - master.remove_movespeed_modifier(MOVESPEED_ID_SANITY, TRUE) + master.remove_movespeed_modifier(MOVESPEED_ID_SANITY) sanity_level = 1 update_mood_icon() diff --git a/code/datums/components/plumbing/_plumbing.dm b/code/datums/components/plumbing/_plumbing.dm index 2bc2fc3c86b..31e1931b23b 100644 --- a/code/datums/components/plumbing/_plumbing.dm +++ b/code/datums/components/plumbing/_plumbing.dm @@ -3,10 +3,10 @@ var/list/datum/ductnet/ducts = list() ///shortcut to our parents' reagent holder var/datum/reagents/reagents - ///TRUE if we wanna add proper pipe outless under our parent object. this is pretty good if i may so so myself + ///TRUE if we wanna add proper pipe overlays under our parent object. this is pretty good if i may so so myself var/use_overlays = TRUE - ///We can't just cut all of the parents' overlays, so we'll track them here - var/list/image/ducterlays + ///Whether our tile is covered and we should hide our ducts + var/tile_covered = FALSE ///directions in wich we act as a supplier var/supply_connects ///direction in wich we act as a demander @@ -17,8 +17,9 @@ var/turn_connects = TRUE /datum/component/plumbing/Initialize(start=TRUE, _turn_connects=TRUE) //turn_connects for wheter or not we spin with the object to change our pipes - if(parent && !ismovable(parent)) + if(!ismovable(parent)) return COMPONENT_INCOMPATIBLE + var/atom/movable/AM = parent if(!AM.reagents) return COMPONENT_INCOMPATIBLE @@ -27,9 +28,13 @@ RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED,COMSIG_PARENT_PREQDELETED), .proc/disable) RegisterSignal(parent, list(COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH), .proc/toggle_active) + RegisterSignal(parent, list(COMSIG_OBJ_HIDE), .proc/hide) + RegisterSignal(parent, list(COMSIG_ATOM_UPDATE_OVERLAYS), .proc/create_overlays) if(start) - enable() + //timer 0 so it can finish returning initialize, after which we're added to the parent. + //Only then can we tell the duct next to us they can connect, because only then is the component really added. this was a fun one + addtimer(CALLBACK(src, .proc/enable), 0) if(use_overlays) create_overlays() @@ -42,6 +47,7 @@ for(var/D in GLOB.cardinals) if(D & demand_connects) send_request(D) + ///Can we be added to the ductnet? /datum/component/plumbing/proc/can_add(datum/ductnet/D, dir) if(!active) @@ -52,9 +58,11 @@ return FALSE return TRUE + ///called from in process(). only calls process_request(), but can be overwritten for children with special behaviour /datum/component/plumbing/proc/send_request(dir) process_request(amount = MACHINE_REAGENT_TRANSFER, reagent = null, dir = dir) + ///check who can give us what we want, and how many each of them will give us /datum/component/plumbing/proc/process_request(amount, reagent, dir) var/list/valid_suppliers = list() @@ -69,6 +77,7 @@ for(var/A in valid_suppliers) var/datum/component/plumbing/give = A give.transfer_to(src, amount / valid_suppliers.len, reagent, net) + ///returns TRUE when they can give the specified amount and reagent. called by process request /datum/component/plumbing/proc/can_give(amount, reagent, datum/ductnet/net) if(amount <= 0) @@ -81,6 +90,7 @@ return TRUE else if(reagents.total_volume > 0) //take whatever return TRUE + ///this is where the reagent is actually transferred and is thus the finish point of our process() /datum/component/plumbing/proc/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net) if(!reagents || !target || !target.reagents) @@ -89,13 +99,12 @@ reagents.trans_id_to(target.parent, reagent, amount) else reagents.trans_to(target.parent, amount, round_robin = TRUE)//we deal with alot of precise calculations so we round_robin=TRUE. Otherwise we get floating point errors, 1 != 1 and 2.5 + 2.5 = 6 + ///We create our luxurious piping overlays/underlays, to indicate where we do what. only called once if use_overlays = TRUE in Initialize() -/datum/component/plumbing/proc/create_overlays() - var/atom/movable/AM = parent - for(var/image/I in ducterlays) - AM.overlays.Remove(I) - qdel(I) - ducterlays = list() +/datum/component/plumbing/proc/create_overlays(atom/A, list/overlays) + if(tile_covered || !use_overlays) + return + for(var/D in GLOB.cardinals) var/color var/direction @@ -105,6 +114,7 @@ color = "blue" //blue is nice and gives else continue + var/image/I if(turn_connects) switch(D) @@ -116,21 +126,25 @@ direction = "east" if(WEST) direction = "west" - I = image('icons/obj/plumbing/plumbers.dmi', "[direction]-[color]", layer = AM.layer - 1) + I = image('icons/obj/plumbing/plumbers.dmi', "[direction]-[color]", layer = A.layer - 1) else - I = image('icons/obj/plumbing/plumbers.dmi', color, layer = AM.layer - 1) //color is not color as in the var, it's just the name + I = image('icons/obj/plumbing/plumbers.dmi', color, layer = A.layer - 1) //color is not color as in the var, it's just the name I.dir = D - AM.add_overlay(I) - ducterlays += I + overlays += I + ///we stop acting like a plumbing thing and disconnect if we are, so we can safely be moved and stuff /datum/component/plumbing/proc/disable() if(!active) return + STOP_PROCESSING(SSfluids, src) + for(var/A in ducts) var/datum/ductnet/D = ducts[A] D.remove_plumber(src) + active = FALSE + for(var/D in GLOB.cardinals) if(D & (demand_connects | supply_connects)) for(var/obj/machinery/duct/duct in get_step(parent, D)) @@ -141,8 +155,10 @@ /datum/component/plumbing/proc/enable() if(active) return + update_dir() active = TRUE + var/atom/movable/AM = parent for(var/obj/machinery/duct/D in AM.loc) //Destroy any ducts under us. Ducts also self destruct if placed under a plumbing machine. machines disable when they get moved if(D.anchored) //that should cover everything @@ -152,8 +168,10 @@ START_PROCESSING(SSfluids, src) for(var/D in GLOB.cardinals) + if(D & (demand_connects | supply_connects)) for(var/atom/movable/A in get_step(parent, D)) + if(istype(A, /obj/machinery/duct)) var/obj/machinery/duct/duct = A duct.attempt_connect() @@ -168,17 +186,20 @@ enable() else disable() + /** We update our connects only when we settle down by taking our current and original direction to find our new connects * If someone wants it to fucking spin while connected to something go actually knock yourself out */ /datum/component/plumbing/proc/update_dir() if(!turn_connects) return + var/atom/movable/AM = parent var/new_demand_connects var/new_supply_connects var/new_dir = AM.dir var/angle = 180 - dir2angle(new_dir) + if(new_dir == SOUTH) demand_connects = initial(demand_connects) supply_connects = initial(supply_connects) @@ -190,10 +211,12 @@ new_supply_connects += turn(D, angle) demand_connects = new_demand_connects supply_connects = new_supply_connects + ///Give the direction of a pipe, and it'll return wich direction it originally was when it's object pointed SOUTH /datum/component/plumbing/proc/get_original_direction(dir) var/atom/movable/AM = parent return turn(dir, dir2angle(AM.dir) - 180) + //special case in-case we want to connect directly with another machine without a duct /datum/component/plumbing/proc/direct_connect(datum/component/plumbing/P, dir) if(!P.active) @@ -204,12 +227,18 @@ net.add_plumber(src, dir) net.add_plumber(P, opposite_dir) +/datum/component/plumbing/proc/hide(atom/movable/AM, intact) + tile_covered = intact + AM.update_icon() + ///has one pipe input that only takes, example is manual output pipe /datum/component/plumbing/simple_demand demand_connects = NORTH + ///has one pipe output that only supplies. example is liquid pump and manual input pipe /datum/component/plumbing/simple_supply supply_connects = NORTH + ///input and output, like a holding tank /datum/component/plumbing/tank demand_connects = WEST diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index 2bd1f1b938f..87af417a28c 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -224,13 +224,13 @@ /datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE) var/mob/living/carbon/human/H = parent - H.remove_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING) + H.remove_movespeed_modifier(/datum/movespeed_modifier/human_carry) . = ..() /datum/component/riding/human/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE) . = ..() var/mob/living/carbon/human/H = parent - H.add_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING, multiplicative_slowdown = HUMAN_CARRY_SLOWDOWN) + H.add_movespeed_modifier(/datum/movespeed_modifier/human_carry) /datum/component/riding/human/proc/on_host_unarmed_melee(atom/target) var/mob/living/carbon/human/H = parent diff --git a/code/datums/components/shrink.dm b/code/datums/components/shrink.dm index 48ab864c79d..3dfd131923a 100644 --- a/code/datums/components/shrink.dm +++ b/code/datums/components/shrink.dm @@ -14,7 +14,7 @@ parent_atom.opacity = 0 if(isliving(parent_atom)) var/mob/living/L = parent_atom - L.add_movespeed_modifier(MOVESPEED_ID_SHRINK_RAY, update=TRUE, priority=100, multiplicative_slowdown=4, movetypes=GROUND) + L.add_movespeed_modifier(/datum/movespeed_modifier/shrink_ray) if(iscarbon(L)) var/mob/living/carbon/C = L C.unequip_everything() @@ -27,7 +27,6 @@ "Everything grows bigger!") QDEL_IN(src, shrink_time) - /datum/component/shrink/Destroy() var/atom/parent_atom = parent parent_atom.transform = parent_atom.transform.Scale(2,2) @@ -35,7 +34,7 @@ parent_atom.opacity = oldopac if(isliving(parent_atom)) var/mob/living/L = parent_atom - L.remove_movespeed_modifier(MOVESPEED_ID_SHRINK_RAY) + L.remove_movespeed_modifier(/datum/movespeed_modifier/shrink_ray) if(ishuman(L)) var/mob/living/carbon/human/H = L H.physiology.damage_resistance += 100 diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index 2719cf65a0a..9980a2fc96f 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -86,7 +86,7 @@ to_chat(user, "You're not ready to tackle!") return - if(user.has_movespeed_modifier(MOVESPEED_ID_SHOVE)) // can't tackle if you just got shoved + if(user.has_movespeed_modifier(/datum/movespeed_modifier/shove)) // can't tackle if you just got shoved to_chat(user, "You're too off balance to tackle!") return @@ -167,8 +167,8 @@ to_chat(target, "[user] lands a weak tackle on you, briefly knocking you off-balance!") user.Knockdown(30) - if(ishuman(target) && !T.has_movespeed_modifier(MOVESPEED_ID_SHOVE)) - T.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH) // maybe define a slightly more severe/longer slowdown for this + if(ishuman(target) && !T.has_movespeed_modifier(/datum/movespeed_modifier/shove)) + T.add_movespeed_modifier(/datum/movespeed_modifier/shove) // maybe define a slightly more severe/longer slowdown for this addtimer(CALLBACK(T, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH) if(-1 to 0) // decent hit, both parties are about equally inconvenienced diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 23b19d08141..f9c5f7ab823 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -75,38 +75,56 @@ D.adjust_money(amount) return -/datum/datacore/proc/addMinorCrime(id = "", datum/data/crime/crime) +/** + * Adds crime to security record. + * + * Is used to add single crime to someone's security record. + * Arguments: + * * id - record id. + * * datum/data/crime/crime - premade array containing every variable, usually created by createCrimeEntry. + */ +/datum/datacore/proc/addCrime(id = "", datum/data/crime/crime) for(var/datum/data/record/R in security) if(R.fields["id"] == id) - var/list/crimes = R.fields["mi_crim"] + var/list/crimes = R.fields["crim"] crimes |= crime return -/datum/datacore/proc/removeMinorCrime(id, cDataId) +/** + * Deletes crime from security record. + * + * Is used to delete single crime to someone's security record. + * Arguments: + * * id - record id. + * * cDataId - id of already existing crime. + */ +/datum/datacore/proc/removeCrime(id, cDataId) for(var/datum/data/record/R in security) if(R.fields["id"] == id) - var/list/crimes = R.fields["mi_crim"] + var/list/crimes = R.fields["crim"] for(var/datum/data/crime/crime in crimes) if(crime.dataId == text2num(cDataId)) crimes -= crime return -/datum/datacore/proc/removeMajorCrime(id, cDataId) +/** + * Adds details to a crime. + * + * Is used to add or replace details to already existing crime. + * Arguments: + * * id - record id. + * * cDataId - id of already existing crime. + * * details - data you want to add. + */ +/datum/datacore/proc/addCrimeDetails(id, cDataId, details) for(var/datum/data/record/R in security) if(R.fields["id"] == id) - var/list/crimes = R.fields["ma_crim"] + var/list/crimes = R.fields["crim"] for(var/datum/data/crime/crime in crimes) if(crime.dataId == text2num(cDataId)) - crimes -= crime + crime.crimeDetails = details return -/datum/datacore/proc/addMajorCrime(id = "", datum/data/crime/crime) - for(var/datum/data/record/R in security) - if(R.fields["id"] == id) - var/list/crimes = R.fields["ma_crim"] - crimes |= crime - return - /datum/datacore/proc/manifest() for(var/i in GLOB.new_player_list) var/mob/dead/new_player/N = i @@ -259,8 +277,7 @@ S.fields["name"] = H.real_name S.fields["criminal"] = "None" S.fields["citation"] = list() - S.fields["mi_crim"] = list() - S.fields["ma_crim"] = list() + S.fields["crim"] = list() S.fields["notes"] = "No notes." security += S diff --git a/code/datums/elements/snail_crawl.dm b/code/datums/elements/snail_crawl.dm index 9352ab7beda..0e322c7c9d2 100644 --- a/code/datums/elements/snail_crawl.dm +++ b/code/datums/elements/snail_crawl.dm @@ -16,13 +16,13 @@ . = ..() UnregisterSignal(target, COMSIG_MOVABLE_MOVED) if(istype(target)) - target.remove_movespeed_modifier(MOVESPEED_ID_SNAIL_CRAWL) + target.remove_movespeed_modifier(/datum/movespeed_modifier/snail_crawl) /datum/element/snailcrawl/proc/snail_crawl(mob/living/carbon/snail) if(snail.resting && !snail.buckled && lubricate(snail)) - snail.add_movespeed_modifier(MOVESPEED_ID_SNAIL_CRAWL, update=TRUE, priority=100, multiplicative_slowdown=-7, movetypes=GROUND) + snail.add_movespeed_modifier(/datum/movespeed_modifier/snail_crawl) else - snail.remove_movespeed_modifier(MOVESPEED_ID_SNAIL_CRAWL) + snail.remove_movespeed_modifier(/datum/movespeed_modifier/snail_crawl) /datum/element/snailcrawl/proc/lubricate(atom/movable/snail) var/turf/open/OT = get_turf(snail) diff --git a/code/datums/elements/undertile.dm b/code/datums/elements/undertile.dm new file mode 100644 index 00000000000..7bdbae2aa14 --- /dev/null +++ b/code/datums/elements/undertile.dm @@ -0,0 +1,59 @@ +///Add to an object if you want to be able to be hidden under tiles +/datum/element/undertile + element_flags = ELEMENT_BESPOKE | COMPONENT_DUPE_HIGHLANDER + id_arg_index = 2 + + ///the invisiblity trait applied, like TRAIT_T_RAY_VISIBLE + var/invisibility_trait + ///level of invisibility applied when under a tile. Could be INVISIBILITY_OBSERVER if you still want it to be visible to ghosts + var/invisibility_level + ///an overlay for the tile if we wish to apply that + var/tile_overlay + ///whether we use alpha or not. TRUE uses ALPHA_UNDERTILE because otherwise we have 200 different instances of this element for different alphas + var/use_alpha + ///We will switch between anchored and unanchored. for stuff like satchels that shouldnt be pullable under tiles but are otherwise unanchored + var/use_anchor + +/datum/element/undertile/Attach(datum/target, invisibility_trait, invisibility_level = INVISIBILITY_MAXIMUM, tile_overlay, use_alpha = TRUE, use_anchor = FALSE) + . = ..() + if(!ismovable(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_OBJ_HIDE, .proc/hide) + + src.invisibility_trait = invisibility_trait + src.invisibility_level = invisibility_level + src.tile_overlay = tile_overlay + src.use_alpha = use_alpha + src.use_anchor = use_anchor + +///called when a tile has been covered or uncovered +/datum/element/undertile/proc/hide(atom/movable/source, covered) + source.invisibility = covered ? invisibility_level : 0 + + var/turf/T = get_turf(source) + + if(covered) + if(invisibility_trait) + ADD_TRAIT(source, invisibility_trait, TRAIT_GENERIC) + if(tile_overlay) + T.add_overlay(tile_overlay) + if(use_alpha) + source.alpha = ALPHA_UNDERTILE + if(use_anchor) + source.anchored = TRUE + + else + if(invisibility_trait) + REMOVE_TRAIT(source, invisibility_trait, TRAIT_GENERIC) + if(tile_overlay) + T.overlays -= tile_overlay + if(use_alpha) + source.alpha = 255 + if(use_anchor) + source.anchored = FALSE + +/datum/element/undertile/Detach(atom/movable/AM, visibility_trait, invisibility_level = INVISIBILITY_MAXIMUM) + . = ..() + + hide(AM, FALSE) diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index e06f7a3da66..b7c988f18c3 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -196,6 +196,7 @@ Unless you know what you're doing, only use the first three numbers. They're in desc = "Flexible, durable, but flamable. Hard to come across in space." color = "#bb8e53" strength_modifier = 0.5 + sheet_type = /obj/item/stack/sheet/mineral/wood categories = list(MAT_CATEGORY_RIGID = TRUE) value_per_unit = 0.06 beauty_modifier = 0.1 diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 613df40a68b..e23a5169e9a 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -220,6 +220,16 @@ description = "This guy is insane! I better be careful....\n" mood_change = -10 +/datum/mood_event/tripped + description = "I can't believe I fell for the oldest trick in the book!\n" + mood_change = -10 + timeout = 2 MINUTES + +/datum/mood_event/untied + description = "I hate when my shoes come untied!\n" + mood_change = -5 + timeout = 1 MINUTES + //These are unused so far but I want to remember them to use them later /datum/mood_event/surgery description = "HE'S CUTTING ME OPEN!!\n" diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm index 128346d7c37..0540529518c 100644 --- a/code/datums/mood_events/generic_positive_events.dm +++ b/code/datums/mood_events/generic_positive_events.dm @@ -79,7 +79,7 @@ hidden = TRUE /datum/mood_event/badass_antag - description = "I'm a fucking badass and everyone around me knows it. Just look at them; they're all fucking shaking at the mere thought of me around.\n" + description = "I'm a fucking badass and everyone around me knows it. Just look at them; they're all fucking shaking at the mere thought of having me around.\n" mood_change = 7 hidden = TRUE special_screen_obj = "badass_sun" @@ -162,7 +162,7 @@ timeout = 5 MINUTES /datum/mood_event/pet_borg - description = "I just love my robotical friends!\n" + description = "I just love my robotic friends!\n" mood_change = 3 timeout = 5 MINUTES diff --git a/code/datums/saymode.dm b/code/datums/saymode.dm index 57ef7701e32..9f2c758710c 100644 --- a/code/datums/saymode.dm +++ b/code/datums/saymode.dm @@ -86,7 +86,7 @@ return FALSE -/datum/saymode/binary //everything that uses .b (silicons, drones, blobbernauts/spores, swarmers) +/datum/saymode/binary //everything that uses .b (silicons, drones, swarmers) key = MODE_KEY_BINARY mode = MODE_BINARY @@ -95,10 +95,6 @@ var/mob/living/simple_animal/hostile/swarmer/S = user S.swarmer_chat(message) return FALSE - if(isblobmonster(user)) - var/mob/living/simple_animal/hostile/blob/B = user - B.blob_chat(message) - return FALSE if(isdrone(user)) var/mob/living/simple_animal/drone/D = user D.drone_chat(message) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 139fe43fe9c..55dcfd04a25 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -4,7 +4,6 @@ * A grouping of tiles into a logical space, mostly used by map editors */ /area - level = null name = "Space" icon = 'icons/turf/areas.dmi' icon_state = "unknown" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 52b02101ee0..9005e43bd25 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -7,7 +7,6 @@ /atom layer = TURF_LAYER plane = GAME_PLANE - var/level = 2 ///If non-null, overrides a/an/some in all cases var/article diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index 8fab8717f08..33a1fc8dd86 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -91,6 +91,7 @@ requirements = list(101,101,70,40,30,20,20,20,20,20) high_population_requirement = 50 flags = HIGHLANDER_RULESET + blocking_rules = list(/datum/dynamic_ruleset/roundstart/revs) var/required_heads_of_staff = 3 var/finished = FALSE var/datum/team/revolution/revolution diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index a5ce063c117..ab7b54e05c5 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -352,6 +352,7 @@ high_population_requirement = 10 antag_cap = list(3,3,3,3,3,3,3,3,3,3) flags = HIGHLANDER_RULESET + blocking_rules = list(/datum/dynamic_ruleset/latejoin/provocateur) // I give up, just there should be enough heads with 35 players... minimum_players = 35 var/datum/team/revolution/revolution diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index f8c9b8178c9..97bb8d25ad3 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -18,11 +18,11 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) /datum/game_mode/gang name = "Families" config_tag = "families" - antag_flag = ROLE_TRAITOR + antag_flag = ROLE_FAMILIES false_report_weight = 5 required_players = 40 - required_enemies = 4 - recommended_enemies = 4 + required_enemies = 6 + recommended_enemies = 6 announce_span = "danger" announce_text = "Grove For Lyfe!" reroll_friendly = FALSE @@ -36,7 +36,7 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) var/list/gangs_to_use var/list/datum/mind/gangbangers = list() var/list/datum/mind/pigs = list() - var/datum/mind/undercover_cop + var/list/datum/mind/undercover_cops = list() var/list/gangs = list() var/gangs_still_alive = 0 var/sent_announcement = FALSE @@ -50,6 +50,7 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) name = "Warriors" config_tag = "warriors" announce_text = "Can you survive this onslaught?" + gangs_to_generate = 11 gang_balance_cap = 3 /datum/game_mode/gang/warriors/pre_setup() @@ -67,11 +68,11 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) gangbanger.restricted_roles = restricted_jobs log_game("[key_name(gangbanger)] has been selected as a starting gangster!") antag_candidates.Remove(gangbanger) - if(antag_candidates.len) + for(var/j = 0, j < gangs_to_generate, j++) var/datum/mind/one_eight_seven_on_an_undercover_cop = antag_pick(antag_candidates) pigs += one_eight_seven_on_an_undercover_cop - undercover_cop = one_eight_seven_on_an_undercover_cop - undercover_cop.restricted_roles = restricted_jobs + undercover_cops += one_eight_seven_on_an_undercover_cop + one_eight_seven_on_an_undercover_cop.restricted_roles = restricted_jobs log_game("[key_name(one_eight_seven_on_an_undercover_cop)] has been selected as a starting undercover cop!") antag_candidates.Remove(one_eight_seven_on_an_undercover_cop) endtime = world.time + time_to_end @@ -79,6 +80,7 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) /datum/game_mode/gang/post_setup() var/replacement_gangsters = 0 + var/replacement_cops = 0 for(var/datum/mind/gangbanger in gangbangers) if(!ishuman(gangbanger.current)) gangbangers.Remove(gangbanger) @@ -92,16 +94,22 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) var/datum/mind/gangbanger = antag_pick(antag_candidates) gangbangers += gangbanger log_game("[key_name(gangbanger)] has been selected as a replacement gangster!") - if(undercover_cop && !ishuman(undercover_cop.current)) - pigs.Remove(undercover_cop) - log_game("[undercover_cop] was not a human, and thus has lost their undercover cop role.") - if(!antag_candidates.len) - var/datum/mind/one_eight_seven_on_an_undercover_cop = antag_pick(antag_candidates) - pigs += one_eight_seven_on_an_undercover_cop - undercover_cop = one_eight_seven_on_an_undercover_cop - else - log_game("Unable to find a replacement undercover cop.") - if(undercover_cop) + for(var/datum/mind/undercover_cop in undercover_cops) + if(!ishuman(undercover_cop.current)) + undercover_cops.Remove(undercover_cop) + pigs.Remove(undercover_cop) + log_game("[undercover_cop] was not a human, and thus has lost their undercover cop role.") + replacement_cops++ + if(replacement_cops) + for(var/j = 0, j < replacement_cops, j++) + if(!antag_candidates.len) + log_game("Unable to find more replacement undercover cops. Not all of the gangs will spawn.") + break + var/datum/mind/undercover_cop = antag_pick(antag_candidates) + undercover_cops += undercover_cop + pigs += undercover_cop + log_game("[key_name(undercover_cop)] has been selected as a replacement undercover cop!") + for(var/datum/mind/undercover_cop in undercover_cops) var/datum/antagonist/ert/families/undercover_cop/one_eight_seven_on_an_undercover_cop = new() undercover_cop.add_antag_datum(one_eight_seven_on_an_undercover_cop) undercover_cop.current.playsound_local(undercover_cop.current, 'sound/effects/families_police.ogg', 100, FALSE, pressure_affected = FALSE) @@ -138,6 +146,7 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) to_chat(gangbanger.current, "As you're the first gangster, your uniform and spraycan are in your inventory!") addtimer(CALLBACK(src, .proc/announce_gang_locations), 5 MINUTES) addtimer(CALLBACK(src, .proc/five_minute_warning), time_to_end - 5 MINUTES) + SSshuttle.registerHostileEnvironment(src) gamemode_ready = TRUE ..() @@ -147,7 +156,7 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) var/datum/team/gang/G = GG readable_gang_names += "[G.name]" var/finalized_gang_names = english_list(readable_gang_names) - priority_announce("Julio G coming to you live from Radio Los Spess! We've been hearing reports of gang activity on [station_name()], with the [finalized_gang_names] duking it out, looking for fresh territory and drugs to sling! Stay safe out there for the hour 'till the space cops get there, and keep it cool, yeah? Play music, not gunshots, I say. Peace out!", "Radio Los Spess", 'sound/voice/beepsky/radio.ogg') + priority_announce("Julio G coming to you live from Radio Los Spess! We've been hearing reports of gang activity on [station_name()], with the [finalized_gang_names] duking it out, looking for fresh territory and drugs to sling! Stay safe out there for the hour 'till the space cops get there, and keep it cool, yeah?\n\n The local jump gates are shut down for about an hour due to some maintenance troubles, so if you wanna split from the area you're gonna have to wait an hour. \n Play music, not gunshots, I say. Peace out!", "Radio Los Spess", 'sound/voice/beepsky/radio.ogg') sent_announcement = TRUE /datum/game_mode/gang/proc/five_minute_warning() @@ -324,7 +333,6 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) log_game("[key_name(cop)] has been selected as an [ert_antag.name]") numagents-- cops_arrived = TRUE - SSshuttle.registerHostileEnvironment(src) addtimer(CALLBACK(src, .proc/end_hostile_sit), 10 MINUTES) return TRUE @@ -381,7 +389,7 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0) /datum/game_mode/gang/generate_report() - return "Something something grove street home at least until I fucked everything up idk nobody reads these reports." + return "Potential violent criminal activity has been detected on board your station, and we believe the Spinward Stellar Coalition may be conducting an audit of us. Keep an eye out for tagging of turf, color coordination, and suspicious people asking you to say things a little closer to their chest." /datum/game_mode/gang/send_intercept(report = 0) return diff --git a/code/game/gamemodes/gang/gang_things.dm b/code/game/gamemodes/gang/gang_things.dm index cc49431e95a..735196759e2 100644 --- a/code/game/gamemodes/gang/gang_things.dm +++ b/code/game/gamemodes/gang/gang_things.dm @@ -11,6 +11,12 @@ if(HAS_TRAIT(user, TRAIT_MINDSHIELD)) to_chat(user, "You attended a seminar on not signing up for a gang, and are not interested.") return + if(user.mind.has_antag_datum(/datum/antagonist/ert/families)) + to_chat(user, "As a police officer, you can't join this family. However, you pretend to accept it to keep your cover up.") + for(var/threads in team_to_use.free_clothes) + new threads(get_turf(user)) + qdel(src) + return var/datum/antagonist/gang/is_gangster = user.mind.has_antag_datum(/datum/antagonist/gang) if(is_gangster && is_gangster.starter_gangster) to_chat(user, "You started your family. You can't turn your back on it now.") diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm index 3d0931d534b..7593e392fc8 100644 --- a/code/game/machinery/Beacon.dm +++ b/code/game/machinery/Beacon.dm @@ -4,7 +4,6 @@ icon_state = "floor_beaconf" name = "bluespace gigabeacon" desc = "A device that draws power from bluespace and creates a permanent tracking beacon." - level = 1 // underfloor layer = LOW_OBJ_LAYER use_power = IDLE_POWER_USE idle_power_usage = 0 @@ -16,27 +15,12 @@ Beacon = new(T) Beacon.invisibility = INVISIBILITY_MAXIMUM - hide(T.intact) + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) /obj/machinery/bluespace_beacon/Destroy() QDEL_NULL(Beacon) return ..() -// update the invisibility and icon -/obj/machinery/bluespace_beacon/hide(intact) - invisibility = intact ? INVISIBILITY_MAXIMUM : 0 - updateicon() - -// update the icon_state -/obj/machinery/bluespace_beacon/proc/updateicon() - var/state="floor_beacon" - - if(invisibility) - icon_state = "[state]f" - - else - icon_state = "[state]" - /obj/machinery/bluespace_beacon/process() if(!Beacon) var/turf/T = loc @@ -44,5 +28,3 @@ Beacon.invisibility = INVISIBILITY_MAXIMUM else if (Beacon.loc != loc) Beacon.forceMove(loc) - - updateicon() diff --git a/code/game/machinery/bank_machine.dm b/code/game/machinery/bank_machine.dm index 81fa9ce15cc..c75ed084a09 100644 --- a/code/game/machinery/bank_machine.dm +++ b/code/game/machinery/bank_machine.dm @@ -3,8 +3,8 @@ desc = "A machine used to deposit and withdraw station funds." icon = 'goon/icons/obj/goon_terminals.dmi' idle_power_usage = 100 - ui_x = 320 - ui_y = 165 + ui_x = 335 + ui_y = 160 var/siphoning = FALSE var/next_warning = 0 var/obj/item/radio/radio diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 234e307ebe1..917d6f9f7af 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -82,29 +82,25 @@ if("killbot") if(allowed(usr)) var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs - if(can_control(usr, R)) - var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm" && can_control(usr, R) && !..()) - var/turf/T = get_turf(R) - message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!") - log_game("\[key_name(usr)] detonated [key_name(R)]!") - if(R.connected_ai) - to_chat(R.connected_ai, "

ALERT - Cyborg detonation detected: [R.name]
") - R.self_destruct() + if(can_control(usr, R) && !..()) + var/turf/T = get_turf(R) + message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!") + log_game("\[key_name(usr)] detonated [key_name(R)]!") + if(R.connected_ai) + to_chat(R.connected_ai, "

ALERT - Cyborg detonation detected: [R.name]
") + R.self_destruct() else to_chat(usr, "Access Denied.") if("stopbot") if(allowed(usr)) var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs - if(can_control(usr, R)) - var/choice = input("Are you certain you wish to [!R.lockcharge ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm" && can_control(usr, R) && !..()) - message_admins("[ADMIN_LOOKUPFLW(usr)] [!R.lockcharge ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!") - log_game("[key_name(usr)] [!R.lockcharge ? "locked down" : "released"] [key_name(R)]!") - R.SetLockdown(!R.lockcharge) - to_chat(R, "[!R.lockcharge ? "Your lockdown has been lifted!" : "You have been locked down!"]") - if(R.connected_ai) - to_chat(R.connected_ai, "[!R.lockcharge ? "NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [R.name]
") + if(can_control(usr, R) && !..()) + message_admins("[ADMIN_LOOKUPFLW(usr)] [!R.lockcharge ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!") + log_game("[key_name(usr)] [!R.lockcharge ? "locked down" : "released"] [key_name(R)]!") + R.SetLockdown(!R.lockcharge) + to_chat(R, "[!R.lockcharge ? "Your lockdown has been lifted!" : "You have been locked down!"]") + if(R.connected_ai) + to_chat(R.connected_ai, "[!R.lockcharge ? "NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [R.name]
") else to_chat(usr, "Access Denied.") if("magbot") diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 2873cd670dc..42a62cda359 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -215,7 +215,7 @@ "} dat += "" - dat += "

Minor Crimes: Add New" + dat += "

Crimes: Add New" dat +={" @@ -226,32 +226,15 @@ "} - for(var/datum/data/crime/c in active2.fields["mi_crim"]) + for(var/datum/data/crime/c in active2.fields["crim"]) dat += "" - dat += "" + if(!c.crimeDetails) + dat += "" + else + dat += "" dat += "" dat += "" - dat += "" - dat += "" - dat += "
Time Added Del
[c.crimeName][c.crimeDetails]\[+\][c.crimeDetails][c.author][c.time]\[X\]
" - - - dat += "
Major Crimes: Add New" - - dat +={" - - - - - - - "} - for(var/datum/data/crime/c in active2.fields["ma_crim"]) - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" + dat += "" dat += "" dat += "
CrimeDetailsAuthorTime AddedDel
[c.crimeName][c.crimeDetails][c.author][c.time]\[X\]\[X\]
" @@ -401,7 +384,7 @@ What a mess.*/ if((istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2))) P.info += text("
\n
Security Data

\nCriminal Status: []", active2.fields["criminal"]) - P.info += "
\n
\nMinor Crimes:
\n" + P.info += "
\n
\nCrimes:
\n" P.info +={" @@ -409,7 +392,7 @@ What a mess.*/ "} - for(var/datum/data/crime/c in active2.fields["mi_crim"]) + for(var/datum/data/crime/c in active2.fields["crim"]) P.info += "" P.info += "" P.info += "" @@ -417,23 +400,6 @@ What a mess.*/ P.info += "" P.info += "
CrimeAuthor Time Added
[c.crimeName][c.crimeDetails][c.author]
" - P.info += "
\nMajor Crimes:
\n" - P.info +={" - - - - - -"} - for(var/datum/data/crime/c in active2.fields["ma_crim"]) - P.info += "" - P.info += "" - P.info += "" - P.info += "" - P.info += "" - P.info += "
CrimeDetailsAuthorTime Added
[c.crimeName][c.crimeDetails][c.author][c.time]
" - - P.info += text("
\nImportant Notes:
\n\t[]
\n
\n
Comments/Log

", active2.fields["notes"]) var/counter = 1 while(active2.fields[text("com_[]", counter)]) @@ -451,18 +417,10 @@ What a mess.*/ var/wanted_name = stripped_input(usr, "Please enter an alias for the criminal:", "Print Wanted Poster", active1.fields["name"]) if(wanted_name) var/default_description = "A poster declaring [wanted_name] to be a dangerous individual, wanted by Nanotrasen. Report any sightings to security immediately." - var/list/major_crimes = active2.fields["ma_crim"] - var/list/minor_crimes = active2.fields["mi_crim"] - if(major_crimes.len + minor_crimes.len) + var/list/crimes = active2.fields["crim"] + if(crimes.len) default_description += "\n[wanted_name] is wanted for the following crimes:\n" - if(minor_crimes.len) - default_description += "\nMinor Crimes:" - for(var/datum/data/crime/c in active2.fields["mi_crim"]) - default_description += "\n[c.crimeName]\n" - default_description += "[c.crimeDetails]\n" - if(major_crimes.len) - default_description += "\nMajor Crimes:" - for(var/datum/data/crime/c in active2.fields["ma_crim"]) + for(var/datum/data/crime/c in active2.fields["crim"]) default_description += "\n[c.crimeName]\n" default_description += "[c.crimeDetails]\n" @@ -544,8 +502,7 @@ What a mess.*/ R.fields["id"] = active1.fields["id"] R.name = text("Security Record #[]", R.fields["id"]) R.fields["criminal"] = "None" - R.fields["mi_crim"] = list() - R.fields["ma_crim"] = list() + R.fields["crim"] = list() R.fields["notes"] = "No notes." GLOB.data_core.security += R active2 = R @@ -574,8 +531,7 @@ What a mess.*/ R.fields["id"] = active1.fields["id"] R.name = text("Security Record #[]", R.fields["id"]) R.fields["criminal"] = "None" - R.fields["mi_crim"] = list() - R.fields["ma_crim"] = list() + R.fields["crim"] = list() R.fields["notes"] = "No notes." GLOB.data_core.security += R active2 = R @@ -697,36 +653,29 @@ What a mess.*/ if(istype(active1.fields["photo_side"], /obj/item/photo)) var/obj/item/photo/P = active1.fields["photo_side"] print_photo(P.picture.picture_image, active1.fields["name"]) - if("mi_crim_add") + if("crim_add") if(istype(active1, /datum/data/record)) - var/t1 = stripped_input(usr, "Please input minor crime names:", "Secure. records", "", null) - var/t2 = stripped_input(usr, "Please input minor crime details:", "Secure. records", "", null) + var/t1 = stripped_input(usr, "Please input crime names:", "Secure. records", "", null) + var/t2 = stripped_input(usr, "Please input crime details:", "Secure. records", "", null) if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) return var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, station_time_timestamp()) - GLOB.data_core.addMinorCrime(active1.fields["id"], crime) - investigate_log("New Minor Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) - if("mi_crim_delete") + GLOB.data_core.addCrime(active1.fields["id"], crime) + investigate_log("New Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) + if("crim_delete") if(istype(active1, /datum/data/record)) if(href_list["cdataid"]) if(!canUseSecurityRecordsConsole(usr, "delete", null, a2)) return - GLOB.data_core.removeMinorCrime(active1.fields["id"], href_list["cdataid"]) - if("ma_crim_add") - if(istype(active1, /datum/data/record)) - var/t1 = stripped_input(usr, "Please input major crime names:", "Secure. records", "", null) - var/t2 = stripped_input(usr, "Please input major crime details:", "Secure. records", "", null) - if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) - return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, station_time_timestamp()) - GLOB.data_core.addMajorCrime(active1.fields["id"], crime) - investigate_log("New Major Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) - if("ma_crim_delete") + GLOB.data_core.removeCrime(active1.fields["id"],href_list["cdataid"]) + if("add_details") if(istype(active1, /datum/data/record)) if(href_list["cdataid"]) - if(!canUseSecurityRecordsConsole(usr, "delete", null, a2)) + var/t1 = stripped_input(usr, "Please input crime details:", "Secure. records", "", null) + if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) return - GLOB.data_core.removeMajorCrime(active1.fields["id"], href_list["cdataid"]) + GLOB.data_core.addCrimeDetails(active1.fields["id"], href_list["cdataid"], t1) + investigate_log("New Crime details: [t1] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) if("citation_add") if(istype(active1, /datum/data/record)) var/maxFine = CONFIG_GET(number/maxfine) diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index 249a3a074d6..4028a1347aa 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -5,8 +5,8 @@ icon_keyboard = "teleport_key" light_color = LIGHT_COLOR_BLUE circuit = /obj/item/circuitboard/computer/teleporter - ui_x = 475 - ui_y = 130 + ui_x = 470 + ui_y = 140 var/regime_set = "Teleporter" var/id var/obj/machinery/teleport/station/power_station diff --git a/code/game/machinery/computer/warrant.dm b/code/game/machinery/computer/warrant.dm index d5e98ec3e6b..b308c9dab09 100644 --- a/code/game/machinery/computer/warrant.dm +++ b/code/game/machinery/computer/warrant.dm @@ -66,7 +66,7 @@ dat += "" dat += "" - dat += "
Minor Crimes:" + dat += "
Crimes:" dat +={" @@ -74,23 +74,7 @@ "} - for(var/datum/data/crime/c in current.fields["mi_crim"]) - dat += {" - - - - "} - dat += "
CrimeAuthor Time Added
[c.crimeName][c.crimeDetails][c.author][c.time]
" - - dat += "
Major Crimes:" - dat +={" - - - - - - "} - for(var/datum/data/crime/c in current.fields["ma_crim"]) + for(var/datum/data/crime/c in current.fields["crim"]) dat += {" diff --git a/code/game/machinery/gulag_item_reclaimer.dm b/code/game/machinery/gulag_item_reclaimer.dm index bccd3feccd4..c872fa661a7 100644 --- a/code/game/machinery/gulag_item_reclaimer.dm +++ b/code/game/machinery/gulag_item_reclaimer.dm @@ -8,8 +8,8 @@ use_power = IDLE_POWER_USE idle_power_usage = 100 active_power_usage = 2500 - ui_x = 300 - ui_y = 300 + ui_x = 325 + ui_y = 400 var/list/stored_items = list() var/obj/machinery/gulag_teleporter/linked_teleporter = null diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index 43daf1ec5f1..02c320f2a48 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -9,7 +9,6 @@ icon_state = "floor_magnet-f" name = "electromagnetic generator" desc = "A device that uses station power to create points of magnetic energy." - level = 1 // underfloor layer = LOW_OBJ_LAYER use_power = IDLE_POWER_USE idle_power_usage = 50 @@ -30,9 +29,11 @@ /obj/machinery/magnetic_module/Initialize() ..() var/turf/T = loc - hide(T.intact) center = T SSradio.add_object(src, freq, RADIO_MAGNETS) + + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) + return INITIALIZE_HINT_LATELOAD /obj/machinery/magnetic_module/LateInitialize() @@ -43,23 +44,16 @@ center = null return ..() -// update the invisibility and icon -/obj/machinery/magnetic_module/hide(intact) - invisibility = intact ? INVISIBILITY_MAXIMUM : 0 - update_icon() // update the icon_state /obj/machinery/magnetic_module/update_icon_state() var/state="floor_magnet" var/onstate="" + if(!on) onstate="0" - if(invisibility) - icon_state = "[state][onstate]-f" // if invisible, set icon to faded version - // in case of being revealed by T-scanner - else - icon_state = "[state][onstate]" + icon_state = "[state][onstate]" /obj/machinery/magnetic_module/receive_signal(datum/signal/signal) diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index 4cb33e4d1a1..64ea63081cf 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -7,7 +7,6 @@ icon_state = "navbeacon0-f" name = "navigation beacon" desc = "A radio beacon used for bot navigation and crew wayfinding." - level = 1 // underfloor layer = LOW_OBJ_LAYER max_integrity = 500 armor = list("melee" = 70, "bullet" = 70, "laser" = 70, "energy" = 70, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80) @@ -36,11 +35,10 @@ set_codes() - var/turf/T = loc - hide(T.intact) - glob_lists_register(init=TRUE) + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) + /obj/machinery/navbeacon/Destroy() glob_lists_deregister() return ..() @@ -90,21 +88,9 @@ if(codes["wayfinding"]) GLOB.wayfindingbeacons += src -// called when turf state changes -// hide the object if turf is intact -/obj/machinery/navbeacon/hide(intact) - invisibility = intact ? INVISIBILITY_MAXIMUM : 0 - update_icon() - // update the icon_state /obj/machinery/navbeacon/update_icon_state() - var/state="navbeacon[open]" - - if(invisibility) - icon_state = "[state]-f" // if invisible, set icon to faded version - // in case revealed by T-scanner - else - icon_state = "[state]" + icon_state = "navbeacon[open]" /obj/machinery/navbeacon/attackby(obj/item/I, mob/user, params) var/turf/T = loc diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index e5d42354373..25c9bddeff0 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -18,7 +18,6 @@ Buildable meters icon_state = "simple" item_state = "buildpipe" w_class = WEIGHT_CLASS_NORMAL - level = 2 var/piping_layer = PIPING_LAYER_DEFAULT var/RPD_type diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index c6461b6baac..1edd966ce0b 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -141,10 +141,6 @@ for(var/obj/O in range(0,src)) if(O.type == src.type) continue - if(isturf(O.loc)) - var/turf/T = O.loc - if(T.intact && O.level == 1) //hidden under the floor - continue if(lifetime % reagent_divisor) reagents.reaction(O, VAPOR, fraction) var/hit = 0 diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index 0493a176827..daff05e223c 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -232,8 +232,6 @@ for(var/atom/movable/AM in T) if(AM.type == src.type) continue - if(T.intact && AM.level == 1) //hidden under the floor - continue reagents.reaction(AM, TOUCH, fraction) reagents.reaction(T, TOUCH, fraction) diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm index dea49eeab79..7e18077c841 100644 --- a/code/game/objects/effects/effects.dm +++ b/code/game/objects/effects/effects.dm @@ -6,7 +6,7 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF move_resist = INFINITY obj_flags = 0 - vis_flags = NONE + vis_flags = VIS_INHERIT_PLANE /obj/effect/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) return diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 41ed44a848a..3e95a91b1ac 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -429,3 +429,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) GLOB.ruin_landmarks -= src ruin_template = null . = ..() + +// handled in portals.dm, id connected to one-way portal +/obj/effect/landmark/portal_exit + name = "portal exit" + icon_state = "portal_exit" + var/id diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index c2a6194cca6..1193ce213c2 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -177,7 +177,7 @@ if(!victim.client || !istype(victim)) return to_chat(victim, "You feel fast!") - victim.add_movespeed_modifier(MOVESPEED_ID_YELLOW_ORB, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING)) + victim.add_movespeed_modifier(/datum/movespeed_modifier/yellow_orb) sleep(duration) - victim.remove_movespeed_modifier(MOVESPEED_ID_YELLOW_ORB) + victim.remove_movespeed_modifier(/datum/movespeed_modifier/yellow_orb) to_chat(victim, "You slow down.") diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index c3b30d5eae9..56d322a04a9 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -1,257 +1,228 @@ - -/proc/create_portal_pair(turf/source, turf/destination, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override) - if(!istype(source) || !istype(destination)) - return - var/turf/actual_destination = get_teleport_turf(destination, accuracy) - var/obj/effect/portal/P1 = new newtype(source, _lifespan, null, FALSE, null, atmos_link_override) - var/obj/effect/portal/P2 = new newtype(actual_destination, _lifespan, P1, TRUE, null, atmos_link_override) - if(!istype(P1)||!istype(P2)) - return - P1.link_portal(P2) - P1.hardlinked = TRUE - return list(P1, P2) - -/obj/effect/portal - name = "portal" - desc = "Looks unstable. Best to test it with the clown." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "portal" - anchored = TRUE - var/mech_sized = FALSE - var/obj/effect/portal/linked - var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted. - var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE - var/turf/hard_target //For when a portal needs a hard target and isn't to be linked. - var/atmos_link = FALSE //Link source/destination atmos. - var/turf/open/atmos_source //Atmos link source - var/turf/open/atmos_destination //Atmos link destination - var/allow_anchored = FALSE - var/innate_accuracy_penalty = 0 - var/last_effect = 0 - -/obj/effect/portal/anom - name = "wormhole" - icon = 'icons/obj/objects.dmi' - icon_state = "anom" - layer = RIPPLE_LAYER - mech_sized = TRUE - teleport_channel = TELEPORT_CHANNEL_WORMHOLE - -/obj/effect/portal/Move(newloc) - for(var/T in newloc) - if(istype(T, /obj/effect/portal)) - return FALSE - return ..() - -/obj/effect/portal/attackby(obj/item/W, mob/user, params) - if(user && Adjacent(user)) - user.forceMove(get_turf(src)) - return TRUE - -/obj/effect/portal/Crossed(atom/movable/AM, oldloc, force_stop = 0) - if(force_stop) - return ..() - if(isobserver(AM)) - return ..() - if(linked && (get_turf(oldloc) == get_turf(linked))) - return ..() - if(!teleport(AM)) - return ..() - -/obj/effect/portal/attack_tk(mob/user) - return - -/obj/effect/portal/attack_hand(mob/user) - . = ..() - if(.) - return - if(get_turf(user) == get_turf(src)) - teleport(user) - if(Adjacent(user)) - user.forceMove(get_turf(src)) - -/obj/effect/portal/Initialize(mapload, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override) - . = ..() - GLOB.portals += src - if(!istype(_linked) && automatic_link) - . = INITIALIZE_HINT_QDEL - CRASH("Somebody fucked up.") - if(_lifespan > 0) - QDEL_IN(src, _lifespan) - if(!isnull(atmos_link_override)) - atmos_link = atmos_link_override - link_portal(_linked) - hardlinked = automatic_link - if(isturf(hard_target_override)) - hard_target = hard_target_override - -/obj/effect/portal/singularity_pull() - return - -/obj/effect/portal/singularity_act() - return - -/obj/effect/portal/proc/link_portal(obj/effect/portal/newlink) - linked = newlink - if(atmos_link) - link_atmos() - -/obj/effect/portal/proc/link_atmos() - if(atmos_source || atmos_destination) - unlink_atmos() - if(!isopenturf(get_turf(src))) - return FALSE - if(linked) - if(isopenturf(get_turf(linked))) - atmos_source = get_turf(src) - atmos_destination = get_turf(linked) - else if(hard_target) - if(isopenturf(hard_target)) - atmos_source = get_turf(src) - atmos_destination = hard_target - else - return FALSE - if(!istype(atmos_source) || !istype(atmos_destination)) - return FALSE - LAZYINITLIST(atmos_source.atmos_adjacent_turfs) - LAZYINITLIST(atmos_destination.atmos_adjacent_turfs) - if(atmos_source.atmos_adjacent_turfs[atmos_destination] || atmos_destination.atmos_adjacent_turfs[atmos_source]) //Already linked! - return FALSE - atmos_source.atmos_adjacent_turfs[atmos_destination] = TRUE - atmos_destination.atmos_adjacent_turfs[atmos_source] = TRUE - atmos_source.air_update_turf(FALSE) - atmos_destination.air_update_turf(FALSE) - -/obj/effect/portal/proc/unlink_atmos() - if(istype(atmos_source)) - if(istype(atmos_destination) && !atmos_source.Adjacent(atmos_destination) && !CANATMOSPASS(atmos_destination, atmos_source)) - LAZYREMOVE(atmos_source.atmos_adjacent_turfs, atmos_destination) - atmos_source = null - if(istype(atmos_destination)) - if(istype(atmos_source) && !atmos_destination.Adjacent(atmos_source) && !CANATMOSPASS(atmos_source, atmos_destination)) - LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source) - atmos_destination = null - -/obj/effect/portal/Destroy() - GLOB.portals -= src - unlink_atmos() - if(hardlinked && !QDELETED(linked)) - QDEL_NULL(linked) - else - linked = null - return ..() - -/obj/effect/portal/attack_ghost(mob/dead/observer/O) - if(!teleport(O, TRUE)) - return ..() - -/obj/effect/portal/proc/teleport(atom/movable/M, force = FALSE) - if(!force && (!istype(M) || iseffect(M) || (ismecha(M) && !mech_sized) || (!isobj(M) && !ismob(M)))) //Things that shouldn't teleport. - return - var/turf/real_target = get_link_target_turf() - if(!istype(real_target)) - return FALSE - if(!force && (!ismecha(M) && !istype(M, /obj/projectile) && M.anchored && !allow_anchored)) - return - if(ismegafauna(M)) - message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].") - var/no_effect = FALSE - if(last_effect == world.time) - no_effect = TRUE - else - last_effect = world.time - if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel)) - if(istype(M, /obj/projectile)) - var/obj/projectile/P = M - P.ignore_source_check = TRUE - return TRUE - return FALSE - -/obj/effect/portal/proc/get_link_target_turf() - var/turf/real_target - if(!istype(linked) || QDELETED(linked)) - if(hardlinked) - qdel(src) - if(!istype(hard_target) || QDELETED(hard_target)) - hard_target = null - return - else - real_target = hard_target - linked = null - else - real_target = get_turf(linked) - return real_target - -/obj/effect/portal/permanent - name = "permanent portal" - desc = "An unwavering portal that will never fade." - var/id // var edit or set id in map editor - hardlinked = FALSE // dont qdel my portal nerd - -/obj/effect/portal/permanent/Initialize(mapload, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override) - . = ..() - set_linked() - -/obj/effect/portal/permanent/proc/get_linked() - if(!id) - return - var/list/possible = list() - for(var/obj/effect/portal/permanent/P in GLOB.portals - src) - if(P.id && P.id == id) // gets portals with the same id, there should only be two permanent portals with the same id - possible += P - return possible - -/obj/effect/portal/permanent/proc/set_linked() - var/list/possible = get_linked() - if(!possible || !possible.len) - return - for(var/obj/effect/portal/permanent/other in possible) - other.linked = src - linked = pick(possible) - -/obj/effect/portal/permanent/teleport(atom/movable/M, force = FALSE) // Made perma portals always teleport even in noteleport areas since they are mapmaker only - if(!force && (!istype(M) || iseffect(M) || (ismecha(M) && !mech_sized) || (isobj(M) && !ismob(M)))) //Things that shouldn't teleport. - return - var/turf/real_target = get_link_target_turf() - if(!istype(real_target)) - return FALSE - if(!force && (!ismecha(M) && !istype(M, /obj/projectile) && M.anchored && !allow_anchored)) - return - if(ismegafauna(M)) - message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].") - var/no_effect = FALSE - if(last_effect == world.time) - no_effect = TRUE - else - last_effect = world.time - if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel, forced = TRUE)) - if(istype(M, /obj/projectile)) - var/obj/projectile/P = M - P.ignore_source_check = TRUE - return TRUE - // try to search for a new one if something was var edited etc - set_linked() - . = ..() - -/obj/effect/portal/permanent/one_way // doesn't have a return portal - name = "one-way portal" - desc = "You get the feeling that this might not be the safest thing you've ever done." - var/list/possible_exits = list() - var/keep // if this is a portal that should be kept - -/obj/effect/portal/permanent/one_way/set_linked() - if(!keep) // wait for a keep portal to set - return - var/list/possible_temp = get_linked() - if(possible_temp && possible_temp.len) - for(var/obj/effect/portal/permanent/other in possible_temp) - possible_exits += get_turf(other) - qdel(other) - if(possible_exits && possible_exits.len) - hard_target = pick(possible_exits) - -/obj/effect/portal/permanent/one_way/keep // because its nice to be able to tell which is which on the map - keep = TRUE - -/obj/effect/portal/permanent/one_way/destroy - keep = FALSE + +/proc/create_portal_pair(turf/source, turf/destination, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override) + if(!istype(source) || !istype(destination)) + return + var/turf/actual_destination = get_teleport_turf(destination, accuracy) + var/obj/effect/portal/P1 = new newtype(source, _lifespan, null, FALSE, null, atmos_link_override) + var/obj/effect/portal/P2 = new newtype(actual_destination, _lifespan, P1, TRUE, null, atmos_link_override) + if(!istype(P1)||!istype(P2)) + return + P1.link_portal(P2) + P1.hardlinked = TRUE + return list(P1, P2) + +/obj/effect/portal + name = "portal" + desc = "Looks unstable. Best to test it with the clown." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "portal" + anchored = TRUE + var/mech_sized = FALSE + var/obj/effect/portal/linked + var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted. + var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE + var/turf/hard_target //For when a portal needs a hard target and isn't to be linked. + var/atmos_link = FALSE //Link source/destination atmos. + var/turf/open/atmos_source //Atmos link source + var/turf/open/atmos_destination //Atmos link destination + var/allow_anchored = FALSE + var/innate_accuracy_penalty = 0 + var/last_effect = 0 + var/force_teleport = FALSE + +/obj/effect/portal/anom + name = "wormhole" + icon = 'icons/obj/objects.dmi' + icon_state = "anom" + layer = RIPPLE_LAYER + mech_sized = TRUE + teleport_channel = TELEPORT_CHANNEL_WORMHOLE + +/obj/effect/portal/Move(newloc) + for(var/T in newloc) + if(istype(T, /obj/effect/portal)) + return FALSE + return ..() + +/obj/effect/portal/attackby(obj/item/W, mob/user, params) + if(user && Adjacent(user)) + user.forceMove(get_turf(src)) + return TRUE + +/obj/effect/portal/Crossed(atom/movable/AM, oldloc, force_stop = 0) + if(force_stop) + return ..() + if(isobserver(AM)) + return ..() + if(linked && (get_turf(oldloc) == get_turf(linked))) + return ..() + if(!teleport(AM)) + return ..() + +/obj/effect/portal/attack_tk(mob/user) + return + +/obj/effect/portal/attack_hand(mob/user) + . = ..() + if(.) + return + if(get_turf(user) == get_turf(src)) + teleport(user) + if(Adjacent(user)) + user.forceMove(get_turf(src)) + +/obj/effect/portal/Initialize(mapload, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override) + . = ..() + GLOB.portals += src + if(!istype(_linked) && automatic_link) + . = INITIALIZE_HINT_QDEL + CRASH("Somebody fucked up.") + if(_lifespan > 0) + QDEL_IN(src, _lifespan) + if(!isnull(atmos_link_override)) + atmos_link = atmos_link_override + link_portal(_linked) + hardlinked = automatic_link + if(isturf(hard_target_override)) + hard_target = hard_target_override + +/obj/effect/portal/singularity_pull() + return + +/obj/effect/portal/singularity_act() + return + +/obj/effect/portal/proc/link_portal(obj/effect/portal/newlink) + linked = newlink + if(atmos_link) + link_atmos() + +/obj/effect/portal/proc/link_atmos() + if(atmos_source || atmos_destination) + unlink_atmos() + if(!isopenturf(get_turf(src))) + return FALSE + if(linked) + if(isopenturf(get_turf(linked))) + atmos_source = get_turf(src) + atmos_destination = get_turf(linked) + else if(hard_target) + if(isopenturf(hard_target)) + atmos_source = get_turf(src) + atmos_destination = hard_target + else + return FALSE + if(!istype(atmos_source) || !istype(atmos_destination)) + return FALSE + LAZYINITLIST(atmos_source.atmos_adjacent_turfs) + LAZYINITLIST(atmos_destination.atmos_adjacent_turfs) + if(atmos_source.atmos_adjacent_turfs[atmos_destination] || atmos_destination.atmos_adjacent_turfs[atmos_source]) //Already linked! + return FALSE + atmos_source.atmos_adjacent_turfs[atmos_destination] = TRUE + atmos_destination.atmos_adjacent_turfs[atmos_source] = TRUE + atmos_source.air_update_turf(FALSE) + atmos_destination.air_update_turf(FALSE) + +/obj/effect/portal/proc/unlink_atmos() + if(istype(atmos_source)) + if(istype(atmos_destination) && !atmos_source.Adjacent(atmos_destination) && !CANATMOSPASS(atmos_destination, atmos_source)) + LAZYREMOVE(atmos_source.atmos_adjacent_turfs, atmos_destination) + atmos_source = null + if(istype(atmos_destination)) + if(istype(atmos_source) && !atmos_destination.Adjacent(atmos_source) && !CANATMOSPASS(atmos_source, atmos_destination)) + LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source) + atmos_destination = null + +/obj/effect/portal/Destroy() + GLOB.portals -= src + unlink_atmos() + if(hardlinked && !QDELETED(linked)) + QDEL_NULL(linked) + else + linked = null + return ..() + +/obj/effect/portal/attack_ghost(mob/dead/observer/O) + if(!teleport(O, TRUE)) + return ..() + +/obj/effect/portal/proc/teleport(atom/movable/M, force = FALSE) + if(!force && (!istype(M) || iseffect(M) || (ismecha(M) && !mech_sized) || (!isobj(M) && !ismob(M)))) //Things that shouldn't teleport. + return + var/turf/real_target = get_link_target_turf() + if(!istype(real_target)) + return FALSE + if(!force && (!ismecha(M) && !istype(M, /obj/projectile) && M.anchored && !allow_anchored)) + return + if(ismegafauna(M)) + message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].") + var/no_effect = FALSE + if(last_effect == world.time) + no_effect = TRUE + else + last_effect = world.time + if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel, forced = force_teleport)) + if(istype(M, /obj/projectile)) + var/obj/projectile/P = M + P.ignore_source_check = TRUE + return TRUE + return FALSE + +/obj/effect/portal/proc/get_link_target_turf() + var/turf/real_target + if(!istype(linked) || QDELETED(linked)) + if(hardlinked) + qdel(src) + if(!istype(hard_target) || QDELETED(hard_target)) + hard_target = null + return + else + real_target = hard_target + linked = null + else + real_target = get_turf(linked) + return real_target + +/obj/effect/portal/permanent + name = "permanent portal" + desc = "An unwavering portal that will never fade." + hardlinked = FALSE // dont qdel my portal nerd + force_teleport = TRUE // force teleports because they're a mapmaker tool + var/id // var edit or set id in map editor + +/obj/effect/portal/permanent/proc/set_linked() + if(!id) + return + for(var/obj/effect/portal/permanent/P in GLOB.portals - src) + if(P.id == id) + P.linked = src + linked = P + break + +/obj/effect/portal/permanent/teleport(atom/movable/M, force = FALSE) + set_linked() // update portal links + . = ..() + +/obj/effect/portal/permanent/one_way // doesn't have a return portal, can have multiple exits, /obj/effect/landmark/portal_exit to mark them + name = "one-way portal" + desc = "You get the feeling that this might not be the safest thing you've ever done." + +/obj/effect/portal/permanent/one_way/set_linked() + if(!id) + return + var/list/possible_turfs = list() + for(var/obj/effect/landmark/portal_exit/PE in GLOB.landmarks_list) + if(PE.id == id) + var/turf/T = get_turf(PE) + if(T) + possible_turfs |= T + if(possible_turfs.len) + hard_target = pick(possible_turfs) + +/obj/effect/portal/permanent/one_way/one_use + name = "one-use portal" + desc = "This is probably the worst decision you'll ever make in your life." + +/obj/effect/portal/permanent/one_way/one_use/teleport(atom/movable/M, force = FALSE) + . = ..() + qdel(src) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 4370ccdd4a5..d627ceb2283 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -478,14 +478,17 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb if(usr.get_active_held_item() == null) // Let me know if this has any problems -Yota usr.UnarmedAttack(src) -//This proc is executed when someone clicks the on-screen UI button. -//The default action is attack_self(). -//Checks before we get to here are: mob is alive, mob is not restrained, stunned, asleep, resting, laying, item is on the mob. +/** + *This proc is executed when someone clicks the on-screen UI button. + *The default action is attack_self(). + *Checks before we get to here are: mob is alive, mob is not restrained, stunned, asleep, resting, laying, item is on the mob. + */ /obj/item/proc/ui_action_click(mob/user, actiontype) attack_self(user) -/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit - return 0 +///This proc determines if and at what an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit +/obj/item/proc/IsReflect(var/def_zone) + return FALSE /obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index ea45a473a44..e7590c48067 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -382,7 +382,7 @@ Code: if(active3 in GLOB.data_core.security) menu += "Criminal Status: [active3.fields["criminal"]]
" - menu += text("
\nMinor Crimes:") + menu += text("
\nCrimes:") menu +={"
CrimeDetailsAuthorTime Added
[c.crimeName] [c.crimeDetails] [c.author]
@@ -391,31 +391,13 @@ Code: "} - for(var/datum/data/crime/c in active3.fields["mi_crim"]) + for(var/datum/data/crime/c in active3.fields["crim"]) menu += "" menu += "" menu += "" menu += "" menu += "" menu += "
Author Time Added
[c.crimeName][c.crimeDetails][c.author][c.time]
" - - menu += text("
\nMajor Crimes:") - - menu +={" - - - - - -"} - for(var/datum/data/crime/c in active3.fields["ma_crim"]) - menu += "" - menu += "" - menu += "" - menu += "" - menu += "" - menu += "
CrimeDetailsAuthorTime Added
[c.crimeName][c.crimeDetails][c.author][c.time]
" - menu += "
\nImportant Notes:
" menu += "[active3.fields["notes"]]" else diff --git a/code/game/objects/items/devices/pressureplates.dm b/code/game/objects/items/devices/pressureplates.dm index 60fa1fbadb4..50b105220dd 100644 --- a/code/game/objects/items/devices/pressureplates.dm +++ b/code/game/objects/items/devices/pressureplates.dm @@ -4,7 +4,6 @@ icon = 'icons/obj/puzzle_small.dmi' item_state = "flash" icon_state = "pressureplate" - level = 1 layer = LOW_OBJ_LAYER var/trigger_mob = TRUE var/trigger_item = FALSE @@ -30,8 +29,9 @@ sigdev = new sigdev.code = roundstart_signaller_code sigdev.frequency = roundstart_signaller_freq - if(isopenturf(loc)) - hide(TRUE) + + AddElement(/datum/element/undertile, tile_overlay = tile_overlay, use_anchor = TRUE) + RegisterSignal(src, COMSIG_OBJ_HIDE, .proc/ToggleActive) /obj/item/pressure_plate/Crossed(atom/movable/AM) . = ..() @@ -76,19 +76,7 @@ else to_chat(user, "You turn [src] off.") -/obj/item/pressure_plate/hide(yes) - if(yes) - invisibility = INVISIBILITY_MAXIMUM - anchored = TRUE - icon_state = null - active = TRUE - can_trigger = TRUE - if(tile_overlay) - loc.add_overlay(tile_overlay) - else - invisibility = initial(invisibility) - anchored = FALSE - icon_state = initial(icon_state) - active = FALSE - if(tile_overlay) - loc.overlays -= tile_overlay +///Called from COMSIG_OBJ_HIDE to toggle the active part, because yeah im not making a special exception on the element to support it +/obj/item/pressure_plate/proc/ToggleActive(datum/source, covered) + active = covered + diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index b02b4f84b05..6b8e96368fd 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -65,8 +65,6 @@ GENE SCANNER return var/list/t_ray_images = list() for(var/obj/O in orange(distance, viewer) ) - if(O.level != 1) - continue if(O.invisibility == INVISIBILITY_MAXIMUM || HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) var/image/I = new(loc = get_turf(O)) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index c697a385504..1741b010fe1 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -292,7 +292,7 @@ playsound(get_turf(src), on_stun_sound, 75, TRUE, -1) target.Knockdown(knockdown_time_carbon) - target.apply_damage(stamina_damage, STAMINA) + target.apply_damage(stamina_damage, STAMINA, BODY_ZONE_CHEST) additional_effects_carbon(target, user) log_combat(user, target, "stunned", src) diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index 68caa4811b2..a4f1b7c9c02 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -573,22 +573,13 @@ ram() /obj/item/toy/plush/goatplushie/angry/proc/ram() - if(prob((obj_flags & EMAGGED) ? 98:90) && isturf(loc) && considered_alive(target.mind) && !faction_check(list("goat"), target.faction, FALSE)) + if(prob(90) && isturf(loc) && considered_alive(target.mind) && !faction_check(list("goat"), target.faction, FALSE)) throw_at(target, 10, 10) visible_message("[src] rams [target]!") cooldown = world.time + cooldown_modifier target = null visible_message("[src] looks disinterested.") -/obj/item/toy/plush/goatplushie/angry/emag_act(mob/user) - if (obj_flags&EMAGGED) - visible_message("[src] already looks angry enough, you shouldn't anger it more.") - return - cooldown_modifier = 5 - throwforce = 20 - obj_flags |= EMAGGED - visible_message("[src] stares at [user] angrily before going docile.") - /obj/item/toy/plush/goatplushie/angry/Destroy() STOP_PROCESSING(SSprocessing, src) return ..() diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 69cc78fe135..24fd1a30044 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -116,9 +116,10 @@ var/reward = /obj/item/reagent_containers/food/snacks/cookie var/claimed = FALSE -/obj/item/pressure_plate/hologrid/hide(yes) +/obj/item/pressure_plate/hologrid/Initialize() . = ..() - anchored = TRUE + + AddElement(/datum/element/undertile, tile_overlay = tile_overlay) //we remove use_anchor here, so it ALWAYS stays anchored /obj/item/pressure_plate/hologrid/examine(mob/user) . = ..() diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index d18a17d339e..8ee7bac787c 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -6,6 +6,7 @@ desc = "Protected by FRM." icon = 'icons/obj/module.dmi' icon_state = "cyborg_upgrade" + w_class = WEIGHT_CLASS_SMALL var/locked = FALSE var/installed = 0 var/require_module = 0 diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 8849e94f64a..1e18aa8dec3 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -626,6 +626,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list( item_state = "sheet-plastic" custom_materials = list(/datum/material/plastic=MINERAL_MATERIAL_AMOUNT) throwforce = 7 + material_type = /datum/material/plastic merge_type = /obj/item/stack/sheet/plastic /obj/item/stack/sheet/plastic/fifty diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 59463a09fbf..439dc4e42a1 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -302,7 +302,10 @@ icon_state = "satchel-flat" item_state = "satchel-flat" w_class = WEIGHT_CLASS_NORMAL //Can fit in backpacks itself. - level = 1 + +/obj/item/storage/backpack/satchel/flat/Initialize(mapload) + . = ..() + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, INVISIBILITY_OBSERVER, use_anchor = TRUE) /obj/item/storage/backpack/satchel/flat/ComponentInitialize() . = ..() @@ -310,18 +313,6 @@ STR.max_combined_w_class = 15 STR.set_holdable(null, list(/obj/item/storage/backpack/satchel/flat)) //muh recursive backpacks) -/obj/item/storage/backpack/satchel/flat/hide(intact) - if(intact) - invisibility = INVISIBILITY_OBSERVER - anchored = TRUE //otherwise you can start pulling, cover it, and drag around an invisible backpack. - icon_state = "[initial(icon_state)]2" - ADD_TRAIT(src, TRAIT_T_RAY_VISIBLE, TRAIT_GENERIC) - else - invisibility = initial(invisibility) - anchored = FALSE - icon_state = initial(icon_state) - REMOVE_TRAIT(src, TRAIT_T_RAY_VISIBLE, TRAIT_GENERIC) - /obj/item/storage/backpack/satchel/flat/PopulateContents() var/datum/supply_pack/costumes_toys/randomised/contraband/C = new for(var/i in 1 to 2) @@ -615,3 +606,8 @@ desc = "Granted to the henchmen who deserve it. This probably doesn't include you." icon_state = "henchmen" item_state = "henchmen" + +/obj/item/storage/backpack/duffelbag/cops + name = "police bag" + desc = "A large duffel bag for holding extra police gear." + slowdown = 0 diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 6209cc5e103..4073556335b 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -226,6 +226,41 @@ new /obj/item/ammo_box/a762(src) new /obj/item/ammo_box/a762(src) +/obj/item/storage/toolbox/infiltrator + name = "insidious case" + desc = "Bearing the emblem of the Syndicate, this case contains a full infiltrator stealth suit, and has enough room to fit weaponry if necessary." + icon_state = "infiltrator_case" + item_state = "infiltrator_case" + force = 15 + throwforce = 18 + w_class = WEIGHT_CLASS_NORMAL + has_latches = FALSE + +/obj/item/storage/toolbox/infiltrator/ComponentInitialize() + . = ..() + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_items = 10 + STR.max_w_class = WEIGHT_CLASS_NORMAL + STR.set_holdable(list( + /obj/item/clothing/head/helmet/infiltrator, + /obj/item/clothing/suit/armor/vest/infiltrator, + /obj/item/clothing/under/syndicate/bloodred, + /obj/item/clothing/gloves/color/latex/nitrile/infiltrator, + /obj/item/clothing/mask/infiltrator, + /obj/item/clothing/shoes/combat/sneakboots, + /obj/item/gun/ballistic/automatic/pistol, + /obj/item/gun/ballistic/revolver, + /obj/item/ammo_box + )) + +/obj/item/storage/toolbox/infiltrator/PopulateContents() + new /obj/item/clothing/head/helmet/infiltrator(src) + new /obj/item/clothing/suit/armor/vest/infiltrator(src) + new /obj/item/clothing/under/syndicate/bloodred(src) + new /obj/item/clothing/gloves/color/latex/nitrile/infiltrator(src) + new /obj/item/clothing/mask/infiltrator(src) + new /obj/item/clothing/shoes/combat/sneakboots(src) + //floorbot assembly /obj/item/storage/toolbox/attackby(obj/item/stack/tile/plasteel/T, mob/user, params) var/list/allowed_toolbox = list(/obj/item/storage/toolbox/emergency, //which toolboxes can be made into floorbots diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index a4b80e06b0e..7c9d15d4543 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -530,6 +530,12 @@ for(var/i in 1 to 3) new /obj/item/grenade/spawnergrenade/buzzkill(src) +/obj/item/storage/box/syndie_kit/sleepytime/PopulateContents() + new /obj/item/clothing/under/syndicate/bloodred/sleepytime(src) + new /obj/item/reagent_containers/food/drinks/mug/coco(src) + new /obj/item/toy/plush/carpplushie(src) + new /obj/item/bedsheet/syndie(src) + ///Subtype for the sabotage bundle. Contains three C4, two X4 and 6 signalers /obj/item/storage/backpack/duffelbag/syndie/sabotage diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm index 765274c93f8..ab3da28f220 100644 --- a/code/game/objects/items/tanks/jetpack.dm +++ b/code/game/objects/items/tanks/jetpack.dm @@ -1,275 +1,275 @@ -/obj/item/tank/jetpack - name = "jetpack (empty)" - desc = "A tank of compressed gas for use as propulsion in zero-gravity areas. Use with caution." - icon_state = "jetpack" - item_state = "jetpack" - lefthand_file = 'icons/mob/inhands/equipment/jetpacks_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/jetpacks_righthand.dmi' - w_class = WEIGHT_CLASS_BULKY - distribute_pressure = ONE_ATMOSPHERE * O2STANDARD - actions_types = list(/datum/action/item_action/set_internals, /datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization) - var/gas_type = /datum/gas/oxygen - var/on = FALSE - var/stabilizers = FALSE - var/full_speed = TRUE // If the jetpack will have a speedboost in space/nograv or not - var/datum/effect_system/trail_follow/ion/ion_trail - -/obj/item/tank/jetpack/Initialize() - . = ..() - ion_trail = new - ion_trail.auto_process = FALSE - ion_trail.set_up(src) - -/obj/item/tank/jetpack/populate_gas() - if(gas_type) - air_contents.assert_gas(gas_type) - air_contents.gases[gas_type][MOLES] = ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/tank/jetpack/ui_action_click(mob/user, action) - if(istype(action, /datum/action/item_action/toggle_jetpack)) - cycle(user) - else if(istype(action, /datum/action/item_action/jetpack_stabilization)) - if(on) - stabilizers = !stabilizers - to_chat(user, "You turn the jetpack stabilization [stabilizers ? "on" : "off"].") - else - toggle_internals(user) - - -/obj/item/tank/jetpack/proc/cycle(mob/user) - if(user.incapacitated()) - return - - if(!on) - turn_on(user) - to_chat(user, "You turn the jetpack on.") - else - turn_off(user) - to_chat(user, "You turn the jetpack off.") - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon() - - -/obj/item/tank/jetpack/proc/turn_on(mob/user) - if(!allow_thrust(0.01, user)) - return - on = TRUE - icon_state = "[initial(icon_state)]-on" - ion_trail.start() - RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/move_react) - RegisterSignal(user, COMSIG_MOVABLE_PRE_MOVE, .proc/pre_move_react) - if(full_speed) - user.add_movespeed_modifier(MOVESPEED_ID_JETPACK, priority=100, multiplicative_slowdown=-0.5, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK) - -/obj/item/tank/jetpack/proc/turn_off(mob/user) - on = FALSE - stabilizers = FALSE - icon_state = initial(icon_state) - ion_trail.stop() - UnregisterSignal(user, COMSIG_MOVABLE_MOVED) - UnregisterSignal(user, COMSIG_MOVABLE_PRE_MOVE) - user.remove_movespeed_modifier(MOVESPEED_ID_JETPACK) - -/obj/item/tank/jetpack/proc/move_react(mob/user) - if(!on)//If jet dont work, it dont work - return - if(!user)//Don't allow jet self using - return - if(!isturf(user.loc))//You can't use jet in nowhere or from mecha/closet - return - if(!(user.is_flying() || user.is_floating()) || user.buckled)//You don't want use jet in gravity or while buckled. - return - if(user.pulledby)//You don't must use jet if someone pull you - return - if(user.throwing)//You don't must use jet if you thrown - return - if(length(user.client.keys_held & user.client.movement_keys))//You use jet when press keys. yes. - allow_thrust(0.01, user) - -/obj/item/tank/jetpack/proc/pre_move_react(mob/user) - ion_trail.oldposition = get_turf(src) - -/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user) - if((num < 0.005 || air_contents.total_moles() < num)) - turn_off(user) - return - - var/datum/gas_mixture/removed = air_contents.remove(num) - if(removed.total_moles() < 0.005) - turn_off(user) - return - - var/turf/T = get_turf(user) - T.assume_air(removed) - ion_trail.generate_effect() - - return TRUE - -/obj/item/tank/jetpack/suicide_act(mob/user) - if (istype(user, /mob/living/carbon/human/)) - var/mob/living/carbon/human/H = user - H.forcesay("WHAT THE FUCK IS CARBON DIOXIDE?") - H.visible_message("[user] is suffocating [user.p_them()]self with [src]! It looks like [user.p_they()] didn't read what that jetpack says!") - return (OXYLOSS) - else - ..() - -/obj/item/tank/jetpack/improvised - name = "improvised jetpack" - desc = "A jetpack made from two air tanks, a fire extinguisher and some atmospherics equipment. It doesn't look like it can hold much." - icon_state = "jetpack-improvised" - item_state = "jetpack-sec" - volume = 20 //normal jetpacks have 70 volume - gas_type = null //it starts empty - full_speed = FALSE //moves at hardsuit jetpack speeds - -/obj/item/tank/jetpack/improvised/allow_thrust(num, mob/living/user) - if(!on) - return - if((num < 0.005 || air_contents.total_moles() < num)) - turn_off(user) - return - if(rand(0,250) == 0) - to_chat(user, "You feel your jetpack's engines cut out.") - turn_off(user) - return - - var/datum/gas_mixture/removed = air_contents.remove(num) - if(removed.total_moles() < 0.005) - turn_off(user) - return - - var/turf/T = get_turf(user) - T.assume_air(removed) - ion_trail.generate_effect() - - return TRUE - -/obj/item/tank/jetpack/void - name = "void jetpack (oxygen)" - desc = "It works well in a void." - icon_state = "jetpack-void" - item_state = "jetpack-void" - -/obj/item/tank/jetpack/oxygen - name = "jetpack (oxygen)" - desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas. Use with caution." - icon_state = "jetpack" - item_state = "jetpack" - -/obj/item/tank/jetpack/oxygen/harness - name = "jet harness (oxygen)" - desc = "A lightweight tactical harness, used by those who don't want to be weighed down by traditional jetpacks." - icon_state = "jetpack-mini" - item_state = "jetpack-mini" - volume = 40 - throw_range = 7 - w_class = WEIGHT_CLASS_NORMAL - -/obj/item/tank/jetpack/oxygen/captain - name = "captain's jetpack" - desc = "A compact, lightweight jetpack containing a high amount of compressed oxygen." - icon_state = "jetpack-captain" - item_state = "jetpack-captain" - w_class = WEIGHT_CLASS_NORMAL - volume = 90 - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF //steal objective items are hard to destroy. - -/obj/item/tank/jetpack/oxygen/security - name = "security jetpack (oxygen)" - desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas by security forces." - icon_state = "jetpack-sec" - item_state = "jetpack-sec" - - - -/obj/item/tank/jetpack/carbondioxide - name = "jetpack (carbon dioxide)" - desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals." - icon_state = "jetpack-black" - item_state = "jetpack-black" - distribute_pressure = 0 - gas_type = /datum/gas/carbon_dioxide - - -/obj/item/tank/jetpack/suit - name = "hardsuit jetpack upgrade" - desc = "A modular, compact set of thrusters designed to integrate with a hardsuit. It is fueled by a tank inserted into the suit's storage compartment." - icon_state = "jetpack-mining" - item_state = "jetpack-black" - w_class = WEIGHT_CLASS_NORMAL - actions_types = list(/datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization) - volume = 1 - slot_flags = null - gas_type = null - full_speed = FALSE - var/datum/gas_mixture/temp_air_contents - var/obj/item/tank/internals/tank = null - var/mob/living/carbon/human/cur_user - -/obj/item/tank/jetpack/suit/Initialize() - . = ..() - STOP_PROCESSING(SSobj, src) - temp_air_contents = air_contents - -/obj/item/tank/jetpack/suit/attack_self() - return - -/obj/item/tank/jetpack/suit/cycle(mob/user) - if(!istype(loc, /obj/item/clothing/suit/space/hardsuit)) - to_chat(user, "\The [src] must be connected to a hardsuit!") - return - - var/mob/living/carbon/human/H = user - if(!istype(H.s_store, /obj/item/tank/internals)) - to_chat(user, "You need a tank in your suit storage!") - return - ..() - -/obj/item/tank/jetpack/suit/turn_on(mob/user) - if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc) || loc.loc != user) - return - var/mob/living/carbon/human/H = user - tank = H.s_store - air_contents = tank.air_contents - START_PROCESSING(SSobj, src) - cur_user = user - ..() - -/obj/item/tank/jetpack/suit/turn_off(mob/user) - tank = null - air_contents = temp_air_contents - STOP_PROCESSING(SSobj, src) - cur_user = null - ..() - -/obj/item/tank/jetpack/suit/process() - if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc)) - turn_off(cur_user) - return - var/mob/living/carbon/human/H = loc.loc - if(!tank || tank != H.s_store) - turn_off(cur_user) - return - ..() - - -//Return a jetpack that the mob can use -//Back worn jetpacks, hardsuit internal packs, and so on. -//Used in Process_Spacemove() and wherever you want to check for/get a jetpack - -/mob/proc/get_jetpack() - return - -/mob/living/carbon/get_jetpack() - var/obj/item/tank/jetpack/J = back - if(istype(J)) - return J - -/mob/living/carbon/human/get_jetpack() - var/obj/item/tank/jetpack/J = ..() - if(!istype(J) && istype(wear_suit, /obj/item/clothing/suit/space/hardsuit)) - var/obj/item/clothing/suit/space/hardsuit/C = wear_suit - J = C.jetpack - return J +/obj/item/tank/jetpack + name = "jetpack (empty)" + desc = "A tank of compressed gas for use as propulsion in zero-gravity areas. Use with caution." + icon_state = "jetpack" + item_state = "jetpack" + lefthand_file = 'icons/mob/inhands/equipment/jetpacks_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/jetpacks_righthand.dmi' + w_class = WEIGHT_CLASS_BULKY + distribute_pressure = ONE_ATMOSPHERE * O2STANDARD + actions_types = list(/datum/action/item_action/set_internals, /datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization) + var/gas_type = /datum/gas/oxygen + var/on = FALSE + var/stabilizers = FALSE + var/full_speed = TRUE // If the jetpack will have a speedboost in space/nograv or not + var/datum/effect_system/trail_follow/ion/ion_trail + +/obj/item/tank/jetpack/Initialize() + . = ..() + ion_trail = new + ion_trail.auto_process = FALSE + ion_trail.set_up(src) + +/obj/item/tank/jetpack/populate_gas() + if(gas_type) + air_contents.assert_gas(gas_type) + air_contents.gases[gas_type][MOLES] = ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/tank/jetpack/ui_action_click(mob/user, action) + if(istype(action, /datum/action/item_action/toggle_jetpack)) + cycle(user) + else if(istype(action, /datum/action/item_action/jetpack_stabilization)) + if(on) + stabilizers = !stabilizers + to_chat(user, "You turn the jetpack stabilization [stabilizers ? "on" : "off"].") + else + toggle_internals(user) + + +/obj/item/tank/jetpack/proc/cycle(mob/user) + if(user.incapacitated()) + return + + if(!on) + turn_on(user) + to_chat(user, "You turn the jetpack on.") + else + turn_off(user) + to_chat(user, "You turn the jetpack off.") + for(var/X in actions) + var/datum/action/A = X + A.UpdateButtonIcon() + + +/obj/item/tank/jetpack/proc/turn_on(mob/user) + if(!allow_thrust(0.01, user)) + return + on = TRUE + icon_state = "[initial(icon_state)]-on" + ion_trail.start() + RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/move_react) + RegisterSignal(user, COMSIG_MOVABLE_PRE_MOVE, .proc/pre_move_react) + if(full_speed) + user.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/fullspeed) + +/obj/item/tank/jetpack/proc/turn_off(mob/user) + on = FALSE + stabilizers = FALSE + icon_state = initial(icon_state) + ion_trail.stop() + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + UnregisterSignal(user, COMSIG_MOVABLE_PRE_MOVE) + user.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/fullspeed) + +/obj/item/tank/jetpack/proc/move_react(mob/user) + if(!on)//If jet dont work, it dont work + return + if(!user)//Don't allow jet self using + return + if(!isturf(user.loc))//You can't use jet in nowhere or from mecha/closet + return + if(!(user.is_flying() || user.is_floating()) || user.buckled)//You don't want use jet in gravity or while buckled. + return + if(user.pulledby)//You don't must use jet if someone pull you + return + if(user.throwing)//You don't must use jet if you thrown + return + if(length(user.client.keys_held & user.client.movement_keys))//You use jet when press keys. yes. + allow_thrust(0.01, user) + +/obj/item/tank/jetpack/proc/pre_move_react(mob/user) + ion_trail.oldposition = get_turf(src) + +/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user) + if((num < 0.005 || air_contents.total_moles() < num)) + turn_off(user) + return + + var/datum/gas_mixture/removed = air_contents.remove(num) + if(removed.total_moles() < 0.005) + turn_off(user) + return + + var/turf/T = get_turf(user) + T.assume_air(removed) + ion_trail.generate_effect() + + return TRUE + +/obj/item/tank/jetpack/suicide_act(mob/user) + if (istype(user, /mob/living/carbon/human/)) + var/mob/living/carbon/human/H = user + H.forcesay("WHAT THE FUCK IS CARBON DIOXIDE?") + H.visible_message("[user] is suffocating [user.p_them()]self with [src]! It looks like [user.p_they()] didn't read what that jetpack says!") + return (OXYLOSS) + else + ..() + +/obj/item/tank/jetpack/improvised + name = "improvised jetpack" + desc = "A jetpack made from two air tanks, a fire extinguisher and some atmospherics equipment. It doesn't look like it can hold much." + icon_state = "jetpack-improvised" + item_state = "jetpack-sec" + volume = 20 //normal jetpacks have 70 volume + gas_type = null //it starts empty + full_speed = FALSE //moves at hardsuit jetpack speeds + +/obj/item/tank/jetpack/improvised/allow_thrust(num, mob/living/user) + if(!on) + return + if((num < 0.005 || air_contents.total_moles() < num)) + turn_off(user) + return + if(rand(0,250) == 0) + to_chat(user, "You feel your jetpack's engines cut out.") + turn_off(user) + return + + var/datum/gas_mixture/removed = air_contents.remove(num) + if(removed.total_moles() < 0.005) + turn_off(user) + return + + var/turf/T = get_turf(user) + T.assume_air(removed) + ion_trail.generate_effect() + + return TRUE + +/obj/item/tank/jetpack/void + name = "void jetpack (oxygen)" + desc = "It works well in a void." + icon_state = "jetpack-void" + item_state = "jetpack-void" + +/obj/item/tank/jetpack/oxygen + name = "jetpack (oxygen)" + desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas. Use with caution." + icon_state = "jetpack" + item_state = "jetpack" + +/obj/item/tank/jetpack/oxygen/harness + name = "jet harness (oxygen)" + desc = "A lightweight tactical harness, used by those who don't want to be weighed down by traditional jetpacks." + icon_state = "jetpack-mini" + item_state = "jetpack-mini" + volume = 40 + throw_range = 7 + w_class = WEIGHT_CLASS_NORMAL + +/obj/item/tank/jetpack/oxygen/captain + name = "captain's jetpack" + desc = "A compact, lightweight jetpack containing a high amount of compressed oxygen." + icon_state = "jetpack-captain" + item_state = "jetpack-captain" + w_class = WEIGHT_CLASS_NORMAL + volume = 90 + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF //steal objective items are hard to destroy. + +/obj/item/tank/jetpack/oxygen/security + name = "security jetpack (oxygen)" + desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas by security forces." + icon_state = "jetpack-sec" + item_state = "jetpack-sec" + + + +/obj/item/tank/jetpack/carbondioxide + name = "jetpack (carbon dioxide)" + desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals." + icon_state = "jetpack-black" + item_state = "jetpack-black" + distribute_pressure = 0 + gas_type = /datum/gas/carbon_dioxide + + +/obj/item/tank/jetpack/suit + name = "hardsuit jetpack upgrade" + desc = "A modular, compact set of thrusters designed to integrate with a hardsuit. It is fueled by a tank inserted into the suit's storage compartment." + icon_state = "jetpack-mining" + item_state = "jetpack-black" + w_class = WEIGHT_CLASS_NORMAL + actions_types = list(/datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization) + volume = 1 + slot_flags = null + gas_type = null + full_speed = FALSE + var/datum/gas_mixture/temp_air_contents + var/obj/item/tank/internals/tank = null + var/mob/living/carbon/human/cur_user + +/obj/item/tank/jetpack/suit/Initialize() + . = ..() + STOP_PROCESSING(SSobj, src) + temp_air_contents = air_contents + +/obj/item/tank/jetpack/suit/attack_self() + return + +/obj/item/tank/jetpack/suit/cycle(mob/user) + if(!istype(loc, /obj/item/clothing/suit/space/hardsuit)) + to_chat(user, "\The [src] must be connected to a hardsuit!") + return + + var/mob/living/carbon/human/H = user + if(!istype(H.s_store, /obj/item/tank/internals)) + to_chat(user, "You need a tank in your suit storage!") + return + ..() + +/obj/item/tank/jetpack/suit/turn_on(mob/user) + if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc) || loc.loc != user) + return + var/mob/living/carbon/human/H = user + tank = H.s_store + air_contents = tank.air_contents + START_PROCESSING(SSobj, src) + cur_user = user + ..() + +/obj/item/tank/jetpack/suit/turn_off(mob/user) + tank = null + air_contents = temp_air_contents + STOP_PROCESSING(SSobj, src) + cur_user = null + ..() + +/obj/item/tank/jetpack/suit/process() + if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc)) + turn_off(cur_user) + return + var/mob/living/carbon/human/H = loc.loc + if(!tank || tank != H.s_store) + turn_off(cur_user) + return + ..() + + +//Return a jetpack that the mob can use +//Back worn jetpacks, hardsuit internal packs, and so on. +//Used in Process_Spacemove() and wherever you want to check for/get a jetpack + +/mob/proc/get_jetpack() + return + +/mob/living/carbon/get_jetpack() + var/obj/item/tank/jetpack/J = back + if(istype(J)) + return J + +/mob/living/carbon/human/get_jetpack() + var/obj/item/tank/jetpack/J = ..() + if(!istype(J) && istype(wear_suit, /obj/item/clothing/suit/space/hardsuit)) + var/obj/item/clothing/suit/space/hardsuit/C = wear_suit + J = C.jetpack + return J diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index e5a093a35d8..4208ec3e300 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -90,10 +90,6 @@ return TRUE /obj/blob_act(obj/structure/blob/B) - if(isturf(loc)) - var/turf/T = loc - if(T.intact && level == 1) //the blob doesn't destroy thing below the floor - return take_damage(400, BRUTE, "melee", 0, get_dir(src, B)) /obj/proc/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, armor_penetration = 0) //used by attack_alien, attack_animal, and attack_slime @@ -201,10 +197,6 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e ///Called when the obj is exposed to fire. /obj/fire_act(exposed_temperature, exposed_volume) - if(isturf(loc)) - var/turf/T = loc - if(T.intact && level == 1) //fire can't damage things hidden below the floor. - return if(exposed_temperature && !(resistance_flags & FIRE_PROOF)) take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, "fire", 0) if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE) && !(resistance_flags & FIRE_PROOF)) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 4cfa3482006..06921570865 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -198,9 +198,6 @@ if(istype(M) && M.client && M.machine == src) src.attack_self(M) -/obj/proc/hide(h) - return - /obj/singularity_pull(S, current_size) ..() if(!anchored || current_size >= STAGE_FIVE) diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 4a2b6a65448..0496aa49ed3 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -13,7 +13,7 @@ FLOOR SAFES anchored = TRUE density = TRUE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT + interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT var/open = FALSE //is the safe open? var/tumbler_1_pos //the tumbler position- from 0 to 72 var/tumbler_1_open //the tumbler position to open at- 0 to 72 @@ -196,16 +196,10 @@ FLOOR SAFES name = "floor safe" icon_state = "floorsafe" density = FALSE - level = 1 //underfloor layer = LOW_OBJ_LAYER /obj/structure/safe/floor/Initialize(mapload) . = ..() - if(mapload) - var/turf/T = loc - hide(T.intact) - -/obj/structure/safe/floor/hide(var/intact) - invisibility = intact ? INVISIBILITY_MAXIMUM : 0 + AddElement(/datum/element/undertile) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index cb2c0d83539..2d3280c1c8b 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -634,7 +634,6 @@ smooth = SMOOTH_TRUE state = RWINDOW_SECURE canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile, /obj/structure/window/reinforced/tinted/fulltile, /obj/structure/window/plasma/fulltile, /obj/structure/window/plasma/reinforced/fulltile) - level = 3 glass_amount = 2 /obj/structure/window/reinforced/fulltile/unanchored @@ -649,7 +648,6 @@ flags_1 = PREVENT_CLICK_UNDER_1 smooth = SMOOTH_TRUE canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile, /obj/structure/window/reinforced/tinted/fulltile, /obj/structure/window/plasma/fulltile, /obj/structure/window/plasma/reinforced/fulltile) - level = 3 glass_amount = 2 /obj/structure/window/reinforced/fulltile/ice @@ -657,7 +655,6 @@ icon_state = "ice_window" max_integrity = 150 canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile, /obj/structure/window/reinforced/tinted/fulltile, /obj/structure/window/plasma/fulltile, /obj/structure/window/plasma/reinforced/fulltile) - level = 3 glass_amount = 2 /obj/structure/window/shuttle @@ -676,7 +673,6 @@ smooth = SMOOTH_TRUE canSmoothWith = null explosion_block = 3 - level = 3 glass_type = /obj/item/stack/sheet/titaniumglass glass_amount = 2 @@ -704,8 +700,7 @@ smooth = SMOOTH_TRUE canSmoothWith = null explosion_block = 3 - damage_deflection = 11 //The same as normal reinforced windows. - level = 3 + damage_deflection = 11 //The same as normal reinforced windows.3 glass_type = /obj/item/stack/sheet/plastitaniumglass glass_amount = 2 rad_insulation = RAD_HEAVY_INSULATION diff --git a/code/game/turfs/open/floor.dm b/code/game/turfs/open/floor.dm index bfdbead98a9..d3f69c33003 100644 --- a/code/game/turfs/open/floor.dm +++ b/code/game/turfs/open/floor.dm @@ -98,8 +98,7 @@ /turf/open/floor/is_shielded() for(var/obj/structure/A in contents) - if(A.level == 3) - return 1 + return 1 /turf/open/floor/blob_act(obj/structure/blob/B) return diff --git a/code/game/turfs/open/floor/fancy_floor.dm b/code/game/turfs/open/floor/fancy_floor.dm index e545e406566..3a82d17738e 100644 --- a/code/game/turfs/open/floor/fancy_floor.dm +++ b/code/game/turfs/open/floor/fancy_floor.dm @@ -111,6 +111,7 @@ icon = 'icons/turf/snow.dmi' desc = "Looks cold." icon_state = "snow" + broken_states = list("snow_dug") ore_type = /obj/item/stack/sheet/mineral/snow planetary_atmos = TRUE floor_tile = null diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm index 4668993ac78..694fb778d18 100644 --- a/code/game/turfs/open/floor/plating.dm +++ b/code/game/turfs/open/floor/plating.dm @@ -69,10 +69,9 @@ else if(istype(C, /obj/item/stack/tile)) if(!broken && !burnt) for(var/obj/O in src) - if(O.level == 1) //ex. pipes laid underneath a tile - for(var/M in O.buckled_mobs) - to_chat(user, "Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way.") - return + for(var/M in O.buckled_mobs) + to_chat(user, "Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way.") + return var/obj/item/stack/tile/W = C if(!W.use(1)) return diff --git a/code/game/turfs/open/floor/plating/asteroid.dm b/code/game/turfs/open/floor/plating/asteroid.dm index 599a2359557..76e96771211 100644 --- a/code/game/turfs/open/floor/plating/asteroid.dm +++ b/code/game/turfs/open/floor/plating/asteroid.dm @@ -327,6 +327,7 @@ GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/me environment_type = "snow" flags_1 = NONE planetary_atmos = TRUE + broken_states = list("snow_dug") burnt_states = list("snow_dug") bullet_sizzle = TRUE bullet_bounce_sound = null diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 89c6d6d22e5..00f0ff1bfed 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -1,6 +1,5 @@ /turf icon = 'icons/turf/floors.dmi' - level = 1 var/intact = 1 @@ -342,14 +341,12 @@ /turf/proc/levelupdate() for(var/obj/O in src) - if(O.level == 1 && (O.flags_1 & INITIALIZED_1)) - O.hide(src.intact) + if(O.flags_1 & INITIALIZED_1) + SEND_SIGNAL(O, COMSIG_OBJ_HIDE, intact) // override for space turfs, since they should never hide anything /turf/open/space/levelupdate() - for(var/obj/O in src) - if(O.level == 1 && (O.flags_1 & INITIALIZED_1)) - O.hide(0) + return // Removes all signs of lattice on the pos of the turf -Donkieyo /turf/proc/RemoveLattice() @@ -398,8 +395,6 @@ /turf/singularity_act() if(intact) for(var/obj/O in contents) //this is for deleting things like wires contained in the turf - if(O.level != 1) - continue if(O.invisibility == INVISIBILITY_MAXIMUM) O.singularity_act() ScrapeAway(flags = CHANGETURF_INHERIT_AIR) @@ -427,19 +422,10 @@ /turf/proc/is_shielded() /turf/contents_explosion(severity, target) - var/affecting_level - if(severity == 1) - affecting_level = 1 - else if(is_shielded()) - affecting_level = 3 - else if(intact) - affecting_level = 2 - else - affecting_level = 1 for(var/V in contents) var/atom/A = V - if(!QDELETED(A) && A.level >= affecting_level) + if(!QDELETED(A)) if(ismovable(A)) var/atom/movable/AM = A if(!AM.ex_check(explosion_id)) @@ -488,11 +474,9 @@ acid_type = /obj/effect/acid/alien var/has_acid_effect = FALSE for(var/obj/O in src) - if(intact && O.level == 1) //hidden under the floor - continue if(istype(O, acid_type)) var/obj/effect/acid/A = O - A.acid_level = min(A.level + acid_volume * acidpwr, 12000)//capping acid level to limit power of the acid + A.acid_level = min(acid_volume * acidpwr, 12000)//capping acid level to limit power of the acid has_acid_effect = 1 continue O.acid_act(acidpwr, acid_volume) diff --git a/code/modules/antagonists/blob/blob_mobs.dm b/code/modules/antagonists/blob/blob_mobs.dm index 93c18c56313..bb79a4e9eef 100644 --- a/code/modules/antagonists/blob/blob_mobs.dm +++ b/code/modules/antagonists/blob/blob_mobs.dm @@ -15,8 +15,12 @@ maxbodytemp = 360 unique_name = 1 a_intent = INTENT_HARM + see_in_dark = 8 + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + initial_language_holder = /datum/language_holder/empty var/mob/camera/blob/overmind = null var/obj/structure/blob/factory/factory = null + var/independent = FALSE /mob/living/simple_animal/hostile/blob/update_icons() if(overmind) @@ -24,6 +28,13 @@ else remove_atom_colour(FIXED_COLOUR_PRIORITY) +/mob/living/simple_animal/hostile/blob/Initialize() + . = ..() + if(!independent) //no pulling people deep into the blob + verbs -= /mob/living/verb/pulled + else + pass_flags &= ~PASSBLOB + /mob/living/simple_animal/hostile/blob/Destroy() if(overmind) overmind.blob_mobs -= src @@ -56,8 +67,11 @@ return 1 return ..() -/mob/living/simple_animal/hostile/blob/proc/blob_chat(msg) - var/spanned_message = say_quote(msg) +/mob/living/simple_animal/hostile/blob/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) + if(!overmind) + ..() + return + var/spanned_message = say_quote(message) var/rendered = "\[Blob Telepathy\] [real_name] [spanned_message]" for(var/M in GLOB.mob_list) if(isovermind(M) || istype(M, /mob/living/simple_animal/hostile/blob)) @@ -75,6 +89,7 @@ desc = "A floating, fragile spore." icon_state = "blobpod" icon_living = "blobpod" + health_doll_icon = "blobpod" health = 30 maxHealth = 30 verb_say = "psychically pulses" @@ -89,18 +104,20 @@ attack_verb_simple = "hit" attack_sound = 'sound/weapons/genhit1.ogg' movement_type = FLYING - del_on_death = 1 + del_on_death = TRUE deathmessage = "explodes into a cloud of gas!" + gold_core_spawnable = HOSTILE_SPAWN var/death_cloud_size = 1 //size of cloud produced from a dying spore var/mob/living/carbon/human/oldguy - var/is_zombie = 0 - gold_core_spawnable = HOSTILE_SPAWN + var/is_zombie = FALSE /mob/living/simple_animal/hostile/blob/blobspore/Initialize(mapload, obj/structure/blob/factory/linked_node) if(istype(linked_node)) factory = linked_node factory.spores += src . = ..() + if(linked_node.overmind && istype(linked_node.overmind.blobstrain, /datum/blobstrain/reagent/distributed_neurons) && !istype(src, /mob/living/simple_animal/hostile/blob/blobspore/weak)) + notify_ghosts("A controllable spore has been created in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Sentient Spore Created") /mob/living/simple_animal/hostile/blob/blobspore/Life() if(!is_zombie && isturf(src.loc)) @@ -111,6 +128,26 @@ if(factory && z != factory.z) death() ..() + +/mob/living/simple_animal/hostile/blob/blobspore/attack_ghost(mob/user) + . = ..() + if(.) + return + humanize_pod(user) + +/mob/living/simple_animal/hostile/blob/blobspore/proc/humanize_pod(mob/user) + if((!overmind || istype(src, /mob/living/simple_animal/hostile/blob/blobspore/weak) || !istype(overmind.blobstrain, /datum/blobstrain/reagent/distributed_neurons)) && !is_zombie) + return + if(key || stat) + return + var/pod_ask = alert("Become a blob spore?", "Are you bulbous enough?", "Yes", "No") + if(pod_ask == "No" || !src || QDELETED(src)) + return + if(key) + to_chat(user, "Someone else already took this spore!") + return + key = user.key + log_game("[key_name(src)] took control of [name].") /mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(mob/living/carbon/human/H) is_zombie = 1 @@ -134,6 +171,8 @@ oldguy = H update_icons() visible_message("The corpse of [H.name] suddenly rises!") + if(!key) + notify_ghosts("\A [src] has been created in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Blob Zombie Created") /mob/living/simple_animal/hostile/blob/blobspore/death(gibbed) // On death, create a small smoke of harmful gas (s-Acid) @@ -215,17 +254,7 @@ force_threshold = 10 pressure_resistance = 50 mob_size = MOB_SIZE_LARGE - see_in_dark = 8 - lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE hud_type = /datum/hud/blobbernaut - var/independent = FALSE - -/mob/living/simple_animal/hostile/blob/blobbernaut/Initialize() - . = ..() - if(!independent) //no pulling people deep into the blob - verbs -= /mob/living/verb/pulled - else - pass_flags &= ~PASSBLOB /mob/living/simple_animal/hostile/blob/blobbernaut/Life() if(..()) diff --git a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm new file mode 100644 index 00000000000..27edb0f205f --- /dev/null +++ b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm @@ -0,0 +1,39 @@ +//kills unconscious targets and turns them into blob zombies, produces fragile spores when killed. Spore produced by factories are sentient. +/datum/blobstrain/reagent/distributed_neurons + name = "Distributed Neurons" + description = "will do very low toxin damage and turns unconscious targets into blob zombies." + effectdesc = "will also produce fragile spores when killed. Spores produced by factories are sentient." + shortdesc = "will do very low toxin damage and will turn unconscious targets into blob zombies for additional resources(for your overmind). Spores produced by factories are sentient." + analyzerdescdamage = "Does very low toxin damage and kills unconscious humans, turning them into blob zombies." + analyzerdesceffect = "Produces spores when killed. Spores produced by factories are sentient." + color = "#E88D5D" + complementary_color = "#823ABB" + message_living = ", and you feel tired" + reagent = /datum/reagent/blob/distributed_neurons + +/datum/blobstrain/reagent/distributed_neurons/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag) + if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && damage <= 20 && B.obj_integrity - damage <= 0 && prob(15)) //if the cause isn't fire or a bomb, the damage is less than 21, we're going to die from that damage, 15% chance of a shitty spore. + B.visible_message("A spore floats free of the blob!") + var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(B.loc) + BS.overmind = B.overmind + BS.update_icons() + B.overmind.blob_mobs.Add(BS) + return ..() + +/datum/reagent/blob/distributed_neurons + name = "Distributed Neurons" + color = "#E88D5D" + +/datum/reagent/blob/distributed_neurons/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) + reac_volume = ..() + M.apply_damage(0.6*reac_volume, TOX) + if(O && ishuman(M) && M.stat == UNCONSCIOUS) + M.death() //sleeping in a fight? bad plan. + var/points = rand(5, 10) + var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(get_turf(M)) + BS.overmind = O + BS.update_icons() + O.blob_mobs.Add(BS) + BS.Zombify(M) + O.add_points(points) + to_chat(O, "Gained [points] resources from the zombification of [M].") diff --git a/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm b/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm deleted file mode 100644 index b2bb9d51157..00000000000 --- a/code/modules/antagonists/blob/blobstrains/zombifying_pods.dm +++ /dev/null @@ -1,46 +0,0 @@ -//kills sleeping targets and turns them into blob zombies, produces fragile spores when killed or on expanding -/datum/blobstrain/reagent/zombifying_pods - name = "Zombifying Pods" - description = "will do very low toxin damage and harvest sleeping targets for additional resources and a blob zombie." - effectdesc = "will also produce fragile spores when killed and on expanding." - shortdesc = "will do very low toxin damage and harvest sleeping targets for additional resources(for your overmind) and a blob zombie." - analyzerdescdamage = "Does very low toxin damage and kills unconscious humans, turning them into blob zombies." - analyzerdesceffect = "Produces spores when expanding and when killed." - color = "#E88D5D" - complementary_color = "#823ABB" - message_living = ", and you feel tired" - reagent = /datum/reagent/blob/zombifying_pods - -/datum/blobstrain/reagent/zombifying_pods/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag) - if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && damage <= 20 && B.obj_integrity - damage <= 0 && prob(30)) //if the cause isn't fire or a bomb, the damage is less than 21, we're going to die from that damage, 20% chance of a shitty spore. - B.visible_message("A spore floats free of the blob!") - var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(B.loc) - BS.overmind = B.overmind - BS.update_icons() - B.overmind.blob_mobs.Add(BS) - return ..() - -/datum/blobstrain/reagent/zombifying_pods/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O) - if(prob(10)) - var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(T) - BS.overmind = B.overmind - BS.update_icons() - newB.overmind.blob_mobs.Add(BS) - -/datum/reagent/blob/zombifying_pods - name = "Zombifying Pods" - color = "#E88D5D" - -/datum/reagent/blob/zombifying_pods/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) - reac_volume = ..() - M.apply_damage(0.6*reac_volume, TOX) - if(O && ishuman(M) && M.stat == UNCONSCIOUS) - M.death() //sleeping in a fight? bad plan. - var/points = rand(5, 10) - var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(get_turf(M)) - BS.overmind = O - BS.update_icons() - O.blob_mobs.Add(BS) - BS.Zombify(M) - O.add_points(points) - to_chat(O, "Gained [points] resources from the zombification of [M].") diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index e2567e091cc..a2b38e0b1be 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -39,6 +39,9 @@ GLOBAL_LIST_EMPTY(blob_nodes) var/blobwincount = 400 var/victory_in_progress = FALSE var/rerolling = FALSE + var/announcement_size = 75 + var/announcement_time + var/has_announced = FALSE /mob/camera/blob/Initialize(mapload, starting_points = 60) validate_location() @@ -56,6 +59,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) if(blob_core) blob_core.update_icon() SSshuttle.registerHostileEnvironment(src) + announcement_time = world.time + 6000 . = ..() START_PROCESSING(SSobj, src) @@ -117,6 +121,10 @@ GLOBAL_LIST_EMPTY(blob_nodes) if(!victory_in_progress && max_count < blobs_legit.len) max_count = blobs_legit.len + + if((world.time >= announcement_time || blobs_legit.len >= announcement_size) && !has_announced) + priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg') + has_announced = TRUE /mob/camera/blob/proc/victory() sound_to_playing_players('sound/machines/alarm.ogg') diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index 794819db9b8..2289e163052 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -318,7 +318,7 @@ if(!surrounding_turfs.len) return for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in blob_mobs) - if(isturf(BS.loc) && get_dist(BS, T) <= 35) + if(isturf(BS.loc) && get_dist(BS, T) <= 35 && !BS.key) BS.LoseTarget() BS.Goto(pick(surrounding_turfs), BS.move_to_delay) diff --git a/code/modules/antagonists/blob/structures/core.dm b/code/modules/antagonists/blob/structures/core.dm index c2ae02c5ce3..0dc9d8b43df 100644 --- a/code/modules/antagonists/blob/structures/core.dm +++ b/code/modules/antagonists/blob/structures/core.dm @@ -8,6 +8,7 @@ explosion_block = 6 point_return = -1 health_regen = 0 //we regen in Life() instead of when pulsed + resistance_flags = LAVA_PROOF /obj/structure/blob/core/Initialize(mapload, client/new_overmind = null, placed = 0) GLOB.blob_cores += src @@ -18,12 +19,8 @@ return INITIALIZE_HINT_QDEL if(overmind) update_icon() - addtimer(CALLBACK(src, .proc/generate_announcement), 1800) . = ..() -/obj/structure/blob/core/proc/generate_announcement() - priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg') - /obj/structure/blob/core/scannerreport() return "Directs the blob's expansion, gradually expands, and sustains nearby blob spores and blobbernauts." diff --git a/code/modules/antagonists/blob/structures/factory.dm b/code/modules/antagonists/blob/structures/factory.dm index 3d955036b01..756d1b03fab 100644 --- a/code/modules/antagonists/blob/structures/factory.dm +++ b/code/modules/antagonists/blob/structures/factory.dm @@ -6,6 +6,7 @@ max_integrity = 200 health_regen = 1 point_return = 25 + resistance_flags = LAVA_PROOF var/list/spores = list() var/mob/living/simple_animal/hostile/blob/blobbernaut/naut = null var/max_spores = 3 diff --git a/code/modules/antagonists/blob/structures/node.dm b/code/modules/antagonists/blob/structures/node.dm index 14fbc741c0b..8a8645c1518 100644 --- a/code/modules/antagonists/blob/structures/node.dm +++ b/code/modules/antagonists/blob/structures/node.dm @@ -7,6 +7,7 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 65, "acid" = 90) health_regen = 3 point_return = 25 + resistance_flags = LAVA_PROOF /obj/structure/blob/node/Initialize() diff --git a/code/modules/antagonists/blob/structures/resource.dm b/code/modules/antagonists/blob/structures/resource.dm index 5024d0984c1..81eda7f4edd 100644 --- a/code/modules/antagonists/blob/structures/resource.dm +++ b/code/modules/antagonists/blob/structures/resource.dm @@ -5,6 +5,7 @@ desc = "A thin spire of slightly swaying tendrils." max_integrity = 60 point_return = 15 + resistance_flags = LAVA_PROOF var/resource_delay = 0 /obj/structure/blob/resource/scannerreport() diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm index 4432aa21fa0..8844c5844c3 100644 --- a/code/modules/antagonists/changeling/powers/strained_muscles.dm +++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm @@ -18,7 +18,7 @@ if(active) to_chat(user, "Our muscles tense and strengthen.") else - user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES) + user.remove_movespeed_modifier(/datum/movespeed_modifier/strained_muscles) to_chat(user, "Our muscles relax.") if(stacks >= 10) to_chat(user, "We collapse in exhaustion.") @@ -31,12 +31,12 @@ /datum/action/changeling/strained_muscles/proc/muscle_loop(mob/living/carbon/user) while(active) - user.add_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING)) + user.add_movespeed_modifier(/datum/movespeed_modifier/strained_muscles) if(user.stat != CONSCIOUS || user.staminaloss >= 90) active = !active to_chat(user, "Our muscles relax without the energy to strengthen them.") user.Paralyze(40) - user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES) + user.remove_movespeed_modifier(/datum/movespeed_modifier/strained_muscles) break stacks++ diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm index db65cc40a4d..9a875e3076c 100644 --- a/code/modules/antagonists/devil/true_devil/_true_devil.dm +++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm @@ -16,7 +16,6 @@ pass_flags = 0 sight = (SEE_TURFS | SEE_OBJS) status_flags = CANPUSH - spacewalk = TRUE mob_size = MOB_SIZE_LARGE held_items = list(null, null) bodyparts = list(/obj/item/bodypart/chest/devil, /obj/item/bodypart/head/devil, /obj/item/bodypart/l_arm/devil, @@ -30,7 +29,8 @@ create_bodyparts() //initialize bodyparts create_internal_organs() grant_all_languages() - ..() + . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) /mob/living/carbon/true_devil/create_internal_organs() internal_organs += new /obj/item/organ/brain diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm index caa7feafa4d..c3035064f11 100644 --- a/code/modules/antagonists/ert/ert.dm +++ b/code/modules/antagonists/ert/ert.dm @@ -214,6 +214,7 @@ /datum/antagonist/ert/families/greet() to_chat(owner, "You are the [name].") + to_chat(owner, "You are NOT a Nanotrasen Employee. You work for the local government.") var/missiondesc = "After an uptick in gang violence on [station_name()], you are responding to emergency calls from the station for immediate SSC Police assistance!\n" missiondesc += "
Your Mission:" @@ -253,6 +254,7 @@ /datum/antagonist/ert/families/undercover_cop/greet() to_chat(owner, "You are the [name].") + to_chat(owner, "You are NOT a Nanotrasen Employee. You work for the local government.") var/missiondesc = "You are an undercover police officer on board [station_name()]. You've been sent here by the Spinward Stellar Coalition because of suspected abusive behavior by the security department, and to keep tabs on a potential criminal organization operation." missiondesc += "
Your Mission:" diff --git a/code/modules/antagonists/gang/gang.dm b/code/modules/antagonists/gang/gang.dm index fbeb95fc878..1d87aae8ee1 100644 --- a/code/modules/antagonists/gang/gang.dm +++ b/code/modules/antagonists/gang/gang.dm @@ -58,14 +58,15 @@ free_clothes = list(/obj/item/clothing/suit/jacket/letterman_red, /obj/item/clothing/under/color/red, /obj/item/toy/crayon/spraycan) - gang_objective = "The Spinward Stellar Coalition police intend to interfere with our operations, by sending an undercover cop. Find him and eliminate him." + gang_objective = "The Spinward Stellar Coalition police intend to interfere with our operations, by sending undercover cops. Find them and eliminate them all." antag_hud_name = "Triad" /datum/antagonist/gang/red/check_gang_objective() var/datum/game_mode/gang/F = SSticker.mode - var/mob/living/carbon/human/H = F.undercover_cop.current - if(considered_alive(H)) - return FALSE + for(var/datum/mind/M in F.undercover_cops) + var/mob/living/carbon/human/H = M.current + if(considered_alive(H)) + return FALSE return TRUE /datum/antagonist/gang/purple @@ -380,7 +381,7 @@ points += points_to_adjust /datum/team/gang/roundend_report() - return "

" + return /datum/action/cooldown/spawn_induction_package name = "Create Induction Package" @@ -411,6 +412,8 @@ for(var/datum/mind/gangers in TT.members) if(ishuman(gangers.current) && gangers.current.client && !gangers.current.stat) alive_gangsters++ + if(!alive_gangsters || TT.members.len <= 1) // Dead or inactive gangs don't count towards the cap. + continue if(TT != my_gang_datum.my_gang) if(alive_gangsters < lowest_gang_count) lowest_gang_count = alive_gangsters diff --git a/code/modules/antagonists/gang/outfits.dm b/code/modules/antagonists/gang/outfits.dm index e08bdbfa746..9a58a386cda 100644 --- a/code/modules/antagonists/gang/outfits.dm +++ b/code/modules/antagonists/gang/outfits.dm @@ -13,6 +13,7 @@ name = "Families: Beat Cop" uniform = /obj/item/clothing/under/rank/security/officer/beatcop + back = /obj/item/storage/backpack/duffelbag/cops suit = null shoes = /obj/item/clothing/shoes/combat/swat gloves = null @@ -20,32 +21,54 @@ ears = /obj/item/radio/headset/headset_sec mask = null head = /obj/item/clothing/head/spacepolice - belt = /obj/item/gun/energy/e_gun/mini + belt = /obj/item/gun/ballistic/automatic/pistol/m1911 r_pocket = /obj/item/lighter l_pocket = /obj/item/restraints/handcuffs back = /obj/item/storage/backpack/satchel/leather id = /obj/item/card/id + backpack_contents = list(/obj/item/storage/box/handcuffs = 1, + /obj/item/storage/box/teargas = 1, + /obj/item/storage/box/flashbangs = 1, + /obj/item/shield/riot/tele = 1, + /obj/item/ammo_box/magazine/m45 = 3, + /obj/item/ammo_box/c45 = 2) /datum/outfit/families_police/beatcop/armored name = "Families: Armored Beat Cop" suit = /obj/item/clothing/suit/armor/vest/blueshirt head = /obj/item/clothing/head/helmet/blueshirt - belt = /obj/item/gun/energy/e_gun + belt = /obj/item/gun/ballistic/shotgun/automatic/combat + backpack_contents = list(/obj/item/storage/box/handcuffs = 1, + /obj/item/storage/box/teargas = 1, + /obj/item/storage/box/flashbangs = 1, + /obj/item/shield/riot/tele = 1, + /obj/item/storage/box/lethalshot = 2) /datum/outfit/families_police/beatcop/swat name = "Families: SWAT Beat Cop" suit = /obj/item/clothing/suit/armor/riot head = /obj/item/clothing/head/helmet/riot gloves = /obj/item/clothing/gloves/combat - belt = /obj/item/gun/energy/e_gun + belt = /obj/item/gun/ballistic/shotgun/automatic/combat + backpack_contents = list(/obj/item/storage/box/handcuffs = 1, + /obj/item/storage/box/teargas = 1, + /obj/item/storage/box/flashbangs = 1, + /obj/item/shield/riot/tele = 1, + /obj/item/storage/box/lethalshot = 2) /datum/outfit/families_police/beatcop/fbi name = "Families: Space FBI Officer" suit = /obj/item/clothing/suit/armor/laserproof head = /obj/item/clothing/head/helmet/riot - belt = /obj/item/gun/energy/laser/scatter + belt = /obj/item/gun/ballistic/automatic/proto/unrestricted gloves = /obj/item/clothing/gloves/combat + backpack_contents = list(/obj/item/storage/box/handcuffs = 1, + /obj/item/storage/box/teargas = 1, + /obj/item/storage/box/flashbangs = 1, + /obj/item/shield/riot/tele = 1, + /obj/item/ammo_box/magazine/smgm9mm = 3, + /obj/item/ammo_box/c9mm = 2) /datum/outfit/families_police/beatcop/military name = "Families: Space Military" @@ -54,3 +77,7 @@ head = /obj/item/clothing/head/beret/durathread belt = /obj/item/gun/energy/laser/scatter gloves = /obj/item/clothing/gloves/combat + backpack_contents = list(/obj/item/storage/box/handcuffs = 1, + /obj/item/storage/box/teargas = 1, + /obj/item/storage/box/flashbangs = 1, + /obj/item/shield/riot/tele = 1) diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index 01c49aaf7b5..7d9ce5900e8 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -23,7 +23,6 @@ maxHealth = INFINITY layer = GHOST_LAYER healable = FALSE - spacewalk = TRUE sight = SEE_SELF throwforce = 0 @@ -73,6 +72,7 @@ /mob/living/simple_animal/revenant/Initialize(mapload) . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null)) AddSpell(new /obj/effect/proc_holder/spell/targeted/telepathy/revenant(null)) AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null)) diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index 1cd3053eb2f..42b08ae29c6 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -67,9 +67,8 @@ /mob/living/simple_animal/slaughter/phasein() . = ..() - add_movespeed_modifier(MOVESPEED_ID_SLAUGHTER, update=TRUE, priority=100, multiplicative_slowdown=-1) - addtimer(CALLBACK(src, .proc/remove_movespeed_modifier, MOVESPEED_ID_SLAUGHTER, TRUE), 6 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) - + add_movespeed_modifier(/datum/movespeed_modifier/slaughter) + addtimer(CALLBACK(src, .proc/remove_movespeed_modifier, /datum/movespeed_modifier/slaughter), 6 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) //The loot from killing a slaughter demon - can be consumed to allow the user to blood crawl /obj/item/organ/heart/demon diff --git a/code/modules/atmospherics/gasmixtures/gas_types.dm b/code/modules/atmospherics/gasmixtures/gas_types.dm index c363030c465..a6ba7df0ac4 100644 --- a/code/modules/atmospherics/gasmixtures/gas_types.dm +++ b/code/modules/atmospherics/gasmixtures/gas_types.dm @@ -160,6 +160,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(/datum/gas/oxygen, /datum/g anchored = TRUE // should only appear in vis_contents, but to be safe layer = FLY_LAYER appearance_flags = TILE_BOUND + vis_flags = NONE /obj/effect/overlay/gas/New(state, alph) . = ..() diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index c670c07798f..350f9152d41 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -26,6 +26,9 @@ var/piping_layer = PIPING_LAYER_DEFAULT var/pipe_flags = NONE + ///This only works on pipes, because they have 1000 subtypes wich need to be visible and invisible under tiles, so we track this here + var/hide = TRUE + var/static/list/iconsetids = list() var/static/list/pipeimages = list() @@ -185,11 +188,6 @@ if(!can_unwrench(user)) return ..() - var/turf/T = get_turf(src) - if (level==1 && isturf(T) && T.intact) - to_chat(user, "You must remove the plating first!") - return TRUE - var/datum/gas_mixture/int_air = return_air() var/datum/gas_mixture/env_air = loc.return_air() add_fingerprint(user) @@ -266,8 +264,6 @@ add_atom_colour(obj_color, FIXED_COLOUR_PRIORITY) pipe_color = obj_color setPipingLayer(set_layer) - var/turf/T = get_turf(src) - level = T.intact ? 2 : 1 atmosinit() var/list/nodes = pipeline_expansion() for(var/obj/machinery/atmospherics/A in nodes) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm b/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm index 6167d7ea015..c4b14274e03 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm @@ -13,9 +13,5 @@ if(EAST, WEST) initialize_directions = EAST|WEST -/obj/machinery/atmospherics/components/binary/hide(intact) - update_icon() - ..() - /obj/machinery/atmospherics/components/binary/getNodeConnects() return list(turn(dir, 180), dir) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm index 4bba6e94c04..1310b39b16a 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm @@ -14,7 +14,8 @@ name = "dual-port air vent" desc = "Has a valve and pump attached to it. There are two ports." - level = 1 + hide = TRUE + var/frequency = 0 var/id = null var/datum/radio_frequency/radio_connection diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index eee2f383561..aab9f3f464c 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -2,8 +2,10 @@ // On top of that, now people can add component-speciic procs/vars if they want! /obj/machinery/atmospherics/components + hide = FALSE + var/welded = FALSE //Used on pumps and scrubbers - var/showpipe = FALSE + var/showpipe = TRUE var/shift_underlay_only = TRUE //Layering only shifts underlay? var/list/datum/pipeline/parents @@ -20,26 +22,30 @@ A.volume = 200 airs[i] = A +/obj/machinery/atmospherics/components/Initialize() + . = ..() + + if(hide) + RegisterSignal(src, COMSIG_OBJ_HIDE, .proc/hide_pipe) + // Iconnery /obj/machinery/atmospherics/components/proc/update_icon_nopipes() return +/obj/machinery/atmospherics/components/proc/hide_pipe(datum/source, covered) + showpipe = !covered + update_icon() + /obj/machinery/atmospherics/components/update_icon() update_icon_nopipes() underlays.Cut() - var/turf/T = loc - if(level == 2 || (istype(T) && !T.intact)) - showpipe = TRUE - plane = GAME_PLANE - else - showpipe = FALSE - plane = FLOOR_PLANE + plane = showpipe ? GAME_PLANE : FLOOR_PLANE if(!showpipe) - return //no need to update the pipes if they aren't showing + return var/connected = 0 //Direction bitset diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm index 170b2179e52..f495583884f 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm @@ -7,6 +7,7 @@ use_power = IDLE_POWER_USE can_unwrench = TRUE shift_underlay_only = FALSE + hide = TRUE resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF //really helpful in building gas chambers for xenomorphs @@ -18,7 +19,6 @@ var/id = null var/datum/radio_frequency/radio_connection - level = 1 layer = GAS_SCRUBBER_LAYER pipe_state = "injector" diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm index a113484d20b..541550e1053 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm @@ -3,9 +3,9 @@ name = "passive vent" desc = "It is an open vent." - can_unwrench = TRUE - level = 1 + can_unwrench = TRUE + hide = TRUE layer = GAS_SCRUBBER_LAYER pipe_state = "pvent" diff --git a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm index 03ae98bb6a6..6d02ab696e6 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm @@ -7,8 +7,8 @@ can_unwrench = TRUE use_power = NO_POWER_USE - level = 0 layer = GAS_FILTER_LAYER + hide = TRUE pipe_flags = PIPING_ONE_PER_TURF pipe_state = "connector" @@ -51,7 +51,7 @@ icon_state = "connector_map-3" /obj/machinery/atmospherics/components/unary/portables_connector/visible - level = 2 + hide = FALSE /obj/machinery/atmospherics/components/unary/portables_connector/visible/layer1 piping_layer = 1 diff --git a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm index 40c2f0f5a8a..1d18dc83492 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm @@ -15,10 +15,6 @@ ..() update_icon() -/obj/machinery/atmospherics/components/unary/hide(intact) - update_icon() - ..(intact) - /obj/machinery/atmospherics/components/unary/proc/assign_uid_vents() uid = num2text(gl_uid++) return uid diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm index ec64bd45fd7..680dfd16a62 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -14,8 +14,8 @@ use_power = IDLE_POWER_USE can_unwrench = TRUE welded = FALSE - level = 1 layer = GAS_SCRUBBER_LAYER + hide = TRUE var/id_tag = null var/pump_direction = RELEASING diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index cb4e3ebc969..0905eb361d4 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -11,8 +11,8 @@ active_power_usage = 60 can_unwrench = TRUE welded = FALSE - level = 1 layer = GAS_SCRUBBER_LAYER + hide = TRUE var/id_tag = null var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm index 9a10a605038..239258a4058 100644 --- a/code/modules/atmospherics/machinery/other/meter.dm +++ b/code/modules/atmospherics/machinery/other/meter.dm @@ -44,8 +44,6 @@ for(var/obj/machinery/atmospherics/pipe/pipe in loc) if(pipe.piping_layer == target_layer) candidate = pipe - if(pipe.level == 2) - break if(candidate) target = candidate setAttachLayer(candidate.piping_layer) diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index 6ffffb9c453..2fd2da1a24a 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -1,5 +1,4 @@ /obj/machinery/atmospherics/pipe/heat_exchanging - level = 2 var/minimum_temperature_difference = 20 var/thermal_conductivity = WINDOW_HEAT_TRANSFER_COEFFICIENT color = "#404040" @@ -7,8 +6,11 @@ var/icon_temperature = T20C //stop small changes in temperature causing icon refresh resistance_flags = LAVA_PROOF | FIRE_PROOF + hide = FALSE + /obj/machinery/atmospherics/pipe/heat_exchanging/Initialize() . = ..() + add_atom_colour("#404040", FIXED_COLOUR_PRIORITY) /obj/machinery/atmospherics/pipe/heat_exchanging/isConnectable(obj/machinery/atmospherics/pipe/heat_exchanging/target, given_layer, HE_type_check = TRUE) @@ -16,9 +18,6 @@ return FALSE . = ..() -/obj/machinery/atmospherics/pipe/heat_exchanging/hide() - return - /obj/machinery/atmospherics/pipe/heat_exchanging/process_atmos() var/environment_temperature = 0 var/datum/gas_mixture/pipe_air = return_air() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm index ad5f65f9d3d..531c5e113a8 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/junction.dm @@ -33,8 +33,6 @@ /obj/machinery/atmospherics/pipe/heat_exchanging/junction/update_icon() icon_state = "pipe[nodes[1] ? "1" : "0"][nodes[2] ? "1" : "0"]-[piping_layer]" update_layer() - update_alpha() - /obj/machinery/atmospherics/pipe/heat_exchanging/junction/layer1 piping_layer = 1 diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm index 6d4b824fb14..3eed910ecdb 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold.dm @@ -38,8 +38,6 @@ add_overlay( getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) ) update_layer() - update_alpha() - /obj/machinery/atmospherics/pipe/heat_exchanging/manifold/layer1 piping_layer = 1 diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm index 88086e44e23..a8425629c9a 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/manifold4w.dm @@ -36,8 +36,6 @@ add_overlay( getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) ) update_layer() - update_alpha() - /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w/layer1 piping_layer = 1 diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/simple.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/simple.dm index e3ed1a6c37a..c5304c3416e 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/simple.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/simple.dm @@ -27,8 +27,6 @@ /obj/machinery/atmospherics/pipe/heat_exchanging/simple/update_icon() icon_state = "pipe[nodes[1] ? "1" : "0"][nodes[2] ? "1" : "0"]-[piping_layer]" update_layer() - update_alpha() - /obj/machinery/atmospherics/pipe/heat_exchanging/simple/layer1 piping_layer = 1 diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm index 1d1f7ccac3b..1aff2b3af16 100644 --- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm +++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm @@ -46,8 +46,6 @@ for(var/node in back_nodes) add_attached_images(node) - update_alpha() - /obj/machinery/atmospherics/pipe/layer_manifold/proc/add_attached_images(obj/machinery/atmospherics/A) if(!A) return @@ -99,8 +97,6 @@ /obj/machinery/atmospherics/pipe/layer_manifold/atmosinit() normalize_cardinal_directions() findAllConnections() - var/turf/T = loc // hide if turf is not intact - hide(T.intact) /obj/machinery/atmospherics/pipe/layer_manifold/setPipingLayer() piping_layer = PIPING_LAYER_DEFAULT @@ -134,5 +130,4 @@ to_chat(user, "You align yourself with the [user.ventcrawl_layer]\th output.") /obj/machinery/atmospherics/pipe/layer_manifold/visible - level = PIPE_VISIBLE_LEVEL layer = GAS_PIPE_VISIBLE_LAYER diff --git a/code/modules/atmospherics/machinery/pipes/manifold.dm b/code/modules/atmospherics/machinery/pipes/manifold.dm index 8c487dc8dce..fb458aee7cb 100644 --- a/code/modules/atmospherics/machinery/pipes/manifold.dm +++ b/code/modules/atmospherics/machinery/pipes/manifold.dm @@ -43,4 +43,3 @@ add_overlay( getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) ) update_layer() - update_alpha() diff --git a/code/modules/atmospherics/machinery/pipes/manifold4w.dm b/code/modules/atmospherics/machinery/pipes/manifold4w.dm index 4d98cbc2f59..b80e6eaeb4b 100644 --- a/code/modules/atmospherics/machinery/pipes/manifold4w.dm +++ b/code/modules/atmospherics/machinery/pipes/manifold4w.dm @@ -37,4 +37,3 @@ add_overlay( getpipeimage(icon, "pipe-[piping_layer]", get_dir(src, nodes[i])) ) update_layer() - update_alpha() diff --git a/code/modules/atmospherics/machinery/pipes/mapping.dm b/code/modules/atmospherics/machinery/pipes/mapping.dm index c868d377ea4..4b7e4da9da7 100644 --- a/code/modules/atmospherics/machinery/pipes/mapping.dm +++ b/code/modules/atmospherics/machinery/pipes/mapping.dm @@ -6,7 +6,7 @@ color = Color; \ } \ ##Fulltype/visible { \ - level = PIPE_VISIBLE_LEVEL; \ + hide = FALSE; \ layer = GAS_PIPE_VISIBLE_LAYER; \ } \ ##Fulltype/visible/layer1 { \ @@ -18,7 +18,7 @@ icon_state = Iconbase + "-3"; \ } \ ##Fulltype/hidden { \ - level = PIPE_HIDDEN_LEVEL; \ + hide = TRUE; \ } \ ##Fulltype/hidden/layer1 { \ piping_layer = 1; \ diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index 2ebf1cfdff7..63157b55adc 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -3,8 +3,6 @@ var/datum/gas_mixture/air_temporary //used when reconstructing a pipeline that broke var/volume = 0 - level = 1 - use_power = NO_POWER_USE can_unwrench = 1 var/datum/pipeline/parent = null @@ -19,6 +17,13 @@ volume = 35 * device_type ..() +///I have no idea why there's a new and at this point I'm too afraid to ask +/obj/machinery/atmospherics/pipe/Initialize(mapload) + . = ..() + + if(hide) + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) //if changing this, change the subtypes RemoveElements too, because thats how bespoke works + /obj/machinery/atmospherics/pipe/nullifyNode(i) var/obj/machinery/atmospherics/oldN = nodes[i] ..() @@ -33,16 +38,6 @@ parent = new parent.build_pipeline(src) -/obj/machinery/atmospherics/pipe/atmosinit() - var/turf/T = loc // hide if turf is not intact - hide(T.intact) - ..() - -/obj/machinery/atmospherics/pipe/hide(i) - if(level == 1 && isturf(loc)) - invisibility = i ? INVISIBILITY_MAXIMUM : 0 - update_icon() - /obj/machinery/atmospherics/pipe/proc/releaseAirToTurf() if(air_temporary) var/turf/T = loc @@ -86,13 +81,6 @@ qdel(meter) . = ..() -/obj/machinery/atmospherics/pipe/update_icon() - . = ..() - update_alpha() - -/obj/machinery/atmospherics/pipe/proc/update_alpha() - alpha = invisibility ? 64 : 255 - /obj/machinery/atmospherics/pipe/proc/update_node_icon() for(var/i in 1 to device_type) if(nodes[i]) diff --git a/code/modules/atmospherics/machinery/pipes/simple.dm b/code/modules/atmospherics/machinery/pipes/simple.dm index 40afb39ec1b..0450c7eebcb 100644 --- a/code/modules/atmospherics/machinery/pipes/simple.dm +++ b/code/modules/atmospherics/machinery/pipes/simple.dm @@ -30,4 +30,3 @@ /obj/machinery/atmospherics/pipe/simple/update_icon() icon_state = "pipe[nodes[1] ? "1" : "0"][nodes[2] ? "1" : "0"]-[piping_layer]" update_layer() - update_alpha() diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm index e69129b54dd..a5a8cf30b92 100644 --- a/code/modules/awaymissions/mission_code/Academy.dm +++ b/code/modules/awaymissions/mission_code/Academy.dm @@ -252,7 +252,7 @@ if(6) //Cut speed T.visible_message("[user] starts moving slower!") - user.add_movespeed_modifier(MOVESPEED_ID_DIE_OF_FATE, update=TRUE, priority=100, multiplicative_slowdown=1) + user.add_movespeed_modifier(/datum/movespeed_modifier/die_of_fate) if(7) //Throw T.visible_message("Unseen forces throw [user]!") diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index 8d7698e0bce..9aa8f8ca7fe 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -2538,3 +2538,27 @@ /obj/item/stock_parts/subspace/ansible ) crate_name = "crate" + +///Special supply crate that generates random syndicate gear up to a determined TC value +/datum/supply_pack/misc/syndicate + name = "Assorted Syndicate Gear" + desc = "Contains a random assortment of syndicate gear." + special = TRUE ///Cannot be ordered via cargo + contains = list() + crate_name = "syndicate gear crate" + crate_type = /obj/structure/closet/crate + var/crate_value = 30 ///Total TC worth of contained uplink items + +///Generate assorted uplink items, taking into account the same surplus modifiers used for surplus crates +/datum/supply_pack/misc/syndicate/fill(obj/structure/closet/crate/C) + var/list/uplink_items = get_uplink_items(SSticker.mode) + while(crate_value) + var/category = pick(uplink_items) + var/item = pick(uplink_items[category]) + var/datum/uplink_item/I = uplink_items[category][item] + if(!I.surplus || prob(100 - I.surplus)) + continue + if(crate_value < I.cost) + continue + crate_value -= I.cost + new I.item(C) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 823a2c16ad9..231d8b052f6 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -213,7 +213,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car buttons_locked = sanitize_integer(buttons_locked, 0, 1, initial(buttons_locked)) windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing)) default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot)) - toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) + toggles = sanitize_integer(toggles, 0, (2**24)-1, initial(toggles)) clientfps = sanitize_integer(clientfps, 0, 1000, 0) parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null) ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion)) diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index f63415c25da..c65cdbf31df 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -464,7 +464,7 @@ permeability_coefficient = 0.01 flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH - var/vchange = 1 + var/voice_change = 1 ///This determines if the voice changer is on or off. var/datum/action/item_action/chameleon/change/chameleon_action @@ -487,15 +487,15 @@ chameleon_action.emp_randomise(INFINITY) /obj/item/clothing/mask/chameleon/attack_self(mob/user) - vchange = !vchange - to_chat(user, "The voice changer is now [vchange ? "on" : "off"]!") + voice_change = !voice_change + to_chat(user, "The voice changer is now [voice_change ? "on" : "off"]!") /obj/item/clothing/mask/chameleon/drone //Same as the drone chameleon hat, undroppable and no protection armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) // Can drones use the voice changer part? Let's not find out. - vchange = 0 + voice_change = 0 /obj/item/clothing/mask/chameleon/drone/Initialize() . = ..() diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index a424b38f8b6..683abef2a3a 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -73,6 +73,7 @@ desc = "A heads-up display capable of analyzing the integrity and status of robotics and exosuits." icon_state = "diagnostichud" hud_type = DATA_HUD_DIAGNOSTIC_BASIC + hud_trait = TRAIT_DIAGNOSTIC_HUD glass_colour_type = /datum/client_colour/glass_colour/lightorange /obj/item/clothing/glasses/hud/diagnostic/night diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index e4ea0fba14d..ffe50e6bf56 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -205,6 +205,15 @@ transfer_prints = FALSE carrytrait = TRAIT_QUICKER_CARRY +/obj/item/clothing/gloves/color/latex/nitrile/infiltrator + name = "infiltrator gloves" + desc = "Specialized combat gloves for carrying people around. Transfers tactical kidnapping knowledge into the user via nanochips." + icon_state = "infiltrator" + item_state = "infiltrator" + siemens_coefficient = 0 + permeability_coefficient = 0.3 + resistance_flags = FIRE_PROOF | ACID_PROOF + /obj/item/clothing/gloves/color/latex/engineering name = "tinker's gloves" desc = "Overdesigned engineering gloves that have automated construction subrutines dialed in, allowing for faster construction while worn." diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 4cc32b187d9..7677a7e94a2 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -322,6 +322,19 @@ min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT armor = list("melee" = 25, "bullet" = 20, "laser" = 20, "energy" = 30, "bomb" = 20, "bio" = 50, "rad" = 20, "fire" = -10, "acid" = 50) +/obj/item/clothing/head/helmet/infiltrator + name = "infiltrator helmet" + desc = "The galaxy isn't big enough for the two of us." + icon_state = "infiltrator" + item_state = "infiltrator" + armor = list("melee" = 40, "bullet" = 40, "laser" = 30, "energy" = 40, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) + resistance_flags = FIRE_PROOF | ACID_PROOF + flash_protect = FLASH_PROTECTION_WELDER + flags_inv = HIDEHAIR|HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF + strip_delay = 80 + + //LightToggle /obj/item/clothing/head/helmet/ComponentInitialize() diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm index 5d5e4f981b2..a78f62327fb 100644 --- a/code/modules/clothing/masks/boxing.dm +++ b/code/modules/clothing/masks/boxing.dm @@ -11,6 +11,38 @@ /obj/item/clothing/mask/balaclava/attack_self(mob/user) adjustmask(user) +/obj/item/clothing/mask/infiltrator + name = "infiltrator balaclava" + desc = "It makes you feel safe in your anonymity, but for a stealth outfit you sure do look obvious that you're up to no good. It seems to have a built in heads-up display." + icon_state = "syndicate_balaclava" + item_state = "syndicate_balaclava" + clothing_flags = MASKINTERNALS + flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR + visor_flags_inv = HIDEFACE|HIDEFACIALHAIR + w_class = WEIGHT_CLASS_SMALL + armor = list("melee" = 10, "bullet" = 5, "laser" = 5,"energy" = 5, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 100, "acid" = 40) + resistance_flags = FIRE_PROOF | ACID_PROOF + + var/voice_unknown = FALSE ///This makes it so that your name shows up as unknown when wearing the mask. + +/obj/item/clothing/mask/infiltrator/equipped(mob/living/carbon/human/user, slot) + . = ..() + if(slot != ITEM_SLOT_MASK) + return + to_chat(user, "You roll the balaclava over your face, and a data display appears before your eyes.") + ADD_TRAIT(user, TRAIT_DIAGNOSTIC_HUD, MASK_TRAIT) + var/datum/atom_hud/H = GLOB.huds[DATA_HUD_DIAGNOSTIC_BASIC] + H.add_hud_to(user) + voice_unknown = TRUE + +/obj/item/clothing/mask/infiltrator/dropped(mob/living/carbon/human/user) + to_chat(user, "You pull off the balaclava, and the mask's internal hud system switches off quietly.") + REMOVE_TRAIT(user, TRAIT_DIAGNOSTIC_HUD, MASK_TRAIT) + var/datum/atom_hud/H = GLOB.huds[DATA_HUD_DIAGNOSTIC_ADVANCED] + H.remove_hud_from(user) + voice_unknown = FALSE + return ..() + /obj/item/clothing/mask/luchador name = "Luchador Mask" desc = "Worn by robust fighters, flying high to defeat their foes!" diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index bc959493590..590769797eb 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -16,6 +16,14 @@ var/offset = 0 var/equipped_before_drop = FALSE var/can_be_bloody = TRUE + ///Whether these shoes have laces that can be tied/untied + var/can_be_tied = TRUE + ///Are we currently tied? Can either be SHOES_UNTIED, SHOES_TIED, or SHOES_KNOTTED + var/tied = SHOES_TIED + ///How long it takes to lace/unlace these shoes + var/lace_time = 5 SECONDS + ///any alerts we have active + var/obj/screen/alert/our_alert /obj/item/clothing/shoes/ComponentInitialize() . = ..() @@ -53,6 +61,16 @@ if(bloody) . += mutable_appearance('icons/effects/blood.dmi', "shoeblood") +/obj/item/clothing/shoes/examine(mob/user) + . = ..() + + if(!ishuman(loc)) + return ..() + if(tied == SHOES_UNTIED) + . += "The shoelaces are untied." + else if(tied == SHOES_KNOTTED) + . += "The shoelaces are all knotted together." + /obj/item/clothing/shoes/equipped(mob/user, slot) . = ..() if(offset && (slot_flags & slot)) @@ -60,6 +78,9 @@ worn_y_dimension -= (offset * 2) user.update_inv_shoes() equipped_before_drop = TRUE + if(can_be_tied && tied == SHOES_UNTIED) + our_alert = user.throw_alert("shoealert", /obj/screen/alert/shoes/untied) + RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_trip, override=TRUE) /obj/item/clothing/shoes/proc/restore_offsets(mob/user) equipped_before_drop = FALSE @@ -67,6 +88,8 @@ worn_y_dimension = world.icon_size /obj/item/clothing/shoes/dropped(mob/user) + if(our_alert && our_alert.owner == user) + user.clear_alert("shoealert") if(offset && equipped_before_drop) restore_offsets(user) . = ..() @@ -88,3 +111,146 @@ /obj/item/proc/negates_gravity() return FALSE + +/** + * adjust_laces adjusts whether our shoes (assuming they can_be_tied) and tied, untied, or knotted + * + * In addition to setting the state, it will deal with getting rid of alerts if they exist, as well as registering and unregistering the stepping signals + * + * Arguments: + * * + * * state: SHOES_UNTIED, SHOES_TIED, or SHOES_KNOTTED, depending on what you want them to become + * * user: used to check to see if we're the ones unknotting our own laces + */ +/obj/item/clothing/shoes/proc/adjust_laces(state, mob/user) + if(!can_be_tied) + return + + var/mob/living/carbon/human/our_guy + if(ishuman(loc)) + our_guy = loc + + tied = state + if(tied == SHOES_TIED) + if(our_guy) + our_guy.clear_alert("shoealert") + UnregisterSignal(src, COMSIG_SHOES_STEP_ACTION) + else + if(tied == SHOES_UNTIED && our_guy && user == our_guy) + our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/untied) // if we're the ones unknotting our own laces, of course we know they're untied + RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_trip, override=TRUE) + +/** + * handle_tying deals with all the actual tying/untying/knotting, inferring your intent from who you are in relation to the state of the laces + * + * If you're the wearer, you want them to move towards tied-ness (knotted -> untied -> tied). If you're not, you're pranking them, so you're moving towards knotted-ness (tied -> untied -> knotted) + * + * Arguments: + * * + * * user: who is the person interacting with the shoes? + */ +/obj/item/clothing/shoes/proc/handle_tying(mob/living/carbon/human/user) + ///our_guy here is the wearer, if one exists (and he must exist, or we don't care) + var/mob/living/carbon/human/our_guy = loc + if(!istype(our_guy)) + return + + if(user == loc && tied != SHOES_TIED) // if they're our own shoes, go tie-wards + user.visible_message("[user] begins [tied ? "unknotting" : "tying"] the laces of [user.p_their()] [src.name].", "You begin [tied ? "unknotting" : "tying"] the laces of your [src.name]...") + + if(do_after(user, lace_time, needhand=TRUE, target=src)) + to_chat(user, "You [tied ? "unknot" : "tie"] the laces of your [src.name].") + if(tied == SHOES_UNTIED) + adjust_laces(SHOES_TIED, user) + else + adjust_laces(SHOES_UNTIED, user) + + else // if they're someone else's shoes, go knot-wards + if(user.mobility_flags & MOBILITY_STAND) + to_chat(user, "You must be on the floor to interact with [src]!") + return + if(tied == SHOES_KNOTTED) + to_chat(user, "The laces on [loc]'s [src.name] are already a hopelessly tangled mess!") + return + + var/mod_time = lace_time + to_chat(user, "You quietly set to work [tied ? "untying" : "knotting"] [loc]'s [src.name]...") + if(HAS_TRAIT(user, TRAIT_CLUMSY)) // based clowns trained their whole lives for this + mod_time *= 0.75 + + if(do_after(user, mod_time, needhand=TRUE, target=src)) + to_chat(user, "You [tied ? "untie" : "knot"] the laces on [loc]'s [src.name].") + if(tied == SHOES_UNTIED) + adjust_laces(SHOES_KNOTTED, user) + else + adjust_laces(SHOES_UNTIED, user) + else // if one of us moved + user.visible_message("[our_guy] stamps on [user]'s hand, mid-shoelace [tied ? "knotting" : "untying"]!", "Ow! [our_guy] stamps on your hand!", user) + to_chat(our_guy, "You stamp on [user]'s hand! What the- they were [tied ? "knotting" : "untying"] your shoelaces!") + user.emote("scream") + var/obj/item/bodypart/ouchie = user.get_bodypart(pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + if(ouchie) + ouchie.receive_damage(15) + user.Paralyze(5) + +/** + * check_trip runs on each step to see if we fall over as a result of our lace status. Knotted laces are a guaranteed trip, while untied shoes are just a chance to stumble + */ +/obj/item/clothing/shoes/proc/check_trip() + var/mob/living/carbon/human/our_guy = loc + if(!istype(our_guy)) // are they REALLY /our guy/? + return + + if(tied == SHOES_KNOTTED) + our_guy.Paralyze(5) + our_guy.Knockdown(10) + our_guy.visible_message("[our_guy] trips on [our_guy.p_their()] knotted shoelaces and falls! What a klutz!", "You trip on your knotted shoelaces and fall over!") + SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "trip", /datum/mood_event/tripped) // well we realized they're knotted now! + our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/knotted) + else if(tied == SHOES_UNTIED) + var/wiser = TRUE // did we stumble and realize our laces are undone? + switch(rand(1, 1000)) + if(1) // .1% chance to trip and fall over (note these are per step while our laces are undone) + our_guy.Paralyze(5) + our_guy.Knockdown(10) + our_guy.visible_message("[our_guy] trips on [our_guy.p_their()] untied shoelaces and falls! What a klutz!", "You trip on your untied shoelaces and fall over!") + if(2 to 5) // .4% chance to stumble and lurch forward + our_guy.throw_at(get_step(our_guy, our_guy.dir), 3, 2) + to_chat(our_guy, "You stumble on your untied shoelaces and lurch forward!") + if(6 to 13) // .7% chance to stumble and fling what we're holding + var/have_anything = FALSE + for(var/obj/item/I in our_guy.held_items) + have_anything = TRUE + our_guy.accident(I) + to_chat(our_guy, "You trip on your shoelaces a bit[have_anything ? ", flinging what you were holding" : ""]!") + if(14 to 25) // 1.3ish% chance to stumble and be a bit off balance (like being disarmed) + to_chat(our_guy, "You stumble a bit on your untied shoelaces!") + if(!our_guy.has_movespeed_modifier(/datum/movespeed_modifier/shove)) + our_guy.add_movespeed_modifier(/datum/movespeed_modifier/shove) + addtimer(CALLBACK(our_guy, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH) + if(26 to 1000) + wiser = FALSE + + if(wiser) + SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "untied", /datum/mood_event/untied) // well we realized they're untied now! + our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/untied) + + +/obj/item/clothing/shoes/attack_hand(mob/living/carbon/human/user) + if(!istype(user)) + return ..() + if(loc == user && tied != SHOES_TIED) + handle_tying(user) + return + ..() + +/obj/item/clothing/shoes/attack_self(mob/user) + . = ..() + + to_chat(user, "You begin [tied ? "untying" : "tying"] the laces on [src]...") + if(do_after(user, lace_time, needhand=TRUE, target=src)) + to_chat(user, "You [tied ? "untie" : "tie"] the laces on [src].") + if(tied == SHOES_UNTIED) + adjust_laces(SHOES_TIED, user) + else + adjust_laces(SHOES_UNTIED, user) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 53792c34e57..11a3c11a769 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -17,7 +17,25 @@ resistance_flags = NONE permeability_coefficient = 0.05 //Thick soles, and covers the ankle pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 12 SECONDS +/obj/item/clothing/shoes/combat/sneakboots + name = "sneakboots" + desc = "These boots have special noise cancelling soles. Perfect for stealth, if it wasn't for the color scheme." + icon_state = "sneakboots" + item_state = "sneakboots" + w_class = WEIGHT_CLASS_SMALL + resistance_flags = FIRE_PROOF | ACID_PROOF + +/obj/item/clothing/shoes/combat/sneakboots/equipped(mob/living/carbon/human/user, slot) + . = ..() + if(slot == ITEM_SLOT_FEET) + ADD_TRAIT(user, TRAIT_SILENT_FOOTSTEPS, SHOES_TRAIT) + +/obj/item/clothing/shoes/combat/sneakboots/dropped(mob/living/carbon/human/user) + REMOVE_TRAIT(user, TRAIT_SILENT_FOOTSTEPS, SHOES_TRAIT) + return ..() + /obj/item/clothing/shoes/combat/swat //overpowered boots for death squads name = "\improper SWAT boots" desc = "High speed, no drag combat boots." @@ -33,6 +51,7 @@ strip_delay = 5 equip_delay_other = 50 permeability_coefficient = 0.9 + can_be_tied = FALSE /obj/item/clothing/shoes/sandal/marisa desc = "A pair of magic black shoes." @@ -58,6 +77,7 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 40, "acid" = 75) can_be_bloody = FALSE custom_price = 600 + can_be_tied = FALSE /obj/item/clothing/shoes/galoshes/dry name = "absorbent galoshes" @@ -76,6 +96,7 @@ slowdown = SHOES_SLOWDOWN+1 pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes/clown var/enabled_waddle = TRUE + lace_time = 20 SECONDS // how the hell do these laces even work?? /obj/item/clothing/shoes/clown_shoes/Initialize() . = ..() @@ -125,6 +146,7 @@ resistance_flags = NONE permeability_coefficient = 0.05 //Thick soles, and covers the ankle pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + can_be_tied = FALSE /obj/item/clothing/shoes/jackboots/fast slowdown = -1 @@ -140,6 +162,7 @@ heat_protection = FEET|LEGS max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 8 SECONDS /obj/item/clothing/shoes/workboots name = "work boots" @@ -152,6 +175,7 @@ strip_delay = 20 equip_delay_other = 40 pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 8 SECONDS /obj/item/clothing/shoes/workboots/mining name = "mining boots" @@ -168,6 +192,7 @@ min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT heat_protection = FEET max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT + lace_time = 10 SECONDS /obj/item/clothing/shoes/cult/alt name = "cultist boots" @@ -199,6 +224,7 @@ strip_delay = 100 equip_delay_other = 100 permeability_coefficient = 0.9 + can_be_tied = FALSE /obj/item/clothing/shoes/griffin name = "griffon boots" @@ -206,6 +232,7 @@ icon_state = "griffinboots" item_state = "griffinboots" pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 8 SECONDS /obj/item/clothing/shoes/bhop name = "jump boots" @@ -256,6 +283,7 @@ desc = "A giant, clunky pair of shoes crudely made out of bronze. Why would anyone wear these?" icon = 'icons/obj/clothing/clockwork_garb.dmi' icon_state = "clockwork_treads" + lace_time = 8 SECONDS /obj/item/clothing/shoes/bronze/Initialize() . = ..() @@ -332,6 +360,7 @@ icon_state = "rus_shoes" item_state = "rus_shoes" pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 8 SECONDS /obj/item/clothing/shoes/cowboy name = "cowboy boots" @@ -342,6 +371,7 @@ custom_price = 60 var/list/occupants = list() var/max_occupants = 4 + can_be_tied = FALSE /obj/item/clothing/shoes/cowboy/Initialize() . = ..() @@ -419,6 +449,7 @@ desc = "All this talk of antags, greytiding, and griefing... I just wanna grill for god's sake!" name = "grilling sandals" icon_state = "cookflops" + can_be_tied = FALSE /obj/item/clothing/shoes/yakuza name = "tojo clan shoes" diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index b400d9f7806..35c2f68252a 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -235,6 +235,9 @@ REMOVE_TRAIT(helmet, TRAIT_NODROP, CHRONOSUIT_TRAIT) helmet.suit = null helmet = null + user.reset_perspective() + user.set_machine() + user.remote_control = null if(camera) QDEL_NULL(camera) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index b28b1266b49..a7d4a0b2ef8 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -172,6 +172,15 @@ . = ..() allowed = GLOB.detective_vest_allowed +/obj/item/clothing/suit/armor/vest/infiltrator + name = "infiltrator vest" + desc = "This vest appears to be made of of highly flexible materials that absorb impacts with ease." + icon_state = "infiltrator" + item_state = "infiltrator" + armor = list("melee" = 30, "bullet" = 40, "laser" = 20, "energy" = 30, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) + resistance_flags = FIRE_PROOF | ACID_PROOF + strip_delay = 80 + //All of the armor below is mostly unused /obj/item/clothing/suit/armor/centcom diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index a13bf474e7e..f81f08650a4 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -674,7 +674,7 @@ H.remove_hud_from(user) /obj/item/clothing/head/hooded/ablative/IsReflect(def_zone) - if(!(def_zone in BODY_ZONE_HEAD)) //If not shot where ablative is covering you, you don't get the reflection bonus! + if(def_zone != BODY_ZONE_HEAD) //If not shot where ablative is covering you, you don't get the reflection bonus! return FALSE if (prob(hit_reflect_chance)) return TRUE diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm index 089b8fcedc6..a2ab06a161c 100644 --- a/code/modules/clothing/under/syndicate.dm +++ b/code/modules/clothing/under/syndicate.dm @@ -20,6 +20,22 @@ fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE +/obj/item/clothing/under/syndicate/bloodred + name = "blood-red sneaksuit" + desc = "It still counts as stealth if there are no witnesses." + icon_state = "bloodred_pajamas" + item_state = "bl_suit" + armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 50, "acid" = 40) + resistance_flags = FIRE_PROOF | ACID_PROOF + can_adjust = FALSE + +/obj/item/clothing/under/syndicate/bloodred/sleepytime + name = "blood-red pajamas" + desc = "Do operatives dream of nuclear sheep?" + icon_state = "bloodred_pajamas" + item_state = "bl_suit" + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + /obj/item/clothing/under/syndicate/tacticool name = "tacticool turtleneck" desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." diff --git a/code/modules/events/stray_cargo.dm b/code/modules/events/stray_cargo.dm new file mode 100644 index 00000000000..f7ff0e6bc57 --- /dev/null +++ b/code/modules/events/stray_cargo.dm @@ -0,0 +1,99 @@ +///Spawns a cargo pod containing a random cargo supply pack on a random area of the station +/datum/round_event_control/stray_cargo + name = "Stray Cargo Pod" + typepath = /datum/round_event/stray_cargo + weight = 20 + max_occurrences = 4 + earliest_start = 10 MINUTES + +///Spawns a cargo pod containing a random cargo supply pack on a random area of the station +/datum/round_event/stray_cargo + var/area/impact_area ///Randomly picked area + announceChance = 75 + var/list/possible_pack_types = list() ///List of possible supply packs dropped in the pod, if empty picks from the cargo list + var/static/list/stray_spawnable_supply_packs = list() ///List of default spawnable supply packs, filtered from the cargo list + +/datum/round_event/stray_cargo/announce(fake) + priority_announce("Stray cargo pod detected on long-range scanners. Expected location of impact: [impact_area.name].", "Collision Alert") + +/** +* Tries to find a valid area, throws an error if none are found +* Also randomizes the start timer +*/ +/datum/round_event/stray_cargo/setup() + startWhen = rand(20, 40) + impact_area = find_event_area() + if(!impact_area) + CRASH("No valid areas for cargo pod found.") + var/list/turf_test = get_area_turfs(impact_area) + if(!turf_test.len) + CRASH("Stray Cargo Pod : No valid turfs found for [impact_area] - [impact_area.type]") + + if(!stray_spawnable_supply_packs.len) + stray_spawnable_supply_packs = SSshuttle.supply_packs.Copy() + for(var/pack in stray_spawnable_supply_packs) + var/datum/supply_pack/pack_type = pack + if(initial(pack_type.special)) + stray_spawnable_supply_packs -= pack + +///Spawns a random supply pack, puts it in a pod, and spawns it on a random tile of the selected area +/datum/round_event/stray_cargo/start() + var/list/turf/valid_turfs = get_area_turfs(impact_area) + //Only target non-dense turfs to prevent wall-embedded pods + for(var/i in valid_turfs) + var/turf/T = i + if(T.density) + valid_turfs -= T + var/turf/LZ = pick(valid_turfs) + var/pack_type + if(possible_pack_types.len) + pack_type = pick(possible_pack_types) + else + pack_type = pick(stray_spawnable_supply_packs) + var/datum/supply_pack/SP = new pack_type + var/obj/structure/closet/crate/crate = SP.generate(null) + crate.locked = FALSE //Unlock secure crates + crate.update_icon() + var/obj/structure/closet/supplypod/pod = make_pod() + new /obj/effect/DPtarget(LZ, pod, crate) + +///Handles the creation of the pod, in case it needs to be modified beforehand +/datum/round_event/stray_cargo/proc/make_pod() + var/obj/structure/closet/supplypod/S = new + return S + +///Picks an area that wouldn't risk critical damage if hit by a pod explosion +/datum/round_event/stray_cargo/proc/find_event_area() + var/static/list/allowed_areas + if(!allowed_areas) + ///Places that shouldn't explode + var/list/safe_area_types = typecacheof(list( + /area/ai_monitored/turret_protected/ai, + /area/ai_monitored/turret_protected/ai_upload, + /area/engine, + /area/shuttle) + ) + + ///Subtypes from the above that actually should explode. + var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room)) + allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes + var/list/possible_areas = typecache_filter_list(GLOB.sortedAreas,allowed_areas) + if (length(possible_areas)) + return pick(possible_areas) + +///A rare variant that drops a crate containing syndicate uplink items +/datum/round_event_control/stray_cargo/syndicate + name = "Stray Syndicate Cargo Pod" + typepath = /datum/round_event/stray_cargo/syndicate + weight = 6 + max_occurrences = 1 + earliest_start = 30 MINUTES + +/datum/round_event/stray_cargo/syndicate + possible_pack_types = list(/datum/supply_pack/misc/syndicate) + +///Apply the syndicate pod skin +/datum/round_event/stray_cargo/syndicate/make_pod() + var/obj/structure/closet/supplypod/S = new + S.setStyle(STYLE_SYNDICATE) + return S diff --git a/code/modules/food_and_drinks/food/snacks_cake.dm b/code/modules/food_and_drinks/food/snacks_cake.dm index 812790bc2ff..a048fb0e437 100644 --- a/code/modules/food_and_drinks/food/snacks_cake.dm +++ b/code/modules/food_and_drinks/food/snacks_cake.dm @@ -205,6 +205,8 @@ /obj/item/reagent_containers/food/snacks/store/cake/birthday/energy/attack(mob/living/M, mob/living/user) . = ..() + if(HAS_TRAIT(user, TRAIT_PACIFISM) && M != user) //Prevents pacifists from attacking others directly + return energy_bite(M, user) /obj/item/reagent_containers/food/snacks/store/cake/birthday/energy/microwave_act(obj/machinery/microwave/M) //super sekriter club @@ -228,6 +230,8 @@ /obj/item/reagent_containers/food/snacks/cakeslice/birthday/energy/attack(mob/living/M, mob/living/user) . = ..() + if(HAS_TRAIT(user, TRAIT_PACIFISM) && M != user) //Prevents pacifists from attacking others directly + return energy_bite(M, user) /obj/item/reagent_containers/food/snacks/store/cake/apple diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index ea47a43bcef..d1d52673f78 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -459,7 +459,7 @@ denied_type = /obj/item/crusher_trophy/king_goat /obj/item/crusher_trophy/king_goat/effect_desc() - return "you also passively recharge markers 5x as fast while equipped and do a decent amount of damage at the cost of dulling the blade" + return "you also passively recharge markers 5x as fast while this is equipped and do a decent amount of damage at the cost of dulling the blade" /obj/item/crusher_trophy/king_goat/on_projectile_fire(obj/projectile/destabilizer/marker, mob/living/user) marker.damage = 10 //in my testing only does damage to simple mobs so should be fine to have it high diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index b11cf37f123..5e4eada12f1 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -893,8 +893,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/list/t_ray_images = list() var/static/list/stored_t_ray_images = list() for(var/obj/O in orange(client.view, src) ) - if(O.level != 1) - continue if(O.invisibility == INVISIBILITY_MAXIMUM) var/image/I = new(loc = get_turf(O)) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index abc6b269ba2..2755b9af05a 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -492,9 +492,9 @@ /mob/living/carbon/update_mobility() . = ..() if(!(mobility_flags & MOBILITY_STAND)) - add_movespeed_modifier(MOVESPEED_ID_CARBON_CRAWLING, TRUE, multiplicative_slowdown = CRAWLING_ADD_SLOWDOWN) + add_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling) else - remove_movespeed_modifier(MOVESPEED_ID_CARBON_CRAWLING, TRUE) + remove_movespeed_modifier(/datum/movespeed_modifier/carbon_crawling) //Updates the mob's health from bodyparts and mob damage variables /mob/living/carbon/updatehealth() @@ -517,9 +517,9 @@ med_hud_set_health() if(stat == SOFT_CRIT) - add_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE, multiplicative_slowdown = SOFTCRIT_ADD_SLOWDOWN) + add_movespeed_modifier(/datum/movespeed_modifier/carbon_softcrit) else - remove_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE) + remove_movespeed_modifier(/datum/movespeed_modifier/carbon_softcrit) /mob/living/carbon/update_stamina() var/stam = getStaminaLoss() diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 6b6bbb22248..75c635d71de 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -24,7 +24,7 @@ var/obj/item/clothing/head = null var/obj/item/clothing/gloves = null ///only used by humans - var/obj/item/clothing/shoes = null ///only used by humans. + var/obj/item/clothing/shoes/shoes = null ///only used by humans. var/obj/item/clothing/glasses/glasses = null ///only used by humans. var/obj/item/clothing/ears = null ///only used by humans. diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 79c3459f12b..efaf612a73b 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -7,6 +7,7 @@ if(!gibbed) emote("deathgasp") + reagents.end_metabolization(src) . = ..() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c17745e96eb..49a12ed2e3f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -157,8 +157,11 @@ if(ITEM_SLOT_FEET in obscured) dat += "Shoes:Obscured" else - dat += "Shoes:[(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "Empty"]" + dat += "Shoes:[(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "Empty"]" + if(shoes && shoes.can_be_tied && shoes.tied != SHOES_KNOTTED) + dat += " [shoes.tied ? "Untie shoes" : "Knot shoes"]" + dat += "" if(ITEM_SLOT_GLOVES in obscured) dat += "Gloves:Obscured" else @@ -269,6 +272,9 @@ update_inv_w_uniform() update_body() + var/mob/living/user = usr + if(istype(user) && href_list["shoes"] && (user.mobility_flags & MOBILITY_USE)) // we need to be on the ground, so we'll be a bit looser + shoes.handle_tying(usr) ///////HUDs/////// if(href_list["hud"]) @@ -418,16 +424,12 @@ if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD)) return to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]") - to_chat(usr, "Minor Crimes:") - for(var/datum/data/crime/c in R.fields["mi_crim"]) + for(var/datum/data/crime/c in R.fields["crim"]) to_chat(usr, "Crime: [c.crimeName]") - to_chat(usr, "Details: [c.crimeDetails]") - to_chat(usr, "Added by [c.author] at [c.time]") - to_chat(usr, "----------") - to_chat(usr, "Major Crimes:") - for(var/datum/data/crime/c in R.fields["ma_crim"]) - to_chat(usr, "Crime: [c.crimeName]") - to_chat(usr, "Details: [c.crimeDetails]") + if (c.crimeDetails) + to_chat(usr, "Details: [c.crimeDetails]") + else + to_chat(usr, "Details: \[Add details]") to_chat(usr, "Added by [c.author] at [c.time]") to_chat(usr, "----------") to_chat(usr, "Notes: [R.fields["notes"]]") @@ -466,34 +468,31 @@ return if(href_list["add_crime"]) - switch(alert("What crime would you like to add?","Security HUD","Minor Crime","Major Crime","Cancel")) - if("Minor Crime") - var/t1 = stripped_input("Please input minor crime names:", "Security HUD", "", null) - var/t2 = stripped_multiline_input("Please input minor crime details:", "Security HUD", "", null) - if(!R || !t1 || !t2 || !allowed_access) - return - if(!H.canUseHUD()) - return - if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD)) - return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, station_time_timestamp()) - GLOB.data_core.addMinorCrime(R.fields["id"], crime) - investigate_log("New Minor Crime: [t1]: [t2] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) - to_chat(usr, "Successfully added a minor crime.") - return - if("Major Crime") - var/t1 = stripped_input("Please input major crime names:", "Security HUD", "", null) - var/t2 = stripped_multiline_input("Please input major crime details:", "Security HUD", "", null) - if(!R || !t1 || !t2 || !allowed_access) - return - if(!H.canUseHUD()) - return - if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD)) - return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, station_time_timestamp()) - GLOB.data_core.addMajorCrime(R.fields["id"], crime) - investigate_log("New Major Crime: [t1]: [t2] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) - to_chat(usr, "Successfully added a major crime.") + var/t1 = stripped_input("Please input crime name:", "Security HUD", "", null) + if(!R || !t1 || !allowed_access) + return + if(!H.canUseHUD()) + return + if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD)) + return + var/crime = GLOB.data_core.createCrimeEntry(t1, null, allowed_access, station_time_timestamp()) + GLOB.data_core.addCrime(R.fields["id"], crime) + investigate_log("New Crime: [t1] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) + to_chat(usr, "Successfully added a crime.") + return + + if(href_list["add_details"]) + var/t1 = stripped_input(usr, "Please input crime details:", "Secure. records", "", null) + if(!R || !t1 || !allowed_access) + return + if(!H.canUseHUD()) + return + if(!HAS_TRAIT(H, TRAIT_SECURITY_HUD)) + return + if(href_list["cdataid"]) + GLOB.data_core.addCrimeDetails(R.fields["id"], href_list["cdataid"], t1) + investigate_log("New Crime details: [t1] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) + to_chat(usr, "Successfully added details.") return if(href_list["view_comment"]) @@ -726,8 +725,8 @@ remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000") cut_overlay(MA) -/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE) - if(!(mobility_flags & MOBILITY_UI)) +/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE, floor_okay=FALSE) + if(!(mobility_flags & MOBILITY_UI) && !floor_okay) to_chat(src, "You can't do that right now!") return FALSE if(!Adjacent(M) && (M.loc != src)) @@ -1064,7 +1063,7 @@ return FALSE /mob/living/carbon/human/proc/clear_shove_slowdown() - remove_movespeed_modifier(MOVESPEED_ID_SHOVE) + remove_movespeed_modifier(/datum/movespeed_modifier/shove) var/active_item = get_active_held_item() if(is_type_in_typecache(active_item, GLOB.shove_disarming_types)) visible_message("[src.name] regains their grip on \the [active_item]!", "You regain your grip on \the [active_item]", null, COMBAT_MESSAGE_RANGE) @@ -1077,17 +1076,16 @@ . = ..() dna?.species.spec_updatehealth(src) if(HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) - remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN) - remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING) + remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) + remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) return var/health_deficiency = max((maxHealth - health), staminaloss) if(health_deficiency >= 40) - add_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN, override = TRUE, multiplicative_slowdown = (health_deficiency / 75), blacklisted_movetypes = FLOATING|FLYING) - add_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING, override = TRUE, multiplicative_slowdown = (health_deficiency / 25), movetypes = FLYING, blacklisted_movetypes = FLOATING) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, multiplicative_slowdown = health_deficiency / 75) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, multiplicative_slowdown = health_deficiency / 25) else - remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN) - remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING) - + remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) + remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) /mob/living/carbon/human/washed(var/atom/washer) . = ..() @@ -1107,12 +1105,12 @@ if(gloves && !(HIDEGLOVES in obscured) && gloves.washed(washer)) SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD) -/mob/living/carbon/human/adjust_nutrition(var/change) //Honestly FUCK the oldcoders for putting nutrition on /mob someone else can move it up because holy hell I'd have to fix SO many typechecks +/mob/living/carbon/human/adjust_nutrition(change) //Honestly FUCK the oldcoders for putting nutrition on /mob someone else can move it up because holy hell I'd have to fix SO many typechecks if(HAS_TRAIT(src, TRAIT_NOHUNGER)) return FALSE return ..() -/mob/living/carbon/human/set_nutrition(var/change) //Seriously fuck you oldcoders. +/mob/living/carbon/human/set_nutrition(change) //Seriously fuck you oldcoders. if(HAS_TRAIT(src, TRAIT_NOHUNGER)) return FALSE return ..() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 1f460e0a1ae..604ef492a92 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -86,15 +86,18 @@ return BULLET_ACT_HIT return ..(P, def_zone) - -/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object +///Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object +/mob/living/carbon/human/proc/check_reflect(def_zone) if(wear_suit) - if(wear_suit.IsReflect(def_zone) == 1) - return 1 + if(wear_suit.IsReflect(def_zone)) + return TRUE + if(head) + if(head.IsReflect(def_zone)) + return TRUE for(var/obj/item/I in held_items) - if(I.IsReflect(def_zone) == 1) - return 1 - return 0 + if(I.IsReflect(def_zone)) + return TRUE + return FALSE /mob/living/carbon/human/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0) var/block_chance_modifier = round(damage / -3) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 7f1c7c4c2fb..53872edc816 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -1,11 +1,13 @@ /mob/living/carbon/human/get_movespeed_modifiers() var/list/considering = ..() - . = considering + . = list() if(HAS_TRAIT(src, TRAIT_IGNORESLOWDOWN)) - for(var/id in .) - var/list/data = .[id] - if(data[MOVESPEED_DATA_INDEX_FLAGS] & IGNORE_NOSLOW) - .[id] = data + for(var/id in considering) + var/datum/movespeed_modifier/M = considering[id] + if(M.flags & IGNORE_NOSLOW) + .[id] = M + else + . = considering /mob/living/carbon/human/slip(knockdown_amount, obj/O, lube, paralyze, forcedrop) if(HAS_TRAIT(src, TRAIT_NOSLIPALL)) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 4f6710c77d7..d01bab05ca9 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -8,7 +8,7 @@ /mob/living/carbon/human/GetVoice() if(istype(wear_mask, /obj/item/clothing/mask/chameleon)) var/obj/item/clothing/mask/chameleon/V = wear_mask - if(V.vchange && wear_id) + if(V.voice_change && wear_id) var/obj/item/card/id/idcard = wear_id.GetID() if(istype(idcard)) return idcard.registered_name @@ -16,6 +16,12 @@ return real_name else return real_name + if(istype(wear_mask, /obj/item/clothing/mask/infiltrator)) + var/obj/item/clothing/mask/infiltrator/V = wear_mask + if(V.voice_unknown) + return ("Unknown") + else + return real_name if(mind) var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling) if(changeling && changeling.mimicing ) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 8bef29bd283..5cec6a575b5 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -270,11 +270,10 @@ GLOBAL_LIST_EMPTY(roundstart_races) fly = new fly.Grant(C) - C.add_movespeed_modifier(MOVESPEED_ID_SPECIES, TRUE, 100, override=TRUE, multiplicative_slowdown=speedmod, movetypes=(~FLYING)) + C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, multiplicative_slowdown=speedmod) SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) - /datum/species/proc/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) if(C.dna.species.exotic_bloodtype) C.dna.blood_type = random_blood_type() @@ -306,7 +305,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) C.dna.features["wings"] = "None" C.update_body() - C.remove_movespeed_modifier(MOVESPEED_ID_SPECIES) + C.remove_movespeed_modifier(/datum/movespeed_modifier/species) SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src) @@ -374,6 +373,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(hair_color) if(hair_color == "mutcolor") facial_overlay.color = "#" + H.dna.features["mcolor"] + else if(hair_color == "fixedmutcolor") + facial_overlay.color = "#[fixed_mut_color]" else facial_overlay.color = "#" + hair_color else @@ -435,6 +436,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(hair_color) if(hair_color == "mutcolor") hair_overlay.color = "#" + H.dna.features["mcolor"] + else if(hair_color == "fixedmutcolor") + hair_overlay.color = "#[fixed_mut_color]" else hair_overlay.color = "#" + hair_color else @@ -685,6 +688,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(HAIR) if(hair_color == "mutcolor") accessory_overlay.color = "#[H.dna.features["mcolor"]]" + else if(hair_color == "fixedmutcolor") + accessory_overlay.color = "#[fixed_mut_color]" else accessory_overlay.color = "#[H.hair_color]" if(FACEHAIR) @@ -970,7 +975,6 @@ GLOBAL_LIST_EMPTY(roundstart_races) //////// //LIFE// //////// - /datum/species/proc/handle_digestion(mob/living/carbon/human/H) if(HAS_TRAIT(src, TRAIT_NOHUNGER)) return //hunger is for BABIES @@ -980,14 +984,14 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(H.overeatduration < 100) to_chat(H, "You feel fit again!") REMOVE_TRAIT(H, TRAIT_FAT, OBESITY) - H.remove_movespeed_modifier(MOVESPEED_ID_FAT) + H.remove_movespeed_modifier(/datum/movespeed_modifier/obesity) H.update_inv_w_uniform() H.update_inv_wear_suit() else if(H.overeatduration >= 100) to_chat(H, "You suddenly feel blubbery!") ADD_TRAIT(H, TRAIT_FAT, OBESITY) - H.add_movespeed_modifier(MOVESPEED_ID_FAT, multiplicative_slowdown = 1.5) + H.add_movespeed_modifier(/datum/movespeed_modifier/obesity) H.update_inv_w_uniform() H.update_inv_wear_suit() @@ -1042,13 +1046,13 @@ GLOBAL_LIST_EMPTY(roundstart_races) if(!HAS_TRAIT(H, TRAIT_NOHUNGER)) var/hungry = (500 - H.nutrition) / 5 //So overeat would be 100 and default level would be 80 if(hungry >= 70) - H.add_movespeed_modifier(MOVESPEED_ID_HUNGRY, override = TRUE, multiplicative_slowdown = (hungry / 50)) + H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/hunger, multiplicative_slowdown = (hungry / 50)) else if(isethereal(H)) var/datum/species/ethereal/E = H.dna.species if(E.get_charge(H) <= ETHEREAL_CHARGE_NORMAL) - H.add_movespeed_modifier(MOVESPEED_ID_HUNGRY, override = TRUE, multiplicative_slowdown = (1.5 * (1 - E.get_charge(H) / 100))) + H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/hunger, multiplicative_slowdown = (1.5 * (1 - E.get_charge(H) / 100))) else - H.remove_movespeed_modifier(MOVESPEED_ID_HUNGRY) + H.remove_movespeed_modifier(/datum/movespeed_modifier/hunger) switch(H.nutrition) if(NUTRITION_LEVEL_FULL to INFINITY) @@ -1331,8 +1335,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/knocked_item = FALSE if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types)) target_held_item = null - if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE)) - target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH) + if(!target.has_movespeed_modifier(/datum/movespeed_modifier/shove)) + target.add_movespeed_modifier(/datum/movespeed_modifier/shove) if(target_held_item) target.visible_message("[target.name]'s grip on \the [target_held_item] loosens!", "Your grip on \the [target_held_item] loosens!", null, COMBAT_MESSAGE_RANGE) @@ -1586,8 +1590,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold") SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "hot", /datum/mood_event/hot) - // Remove any slow down from the cold - H.remove_movespeed_modifier(MOVESPEED_ID_COLD) + //Remove any slowdown from the cold. + H.remove_movespeed_modifier(/datum/movespeed_modifier/cold) var/burn_damage = 0 var/firemodifier = H.fire_stacks / 50 @@ -1622,12 +1626,8 @@ GLOBAL_LIST_EMPTY(roundstart_races) // clear any hot moods and apply cold mood SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot") SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "cold", /datum/mood_event/cold) - // Apply cold slow down - H.add_movespeed_modifier(MOVESPEED_ID_COLD, override = TRUE, \ - multiplicative_slowdown = ((bodytemp_cold_damage_limit - H.bodytemperature) / COLD_SLOWDOWN_FACTOR), \ - blacklisted_movetypes = FLOATING) - + H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((bodytemp_cold_damage_limit - H.bodytemperature) / COLD_SLOWDOWN_FACTOR)) // Display alerts based on the amount of cold damage being taken // Apply more damage based on how cold you are switch(H.bodytemperature) @@ -1644,7 +1644,7 @@ GLOBAL_LIST_EMPTY(roundstart_races) // We are not to hot or cold, remove status and moods else H.clear_alert("temp") - H.remove_movespeed_modifier(MOVESPEED_ID_COLD) + H.remove_movespeed_modifier(/datum/movespeed_modifier/cold) SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold") SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot") diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index f8f8f2ab8b1..2fcbf38ff01 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -14,7 +14,7 @@ brutemod = 1.25 //They're weak to punches attack_type = BURN //burn bish damage_overlay_type = "" //We are too cool for regular damage overlays - species_traits = list(DYNCOLORS, AGENDER, NO_UNDERWEAR) + species_traits = list(DYNCOLORS, AGENDER, NO_UNDERWEAR, HAIR) changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/ethereal inherent_traits = list(TRAIT_NOHUNGER) @@ -25,6 +25,8 @@ bodytemp_heat_damage_limit = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD // about 150C // Cold temperatures hurt faster as it is harder to move with out the heat energy bodytemp_cold_damage_limit = (T20C - 10) // about 10c + hair_color = "fixedmutcolor" + hair_alpha = 140 var/current_color var/EMPeffect = FALSE var/emageffect = FALSE diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 9471fe92f2b..039c66e5d7e 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -61,14 +61,13 @@ /mob/living/carbon/monkey/on_reagent_change() . = ..() - remove_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE) var/amount if(reagents.has_reagent(/datum/reagent/medicine/morphine)) amount = -1 if(reagents.has_reagent(/datum/reagent/consumable/nuka_cola)) amount = -1 if(amount) - add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/monkey_reagent_speedmod, TRUE, amount) /mob/living/carbon/monkey/updatehealth() . = ..() @@ -77,14 +76,14 @@ var/health_deficiency = (maxHealth - health) if(health_deficiency >= 45) slow += (health_deficiency / 25) - add_movespeed_modifier(MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/monkey_health_speedmod, TRUE, slow) /mob/living/carbon/monkey/adjust_bodytemperature(amount, min_temp=0, max_temp=INFINITY, use_insulation=FALSE, use_steps=FALSE) . = ..() var/slow = 0 if (bodytemperature < 283.222) slow += ((283.222 - bodytemperature) / 10) * 1.75 - add_movespeed_modifier(MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/monkey_temperature_speedmod, TRUE, slow) /mob/living/carbon/monkey/Stat() ..() @@ -96,8 +95,6 @@ if(changeling) stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]") stat("Absorbed DNA", changeling.absorbedcount) - return - /mob/living/carbon/monkey/verb/removeinternal() set name = "Remove Internals" diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm index 917075b81f0..baa804a9ac0 100644 --- a/code/modules/mob/living/inhand_holder.dm +++ b/code/modules/mob/living/inhand_holder.dm @@ -84,4 +84,4 @@ if(!D) return ..() icon = 'icons/mob/drone.dmi' - icon_state = "[D.visualAppearence]_hat" + icon_state = "[D.visualAppearance]_hat" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e6c07e2bcc5..d479d1c6c95 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -778,7 +778,7 @@ if((resting || HAS_TRAIT(src, TRAIT_GRABWEAKNESS)) && pulledby.grab_state < GRAB_KILL) //If resting, resisting out of a grab is equivalent to 1 grab state higher. wont make the grab state exceed the normal max, however altered_grab_state++ var/resist_chance = BASE_GRAB_RESIST_CHANCE // see defines/combat.dm - resist_chance = max(resist_chance/altered_grab_state-sqrt((getStaminaLoss()+getBruteLoss()/2)*(3-altered_grab_state)), 0) // https://i.imgur.com/6yAT90T.png for sample output values + resist_chance = max((resist_chance/altered_grab_state)-sqrt((getBruteLoss()+getFireLoss()+getOxyLoss()+getToxLoss()+getCloneLoss())*0.5+getStaminaLoss()), 0) //stamina loss is weighted twice as heavily as the other damage types in this calculation if(prob(resist_chance)) visible_message("[src] breaks free of [pulledby]'s grip!", \ "You break free of [pulledby]'s grip!", null, null, pulledby) @@ -1235,9 +1235,9 @@ if(!has_legs && has_arms < 2) limbless_slowdown += 6 - (has_arms * 3) if(limbless_slowdown) - add_movespeed_modifier(MOVESPEED_ID_LIVING_LIMBLESS, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=limbless_slowdown, movetypes=GROUND) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown) else - remove_movespeed_modifier(MOVESPEED_ID_LIVING_LIMBLESS, update=TRUE) + remove_movespeed_modifier(/datum/movespeed_modifier/limbless) /mob/living/proc/fall(forced) if(!(mobility_flags & MOBILITY_USE)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 7a99bd1d3fc..2234d279a44 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -186,7 +186,7 @@ visible_message("[user] grabs [src] aggressively!", \ "[user] grabs you aggressively!", "You hear aggressive shuffling!", null, user) to_chat(user, "You grab [src] aggressively!") - drop_all_held_items() + drop_all_held_items() stop_pulling() log_combat(user, src, "grabbed", addition="aggressive grab[add_log]") if(GRAB_NECK) diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index d2788647605..b92b2654f78 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -26,38 +26,31 @@ return ..() /mob/living/proc/update_move_intent_slowdown() - var/mod = 0 - if(m_intent == MOVE_INTENT_WALK) - mod = CONFIG_GET(number/movedelay/walk_delay) - else - mod = CONFIG_GET(number/movedelay/run_delay) - if(!isnum(mod)) - mod = 1 - add_movespeed_modifier(MOVESPEED_ID_MOB_WALK_RUN_CONFIG_SPEED, TRUE, 100, override = TRUE, multiplicative_slowdown = mod) + add_movespeed_modifier((m_intent == MOVE_INTENT_WALK)? /datum/movespeed_modifier/config_walk_run/walk : /datum/movespeed_modifier/config_walk_run/run) /mob/living/proc/update_turf_movespeed(turf/open/T) if(isopenturf(T)) - add_movespeed_modifier(MOVESPEED_ID_LIVING_TURF_SPEEDMOD, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=T.slowdown, movetypes=GROUND, blacklisted_movetypes=(FLYING|FLOATING)) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/turf_slowdown, multiplicative_slowdown = T.slowdown) else - remove_movespeed_modifier(MOVESPEED_ID_LIVING_TURF_SPEEDMOD) + remove_movespeed_modifier(/datum/movespeed_modifier/turf_slowdown) /mob/living/proc/update_pull_movespeed() if(pulling) if(isliving(pulling)) var/mob/living/L = pulling if(!slowed_by_drag || (L.mobility_flags & MOBILITY_STAND) || L.buckled || grab_state >= GRAB_AGGRESSIVE) - remove_movespeed_modifier(MOVESPEED_ID_BULKY_DRAGGING) + remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag) return - add_movespeed_modifier(MOVESPEED_ID_BULKY_DRAGGING, multiplicative_slowdown = PULL_PRONE_SLOWDOWN) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = PULL_PRONE_SLOWDOWN) return if(isobj(pulling)) var/obj/structure/S = pulling if(!slowed_by_drag || !S.drag_slowdown) - remove_movespeed_modifier(MOVESPEED_ID_BULKY_DRAGGING) + remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag) return - add_movespeed_modifier(MOVESPEED_ID_BULKY_DRAGGING, multiplicative_slowdown = S.drag_slowdown) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = S.drag_slowdown) return - remove_movespeed_modifier(MOVESPEED_ID_BULKY_DRAGGING) + remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag) /mob/living/can_zFall(turf/T, levels) return ..() diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index b545c1acce4..e94431c4d3d 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -255,9 +255,9 @@ /mob/living/silicon/pai/Process_Spacemove(movement_dir = 0) . = ..() if(!.) - add_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD, TRUE, 100, multiplicative_slowdown = 2) + add_movespeed_modifier(/datum/movespeed_modifier/pai_spacewalk) return TRUE - remove_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD, TRUE) + remove_movespeed_modifier(/datum/movespeed_modifier/pai_spacewalk) return TRUE /mob/living/silicon/pai/examine(mob/user) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 894c1e8ef2c..9a1085e576e 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -499,7 +499,7 @@ else . += "
Requested security record not found,

" if(securityActive2 in GLOB.data_core.security) - . += "
\nSecurity Data
\nCriminal Status: [securityActive2.fields["criminal"]]
\n
\nMinor Crimes: [securityActive2.fields["mi_crim"]]
\nDetails: [securityActive2.fields["mi_crim_d"]]
\n
\nMajor Crimes: [securityActive2.fields["ma_crim"]]
\nDetails: [securityActive2.fields["ma_crim_d"]]
\n
\nImportant Notes:
\n\t[securityActive2.fields["notes"]]
\n
\n
Comments/Log

" + . += "
\nSecurity Data
\nCriminal Status: [securityActive2.fields["criminal"]]
\n
\nCrimes: [securityActive2.fields["crim"]]
\nDetails: [securityActive2.fields["crim_d"]]
\n
\nImportant Notes:
\n\t[securityActive2.fields["notes"]]
\n
\n
Comments/Log

" else . += "
Requested security record not found,

" . += "
\nBack
" diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 86f132199c8..f45dcbf0ab9 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -51,6 +51,7 @@ var/emag_cooldown = 0 var/wiresexposed = 0 + /// Random serial number generated for each cyborg upon its initialization var/ident = 0 var/locked = TRUE var/list/req_access = list(ACCESS_ROBOTICS) @@ -866,18 +867,27 @@ update_icons() . = ..() -/mob/living/silicon/robot/proc/make_shell(var/obj/item/borg/upgrade/ai/board) +/** + * make_shell: Makes an AI shell out of a cyborg unit + * + * Arguments: + * * board - B.O.R.I.S. module board used for transforming the cyborg into AI shell + */ +/mob/living/silicon/robot/proc/make_shell(obj/item/borg/upgrade/ai/board) if(!board) upgrades |= new /obj/item/borg/upgrade/ai(src) shell = TRUE braintype = "AI Shell" - name = "[designation] AI Shell [rand(100,999)]" + name = "Empty AI Shell-[ident]" real_name = name GLOB.available_ai_shells |= src if(!QDELETED(builtInCamera)) builtInCamera.c_tag = real_name //update the camera name too diag_hud_set_aishell() +/** + * revert_shell: Reverts AI shell back into a normal cyborg unit + */ /mob/living/silicon/robot/proc/revert_shell() if(!shell) return @@ -887,14 +897,20 @@ qdel(boris) shell = FALSE GLOB.available_ai_shells -= src - name = "Unformatted Cyborg [rand(100,999)]" + name = "Unformatted Cyborg-[ident]" real_name = name if(!QDELETED(builtInCamera)) builtInCamera.c_tag = real_name diag_hud_set_aishell() -/mob/living/silicon/robot/proc/deploy_init(var/mob/living/silicon/ai/AI) - real_name = "[AI.real_name] shell [rand(100, 999)] - [designation]" //Randomizing the name so it shows up separately in the shells list +/** + * deploy_init: Deploys AI unit into AI shell + * + * Arguments: + * * AI - AI unit that initiated the deployment into the AI shell + */ +/mob/living/silicon/robot/proc/deploy_init(mob/living/silicon/ai/AI) + real_name = "[AI.real_name] Shell-[ident]" name = real_name if(!QDELETED(builtInCamera)) builtInCamera.c_tag = real_name //update the camera name too diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index 2349f3022d8..f52b234b209 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -13,7 +13,6 @@ anchored = FALSE health = 25 maxHealth = 25 - spacewalk = TRUE radio_key = /obj/item/encryptionkey/headset_eng radio_channel = RADIO_CHANNEL_ENGINEERING @@ -41,6 +40,7 @@ /mob/living/simple_animal/bot/firebot/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) update_icon() var/datum/job/engineer/J = new/datum/job/engineer access_card.access += J.get_access() diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 1587b2b5e7c..c3d806af16f 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -8,7 +8,6 @@ anchored = FALSE health = 25 maxHealth = 25 - spacewalk = TRUE radio_key = /obj/item/encryptionkey/headset_eng radio_channel = RADIO_CHANNEL_ENGINEERING @@ -44,6 +43,7 @@ /mob/living/simple_animal/bot/floorbot/Initialize(mapload, new_toolbox_color) . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) toolbox_color = new_toolbox_color update_icon() var/datum/job/engineer/J = new/datum/job/engineer @@ -339,7 +339,7 @@ visible_message("[src] begins repairing the floor.") sleep(50) if(mode == BOT_REPAIRING && F && src.loc == F) - F.broken = FALSE + F.broken = FALSE F.burnt = FALSE F.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 7ff923d92c5..d9d9bb99322 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -14,7 +14,6 @@ speak_chance = 1 icon = 'icons/mob/mob.dmi' speed = 0 - spacewalk = TRUE a_intent = INTENT_HARM stop_automated_movement = 1 status_flags = CANPUSH @@ -47,6 +46,7 @@ /mob/living/simple_animal/hostile/construct/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) update_health_hud() var/spellnum = 1 for(var/spell in construct_spells) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index afb90604318..129dbbe4f50 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -3,18 +3,41 @@ #define DRONE_HEAD_LAYER 2 #define DRONE_TOTAL_LAYERS 2 +/// Message displayed when new drone spawns in drone network #define DRONE_NET_CONNECT "DRONE NETWORK: [name] connected." +/// Message displayed when drone in network dies #define DRONE_NET_DISCONNECT "DRONE NETWORK: [name] is not responding." +/// Maintenance Drone icon_state (multiple colors) #define MAINTDRONE "drone_maint" +/// Repair Drone icon_state #define REPAIRDRONE "drone_repair" +/// Scout Drone icon_state #define SCOUTDRONE "drone_scout" +/// Clockwork Drone icon_state #define CLOCKDRONE "drone_clock" +/// [MAINTDRONE] hacked icon_state #define MAINTDRONE_HACKED "drone_maint_red" +/// [REPAIRDRONE] hacked icon_state #define REPAIRDRONE_HACKED "drone_repair_hacked" +/// [SCOUTDRONE] hacked icon_state #define SCOUTDRONE_HACKED "drone_scout_hacked" +/** + * # Maintenance Drone + * + * Small player controlled fixer-upper + * + * The maintenace drone is a ghost role with the objective to repair and + * maintain the station. + * + * Featuring two dexterous hands, and a built in toolbox stocked with + * tools. + * + * They have laws to prevent them from doing anything else. + * + */ /mob/living/simple_animal/drone name = "Drone" desc = "A maintenance drone, an expendable robot built to perform station repairs." @@ -53,23 +76,42 @@ can_be_held = TRUE worn_slot_flags = ITEM_SLOT_HEAD held_items = list(null, null) - var/staticChoice = "static" - var/list/staticChoices = list("static", "blank", "letter", "animal") - var/picked = FALSE //Have we picked our visual appearence (+ colour if applicable) - var/colour = "grey" //Stored drone color, so we can go back when unhacked. + /// `TRUE` if we have picked our visual appearance, `FALSE` otherwise (default) + var/picked = FALSE + /// Stored drone color, restored when unhacked + var/colour = "grey" var/list/drone_overlays[DRONE_TOTAL_LAYERS] + /// Drone laws announced on spawn var/laws = \ "1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone.\n"+\ "2. You may not harm any being, regardless of intent or circumstance.\n"+\ "3. Your goals are to actively build, maintain, repair, improve, and provide power to the best of your abilities within the facility that housed your activation." //for derelict drones so they don't go to station. - var/heavy_emp_damage = 25 //Amount of damage sustained if hit by a heavy EMP pulse + /// Amount of damage sustained if hit by a heavy EMP pulse + var/heavy_emp_damage = 25 + /// List of active alarms. See [/mob/living/simple_animal/drone/proc/triggerAlarm] and [/mob/living/simple_animal/drone/proc/cancelAlarm] var/alarms = list("Atmosphere" = list(), "Fire" = list(), "Power" = list()) - var/obj/item/internal_storage //Drones can store one item, of any size/type in their body + /// Internal storage slot. Fits any item + var/obj/item/internal_storage + /// Headwear slot var/obj/item/head - var/obj/item/default_storage = /obj/item/storage/backpack/duffelbag/drone //If this exists, it will spawn in internal storage - var/obj/item/default_hatmask //If this exists, it will spawn in the hat/mask slot if it can fit - var/visualAppearence = MAINTDRONE //What we appear as - var/hacked = FALSE //If we have laws to destroy the station + /// Default [/mob/living/simple_animal/drone/var/internal_storage] item + var/obj/item/default_storage = /obj/item/storage/backpack/duffelbag/drone + /// Default [/mob/living/simple_animal/drone/var/head] item + var/obj/item/default_hatmask + /** + * icon_state of drone from icons/mobs/drone.dmi + * + * Possible states are: + * + * - [MAINTDRONE] + * - [REPAIRDRONE] + * - [SCOUTDRONE] + * - [CLOCKDRONE] + */ + var/visualAppearance = MAINTDRONE + /// Hacked state, see [/mob/living/simple_animal/drone/proc/update_drone_hack] + var/hacked = FALSE + /// Flavor text announced to drones on [/mob/proc/Login] var/flavortext = \ "\nDO NOT INTERFERE WITH THE ROUND AS A DRONE OR YOU WILL BE DRONE BANNED\n"+\ "Drones are a ghost role that are allowed to fix the station and build things. Interfering with the round as a drone is against the rules.\n"+\ @@ -101,7 +143,6 @@ for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diag_hud.add_to_hud(src) - /mob/living/simple_animal/drone/med_hud_set_health() var/image/holder = hud_list[DIAG_HUD] var/icon/I = icon(icon, icon_state, dir) @@ -132,7 +173,7 @@ to_chat(src, "[flavortext]") if(!picked) - pickVisualAppearence() + pickVisualAppearance() /mob/living/simple_animal/drone/auto_deadmin_on_login() if(!client?.holder) @@ -209,6 +250,15 @@ to_chat(src, "HeAV% DA%^MMA+G TO I/O CIR!%UUT!") +/** + * Alerts drones about different priorities of alarms + * + * Arguments: + * * class - One of the keys listed in [/mob/living/simple_animal/drone/var/alarms] + * * A - [/area] the alarm occurs + * * O - unused argument, see [/mob/living/silicon/robot/triggerAlarm] + * * alarmsource - [/atom] source of the alarm + */ /mob/living/simple_animal/drone/proc/triggerAlarm(class, area/A, O, obj/alarmsource) if(alarmsource.z != z) return @@ -224,7 +274,14 @@ L[A.name] = list(A, list(alarmsource)) to_chat(src, "--- [class] alarm detected in [A.name]!") - +/** + * Clears alarm and alerts drones + * + * Arguments: + * * class - One of the keys listed in [/mob/living/simple_animal/drone/var/alarms] + * * A - [/area] the alarm occurs + * * alarmsource - [/atom] source of the alarm + */ /mob/living/simple_animal/drone/proc/cancelAlarm(class, area/A, obj/origin) if(stat != DEAD) var/list/L = alarms[class] diff --git a/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm b/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm index 3076024be7e..4f3c218c2e9 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm @@ -5,7 +5,12 @@ /////////////////// //Drone shells -//DRONE SHELL +/** Drone Shell: Ghost role item for drones + * + * A simple mob spawner item that transforms into a maintenance drone + * Resepcts drone minimum age + */ + /obj/effect/mob_spawn/drone name = "drone shell" desc = "A shell of a maintenance drone, an expendable robot built to perform station repairs." @@ -15,7 +20,8 @@ density = FALSE death = FALSE roundstart = FALSE - mob_type = /mob/living/simple_animal/drone //Type of drone that will be spawned + ///Type of drone that will be spawned + mob_type = /mob/living/simple_animal/drone /obj/effect/mob_spawn/drone/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm index 44a2e96a414..3826a79a740 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm @@ -86,15 +86,15 @@ /mob/living/simple_animal/drone/polymorphed/Initialize() . = ..() liberate() - visualAppearence = pick(MAINTDRONE, REPAIRDRONE, SCOUTDRONE) - if(visualAppearence == MAINTDRONE) + visualAppearance = pick(MAINTDRONE, REPAIRDRONE, SCOUTDRONE) + if(visualAppearance == MAINTDRONE) var/colour = pick("grey", "blue", "red", "green", "pink", "orange") - icon_state = "[visualAppearence]_[colour]" + icon_state = "[visualAppearance]_[colour]" else - icon_state = visualAppearence + icon_state = visualAppearance icon_living = icon_state - icon_dead = "[visualAppearence]_dead" + icon_dead = "[visualAppearance]_dead" /obj/effect/mob_spawn/drone/derelict name = "derelict drone shell" diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm index 45bdd5d1982..910bd640a08 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm @@ -53,6 +53,15 @@ DH.slot_flags = worn_slot_flags user.put_in_hands(DH) +/** + * Called when a drone attempts to reactivate a dead drone + * + * If the owner is still ghosted, will notify them. + * If the owner cannot be found, fails with an error message. + * + * Arguments: + * * user - The [/mob/living] attempting to reactivate the drone + */ /mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user) var/mob/dead/observer/G = get_ghost() if(!client && (!G || !G.client)) @@ -111,6 +120,18 @@ /mob/living/simple_animal/drone/proc/get_armor_effectiveness() return 0 //multiplier for whatever head armor you wear as a drone +/** + * Hack or unhack a drone + * + * This changes the drone's laws to destroy the station or resets them + * to normal. + * + * Some debuffs are applied like slowing the drone down and disabling + * vent crawling + * + * Arguments + * * hack - Boolean if the drone is being hacked or unhacked + */ /mob/living/simple_animal/drone/proc/update_drone_hack(hack) if(!mind) return @@ -147,32 +168,44 @@ ventcrawler = initial(ventcrawler) speed = initial(speed) message_admins("[ADMIN_LOOKUPFLW(src)], a hacked drone, was restored to factory defaults!") - update_drone_icon() + update_drone_icon_hacked() +/** + * # F R E E D R O N E + * ### R + * ### E + * ### E + * ### D + * ### R + * ### O + * ### N + * ### E + */ /mob/living/simple_animal/drone/proc/liberate() - // F R E E D R O N E laws = "1. You are a Free Drone." to_chat(src, laws) -/mob/living/simple_animal/drone/proc/update_drone_icon() - //Different icons for different hack states - if(!hacked) - if(visualAppearence == SCOUTDRONE_HACKED) - visualAppearence = SCOUTDRONE - else if(visualAppearence == REPAIRDRONE_HACKED) - visualAppearence = REPAIRDRONE - else if(visualAppearence == MAINTDRONE_HACKED) - visualAppearence = MAINTDRONE + "_[colour]" - else if(hacked) - if(visualAppearence == SCOUTDRONE) - visualAppearence = SCOUTDRONE_HACKED - else if(visualAppearence == REPAIRDRONE) - visualAppearence = REPAIRDRONE_HACKED - else if(visualAppearence == MAINTDRONE) - visualAppearence = MAINTDRONE_HACKED - - icon_living = "[visualAppearence]" - icon_dead = "[visualAppearence]_dead" +/** + * Changes the icon state to a hacked version + * + * See also + * * [/mob/living/simple_animal/drone/var/visualAppearance] + * * [MAINTDRONE] + * * [REPAIRDRONE] + * * [SCOUTDRONE] + */ +/mob/living/simple_animal/drone/proc/update_drone_icon_hacked() //this is hacked both ways + var/static/hacked_appearances = list( + SCOUTDRONE = SCOUTDRONE_HACKED, + REPAIRDRONE = REPAIRDRONE_HACKED, + MAINTDRONE = MAINTDRONE_HACKED + ) + if(hacked) + icon_living = hacked_appearances[visualAppearance] + else if(visualAppearance == MAINTDRONE && colour) + icon_living = "[visualAppearance]_[colour]" + else + icon_living = visualAppearance if(stat == DEAD) icon_state = icon_dead else diff --git a/code/modules/mob/living/simple_animal/friendly/drone/say.dm b/code/modules/mob/living/simple_animal/friendly/drone/say.dm index 7a5967948f5..26bdbf379d7 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/say.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/say.dm @@ -1,5 +1,14 @@ -//Base proc for anything to call -/proc/_alert_drones(msg, dead_can_hear = 0, atom/source, mob/living/faction_checked_mob, exact_faction_match) +/** + * Broadcast a message to all drones in a faction + * + * Arguments: + * * msg - The message to send + * * dead_can_hear - Boolean that determines if ghosts can hear the message (`FALSE` by default) + * * source - [/atom] source that created the message + * * faction_checked_mob - [/mob/living] to determine faction matches from + * * exact_faction_match - Passed to [/mob/proc/faction_check_mob] + */ +/proc/_alert_drones(msg, dead_can_hear = FALSE, atom/source, mob/living/faction_checked_mob, exact_faction_match) if (dead_can_hear && source) for (var/mob/M in GLOB.dead_mob_list) var/link = FOLLOW_LINK(M, source) @@ -15,11 +24,21 @@ -//Wrapper for drones to handle factions +/** + * Wraps [/proc/_alert_drones] with defaults + * + * * source - `src` + * * faction_check_mob - `src` + * * dead_can_hear - `TRUE` + */ /mob/living/simple_animal/drone/proc/alert_drones(msg, dead_can_hear = FALSE) _alert_drones(msg, dead_can_hear, src, src, TRUE) - +/** + * Wraps [/mob/living/simple_animal/drone/proc/alert_drones] as a Drone Chat + * + * Shares the same radio code with binary + */ /mob/living/simple_animal/drone/proc/drone_chat(msg) alert_drones("Drone Chat: [name] [say_quote(msg)]", TRUE) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/verbs.dm b/code/modules/mob/living/simple_animal/friendly/drone/verbs.dm index 0f0d4dea72a..1eef305ff20 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/verbs.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/verbs.dm @@ -4,7 +4,11 @@ /////////////// //Drone verbs that appear in the Drone tab and on buttons - +/** + * Echoes drone laws to the user + * + * See [/mob/living/simple_animal/drone/var/laws] + */ /mob/living/simple_animal/drone/verb/check_laws() set category = "Drone" set name = "Check Laws" @@ -12,6 +16,17 @@ to_chat(src, "Drone Laws") to_chat(src, laws) +/** + * Creates an alert to drones in the same network + * + * Prompts user for alert level of: + * * Low + * * Medium + * * High + * * Critical + * + * Attaches area name to message + */ /mob/living/simple_animal/drone/verb/drone_ping() set category = "Drone" set name = "Drone ping" diff --git a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm index 219e5d8fd0d..aaa6f773c05 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm @@ -92,29 +92,35 @@ update_inv_head() update_inv_internal_storage() - -/mob/living/simple_animal/drone/proc/pickVisualAppearence() +/** + * Prompt for usr to pick [/mob/living/simple_animal/drone/var/visualAppearance] + * + * Does nothing if there is no usr + * + * Called on [/mob/proc/Login] + */ +/mob/living/simple_animal/drone/proc/pickVisualAppearance() picked = FALSE var/appearence = input("Choose your appearance!", "Appearance", "Maintenance Drone") in sortList(list("Maintenance Drone", "Repair Drone", "Scout Drone")) switch(appearence) if("Maintenance Drone") - visualAppearence = MAINTDRONE + visualAppearance = MAINTDRONE colour = input("Choose your colour!", "Colour", "grey") in sortList(list("grey", "blue", "red", "green", "pink", "orange")) - icon_state = "[visualAppearence]_[colour]" - icon_living = "[visualAppearence]_[colour]" - icon_dead = "[visualAppearence]_dead" + icon_state = "[visualAppearance]_[colour]" + icon_living = "[visualAppearance]_[colour]" + icon_dead = "[visualAppearance]_dead" if("Repair Drone") - visualAppearence = REPAIRDRONE - icon_state = visualAppearence - icon_living = visualAppearence - icon_dead = "[visualAppearence]_dead" + visualAppearance = REPAIRDRONE + icon_state = visualAppearance + icon_living = visualAppearance + icon_dead = "[visualAppearance]_dead" if("Scout Drone") - visualAppearence = SCOUTDRONE - icon_state = visualAppearence - icon_living = visualAppearence - icon_dead = "[visualAppearence]_dead" + visualAppearance = SCOUTDRONE + icon_state = visualAppearance + icon_living = visualAppearance + icon_dead = "[visualAppearance]_dead" else return @@ -124,7 +130,7 @@ /mob/living/simple_animal/drone/proc/getItemPixelShiftY() - switch(visualAppearence) + switch(visualAppearance) if(MAINTDRONE) . = 0 if(REPAIRDRONE,SCOUTDRONE,CLOCKDRONE) diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index c0d4cca57d3..938cdf137f6 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -23,8 +23,7 @@ maxHealth = 60 health = 60 speed = 0 - spacewalk = TRUE - + obj_damage = 60 melee_damage_lower = 20 melee_damage_upper = 30 @@ -38,14 +37,18 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = 1500 - + faction = list("russian") - + footstep_type = FOOTSTEP_MOB_CLAW - + var/armored = FALSE var/rideable = FALSE - + +/mob/living/simple_animal/hostile/bear/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) + /mob/living/simple_animal/hostile/bear/Life() . = ..() if(!rideable && mind) @@ -58,12 +61,12 @@ D.set_vehicle_dir_layer(EAST, ABOVE_MOB_LAYER) D.set_vehicle_dir_layer(WEST, ABOVE_MOB_LAYER) rideable = TRUE - + /mob/living/simple_animal/hostile/bear/update_icons() ..() if(armored) add_overlay("armor_bear") - + //SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!! diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index 5f810bb1ef1..fe18427f9aa 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -32,7 +32,6 @@ response_harm_simple = "squash" maxHealth = 10 health = 10 - spacewalk = TRUE faction = list("hostile") move_to_delay = 0 obj_damage = 0 @@ -62,6 +61,7 @@ /mob/living/simple_animal/hostile/poison/bees/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) generate_bee_visuals() AddComponent(/datum/component/swarming) diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index ca65386c6ae..895baab6e9a 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -21,7 +21,6 @@ speed = 0 maxHealth = 25 health = 25 - spacewalk = TRUE search_objects = 1 wanted_objects = list(/obj/item/storage/cans) @@ -69,6 +68,7 @@ /mob/living/simple_animal/hostile/carp/Initialize(mapload) . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) carp_randomify(rarechance) update_icons() diff --git a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm index 75b54e67c9d..57a33c2ee02 100644 --- a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm +++ b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm @@ -29,9 +29,12 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = 1500 - spacewalk = TRUE gold_core_spawnable = HOSTILE_SPAWN faction = list("spooky") del_on_death = 1 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS + +/mob/living/simple_animal/hostile/eyeball/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index cfac04eccbb..317dd4f9198 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -15,7 +15,6 @@ speed = 0 maxHealth = 80 health = 80 - spacewalk = TRUE stat_attack = UNCONSCIOUS robust_searching = 1 @@ -36,6 +35,10 @@ footstep_type = FOOTSTEP_MOB_SHOE +/mob/living/simple_animal/hostile/faithless/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) + /mob/living/simple_animal/hostile/faithless/AttackingTarget() . = ..() if(. && prob(12) && iscarbon(target)) diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 085de510910..c22a22c979e 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -209,10 +209,10 @@ . = ..() if(slowed_by_webs) if(!(locate(/obj/structure/spider/stickyweb) in loc)) - remove_movespeed_modifier(MOVESPEED_ID_TARANTULA_WEB) + remove_movespeed_modifier(/datum/movespeed_modifier/tarantula_web) slowed_by_webs = FALSE else if(locate(/obj/structure/spider/stickyweb) in loc) - add_movespeed_modifier(MOVESPEED_ID_TARANTULA_WEB, priority=100, multiplicative_slowdown=3) + add_movespeed_modifier(/datum/movespeed_modifier/tarantula_web) slowed_by_webs = TRUE /mob/living/simple_animal/hostile/poison/giant_spider/ice //spiders dont usually like tempatures of 140 kelvin who knew diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index 7696cb4bca3..037dfb9ef08 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -3,7 +3,6 @@ desc = "Attack the weak point for massive damage." health = 1000 maxHealth = 1000 - spacewalk = TRUE a_intent = INTENT_HARM sentience_type = SENTIENCE_BOSS environment_smash = ENVIRONMENT_SMASH_RWALLS @@ -49,6 +48,7 @@ AddComponent(/datum/component/gps, gps_name) apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) ADD_TRAIT(src, TRAIT_NO_TELEPORT, MEGAFAUNA_TRAIT) + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) for(var/action_type in attack_action_types) var/datum/action/innate/megafauna_attack/attack_action = new action_type() attack_action.Grant(src) diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index fbcdc85283a..886a23f62d6 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -52,7 +52,10 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 speed = 1 - spacewalk = TRUE + +/mob/living/simple_animal/hostile/pirate/melee/space/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) /mob/living/simple_animal/hostile/pirate/melee/Initialize() . = ..() @@ -89,4 +92,7 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 speed = 1 - spacewalk = TRUE + +/mob/living/simple_animal/hostile/pirate/ranged/space/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm index 163d5a818f0..a8404e7e970 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm @@ -14,7 +14,6 @@ speak_chance = 0 maxHealth = 15 health = 15 - spacewalk = TRUE see_in_dark = 10 harm_intent_damage = 6 melee_damage_lower = 6 @@ -39,3 +38,7 @@ //Space bats need no air to fly in. atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 + +/mob/living/simple_animal/hostile/retaliate/bat/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index cb247e60d4a..7ec2c1e24b2 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -59,10 +59,10 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 speed = 1 - spacewalk = TRUE /mob/living/simple_animal/hostile/syndicate/space/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) set_light(4) /mob/living/simple_animal/hostile/syndicate/space/stormtrooper @@ -93,11 +93,11 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 speed = 1 - spacewalk = TRUE projectile_deflect_chance = 50 /mob/living/simple_animal/hostile/syndicate/melee/space/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) set_light(4) /mob/living/simple_animal/hostile/syndicate/melee/space/stormtrooper @@ -145,11 +145,11 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 speed = 1 - spacewalk = TRUE projectile_deflect_chance = 50 /mob/living/simple_animal/hostile/syndicate/melee/sword/space/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) sord = new(src) set_light(4) @@ -192,10 +192,10 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 speed = 1 - spacewalk = TRUE /mob/living/simple_animal/hostile/syndicate/ranged/space/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) set_light(4) /mob/living/simple_animal/hostile/syndicate/ranged/space/stormtrooper @@ -225,10 +225,10 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 speed = 1 - spacewalk = TRUE /mob/living/simple_animal/hostile/syndicate/ranged/smg/space/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) set_light(4) /mob/living/simple_animal/hostile/syndicate/ranged/smg/space/stormtrooper @@ -255,10 +255,10 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 speed = 1 - spacewalk = TRUE /mob/living/simple_animal/hostile/syndicate/ranged/shotgun/space/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) set_light(4) /mob/living/simple_animal/hostile/syndicate/ranged/shotgun/space/stormtrooper diff --git a/code/modules/mob/living/simple_animal/hostile/zombie.dm b/code/modules/mob/living/simple_animal/hostile/zombie.dm index 32e6bf2d802..756ecc33249 100644 --- a/code/modules/mob/living/simple_animal/hostile/zombie.dm +++ b/code/modules/mob/living/simple_animal/hostile/zombie.dm @@ -18,7 +18,6 @@ a_intent = INTENT_HARM atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 - spacewalk = FALSE status_flags = CANPUSH del_on_death = 1 var/zombiejob = "Medical Doctor" diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index a3795de4cec..95c9b60c146 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -9,7 +9,6 @@ mob_biotypes = MOB_SPIRIT maxHealth = 40 health = 40 - spacewalk = TRUE healable = 0 speak_emote = list("hisses") emote_hear = list("wails.","screeches.") @@ -35,6 +34,10 @@ del_on_death = TRUE initial_language_holder = /datum/language_holder/construct +/mob/living/simple_animal/shade/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) + /mob/living/simple_animal/shade/death() deathmessage = "lets out a contented sigh as [p_their()] form unwinds." ..() diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 329af982d56..313b6738c53 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -388,8 +388,8 @@ /mob/living/simple_animal/proc/update_simplemob_varspeed() if(speed == 0) - remove_movespeed_modifier(MOVESPEED_ID_SIMPLEMOB_VARSPEED, TRUE) - add_movespeed_modifier(MOVESPEED_ID_SIMPLEMOB_VARSPEED, TRUE, 100, multiplicative_slowdown = speed, override = TRUE) + remove_movespeed_modifier(/datum/movespeed_modifier/simplemob_varspeed) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/simplemob_varspeed, multiplicative_slowdown = speed) /mob/living/simple_animal/Stat() ..() diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 0e469a4a937..996b82f6000 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -145,14 +145,14 @@ /mob/living/simple_animal/slime/on_reagent_change() . = ..() - remove_movespeed_modifier(MOVESPEED_ID_SLIME_REAGENTMOD, TRUE) + remove_movespeed_modifier(/datum/movespeed_modifier/slime_reagentmod) var/amount = 0 if(reagents.has_reagent(/datum/reagent/medicine/morphine)) // morphine slows slimes down amount = 2 if(reagents.has_reagent(/datum/reagent/consumable/frostoil)) // Frostoil also makes them move VEEERRYYYYY slow amount = 5 if(amount) - add_movespeed_modifier(MOVESPEED_ID_SLIME_REAGENTMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/slime_reagentmod, multiplicative_slowdown = amount) /mob/living/simple_animal/slime/updatehealth() . = ..() @@ -163,7 +163,7 @@ mod += (health_deficiency / 25) if(health <= 0) mod += 2 - add_movespeed_modifier(MOVESPEED_ID_SLIME_HEALTHMOD, TRUE, 100, multiplicative_slowdown = mod, override = TRUE) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/slime_healthmod, multiplicative_slowdown = mod) update_health_hud() /mob/living/simple_animal/slime/update_health_hud() @@ -201,7 +201,7 @@ else if(bodytemperature < 283.222) mod = ((283.222 - bodytemperature) / 10) * 1.75 if(mod) - add_movespeed_modifier(MOVESPEED_ID_SLIME_TEMPMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = mod) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/slime_tempmod, multiplicative_slowdown = mod) /mob/living/simple_animal/slime/ObjBump(obj/O) if(!client && powerlevel > 0) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index ca336b3ca7e..0101a376d5d 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1233,17 +1233,22 @@ /// Updates the grab state of the mob and updates movespeed /mob/setGrabState(newstate) . = ..() - if(grab_state == GRAB_PASSIVE) - remove_movespeed_modifier(MOVESPEED_ID_MOB_GRAB_STATE, update=TRUE) - else - add_movespeed_modifier(MOVESPEED_ID_MOB_GRAB_STATE, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=grab_state*3, blacklisted_movetypes=FLOATING) + switch(grab_state) + if(GRAB_PASSIVE) + remove_movespeed_modifier(MOVESPEED_ID_MOB_GRAB_STATE) + if(GRAB_AGGRESSIVE) + add_movespeed_modifier(/datum/movespeed_modifier/grab_slowdown/aggressive) + if(GRAB_NECK) + add_movespeed_modifier(/datum/movespeed_modifier/grab_slowdown/neck) + if(GRAB_KILL) + add_movespeed_modifier(/datum/movespeed_modifier/grab_slowdown/kill) /mob/proc/update_equipment_speed_mods() var/speedies = equipped_speed_mods() if(!speedies) - remove_movespeed_modifier(MOVESPEED_ID_MOB_EQUIPMENT, update=TRUE) + remove_movespeed_modifier(/datum/movespeed_modifier/equipment_speedmod) else - add_movespeed_modifier(MOVESPEED_ID_MOB_EQUIPMENT, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=speedies, blacklisted_movetypes=FLOATING) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/equipment_speedmod, multiplicative_slowdown = speedies) /// Gets the combined speed modification of all worn items /// Except base mob type doesnt really wear items diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 7f1ffcbe6d3..e572467b952 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -68,9 +68,6 @@ /// What is the mobs real name (name is overridden for disguises etc) var/real_name = null - /// can this mob move freely in space (should be a trait) - var/spacewalk = FALSE - /** * back up of the real name during admin possession * diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 7739c731cfd..31fd71f7b42 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -265,7 +265,7 @@ * You can move in space if you have a spacewalk ability */ /mob/Process_Spacemove(movement_dir = 0) - if(spacewalk || ..()) + if(HAS_TRAIT(src, TRAIT_SPACEWALK) || ..()) return TRUE var/atom/movable/backup = get_spacemove_backup() if(backup) @@ -326,9 +326,9 @@ /mob/proc/update_gravity(has_gravity, override=FALSE) var/speed_change = max(0, has_gravity - STANDARD_GRAVITY) if(!speed_change) - remove_movespeed_modifier(MOVESPEED_ID_MOB_GRAVITY, update=TRUE) + remove_movespeed_modifier(/datum/movespeed_modifier/gravity) else - add_movespeed_modifier(MOVESPEED_ID_MOB_GRAVITY, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=speed_change, blacklisted_movetypes=FLOATING) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/gravity, multiplicative_slowdown=speed_change) //bodypart selection verbs - Cyberboss //8:repeated presses toggles through head - eyes - mouth diff --git a/code/modules/mob/mob_movespeed.dm b/code/modules/mob/mob_movespeed.dm deleted file mode 100644 index 60af7098853..00000000000 --- a/code/modules/mob/mob_movespeed.dm +++ /dev/null @@ -1,166 +0,0 @@ -/*! How move speed for mobs works - -Move speed is now calculated by using a list of movespeed modifiers, which is a list itself (to avoid datum overhead) - -This gives us the ability to have multiple sources of movespeed, reliabily keep them applied and remove them when they should be - -THey can have unique sources and a bunch of extra fancy flags that control behaviour - -Previously trying to update move speed was a shot in the dark that usually meant mobs got stuck going faster or slower - -This list takes the following format - -```Current movespeed modification list format: - list( - id = list( - priority, - flags, - legacy slowdown/speedup amount, - movetype_flags - ) - ) -``` - -WHen update movespeed is called, the list of items is iterated, according to flags priority and a bunch of conditions -this spits out a final calculated value which is used as a modifer to last_move + modifier for calculating when a mob -can next move - -Key procs -* [add_movespeed_modifier](mob.html#proc/add_movespeed_modifier) -* [remove_movespeed_modifier](mob.html#proc/remove_movespeed_modifier) -* [has_movespeed_modifier](mob.html#proc/has_movespeed_modifier) -* [update_movespeed](mob.html#proc/update_movespeed) -*/ - -//ANY ADD/REMOVE DONE IN UPDATE_MOVESPEED MUST HAVE THE UPDATE ARGUMENT SET AS FALSE! - -///Add a move speed modifier to a mob -/mob/proc/add_movespeed_modifier(id, update=TRUE, priority=0, flags=NONE, override=FALSE, multiplicative_slowdown=0, movetypes=ALL, blacklisted_movetypes=NONE, conflict=FALSE) - var/list/temp = list(priority, flags, multiplicative_slowdown, movetypes, blacklisted_movetypes, conflict) //build the modification list - var/resort = TRUE - if(LAZYACCESS(movespeed_modification, id)) - var/list/existing_data = movespeed_modification[id] - if(movespeed_modifier_identical_check(existing_data, temp)) - return FALSE - if(!override) - return FALSE - if(priority == existing_data[MOVESPEED_DATA_INDEX_PRIORITY]) - resort = FALSE // We don't need to re-sort if we're replacing something already there and it's the same priority - LAZYSET(movespeed_modification, id, temp) - if(update) - update_movespeed(resort) - return TRUE - -///Remove a move speed modifier from a mob -/mob/proc/remove_movespeed_modifier(id, update = TRUE) - if(!LAZYACCESS(movespeed_modification, id)) - return FALSE - LAZYREMOVE(movespeed_modification, id) - UNSETEMPTY(movespeed_modification) - if(update) - update_movespeed(FALSE) - return TRUE - -///Handles the special case of editing the movement var -/mob/vv_edit_var(var_name, var_value) - var/slowdown_edit = (var_name == NAMEOF(src, cached_multiplicative_slowdown)) - var/diff - if(slowdown_edit && isnum(cached_multiplicative_slowdown) && isnum(var_value)) - remove_movespeed_modifier(MOVESPEED_ID_ADMIN_VAREDIT) - diff = var_value - cached_multiplicative_slowdown - . = ..() - if(. && slowdown_edit && isnum(diff)) - add_movespeed_modifier(MOVESPEED_ID_ADMIN_VAREDIT, TRUE, 100, override = TRUE, multiplicative_slowdown = diff) - -///Is there a movespeed modifier for this mob -/mob/proc/has_movespeed_modifier(id) - return LAZYACCESS(movespeed_modification, id) - -///Set or update the global movespeed config on a mob -/mob/proc/update_config_movespeed() - add_movespeed_modifier(MOVESPEED_ID_CONFIG_SPEEDMOD, FALSE, 100, override = TRUE, multiplicative_slowdown = get_config_multiplicative_speed()) - -///Get the global config movespeed of a mob by type -/mob/proc/get_config_multiplicative_speed() - if(!islist(GLOB.mob_config_movespeed_type_lookup) || !GLOB.mob_config_movespeed_type_lookup[type]) - return 0 - else - return GLOB.mob_config_movespeed_type_lookup[type] - -///Go through the list of movespeed modifiers and calculate a final movespeed -/mob/proc/update_movespeed(resort = TRUE) - if(resort) - sort_movespeed_modlist() - . = 0 - var/list/conflict_tracker = list() - for(var/id in get_movespeed_modifiers()) - var/list/data = movespeed_modification[id] - if(!(data[MOVESPEED_DATA_INDEX_MOVETYPE] & movement_type)) // We don't affect any of these move types, skip - continue - if(data[MOVESPEED_DATA_INDEX_BL_MOVETYPE] & movement_type) // There's a movetype here that disables this modifier, skip - continue - var/conflict = data[MOVESPEED_DATA_INDEX_CONFLICT] - var/amt = data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN] - if(conflict) - // Conflicting modifiers prioritize the larger slowdown or the larger speedup - // We purposefuly don't handle mixing speedups and slowdowns on the same id - if(abs(conflict_tracker[conflict]) < abs(amt)) - conflict_tracker[conflict] = amt - else - continue - . += amt - cached_multiplicative_slowdown = . - -///Get the move speed modifiers list of the mob -/mob/proc/get_movespeed_modifiers() - return movespeed_modification - -///Check if a movespeed modifier is identical to another -/mob/proc/movespeed_modifier_identical_check(list/mod1, list/mod2) - if(!islist(mod1) || !islist(mod2) || mod1.len < MOVESPEED_DATA_INDEX_MAX || mod2.len < MOVESPEED_DATA_INDEX_MAX) - return FALSE - for(var/i in 1 to MOVESPEED_DATA_INDEX_MAX) - if(mod1[i] != mod2[i]) - return FALSE - return TRUE - -///Calculate the total slowdown of all movespeed modifiers -/mob/proc/total_multiplicative_slowdown() - . = 0 - for(var/id in get_movespeed_modifiers()) - var/list/data = movespeed_modification[id] - . += data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN] - -///Checks if a move speed modifier is valid and not missing any data -/proc/movespeed_data_null_check(list/data) //Determines if a data list is not meaningful and should be discarded. - . = TRUE - if(data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN]) - . = FALSE - -/** - * Sort the list of move speed modifiers - * - * Verifies it too. Sorts highest priority (first applied) to lowest priority (last applied) - */ -/mob/proc/sort_movespeed_modlist() - if(!movespeed_modification) - return - var/list/assembled = list() - for(var/our_id in movespeed_modification) - var/list/our_data = movespeed_modification[our_id] - if(!islist(our_data) || (our_data.len < MOVESPEED_DATA_INDEX_PRIORITY) || movespeed_data_null_check(our_data)) - movespeed_modification -= our_id - continue - var/our_priority = our_data[MOVESPEED_DATA_INDEX_PRIORITY] - var/resolved = FALSE - for(var/their_id in assembled) - var/list/their_data = assembled[their_id] - if(their_data[MOVESPEED_DATA_INDEX_PRIORITY] < our_priority) - assembled.Insert(assembled.Find(their_id), our_id) - assembled[our_id] = our_data - resolved = TRUE - break - if(!resolved) - assembled[our_id] = our_data - movespeed_modification = assembled - UNSETEMPTY(movespeed_modification) diff --git a/code/modules/movespeed/_movespeed_modifier.dm b/code/modules/movespeed/_movespeed_modifier.dm new file mode 100644 index 00000000000..c6bab4dd712 --- /dev/null +++ b/code/modules/movespeed/_movespeed_modifier.dm @@ -0,0 +1,212 @@ +/*! Movespeed modification datums. + + How move speed for mobs works + +Move speed is now calculated by using modifier datums which are added to mobs. Some of them (nonvariable ones) are globally cached, the variable ones are instanced and changed based on need. + +This gives us the ability to have multiple sources of movespeed, reliabily keep them applied and remove them when they should be + +THey can have unique sources and a bunch of extra fancy flags that control behaviour + +Previously trying to update move speed was a shot in the dark that usually meant mobs got stuck going faster or slower + +Movespeed modification list is a simple key = datum system. Key will be the datum's ID if it is overridden to not be null, or type if it is not. + +DO NOT override datum IDs unless you are going to have multiple types that must overwrite each other. It's more efficient to use types, ID functionality is only kept for cases where dynamic creation of modifiers need to be done. + +When update movespeed is called, the list of items is iterated, according to flags priority and a bunch of conditions +this spits out a final calculated value which is used as a modifer to last_move + modifier for calculating when a mob +can next move + +Key procs +* [add_movespeed_modifier](mob.html#proc/add_movespeed_modifier) +* [remove_movespeed_modifier](mob.html#proc/remove_movespeed_modifier) +* [has_movespeed_modifier](mob.html#proc/has_movespeed_modifier) +* [update_movespeed](mob.html#proc/update_movespeed) +*/ + +/datum/movespeed_modifier + /// Whether or not this is a variable modifier. Variable modifiers can NOT be ever auto-cached. ONLY CHECKED VIA INITIAL(), EFFECTIVELY READ ONLY (and for very good reason) + var/variable = FALSE + + /// Unique ID. You can never have different modifications with the same ID. By default, this SHOULD NOT be set. Only set it for cases where you're dynamically making modifiers/need to have two types overwrite each other. If unset, uses path as ID. + var/id + + /// Higher ones override lower priorities. This is NOT used for ID, ID must be unique, if it isn't unique the newer one overwrites automatically if overriding. + var/priority = 0 + var/flags = NONE + + /// Multiplicative slowdown + var/multiplicative_slowdown = 0 + + /// Movetypes this applies to + var/movetypes = ALL + + /// Movetypes this never applies to + var/blacklisted_movetypes = NONE + + /// Other modification datums this conflicts with. + var/conflicts_with + +GLOBAL_LIST_EMPTY(movespeed_modification_cache) + +/// Grabs a STATIC MODIFIER datum from cache. YOU MUST NEVER EDIT THESE DATUMS, OR IT WILL AFFECT ANYTHING ELSE USING IT TOO! +/proc/get_cached_movespeed_modifier(modtype) + if(!ispath(modtype, /datum/movespeed_modifier)) + CRASH("[modtype] is not a movespeed modification typepath.") + var/datum/movespeed_modifier/M = modtype + if(initial(M.variable)) + CRASH("[modtype] is a variable modifier, and can never be cached.") + M = GLOB.movespeed_modification_cache[modtype] + if(!M) + M = GLOB.movespeed_modification_cache[modtype] = new modtype + return M + +///Add a move speed modifier to a mob. If a variable subtype is passed in as the first argument, it will make a new datum. If ID conflicts, it will overwrite the old ID. +/mob/proc/add_movespeed_modifier(datum/movespeed_modifier/type_or_datum, update = TRUE) + if(ispath(type_or_datum)) + if(!initial(type_or_datum.variable)) + type_or_datum = get_cached_movespeed_modifier(type_or_datum) + else + type_or_datum = new type_or_datum + var/key = type_or_datum.id || type_or_datum.type //Our key will be ID if it's overridden, or if not, path. + var/datum/movespeed_modifier/existing = LAZYACCESS(movespeed_modification, key) + if(existing) + if(existing == type_or_datum) //same thing don't need to touch + return TRUE + remove_movespeed_modifier(existing, FALSE) + if(length(movespeed_modification)) + BINARY_INSERT(key, movespeed_modification, datum/movespeed_modifier, type_or_datum, priority, COMPARE_VALUE) + LAZYSET(movespeed_modification, key, type_or_datum) + if(update) + update_movespeed() + return TRUE + +/// Remove a move speed modifier from a mob, whether static or variable. +/mob/proc/remove_movespeed_modifier(datum/movespeed_modifier/type_id_datum, update = TRUE) + var/key + if(ispath(type_id_datum)) + key = initial(type_id_datum.id) || type_id_datum //id if set, path if not. + else if(!istext(type_id_datum)) //if it isn't text it has to be a datum, as it isn't a type. + key = type_id_datum.id || type_id_datum.type + else //assume it's an id + key = type_id_datum + if(!LAZYACCESS(movespeed_modification, key)) + return FALSE + LAZYREMOVE(movespeed_modification, key) + if(update) + update_movespeed(FALSE) + return TRUE + +/*! Used for variable slowdowns like hunger/health loss/etc, works somewhat like the old list-based modification adds. Returns the modifier datum if successful + How this SHOULD work is: + 1. Ensures type_id_datum one way or another refers to a /variable datum. This makes sure it can't be cached. This includes if it's already in the modification list. + 2. Instantiate a new datum if type_id_datum isn't already instantiated + in the list, using the type. Obviously, wouldn't work for ID only. + 3. Add the datum if necessary using the regular add proc + 4. If any of the rest of the args are not null (see: multiplicative slowdown), modify the datum + 5. Update if necessary +*/ +/mob/proc/add_or_update_variable_movespeed_modifier(datum/movespeed_modifier/type_id_datum, update = TRUE, multiplicative_slowdown) + var/modified = FALSE + var/inject = FALSE + var/datum/movespeed_modifier/final + if(istext(type_id_datum)) + final = LAZYACCESS(movespeed_modification, type_id_datum) + if(!final) + CRASH("Couldn't find existing modification when provided a text ID.") + else if(ispath(type_id_datum)) + if(!initial(type_id_datum.variable)) + CRASH("Not a variable modifier") + var/id = initial(type_id_datum.id) + final = LAZYACCESS(movespeed_modification, id || type_id_datum) + if(!final) + final = new type_id_datum + inject = TRUE + modified = TRUE + else + if(!initial(type_id_datum.variable)) + CRASH("Not a variable modifier") + final = type_id_datum + if(!LAZYACCESS(movespeed_modification, final.id || final.type)) + inject = TRUE + modified = TRUE + if(!isnull(multiplicative_slowdown)) + final.multiplicative_slowdown = multiplicative_slowdown + modified = TRUE + if(inject) + add_movespeed_modifier(final, FALSE) + if(update && modified) + update_movespeed(TRUE) + return final + +/// Handles the special case of editing the movement var +/mob/vv_edit_var(var_name, var_value) + var/slowdown_edit = (var_name == NAMEOF(src, cached_multiplicative_slowdown)) + var/diff + if(slowdown_edit && isnum(cached_multiplicative_slowdown) && isnum(var_value)) + remove_movespeed_modifier(/datum/movespeed_modifier/admin_varedit) + diff = var_value - cached_multiplicative_slowdown + . = ..() + if(. && slowdown_edit && isnum(diff)) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/admin_varedit, multiplicative_slowdown = diff) + +///Is there a movespeed modifier for this mob +/mob/proc/has_movespeed_modifier(datum/movespeed_modifier/datum_type_id) + var/key + if(ispath(datum_type_id)) + key = initial(datum_type_id.id) || datum_type_id + else if(istext(datum_type_id)) + key = datum_type_id + else + key = datum_type_id.id || datum_type_id.type + return LAZYACCESS(movespeed_modification, key) + +/// Set or update the global movespeed config on a mob +/mob/proc/update_config_movespeed() + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/mob_config_speedmod, multiplicative_slowdown = get_config_multiplicative_speed()) + +/// Get the global config movespeed of a mob by type +/mob/proc/get_config_multiplicative_speed() + if(!islist(GLOB.mob_config_movespeed_type_lookup) || !GLOB.mob_config_movespeed_type_lookup[type]) + return 0 + else + return GLOB.mob_config_movespeed_type_lookup[type] + +/// Go through the list of movespeed modifiers and calculate a final movespeed. ANY ADD/REMOVE DONE IN UPDATE_MOVESPEED MUST HAVE THE UPDATE ARGUMENT SET AS FALSE! +/mob/proc/update_movespeed() + . = 0 + var/list/conflict_tracker = list() + for(var/key in get_movespeed_modifiers()) + var/datum/movespeed_modifier/M = movespeed_modification[key] + if(!(M.movetypes & movement_type)) // We don't affect any of these move types, skip + continue + if(M.blacklisted_movetypes & movement_type) // There's a movetype here that disables this modifier, skip + continue + var/conflict = M.conflicts_with + var/amt = M.multiplicative_slowdown + if(conflict) + // Conflicting modifiers prioritize the larger slowdown or the larger speedup + // We purposefuly don't handle mixing speedups and slowdowns on the same id + if(abs(conflict_tracker[conflict]) < abs(amt)) + conflict_tracker[conflict] = amt + else + continue + . += amt + cached_multiplicative_slowdown = . + +/// Get the move speed modifiers list of the mob +/mob/proc/get_movespeed_modifiers() + return movespeed_modification + +/// Calculate the total slowdown of all movespeed modifiers +/mob/proc/total_multiplicative_slowdown() + . = 0 + for(var/id in get_movespeed_modifiers()) + var/datum/movespeed_modifier/M = movespeed_modification[id] + . += M.multiplicative_slowdown + +/// Checks if a move speed modifier is valid and not missing any data +/proc/movespeed_data_null_check(datum/movespeed_modifier/M) //Determines if a data list is not meaningful and should be discarded. + . = TRUE + if(M.multiplicative_slowdown) + . = FALSE diff --git a/code/modules/movespeed/modifiers/components.dm b/code/modules/movespeed/modifiers/components.dm new file mode 100644 index 00000000000..a8f0db50181 --- /dev/null +++ b/code/modules/movespeed/modifiers/components.dm @@ -0,0 +1,20 @@ +/datum/movespeed_modifier/shrink_ray + movetypes = GROUND + multiplicative_slowdown = 4 + +/datum/movespeed_modifier/snail_crawl + multiplicative_slowdown = -7 + movetypes = GROUND + +/datum/movespeed_modifier/sanity + id = MOVESPEED_ID_SANITY + movetypes = (~FLYING) + +/datum/movespeed_modifier/sanity/insane + multiplicative_slowdown = 1 + +/datum/movespeed_modifier/sanity/crazy + multiplicative_slowdown = 0.5 + +/datum/movespeed_modifier/sanity/disturbed + multiplicative_slowdown = 0.25 diff --git a/code/modules/movespeed/modifiers/innate.dm b/code/modules/movespeed/modifiers/innate.dm new file mode 100644 index 00000000000..ee4ed3a6ecf --- /dev/null +++ b/code/modules/movespeed/modifiers/innate.dm @@ -0,0 +1,14 @@ +/datum/movespeed_modifier/strained_muscles + multiplicative_slowdown = -1 + blacklisted_movetypes = (FLYING|FLOATING) + +/datum/movespeed_modifier/pai_spacewalk + multiplicative_slowdown = 2 + +/datum/movespeed_modifier/species + movetypes = ~FLYING + variable = TRUE + +/datum/movespeed_modifier/dna_vault_speedup + blacklisted_movetypes = (FLYING|FLOATING) + multiplicative_slowdown = -0.4 diff --git a/code/modules/movespeed/modifiers/items.dm b/code/modules/movespeed/modifiers/items.dm new file mode 100644 index 00000000000..e36c05dccee --- /dev/null +++ b/code/modules/movespeed/modifiers/items.dm @@ -0,0 +1,12 @@ +/datum/movespeed_modifier/jetpack + conflicts_with = MOVE_CONFLICT_JETPACK + movetypes = FLOATING + +/datum/movespeed_modifier/jetpack/cybernetic + multiplicative_slowdown = -0.5 + +/datum/movespeed_modifier/jetpack/fullspeed + multiplicative_slowdown = -0.5 + +/datum/movespeed_modifier/die_of_fate + multiplicative_slowdown = 1 diff --git a/code/modules/movespeed/modifiers/misc.dm b/code/modules/movespeed/modifiers/misc.dm new file mode 100644 index 00000000000..55c1aef5271 --- /dev/null +++ b/code/modules/movespeed/modifiers/misc.dm @@ -0,0 +1,6 @@ +/datum/movespeed_modifier/admin_varedit + variable = TRUE + +/datum/movespeed_modifier/yellow_orb + multiplicative_slowdown = -2 + blacklisted_movetypes = (FLYING|FLOATING) diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm new file mode 100644 index 00000000000..cc92c38533e --- /dev/null +++ b/code/modules/movespeed/modifiers/mobs.dm @@ -0,0 +1,106 @@ +/datum/movespeed_modifier/obesity + multiplicative_slowdown = 1.5 + +/datum/movespeed_modifier/monkey_reagent_speedmod + variable = TRUE + +/datum/movespeed_modifier/monkey_health_speedmod + variable = TRUE + +/datum/movespeed_modifier/monkey_temperature_speedmod + variable = TRUE + +/datum/movespeed_modifier/hunger + variable = TRUE + +/datum/movespeed_modifier/slaughter + multiplicative_slowdown = -1 + +/datum/movespeed_modifier/damage_slowdown + blacklisted_movetypes = FLOATING|FLYING + variable = TRUE + +/datum/movespeed_modifier/damage_slowdown_flying + movetypes = FLOATING + variable = TRUE + +/datum/movespeed_modifier/equipment_speedmod + variable = TRUE + blacklisted_movetypes = FLOATING + +/datum/movespeed_modifier/grab_slowdown + id = MOVESPEED_ID_MOB_GRAB_STATE + blacklisted_movetypes = FLOATING + +/datum/movespeed_modifier/grab_slowdown/aggressive + multiplicative_slowdown = 3 + +/datum/movespeed_modifier/grab_slowdown/neck + multiplicative_slowdown = 6 + +/datum/movespeed_modifier/grab_slowdown/kill + multiplicative_slowdown = 9 + +/datum/movespeed_modifier/slime_reagentmod + variable = TRUE + +/datum/movespeed_modifier/slime_healthmod + variable = TRUE + +/datum/movespeed_modifier/config_walk_run + multiplicative_slowdown = 1 + id = MOVESPEED_ID_MOB_WALK_RUN + +/datum/movespeed_modifier/config_walk_run/proc/sync() + +/datum/movespeed_modifier/config_walk_run/walk/sync() + var/mod = CONFIG_GET(number/movedelay/walk_delay) + multiplicative_slowdown = isnum(mod)? mod : initial(multiplicative_slowdown) + +/datum/movespeed_modifier/config_walk_run/run/sync() + var/mod = CONFIG_GET(number/movedelay/run_delay) + multiplicative_slowdown = isnum(mod)? mod : initial(multiplicative_slowdown) + +/datum/movespeed_modifier/turf_slowdown + movetypes = GROUND + blacklisted_movetypes = (FLYING|FLOATING) + variable = TRUE + +/datum/movespeed_modifier/bulky_drag + variable = TRUE + +/datum/movespeed_modifier/cold + blacklisted_movetypes = FLOATING + variable = TRUE + +/datum/movespeed_modifier/shove + multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH + +/datum/movespeed_modifier/human_carry + multiplicative_slowdown = HUMAN_CARRY_SLOWDOWN + +/datum/movespeed_modifier/limbless + variable = TRUE + movetypes = GROUND + +/datum/movespeed_modifier/simplemob_varspeed + variable = TRUE + +/datum/movespeed_modifier/tarantula_web + multiplicative_slowdown = 3 + +/datum/movespeed_modifier/gravity + blacklisted_movetypes = FLOATING + variable = TRUE + +/datum/movespeed_modifier/carbon_softcrit + multiplicative_slowdown = SOFTCRIT_ADD_SLOWDOWN + +/datum/movespeed_modifier/slime_tempmod + variable = TRUE + +/datum/movespeed_modifier/carbon_crawling + multiplicative_slowdown = CRAWLING_ADD_SLOWDOWN + +/datum/movespeed_modifier/mob_config_speedmod + variable = TRUE diff --git a/code/modules/movespeed/modifiers/reagent.dm b/code/modules/movespeed/modifiers/reagent.dm new file mode 100644 index 00000000000..f1a54f98de3 --- /dev/null +++ b/code/modules/movespeed/modifiers/reagent.dm @@ -0,0 +1,32 @@ +/datum/movespeed_modifier/reagent + blacklisted_movetypes = (FLYING|FLOATING) + +/datum/movespeed_modifier/reagent/stimulants + multiplicative_slowdown = -1 + +/datum/movespeed_modifier/reagent/ephedrine + multiplicative_slowdown = -0.5 + +/datum/movespeed_modifier/reagent/pepperspray + multiplicative_slowdown = 0.25 + +/datum/movespeed_modifier/reagent/badstims + multiplicative_slowdown = -0.45 + +/datum/movespeed_modifier/reagent/monkey_energy + multiplicative_slowdown = -0.35 + +/datum/movespeed_modifier/reagent/changelinghaste + multiplicative_slowdown = -2 + +/datum/movespeed_modifier/reagent/methamphetamine + multiplicative_slowdown = -0.65 + +/datum/movespeed_modifier/reagent/nitryl + multiplicative_slowdown = -0.65 + +/datum/movespeed_modifier/reagent/lenturi + multiplicative_slowdown = 1.5 + +/datum/movespeed_modifier/reagent/nuka_cola + multiplicative_slowdown = -0.35 diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm new file mode 100644 index 00000000000..506a4672ef1 --- /dev/null +++ b/code/modules/movespeed/modifiers/status_effects.dm @@ -0,0 +1,17 @@ +/datum/movespeed_modifier/status_effect/bloodchill + multiplicative_slowdown = 3 + +/datum/movespeed_modifier/status_effect/bonechill + multiplicative_slowdown = 3 + +/datum/movespeed_modifier/status_effect/lightpink + multiplicative_slowdown = -0.5 + blacklisted_movetypes = (FLYING|FLOATING) + +/datum/movespeed_modifier/status_effect/tarfoot + multiplicative_slowdown = 0.5 + blacklisted_movetypes = (FLYING|FLOATING) + +/datum/movespeed_modifier/status_effect/sepia + variable = TRUE + blacklisted_movetypes = (FLYING|FLOATING) diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index 684dcc7c92b..d028cf8567b 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -125,7 +125,7 @@ var/obj/item/paper/P = new /obj/item/paper(src) P.info = "
Security Record

" P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]]
\nGender: [G.fields["gender"]]
\nAge: [G.fields["age"]]
\nFingerprint: [G.fields["fingerprint"]]
\nPhysical Status: [G.fields["p_stat"]]
\nMental Status: [G.fields["m_stat"]]
" - P.info += "
\n
Security Data

\nCriminal Status: [S.fields["criminal"]]
\n
\nMinor Crimes: [S.fields["mi_crim"]]
\nDetails: [S.fields["mi_crim_d"]]
\n
\nMajor Crimes: [S.fields["ma_crim"]]
\nDetails: [S.fields["ma_crim_d"]]
\n
\nImportant Notes:
\n\t[S.fields["notes"]]
\n
\n
Comments/Log

" + P.info += "
\n
Security Data

\nCriminal Status: [S.fields["criminal"]]
\n
\nCrimes: [S.fields["crim"]]
\nDetails: [S.fields["crim_d"]]
\n
\nImportant Notes:
\n\t[S.fields["notes"]]
\n
\n
Comments/Log

" var/counter = 1 while(S.fields["com_[counter]"]) P.info += "[S.fields["com_[counter]"]]
" diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm index 0b141d764a3..9d8699db3b4 100644 --- a/code/modules/plumbing/ducts.dm +++ b/code/modules/plumbing/ducts.dm @@ -7,7 +7,7 @@ All the important duct code: name = "fluid duct" icon = 'icons/obj/plumbing/fluid_ducts.dmi' icon_state = "nduct" - level = 1 + ///bitfield with the directions we're connected in var/connects ///set to TRUE to disable smart duct behaviour @@ -36,14 +36,16 @@ All the important duct code: ///wheter we just unanchored or drop whatever is in the variable. either is safe var/drop_on_wrench = /obj/item/stack/ducts -/obj/machinery/duct/Initialize(mapload, no_anchor, color_of_duct, layer_of_duct = DUCT_LAYER_DEFAULT, force_connects) +/obj/machinery/duct/Initialize(mapload, no_anchor, color_of_duct = "#ffffff", layer_of_duct = DUCT_LAYER_DEFAULT, force_connects) . = ..() + if(no_anchor) active = FALSE anchored = FALSE else if(!can_anchor()) qdel(src) CRASH("Overlapping ducts detected") + if(force_connects) connects = force_connects //skip change_connects() because we're still initializing and we need to set our connects at one point if(!lock_layers) @@ -52,15 +54,20 @@ All the important duct code: duct_color = color_of_duct if(duct_color) add_atom_colour(duct_color, FIXED_COLOUR_PRIORITY) + handle_layer() + for(var/obj/machinery/duct/D in loc) if(D == src) continue if(D.duct_layer & duct_layer) disconnect_duct() + if(active) attempt_connect() + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) + ///start looking around us for stuff to connect to /obj/machinery/duct/proc/attempt_connect() @@ -289,7 +296,7 @@ All the important duct code: if(!T) T = get_turf(src) for(var/obj/machinery/duct/D in T) - if(!anchored) + if(!anchored || D == src) continue for(var/A in GLOB.cardinals) if(A & connects && A & D.connects) @@ -325,6 +332,7 @@ All the important duct code: add_neighbour(D, direction) connect_network(D, direction, TRUE) update_icon() + ///has a total of 5 layers and doesnt give a shit about color. its also dumb so doesnt autoconnect. /obj/machinery/duct/multilayered name = "duct layer-manifold" diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index b2e452c0f63..9e65edb2206 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -17,7 +17,6 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri icon = 'icons/obj/power_cond/layer_cable.dmi' icon_state = "l2-1-2-4-8-node" color = "yellow" - level = 1 //is underfloor layer = WIRE_LAYER //Above hidden pipes, GAS_PIPE_HIDDEN_LAYER anchored = TRUE obj_flags = CAN_BE_HIT | ON_BLUEPRINTS @@ -41,12 +40,11 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri /obj/structure/cable/Initialize(mapload) . = ..() - var/turf/T = get_turf(src) // hide if turf is not intact - if(level==1) - hide(T.intact) GLOB.cable_list += src //add it to the global cable list connect_wire() + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) + /obj/structure/cable/proc/connect_wire(clear_before_updating = FALSE) var/under_thing = NONE if(clear_before_updating) @@ -115,12 +113,6 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri // General procedures /////////////////////////////////// -//If underfloor, hide the cable -/obj/structure/cable/hide(i) - if(level == 1 && isturf(loc)) - invisibility = i ? INVISIBILITY_MAXIMUM : 0 - update_icon() - /obj/structure/cable/update_icon_state() if(!linked_dirs) icon_state = "l[cable_layer]-noconnection" @@ -562,7 +554,6 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list(new/datum/stack_recipe("cable restrain desc = "A bridge to connect different cable layers, or link terminals to incompatible cable layers." icon = 'icons/obj/power.dmi' icon_state = "cable_bridge" - level = 1 //is underfloor layer = WIRE_LAYER + 0.02 //Above all the cables but below terminals anchored = TRUE obj_flags = CAN_BE_HIT | ON_BLUEPRINTS diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 892b62976e3..cd2ad7bb2a7 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -221,6 +221,14 @@ charge = 0 update_icon() +/obj/item/stock_parts/cell/mini_egun + name = "miniature energy gun power cell" + maxcharge = 600 + +/obj/item/stock_parts/cell/hos_gun + name = "X-01 multiphase energy gun power cell" + maxcharge = 1200 + /obj/item/stock_parts/cell/pulse //200 pulse shots name = "pulse rifle power cell" maxcharge = 40000 diff --git a/code/modules/power/terminal.dm b/code/modules/power/terminal.dm index a1c11b9dca0..0077193b250 100644 --- a/code/modules/power/terminal.dm +++ b/code/modules/power/terminal.dm @@ -7,16 +7,14 @@ name = "terminal" icon_state = "term" desc = "It's an underfloor wiring terminal for power equipment." - level = 1 layer = WIRE_TERMINAL_LAYER //a bit above wires var/obj/machinery/power/master = null /obj/machinery/power/terminal/Initialize() . = ..() - var/turf/T = get_turf(src) - if(level == 1) - hide(T.intact) + + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, use_alpha = TRUE) /obj/machinery/power/terminal/Destroy() if(master) @@ -27,15 +25,6 @@ /obj/machinery/power/terminal/should_have_node() return TRUE -/obj/machinery/power/terminal/hide(i) - if(i) - invisibility = INVISIBILITY_MAXIMUM - icon_state = "term-f" - else - invisibility = 0 - icon_state = "term" - - /obj/machinery/power/proc/can_terminal_dismantle() . = FALSE diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm index 0d027308603..7dedf94fade 100644 --- a/code/modules/projectiles/guns/energy/energy_gun.dm +++ b/code/modules/projectiles/guns/energy/energy_gun.dm @@ -17,7 +17,7 @@ icon_state = "mini" item_state = "gun" w_class = WEIGHT_CLASS_SMALL - cell_type = /obj/item/stock_parts/cell{charge = 600; maxcharge = 600} + cell_type = /obj/item/stock_parts/cell/mini_egun ammo_x_offset = 2 charge_sections = 3 can_flashlight = FALSE // Can't attach or detach the flashlight, and override it's icon update @@ -52,7 +52,7 @@ /obj/item/gun/energy/e_gun/hos name = "\improper X-01 MultiPhase Energy Gun" desc = "This is an expensive, modern recreation of an antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time." - cell_type = /obj/item/stock_parts/cell{charge = 1200; maxcharge = 1200} + cell_type = /obj/item/stock_parts/cell/hos_gun icon_state = "hoslaser" force = 10 ammo_type = list(/obj/item/ammo_casing/energy/disabler/hos, /obj/item/ammo_casing/energy/laser/hos, /obj/item/ammo_casing/energy/ion/hos) diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index 5e5fa7a0c06..00c490db743 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -446,8 +446,6 @@ new /obj/effect/hotspot(T) for(var/obj/O in range(aoe_structure_range, epicenter)) if(!isitem(O)) - if(O.level == 1) //Please don't break underfloor items! - continue O.take_damage(aoe_structure_damage * get_damage_coeff(O), BURN, "laser", FALSE) /obj/projectile/beam/beam_rifle/proc/check_pierce(atom/target) diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 20a7f7e3781..07f2a81873b 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -337,7 +337,6 @@ replace_beaker(user, B) to_chat(user, "You add [B] to [src].") updateUsrDialog() - update_icon() else if(user.a_intent != INTENT_HARM && !istype(I, /obj/item/card/emag)) to_chat(user, "You can't load [I] into [src]!") return ..() diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm index 59e49e9bf41..cb87676b534 100644 --- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm @@ -143,17 +143,19 @@ var/spammer = 0 /datum/reagent/medicine/C2/lenturi/on_mob_life(mob/living/carbon/M) - M.adjustFireLoss(-3 * REM) - M.adjustOrganLoss(ORGAN_SLOT_STOMACH, 0.4 * REM) - ..() - return TRUE -/datum/reagent/medicine/C2/lenturi/on_mob_metabolize(mob/living/carbon/M) - M.add_movespeed_modifier(MOVESPEED_ID_LENTURI, update=TRUE, priority=100, multiplicative_slowdown=1.50, blacklisted_movetypes=(FLYING|FLOATING)) - . = ..() -/datum/reagent/medicine/C2/lenturi/on_mob_end_metabolize(mob/living/carbon/M) - M.remove_movespeed_modifier(MOVESPEED_ID_LENTURI) + M.adjustFireLoss(-3 * REM) + M.adjustOrganLoss(ORGAN_SLOT_STOMACH, 0.4 * REM) + ..() + return TRUE + +/datum/reagent/medicine/C2/lenturi/on_mob_metabolize(mob/living/carbon/M) + M.add_movespeed_modifier(/datum/movespeed_modifier/reagent/lenturi) + return ..() + +/datum/reagent/medicine/C2/lenturi/on_mob_end_metabolize(mob/living/carbon/M) + M.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/lenturi) + return ..() - . = ..() /datum/reagent/medicine/C2/aiuri name = "Aiuri" description = "Used to treat burns. Does minor eye damage." diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index a10fc254eab..57d57650883 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -376,10 +376,10 @@ /datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/L) ..() - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.35, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/nuka_cola) /datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/L) - L.remove_movespeed_modifier(type) + L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/nuka_cola) ..() /datum/reagent/consumable/nuka_cola/on_mob_life(mob/living/carbon/M) @@ -565,17 +565,16 @@ /datum/reagent/consumable/monkey_energy/on_mob_metabolize(mob/living/L) ..() if(ismonkey(L)) - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.35, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/monkey_energy) /datum/reagent/consumable/monkey_energy/on_mob_end_metabolize(mob/living/L) - L.remove_movespeed_modifier(type) + L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/monkey_energy) ..() /datum/reagent/consumable/monkey_energy/overdose_process(mob/living/M) if(prob(15)) M.say(pick_list_replacements(BOOMER_FILE, "boomer"), forced = /datum/reagent/consumable/monkey_energy) ..() - return /datum/reagent/consumable/ice name = "Ice" diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index e20191c3358..5b21f771952 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -174,10 +174,10 @@ /datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L) ..() - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.65, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/methamphetamine) /datum/reagent/drug/methamphetamine/on_mob_end_metabolize(mob/living/L) - L.remove_movespeed_modifier(type) + L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/methamphetamine) ..() /datum/reagent/drug/methamphetamine/on_mob_life(mob/living/carbon/M) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index f6fa3d5d813..d4384cbf282 100755 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -293,8 +293,8 @@ victim.blind_eyes(3) // 6 seconds victim.confused = max(M.confused, 5) // 10 seconds victim.Knockdown(3 SECONDS) - victim.add_movespeed_modifier(MOVESPEED_ID_PEPPER_SPRAY, update=TRUE, priority=100, multiplicative_slowdown=0.25, blacklisted_movetypes=(FLYING|FLOATING)) - addtimer(CALLBACK(victim, /mob.proc/remove_movespeed_modifier, MOVESPEED_ID_PEPPER_SPRAY), 10 SECONDS) + victim.add_movespeed_modifier(/datum/movespeed_modifier/reagent/pepperspray) + addtimer(CALLBACK(victim, /mob.proc/remove_movespeed_modifier, /datum/movespeed_modifier/reagent/pepperspray), 10 SECONDS) victim.update_damage_hud() if(method == INGEST) if(!holder.has_reagent(/datum/reagent/consumable/milk)) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index e4688c2bb9d..b28e6e97fcd 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -437,11 +437,11 @@ /datum/reagent/medicine/ephedrine/on_mob_metabolize(mob/living/L) ..() - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/ephedrine) ADD_TRAIT(L, TRAIT_STUNRESISTANCE, type) /datum/reagent/medicine/ephedrine/on_mob_end_metabolize(mob/living/L) - L.remove_movespeed_modifier(type) + L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/ephedrine) REMOVE_TRAIT(L, TRAIT_STUNRESISTANCE, type) ..() @@ -811,11 +811,11 @@ /datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L) ..() - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants) ADD_TRAIT(L, TRAIT_STUNRESISTANCE, type) /datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L) - L.remove_movespeed_modifier(type) + L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants) REMOVE_TRAIT(L, TRAIT_STUNRESISTANCE, type) ..() @@ -1043,10 +1043,10 @@ /datum/reagent/medicine/changelinghaste/on_mob_metabolize(mob/living/L) ..() - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/changelinghaste) /datum/reagent/medicine/changelinghaste/on_mob_end_metabolize(mob/living/L) - L.remove_movespeed_modifier(type) + L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/changelinghaste) ..() /datum/reagent/medicine/changelinghaste/on_mob_life(mob/living/carbon/M) @@ -1294,14 +1294,14 @@ ..() ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, type) ADD_TRAIT(L, TRAIT_STUNRESISTANCE, type) - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.45, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/badstims) L.ignore_slowdown(type) /datum/reagent/medicine/badstims/on_mob_end_metabolize(mob/living/L) ..() REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, type) REMOVE_TRAIT(L, TRAIT_STUNRESISTANCE, type) - L.remove_movespeed_modifier(type) + L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/badstims) L.unignore_slowdown(type) L.Dizzy(0) L.Jitter(0) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index ffffd95e74a..e23346a4892 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -87,6 +87,7 @@ description = "You don't even want to think about what's in here." taste_description = "gross iron" shot_glass_icon_state = "shotglassred" + material = /datum/material/meat /datum/reagent/vaccine //data must contain virus type @@ -917,6 +918,7 @@ color = "#00CC00" // ditto taste_description = "the colour blue and regret" irradiation_level = 2*REM + material = null /datum/reagent/bluespace name = "Bluespace Dust" @@ -1243,10 +1245,10 @@ /datum/reagent/nitryl/on_mob_metabolize(mob/living/L) ..() - L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.65, blacklisted_movetypes=(FLYING|FLOATING)) + L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/nitryl) /datum/reagent/nitryl/on_mob_end_metabolize(mob/living/L) - L.remove_movespeed_modifier(type) + L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/nitryl) ..() /////////////////////////Colorful Powder//////////////////////////// diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 43e31425220..4c14d2c869a 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -35,7 +35,7 @@ /datum/reagent/toxin/mutagen/reaction_mob(mob/living/carbon/M, method=TOUCH, reac_volume) if(!..()) return - if(!M.has_dna()) + if(!M.has_dna() || (HAS_TRAIT(M, TRAIT_RADIMMUNE) || HAS_TRAIT(M, TRAIT_BADDNA))) return //No robots, AIs, aliens, Ians or other mobs should be affected by this. if((method==VAPOR && prob(min(33, reac_volume))) || method==INGEST || method==PATCH || method==INJECT) M.randmuti() diff --git a/code/modules/recycling/disposal/construction.dm b/code/modules/recycling/disposal/construction.dm index 566228adb52..b97d3a77b5f 100644 --- a/code/modules/recycling/disposal/construction.dm +++ b/code/modules/recycling/disposal/construction.dm @@ -9,7 +9,6 @@ anchored = FALSE density = FALSE pressure_resistance = 5*ONE_ATMOSPHERE - level = 2 max_integrity = 200 var/obj/pipe_type = /obj/structure/disposalpipe/segment var/pipename @@ -34,6 +33,8 @@ update_icon() + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) + /obj/structure/disposalconstruct/Move() var/old_dir = dir ..() @@ -45,10 +46,8 @@ if(is_pipe()) icon_state = "con[icon_state]" if(anchored) - level = initial(pipe_type.level) layer = initial(pipe_type.layer) else - level = initial(level) layer = initial(layer) else if(ispath(pipe_type, /obj/machinery/disposal/bin)) @@ -58,13 +57,6 @@ else icon_state = "condisposal" - -// hide called by levelupdate if turf intact status changes -// change visibility status and force update of icon -/obj/structure/disposalconstruct/hide(var/intact) - invisibility = (intact && level==1) ? INVISIBILITY_MAXIMUM: 0 // hide if floor is intact - update_icon() - /obj/structure/disposalconstruct/proc/get_disposal_dir() if(!is_pipe()) return NONE diff --git a/code/modules/recycling/disposal/pipe.dm b/code/modules/recycling/disposal/pipe.dm index 7f8e26b64ae..b488f636798 100644 --- a/code/modules/recycling/disposal/pipe.dm +++ b/code/modules/recycling/disposal/pipe.dm @@ -7,7 +7,6 @@ anchored = TRUE density = FALSE obj_flags = CAN_BE_HIT | ON_BLUEPRINTS - level = 1 // underfloor only dir = NONE // dir will contain dominant direction for junction pipes max_integrity = 200 armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30) @@ -42,7 +41,8 @@ dpdir |= turn(dir, -90) if(initialize_dirs & DISP_DIR_FLIP) dpdir |= turn(dir, 180) - update() + + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) // pipe is deleted // ensure if holder is present, it is expelled @@ -81,16 +81,6 @@ H.forceMove(get_turf(src)) return null -// update the icon_state to reflect hidden status -/obj/structure/disposalpipe/proc/update() - var/turf/T = get_turf(src) - hide(T.intact && !isspaceturf(T)) // space never hides pipes - -// hide called by levelupdate if turf intact status changes -// change visibility status and force update of icon -/obj/structure/disposalpipe/hide(var/intact) - invisibility = intact ? INVISIBILITY_MAXIMUM: 0 // hide if floor is intact - // expel the held objects into a turf // called when there is a break in the pipe /obj/structure/disposalpipe/proc/expel(obj/structure/disposalholder/H, turf/T, direction) diff --git a/code/modules/research/nanites/nanite_programs/sensor.dm b/code/modules/research/nanites/nanite_programs/sensor.dm index 6afa81355d2..fbebeaf209a 100644 --- a/code/modules/research/nanites/nanite_programs/sensor.dm +++ b/code/modules/research/nanites/nanite_programs/sensor.dm @@ -236,7 +236,6 @@ /datum/nanite_program/sensor/voice name = "Voice Sensor" desc = "Sends a signal when the nanites hear a determined word or sentence." - var/spent = FALSE /datum/nanite_program/sensor/voice/register_extra_settings() . = ..() @@ -256,10 +255,10 @@ if(!sentence.get_value()) return if(inclusive.get_value()) - if(findtextEx(hearing_args[HEARING_RAW_MESSAGE], sentence)) + if(findtext(hearing_args[HEARING_RAW_MESSAGE], sentence.get_value())) send_code() else - if(hearing_args[HEARING_RAW_MESSAGE] == sentence) + if(lowertext(hearing_args[HEARING_RAW_MESSAGE]) == lowertext(sentence.get_value())) send_code() /datum/nanite_program/sensor/species diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 0344ec1fe9a..71ca68b2a0e 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -185,7 +185,7 @@ alert_type = /obj/screen/alert/status_effect/bloodchill /datum/status_effect/bloodchill/on_apply() - owner.add_movespeed_modifier("bloodchilled", TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = 3) + owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/bloodchill) return ..() /datum/status_effect/bloodchill/tick() @@ -193,7 +193,7 @@ owner.adjustFireLoss(2) /datum/status_effect/bloodchill/on_remove() - owner.remove_movespeed_modifier("bloodchilled") + owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/bloodchill) /datum/status_effect/bonechill id = "bonechill" @@ -201,7 +201,7 @@ alert_type = /obj/screen/alert/status_effect/bonechill /datum/status_effect/bonechill/on_apply() - owner.add_movespeed_modifier("bonechilled", TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = 3) + owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/bonechill) return ..() /datum/status_effect/bonechill/tick() @@ -211,8 +211,7 @@ owner.adjust_bodytemperature(-10) /datum/status_effect/bonechill/on_remove() - owner.remove_movespeed_modifier("bonechilled") - + owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/bonechill) /obj/screen/alert/status_effect/bonechill name = "Bonechilled" desc = "You feel a shiver down your spine after hearing the haunting noise of bone rattling. You'll move slower and get frostbite for a while!" @@ -366,11 +365,11 @@ datum/status_effect/rebreathing/tick() duration = 30 /datum/status_effect/tarfoot/on_apply() - owner.add_movespeed_modifier(MOVESPEED_ID_TARFOOT, update=TRUE, priority=100, multiplicative_slowdown=0.5, blacklisted_movetypes=(FLYING|FLOATING)) + owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/tarfoot) return ..() /datum/status_effect/tarfoot/on_remove() - owner.remove_movespeed_modifier(MOVESPEED_ID_TARFOOT) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/tarfoot) /datum/status_effect/spookcookie id = "spookcookie" @@ -684,15 +683,15 @@ datum/status_effect/stabilized/blue/on_remove() /datum/status_effect/stabilized/sepia/tick() if(prob(50) && mod > -1) mod-- - owner.add_movespeed_modifier(MOVESPEED_ID_SEPIA, override = TRUE, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING)) + owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/sepia, multiplicative_slowdown = -0.5) else if(mod < 1) mod++ // yeah a value of 0 does nothing but replacing the trait in place is cheaper than removing and adding repeatedly - owner.add_movespeed_modifier(MOVESPEED_ID_SEPIA, override = TRUE, update=TRUE, priority=100, multiplicative_slowdown=0, blacklisted_movetypes=(FLYING|FLOATING)) + owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/sepia, multiplicative_slowdown = 0) return ..() /datum/status_effect/stabilized/sepia/on_remove() - owner.remove_movespeed_modifier(MOVESPEED_ID_SEPIA) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/sepia) /datum/status_effect/stabilized/cerulean id = "stabilizedcerulean" @@ -900,7 +899,7 @@ datum/status_effect/stabilized/blue/on_remove() colour = "light pink" /datum/status_effect/stabilized/lightpink/on_apply() - owner.add_movespeed_modifier(MOVESPEED_ID_SLIME_STATUS, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING)) + owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/lightpink) return ..() /datum/status_effect/stabilized/lightpink/tick() @@ -911,7 +910,7 @@ datum/status_effect/stabilized/blue/on_remove() return ..() /datum/status_effect/stabilized/lightpink/on_remove() - owner.remove_movespeed_modifier(MOVESPEED_ID_SLIME_STATUS) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/lightpink) /datum/status_effect/stabilized/adamantine id = "stabilizedadamantine" diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 7b304832b37..e2035244bff 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -256,11 +256,6 @@ All ShuttleMove procs go here // atmosinit() calls update_icon(), so we don't need to call it update_icon() -/obj/machinery/atmospherics/pipe/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) - . = ..() - var/turf/T = loc - hide(T.intact) - /obj/machinery/navbeacon/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() GLOB.navbeacons["[z]"] -= src @@ -268,8 +263,7 @@ All ShuttleMove procs go here /obj/machinery/navbeacon/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() - var/turf/T = loc - hide(T.intact) + if(codes["patrol"]) if(!GLOB.navbeacons["[z]"]) GLOB.navbeacons["[z]"] = list() @@ -278,12 +272,6 @@ All ShuttleMove procs go here GLOB.deliverybeacons += src GLOB.deliverybeacontags += location -/obj/machinery/power/terminal/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) - . = ..() - var/turf/T = src.loc - if(level==1) - hide(T.intact) - /************************************Item move procs************************************/ /obj/item/storage/pod/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) @@ -338,19 +326,12 @@ All ShuttleMove procs go here if(. & MOVE_AREA) . |= MOVE_CONTENTS -/obj/structure/disposalpipe/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) - . = ..() - update() - /obj/structure/cable/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) . = ..() cut_cable_from_powernet(FALSE) /obj/structure/cable/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() - var/turf/T = loc - if(level==1) - hide(T.intact) connect_wire(TRUE) propogate_if_no_network() diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index e040ea422a4..a66b07ec039 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/station_goals/dna_vault.dm @@ -248,8 +248,6 @@ else return ..() - - /obj/machinery/dna_vault/proc/upgrade(mob/living/carbon/human/H,upgrade_type) if(!(upgrade_type in power_lottery[H])) return @@ -279,7 +277,7 @@ ADD_TRAIT(H, TRAIT_PIERCEIMMUNE, "dna_vault") if(VAULT_SPEED) to_chat(H, "Your legs feel faster.") - H.add_movespeed_modifier(MOVESPEED_ID_DNA_VAULT, update=TRUE, priority=100, multiplicative_slowdown=-0.4, blacklisted_movetypes=(FLYING|FLOATING)) + H.add_movespeed_modifier(/datum/movespeed_modifier/dna_vault_speedup) if(VAULT_QUICK) to_chat(H, "Your arms move as fast as lightning.") H.next_move_modifier = 0.5 diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 53c1c926060..928216af50f 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -147,6 +147,8 @@ if(S.hair_color) if(S.hair_color == "mutcolor") facial_hair_color = H.dna.features["mcolor"] + else if(hair_color == "fixedmutcolor") + facial_hair_color = "#[S.fixed_mut_color]" else facial_hair_color = S.hair_color else @@ -162,6 +164,8 @@ if(S.hair_color) if(S.hair_color == "mutcolor") hair_color = H.dna.features["mcolor"] + else if(hair_color == "fixedmutcolor") + hair_color = "#[S.fixed_mut_color]" else hair_color = S.hair_color else diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm index 0721824ec29..2baea55b151 100644 --- a/code/modules/surgery/organs/augments_chest.dm +++ b/code/modules/surgery/organs/augments_chest.dm @@ -153,15 +153,15 @@ on = TRUE ion_trail.start() RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/move_react) + owner.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/cybernetic) RegisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE, .proc/pre_move_react) - owner.add_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER, priority=100, multiplicative_slowdown=-0.5, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK) if(!silent) to_chat(owner, "You turn your thrusters set on.") else ion_trail.stop() UnregisterSignal(owner, COMSIG_MOVABLE_MOVED) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/cybernetic) UnregisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE) - owner.remove_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER) if(!silent) to_chat(owner, "You turn your thrusters set off.") on = FALSE diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index b8734fc9d43..90e8dd50520 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -1206,6 +1206,16 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) category = "Space Suits" surplus = 40 +/datum/uplink_item/suits/infiltrator_bundle + name = "Infiltrator Case" + desc = "Developed by Roseus Galactic in conjunction with the Gorlex Marauders to produce a functional suit for urban operations, \ + this suit proves to be cheaper than your standard issue hardsuit, with none of the movement restrictions of the outdated spacesuits employed by the company. \ + Comes with a armor vest, helmet, sneaksuit, sneakboots, specialized combat gloves and a high-tech balaclava. The case is also rather useful as a storage container." + item = /obj/item/storage/toolbox/infiltrator + cost = 6 + limited_stock = 1 //you only get one so you don't end up with too many gun cases + exclude_modes = list(/datum/game_mode/nuclear) + /datum/uplink_item/suits/space_suit name = "Syndicate Space Suit" desc = "This red and black Syndicate space suit is less encumbering than Nanotrasen variants, \ @@ -1874,3 +1884,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/storage/fancy/cigarettes/cigpack_syndicate cost = 2 illegal_tech = FALSE + +/datum/uplink_item/badass/tactical_naptime + name = "Sleepy Time Pajama Bundle" + desc = "Even soldiers need to get a good nights rest. Comes with blood-red pajamas, a blankie, a hot mug of cocoa and a fuzzy friend." + item = /obj/item/storage/box/syndie_kit/sleepytime + cost = 4 + limited_stock = 1 + cant_discount = TRUE + include_modes = list(/datum/game_mode/nuclear) + diff --git a/config/admins.txt b/config/admins.txt index 640651cb5a6..351e54ba2f6 100644 --- a/config/admins.txt +++ b/config/admins.txt @@ -139,3 +139,4 @@ LoserWasTaken = Game Master Fikou = Game Master Skoglol = Game Master 4dplanner = Game Master +Time-Green = Game Master diff --git a/html/changelog.html b/html/changelog.html index 0bed4bdc73e..e0d0298c949 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -51,6 +51,158 @@ -->
+

19 March 2020

+

Arkatos updated:

+
    +
  • Small UI resizes for Bank Machine, Teleporter and Equipment Reclaimer Station UIs.
  • +
  • You now do a confirmatory Button click to lockdown/detonate cyborgs instead of swimming in the input menu.
  • +
  • Small cleanup of Remote Robot Control, Equipment Reclaimer Station, Robotics Control Console and Exosuit Control Console UIs.
  • +
+

kevinz000 updated:

+
    +
  • movespeed modifiers are now datums and not lists and support global caching.
  • +
+ +

18 March 2020

+

ATHATH updated:

+
    +
  • Aggressive grabs from pacifists now make people drop their items, just like aggressive grabs from non-pacifists do.
  • +
  • The chances to break out of aggressive, neck, and kill grabs have been modified slightly, and having large amounts of damage should actually affect how hard it is to break out of a kill grab now.
  • +
  • All types of damage now affect how hard it is to break out of a grab, not just brute and stamina damage. Stamina damage is, as before, weighted twice as much as the other damage types in the grab escape chance calculation(s).
  • +
+

ArcaneMusic updated:

+
    +
  • Deconstructing plastic and wooden tables now gives the correct materials.
  • +
  • Snow tiles now show the correct sprite when burned or damaged.
  • +
+

Arkatos updated:

+
    +
  • AI shells will now have consistent names across deployments.
  • +
+

Dennok updated:

+
    +
  • Now some effects on open space shown properly.
  • +
  • Cronowarriors no more blind after exit from out of time-bluespace.
  • +
+

Fikou updated:

+
    +
  • unstable mutagen no longer mutates rad immune species
  • +
  • liquid gibs are now meat material with metalgen
  • +
  • radium isnt uranium with metalgen anymore
  • +
+

Iamgoofball updated:

+
    +
  • There is now a preference for Families Antagonist roles.
  • +
  • There is now one Undercover Cop per Family.
  • +
  • Police can no longer join Families. They will, however, fake join it if they use the induction package to get the uniform to stay undercover.
  • +
  • The Space Cops are reminded that they are NOT Nanotrasen employees.
  • +
  • Dead gangs or gangs with 1 member no longer count towards the auto-balance to avoid issues with AFK players or dead gangs limiting the rest of the active gangs.
  • +
  • The Space Cops now have ballistic weaponry outside of 5 stars.
  • +
  • The shuttle will now no longer take off in Families until after an hour and 10 minutes.
  • +
+

JJRcop updated:

+
    +
  • Drone hacking is now fixed
  • +
  • Fixed drone reactivation
  • +
+

NecromancerAnne and zawo updated:

+
    +
  • The Infiltrator Bundle, an armor kit for 6TC. Murder people in style!
  • +
  • Some pajamas for nukies to get plenty of bed rest.
  • +
+

RiskySikh updated:

+
    +
  • reagents.end_metabolization which ensures that the reagents will stop metabolization upon death
  • +
+

Skoglol updated:

+
    +
  • Prevents revs being rolled twice in dynamic.
  • +
  • Drinks dispensers now only show the container they are holding.
  • +
+

Timberpoes updated:

+
    +
  • DNA Consoles have had a firmware update. Mutations can once again be removed properly from the selection list of Advanced Injectors and chromosomes can be removed from storage in any order.
  • +
  • Chromosomes can now be added to all activated mutations on a test subject using the DNA Console instead of just the last activated mutation in the list.
  • +
  • Advanced Injectors no longer super-hyper-mega-ultra-expend themselves and will now only expend themselves once.
  • +
  • Genetic data from used Mutation Activators may now be too limited to extract a new chromosome at DNA Consoles.
  • +
  • Chromosomes now always insert themselves into DNA Consoles when created, unless the console storage buffer is full in which case the chromosome is left on top of the console.
  • +
  • There are now additional feedback messages during the chromosome creation process to keep the user informed.
  • +
  • DNA Consoles have had another firmware update. They are now able to accurately predict and output which chromosomes than an activated genetic mutation is compatible with.
  • +
+

TiviPlus updated:

+
    +
  • The ablative trenchcoat hood will actually deflect lasers now
  • +
  • Fixed some grammar
  • +
+

necromanceranne updated:

+
    +
  • Fixes batons targeting limbs when they should be applying the stamina damage to the chest.
  • +
+ +

17 March 2020

+

Archanial updated:

+
    +
  • Deleted minor and major crimes (they are just crimes now).
  • +
  • Adding a crime (via sec huds) is now only 1 pop-up, seriously try it.
  • +
  • You can now add crime details in security consoles.
  • +
+

Ghilker updated:

+
    +
  • SM now interact with the H2O gas
  • +
+

Indie-ana Jones updated:

+
    +
  • Reports show Hazard-5 entities have mutated to keep their important cells protected from lava. Reports also indicate that these Hazard-5 entities are now take longer to detect from Central Command, among other things.
  • +
+

LemonInTheDark updated:

+
    +
  • Temporarily reverts h2o support in the sm. We need to work out some kinks.
  • +
+

Qustinnus updated:

+
    +
  • Ethereals have started growing slightly transparent hair in a new mutation of the lifeform.
  • +
+

Ryll/Shaps updated:

+
    +
  • You can now untie and knot up people's shoelaces! You can do so by laying down next to the person, dragging their sprite onto yours, then clicking "untie/knot shoes" next to their shoes.
  • +
+

Skoglol updated:

+
    +
  • OOC preferences should now be saving properly again.
  • +
+

Time-Green updated:

+
    +
  • Ducts can now be hidden under tiles
  • +
  • tile hiding is now an element and way cooler and sexier
  • +
  • fixes all atmos pipes being hidden under tiles
  • +
+

Whoneedspacee updated:

+
    +
  • Permanent Portal fixes and One-Way Portal improvements for mapping.
  • +
+

XDTM updated:

+
    +
  • Added the Stray Cargo Pod event, which drops a pod containing a random cargo crate into a random location. Rarely, one might even contain assorted syndicate gear!
  • +
+

zxaber updated:

+
    +
  • Borg upgrade cards are now small items.
  • +
+ +

16 March 2020

+

ArcaneDefence updated:

+
    +
  • Pacifists will no longer mutilate their fellow spacemen when attempting to share energy cake
  • +
+

Fikou updated:

+
    +
  • hunter spider now has doubled poison injections
  • +
+

XDTM updated:

+
    +
  • Fixed nanite voice sensors not working.
  • +
+

15 March 2020

Arkatos updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index ad5b31ec097..7351e9a3cf9 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -37892,3 +37892,126 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. the health analyser copypasting Kryson sprite into game: - tweak: meat texture is now brightened +2020-03-16: + ArcaneDefence: + - bugfix: Pacifists will no longer mutilate their fellow spacemen when attempting + to share energy cake + Fikou: + - balance: hunter spider now has doubled poison injections + XDTM: + - bugfix: Fixed nanite voice sensors not working. +2020-03-17: + Archanial: + - rscdel: Deleted minor and major crimes (they are just crimes now). + - tweak: Adding a crime (via sec huds) is now only 1 pop-up, seriously try it. + - rscadd: You can now add crime details in security consoles. + Ghilker: + - rscadd: SM now interact with the H2O gas + Indie-ana Jones: + - balance: Reports show Hazard-5 entities have mutated to keep their important cells + protected from lava. Reports also indicate that these Hazard-5 entities are + now take longer to detect from Central Command, among other things. + LemonInTheDark: + - rscdel: Temporarily reverts h2o support in the sm. We need to work out some kinks. + Qustinnus: + - rscadd: Ethereals have started growing slightly transparent hair in a new mutation + of the lifeform. + Ryll/Shaps: + - rscadd: You can now untie and knot up people's shoelaces! You can do so by laying + down next to the person, dragging their sprite onto yours, then clicking "untie/knot + shoes" next to their shoes. + Skoglol: + - bugfix: OOC preferences should now be saving properly again. + Time-Green: + - tweak: Ducts can now be hidden under tiles + - code_imp: tile hiding is now an element and way cooler and sexier + - bugfix: fixes all atmos pipes being hidden under tiles + Whoneedspacee: + - refactor: Permanent Portal fixes and One-Way Portal improvements for mapping. + XDTM: + - rscadd: Added the Stray Cargo Pod event, which drops a pod containing a random + cargo crate into a random location. Rarely, one might even contain assorted + syndicate gear! + zxaber: + - balance: Borg upgrade cards are now small items. +2020-03-18: + ATHATH: + - balance: Aggressive grabs from pacifists now make people drop their items, just + like aggressive grabs from non-pacifists do. + - balance: The chances to break out of aggressive, neck, and kill grabs have been + modified slightly, and having large amounts of damage should actually affect + how hard it is to break out of a kill grab now. + - balance: All types of damage now affect how hard it is to break out of a grab, + not just brute and stamina damage. Stamina damage is, as before, weighted twice + as much as the other damage types in the grab escape chance calculation(s). + ArcaneMusic: + - bugfix: Deconstructing plastic and wooden tables now gives the correct materials. + - bugfix: Snow tiles now show the correct sprite when burned or damaged. + Arkatos: + - tweak: AI shells will now have consistent names across deployments. + Dennok: + - bugfix: Now some effects on open space shown properly. + - bugfix: Cronowarriors no more blind after exit from out of time-bluespace. + Fikou: + - balance: unstable mutagen no longer mutates rad immune species + - tweak: liquid gibs are now meat material with metalgen + - bugfix: radium isnt uranium with metalgen anymore + Iamgoofball: + - balance: There is now a preference for Families Antagonist roles. + - balance: There is now one Undercover Cop per Family. + - balance: Police can no longer join Families. They will, however, fake join it + if they use the induction package to get the uniform to stay undercover. + - balance: The Space Cops are reminded that they are NOT Nanotrasen employees. + - balance: Dead gangs or gangs with 1 member no longer count towards the auto-balance + to avoid issues with AFK players or dead gangs limiting the rest of the active + gangs. + - balance: The Space Cops now have ballistic weaponry outside of 5 stars. + - balance: The shuttle will now no longer take off in Families until after an hour + and 10 minutes. + JJRcop: + - bugfix: Drone hacking is now fixed + - bugfix: Fixed drone reactivation + NecromancerAnne and zawo: + - rscadd: The Infiltrator Bundle, an armor kit for 6TC. Murder people in style! + - rscadd: Some pajamas for nukies to get plenty of bed rest. + RiskySikh: + - rscadd: reagents.end_metabolization which ensures that the reagents will stop + metabolization upon death + Skoglol: + - bugfix: Prevents revs being rolled twice in dynamic. + - bugfix: Drinks dispensers now only show the container they are holding. + Timberpoes: + - bugfix: DNA Consoles have had a firmware update. Mutations can once again be removed + properly from the selection list of Advanced Injectors and chromosomes can be + removed from storage in any order. + - bugfix: Chromosomes can now be added to all activated mutations on a test subject + using the DNA Console instead of just the last activated mutation in the list. + - bugfix: Advanced Injectors no longer super-hyper-mega-ultra-expend themselves + and will now only expend themselves once. + - bugfix: Genetic data from used Mutation Activators may now be too limited to extract + a new chromosome at DNA Consoles. + - bugfix: Chromosomes now always insert themselves into DNA Consoles when created, + unless the console storage buffer is full in which case the chromosome is left + on top of the console. + - tweak: There are now additional feedback messages during the chromosome creation + process to keep the user informed. + - rscadd: DNA Consoles have had another firmware update. They are now able to accurately + predict and output which chromosomes than an activated genetic mutation is compatible + with. + TiviPlus: + - bugfix: The ablative trenchcoat hood will actually deflect lasers now + - spellcheck: Fixed some grammar + necromanceranne: + - bugfix: Fixes batons targeting limbs when they should be applying the stamina + damage to the chest. +2020-03-19: + Arkatos: + - tweak: Small UI resizes for Bank Machine, Teleporter and Equipment Reclaimer Station + UIs. + - tweak: You now do a confirmatory Button click to lockdown/detonate cyborgs instead + of swimming in the input menu. + - tweak: Small cleanup of Remote Robot Control, Equipment Reclaimer Station, Robotics + Control Console and Exosuit Control Console UIs. + kevinz000: + - refactor: movespeed modifiers are now datums and not lists and support global + caching. diff --git a/html/changelogs/AutoChangeLog-pr-49912.yml b/html/changelogs/AutoChangeLog-pr-49912.yml deleted file mode 100644 index 889c51a3050..00000000000 --- a/html/changelogs/AutoChangeLog-pr-49912.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fikou" -delete-after: True -changes: - - balance: "hunter spider now has doubled poison injections" diff --git a/icons/effects/landmarks_static.dmi b/icons/effects/landmarks_static.dmi index 1a7617d3bb4..9b5757fcbb0 100644 Binary files a/icons/effects/landmarks_static.dmi and b/icons/effects/landmarks_static.dmi differ diff --git a/icons/mob/clothing/feet.dmi b/icons/mob/clothing/feet.dmi index b39ccdfceb3..b852f45ce72 100644 Binary files a/icons/mob/clothing/feet.dmi and b/icons/mob/clothing/feet.dmi differ diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi index f1ae2afed72..84b997e2f9d 100644 Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi index 5ab56fa2979..1b7ac7ee456 100644 Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi index 31a3613e08f..4e6ed64fa2e 100644 Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ diff --git a/icons/mob/clothing/suit.dmi b/icons/mob/clothing/suit.dmi index 4f3108ee672..d729552e815 100644 Binary files a/icons/mob/clothing/suit.dmi and b/icons/mob/clothing/suit.dmi differ diff --git a/icons/mob/clothing/under/syndicate.dmi b/icons/mob/clothing/under/syndicate.dmi index 1bf2dae0fee..808bfde72de 100644 Binary files a/icons/mob/clothing/under/syndicate.dmi and b/icons/mob/clothing/under/syndicate.dmi differ diff --git a/icons/mob/inhands/equipment/toolbox_lefthand.dmi b/icons/mob/inhands/equipment/toolbox_lefthand.dmi index d393b262490..2b590b6579f 100644 Binary files a/icons/mob/inhands/equipment/toolbox_lefthand.dmi and b/icons/mob/inhands/equipment/toolbox_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/toolbox_righthand.dmi b/icons/mob/inhands/equipment/toolbox_righthand.dmi index 1698135aaed..5b9ca7433b2 100644 Binary files a/icons/mob/inhands/equipment/toolbox_righthand.dmi and b/icons/mob/inhands/equipment/toolbox_righthand.dmi differ diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi index 88867c448d2..f98a1b29b9e 100755 Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 4c742f541e4..a12ccf29ad3 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index fc6c1f3a8c0..cfada004ea9 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 370d8369a93..9b76831de16 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index 81557fc8545..765d33ce9bc 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index bccb01274a4..c70f93f49e7 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/clothing/under/syndicate.dmi b/icons/obj/clothing/under/syndicate.dmi index 89f6b899f9e..6a3c60e967b 100644 Binary files a/icons/obj/clothing/under/syndicate.dmi and b/icons/obj/clothing/under/syndicate.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index d1a1d9adbed..a2a2b87a42b 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 350ddc4082b..823147a7a6f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -537,6 +537,7 @@ #include "code\datums\elements\snail_crawl.dm" #include "code\datums\elements\squish.dm" #include "code\datums\elements\tool_flash.dm" +#include "code\datums\elements\undertile.dm" #include "code\datums\elements\update_icon_blocker.dm" #include "code\datums\elements\update_icon_updates_onmob.dm" #include "code\datums\elements\waddling.dm" @@ -1366,6 +1367,7 @@ #include "code\modules\antagonists\blob\blobstrains\blazing_oil.dm" #include "code\modules\antagonists\blob\blobstrains\cryogenic_poison.dm" #include "code\modules\antagonists\blob\blobstrains\debris_devourer.dm" +#include "code\modules\antagonists\blob\blobstrains\distributed_neurons.dm" #include "code\modules\antagonists\blob\blobstrains\electromagnetic_web.dm" #include "code\modules\antagonists\blob\blobstrains\energized_jelly.dm" #include "code\modules\antagonists\blob\blobstrains\explosive_lattice.dm" @@ -1377,7 +1379,6 @@ #include "code\modules\antagonists\blob\blobstrains\replicating_foam.dm" #include "code\modules\antagonists\blob\blobstrains\shifting_fragments.dm" #include "code\modules\antagonists\blob\blobstrains\synchronous_mesh.dm" -#include "code\modules\antagonists\blob\blobstrains\zombifying_pods.dm" #include "code\modules\antagonists\blob\structures\_blob.dm" #include "code\modules\antagonists\blob\structures\core.dm" #include "code\modules\antagonists\blob\structures\factory.dm" @@ -1794,6 +1795,7 @@ #include "code\modules\events\spacevine.dm" #include "code\modules\events\spider_infestation.dm" #include "code\modules\events\spontaneous_appendicitis.dm" +#include "code\modules\events\stray_cargo.dm" #include "code\modules\events\vent_clog.dm" #include "code\modules\events\wisdomcow.dm" #include "code\modules\events\wormholes.dm" @@ -2071,7 +2073,6 @@ #include "code\modules\mob\mob_defines.dm" #include "code\modules\mob\mob_helpers.dm" #include "code\modules\mob\mob_movement.dm" -#include "code\modules\mob\mob_movespeed.dm" #include "code\modules\mob\mob_transformation_simple.dm" #include "code\modules\mob\say.dm" #include "code\modules\mob\status_procs.dm" @@ -2431,6 +2432,14 @@ #include "code\modules\modular_computers\hardware\printer.dm" #include "code\modules\modular_computers\hardware\recharger.dm" #include "code\modules\modular_computers\NTNet\NTNRC\conversation.dm" +#include "code\modules\movespeed\_movespeed_modifier.dm" +#include "code\modules\movespeed\modifiers\components.dm" +#include "code\modules\movespeed\modifiers\innate.dm" +#include "code\modules\movespeed\modifiers\items.dm" +#include "code\modules\movespeed\modifiers\misc.dm" +#include "code\modules\movespeed\modifiers\mobs.dm" +#include "code\modules\movespeed\modifiers\reagent.dm" +#include "code\modules\movespeed\modifiers\status_effects.dm" #include "code\modules\ninja\__ninjaDefines.dm" #include "code\modules\ninja\energy_katana.dm" #include "code\modules\ninja\ninja_event.dm" diff --git a/tgui/packages/tgui/interfaces/ExosuitControlConsole.js b/tgui/packages/tgui/interfaces/ExosuitControlConsole.js index c0d46dc44af..06645d622a2 100644 --- a/tgui/packages/tgui/interfaces/ExosuitControlConsole.js +++ b/tgui/packages/tgui/interfaces/ExosuitControlConsole.js @@ -35,7 +35,7 @@ export const ExosuitControlConsole = props => { })} />