diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 0f5e927ad7..a4d6c07526 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -240,6 +240,17 @@ This prevents nesting levels from getting deeper then they need to be. * Queries must never specify the database, be it in code, or in text files in the repo. +### Mapping Standards +* TGM Format & Map Merge + * All new maps submitted to the repo through a pull request must be in TGM format (unless there is a valid reason present to have it in the default BYOND format.) This is done using the [Map Merge](https://github.com/tgstation/tgstation/wiki/Map-Merger) utility included in the repo to convert the file to TGM format. + * Likewise, you MUST run `Map Merge - TGM.bat` prior to opening your PR when updating existing maps to minimize the change differences (even when using third party mapping programs such as FastDMM.) + * Failure to run Map Merge on a map after using third party mapping programs (such as FastDMM) greatly increases the risk of the map's key dictionary becoming corrupted by future edits after running map merge. Resolving the corruption issue involves rebuilding the map's key dictionary; id est rewriting all the keys contained within the map by reconverting it from BYOND to TGM format - which creates very large differences that ultimately delay the PR process and is extremely likely to cause merge conflicts with other pull requests. + +* Variable Editing (Var-edits) + * While var-editing an item within the editor is perfectly fine, it is preferred that when you are changing the base behavior of an item (how it functions) that you make a new subtype of that item within the code, especially if you plan to use the item in multiple locations on the same map, or across multiple maps. This makes it easier to make corrections as needed to all instances of the item at one time as opposed to having to find each instance of it and change them all individually. + * Subtypes only intended to be used on away mission or ruin maps should be contained within an .dm file with a name corresponding to that map within `code\modules\awaymissions` or `code\modules\ruins` respectively. This is so in the event that the map is removed, that subtype will be removed at the same time as well to minimize leftover/unused data within the repo. + * Please attempt to clean out any dirty variables that may be contained within items you alter through var-editing. For example, due to how DM functions, changing the `pixel_x` variable from 23 to 0 will leave a dirty record in the map's code of `pixel_x = 0`. Likewise this can happen when changing an item's icon to something else and then back. This can lead to some issues where an item's icon has changed within the code, but becomes broken on the map due to it still attempting to use the old entry. + * Areas should not be var-edited on a map to change it's name or attributes. All areas of a single type and it's altered instances are considered the same area within the code, and editing their variables on a map can lead to issues with powernets and event subsystems which are difficult to debug. ### Other Notes diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index f7862ffa9d..36daa43402 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -40811,6 +40811,7 @@ network = list("MiniSat","tcomm"); pixel_y = -29 }, +/obj/structure/bed/dogbed/renault, /mob/living/simple_animal/pet/fox/Renault, /turf/open/floor/carpet, /area/crew_quarters/heads/captain/private) diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 87e314b5ba..6a1285bcc9 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -46290,11 +46290,6 @@ /turf/open/floor/plasteel, /area/engine/engineering) "car" = ( -/obj/structure/cable/yellow{ - icon_state = "1-4"; - d1 = 1; - d2 = 4 - }, /obj/structure/cable/yellow{ d1 = 1; d2 = 8; @@ -47261,16 +47256,6 @@ /turf/open/floor/plasteel, /area/engine/engineering) "ccV" = ( -/obj/structure/cable/yellow{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/structure/cable/yellow{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -47282,22 +47267,12 @@ id = "Singularity"; name = "radiation shutters" }, -/obj/structure/cable/yellow{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/effect/turf_decal/bot{ dir = 2 }, /turf/open/floor/plasteel/black, /area/engine/engineering) "ccX" = ( -/obj/structure/cable/yellow{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/structure/cable/yellow{ d1 = 2; d2 = 4; @@ -47326,11 +47301,6 @@ /turf/open/floor/plating, /area/engine/engineering) "cda" = ( -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, /obj/effect/landmark/event_spawn, /turf/open/floor/plating, /area/engine/engineering) @@ -47346,16 +47316,6 @@ /turf/open/floor/plating, /area/engine/engineering) "cdc" = ( -/obj/structure/cable/yellow{ - d1 = 2; - d2 = 8; - icon_state = "2-8" - }, -/obj/structure/cable/yellow{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, @@ -47599,19 +47559,9 @@ /turf/open/floor/plasteel, /area/engine/engineering) "cdQ" = ( -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /turf/open/floor/plasteel/yellow/side, /area/engine/engineering) "cdR" = ( -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/machinery/button/door{ id = "Singularity"; name = "Shutters Control"; @@ -47666,11 +47616,6 @@ /turf/open/floor/plating, /area/engine/engineering) "cdX" = ( -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/machinery/button/door{ id = "Singularity"; name = "Shutters Control"; @@ -47850,14 +47795,10 @@ id = "Singularity"; name = "radiation shutters" }, -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/engine/engineering) "ceu" = ( @@ -48053,9 +47994,6 @@ /turf/open/floor/plating, /area/engine/engineering) "ceY" = ( -/obj/machinery/power/rad_collector/anchored, -/obj/item/tank/internals/plasma, -/obj/structure/cable/yellow, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -48872,6 +48810,9 @@ icon_state = "0-8" }, /obj/machinery/power/tesla_coil, +/obj/structure/window/plasma/reinforced{ + dir = 4 + }, /turf/open/floor/plating/airless, /area/engine/engineering) "chy" = ( @@ -48884,6 +48825,9 @@ d2 = 4 }, /obj/machinery/power/tesla_coil, +/obj/structure/window/plasma/reinforced{ + dir = 8 + }, /turf/open/floor/plating/airless, /area/engine/engineering) "chA" = ( @@ -49000,7 +48944,15 @@ /turf/open/floor/plating/airless, /area/engine/engineering) "chQ" = ( -/turf/open/space/basic, +/obj/structure/window/plasma/reinforced{ + dir = 4 + }, +/obj/machinery/power/rad_collector/anchored, +/obj/structure/cable/yellow{ + d2 = 8; + icon_state = "0-8" + }, +/turf/open/floor/plating/airless, /area/engine/engineering) "chR" = ( /obj/structure/cable{ @@ -54066,6 +54018,78 @@ /obj/machinery/smoke_machine, /turf/open/floor/plasteel/white, /area/medical/chemistry) +"YXI" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "Singularity"; + name = "radiation shutters" + }, +/obj/effect/turf_decal/bot{ + dir = 2 + }, +/turf/open/floor/plasteel/black, +/area/engine/engineering) +"YXJ" = ( +/obj/machinery/power/rad_collector/anchored, +/turf/open/floor/plating, +/area/engine/engineering) +"YXK" = ( +/obj/machinery/power/rad_collector/anchored, +/turf/open/floor/plating, +/area/engine/engineering) +"YXL" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plating, +/area/engine/engineering) +"YXM" = ( +/obj/structure/cable/yellow{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/obj/structure/cable/yellow{ + icon_state = "1-4"; + d1 = 1; + d2 = 4 + }, +/obj/item/tank/internals/plasma, +/turf/open/floor/plating/airless, +/area/engine/engineering) +"YXN" = ( +/obj/structure/window/plasma/reinforced{ + dir = 8 + }, +/obj/machinery/power/rad_collector/anchored, +/obj/structure/cable/yellow{ + icon_state = "0-4"; + d2 = 4 + }, +/turf/open/floor/plating/airless, +/area/engine/engineering) +"YXO" = ( +/obj/structure/window/plasma/reinforced{ + dir = 8 + }, +/obj/machinery/power/rad_collector/anchored, +/obj/structure/cable/yellow{ + icon_state = "0-4"; + d2 = 4 + }, +/turf/open/floor/plating/airless, +/area/engine/engineering) +"YXP" = ( +/obj/structure/window/plasma/reinforced{ + dir = 8 + }, +/obj/machinery/power/rad_collector/anchored, +/obj/structure/cable/yellow{ + icon_state = "0-4"; + d2 = 4 + }, +/turf/open/floor/plating/airless, +/area/engine/engineering) (1,1,1) = {" aaa @@ -81734,7 +81758,7 @@ bOG bva bDi bXk -cbX +YXJ cbX cdK bXk @@ -81991,7 +82015,7 @@ bOG bTE cae bXk -cbX +YXK cbX cdK bXk @@ -83791,20 +83815,20 @@ bZC cal cbh cam -ccT +cam cdQ cet ceY -cfa +cbX cfU cgu cgU chw -cgU +YXM +chw +chw chw -cgU chw -cgU cjs cfV cfV @@ -84048,18 +84072,18 @@ bZA cam cam cam -ccU +cam cdQ cet -ceZ -cfa +ceY +cbX cfV cgv cfV chx chQ chx -cfV +chQ chx chQ chx @@ -84308,8 +84332,8 @@ ccc ccV cdR cet -ceZ -cfa +ceY +cbX cfU cgv cgV @@ -85587,9 +85611,9 @@ bXo bYi bYV bZA -cas -cbk -cce +cdN +YXI +YXL cda cdV cex @@ -85847,7 +85871,7 @@ bZF cat bXk ccg -cdb +cey cdW cey cey @@ -86364,8 +86388,8 @@ cch cdc cdX cet -ceZ -cfa +ceY +cbX cfU cgv cgV @@ -86618,20 +86642,20 @@ bZA cam cam cam -cdd +cam cdQ cet -ceZ -cfa +ceY +cbX cfV cgv cfV chz -chQ +YXN chz -cfV +YXO chz -chQ +YXP chz cfV cfV @@ -86875,20 +86899,20 @@ bZC cal cbm cci -cde +cam cdQ cet -ceZ -cfa +ceY +cbX cfU cgx cgU chA -cgU chA -cgU chA -cgU +chA +chA +chA cjt cfV cfV diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 8017cde520..69596e7a0f 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -93,6 +93,7 @@ //Mob AI Status //Hostile simple animals +//If you add a new status, be sure to add a list for it to the simple_animals global in _globalvars/lists/mobs.dm #define AI_ON 1 #define AI_IDLE 2 #define AI_OFF 3 diff --git a/code/__DEFINES/radiation.dm b/code/__DEFINES/radiation.dm index 4787754e3a..196f3cc079 100644 --- a/code/__DEFINES/radiation.dm +++ b/code/__DEFINES/radiation.dm @@ -18,13 +18,16 @@ Ask ninjanomnom if they're around #define RAD_TOX_COEFFICIENT 0.05 // Toxin damage per tick coefficient #define RAD_MOB_SAFE 300 // How much stored radiation in a mob with no ill effects -#define RAD_MOB_KNOCKDOWN 1500 // How much stored radiation to start stunning -// If (mutate*2= chnotify + 9000) - chnotify = REALTIMEOFDAY - send2irc_adminless_only("NOCHEAT", "[key_name(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)]))") - return + if(isnull(pixel_turf)) + return + if(!can_see(A)) + message_admins("[key_name_admin(src)] might be running a modified client! (failed can_see on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))") + var/message = "[key_name(src)] might be running a modified client! (failed can_see on AI click of [A]([COORD(pixel_turf)]))" + log_admin(message) + if(REALTIMEOFDAY >= chnotify + 9000) + chnotify = REALTIMEOFDAY + send2irc_adminless_only("NOCHEAT", message) + return var/list/modifiers = params2list(params) if(modifiers["shift"] && modifiers["ctrl"]) @@ -74,7 +69,7 @@ if(world.time <= next_move) return - if(aicamera.in_camera_mode && pixel_turf && turf_visible) + if(aicamera.in_camera_mode) aicamera.camera_mode_off() aicamera.captureimage(pixel_turf, usr) return diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 3cc6734482..2d3a3341da 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -243,7 +243,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." /obj/screen/alert/fire/Click() var/mob/living/L = usr - if(!L.can_resist()) + if(!istype(L) || !L.can_resist()) return L.changeNext_move(CLICK_CD_RESIST) if(L.canmove) @@ -559,7 +559,7 @@ so as to remain in compliance with the most up-to-date laws." /obj/screen/alert/restrained/Click() var/mob/living/L = usr - if(!L.can_resist()) + if(!istype(L) || !L.can_resist()) return L.changeNext_move(CLICK_CD_RESIST) if((L.canmove) && (L.last_special <= world.time)) @@ -567,7 +567,7 @@ so as to remain in compliance with the most up-to-date laws." /obj/screen/alert/restrained/buckled/Click() var/mob/living/L = usr - if(!L.can_resist()) + if(!istype(L) || !L.can_resist()) return L.changeNext_move(CLICK_CD_RESIST) if(L.last_special <= world.time) diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm new file mode 100644 index 0000000000..49846e6c9d --- /dev/null +++ b/code/controllers/subsystem/idlenpcpool.dm @@ -0,0 +1,34 @@ +SUBSYSTEM_DEF(idlenpcpool) + name = "Idling NPC Pool" + flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND + priority = 10 + wait = 60 + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + + var/list/currentrun = list() + +/datum/controller/subsystem/idlenpcpool/stat_entry() + var/list/idlelist = GLOB.simple_animals[AI_IDLE] + ..("IdleNPCS:[idlelist.len]") + +/datum/controller/subsystem/idlenpcpool/fire(resumed = FALSE) + + if (!resumed) + var/list/idlelist = GLOB.simple_animals[AI_IDLE] + src.currentrun = idlelist.Copy() + + //cache for sanic speed (lists are references anyways) + var/list/currentrun = src.currentrun + + + while(currentrun.len) + var/mob/living/simple_animal/SA = currentrun[currentrun.len] + --currentrun.len + + if(!SA.ckey) + if(SA.stat != DEAD) + SA.handle_automated_movement() + if(SA.stat != DEAD) + SA.consider_wakeup() + if (MC_TICK_CHECK) + return diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index 4f875721e8..6ee4626f25 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -37,7 +37,8 @@ SUBSYSTEM_DEF(npcpool) // 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them. if (!resumed) - src.currentrun = GLOB.simple_animals.Copy() + var/list/activelist = GLOB.simple_animals[AI_ON] + src.currentrun = activelist.Copy() stage = PROCESSING_SIMPLES //cache for sanic speed (lists are references anyways) var/list/currentrun = src.currentrun diff --git a/code/datums/looping_sounds/looping_sound.dm b/code/datums/looping_sounds/looping_sound.dm new file mode 100644 index 0000000000..2374da67b4 --- /dev/null +++ b/code/datums/looping_sounds/looping_sound.dm @@ -0,0 +1,89 @@ +/* + list/atom/output_atoms + + mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end. + mid_length (num) The length to wait between playing mid_sounds + + start_sound (soundfile) Played before starting the mid_sounds loop + start_length (num) How long to wait before starting the main loop after playing start_sound + + end_sound (soundfile) The sound played after the main loop has concluded + + chance (num) Chance per loop to play a mid_sound + volume (num) Sound output volume + muted (bool) Private. Used to stop the sound loop. + max_loops (num) The max amount of loops to run for. +*/ +/datum/looping_sound + var/list/atom/output_atoms + var/mid_sounds + var/mid_length + var/start_sound + var/start_length + var/end_sound + var/chance + var/volume + var/muted = TRUE + var/max_loops + +/datum/looping_sound/New(list/_output_atoms, start_immediately=FALSE) + if(!mid_sounds) + WARNING("A looping sound datum was created without sounds to play.") + return + + if(_output_atoms) + output_atoms = _output_atoms + else + output_atoms = list() + + if(start_immediately) + start() + +/datum/looping_sound/Destroy() + stop() + output_atoms = null + return ..() + +/datum/looping_sound/proc/start() + if(!muted) + return + muted = FALSE + on_start() + +/datum/looping_sound/proc/stop() + if(muted) + return + muted = TRUE + +/datum/looping_sound/proc/sound_loop(looped=0) + if(muted || (max_loops && looped > max_loops)) + on_stop(looped) + return + if(!chance || prob(chance)) + play(get_sound(looped)) + addtimer(CALLBACK(src, .proc/sound_loop, ++looped), mid_length) + +/datum/looping_sound/proc/play(soundfile) + var/list/atoms_cache = output_atoms + for(var/i in 1 to atoms_cache.len) + var/atom/thing = atoms_cache[i] + playsound(thing, soundfile, volume) + +/datum/looping_sound/proc/get_sound(looped, _mid_sounds) + if(!_mid_sounds) + . = mid_sounds + else + . = _mid_sounds + while(!isfile(.) && !isnull(.)) + . = pickweight(.) + +/datum/looping_sound/proc/on_start() + var/start_wait = 0 + if(start_sound) + play(start_sound) + start_wait = start_length + addtimer(CALLBACK(src, .proc/sound_loop), start_wait) + +/datum/looping_sound/proc/on_stop(looped) + if(end_sound) + play(end_sound) \ No newline at end of file diff --git a/code/datums/looping_sounds/machinery_sounds.dm b/code/datums/looping_sounds/machinery_sounds.dm new file mode 100644 index 0000000000..88b2b06878 --- /dev/null +++ b/code/datums/looping_sounds/machinery_sounds.dm @@ -0,0 +1,9 @@ +/datum/looping_sound/showering + start_sound = 'sound/machines/shower/shower_start.ogg' + start_length = 2 + mid_sounds = list('sound/machines/shower/shower_mid1.ogg'=1,'sound/machines/shower/shower_mid2.ogg'=1,'sound/machines/shower/shower_mid3.ogg'=1) + mid_length = 10 + end_sound = 'sound/machines/shower/shower_end.ogg' + volume = 25 + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/code/datums/radiation_wave.dm b/code/datums/radiation_wave.dm index 91b57414c7..2432427f4a 100644 --- a/code/datums/radiation_wave.dm +++ b/code/datums/radiation_wave.dm @@ -89,7 +89,7 @@ continue thing.rad_act(strength) - var/static/list/blacklisted = typecacheof(list(/turf, /obj/structure/cable, /obj/machinery/atmospherics)) + var/static/list/blacklisted = typecacheof(list(/turf, /mob, /obj/structure/cable, /obj/machinery/atmospherics)) if(!can_contaminate || blacklisted[thing.type]) continue if(prob((strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1/(steps*range_modifier), 1))) // Only stronk rads get to have little baby rads diff --git a/code/game/gamemodes/clock_cult/clock_effects/city_of_cogs_rift.dm b/code/game/gamemodes/clock_cult/clock_effects/city_of_cogs_rift.dm index a1946c4c22..135c9a0b41 100644 --- a/code/game/gamemodes/clock_cult/clock_effects/city_of_cogs_rift.dm +++ b/code/game/gamemodes/clock_cult/clock_effects/city_of_cogs_rift.dm @@ -38,7 +38,7 @@ beckon(AM) /obj/effect/clockwork/city_of_cogs_rift/proc/beckon(atom/movable/AM) - AM.visible_message("[AM] passes through [src]!", ignore_mob = AM) + AM.visible_message("[AM] passes through [src]!", ignored_mob = AM) AM.forceMove(pick(!is_servant_of_ratvar(AM) ? GLOB.city_of_cogs_spawns : GLOB.servant_spawns)) AM.visible_message("[AM] materializes from the air!", \ "You pass through [src] and appear [is_servant_of_ratvar(AM) ? "back at the City of Cogs" : "somewhere unfamiliar. Looks like it was a one-way trip.."].") diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 027e6e4856..326889b872 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -45,7 +45,11 @@ /datum/game_mode/wizard/check_finished() for(var/datum/mind/wizard in wizards) if(isliving(wizard.current) && wizard.current.stat!=DEAD) - return ..() + return FALSE + + for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead() + if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard)) + return FALSE if(SSevents.wizardmode) //If summon events was active, turn it off SSevents.toggleWizardmode() diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index a8cfd09507..7f5276d908 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -9,7 +9,7 @@ #define RADIATION_DURATION_MAX 30 #define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate -#define RADIATION_IRRADIATION_MULTIPLIER 10 //multiplier for how much radiation a test subject recieves +#define RADIATION_IRRADIATION_MULTIPLIER 1 //multiplier for how much radiation a test subject recieves #define SCANNER_ACTION_SE 1 #define SCANNER_ACTION_UI 2 diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index fac414d5a0..d1a99c7b5c 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -798,7 +798,7 @@ // Otherwise it will runtime with this kind of error: null.Topic() if(!nowindow) ..() - if(usr.incapacitated() && !IsAdminGhost(usr)) + if(!usr.canUseTopic(src) && !IsAdminGhost(usr)) return add_fingerprint(usr) if(href_list["close"]) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 6085319aab..dd8003ed47 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -617,7 +617,7 @@ GLOBAL_LIST_EMPTY(PDAs) P.show_recieved_message(msg,src) if(!multiple) show_to_ghosts(user,msg) - log_talk(user,"[key_name(user)] (PDA: [initial(name)]) sent \"[message]\" to [key_name(P,null,TRUE)]",LOGPDA) + log_talk(user,"[key_name(user)] (PDA: [initial(name)]) sent \"[message]\" to [P.name]",LOGPDA) else if(!multiple) to_chat(user, "ERROR: Server isn't responding.") diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index 6ba8425392..23fc8a29ea 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -124,6 +124,8 @@ GLOBAL_LIST_EMPTY(GPS_list) a = copytext(sanitize(a), 1, 20) gpstag = a . = TRUE + name = "global positioning system ([gpstag])" + if("power") toggletracking(usr) . = TRUE @@ -134,15 +136,6 @@ GLOBAL_LIST_EMPTY(GPS_list) global_mode = !global_mode . = TRUE -/obj/item/device/gps/Topic(href, href_list) - ..() - if(href_list["tag"] ) - var/a = input("Please enter desired tag.", name, gpstag) as text - a = uppertext(copytext(sanitize(a), 1, 5)) - if(in_range(src, usr)) - gpstag = a - name = "global positioning system ([gpstag])" - attack_self(usr) /obj/item/device/gps/science icon_state = "gps-s" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index cec16f37c4..30fd178f12 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -109,7 +109,6 @@ new /obj/item/clothing/gloves/krav_maga/sec(src) new /obj/item/door_remote/head_of_security(src) new /obj/item/gun/ballistic/shotgun/automatic/combat/compact(src) - new /obj/item/pinpointer/crew(src) /obj/structure/closet/secure_closet/security name = "security officer's locker" diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index 2deb2d2fde..70176ede53 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -68,14 +68,15 @@ START_PROCESSING(SSfastprocess, src) /obj/machinery/manned_turret/process() - if(!LAZYLEN(buckled_mobs)) + if (!update_positioning()) return PROCESS_KILL - update_positioning() /obj/machinery/manned_turret/proc/update_positioning() + if (!LAZYLEN(buckled_mobs)) + return FALSE var/mob/living/controller = buckled_mobs[1] if(!istype(controller)) - return + return FALSE var/client/C = controller.client if(C) var/atom/A = C.mouseObject @@ -143,7 +144,7 @@ addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire) /obj/machinery/manned_turret/proc/fire_helper(mob/user) - if(user.incapacitated()) + if(user.incapacitated() || !(user in buckled_mobs)) return update_positioning() //REFRESH MOUSE TRACKING!! var/turf/targets_from = get_turf(src) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 18d8b8f7f0..e22d75f9aa 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -199,7 +199,15 @@ var/obj/effect/mist/mymist = null var/ismist = 0 //needs a var so we can make it linger~ var/watertemp = "normal" //freezing, normal, or boiling + var/datum/looping_sound/showering/soundloop +/obj/machinery/shower/Initialize() + . = ..() + soundloop = new(list(src), FALSE) + +/obj/machinery/shower/Destroy() + QDEL_NULL(soundloop) + return ..() /obj/effect/mist name = "mist" @@ -215,6 +223,7 @@ update_icon() add_fingerprint(M) if(on) + soundloop.start() wash_turf() for(var/atom/movable/G in loc) if(isliving(G)) @@ -223,6 +232,7 @@ else if(isobj(G)) // Skip the light objects wash_obj(G) else + soundloop.stop() if(isopenturf(loc)) var/turf/open/tile = loc tile.MakeSlippery(min_wet_time = 5, wet_time_to_add = 1) @@ -368,6 +378,15 @@ else L.clean_blood() +/obj/machinery/shower/proc/contamination_cleanse(atom/movable/thing) + var/datum/component/radioactive/healthy_green_glow = thing.GetComponent(/datum/component/radioactive) + if(!healthy_green_glow || QDELETED(healthy_green_glow)) + return + var/strength = healthy_green_glow.strength + if(strength <= RAD_BACKGROUND_RADIATION) + qdel(healthy_green_glow) + return + healthy_green_glow.strength = max(strength-1, 0) /obj/machinery/shower/process() if(on) @@ -377,6 +396,7 @@ wash_mob(AM) else if(isobj(AM)) wash_obj(AM) + contamination_cleanse(AM) /obj/machinery/shower/deconstruct(disassembled = TRUE) new /obj/item/stack/sheet/metal (loc, 3) diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 721ed63794..265731e96e 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -27,7 +27,7 @@ var/datum/excited_group/excited_group var/excited = 0 var/recently_active = 0 - var/datum/gas_mixture/air + var/datum/gas_mixture/turf/air var/obj/effect/hotspot/active_hotspot var/atmos_cooldown = 0 diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 74264b4eae..9b5ea089c2 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -65,22 +65,17 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) //PV = nRT -/datum/gas_mixture/proc/heat_capacity() //joules per kelvin +/datum/gas_mixture/proc/heat_capacity(data = MOLES) //joules per kelvin var/list/cached_gases = gases . = 0 for(var/id in cached_gases) var/gas_data = cached_gases[id] - . += gas_data[MOLES] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT] - if(!. && temperature) //if temp isn't defined, this mixture isn't a vacuum like space is. it hasn't been filled with *anything* so we want it to take on the properties of whatever gas enters it - . += HEAT_CAPACITY_VACUUM //however, if temp is defined but HC is still 0, then we want the mixture to behave like space does, as a heat sink + . += gas_data[data] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT] - -/datum/gas_mixture/proc/heat_capacity_archived() //joules per kelvin - var/list/cached_gases = gases - . = 0 - for(var/id in cached_gases) - var/gas_data = cached_gases[id] - . += gas_data[ARCHIVE] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT] +/datum/gas_mixture/turf/heat_capacity() + . = ..() + if(!.) + . += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space //prefer this in performance critical areas #define TOTAL_MOLES(cached_gases, out_var)\ @@ -195,7 +190,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) amount = min(amount, sum) //Can not take more air than tile has! if(amount <= 0) return null - var/datum/gas_mixture/removed = new + var/datum/gas_mixture/removed = new type var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars removed.temperature = temperature @@ -213,7 +208,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) ratio = min(ratio, 1) var/list/cached_gases = gases - var/datum/gas_mixture/removed = new + var/datum/gas_mixture/removed = new type var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars removed.temperature = temperature @@ -228,7 +223,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) /datum/gas_mixture/copy() var/list/cached_gases = gases - var/datum/gas_mixture/copy = new + var/datum/gas_mixture/copy = new type var/list/copy_gases = copy.gases copy.temperature = temperature @@ -364,8 +359,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) sharer_temperature = sharer.temperature_archived var/temperature_delta = temperature_archived - sharer_temperature if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity_archived() - sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity_archived() + var/self_heat_capacity = heat_capacity(ARCHIVE) + sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity(ARCHIVE) if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) var/heat = conduction_coefficient*temperature_delta* \ diff --git a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm index 4097ab5c6a..90b9550028 100644 --- a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm +++ b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm @@ -19,9 +19,6 @@ /datum/gas_mixture/immutable/merge() return 0 //we're immutable. -/datum/gas_mixture/immutable/heat_capacity_archived() - return heat_capacity() - /datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4) . = ..(sharer, 0) garbage_collect() diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm index 7294638162..4edced52b3 100644 --- a/code/modules/atmospherics/machinery/other/meter.dm +++ b/code/modules/atmospherics/machinery/other/meter.dm @@ -24,7 +24,7 @@ if(!isnull(new_piping_layer)) target_layer = new_piping_layer SSair.atmos_machinery += src - if(mapload && !target) + if(!target) reattach_to_layer() return ..() diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index cad1584991..590297820e 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -49,7 +49,7 @@ //Make sure are close enough for a valid connection if(new_port.loc != get_turf(src)) - return TRUE + return FALSE //Perform the connection connected_port = new_port diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm index 7908964b1c..e3a99fdb9a 100644 --- a/code/modules/clothing/glasses/engine_goggles.dm +++ b/code/modules/clothing/glasses/engine_goggles.dm @@ -1,45 +1,48 @@ //Engineering Mesons +#define MODE_NONE "" +#define MODE_MESON "meson" +#define MODE_TRAY "t-ray" +#define MODE_RAD "radiation" + /obj/item/clothing/glasses/meson/engine name = "engineering scanner goggles" - desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, regardless of lighting condition. The T-ray Scanner mode lets you see underfloor objects such as cables and pipes." - icon_state = "trayson-meson" + desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, the T-ray Scanner mode lets you see underfloor objects such as cables and pipes, and the Radiation Scanner mode let's you see objects contaminated by radiation." + icon_state = "trayson" actions_types = list(/datum/action/item_action/toggle_mode) origin_tech = "materials=3;magnets=3;engineering=3;plasmatech=3" - var/mesons_on = TRUE //if set to FALSE, these goggles work as t-ray scanners. + vision_flags = NONE + darkness_view = 2 + invis_view = SEE_INVISIBLE_LIVING + + var/list/modes = list(MODE_NONE = MODE_MESON, MODE_MESON = MODE_TRAY, MODE_TRAY = MODE_RAD, MODE_RAD = MODE_NONE) + var/mode = MODE_NONE var/range = 1 - - /obj/item/clothing/glasses/meson/engine/Initialize() . = ..() START_PROCESSING(SSobj, src) + update_icon() /obj/item/clothing/glasses/meson/engine/Destroy() STOP_PROCESSING(SSobj, src) return ..() /obj/item/clothing/glasses/meson/engine/proc/toggle_mode(mob/user, voluntary) - mesons_on = !mesons_on + mode = modes[mode] + to_chat(user, "[voluntary ? "You turn the goggles":"The goggles turn"] [mode ? "to [mode] mode":"off"][voluntary ? ".":"!"]") - if(!mesons_on) - vision_flags = 0 - darkness_view = 2 - invis_view = SEE_INVISIBLE_LIVING - lighting_alpha = null - if(voluntary) - to_chat(user, "You toggle the goggles' scanning mode to \[T-Ray].") - else - to_chat(user, "The goggles abruptly toggle to \[T-Ray] mode!") - else - vision_flags = SEE_TURFS - darkness_view = 1 - lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE - if(voluntary) - to_chat(user, "You toggle the goggles' scanning mode to \[Meson].") - else - to_chat(user, "The goggles abruptly toggle to \[Meson] mode!") + switch(mode) + if(MODE_MESON) + vision_flags = SEE_TURFS + darkness_view = 1 + lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE + + if(MODE_TRAY) //undoes the last mode, meson + vision_flags = NONE + darkness_view = 2 + lighting_alpha = null if(ishuman(user)) var/mob/living/carbon/human/H = user @@ -55,7 +58,7 @@ toggle_mode(user, TRUE) /obj/item/clothing/glasses/meson/engine/process() - if(mesons_on) + if(mode == MODE_MESON) var/turf/T = get_turf(src) if(T && T.z == ZLEVEL_MINING) toggle_mode(loc) @@ -63,11 +66,13 @@ if(!ishuman(loc)) return - var/mob/living/carbon/human/user = loc - if(user.glasses != src) + if(user.glasses != src || !user.client) return - scan() + if(mode == MODE_TRAY) + scan() + else if(mode == MODE_RAD) + show_rads() /obj/item/clothing/glasses/meson/engine/proc/scan() for(var/turf/T in range(range, loc)) @@ -79,17 +84,40 @@ flick_sonar(O) /obj/item/clothing/glasses/meson/engine/proc/flick_sonar(obj/pipe) - if(ismob(loc)) - var/mob/M = loc - var/image/I = new(loc = get_turf(pipe)) - var/mutable_appearance/MA = new(pipe) + var/mob/M = loc + var/image/I = new(loc = get_turf(pipe)) + var/mutable_appearance/MA = new(pipe) + MA.alpha = 128 + I.appearance = MA + flick_overlay(I, list(M.client), 8) + +/obj/item/clothing/glasses/meson/engine/proc/show_rads() + var/mob/living/carbon/human/user = loc + var/list/rad_places = list() + for(var/datum/component/radioactive/thing in SSradiation.processing) + var/atom/owner = thing.parent + var/turf/place = get_turf(owner) + if(rad_places[place]) + rad_places[place] += thing.strength + else + rad_places[place] = thing.strength + + for(var/i in rad_places) + var/turf/place = i + if(get_dist(user, place) >= range*2) //Rads are easier to see than wires under the floor + continue + var/strength = round(rad_places[i] / 1000, 0.1) + var/image/pic = new(loc = place) + var/mutable_appearance/MA = new() MA.alpha = 128 - I.appearance = MA - if(M.client) - flick_overlay(I, list(M.client), 8) + MA.maptext = "[strength]k" + MA.color = "#64C864" + MA.layer = AREA_LAYER + pic.appearance = MA + flick_overlay(pic, list(user.client), 8) /obj/item/clothing/glasses/meson/engine/update_icon() - icon_state = mesons_on ? "trayson-meson" : "trayson-tray" + icon_state = "[initial(icon_state)]-[mode]" if(istype(loc, /mob/living/carbon/human/)) var/mob/living/carbon/human/user = loc if(user.glasses == src) @@ -98,35 +126,13 @@ /obj/item/clothing/glasses/meson/engine/tray //atmos techs have lived far too long without tray goggles while those damned engineers get their dual-purpose gogles all to themselves name = "optical t-ray scanner" desc = "Used by engineering staff to see underfloor objects such as cables and pipes." - icon_state = "trayson-tray_off" origin_tech = "materials=3;magnets=2;engineering=2" - mesons_on = FALSE - var/on = FALSE - vision_flags = 0 - darkness_view = 2 - invis_view = SEE_INVISIBLE_LIVING range = 2 + modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_NONE) -/obj/item/clothing/glasses/meson/engine/tray/process() - if(!on) - return - ..() - -/obj/item/clothing/glasses/meson/engine/tray/update_icon() - icon_state = "trayson-tray[on ? "" : "_off"]" - if(istype(loc, /mob/living/carbon/human/)) - var/mob/living/carbon/human/user = loc - if(user.glasses == src) - user.update_inv_glasses() - -/obj/item/clothing/glasses/meson/engine/tray/toggle_mode(mob/user, voluntary) - on = !on - - to_chat(user, "[voluntary ? "You turn the goggles":"The goggles turn"] [on ? "on":"off"][voluntary ? ".":"!"]") - - update_icon() - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon() +#undef MODE_NONE +#undef MODE_MESON +#undef MODE_TRAY +#undef MODE_RAD \ No newline at end of file diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm index 2fe1f775b4..e5d7b6b4fe 100644 --- a/code/modules/fields/timestop.dm +++ b/code/modules/fields/timestop.dm @@ -119,7 +119,7 @@ L.anchored = TRUE if(ishostile(L)) var/mob/living/simple_animal/hostile/H = L - H.AIStatus = AI_OFF + H.toggle_ai(AI_OFF) H.LoseTarget() /datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L) @@ -128,4 +128,4 @@ frozen_mobs -= L if(ishostile(L)) var/mob/living/simple_animal/hostile/H = L - H.AIStatus = initial(H.AIStatus) + H.toggle_ai(initial(H.AIStatus)) diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 58f091fd4c..1fcb03e2b6 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -59,7 +59,7 @@ SetCollectBehavior() /mob/living/simple_animal/hostile/mining_drone/sentience_act() - AIStatus = AI_OFF + ..() check_friendly_fire = 0 /mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 41e6754493..7a212d371b 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1144,11 +1144,14 @@ radiation = 0 return TRUE - if(radiation > RAD_MOB_KNOCKDOWN) + if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB)) if(!H.IsKnockdown()) H.emote("collapse") - H.Knockdown(RAD_KNOCKDOWN_TIME) + H.Knockdown(RAD_MOB_KNOCKDOWN_AMOUNT) to_chat(H, "You feel weak.") + + if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB)) + H.vomit(10, TRUE) if(radiation > RAD_MOB_MUTATE) if(prob(1)) @@ -1158,10 +1161,9 @@ H.domutcheck() if(radiation > RAD_MOB_HAIRLOSS) - if(prob(15)) - if(!( H.hair_style == "Shaved") || !(H.hair_style == "Bald") || (HAIR in species_traits)) - to_chat(H, "Your hair starts to fall out in clumps...") - addtimer(CALLBACK(src, .proc/go_bald, H), 50) + if(prob(15) && !(H.hair_style == "Bald") && (HAIR in species_traits)) + to_chat(H, "Your hair starts to fall out in clumps...") + addtimer(CALLBACK(src, .proc/go_bald, H), 50) /datum/species/proc/go_bald(mob/living/carbon/human/H) if(QDELETED(H)) //may be called from a timer diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index de0f733944..bc654f9201 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -63,7 +63,7 @@ There are several things that need to be remembered: ..() /mob/living/carbon/human/update_fire() - ..("Standing") + ..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning") /* --------------------------------------- */ diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 714ba02a85..613a04bd17 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -24,10 +24,10 @@ /mob/living/carbon/monkey/handle_mutations_and_radiation() if(radiation) - if(radiation > RAD_MOB_KNOCKDOWN) + if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB)) if(!IsKnockdown()) emote("collapse") - Knockdown(200) + Knockdown(RAD_MOB_KNOCKDOWN_AMOUNT) to_chat(src, "You feel weak.") if(radiation > RAD_MOB_MUTATE) if(prob(1)) @@ -39,6 +39,8 @@ if(radiation > RAD_MOB_MUTATE * 2 && prob(50)) gorillize() return + if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB)) + vomit(10, TRUE) return ..() /mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath) diff --git a/code/modules/mob/living/carbon/status_procs.dm b/code/modules/mob/living/carbon/status_procs.dm index ce14664a0e..13a97c4407 100644 --- a/code/modules/mob/living/carbon/status_procs.dm +++ b/code/modules/mob/living/carbon/status_procs.dm @@ -41,39 +41,28 @@ clear_fullscreen("eye_damage") /mob/living/carbon/adjust_drugginess(amount) - var/old_druggy = druggy - if(amount>0) - druggy += amount - if(!old_druggy) - overlay_fullscreen("high", /obj/screen/fullscreen/high) - throw_alert("high", /obj/screen/alert/high) - else if(old_druggy) - druggy = max(druggy+amount, 0) - if(!druggy) - clear_fullscreen("high") - clear_alert("high") + druggy = max(druggy+amount, 0) + if(druggy) + overlay_fullscreen("high", /obj/screen/fullscreen/high) + throw_alert("high", /obj/screen/alert/high) + else + clear_fullscreen("high") + clear_alert("high") + /mob/living/carbon/set_drugginess(amount) - var/old_druggy = druggy - druggy = amount - if(amount>0) - if(!old_druggy) - overlay_fullscreen("high", /obj/screen/fullscreen/high) - throw_alert("high", /obj/screen/alert/high) - else if(old_druggy) + druggy = max(amount, 0) + if(druggy) + overlay_fullscreen("high", /obj/screen/fullscreen/high) + throw_alert("high", /obj/screen/alert/high) + else clear_fullscreen("high") clear_alert("high") /mob/living/carbon/adjust_disgust(amount) - var/old_disgust = disgust - if(amount>0) - disgust = min(disgust+amount, DISGUST_LEVEL_MAXEDOUT) - - else if(old_disgust) - disgust = max(disgust+amount, 0) + disgust = Clamp(disgust+amount, 0, DISGUST_LEVEL_MAXEDOUT) /mob/living/carbon/set_disgust(amount) - if(amount >= 0) - disgust = amount + disgust = Clamp(amount, 0, DISGUST_LEVEL_MAXEDOUT) /mob/living/carbon/cure_blind() if(disabilities & BLIND) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index bbb36edad3..0cfda3821f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -586,7 +586,7 @@ if(!force_moving) ..(pressure_difference, direction, pressure_resistance_prob_delta) -/mob/living/proc/can_resist() +/mob/living/can_resist() return !((next_move > world.time) || incapacitated(ignore_restraints = TRUE)) /mob/living/verb/resist() diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 2f8bcc5595..b176649a37 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -813,12 +813,16 @@ return FALSE if(be_close && !in_range(M, src)) return FALSE - //stop AIs from leaving windows open and using then after they lose vision - //apc_override is needed here because AIs use their own APC when powerless - //get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera - if(M && GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override) - return FALSE - return TRUE + return can_see(M) //stop AIs from leaving windows open and using then after they lose vision + +/mob/living/silicon/ai/proc/can_see(atom/A) + if(isturf(loc)) //AI in core, check if on cameras + //get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera + //apc_override is needed here because AIs use their own APC when depowered + return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(get_turf_pixel(A))) || apc_override + //AI is carded/shunted + //view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist + return get_dist(src, A) <= client.view /mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index d85ac96784..6df7717327 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -305,6 +305,7 @@ /obj/item/device/multitool/cyborg, /obj/item/device/t_scanner, /obj/item/device/analyzer, + /obj/item/device/geiger_counter, /obj/item/device/assembly/signaler/cyborg, /obj/item/areaeditor/blueprints/cyborg, /obj/item/device/electroadaptive_pseudocircuit, diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index be41ba791d..04a83647ed 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -348,7 +348,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, mode = BOT_HUNT /mob/living/simple_animal/bot/honkbot/Crossed(atom/movable/AM) - if(ismob(AM)) + if(ismob(AM) && (on)) //only if its online if(prob(30)) //you're far more likely to trip on a honkbot var/mob/living/carbon/C = AM if(!istype(C) || !C || in_range(src, target)) @@ -362,7 +362,8 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, "[C] leaps out of [src]'s way!")]") C.Knockdown(10) playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 1, -1) - speak("Honk!") + if(!client) + speak("Honk!") sensor_blink() return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index 9f7a7d1bbf..0213a79e4a 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -49,6 +49,8 @@ var/idle = 0 var/isqueen = FALSE var/icon_base = "bee" + var/static/beehometypecache = typecacheof(/obj/structure/beebox) + var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics) /mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0) @@ -118,7 +120,7 @@ if(istype(A, /obj/machinery/hydroponics)) var/obj/machinery/hydroponics/Hydro = A if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit) - wanted_objects |= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted + wanted_objects |= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted return TRUE return FALSE @@ -132,8 +134,9 @@ if(target == beehome) var/obj/structure/beebox/BB = target forceMove(BB) + toggle_ai(AI_IDLE) target = null - wanted_objects -= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home + wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home return //no don't attack the goddamm box else . = ..() @@ -157,7 +160,7 @@ return target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity - wanted_objects -= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted + wanted_objects -= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted Hydro.recent_bee_visit = TRUE spawn(BEE_TRAY_RECENT_VISIT) if(Hydro) @@ -187,12 +190,13 @@ if(loc == beehome) idle = min(100, ++idle) if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM)) + toggle_ai(AI_ON) forceMove(beehome.drop_location()) else idle = max(0, --idle) if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME)) if(!FindTarget()) - wanted_objects |= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home + wanted_objects |= beehometypecache //so we don't attack beeboxes when not going home target = beehome if(!beehome) //add outselves to a beebox (of the same reagent) if we have no home for(var/obj/structure/beebox/BB in view(vision_range, src)) @@ -285,3 +289,11 @@ QDEL_NULL(queen) return ..() +/mob/living/simple_animal/hostile/poison/bees/consider_wakeup() + if (beehome && loc == beehome) // If bees are chilling in their nest, they're not actively looking for targets + idle = min(100, ++idle) + if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM)) + toggle_ai(AI_ON) + forceMove(beehome.drop_location()) + else + ..() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 6f3b526a03..f1b3043447 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -49,7 +49,6 @@ var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead. var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses var/attack_same = 0 //Set us to 1 to allow us to attack our own faction - var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever) var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects. @@ -88,7 +87,7 @@ DestroySurroundings() if(!MoveToTarget(possible_targets)) //if we lose our target if(AIShouldSleep(possible_targets)) // we try to acquire a new one - AIStatus = AI_IDLE // otherwise we go idle + toggle_ai(AI_IDLE) // otherwise we go idle return 1 /mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user) @@ -289,7 +288,7 @@ target = null LoseSearchObjects() if(AIStatus == AI_IDLE) - AIStatus = AI_ON + toggle_ai(AI_ON) FindTarget() else if(target != null && prob(40))//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one FindTarget() @@ -424,7 +423,7 @@ if(AI_IDLE) if(FindTarget(possible_targets, 1)) . = 1 - AIStatus = AI_ON //Wake up for more than one Life() cycle. + toggle_ai(AI_ON) //Wake up for more than one Life() cycle. else . = 0 @@ -455,3 +454,9 @@ if(!value) value = initial(search_objects) search_objects = value + +/mob/living/simple_animal/hostile/consider_wakeup() + ..() + if(AIStatus == AI_IDLE && FindTarget(ListTargets(), 1)) + toggle_ai(AI_ON) + diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index c9b858f76c..a9ed6a4120 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -82,6 +82,10 @@ var/dextrous_hud_type = /datum/hud/dextrous var/datum/personal_crafting/handcrafting + var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever) + + var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check. + //domestication var/tame = 0 @@ -89,7 +93,7 @@ /mob/living/simple_animal/Initialize() . = ..() - GLOB.simple_animals += src + GLOB.simple_animals[AIStatus] += src handcrafting = new() if(gender == PLURAL) gender = pick(MALE,FEMALE) @@ -102,7 +106,7 @@ verbs |= /mob/living/proc/animal_nom /mob/living/simple_animal/Destroy() - GLOB.simple_animals -= src + GLOB.simple_animals[AIStatus] -= src return ..() /mob/living/simple_animal/updatehealth() @@ -422,7 +426,7 @@ /mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion - return + toggle_ai(AI_OFF) // To prevent any weirdness. /mob/living/simple_animal/update_sight() if(!client) @@ -545,3 +549,23 @@ /mob/living/simple_animal/buckle_mob(mob/living/buckled_mob, force = 0, check_loc = 1) . = ..() riding_datum = new/datum/riding/animal + + +/mob/living/simple_animal/proc/toggle_ai(togglestatus) + if (AIStatus != togglestatus) + if (togglestatus > 0 && togglestatus < 4) + GLOB.simple_animals[AIStatus] -= src + GLOB.simple_animals[togglestatus] += src + AIStatus = togglestatus + else + stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]") + +/mob/living/simple_animal/proc/consider_wakeup() + if (pulledby || shouldwakeup) + toggle_ai(AI_ON) + +/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE, forced = FALSE) + . = ..() + if(!ckey && !stat)//Not unconscious + if(AIStatus == AI_IDLE) + toggle_ai(AI_ON) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/spawner.dm b/code/modules/mob/living/simple_animal/spawner.dm index a8ff6be4ba..33eade6014 100644 --- a/code/modules/mob/living/simple_animal/spawner.dm +++ b/code/modules/mob/living/simple_animal/spawner.dm @@ -30,7 +30,7 @@ spawned_mobs = null return ..() -/mob/living/simple_animal/hostile/spawner/handle_automated_action() +/mob/living/simple_animal/hostile/spawner/Life() . = ..() spawn_mob() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 02c1fa4b44..657c4f0ded 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -356,6 +356,9 @@ else M.LAssailant = usr +/mob/proc/can_resist() + return FALSE //overridden in living.dm + /mob/proc/spin(spintime, speed) set waitfor = 0 var/D = dir diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 3d87de4e62..d17071eeb3 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -278,7 +278,7 @@ //dist_check - set to only shock mobs within 1 of source (vendors, airlocks, etc.) //No animations will be performed by this proc. /proc/electrocute_mob(mob/living/carbon/M, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE) - if(ismecha(M.loc)) + if(!M || ismecha(M.loc)) return 0 //feckin mechs are dumb if(dist_check) if(!in_range(source,M)) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index d7094d8c85..ce2cd90a49 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -21,7 +21,7 @@ var/move_self = 1 //Do we move on our own? var/grav_pull = 4 //How many tiles out do we pull? var/consume_range = 0 //How many tiles out do we eat - var/event_chance = 15 //Prob for event each tick + var/event_chance = 10 //Prob for event each tick var/target = null //its target. moves towards the target if it has one var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing var/last_warning @@ -114,7 +114,7 @@ /obj/singularity/process() if(current_size >= STAGE_TWO) move() - radiation_pulse(src, energy, 0.5) + radiation_pulse(src, min(5000, (energy*3)+1000), RAD_DISTANCE_COEFFICIENT*0.5) if(prob(event_chance))//Chance for it to run a special event TODO:Come up with one or two more that fit event() eat() @@ -367,15 +367,13 @@ /obj/singularity/proc/event() - var/numb = pick(1,2,3,4,5,6) + var/numb = rand(1,4) switch(numb) if(1)//EMP emp_area() - if(2,3)//tox damage all carbon mobs in area - toxmob() - if(4)//Stun mobs who lack optic scanners + if(2)//Stun mobs who lack optic scanners mezzer() - if(5,6) //Sets all nearby mobs on fire + if(3,4) //Sets all nearby mobs on fire if(current_size < STAGE_SIX) return 0 combust_mobs() @@ -384,13 +382,6 @@ return 1 -/obj/singularity/proc/toxmob() - var/radiation = 15 - if (energy>200) - radiation += round((energy-150)/10,1) - radiation_pulse(src, radiation) - - /obj/singularity/proc/combust_mobs() for(var/mob/living/carbon/C in urange(20, src, 1)) C.visible_message("[C]'s skin bursts into flame!", \ diff --git a/code/modules/reagents/chemistry/reagents/blob_reagents.dm b/code/modules/reagents/chemistry/reagents/blob_reagents.dm index 054e9a84cf..de96631bc9 100644 --- a/code/modules/reagents/chemistry/reagents/blob_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/blob_reagents.dm @@ -78,7 +78,7 @@ /datum/reagent/blob/networked_fibers name = "Networked Fibers" id = "networked_fibers" - description = "will do high brute and burn damage but non-manual expansion will only generate resources." + description = "will do high brute and burn damage and will generate resources quicker, but can only expand manually." shortdesc = "will do high brute and burn damage." effectdesc = "will move your core when manually expanding near it." analyzerdescdamage = "Does high brute and burn damage." diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index a25401eec5..818ea3d17f 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -466,7 +466,7 @@ metabolization_rate = 0.5 * REAGENTS_METABOLISM /datum/reagent/medicine/pen_acid/on_mob_life(mob/living/M) - M.radiation -= min(M.radiation, log(M.radiation)*10) + M.radiation -= min(M.radiation-RAD_MOB_SAFE, 0)/100 M.adjustToxLoss(-2*REM, 0) for(var/datum/reagent/R in M.reagents.reagent_list) if(R != src) diff --git a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm index 1cc5b482f0..7f301bf8b9 100644 --- a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm +++ b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm @@ -16,7 +16,7 @@ new /obj/item/device/assembly/signaler/anomaly (get_step(loc, pick(GLOB.alldirs))) return ..() -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/handle_automated_action() +/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/Life() consume() return ..() diff --git a/code/modules/tgui/states/default.dm b/code/modules/tgui/states/default.dm index 573dcdf7cf..3ae48c7bc7 100644 --- a/code/modules/tgui/states/default.dm +++ b/code/modules/tgui/states/default.dm @@ -42,8 +42,8 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new) if(. < UI_INTERACTIVE) return - // The AI can interact with anything it can see nearby, or with cameras. - if((get_dist(src, src_object) <= client.view) || GLOB.cameranet.checkTurfVis(get_turf_pixel(src_object))) + // The AI can interact with anything it can see nearby, or with cameras while wireless control is enabled. + if(!control_disabled && can_see(src_object)) return UI_INTERACTIVE return UI_CLOSE diff --git a/html/changelogs/AutoChangeLog-pr-3482.yml b/html/changelogs/AutoChangeLog-pr-3482.yml new file mode 100644 index 0000000000..e1f50ba5d5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3482.yml @@ -0,0 +1,4 @@ +author: "Gun Hog" +delete-after: True +changes: + - bugfix: "The GPS item now correctly changes its name when the GPS tag is changed." diff --git a/html/changelogs/AutoChangeLog-pr-3484.yml b/html/changelogs/AutoChangeLog-pr-3484.yml new file mode 100644 index 0000000000..a296d8f74e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3484.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - tweak: "Engineering cyborgs now have access to geiger counters." diff --git a/html/changelogs/AutoChangeLog-pr-3486.yml b/html/changelogs/AutoChangeLog-pr-3486.yml new file mode 100644 index 0000000000..b07d24883b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3486.yml @@ -0,0 +1,10 @@ +author: "ninjanomnom" +delete-after: True +changes: + - rscadd: "You can vomit blood at high enough radiation." + - balance: "Radiation knockdown is far far shorter." + - balance: "Genetics modification is less harmful but still, upgrade your machines." + - balance: "Pentetic acid is useless for low amounts of radiation but indispensable for high amounts now." + - balance: "Singularity radiation has been normalized and Pubby engine has been remapped." + - bugfix: "No more hair loss spam" + - bugfix: "Mob rad contamination has been disabled for now. Regular contamination is still a thing." diff --git a/html/changelogs/AutoChangeLog-pr-3487.yml b/html/changelogs/AutoChangeLog-pr-3487.yml new file mode 100644 index 0000000000..602ea77c7a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3487.yml @@ -0,0 +1,4 @@ +author: "More Robust Than You" +delete-after: True +changes: + - tweak: "People that are burning slightly less will appear to be burning... slightly less." diff --git a/html/changelogs/AutoChangeLog-pr-3488.yml b/html/changelogs/AutoChangeLog-pr-3488.yml new file mode 100644 index 0000000000..4962e5d679 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3488.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - bugfix: "Renault now has a comfy new bed on Metastation!" diff --git a/html/changelogs/AutoChangeLog-pr-3498.yml b/html/changelogs/AutoChangeLog-pr-3498.yml new file mode 100644 index 0000000000..45780c6d0b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3498.yml @@ -0,0 +1,4 @@ +author: "ninjanomnom" +delete-after: True +changes: + - rscadd: "Engineering scanner goggles have a radiation mode now" diff --git a/html/changelogs/AutoChangeLog-pr-3499.yml b/html/changelogs/AutoChangeLog-pr-3499.yml new file mode 100644 index 0000000000..21ebf770c9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3499.yml @@ -0,0 +1,5 @@ +author: "ninjanomnom" +delete-after: True +changes: + - rscadd: "Objects placed under showers are cleansed of radioactive contamination over a short time." + - soundadd: "Showers make sound now." diff --git a/html/changelogs/AutoChangeLog-pr-3503.yml b/html/changelogs/AutoChangeLog-pr-3503.yml new file mode 100644 index 0000000000..0fd9f587eb --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3503.yml @@ -0,0 +1,5 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - tweak: "You will no longer trip on inactive honkbots." + - bugfix: "Sentient Honkbots are no longer forced to speak when somebody trip on them." diff --git a/html/changelogs/AutoChangeLog-pr-3504.yml b/html/changelogs/AutoChangeLog-pr-3504.yml new file mode 100644 index 0000000000..e0f0c79ffd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3504.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - tweak: "You can now press Ctrl+H to stop pulling, or simply H to stop pulling if you're in hotkey mode." diff --git a/html/changelogs/AutoChangeLog-pr-3506.yml b/html/changelogs/AutoChangeLog-pr-3506.yml new file mode 100644 index 0000000000..7ec7575219 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3506.yml @@ -0,0 +1,4 @@ +author: "Naksu" +delete-after: True +changes: + - bugfix: "Manned turrets stop firing when there's no-one in the turret shooting." diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index 193182892d..39f5f1a6f8 100644 Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ diff --git a/icons/obj/atmospherics/pipes/manifold.dmi b/icons/obj/atmospherics/pipes/manifold.dmi index 3e4d218ca6..4eebe1a078 100644 Binary files a/icons/obj/atmospherics/pipes/manifold.dmi and b/icons/obj/atmospherics/pipes/manifold.dmi differ diff --git a/icons/obj/atmospherics/pipes/pipe_item.dmi b/icons/obj/atmospherics/pipes/pipe_item.dmi index d953fc4c89..de7940bd03 100644 Binary files a/icons/obj/atmospherics/pipes/pipe_item.dmi and b/icons/obj/atmospherics/pipes/pipe_item.dmi differ diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index 1152b395ab..5045ccce2b 100644 Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ diff --git a/interface/interface.dm b/interface/interface.dm index a67cc5d290..0e0ecbdc8c 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -116,6 +116,7 @@ Hotkey-Mode: (hotkey-mode must be on) \tt = say \to = OOC \tb = resist +\th = stop pulling \tx = swap-hand \tz = activate held object (or y) \tf = cycle-intents-left @@ -138,6 +139,7 @@ Any-Mode: (hotkey doesn't need to be on) \tCtrl+e = equip \tCtrl+r = throw \tCtrl+b = resist +\tCtrl+h = stop pulling \tCtrl+o = OOC \tCtrl+x = swap-hand \tCtrl+z = activate held object (or Ctrl+y) @@ -149,7 +151,7 @@ Any-Mode: (hotkey doesn't need to be on) \tCtrl+4 = harm-intent \tCtrl+'+/-' OR \tShift+Mousewheel = Ghost zoom in/out -\tDEL = pull +\tDEL = stop pulling \tINS = cycle-intents-right \tHOME = drop \tPGUP = swap-hand @@ -171,9 +173,9 @@ Hotkey-Mode: (hotkey-mode must be on) \td = right \tw = up \tq = unequip active module +\th = stop pulling \tm = me \tt = say -\th = talk-wheel \to = OOC \tx = cycle active modules \tb = resist @@ -195,7 +197,7 @@ Any-Mode: (hotkey doesn't need to be on) \tCtrl+q = unequip active module \tCtrl+x = cycle active modules \tCtrl+b = resist -\tCtrl+h = talk-wheel +\tCtrl+h = stop pulling \tCtrl+o = OOC \tCtrl+z = activate held object (or Ctrl+y) \tCtrl+f = cycle-intents-left @@ -204,7 +206,7 @@ Any-Mode: (hotkey doesn't need to be on) \tCtrl+2 = activate module 2 \tCtrl+3 = activate module 3 \tCtrl+4 = toggle intents -\tDEL = pull +\tDEL = stop pulling \tINS = toggle intents \tPGUP = cycle active modules \tPGDN = activate held object diff --git a/interface/skin.dmf b/interface/skin.dmf index d30261f6b3..1dbebc524f 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -63,6 +63,10 @@ macro "default" name = "DELETE" command = "delete-key-pressed" is-disabled = false + elem + name = "CTRL+H" + command = "delete-key-pressed" + is-disabled = false elem name = "CTRL+1" command = "a-intent help" @@ -285,6 +289,10 @@ macro "hotkeys" name = "DELETE" command = "delete-key-pressed" is-disabled = false + elem + name = "H" + command = "delete-key-pressed" + is-disabled = false elem name = "1" command = "a-intent help" @@ -583,6 +591,10 @@ macro "robot-default" name = "DELETE" command = "delete-key-pressed" is-disabled = false + elem + name = "CTRL+H" + command = "delete-key-pressed" + is-disabled = false elem name = "CTRL+1" command = "toggle-module 1" @@ -777,6 +789,10 @@ macro "robot-hotkeys" name = "DELETE" command = "delete-key-pressed" is-disabled = false + elem + name = "H" + command = "delete-key-pressed" + is-disabled = false elem name = "1" command = "toggle-module 1" diff --git a/sound/machines/shower/shower_end.ogg b/sound/machines/shower/shower_end.ogg new file mode 100644 index 0000000000..80b93af39e Binary files /dev/null and b/sound/machines/shower/shower_end.ogg differ diff --git a/sound/machines/shower/shower_mid1.ogg b/sound/machines/shower/shower_mid1.ogg new file mode 100644 index 0000000000..e1ae5a0c45 Binary files /dev/null and b/sound/machines/shower/shower_mid1.ogg differ diff --git a/sound/machines/shower/shower_mid2.ogg b/sound/machines/shower/shower_mid2.ogg new file mode 100644 index 0000000000..4a54acd352 Binary files /dev/null and b/sound/machines/shower/shower_mid2.ogg differ diff --git a/sound/machines/shower/shower_mid3.ogg b/sound/machines/shower/shower_mid3.ogg new file mode 100644 index 0000000000..8b4776a9b9 Binary files /dev/null and b/sound/machines/shower/shower_mid3.ogg differ diff --git a/sound/machines/shower/shower_start.ogg b/sound/machines/shower/shower_start.ogg new file mode 100644 index 0000000000..e5529f401b Binary files /dev/null and b/sound/machines/shower/shower_start.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 903f4878c8..af1858e179 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -226,6 +226,7 @@ #include "code\controllers\subsystem\fire_burning.dm" #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\icon_smooth.dm" +#include "code\controllers\subsystem\idlenpcpool.dm" #include "code\controllers\subsystem\inbounds.dm" #include "code\controllers\subsystem\ipintel.dm" #include "code\controllers\subsystem\job.dm" @@ -376,6 +377,8 @@ #include "code\datums\helper_datums\icon_snapshot.dm" #include "code\datums\helper_datums\teleport.dm" #include "code\datums\helper_datums\topic_input.dm" +#include "code\datums\looping_sounds\looping_sound.dm" +#include "code\datums\looping_sounds\machinery_sounds.dm" #include "code\datums\martial\boxing.dm" #include "code\datums\martial\cqc.dm" #include "code\datums\martial\krav_maga.dm"