diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 71fe793c3cc..7f5a9263de6 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -2,13 +2,13 @@
## What Does This PR Do
-
+
## Why It's Good For The Game
-
+
## Images of changes
-
+
## Changelog
:cl:
@@ -27,3 +27,4 @@ experiment: Added an experimental thingy
+
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 5547f1b61f6..b6d5ddfed6d 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,8 +1,5 @@
{
- "workbench.editorAssociations": [
- {
- "filenamePattern": "*.dmi",
- "viewType": "imagePreview.previewEditor"
- }
- ]
-}
+ "workbench.editorAssociations": {
+ "*.dmi": "imagePreview.previewEditor"
+ }
+}
\ No newline at end of file
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index 242b1c01f7b..2c0bfe22a86 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -146,6 +146,9 @@ GLOBAL_PROTECT(log_end)
rustg_log_write(GLOB.sql_log, "[text][GLOB.log_end]")
SEND_TEXT(world.log, text) // Redirect it to DD too
+/proc/log_chat_debug(text)
+ rustg_log_write(GLOB.chat_debug_log, "[text][GLOB.log_end]")
+
// A logging proc that only outputs after setup is done, to
// help devs test initialization stuff that happens a lot
/proc/log_after_setup(message)
diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm
index cb953a2a503..c111aff28cf 100644
--- a/code/_globalvars/logging.dm
+++ b/code/_globalvars/logging.dm
@@ -19,6 +19,8 @@ GLOBAL_VAR(http_log)
GLOBAL_PROTECT(http_log)
GLOBAL_VAR(sql_log)
GLOBAL_PROTECT(sql_log)
+GLOBAL_VAR(chat_debug_log)
+GLOBAL_PROTECT(chat_debug_log)
GLOBAL_VAR(round_id)
GLOBAL_PROTECT(round_id)
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index bb2c4647d89..16383b05352 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -784,6 +784,7 @@
var/obj/item/card/id/I = H.wear_id
if(istype(I))
apply_to_card(I, H, list(ACCESS_TRADE_SOL, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS), name)
+ H.sec_hud_set_ID()
/datum/outfit/admin/chrono
name = "Chrono Legionnaire"
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 191bc9638a4..d9cc6ab55c0 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -944,9 +944,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/narsie_act()
return
-/atom/proc/ratvar_act()
- return
-
/**
* Respond to an electric bolt action on our item
*
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 284b130f803..61097b2c796 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -178,12 +178,10 @@
/mob/living/carbon/med_hud_set_status()
var/image/holder = hud_list[STATUS_HUD]
var/mob/living/simple_animal/borer/B = has_brain_worms()
- var/dead = stat == DEAD || HAS_TRAIT(src, TRAIT_FAKEDEATH)
// To the right of health bar
- if(dead)
- var/mob/dead/observer/ghost = get_ghost(TRUE)
+ if(stat == DEAD || HAS_TRAIT(src, TRAIT_FAKEDEATH))
var/revivable
- if(ghost && !ghost.can_reenter_corpse) // DNR or AntagHUD
+ if(!ghost_can_reenter()) // DNR or AntagHUD
revivable = FALSE
else if(timeofdeath && (round(world.time - timeofdeath) < DEFIB_TIME_LIMIT))
revivable = TRUE
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 90498c9ab26..67a18cbfc45 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -595,7 +595,8 @@ structure_check() searches for nearby cultist structures required for the invoca
return
sacrifices_used += SOULS_TO_REVIVE
mob_to_revive.revive()
- mob_to_revive.grab_ghost()
+ if(mob_to_revive.ghost_can_reenter())
+ mob_to_revive.grab_ghost()
if(!mob_to_revive.client || mob_to_revive.client.is_afk())
set waitfor = FALSE
diff --git a/code/game/gamemodes/miniantags/guardian/types/healer.dm b/code/game/gamemodes/miniantags/guardian/types/healer.dm
index 64a6522833c..6411998eb1e 100644
--- a/code/game/gamemodes/miniantags/guardian/types/healer.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/healer.dm
@@ -94,7 +94,7 @@
F.icon = 'icons/turf/floors.dmi'
F.name = "bluespace recieving pad"
F.desc = "A recieving zone for bluespace teleportations. Building a wall over it should disable it."
- F.icon_state = "light_on-w"
+ F.icon_state = "light_on"
to_chat(src, "Beacon placed! You may now warp targets to it, including your user, via Alt+Click. ")
if(beacon)
beacon.ChangeTurf(/turf/simulated/floor/plating)
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index d79f8c2f41b..e0a933164d7 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -108,18 +108,23 @@
var/agent_number = 1
var/spawnpos = 1
+ var/obj/machinery/nuclearbomb/syndicate/the_bomb
+ if(nuke_spawn && length(synd_spawn))
+ the_bomb = new /obj/machinery/nuclearbomb/syndicate(nuke_spawn.loc)
+ the_bomb.r_code = nuke_code
+
for(var/datum/mind/synd_mind in syndicates)
if(spawnpos > synd_spawn.len)
spawnpos = 2
synd_mind.current.loc = synd_spawn[spawnpos]
synd_mind.offstation_role = TRUE
forge_syndicate_objectives(synd_mind)
- create_syndicate(synd_mind)
+ create_syndicate(synd_mind, the_bomb)
greet_syndicate(synd_mind)
equip_syndicate(synd_mind.current)
if(!leader_selected)
- prepare_syndicate_leader(synd_mind, nuke_code)
+ prepare_syndicate_leader(synd_mind, the_bomb)
leader_selected = 1
else
synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]"
@@ -131,9 +136,6 @@
scale_telecrystals()
share_telecrystals()
- if(nuke_spawn && synd_spawn.len > 0)
- var/obj/machinery/nuclearbomb/syndicate/the_bomb = new /obj/machinery/nuclearbomb/syndicate(nuke_spawn.loc)
- the_bomb.r_code = nuke_code
return ..()
@@ -160,7 +162,7 @@
U.hidden_uplink.uses++
remainder--
-/datum/game_mode/proc/create_syndicate(datum/mind/synd_mind) // So we don't have inferior species as ops - randomize a human
+/datum/game_mode/proc/create_syndicate(datum/mind/synd_mind, obj/machinery/nuclearbomb/syndicate/the_bomb) // So we don't have inferior species as ops - randomize a human
var/mob/living/carbon/human/M = synd_mind.current
M.set_species(/datum/species/human, TRUE)
@@ -186,7 +188,11 @@
M.regenerate_icons()
M.update_body()
-/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code)
+ if(the_bomb)
+ synd_mind.store_memory("Syndicate [the_bomb.name] Code: [the_bomb.r_code]")
+ to_chat(synd_mind.current, "The code for \the [the_bomb.name] is: [the_bomb.r_code]")
+
+/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, obj/machinery/nuclearbomb/syndicate/the_bomb)
var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
synd_mind.current.real_name = "[syndicate_name()] Team [leader_title]"
to_chat(synd_mind.current, "You are the Syndicate leader for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.")
@@ -198,11 +204,9 @@
update_syndicate_id(synd_mind, leader_title, TRUE)
- if(nuke_code)
- synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0)
- to_chat(synd_mind.current, "The nuclear authorization code is: [nuke_code]")
+ if(the_bomb)
var/obj/item/paper/P = new
- P.info = "The nuclear authorization code is: [nuke_code]"
+ P.info = "The code for \the [the_bomb.name] is: [the_bomb.r_code]"
P.name = "nuclear bomb code"
var/obj/item/stamp/syndicate/stamp = new
P.stamp(stamp)
@@ -216,8 +220,6 @@
H.equip_to_slot_or_del(P, slot_r_store, 0)
H.update_icons()
- else
- nuke_code = "code will be provided later"
/datum/game_mode/proc/update_syndicate_id(datum/mind/synd_mind, is_leader = FALSE)
var/list/found_ids = synd_mind.current.search_contents_for(/obj/item/card/id)
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index 550d36482c7..16824ecd770 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -257,17 +257,17 @@
return ..()
////////////////////////////Proc for moving soul in and out off stone//////////////////////////////////////
-
+// this whole proc is pain
/obj/item/soulstone/proc/transfer_soul(choice, target, mob/user)
switch(choice)
if("FORCE")
var/mob/living/T = target
- if(T.client != null)
+ if(T.client && T.ghost_can_reenter()) // Haven't DC'd or ahudded
init_shade(T, user)
- else
+ else // Poll ghosts
to_chat(user, "Capture failed! The soul has already fled its mortal frame. You attempt to bring it back...")
T.Paralyse(20)
- if(!get_cult_ghost(T, user))
+ if(!get_cult_ghost(T, user, TRUE))
T.dust() //If we can't get a ghost, kill the sacrifice anyway.
if("VICTIM")
@@ -280,7 +280,7 @@
else
if(T.client == null)
to_chat(user, "Capture failed! The soul has already fled its mortal frame. You attempt to bring it back...")
- get_cult_ghost(T, user)
+ get_cult_ghost(T, user, get_new_player = !T.ghost_can_reenter())
else
if(length(contents))
to_chat(user, "Capture failed! The soul stone is full! Use or free an existing soul to make room.")
@@ -417,13 +417,14 @@
return /mob/living/simple_animal/shade/holy
return /mob/living/simple_animal/shade/cult
-/obj/item/soulstone/proc/get_cult_ghost(mob/living/M, mob/user)
+/obj/item/soulstone/proc/get_cult_ghost(mob/living/M, mob/user, get_new_player = FALSE)
var/mob/dead/observer/chosen_ghost
- for(var/mob/dead/observer/ghost in GLOB.player_list) // We put them back in their body
- if(ghost.mind && ghost.mind.current == M && ghost.client)
- chosen_ghost = ghost
- break
+ if(!get_new_player)
+ for(var/mob/dead/observer/ghost in GLOB.player_list) // We put them back in their body
+ if(ghost.mind && ghost.mind.current == M && ghost.client)
+ chosen_ghost = ghost
+ break
if(!chosen_ghost) // Failing that, we grab a ghost
var/list/consenting_candidates
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index ffa434e7f2d..d0674e34049 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -225,5 +225,6 @@
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
message_admins("[key_name_admin(usr)] emagged [key_name_admin(R)] using robotic console!")
R.emagged = TRUE
+ R.module.rebuild_modules()
to_chat(R, "Failsafe protocols overriden. New tools available.")
. = TRUE
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 59d839018bb..88dc39e568c 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -195,11 +195,6 @@
/obj/machinery/door/window/narsie_act()
color = NARSIE_WINDOW_COLOUR
-/obj/machinery/door/window/ratvar_act()
- var/obj/machinery/door/window/clockwork/C = new(loc, dir)
- C.name = name
- qdel(src)
-
/obj/machinery/door/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature > T0C + (reinf ? 1600 : 800))
@@ -358,9 +353,6 @@
if(prob(80/severity))
open()
-/obj/machinery/door/window/clockwork/ratvar_act()
- obj_integrity = max_integrity
-
/obj/machinery/door/window/clockwork/hasPower()
return TRUE //yup that's power all right
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 28a2006e0aa..138708f4f81 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -288,6 +288,9 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
if(!user.unEquip(src, silent = TRUE))
return 0
+ if(flags & ABSTRACT)
+ return 0
+
else
if(isliving(loc))
return 0
diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm
index 788de290b19..f10c88e0907 100644
--- a/code/game/objects/items/cardboard_cutouts.dm
+++ b/code/game/objects/items/cardboard_cutouts.dm
@@ -120,10 +120,6 @@
name = "Unknown"
desc = "A cardboard cutout of a cultist."
icon_state = "cutout_cultist"
- //if("Clockwork Cultist")
- // name = "[random_name(pick(MALE,FEMALE))]"
- // desc = "A cardboard cutout of a servant of Ratvar."
- // icon_state = "cutout_servant"
if("Revolutionary")
name = "Unknown"
desc = "A cardboard cutout of a revolutionary."
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 28e63041cd2..5d447675c49 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -132,8 +132,7 @@ REAGENT SCANNER
var/BR = H.getBruteLoss() > 50 ? "[H.getBruteLoss()]" : H.getBruteLoss()
var/status = "Dead" // Dead by default to make it simpler
- var/mob/dead/observer/ghost = H.get_ghost(TRUE)
- var/DNR = (ghost && !ghost.can_reenter_corpse)
+ var/DNR = !H.ghost_can_reenter() // If the ghost can't reenter
if(H.stat == DEAD)
if(DNR)
status = "Dead \[DNR]"
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 84c59310418..99dee4e4961 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -117,10 +117,6 @@ GLOBAL_LIST_INIT(metal_recipes, list(
/obj/item/stack/sheet/metal/fifty
amount = 50
-/obj/item/stack/sheet/metal/ratvar_act()
- new /obj/item/stack/tile/brass(loc, amount)
- qdel(src)
-
/obj/item/stack/sheet/metal/narsie_act()
new /obj/item/stack/sheet/runed_metal(loc, amount)
qdel(src)
@@ -378,10 +374,6 @@ GLOBAL_LIST_INIT(cult_recipes, list ( \
. = ..()
icon_state = SSticker.cultdat?.runed_metal_icon_state
-/obj/item/stack/sheet/runed_metal/ratvar_act()
- new /obj/item/stack/tile/brass(loc, amount)
- qdel(src)
-
/obj/item/stack/sheet/runed_metal/attack_self(mob/living/user)
if(!iscultist(user))
to_chat(user, "Only one with forbidden knowledge could hope to work this metal...")
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index 92d13337766..c12809ca160 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -428,6 +428,8 @@
if(iswallturf(A))
if(istype(A, /turf/simulated/wall/r_wall) && !canRwall)
return FALSE
+ if(istype(A, /turf/simulated/wall/indestructible))
+ return FALSE
if(checkResource(5, user))
to_chat(user, "Deconstructing Wall...")
playsound(loc, 'sound/machines/click.ogg', 50, 1)
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index a7d4bc4be3b..0df5817f598 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -206,11 +206,6 @@
return TRUE
..()
-/obj/item/melee/baton/cyborg_recharge(coeff, emagged)
- if(cell)
- cell.charge = cell.maxcharge
- update_icon()
-
//Makeshift stun baton. Replacement for stun gloves.
/obj/item/melee/baton/cattleprod
name = "stunprod"
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index 8217a86e505..c52338b9e7d 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -51,10 +51,6 @@
if(0 to 40)
return "It looks heavily damaged."
-/obj/structure/falsewall/ratvar_act()
- new /obj/structure/falsewall/brass(loc)
- qdel(src)
-
/obj/structure/falsewall/Destroy()
density = 0
air_update_turf(1)
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 68025f98fce..c9f78cf01d0 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -55,13 +55,6 @@
if(!anchored)
. += "The anchoring screws are unscrewed. The rods look like they could be cut through."
-/obj/structure/grille/ratvar_act()
- if(broken)
- new /obj/structure/grille/ratvar/broken(loc)
- else
- new /obj/structure/grille/ratvar(loc)
- qdel(src)
-
/obj/structure/grille/Bumped(atom/user)
if(ismob(user))
if(!(shockcooldown <= world.time))
@@ -289,9 +282,6 @@
color = "#960000"
animate(src, color = previouscolor, time = 8)
-/obj/structure/grille/ratvar/ratvar_act()
- return
-
/obj/structure/grille/ratvar/broken
icon_state = "brokenratvargrille"
density = FALSE
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index d84c1f39728..3561bd1f239 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -61,18 +61,6 @@
/obj/structure/lattice/clockwork/Initialize(mapload)
. = ..()
- ratvar_act()
-
-/obj/structure/lattice/clockwork/ratvar_act()
- if((x + y) % 2 != 0)
- icon = 'icons/obj/smooth_structures/lattice_clockwork_large.dmi'
- pixel_x = -9
- pixel_y = -9
- else
- icon = 'icons/obj/smooth_structures/lattice_clockwork.dmi'
- pixel_x = 0
- pixel_y = 0
- return TRUE
/obj/structure/lattice/catwalk
name = "catwalk"
@@ -109,18 +97,6 @@
/obj/structure/lattice/catwalk/clockwork/Initialize(mapload)
. = ..()
- ratvar_act()
if(!mapload)
new /obj/effect/temp_visual/ratvar/floor/catwalk(loc)
new /obj/effect/temp_visual/ratvar/beam/catwalk(loc)
-
-/obj/structure/lattice/catwalk/clockwork/ratvar_act()
- if((x + y) % 2 != 0)
- icon = 'icons/obj/smooth_structures/catwalk_clockwork_large.dmi'
- pixel_x = -9
- pixel_y = -9
- else
- icon = 'icons/obj/smooth_structures/catwalk_clockwork.dmi'
- pixel_x = 0
- pixel_y = 0
- return TRUE
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 0387f73a456..9b8eb06e216 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -24,11 +24,6 @@
W.setDir(dir)
qdel(src)
-/obj/structure/chair/ratvar_act()
- var/obj/structure/chair/brass/B = new(get_turf(src))
- B.setDir(dir)
- qdel(src)
-
/obj/structure/chair/Move(atom/newloc, direct)
..()
handle_rotation()
@@ -441,9 +436,6 @@
if(turns >= 8)
STOP_PROCESSING(SSfastprocess, src)
-/obj/structure/chair/brass/ratvar_act()
- return
-
/obj/structure/chair/brass/AltClick(mob/living/user)
turns = 0
if(!istype(user) || user.incapacitated() || !in_range(src, user))
diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm
index 575f666848a..966c3f313b4 100644
--- a/code/game/objects/structures/table_frames.dm
+++ b/code/game/objects/structures/table_frames.dm
@@ -91,10 +91,6 @@
new /obj/structure/table_frame/wood(loc)
qdel(src)
-/obj/structure/table_frame/ratvar_act()
- new /obj/structure/table_frame/brass(loc)
- qdel(src)
-
/*
* Wooden Frames
*/
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 5bce42875fe..28e61e90e58 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -84,10 +84,6 @@
new /obj/structure/table/wood(loc)
qdel(src)
-/obj/structure/table/ratvar_act()
- new /obj/structure/table/reinforced/brass(loc)
- qdel(src)
-
/obj/structure/table/do_climb(mob/living/user)
. = ..()
item_placed(user)
@@ -571,9 +567,6 @@
color = "#960000"
animate(src, color = previouscolor, time = 8)
-/obj/structure/table/reinforced/brass/ratvar_act()
- obj_integrity = max_integrity
-
/obj/structure/table/tray
name = "surgical tray"
desc = "A small metal tray with wheels."
@@ -637,9 +630,6 @@
/obj/structure/table/tray/narsie_act()
return 0
-/obj/structure/table/tray/ratvar_act()
- return 0
-
/*
* Racks
*/
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index b98c8b7c4c4..0643db75416 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -72,13 +72,6 @@
/obj/structure/window/narsie_act()
color = NARSIE_WINDOW_COLOUR
-/obj/structure/window/ratvar_act()
- if(!fulltile)
- new/obj/structure/window/reinforced/clockwork(get_turf(src), dir)
- else
- new/obj/structure/window/reinforced/clockwork/fulltile(get_turf(src))
- qdel(src)
-
/obj/structure/window/rpd_act()
return
@@ -727,10 +720,6 @@
made_glow = TRUE
..()
-/obj/structure/window/reinforced/clockwork/ratvar_act()
- obj_integrity = max_integrity
- update_nearby_icons()
-
/obj/structure/window/reinforced/clockwork/narsie_act()
take_damage(rand(25, 75), BRUTE)
if(src)
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index c9fbd4df113..24fcba648f2 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -231,11 +231,6 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
if(prob(20))
ChangeTurf(/turf/simulated/floor/engine/cult)
-/turf/simulated/floor/ratvar_act(force, ignore_mobs)
- . = ..()
- if(.)
- ChangeTurf(/turf/simulated/floor/clockwork)
-
/turf/simulated/floor/acid_melt()
ChangeTurf(baseturf)
diff --git a/code/game/turfs/simulated/floor/indestructible.dm b/code/game/turfs/simulated/floor/indestructible.dm
index cd7abaeb188..67e3f3f5ecd 100644
--- a/code/game/turfs/simulated/floor/indestructible.dm
+++ b/code/game/turfs/simulated/floor/indestructible.dm
@@ -15,9 +15,6 @@
/turf/simulated/floor/indestructible/narsie_act()
return
-/turf/simulated/floor/indestructible/ratvar_act(force, ignore_mobs)
- return
-
/turf/simulated/floor/indestructible/burn_down()
return
diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm
index 6264fb366ab..4c4e3e44a15 100644
--- a/code/game/turfs/simulated/floor/light_floor.dm
+++ b/code/game/turfs/simulated/floor/light_floor.dm
@@ -80,3 +80,8 @@
/turf/simulated/floor/light/extinguish_light()
toggle_light(FALSE)
visible_message("[src] flickers and falls dark.")
+
+/turf/simulated/floor/light/clean(floor_only)
+ var/color_save = color
+ ..()
+ color = color_save
diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm
index 2876378eb06..96b79588793 100644
--- a/code/game/turfs/simulated/floor/misc_floor.dm
+++ b/code/game/turfs/simulated/floor/misc_floor.dm
@@ -176,11 +176,6 @@
QDEL_NULL(realappearence)
return ..()
-/turf/simulated/floor/clockwork/ReplaceWithLattice()
- . = ..()
- for(var/obj/structure/lattice/L in src)
- L.ratvar_act()
-
/turf/simulated/floor/clockwork/crowbar_act(mob/user, obj/item/I)
. = TRUE
if(!I.tool_use_check(user, 0))
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 94d95c2af86..d0805cf5099 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -187,13 +187,6 @@
/turf/simulated/floor/engine/cult/narsie_act()
return
-/turf/simulated/floor/engine/cult/ratvar_act()
- . = ..()
- if(istype(src, /turf/simulated/floor/engine/cult)) //if we haven't changed type
- var/previouscolor = color
- color = "#FAE48C"
- animate(src, color = previouscolor, time = 8)
-
//air filled floors; used in atmos pressure chambers
/turf/simulated/floor/engine/n20
diff --git a/code/game/turfs/simulated/walls_indestructible.dm b/code/game/turfs/simulated/walls_indestructible.dm
index 56feb811745..37208cd0b81 100644
--- a/code/game/turfs/simulated/walls_indestructible.dm
+++ b/code/game/turfs/simulated/walls_indestructible.dm
@@ -27,9 +27,6 @@
/turf/simulated/wall/indestructible/narsie_act()
return
-/turf/simulated/wall/indestructible/ratvar_act(force, ignore_mobs)
- return
-
/turf/simulated/wall/indestructible/burn_down()
return
diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm
index e32fa627297..a841f06665e 100644
--- a/code/game/turfs/simulated/walls_misc.dm
+++ b/code/game/turfs/simulated/walls_misc.dm
@@ -69,11 +69,6 @@
QDEL_NULL(realappearance)
return ..()
-/turf/simulated/wall/clockwork/ReplaceWithLattice()
- ..()
- for(var/obj/structure/lattice/L in src)
- L.ratvar_act()
-
/turf/simulated/wall/clockwork/narsie_act()
..()
if(istype(src, /turf/simulated/wall/clockwork)) //if we haven't changed type
@@ -122,19 +117,3 @@
to_chat(M.occupant, "The wall's intense heat completely reflects your [M.name]'s attack!")
M.take_damage(20, BURN)
-/turf/simulated/wall/clockwork/proc/turn_up_the_heat()
- if(!heated)
- name = "superheated [name]"
- visible_message("[src] sizzles with heat!")
- playsound(src, 'sound/machines/fryer/deep_fryer_emerge.ogg', 50, TRUE)
- heated = TRUE
- hardness = -100 //Lower numbers are tougher, so this makes the wall essentially impervious to smashing
- slicing_duration = 150
- animate(realappearance, color = "#FFC3C3", time = 5)
- else
- name = initial(name)
- visible_message("[src] cools down.")
- heated = FALSE
- hardness = initial(hardness)
- slicing_duration = initial(slicing_duration)
- animate(realappearance, color = initial(realappearance.color), time = 25)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 4678bd94ce4..938e2f8a851 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -179,7 +179,7 @@
// override for space turfs, since they should never hide anything
/turf/space/levelupdate()
for(var/obj/O in src)
- if(O.level == 1)
+ if(O.level == 1 && O.initialized) // Only do this if the object has initialized
O.hide(FALSE)
// Removes all signs of lattice on the pos of the turf -Donkieyo
@@ -330,6 +330,20 @@
/turf/proc/Bless()
flags |= NOJAUNT
+/turf/proc/clean(floor_only)
+ for(var/obj/effect/decal/cleanable/C in src)
+ var/obj/effect/decal/cleanable/blood/B = C
+ if(istype(B) && B.off_floor)
+ floor_only = FALSE
+ else
+ qdel(C)
+ color = initial(color)
+ if(floor_only)
+ clean_blood()
+
+ for(var/mob/living/simple_animal/slime/M in src)
+ M.adjustToxLoss(rand(5, 10))
+
// Defined here to avoid runtimes
/turf/proc/MakeDry(wet_setting = TURF_WET_WATER)
return
@@ -508,15 +522,6 @@
/turf/proc/can_lay_cable()
return can_have_cabling() & !intact
-/turf/ratvar_act(force, ignore_mobs, probability = 40)
- . = (prob(probability) || force)
- for(var/I in src)
- var/atom/A = I
- if(ignore_mobs && ismob(A))
- continue
- if(ismob(A) || .)
- A.ratvar_act()
-
/turf/proc/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = icon
underlay_appearance.icon_state = icon_state
diff --git a/code/game/world.dm b/code/game/world.dm
index 6c8648a2895..60789ed42f2 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -240,6 +240,7 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
GLOB.tgui_log = "[GLOB.log_directory]/tgui.log"
GLOB.http_log = "[GLOB.log_directory]/http.log"
GLOB.sql_log = "[GLOB.log_directory]/sql.log"
+ GLOB.chat_debug_log = "[GLOB.log_directory]/chat_debug.log"
start_log(GLOB.world_game_log)
start_log(GLOB.world_href_log)
start_log(GLOB.world_runtime_log)
@@ -247,6 +248,7 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
start_log(GLOB.tgui_log)
start_log(GLOB.http_log)
start_log(GLOB.sql_log)
+ start_log(GLOB.chat_debug_log)
// This log follows a special format and this path should NOT be used for anything else
GLOB.runtime_summary_log = "data/logs/runtime_summary.log"
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index b1d64f9abf9..326ed0a5ce3 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -679,7 +679,7 @@
if(query_find_link.NextRow())
if(query_find_link.item[1])
if(!fromban)
- to_chat(src, "Your forum account is already set. (" + query_find_link.item[1] + ")")
+ to_chat(src, "Your forum account is already set. ([query_find_link.item[1]])")
qdel(query_find_link)
return
qdel(query_find_link)
diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm
index 0c58119a6c9..0bf1d67bf71 100644
--- a/code/modules/mining/lavaland/loot/colossus_loot.dm
+++ b/code/modules/mining/lavaland/loot/colossus_loot.dm
@@ -156,7 +156,7 @@
var/atom/Picked = pick(NewFlora)
new Picked(O)
continue
- if(iswallturf(T) && NewTerrainWalls)
+ if(iswallturf(T) && NewTerrainWalls && !istype(T, /turf/simulated/wall/indestructible))
T.ChangeTurf(NewTerrainWalls)
continue
if(istype(Stuff, /obj/structure/chair) && NewTerrainChairs)
@@ -232,9 +232,21 @@
/obj/machinery/anomalous_crystal/helpers/attack_ghost(mob/dead/observer/user)
..()
if(ready_to_deploy)
+ if(!istype(user)) // No revs allowed
+ return
+ if(cannotPossess(user))
+ to_chat(user, "Upon using the antagHUD you forfeited the ability to join the round.")
+ return
+ if(!user.can_reenter_corpse)
+ to_chat(user, "You have forfeited the right to respawn.")
+ return
var/be_helper = alert("Become a Lightgeist? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_helper == "No")
return
+ if(!loc || QDELETED(src) || QDELETED(user))
+ if(user)
+ to_chat(user, "[src] is no longer usable!")
+ return
var/mob/living/simple_animal/hostile/lightgeist/W = new /mob/living/simple_animal/hostile/lightgeist(get_turf(loc))
W.key = user.key
diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm
index 00f70a7031a..7ad45bd58c0 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone.dm
@@ -239,7 +239,7 @@
health = 35
stat = CONSCIOUS
return
- health = 35 - (getBruteLoss() + getFireLoss())
+ health = 35 - (getBruteLoss() + getFireLoss() + getOxyLoss())
update_stat("updatehealth([reason])")
/mob/living/silicon/robot/drone/death(gibbed)
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_console.dm b/code/modules/mob/living/silicon/robot/drone/drone_console.dm
index 02924fbbbda..2c09800c1d6 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_console.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_console.dm
@@ -114,7 +114,8 @@
var/mob/living/silicon/robot/drone/D = locateUID(params["uid"])
if(D)
to_chat(usr, "You issue a kill command for the unfortunate drone.")
- message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
+ if(D != usr) // Don't need to bug admins about a suicide
+ message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
log_game("[key_name(usr)] issued kill order for [key_name(D)] from control console.")
D.shut_down()
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 2dfc5ca2376..4a649dfe7e0 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -562,7 +562,9 @@
if(held_item)
to_chat(src, "You are already holding [held_item]")
return 1
-
+ if(istype(loc, /obj/machinery/disposal) || istype(loc, /obj/structure/disposalholder))
+ to_chat(src, "You are inside a disposal chute!")
+ return 1
for(var/obj/item/I in view(1, src))
//Make sure we're not already holding it and it's small enough
if(I.loc != src && I.w_class <= WEIGHT_CLASS_SMALL)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index df8c8380307..b20fa5fb888 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -509,6 +509,17 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
alert_overlay.plane = FLOAT_PLANE
A.overlays += alert_overlay
+/**
+ * Checks if a mob's ghost can reenter their body or not. Used to check for DNR or AntagHUD.
+ *
+ * Returns FALSE if there is a ghost, and it can't reenter the body. Returns TRUE otherwise.
+ */
+/mob/proc/ghost_can_reenter()
+ var/mob/dead/observer/ghost = get_ghost(TRUE)
+ if(ghost && !ghost.can_reenter_corpse)
+ return FALSE
+ return TRUE
+
/mob/proc/switch_to_camera(obj/machinery/camera/C)
if(!C.can_use() || incapacitated() || (get_dist(C, src) > 1 || machine != src || !has_vision()))
return FALSE
diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm
index b6074ca3936..96f5a766778 100644
--- a/code/modules/reagents/chemistry/reagents/medicine.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine.dm
@@ -774,8 +774,7 @@
if(M.getBruteLoss() + M.getFireLoss() + M.getCloneLoss() >= 150)
M.delayed_gib()
return
- var/mob/dead/observer/ghost = M.get_ghost(TRUE)
- if(ghost && !ghost.can_reenter_corpse) // DNR or AntagHUD
+ if(!M.ghost_can_reenter())
M.visible_message("[M] twitches slightly, but is otherwise unresponsive!")
return
diff --git a/code/modules/reagents/chemistry/reagents/water.dm b/code/modules/reagents/chemistry/reagents/water.dm
index 6be18db54a5..8084a990e3c 100644
--- a/code/modules/reagents/chemistry/reagents/water.dm
+++ b/code/modules/reagents/chemistry/reagents/water.dm
@@ -67,20 +67,7 @@
O.clean_blood()
/datum/reagent/space_cleaner/reaction_turf(turf/T, volume)
- if(volume >= 1)
- var/floor_only = TRUE
- for(var/obj/effect/decal/cleanable/C in T)
- var/obj/effect/decal/cleanable/blood/B = C
- if(istype(B) && B.off_floor)
- floor_only = FALSE
- else
- qdel(C)
- T.color = initial(T.color)
- if(floor_only)
- T.clean_blood()
-
- for(var/mob/living/simple_animal/slime/M in T)
- M.adjustToxLoss(rand(5, 10))
+ T.clean(volume >= 1)
/datum/reagent/space_cleaner/reaction_mob(mob/living/M, method=REAGENT_TOUCH, volume)
M.clean_blood()
diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm
index ab2843a4763..07c92cb8b0a 100755
--- a/code/modules/recycling/sortingmachinery.dm
+++ b/code/modules/recycling/sortingmachinery.dm
@@ -286,7 +286,7 @@
return
/obj/machinery/disposal/deliveryChute/Bumped(atom/movable/AM) //Go straight into the chute
- if(istype(AM, /obj/item/projectile)) return
+ if(istype(AM, /obj/item/projectile) || isAI(AM)) return
switch(dir)
if(NORTH)
if(AM.loc.y != src.loc.y+1) return
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index da21ae77d78..ffa8ac763de 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -285,16 +285,16 @@ won't update every console in existence) but it's more of a hassle to do. Also,
clear_wait_message()
SStgui.update_uis(src)
-/obj/machinery/computer/rdconsole/proc/start_destroyer()
+/obj/machinery/computer/rdconsole/proc/start_destroyer(mob/user)
if(!linked_destroy)
return
if(linked_destroy.busy)
- to_chat(usr, "[linked_destroy] is busy at the moment.")
+ to_chat(user, "[linked_destroy] is busy at the moment.")
return
if(!linked_destroy.loaded_item)
- to_chat(usr, "[linked_destroy] appears to be empty.")
+ to_chat(user, "[linked_destroy] appears to be empty.")
return
var/list/temp_tech = linked_destroy.ConvertReqString2List(linked_destroy.loaded_item.origin_tech)
@@ -313,7 +313,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
linked_destroy.busy = TRUE
add_wait_message("Processing and Updating Database...", DECONSTRUCT_DELAY)
flick("d_analyzer_process", linked_destroy)
- addtimer(CALLBACK(src, .proc/finish_destroyer, temp_tech), DECONSTRUCT_DELAY)
+ addtimer(CALLBACK(src, .proc/finish_destroyer, user, temp_tech), DECONSTRUCT_DELAY)
// Sends salvaged materials to a linked protolathe, if any.
/obj/machinery/computer/rdconsole/proc/send_mats()
@@ -329,14 +329,14 @@ won't update every console in existence) but it's more of a hassle to do. Also,
var/can_insert = min(space, salvageable, available)
linked_lathe.materials.insert_amount(can_insert, material)
-/obj/machinery/computer/rdconsole/proc/finish_destroyer(list/temp_tech)
+/obj/machinery/computer/rdconsole/proc/finish_destroyer(mob/user, list/temp_tech)
clear_wait_message()
if(!linked_destroy || !temp_tech)
return
if(!linked_destroy.hacked)
if(!linked_destroy.loaded_item)
- to_chat(usr, "[linked_destroy] appears to be empty.")
+ to_chat(user, "[linked_destroy] appears to be empty.")
else
for(var/T in temp_tech)
files.UpdateTech(T, temp_tech[T])
diff --git a/code/modules/telesci/gps.dm b/code/modules/telesci/gps.dm
index 94639805985..ddb43a387c6 100644
--- a/code/modules/telesci/gps.dm
+++ b/code/modules/telesci/gps.dm
@@ -96,7 +96,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
for(var/g in GLOB.GPS_list)
var/obj/item/gps/G = g
var/turf/GT = get_turf(G)
- if(!G.tracking || G == src)
+ if(isnull(GT) || !G.tracking || G == src)
continue
if((G.local || same_z) && (GT.z != T.z))
continue
diff --git a/goon/code/datums/browserOutput.dm b/goon/code/datums/browserOutput.dm
index 431aa3d90bd..786b09e2da2 100644
--- a/goon/code/datums/browserOutput.dm
+++ b/goon/code/datums/browserOutput.dm
@@ -20,7 +20,6 @@ var/list/chatResources = list(
#define MAX_COOKIE_LENGTH 5
/var/savefile/iconCache = new /savefile("data/iconCache.sav")
-/var/chatDebug = file("data/chatDebug.log")
/datum/chatOutput
var/client/owner = null
@@ -92,7 +91,10 @@ var/list/chatResources = list(
data = doneLoading(arglist(params))
if("debug")
- data = debug(arglist(params))
+ if(!length(params))
+ return
+ var/error = params[1]
+ log_chat_debug("Client: [owner.key || owner] triggered JS error: [error][GLOB.log_end]")
if("ping")
data = ping(arglist(params))
@@ -201,10 +203,6 @@ var/list/chatResources = list(
/datum/chatOutput/proc/ping()
return "pong"
-/datum/chatOutput/proc/debug(error)
- error = "\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client : [owner.key ? owner.key : owner] triggered JS error: [error]"
- chatDebug << error
-
/**
* Sends the lists of code phrases and responses to Goonchat for clientside highlighting
*
diff --git a/icons/am_engine.dmi b/icons/am_engine.dmi
deleted file mode 100644
index a2cd83cec24..00000000000
Binary files a/icons/am_engine.dmi and /dev/null differ
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index e915ba04139..eb888d9ce47 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/effects/genetics.dmi b/icons/effects/genetics.dmi
index e51ce35e3ce..bc011a351c4 100644
Binary files a/icons/effects/genetics.dmi and b/icons/effects/genetics.dmi differ
diff --git a/icons/effects/targeted.dmi b/icons/effects/targeted.dmi
index f2e03c7aacf..f0d4b95f64f 100644
Binary files a/icons/effects/targeted.dmi and b/icons/effects/targeted.dmi differ
diff --git a/icons/laptop.dmi b/icons/laptop.dmi
deleted file mode 100644
index 8b5a7f96ce3..00000000000
Binary files a/icons/laptop.dmi and /dev/null differ
diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi
index 00eac418e67..34288086aa4 100755
Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ
diff --git a/tools/mapmerge2/requirements.txt b/tools/mapmerge2/requirements.txt
index 7a6c3f1c94f..f46bdc31d5f 100644
--- a/tools/mapmerge2/requirements.txt
+++ b/tools/mapmerge2/requirements.txt
@@ -1,3 +1,3 @@
pygit2==1.0.1
bidict==0.13.1
-Pillow==8.1.1
+Pillow==8.2.0