diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm
index 7451c42cab..cc501b5289 100644
--- a/code/__DEFINES/clockcult.dm
+++ b/code/__DEFINES/clockcult.dm
@@ -83,9 +83,9 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define RATVARIAN_SPEAR_COOLDOWN 300 //The cooldown period between summoning another Ratvarian spear
-#define MARAUDER_SCRIPTURE_SCALING_THRESHOLD 200 //The amount of deciseconds that must pass before marauder scripture will not gain a recital penalty
+#define MARAUDER_SCRIPTURE_SCALING_THRESHOLD 600 //The amount of deciseconds that must pass before marauder scripture will not gain a recital penalty
-#define MARAUDER_SCRIPTURE_SCALING_TIME 50 //The amount of extra deciseconds tacked on to the marauder scripture recital time per recent marauder
+#define MARAUDER_SCRIPTURE_SCALING_TIME 20 //The amount of extra deciseconds tacked on to the marauder scripture recital time per recent marauder
#define MARAUDER_SCRIPTURE_SCALING_MAX 300 //The maximum extra time applied to the marauder scripture
diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index 2e1524ebac..b481ba7ddd 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -28,6 +28,8 @@
#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
+#define STATUS_EFFECT_FLESHMEND /datum/status_effect/fleshmend //Very fast healing; suppressed by fire, and heals less fire damage
+
/////////////
// DEBUFFS //
/////////////
diff --git a/code/datums/martial.dm b/code/datums/martial.dm
index 146959d5ab..f594f95429 100644
--- a/code/datums/martial.dm
+++ b/code/datums/martial.dm
@@ -76,6 +76,8 @@
return 1
/datum/martial_art/proc/teach(mob/living/carbon/human/H,make_temporary=0)
+ if(!istype(H) || !H.mind)
+ return FALSE
if(H.mind.martial_art)
if(make_temporary)
if(!H.mind.martial_art.allow_temp_override)
@@ -98,7 +100,7 @@
base = M
/datum/martial_art/proc/remove(mob/living/carbon/human/H)
- if(H.mind.martial_art != src)
+ if(!istype(H) || !H.mind || H.mind.martial_art != src)
return
on_remove(H)
if(base)
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index ec4b81acbe..9179b9bea4 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -412,3 +412,27 @@
/datum/status_effect/sword_spin/on_remove()
owner.visible_message("[owner]'s inhuman strength dissipates and the sword's runes grow cold!")
+
+
+//Used by changelings to rapidly heal
+//Heals 10 brute and oxygen damage every second, and 5 fire
+//Being on fire will suppress this healing
+/datum/status_effect/fleshmend
+ id = "fleshmend"
+ duration = 100
+ alert_type = /obj/screen/alert/status_effect/fleshmend
+
+/datum/status_effect/fleshmend/tick()
+ if(owner.on_fire)
+ linked_alert.icon_state = "fleshmend_fire"
+ return
+ else
+ linked_alert.icon_state = "fleshmend"
+ owner.adjustBruteLoss(-10, FALSE)
+ owner.adjustFireLoss(-5, FALSE)
+ owner.adjustOxyLoss(-10)
+
+/obj/screen/alert/status_effect/fleshmend
+ name = "Fleshmend"
+ desc = "Our wounds are rapidly healing. This effect is prevented if we are on fire."
+ icon_state = "fleshmend"
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index dd9d4a8634..df6a787d60 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -1,52 +1,19 @@
-/obj/effect/proc_holder/changeling/fleshmend
- name = "Fleshmend"
- desc = "Our flesh rapidly regenerates, healing our burns, bruises and shortness of breath. Effectiveness decreases with quick, repeated use."
- helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious. Does not regrow limbs or restore lost blood."
- chemical_cost = 20
- dna_cost = 2
- req_stat = UNCONSCIOUS
- var/recent_uses = 1 //The factor of which the healing should be divided by
- var/healing_ticks = 10
- // The ideal total healing amount,
- // divided by healing_ticks to get heal/tick
- var/total_healing = 100
-
-/obj/effect/proc_holder/changeling/fleshmend/Initialize()
- . = ..()
- START_PROCESSING(SSobj, src)
-
-/obj/effect/proc_holder/changeling/fleshmend/Destroy()
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-/obj/effect/proc_holder/changeling/fleshmend/process()
- if(recent_uses > 1)
- recent_uses = max(1, recent_uses - (1 / healing_ticks))
-
-//Starts healing you every second for 10 seconds.
-//Can be used whilst unconscious.
-/obj/effect/proc_holder/changeling/fleshmend/sting_action(mob/living/user)
- to_chat(user, "We begin to heal rapidly.")
- if(recent_uses > 1)
- to_chat(user, "Our healing's effectiveness is reduced \
- by quick repeated use!")
-
- recent_uses++
- INVOKE_ASYNC(src, .proc/fleshmend, user)
- return TRUE
-
-/obj/effect/proc_holder/changeling/fleshmend/proc/fleshmend(mob/living/user)
-
- // The healing itself - doesn't heal toxin damage
- // (that's anatomic panacea) and the effectiveness decreases with
- // each use in a short timespan
- for(var/i in 1 to healing_ticks)
- if(user)
- var/healpertick = -(total_healing / healing_ticks)
- user.adjustBruteLoss(healpertick / recent_uses, 0)
- user.adjustOxyLoss(healpertick / recent_uses, 0)
- user.adjustFireLoss(healpertick / recent_uses, 0)
- user.updatehealth()
- else
- break
- sleep(10)
+/obj/effect/proc_holder/changeling/fleshmend
+ name = "Fleshmend"
+ desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath. Functions while unconscious."
+ helptext = "If we are on fire, the healing effect will not function. Does not regrow limbs or restore lost blood."
+ chemical_cost = 20
+ dna_cost = 2
+ req_stat = UNCONSCIOUS
+
+//Starts healing you every second for 10 seconds.
+//Can be used whilst unconscious.
+/obj/effect/proc_holder/changeling/fleshmend/sting_action(mob/living/user)
+ if(user.has_status_effect(STATUS_EFFECT_FLESHMEND))
+ to_chat(user, "We are already fleshmending!")
+ return
+ to_chat(user, "We begin to heal rapidly.")
+ user.apply_status_effect(STATUS_EFFECT_FLESHMEND)
+ return TRUE
+
+//Check buffs.dm for the fleshmend status effect code
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
index da1f5965bd..c06bb5395e 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
@@ -73,8 +73,8 @@
name = "Clockwork Marauder"
desc = "Creates a shell for a clockwork marauder, a balanced frontline construct that can deflect projectiles with its shield."
invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal.")
- channel_time = 50
- power_cost = 1000
+ channel_time = 80
+ power_cost = 8000
creator_message = "Your slab disgorges several chunks of replicant alloy that form into a suit of thrumming armor."
usage_tip = "Reciting this scripture multiple times in a short period will cause it to take longer!"
tier = SCRIPTURE_APPLICATION
@@ -94,10 +94,13 @@
var/human_servants = 0
for(var/V in SSticker.mode.servants_of_ratvar)
var/datum/mind/M = V
- if(ishuman(M.current))
+ var/mob/living/L = M.current
+ if(ishuman(L) && L.stat != DEAD)
human_servants++
construct_limit = human_servants / 4 //1 per 4 human servants, and a maximum of 3 marauders
- construct_limit = CLAMP(construct_limit, 1, 3)
+ construct_limit = CLAMP(construct_limit - recent_marauders, 1, 3)
+ if(recent_marauders)
+ to_chat(invoker, "The Hierophant Network needs [MARAUDER_SCRIPTURE_SCALING_THRESHOLD / 10] seconds to recover from marauder summoning; recent summoning has limited the number of available marauders by [recent_marauders]!")
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/pre_recital()
channel_time = initial(channel_time)
diff --git a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm
index 2fa682ff5c..ef035234d0 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm
@@ -35,6 +35,13 @@
else
nomination(user)
+/obj/structure/destructible/clockwork/eminence_spire/attack_drone(mob/living/simple_animal/drone/user)
+ if(!is_servant_of_ratvar(user))
+ ..()
+ else
+ to_chat(user, "You feel the omniscient gaze turn into a puzzled frown. Perhaps you should just stick to building.")
+ return
+
/obj/structure/destructible/clockwork/eminence_spire/attack_ghost(mob/user)
if(!IsAdminGhost(user))
return
diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm
index 6156ee1d86..ba8be95065 100644
--- a/code/game/machinery/PDApainter.dm
+++ b/code/game/machinery/PDApainter.dm
@@ -34,7 +34,9 @@
/obj/item/device/pda/ai,
/obj/item/device/pda/heads,
/obj/item/device/pda/clear,
- /obj/item/device/pda/syndicate)
+ /obj/item/device/pda/syndicate,
+ /obj/item/device/pda/chameleon,
+ /obj/item/device/pda/chameleon/broken)
for(var/P in typesof(/obj/item/device/pda) - blocked)
var/obj/item/device/pda/D = new P
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 7554bb00ae..c425bbf8f4 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -170,8 +170,7 @@
if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff))
busy = TRUE
use_power(power)
- icon_state = "autolathe"
- flick("autolathe_n",src)
+ icon_state = "autolathe_n"
var/time = is_stack ? 32 : 32*coeff*multiplier
addtimer(CALLBACK(src, .proc/make_item, power, metal_cost, glass_cost, multiplier, coeff, is_stack), time)
@@ -207,7 +206,7 @@
for(var/mat in materials_used)
new_item.materials[mat] = materials_used[mat] / multiplier
new_item.autolathe_crafted(src)
-
+ icon_state = "autolathe"
busy = FALSE
updateDialog()
diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm
index 9f9791beec..74e640ae51 100644
--- a/code/game/machinery/computer/teleporter.dm
+++ b/code/game/machinery/computer/teleporter.dm
@@ -166,10 +166,10 @@
L[avoid_assoc_duplicate_keys(A.name, areaindex)] = R
for(var/obj/item/implant/tracking/I in GLOB.tracked_implants)
- if(!I.imp_in || !ismob(I.loc))
+ if(!I.imp_in || !isliving(I.loc))
continue
else
- var/mob/M = I.loc
+ var/mob/living/M = I.loc
if(M.stat == DEAD)
if(M.timeofdeath + 6000 < world.time)
continue
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 0fc957fdca..1362721e1d 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -194,6 +194,10 @@
keyslot = new /obj/item/device/encryptionkey/headset_com
keyslot2 = new /obj/item/device/encryptionkey/headset_cent
+/obj/item/device/radio/headset/headset_cent/empty
+ keyslot = null
+ keyslot2 = null
+
/obj/item/device/radio/headset/headset_cent/commander
keyslot = new /obj/item/device/encryptionkey/heads/captain
diff --git a/code/game/objects/items/implants/implant_clown.dm b/code/game/objects/items/implants/implant_clown.dm
index 18a22c1e60..ae1fef109d 100644
--- a/code/game/objects/items/implants/implant_clown.dm
+++ b/code/game/objects/items/implants/implant_clown.dm
@@ -14,7 +14,7 @@
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 0)
/obj/item/implanter/sad_trombone
- name = "implanter (sad_trombone)"
+ name = "implanter (sad trombone)"
imp_type = /obj/item/implant/sad_trombone
/obj/item/implantcase/sad_trombone
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 84cd51fe22..c1aa39ddb1 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -553,3 +553,16 @@
new /obj/item/reagent_containers/food/drinks/bottle/vodka/badminka(src)
new /obj/item/reagent_containers/syringe/stimulants(src)
new /obj/item/grenade/syndieminibomb(src)
+
+// For ClownOps.
+/obj/item/storage/backpack/duffelbag/clown/syndie
+ slowdown = 0
+ silent = TRUE
+
+/obj/item/storage/backpack/duffelbag/clown/syndie/PopulateContents()
+ new /obj/item/device/pda/clown(src)
+ new /obj/item/clothing/under/rank/clown(src)
+ new /obj/item/clothing/shoes/clown_shoes(src)
+ new /obj/item/clothing/mask/gas/clown_hat(src)
+ new /obj/item/bikehorn(src)
+ new /obj/item/implanter/sad_trombone(src)
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index fb44d094c7..7ce832acd3 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -308,3 +308,27 @@
/obj/item/storage/box/syndie_kit/imp_radio/PopulateContents()
new /obj/item/implanter/radio(src)
+
+/obj/item/storage/box/syndie_kit/centcom_costume/PopulateContents()
+ new /obj/item/clothing/under/rank/centcom_officer(src)
+ new /obj/item/clothing/shoes/sneakers/black(src)
+ new /obj/item/clothing/gloves/color/black(src)
+ new /obj/item/device/radio/headset/headset_cent/empty(src)
+ new /obj/item/clothing/glasses/sunglasses(src)
+ new /obj/item/storage/backpack/satchel(src)
+ new /obj/item/device/pda/heads(src)
+ new /obj/item/clipboard(src)
+
+/obj/item/storage/box/syndie_kit/chameleon/broken/PopulateContents()
+ new /obj/item/clothing/under/chameleon/broken(src)
+ new /obj/item/clothing/suit/chameleon/broken(src)
+ new /obj/item/clothing/gloves/chameleon/broken(src)
+ new /obj/item/clothing/shoes/chameleon/broken(src)
+ new /obj/item/clothing/glasses/chameleon/broken(src)
+ new /obj/item/clothing/head/chameleon/broken(src)
+ new /obj/item/clothing/mask/chameleon/broken(src)
+ new /obj/item/storage/backpack/chameleon/broken(src)
+ new /obj/item/device/radio/headset/chameleon/broken(src)
+ new /obj/item/stamp/chameleon/broken(src)
+ new /obj/item/device/pda/chameleon/broken(src)
+ // No chameleon laser, they can't randomise for //REASONS//
diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm
index c3022a7758..44c44281c6 100644
--- a/code/game/objects/items/teleportation.dm
+++ b/code/game/objects/items/teleportation.dm
@@ -84,10 +84,10 @@ Frequency:
src.temp += "Extranneous Signals:
"
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
- if (!W.imp_in || !ismob(W.loc))
+ if (!W.imp_in || !isliving(W.loc))
continue
else
- var/mob/M = W.loc
+ var/mob/living/M = W.loc
if (M.stat == DEAD)
if (M.timeofdeath + 6000 < world.time)
continue
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 5cdadb186c..415024d2e0 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -129,15 +129,24 @@
return
if(!M.buckled)
return
- var/matrix/m180 = matrix(M.transform)
- m180.Turn(180)
- animate(M, transform = m180, time = 3)
- M.pixel_y = M.get_standard_pixel_y_offset(180)
- M.adjustBruteLoss(30)
- src.visible_message(text("[M] falls free of [src]!"))
- unbuckle_mob(M,force=1)
- M.emote("scream")
- M.AdjustKnockdown(20)
+ release_mob(M)
+
+/obj/structure/kitchenspike/proc/release_mob(mob/living/M)
+ var/matrix/m180 = matrix(M.transform)
+ m180.Turn(180)
+ animate(M, transform = m180, time = 3)
+ M.pixel_y = M.get_standard_pixel_y_offset(180)
+ M.adjustBruteLoss(30)
+ src.visible_message(text("[M] falls free of [src]!"))
+ unbuckle_mob(M,force=1)
+ M.emote("scream")
+ M.AdjustKnockdown(20)
+
+/obj/structure/kitchenspike/Destroy()
+ if(has_buckled_mobs())
+ for(var/mob/living/L in buckled_mobs)
+ release_mob(L)
+ return ..()
/obj/structure/kitchenspike/deconstruct(disassembled = TRUE)
if(disassembled)
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index d282fb9aed..ac3718394d 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -153,13 +153,15 @@
select_look(owner)
return 1
-/datum/action/item_action/chameleon/change/proc/emp_randomise()
+/datum/action/item_action/chameleon/change/proc/emp_randomise(var/amount = EMP_RANDOMISE_TIME)
if(istype(target, /obj/item/gun/energy/laser/chameleon))
return //Please no crash!
START_PROCESSING(SSprocessing, src)
random_look(owner)
- emp_timer = world.time + EMP_RANDOMISE_TIME
+ var/new_value = world.time + amount
+ if(new_value > emp_timer)
+ emp_timer = new_value
/datum/action/item_action/chameleon/change/process()
if(world.time > emp_timer)
@@ -189,8 +191,8 @@
item_state = "engi_suit"
item_color = "engine"
-/obj/item/clothing/under/chameleon/New()
- ..()
+/obj/item/clothing/under/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/under
chameleon_action.chameleon_name = "Jumpsuit"
@@ -200,6 +202,10 @@
/obj/item/clothing/under/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/clothing/under/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/clothing/suit/chameleon
name = "armor"
desc = "A slim armored vest that protects against most types of damage."
@@ -211,8 +217,8 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/suit/chameleon/New()
- ..()
+/obj/item/clothing/suit/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/suit
chameleon_action.chameleon_name = "Suit"
@@ -222,6 +228,10 @@
/obj/item/clothing/suit/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/clothing/suit/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/clothing/glasses/chameleon
name = "Optical Meson Scanner"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition."
@@ -232,8 +242,8 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/glasses/chameleon/New()
- ..()
+/obj/item/clothing/glasses/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/glasses
chameleon_action.chameleon_name = "Glasses"
@@ -243,6 +253,10 @@
/obj/item/clothing/glasses/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/clothing/glasses/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/clothing/gloves/chameleon
desc = "These gloves will protect the wearer from electric shock."
name = "insulated gloves"
@@ -254,8 +268,8 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/gloves/chameleon/New()
- ..()
+/obj/item/clothing/gloves/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/gloves
chameleon_action.chameleon_name = "Gloves"
@@ -265,6 +279,10 @@
/obj/item/clothing/gloves/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/clothing/gloves/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/clothing/head/chameleon
name = "grey cap"
desc = "It's a baseball hat in a tasteful grey colour."
@@ -276,8 +294,8 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/head/chameleon/New()
- ..()
+/obj/item/clothing/head/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/head
chameleon_action.chameleon_name = "Hat"
@@ -287,6 +305,10 @@
/obj/item/clothing/head/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/clothing/head/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/clothing/head/chameleon/drone
// The camohat, I mean, holographic hat projection, is part of the
// drone itself.
@@ -294,8 +316,8 @@
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
// which means it offers no protection, it's just air and light
-/obj/item/clothing/head/chameleon/drone/New()
- ..()
+/obj/item/clothing/head/chameleon/drone/Initialize()
+ . = ..()
chameleon_action.random_look()
var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src)
togglehatmask_action.UpdateButtonIcon()
@@ -320,8 +342,8 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/mask/chameleon/New()
- ..()
+/obj/item/clothing/mask/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/mask
chameleon_action.chameleon_name = "Mask"
@@ -331,6 +353,10 @@
/obj/item/clothing/mask/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/clothing/mask/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/clothing/mask/chameleon/attack_self(mob/user)
vchange = !vchange
to_chat(user, "The voice changer is now [vchange ? "on" : "off"]!")
@@ -343,8 +369,8 @@
// Can drones use the voice changer part? Let's not find out.
vchange = 0
-/obj/item/clothing/mask/chameleon/drone/New()
- ..()
+/obj/item/clothing/mask/chameleon/drone/Initialize()
+ . = ..()
chameleon_action.random_look()
var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src)
togglehatmask_action.UpdateButtonIcon()
@@ -367,8 +393,8 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/shoes/chameleon/New()
- ..()
+/obj/item/clothing/shoes/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/shoes
chameleon_action.chameleon_name = "Shoes"
@@ -378,6 +404,10 @@
/obj/item/clothing/shoes/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/clothing/shoes/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/gun/energy/laser/chameleon
name = "practice laser gun"
desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice."
@@ -405,8 +435,6 @@
chameleon_action.chameleon_blacklist = typecacheof(/obj/item/gun/magic, ignore_root_path = FALSE)
chameleon_action.initialize_disguises()
-/obj/item/gun/energy/laser/chameleon/Initialize()
- . = ..()
projectile_copy_vars = list("name", "icon", "icon_state", "item_state", "speed", "color", "hitsound", "forcedodge", "impact_effect_type", "range", "suppressed", "hitsound_wall", "impact_effect_type", "pass_flags")
chameleon_projectile_vars = list("name" = "practice laser", "icon" = 'icons/obj/projectiles.dmi', "icon_state" = "laser")
gun_copy_vars = list("fire_sound", "burst_size", "fire_delay")
@@ -505,8 +533,8 @@
name = "backpack"
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/storage/backpack/chameleon/New()
- ..()
+/obj/item/storage/backpack/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/storage/backpack
chameleon_action.chameleon_name = "Backpack"
@@ -515,14 +543,18 @@
/obj/item/storage/backpack/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/storage/backpack/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/storage/belt/chameleon
name = "toolbelt"
desc = "Holds tools."
silent = 1
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/storage/belt/chameleon/New()
- ..()
+/obj/item/storage/belt/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/storage/belt
chameleon_action.chameleon_name = "Belt"
@@ -531,6 +563,10 @@
/obj/item/storage/belt/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/storage/belt/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/device/radio/headset/chameleon
name = "radio headset"
var/datum/action/item_action/chameleon/change/chameleon_action
@@ -545,12 +581,16 @@
/obj/item/device/radio/headset/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/device/radio/headset/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
/obj/item/device/pda/chameleon
name = "PDA"
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/device/pda/chameleon/New()
- ..()
+/obj/item/device/pda/chameleon/Initialize()
+ . = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/device/pda
chameleon_action.chameleon_name = "PDA"
@@ -560,3 +600,7 @@
/obj/item/device/pda/chameleon/emp_act(severity)
chameleon_action.emp_randomise()
+/obj/item/device/pda/chameleon/broken/Initialize()
+ . = ..()
+ chameleon_action.emp_randomise(INFINITY)
+
diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm
index 5ce41f838b..0daed12bce 100644
--- a/code/modules/integrated_electronics/subtypes/manipulation.dm
+++ b/code/modules/integrated_electronics/subtypes/manipulation.dm
@@ -292,9 +292,9 @@
/obj/item/integrated_circuit/manipulation/grabber
name = "grabber"
- desc = "A circuit with it's own inventory for tiny/small items, used to grab and store things."
+ desc = "A circuit which is used to grab and store tiny to small objects within it's self-contained inventory."
icon_state = "grabber"
- extended_desc = "The circuit accepts a reference to thing to be grabbed. It can store up to 10 things. Modes: 1 for grab. 0 for eject the first thing. -1 for eject all."
+ extended_desc = "The circuit accepts a reference to an object to be grabbed and can store up to 10 objects. Modes: 1 to grab, 0 to eject the first object, and -1 to eject all objects."
w_class = WEIGHT_CLASS_SMALL
size = 3
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index d601fde492..976aae894f 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -3,6 +3,7 @@
pressure_resistance = 15
possible_a_intents = list(INTENT_HELP, INTENT_HARM)
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,GLAND_HUD)
+ has_limbs = 1
var/list/stomach_contents = list()
var/list/internal_organs = list() //List of /obj/item/organ in the mob. They don't go in the contents for some reason I don't want to know.
var/list/internal_organs_slot= list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
@@ -33,7 +34,6 @@
var/co2overloadtime = null
var/temperature_resistance = T0C+75
- has_limbs = 1
var/obj/item/reagent_containers/food/snacks/meat/slab/type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab
var/gib_type = /obj/effect/decal/cleanable/blood/gibs
@@ -57,3 +57,5 @@
var/obj/halitem
var/hal_screwyhud = SCREWYHUD_NONE
var/next_hallucination = 0
+ var/cpr_time = 1 //CPR cooldown.
+ var/damageoverlaytemp = 0
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 716373061d..7c4d12aaa1 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -2,6 +2,8 @@
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD,GLAND_HUD)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
pressure_resistance = 25
+ can_buckle = TRUE
+ buckle_lying = FALSE
//Hair colour and style
var/hair_color = "000"
var/hair_style = "Bald"
@@ -43,8 +45,7 @@
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
var/datum/personal_crafting/handcrafting
- can_buckle = TRUE
- buckle_lying = FALSE
var/creamed = FALSE //to use with creampie overlays
var/static/list/can_ride_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot))
+ var/lastpuke = 0
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 904e9b9c21..471d29a361 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -5,6 +5,10 @@
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD)
pressure_resistance = 10
+ var/resize = 1 //Badminnery resize
+ var/lastattacker = null
+ var/lastattackerckey = null
+
//Health and life related vars
var/maxHealth = 100 //Maximum health that should be possible.
var/health = 100 //A mob's health
@@ -17,10 +21,12 @@
var/cloneloss = 0 //Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims
var/staminaloss = 0 //Stamina damage, or exhaustion. You recover it slowly naturally, and are knocked down if it gets too high. Holodeck and hallucinations deal this.
+ var/confused = 0 //Makes the mob move in random directions.
var/hallucination = 0 //Directly affects how long a mob will hallucinate for
var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out.
+ var/timeofdeath = 0
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = FALSE //FALSE is off, INCORPOREAL_MOVE_BASIC is normal, INCORPOREAL_MOVE_SHADOW is for ninjas
@@ -69,7 +75,16 @@
var/blood_volume = 0 //how much blood the mob has
var/obj/effect/proc_holder/ranged_ability //Any ranged ability the mob has, as a click override
+ var/see_override = 0 //0 for no override, sets see_invisible = see_override in silicon & carbon life process via update_sight()
+
var/list/status_effects //a list of all status effects the mob has
+ var/druggy = 0
+
+ //Speech
+ var/stuttering = 0
+ var/slurring = 0
+ var/cultslurring = 0
+ var/derpspeech = 0
var/list/implants = null
@@ -83,3 +98,7 @@
var/registered_z
var/can_be_held = FALSE //whether this can be picked up and held.
+
+ var/radiation = 0 //If the mob is irradiated.
+ var/ventcrawl_layer = PIPING_LAYER_DEFAULT
+ var/losebreath = 0
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 178180eb3d..719d82ce6a 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -6,6 +6,7 @@
flags_1 = HEAR_1
hud_possible = list(ANTAG_HUD)
pressure_resistance = 8
+ mouse_drag_pointer = MOUSE_ACTIVE_POINTER
var/lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
var/datum/mind/mind
var/list/datum/action/actions = list()
@@ -22,10 +23,7 @@
*/
var/zone_selected = null
- var/damageoverlaytemp = 0
var/computer_id = null
- var/lastattacker = null
- var/lastattackerckey = null
var/list/logging = list(INDIVIDUAL_ATTACK_LOG, INDIVIDUAL_SAY_LOG, INDIVIDUAL_EMOTE_LOG, INDIVIDUAL_OOC_LOG)
var/obj/machinery/machine = null
@@ -33,25 +31,15 @@
var/notransform = null //Carbon
var/eye_blind = 0 //Carbon
var/eye_blurry = 0 //Carbon
- var/stuttering = 0 //Carbon
- var/slurring = 0 //Carbon
- var/cultslurring = 0 //Carbon
- var/derpspeech = 0 //Carbon
var/real_name = null
var/spacewalk = FALSE
- var/druggy = 0 //Carbon
- var/confused = 0 //Carbon
var/resting = 0 //Carbon
var/lying = 0
var/lying_prev = 0
var/canmove = 1
- var/lastpuke = 0
var/name_archive //For admin things like possession
- var/timeofdeath = 0//Living
- var/cpr_time = 1//Carbon
-
var/bodytemperature = BODYTEMP_NORMAL //310.15K / 98.6F
var/drowsyness = 0//Carbon
var/dizziness = 0//Carbon
@@ -60,7 +48,6 @@
var/satiety = 0//Carbon
var/overeatduration = 0 // How long this guy is overeating //Carbon
- var/losebreath = 0//Carbon
var/a_intent = INTENT_HELP//Living
var/list/possible_a_intents = null//Living
var/m_intent = MOVE_INTENT_RUN//Living
@@ -75,8 +62,6 @@
var/obj/item/storage/s_active = null//Carbon
- var/see_override = 0 //0 for no override, sets see_invisible = see_override in mob life process
-
var/datum/hud/hud_used = null
var/research_scanner = 0 //For research scanner equipped mobs. Enable to show research data when examining.
@@ -87,8 +72,6 @@
var/job = null//Living
- var/radiation = 0//Carbon
-
var/list/faction = list("neutral") //A list of factions that this mob is currently in, for hostile mob targetting, amongst other things
var/move_on_shuttle = 1 // Can move on the shuttle.
@@ -104,9 +87,6 @@
var/list/viruses = list() // list of all diseases in a mob
var/list/resistances = list()
- mouse_drag_pointer = MOUSE_ACTIVE_POINTER
-
-
var/status_flags = CANSTUN|CANKNOCKDOWN|CANUNCONSCIOUS|CANPUSH //bitflags defining which status effects can be inflicted (replaces canknockdown, canstun, etc)
var/digitalcamo = 0 // Can they be tracked by the AI?
@@ -121,12 +101,8 @@
var/turf/listed_turf = null //the current turf being examined in the stat panel
- var/resize = 1 //Badminnery resize
-
var/list/observers = null //The list of people observing this mob.
var/list/progressbars = null //for stacking do_after bars
var/list/mousemove_intercept_objects
-
- var/ventcrawl_layer = PIPING_LAYER_DEFAULT
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 0b770888ec..17742e9089 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -89,17 +89,17 @@
move_delay = world.time
var/oldloc = mob.loc
- if(mob.confused)
+ if(L.confused)
var/newdir = 0
- if(mob.confused > 40)
+ if(L.confused > 40)
newdir = pick(GLOB.alldirs)
- else if(prob(mob.confused * 1.5))
+ else if(prob(L.confused * 1.5))
newdir = angle2dir(dir2angle(direct) + pick(90, -90))
- else if(prob(mob.confused * 3))
+ else if(prob(L.confused * 3))
newdir = angle2dir(dir2angle(direct) + pick(45, -45))
if(newdir)
direct = newdir
- n = get_step(mob, direct)
+ n = get_step(L, direct)
. = ..()
diff --git a/code/modules/paperwork/stamps.dm b/code/modules/paperwork/stamps.dm
index 3c26382d6f..97038bd94c 100644
--- a/code/modules/paperwork/stamps.dm
+++ b/code/modules/paperwork/stamps.dm
@@ -1,111 +1,122 @@
-/obj/item/stamp
- name = "\improper GRANTED rubber stamp"
- desc = "A rubber stamp for stamping important documents."
- icon = 'icons/obj/bureaucracy.dmi'
- icon_state = "stamp-ok"
- item_state = "stamp"
- throwforce = 0
- w_class = WEIGHT_CLASS_TINY
- throw_speed = 3
- throw_range = 7
- materials = list(MAT_METAL=60)
- item_color = "cargo"
- pressure_resistance = 2
- attack_verb = list("stamped")
-
-/obj/item/stamp/suicide_act(mob/user)
- user.visible_message("[user] stamps 'VOID' on [user.p_their()] forehead, then promptly falls over, dead.")
- return (OXYLOSS)
-
-/obj/item/stamp/qm
- name = "quartermaster's rubber stamp"
- icon_state = "stamp-qm"
- item_color = "qm"
-
-/obj/item/stamp/law
- name = "law office's rubber stamp"
- icon_state = "stamp-law"
- item_color = "cargo"
-
-/obj/item/stamp/captain
- name = "captain's rubber stamp"
- icon_state = "stamp-cap"
- item_color = "captain"
-
-/obj/item/stamp/hop
- name = "head of personnel's rubber stamp"
- icon_state = "stamp-hop"
- item_color = "hop"
-
-/obj/item/stamp/hos
- name = "head of security's rubber stamp"
- icon_state = "stamp-hos"
- item_color = "hosred"
-
-/obj/item/stamp/ce
- name = "chief engineer's rubber stamp"
- icon_state = "stamp-ce"
- item_color = "chief"
-
-/obj/item/stamp/rd
- name = "research director's rubber stamp"
- icon_state = "stamp-rd"
- item_color = "director"
-
-/obj/item/stamp/cmo
- name = "chief medical officer's rubber stamp"
- icon_state = "stamp-cmo"
- item_color = "cmo"
-
-/obj/item/stamp/denied
- name = "\improper DENIED rubber stamp"
- icon_state = "stamp-deny"
- item_color = "redcoat"
-
-/obj/item/stamp/clown
- name = "clown's rubber stamp"
- icon_state = "stamp-clown"
- item_color = "clown"
-
-/obj/item/stamp/attack_paw(mob/user)
- return attack_hand(user)
-
-// Syndicate stamp to forge documents.
-
-/obj/item/stamp/chameleon
- actions_types = list(/datum/action/item_action/toggle)
-
- var/list/stamp_types
- var/list/stamp_names
-
-/obj/item/stamp/chameleon/Initialize()
- . = ..()
- stamp_types = typesof(/obj/item/stamp) - type // Get all stamp types except our own
-
- stamp_names = list()
- // Generate them into a list
- for(var/i in stamp_types)
- var/obj/item/stamp/stamp_type = i
- stamp_names += initial(stamp_type.name)
-
- stamp_names = sortList(stamp_names)
-
-/obj/item/stamp/chameleon/emp_act(severity)
- change_to(pick(stamp_types))
-
-/obj/item/stamp/chameleon/proc/change_to(obj/item/stamp/stamp_type)
- name = initial(stamp_type.name)
- icon_state = initial(stamp_type.icon_state)
- item_color = initial(stamp_type.item_color)
-
-/obj/item/stamp/chameleon/attack_self(mob/user)
- var/input_stamp = input(user, "Choose a stamp to disguise as.",
- "Choose a stamp.") as null|anything in stamp_names
-
- if(user && (src in user.contents) && input_stamp)
- var/obj/item/stamp/stamp_type
- for(var/i in stamp_types)
- stamp_type = i
- if(initial(stamp_type.name) == input_stamp)
- break
- change_to(stamp_type)
+/obj/item/stamp
+ name = "\improper GRANTED rubber stamp"
+ desc = "A rubber stamp for stamping important documents."
+ icon = 'icons/obj/bureaucracy.dmi'
+ icon_state = "stamp-ok"
+ item_state = "stamp"
+ throwforce = 0
+ w_class = WEIGHT_CLASS_TINY
+ throw_speed = 3
+ throw_range = 7
+ materials = list(MAT_METAL=60)
+ item_color = "cargo"
+ pressure_resistance = 2
+ attack_verb = list("stamped")
+
+/obj/item/stamp/suicide_act(mob/user)
+ user.visible_message("[user] stamps 'VOID' on [user.p_their()] forehead, then promptly falls over, dead.")
+ return (OXYLOSS)
+
+/obj/item/stamp/qm
+ name = "quartermaster's rubber stamp"
+ icon_state = "stamp-qm"
+ item_color = "qm"
+
+/obj/item/stamp/law
+ name = "law office's rubber stamp"
+ icon_state = "stamp-law"
+ item_color = "cargo"
+
+/obj/item/stamp/captain
+ name = "captain's rubber stamp"
+ icon_state = "stamp-cap"
+ item_color = "captain"
+
+/obj/item/stamp/hop
+ name = "head of personnel's rubber stamp"
+ icon_state = "stamp-hop"
+ item_color = "hop"
+
+/obj/item/stamp/hos
+ name = "head of security's rubber stamp"
+ icon_state = "stamp-hos"
+ item_color = "hosred"
+
+/obj/item/stamp/ce
+ name = "chief engineer's rubber stamp"
+ icon_state = "stamp-ce"
+ item_color = "chief"
+
+/obj/item/stamp/rd
+ name = "research director's rubber stamp"
+ icon_state = "stamp-rd"
+ item_color = "director"
+
+/obj/item/stamp/cmo
+ name = "chief medical officer's rubber stamp"
+ icon_state = "stamp-cmo"
+ item_color = "cmo"
+
+/obj/item/stamp/denied
+ name = "\improper DENIED rubber stamp"
+ icon_state = "stamp-deny"
+ item_color = "redcoat"
+
+/obj/item/stamp/clown
+ name = "clown's rubber stamp"
+ icon_state = "stamp-clown"
+ item_color = "clown"
+
+/obj/item/stamp/attack_paw(mob/user)
+ return attack_hand(user)
+
+// Syndicate stamp to forge documents.
+
+/obj/item/stamp/chameleon
+ actions_types = list(/datum/action/item_action/toggle)
+
+ var/list/stamp_types
+ var/list/stamp_names
+
+/obj/item/stamp/chameleon/Initialize()
+ . = ..()
+ stamp_types = typesof(/obj/item/stamp) - type // Get all stamp types except our own
+
+ stamp_names = list()
+ // Generate them into a list
+ for(var/i in stamp_types)
+ var/obj/item/stamp/stamp_type = i
+ stamp_names += initial(stamp_type.name)
+
+ stamp_names = sortList(stamp_names)
+
+/obj/item/stamp/chameleon/emp_act(severity)
+ change_to(pick(stamp_types))
+
+/obj/item/stamp/chameleon/proc/change_to(obj/item/stamp/stamp_type)
+ name = initial(stamp_type.name)
+ icon_state = initial(stamp_type.icon_state)
+ item_color = initial(stamp_type.item_color)
+
+/obj/item/stamp/chameleon/attack_self(mob/user)
+ var/input_stamp = input(user, "Choose a stamp to disguise as.",
+ "Choose a stamp.") as null|anything in stamp_names
+
+ if(user && (src in user.contents) && input_stamp)
+ var/obj/item/stamp/stamp_type
+ for(var/i in stamp_types)
+ stamp_type = i
+ if(initial(stamp_type.name) == input_stamp)
+ break
+ change_to(stamp_type)
+
+/obj/item/stamp/chameleon/broken/Initialize()
+ . = ..()
+ START_PROCESSING(SSobj, src)
+
+/obj/item/stamp/chameleon/broken/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/stamp/chameleon/broken/process()
+ change_to(pick(stamp_types))
diff --git a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
index 4f761412f7..00dba2d000 100644
--- a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
+++ b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
@@ -28,7 +28,7 @@
return
for(var/V in mother.map)
var/turf/T = V
- T.empty(deleteturfs? null : T.type, ignore_typecache = ignore_typecache, forceop = TRUE)
+ T.empty(deleteturfs? null : T.type, null, ignore_typecache, CHANGETURF_FORCEOP)
/datum/mapGeneratorModule/bottomLayer/massdelete/no_delete_mobs/New()
..()
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index a4ae8cae13..cced6d9544 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -126,6 +126,8 @@
sharpness = IS_SHARP
can_charge = 0
heat = 3800
+
+ usesound = 'sound/items/welder.ogg'
toolspeed = 0.7 //plasmacutters can be used as welders for a few things, and are faster than standard welders
/obj/item/gun/energy/plasmacutter/examine(mob/user)
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index 6b47b99a32..68770490e9 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -1281,3 +1281,19 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_icon_state = "glass_yellow"
glass_name = "eggnog"
glass_desc = "For enjoying the most wonderful time of the year."
+
+/datum/reagent/consumable/ethanol/narsour
+ name = "Nar'Sour"
+ id = "narsour"
+ description = "Side effects include self-mutilation and hoarding plasteel."
+ color = RUNE_COLOR_DARKRED
+ boozepwr = 10
+ taste_description = "bloody"
+ glass_icon_state = "narsour"
+ glass_name = "Nar'Sour"
+ glass_desc = "A new hit cocktail inspired by THE ARM Breweries will have you shouting Fuu ma'jin in no time!"
+
+/datum/reagent/consumable/ethanol/narsour/on_mob_life(mob/living/M)
+ M.cultslurring = min(M.cultslurring + 3, 3)
+ M.stuttering = min(M.stuttering + 3, 3)
+ ..()
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 4a21f9910d..b8e91c2da8 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -1147,6 +1147,8 @@
addiction_threshold = 5
/datum/reagent/medicine/ketrazine/on_mob_life(mob/living/M)
+ M.status_flags |= IGNORESLOWDOWN
+ M.status_flags |= GOTTAGOFAST
M.adjustToxLoss(-3*REM, 0)
M.adjustBruteLoss(-5*REM, 0)
M.adjustFireLoss(-5*REM, 0)
@@ -1243,4 +1245,3 @@
M.Dizzy(7)
M.Jitter(7)
..()
-
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index fa996b0bc0..0823d64bf1 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -244,8 +244,10 @@
toxpwr = 1
/datum/reagent/toxin/spore/on_mob_life(mob/living/M)
- M.damageoverlaytemp = 60
- M.update_damage_hud()
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ C.damageoverlaytemp = 60
+ C.update_damage_hud()
M.blur_eyes(3)
return ..()
diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index 7123267eb3..8bb62fb233 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -232,4 +232,13 @@
id = "morphine"
results = list("morphine" = 3)
required_reagents = list("carbon" = 2, "hydrogen" = 2, "nitrogen" = 1, "oxygen" = 1)
- required_temp = 480
\ No newline at end of file
+ required_temp = 480
+
+/datum/chemical_reaction/ketrazine
+ name = "Ketrazine"
+ id = "ketrazine"
+ results = list("ketrazine" = 3)
+ required_reagents = list("epinephrine" = 1, "ephedrine" = 1, "tricordazine" = 1, "atropine" = 1)
+ required_catalysts = list("gold" = 1)
+ required_temp = 520
+ mix_message = "The solution fizzes and then settles into an oily, smooth, purple liquid."
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index f539c0dd14..d87750c394 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -248,7 +248,7 @@
var/launch_status = NOLAUNCH
- var/list/movement_force = list("KNOCKDOWN" = 3, "THROW" = 0)
+ var/list/movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
// A timid shuttle will not register itself with the shuttle subsystem
// All shuttle templates are timid
@@ -745,4 +745,4 @@
mode = SHUTTLE_ENDGAME
/obj/docking_port/mobile/emergency/on_emergency_dock()
- return
\ No newline at end of file
+ return
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index 54514689cb..f798eac3d4 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -714,10 +714,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
exclude_modes = list(/datum/game_mode/nuclear)
player_minimum = 20
-/datum/uplink_item/stealthy_tools/chameleon/nuke
- cost = 6
- include_modes = list(/datum/game_mode/nuclear)
-
/datum/uplink_item/stealthy_tools/syndigaloshes
name = "No-Slip Chameleon Shoes"
desc = "These shoes will allow the wearer to run on wet floors and slippery objects without falling down. \
@@ -727,6 +723,12 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
exclude_modes = list(/datum/game_mode/nuclear)
player_minimum = 20
+/datum/uplink_item/stealthy_tools/syndigaloshes/nuke
+ item = /obj/item/clothing/shoes/chameleon
+ cost = 4
+ exclude_modes = list()
+ include_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/stealthy_tools/frame
name = "F.R.A.M.E. PDA Cartridge"
desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \
@@ -736,15 +738,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/cartridge/virus/frame
cost = 4
-/datum/uplink_item/stealthy_tools/syndigaloshes/nuke
- name = "Stealthy No-Slip Chameleon Shoes"
- desc = "These shoes will allow the wearer to run on wet floors and slippery objects without falling down. \
- They do not work on heavily lubricated surfaces. The manufacturer claims they are much more stealthy than the normal brand."
- item = /obj/item/clothing/shoes/chameleon
- cost = 4
- exclude_modes = list()
- include_modes = list(/datum/game_mode/nuclear)
-
/datum/uplink_item/stealthy_tools/agent_card
name = "Agent Identification Card"
desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access \
@@ -1328,6 +1321,27 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
cost = 20
cant_discount = TRUE
+/datum/uplink_item/badass/costumes
+ surplus = 0
+ include_modes = list(/datum/game_mode/nuclear)
+ cost = 4
+ cant_discount = TRUE
+
+/datum/uplink_item/badass/costumes/centcom_official
+ name = "Centcom Official Costume"
+ desc = "Ask the crew to \"inspect\" their nuclear disk and weapons system, and then when they decline, pull out a fully automatic rifle and gun down the Captain. Radio headset does not include key. No gun included."
+ item = /obj/item/storage/box/syndie_kit/centcom_costume
+
+/datum/uplink_item/badass/costumes/clown
+ name = "Clown Costume"
+ desc = "Nothing is more terrifying than clowns with fully automatic weaponry."
+ item = /obj/item/storage/backpack/duffelbag/clown/syndie
+
+/datum/uplink_item/badass/costumes/obvious_chameleon
+ name = "Broken Chameleon Kit"
+ desc = "A set of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more! Please note that this kit did NOT pass quality control."
+ item = /obj/item/storage/box/syndie_kit/chameleon/broken
+
/datum/uplink_item/badass/bundle
name = "Syndicate Bundle"
desc = "Syndicate Bundles are specialized groups of items that arrive in a plain box. \
diff --git a/html/changelogs/AutoChangeLog-pr-5067.yml b/html/changelogs/AutoChangeLog-pr-5067.yml
new file mode 100644
index 0000000000..ab176d32ba
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-5067.yml
@@ -0,0 +1,4 @@
+author: "Robustin"
+delete-after: True
+changes:
+ - rscadd: "A new cocktail: The Nar'Sour. Made from blood, demonsblood, and lemon juice, this cocktail is known to induce a slightly different type of slurring when imbibed."
diff --git a/html/changelogs/AutoChangeLog-pr-5070.yml b/html/changelogs/AutoChangeLog-pr-5070.yml
new file mode 100644
index 0000000000..e9c504e674
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-5070.yml
@@ -0,0 +1,6 @@
+author: "Robustin"
+delete-after: True
+changes:
+ - balance: "Clockwork marauders now take more time (+3s) and power (7x) to create."
+ - balance: "The \"recent marauder\" time limit is now 60 seconds, up from 20. The limit now has a significantly smaller effect on summon time but will act as a further cap on marauder summoning until it has passed."
+ - tweak: "The marauder cap will now only account for living cultists."
diff --git a/html/changelogs/AutoChangeLog-pr-5071.yml b/html/changelogs/AutoChangeLog-pr-5071.yml
new file mode 100644
index 0000000000..facd56fda6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-5071.yml
@@ -0,0 +1,6 @@
+author: "Xhuis"
+delete-after: True
+changes:
+ - balance: "Fleshmend can no longer be stacked several times at once."
+ - balance: "Fleshmend no longer heals changelings who are on fire, and heals burn damage half as quickly as brute and oxygen damage."
+ - code_imp: "Fleshmend has been refactored into a status effect."
diff --git a/html/changelogs/AutoChangeLog-pr-5072.yml b/html/changelogs/AutoChangeLog-pr-5072.yml
new file mode 100644
index 0000000000..748208977b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-5072.yml
@@ -0,0 +1,6 @@
+author: "coiax"
+delete-after: True
+changes:
+ - rscadd: "Nuclear operatives that wish to fail in style can purchase Centcom
+Official and Clown costumes. They can also buy a defective chameleon
+kit."
diff --git a/html/changelogs/AutoChangeLog-pr-5076.yml b/html/changelogs/AutoChangeLog-pr-5076.yml
new file mode 100644
index 0000000000..3017cd534e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-5076.yml
@@ -0,0 +1,4 @@
+author: "Ordo"
+delete-after: True
+changes:
+ - rscadd: "Adds Ketrazine, a powerful but dangerous combat stim which the crew can synthesize"
diff --git a/html/changelogs/AutoChangeLog-pr-5080.yml b/html/changelogs/AutoChangeLog-pr-5080.yml
new file mode 100644
index 0000000000..5b110dc0ae
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-5080.yml
@@ -0,0 +1,4 @@
+author: "Dax Dupont"
+delete-after: True
+changes:
+ - imageadd: "Autolathe now repeats it's animation while printing."
diff --git a/html/changelogs/AutoChangeLog-pr-5081.yml b/html/changelogs/AutoChangeLog-pr-5081.yml
new file mode 100644
index 0000000000..5113078f76
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-5081.yml
@@ -0,0 +1,4 @@
+author: "SPACE CONDUCTOR"
+delete-after: True
+changes:
+ - tweak: "Shuttles will throw you around if ya don't buckle in"
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index e6d40977a7..01fcdcddad 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi
index e4c1de0282..d657bd841b 100644
Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ
diff --git a/tools/WebhookProcessor/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php
index 604f87678e..f7ea3eecfc 100644
--- a/tools/WebhookProcessor/github_webhook_processor.php
+++ b/tools/WebhookProcessor/github_webhook_processor.php
@@ -179,7 +179,9 @@ function set_labels($payload, $labels, $remove) {
$tags = array_merge($labels, $existing);
$tags = array_unique($tags);
- $tags = array_diff($tags, $remove);
+ if($remove) {
+ $tags = array_diff($tags, $remove);
+ }
$final = array();
foreach($tags as $t)