[src] slams into your shoulder, knocking you down!")
- C.Knockdown(60)
+ C.DefaultCombatKnockdown(60)
/obj/item/pneumatic_cannon/proc/fire_items(turf/target, mob/user)
if(fire_mode == PCANNON_FIREALL)
diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm
index ac490b0122..cc466d73fc 100644
--- a/code/game/objects/items/religion.dm
+++ b/code/game/objects/items/religion.dm
@@ -64,8 +64,7 @@
/obj/item/banner/proc/inspiration(mob/living/carbon/human/H)
H.adjustBruteLoss(-15)
H.adjustFireLoss(-15)
- H.AdjustStun(-40)
- H.AdjustKnockdown(-40)
+ H.AdjustAllImmobility(-40)
H.AdjustUnconscious(-40)
playsound(H, 'sound/magic/staff_healing.ogg', 25, FALSE)
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 48c16190d9..d3e966f2fa 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -20,7 +20,7 @@
return
user.do_attack_animation(M)
- M.Knockdown(100)
+ M.DefaultCombatKnockdown(100)
M.apply_effect(EFFECT_STUTTER, 5)
M.visible_message("[user] has prodded [M] with [src]!", \
@@ -81,8 +81,7 @@
user.visible_message("[user] hugs [M] to make [M.p_them()] feel better!", \
"You hug [M] to make [M.p_them()] feel better!")
if(M.resting && !M.recoveringstam)
- M.resting = FALSE
- M.update_canmove()
+ M.set_resting(FALSE, TRUE)
else
user.visible_message("[user] pets [M]!", \
"You pet [M]!")
@@ -100,9 +99,8 @@
else
user.visible_message("[user] hugs [M] in a firm bear-hug! [M] looks uncomfortable...", \
"You hug [M] firmly to make [M.p_them()] feel better! [M] looks uncomfortable...")
- if(M.resting && !M.recoveringstam)
- M.resting = FALSE
- M.update_canmove()
+ if(!CHECK_MOBILITY(M, MOBILITY_STAND) && !M.recoveringstam)
+ M.set_resting(FALSE, TRUE)
else
user.visible_message("[user] bops [M] on the head!", \
"You bop [M] on the head!")
@@ -114,7 +112,6 @@
M.electrocute_act(5, "[user]", safety = 1)
user.visible_message("[user] electrocutes [M] with [user.p_their()] touch!", \
"You electrocute [M] with your touch!")
- M.update_canmove()
else
if(!iscyborg(M))
M.adjustFireLoss(10)
@@ -326,7 +323,7 @@
C.stuttering += 10
C.Jitter(10)
if(2)
- C.Knockdown(40)
+ C.DefaultCombatKnockdown(40)
C.confused += 10
C.stuttering += 15
C.Jitter(25)
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 54f0dc600d..6621095b72 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -317,8 +317,7 @@
O.robot_suit = src
if(!locomotion)
- O.lockcharge = 1
- O.update_canmove()
+ O.SetLockdown(TRUE)
to_chat(O, "Error: Servo motors unresponsive.")
else
@@ -356,8 +355,7 @@
forceMove(O)
O.robot_suit = src
if(!locomotion)
- O.lockcharge = TRUE
- O.update_canmove()
+ O.SetLockdown(TRUE)
else if(istype(W, /obj/item/pen))
to_chat(user, "You need to use a multitool to name [src]!")
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 18568b3d0f..56af03139a 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -577,7 +577,7 @@
return FALSE
R.notransform = TRUE
- var/prev_lockcharge = R.lockcharge
+ var/prev_locked_down = R.locked_down
R.SetLockdown(1)
R.anchored = TRUE
var/datum/effect_system/smoke_spread/smoke = new
@@ -587,7 +587,7 @@
for(var/i in 1 to 4)
playsound(R, pick('sound/items/drill_use.ogg', 'sound/items/jaws_cut.ogg', 'sound/items/jaws_pry.ogg', 'sound/items/welder.ogg', 'sound/items/ratchet.ogg'), 80, 1, -1)
sleep(12)
- if(!prev_lockcharge)
+ if(!prev_locked_down)
R.SetLockdown(0)
R.anchored = FALSE
R.notransform = FALSE
diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm
index 4f5f264c0e..07f4cb4e40 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -237,3 +237,19 @@
w_class = WEIGHT_CLASS_HUGE
item_flags = SLOWS_WHILE_IN_HAND
transparent = FALSE
+
+/obj/item/shield/riot/implant
+ name = "riot tower shield"
+ desc = "A massive shield that can block a lot of attacks and can take a lot of abuse before breaking." //It cant break unless it is removed from the implant
+ item_state = "metal"
+ icon_state = "metal"
+ icon = 'icons/obj/items_and_weapons.dmi'
+ block_chance = 30 //May be big but hard to move around to block.
+ slowdown = 1
+ transparent = FALSE
+ item_flags = SLOWS_WHILE_IN_HAND
+
+/obj/item/shield/riot/implant/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+ if(attack_type == PROJECTILE_ATTACK)
+ final_block_chance = 60 //Massive shield
+ return ..()
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 0eefb88417..6cb351cb74 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -33,6 +33,12 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
new /datum/stack_recipe("sofa (corner)", /obj/structure/chair/sofa/corner, one_per_turf = TRUE, on_floor = TRUE), \
)), \
//END OF CIT CHANGES
+ new/datum/stack_recipe_list("fancy sofas", list( \
+ new /datum/stack_recipe("sofa (middle)", /obj/structure/chair/sofa/corp, one_per_turf = TRUE, on_floor = TRUE), \
+ new /datum/stack_recipe("sofa (left)", /obj/structure/chair/sofa/corp/left, one_per_turf = TRUE, on_floor = TRUE), \
+ new /datum/stack_recipe("sofa (right)", /obj/structure/chair/sofa/corp/right, one_per_turf = TRUE, on_floor = TRUE), \
+ new /datum/stack_recipe("sofa (corner)", /obj/structure/chair/sofa/corp/corner, one_per_turf = TRUE, on_floor = TRUE), \
+ )), \
null, \
new/datum/stack_recipe_list("office chairs", list( \
new/datum/stack_recipe("dark office chair", /obj/structure/chair/office/dark, 5, one_per_turf = TRUE, on_floor = TRUE), \
@@ -42,8 +48,10 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
new/datum/stack_recipe("beige comfy chair", /obj/structure/chair/comfy/beige, 2, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("black comfy chair", /obj/structure/chair/comfy/black, 2, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("brown comfy chair", /obj/structure/chair/comfy/brown, 2, one_per_turf = TRUE, on_floor = TRUE), \
+ new/datum/stack_recipe("green comfy chair", /obj/structure/chair/comfy/green, 2, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("lime comfy chair", /obj/structure/chair/comfy/lime, 2, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("teal comfy chair", /obj/structure/chair/comfy/teal, 2, one_per_turf = TRUE, on_floor = TRUE), \
+ new/datum/stack_recipe("purple comfy chair", /obj/structure/chair/comfy/purple, 2, one_per_turf = TRUE, on_floor = TRUE), \
)), \
null, \
new/datum/stack_recipe("rack parts", /obj/item/rack_parts), \
@@ -96,6 +104,21 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
new/datum/stack_recipe("extinguisher cabinet frame", /obj/item/wallframe/extinguisher_cabinet, 2), \
new/datum/stack_recipe("button frame", /obj/item/wallframe/button, 1), \
null, \
+ new /datum/stack_recipe_list("chess pieces", list( \
+ new /datum/stack_recipe("White Pawn", /obj/structure/chess/whitepawn, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("White Rook", /obj/structure/chess/whiterook, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("White Knight", /obj/structure/chess/whiteknight, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("White Bishop", /obj/structure/chess/whitebishop, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("White Queen", /obj/structure/chess/whitequeen, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("White King", /obj/structure/chess/whiteking, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("Black Pawn", /obj/structure/chess/blackpawn, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("Black Rook", /obj/structure/chess/blackrook, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("Black Knight", /obj/structure/chess/blackknight, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("Black Bishop", /obj/structure/chess/blackbishop, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("Black Queen", /obj/structure/chess/blackqueen, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ new /datum/stack_recipe("Black King", /obj/structure/chess/blackking, 2, time = 10, one_per_turf = 1, on_floor = 1), \
+ )), \
+ null, \
new/datum/stack_recipe("iron door", /obj/structure/mineral_door/iron, 20, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("floodlight frame", /obj/structure/floodlight_frame, 5, one_per_turf = TRUE, on_floor = TRUE), \
))
@@ -206,6 +229,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
null, \
new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \
+ new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 30), \
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\
null, \
@@ -347,6 +371,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
new/datum/stack_recipe("black gloves", /obj/item/clothing/gloves/color/black, 3), \
null, \
new/datum/stack_recipe("blindfold", /obj/item/clothing/glasses/sunglasses/blindfold, 2), \
+ null, \
))
/obj/item/stack/sheet/cloth
@@ -738,6 +763,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("opaque plastic flaps", /obj/structure/plasticflaps/opaque, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \
new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \
new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \
+ new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2)))
/obj/item/stack/sheet/plastic
@@ -790,6 +816,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
/obj/item/stack/sheet/cotton
name = "raw cotton bundle"
desc = "A bundle of raw cotton ready to be spun on the loom."
+ max_amount = 80
singular_name = "raw cotton ball"
icon_state = "sheet-cotton"
is_fabric = TRUE
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index f07b9bfd33..f707c02ce9 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -48,7 +48,7 @@
merge_type = type
if(custom_materials && custom_materials.len)
for(var/i in custom_materials)
- custom_materials[getmaterialref(i)] = mats_per_stack * amount
+ custom_materials[SSmaterials.GetMaterialRef(i)] = mats_per_stack * amount
. = ..()
if(merge)
for(var/obj/item/stack/S in loc)
@@ -57,7 +57,7 @@
var/list/temp_recipes = get_main_recipes()
recipes = temp_recipes.Copy()
if(material_type)
- var/datum/material/M = getmaterialref(material_type) //First/main material
+ var/datum/material/M = SSmaterials.GetMaterialRef(material_type) //First/main material
for(var/i in M.categories)
switch(i)
if(MAT_CATEGORY_RIGID)
@@ -225,7 +225,7 @@
if(R.applies_mats && custom_materials && custom_materials.len)
var/list/used_materials = list()
for(var/i in custom_materials)
- used_materials[getmaterialref(i)] = R.req_amount / R.res_amount * (MINERAL_MATERIAL_AMOUNT / custom_materials.len)
+ used_materials[SSmaterials.GetMaterialRef(i)] = R.req_amount / R.res_amount * (MINERAL_MATERIAL_AMOUNT / custom_materials.len)
O.set_custom_materials(used_materials)
//START: oh fuck i'm so sorry
@@ -347,7 +347,7 @@
src.amount += amount
if(custom_materials && custom_materials.len)
for(var/i in custom_materials)
- custom_materials[getmaterialref(i)] = MINERAL_MATERIAL_AMOUNT * src.amount
+ custom_materials[SSmaterials.GetMaterialRef(i)] = MINERAL_MATERIAL_AMOUNT * src.amount
set_custom_materials() //Refresh
update_icon()
update_weight()
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index b2fbbc8117..7a6e1e3db6 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -246,7 +246,8 @@
set name = "Activate Seed Extraction"
set category = "Object"
set desc = "Activate to convert your plants into plantable seeds."
- if(usr.stat || !usr.canmove || usr.restrained())
+ var/mob/living/L = usr
+ if(istype(L) && !CHECK_MOBILITY(L, MOBILITY_USE))
return
for(var/obj/item/O in contents)
seedify(O, 1)
@@ -353,7 +354,7 @@
if(ishuman(M) || ismonkey(M))
if(prob(10))
- M.Knockdown(40)
+ M.DefaultCombatKnockdown(40)
update_icon()
/obj/item/storage/bag/tray/update_overlays()
diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm
index b4fe6b8f85..f2c50b359e 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -170,7 +170,7 @@
. = ..()
if(!fancy_open || !contents.len)
return
- . *= "[icon_state]_open"
+ . += "[icon_state]_open"
var/cig_position = 1
for(var/C in contents)
var/mutable_appearance/inserted_overlay = mutable_appearance(icon)
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 611870912c..ab55555562 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -397,3 +397,97 @@
/obj/item/storage/box/syndie_kit/revolver/PopulateContents()
new /obj/item/gun/ballistic/revolver(src)
new /obj/item/ammo_box/a357(src)
+
+/obj/item/storage/box/syndie_kit/contract_kit
+ name = "contractor kit"
+ desc = "Supplied to Syndicate contractors in active mission areas."
+
+/obj/item/storage/box/syndicate/contractor_loadout
+ name = "standard loadout"
+ desc = "Supplied to Syndicate contractors, providing their specialised space suit and chameleon uniform."
+ icon_state = "syndiebox"
+ illustration = "writing_syndie"
+
+/obj/item/paper/contractor_guide
+ name = "Contractor Guide"
+
+/obj/item/paper/contractor_guide/Initialize()
+ info = {"Welcome agent, congratulations on your new position as contractor. On top of your already assigned objectives,
+ this kit will provide you contracts to take on for TC payments.
+ Provided within, we give your specialist contractor space suit. It's even more compact, being able to fit into a pocket, and faster than the
+ Syndicate space suit available to you on the uplink. We also provide your chameleon jumpsuit and mask, both of which can be changed
+ to any form you need for the moment. The cigarettes are a special blend - it'll heal your injuries slowly overtime.
+ The three additional items, apart from the tablet and loadout box, have been randomly selected from what we had available. We hope
+ they're useful to you for you mission.
+ The contractor hub, available at the top right of the uplink, will provide you unique items and abilities. These are bought using Contractor Rep,
+ with two Rep being provided each time you complete a contract.
+ Using the tablet
+
+ - Open the Syndicate Contract Uplink program.
+ - Assign yourself.
+ - Here, you can accept a contract, and redeem your TC payments from completed contracts.
+ - The payment number shown in brackets is the bonus you'll recieve when bringing your target alive. You recieve the
+ other number regardless of if they were alive or dead.
+ - Contracts are completed by bringing the target to designated dropoff, calling for extraction, and putting them
+ inside the pod.
+
+ Be careful when accepting a contract. While you'll be able to see the location of the dropoff point, cancelling will make it
+ unavailable to take on again.
+ The tablet can also be recharged at any cell charger.
+ Extracting
+
+ - Make sure both yourself and your target are at the dropoff.
+ - Call the extraction, and stand back from the drop point
+ - If it fails, make sure your target is inside, and there's a free space for the pod to land.
+ - Grab your target, and drag them into the pod.
+
+ Ransoms
+ We need your target for our own reasons, but we ransom them back to your mission area once their use is served. They will return back
+ from where you sent them off from in several minutes time. You will be paid in TC for your services.
+
+ Good luck agent. You can burn this document with the supplied lighter.
"}
+
+ return ..()
+
+/obj/item/storage/box/syndicate/contractor_loadout/PopulateContents()
+ new /obj/item/clothing/head/helmet/space/syndicate/contract(src)
+ new /obj/item/clothing/suit/space/syndicate/contract(src)
+ new /obj/item/clothing/under/chameleon(src)
+ new /obj/item/clothing/mask/chameleon(src)
+ new /obj/item/card/id/syndicate(src)
+ new /obj/item/storage/fancy/cigarettes/cigpack_syndicate(src)
+ new /obj/item/lighter(src)
+
+/obj/item/storage/box/syndie_kit/contract_kit/PopulateContents()
+ new /obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink(src)
+ new /obj/item/storage/box/syndicate/contractor_loadout(src)
+ new /obj/item/melee/classic_baton/telescopic/contractor_baton(src)
+ var/list/item_list = list( // All 4 TC or less - some nukeops only items, but fit nicely to the theme.
+ /obj/item/storage/backpack/duffelbag/syndie/x4,
+ /obj/item/storage/box/syndie_kit/throwing_weapons,
+ /obj/item/gun/syringe/syndicate,
+ /obj/item/pen/edagger,
+ /obj/item/pen/sleepy,
+ /obj/item/flashlight/emp,
+ /obj/item/reagent_containers/syringe/mulligan,
+ /obj/item/clothing/shoes/chameleon/noslip,
+ /obj/item/storage/firstaid/tactical,
+ /obj/item/storage/backpack/duffelbag/syndie/surgery,
+ /obj/item/encryptionkey/syndicate,
+ /obj/item/clothing/glasses/thermal/syndi,
+ /obj/item/slimepotion/slime/sentience/nuclear,
+ /obj/item/storage/box/syndie_kit/imp_radio,
+ /obj/item/storage/box/syndie_kit/imp_uplink,
+ /obj/item/clothing/gloves/krav_maga/combatglovesplus,
+ /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted/riot,
+ /obj/item/reagent_containers/syringe/stimulants,
+ /obj/item/storage/box/syndie_kit/imp_freedom,
+ /obj/item/toy/eightball/haunted
+ )
+ var/obj/item1 = pick_n_take(item_list)
+ var/obj/item2 = pick_n_take(item_list)
+ var/obj/item3 = pick_n_take(item_list)
+ new item1(src) // Create three, non repeat items from the list.
+ new item2(src)
+ new item3(src)
+ new /obj/item/paper/contractor_guide(src) //Paper guide
\ No newline at end of file
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index c48122fb0e..78ba6d4f5f 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -191,7 +191,7 @@
if(!disarming)
if(knockdown)
- L.Knockdown(50, override_stamdmg = 0) //knockdown
+ L.DefaultCombatKnockdown(50, override_stamdmg = 0) //knockdown
L.adjustStaminaLoss(stunpwr)
else
L.drop_all_held_items() //no knockdown/stamina damage, instead disarm.
@@ -218,7 +218,7 @@
user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \
"You accidentally hit yourself with [src]!")
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
- user.Knockdown(stamforce*6)
+ user.DefaultCombatKnockdown(stamforce*6)
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
deductcharge(hitcost)
diff --git a/code/game/objects/items/teleprod.dm b/code/game/objects/items/teleprod.dm
index bab4d6a488..63bde36976 100644
--- a/code/game/objects/items/teleprod.dm
+++ b/code/game/objects/items/teleprod.dm
@@ -16,7 +16,7 @@
user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \
"You accidentally hit yourself with [src]!")
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
- user.Knockdown(stamforce * 6)
+ user.DefaultCombatKnockdown(stamforce * 6)
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
if(do_teleport(user, get_turf(user), 50, channel = TELEPORT_CHANNEL_BLUESPACE))
deductcharge(hitcost)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 1a5f97c4e0..ba51fa3d65 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -228,26 +228,39 @@
var/hacked = FALSE
total_mass = 0.4
var/total_mass_on = TOTAL_MASS_TOY_SWORD
+ var/activation_sound = 'sound/weapons/saberon.ogg'
+ var/deactivation_sound = 'sound/weapons/saberoff.ogg'
+ var/activation_message = "You extend the plastic blade with a quick flick of your wrist."
+ var/deactivation_message = "You push the plastic blade back down into the handle."
+ var/transform_volume = 20
/obj/item/toy/sword/attack_self(mob/user)
- active = !( active )
+ active = !active
if (active)
- to_chat(user, "You extend the plastic blade with a quick flick of your wrist.")
- playsound(user, 'sound/weapons/saberon.ogg', 20, 1)
+ to_chat(user, "[activation_message]")
+ playsound(user, activation_sound, transform_volume, 1)
+ w_class = WEIGHT_CLASS_BULKY
+ AddElement(/datum/element/sword_point)
+ else
+ to_chat(user, "[deactivation_message]")
+ playsound(user, deactivation_sound, transform_volume, 1)
+ w_class = WEIGHT_CLASS_SMALL
+ RemoveElement(/datum/element/sword_point)
+
+ update_icon()
+ add_fingerprint(user)
+
+/obj/item/toy/sword/update_icon_state()
+ if(active)
if(hacked)
icon_state = "swordrainbow"
item_state = "swordrainbow"
else
icon_state = "swordblue"
item_state = "swordblue"
- w_class = WEIGHT_CLASS_BULKY
else
- to_chat(user, "You push the plastic blade back down into the handle.")
- playsound(user, 'sound/weapons/saberoff.ogg', 20, 1)
icon_state = "sword0"
item_state = "sword0"
- w_class = WEIGHT_CLASS_SMALL
- add_fingerprint(user)
// Copied from /obj/item/melee/transforming/energy/sword/attackby
/obj/item/toy/sword/attackby(obj/item/W, mob/living/user, params)
@@ -270,7 +283,7 @@
to_chat(user, "RNBW_ENGAGE")
if(active)
- icon_state = "swordrainbow"
+ update_icon()
user.update_inv_hands()
else
to_chat(user, "It's already fabulous!")
@@ -290,38 +303,24 @@
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("poked", "jabbed", "hit")
light_color = "#37FFF7"
+ activation_sound = 'sound/weapons/nebon.ogg'
+ deactivation_sound = 'sound/weapons/neboff.ogg'
+ transform_volume = 50
+ activation_message = "You activate the holographic blade with a press of a button."
+ deactivation_message = "You deactivate the holographic blade with a press of a button."
var/light_brightness = 3
actions_types = list()
-/obj/item/toy/sword/cx/alt_pre_attack(atom/A, mob/living/user, params) //checks if it can do right click memes
- altafterattack(A, user, TRUE, params)
- return TRUE
-
-/obj/item/toy/sword/cx/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
- if(istype(user))
- user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
- return TRUE
+/obj/item/toy/sword/cx/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/update_icon_updates_onmob)
/obj/item/toy/sword/cx/attack_self(mob/user)
- active = !( active )
+ . = ..()
+ set_light(active ? light_brightness : 0)
- if (active)
- to_chat(user, "You activate the holographic blade with a press of a button.")
- playsound(user, 'sound/weapons/nebon.ogg', 50, 1)
- w_class = WEIGHT_CLASS_BULKY
- attack_verb = list("slashed", "stabbed", "ravaged")
- set_light(light_brightness)
- update_icon()
-
- else
- to_chat(user, "You deactivate the holographic blade with a press of a button.")
- playsound(user, 'sound/weapons/neboff.ogg', 50, 1)
- w_class = WEIGHT_CLASS_SMALL
- attack_verb = list("poked", "jabbed", "hit")
- set_light(0)
- update_icon()
-
- add_fingerprint(user)
+/obj/item/toy/sword/cx/update_icon_state()
+ return
/obj/item/toy/sword/cx/update_overlays()
. = ..()
@@ -1079,8 +1078,13 @@
else
return ..()
-/obj/item/toy/cards/singlecard/attack_self(mob/user)
- if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained())
+/obj/item/toy/cards/singlecard/attack_self(mob/living/user)
+ . = ..()
+ if(.)
+ return
+ if(!ishuman(user))
+ return
+ if(!CHECK_MOBILITY(user, MOBILITY_USE))
return
Flip()
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index 23bd6ed359..11a06e149d 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -396,6 +396,7 @@
hitsound = 'sound/weapons/blade1.ogg'
START_PROCESSING(SSobj, src)
set_light(brightness_on)
+ AddElement(/datum/element/sword_point)
/obj/item/twohanded/dualsaber/unwield() //Specific unwield () to switch hitsounds.
sharpness = initial(sharpness)
@@ -405,6 +406,7 @@
hitsound = "swing_hit"
STOP_PROCESSING(SSobj, src)
set_light(0)
+ RemoveElement(/datum/element/sword_point)
/obj/item/twohanded/dualsaber/process()
if(wielded)
@@ -493,15 +495,6 @@
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
-/obj/item/twohanded/dualsaber/hypereutactic/alt_pre_attack(atom/A, mob/living/user, params) //checks if it can do right click memes
- altafterattack(A, user, TRUE, params)
- return TRUE
-
-/obj/item/twohanded/dualsaber/hypereutactic/altafterattack(atom/target, mob/living/user, proximity_flag, click_parameters) //does right click memes
- if(istype(user))
- user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
- return TRUE
-
/obj/item/twohanded/dualsaber/hypereutactic/update_icon_state()
return
@@ -605,6 +598,8 @@
/obj/item/twohanded/spear/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 100, 70) //decent in a pinch, but pretty bad.
+ AddComponent(/datum/component/jousting)
+ AddElement(/datum/element/sword_point)
/obj/item/twohanded/spear/attack_self(mob/user)
if(explosive)
@@ -630,10 +625,6 @@
return BRUTELOSS
return BRUTELOSS
-/obj/item/twohanded/spear/Initialize()
- . = ..()
- AddComponent(/datum/component/jousting)
-
/obj/item/twohanded/spear/examine(mob/user)
. = ..()
if(explosive)
@@ -818,6 +809,9 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
+/obj/item/twohanded/pitchfork/Initialize(mapload)
+ AddElement(/datum/element/sword_point)
+
/obj/item/twohanded/pitchfork/demonic
name = "demonic pitchfork"
desc = "A red pitchfork, it looks like the work of the devil."
@@ -901,6 +895,7 @@
/obj/item/twohanded/vibro_weapon/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 20, 105)
+ AddElement(/datum/element/sword_point)
/obj/item/twohanded/vibro_weapon/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(wielded)
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 7499d9de09..bc9c3255a6 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -74,6 +74,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/claymore/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 40, 105)
+ AddElement(/datum/element/sword_point)
/obj/item/claymore/suicide_act(mob/user)
user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -346,25 +347,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
return (BRUTELOSS)
-/obj/item/switchblade/crafted
- icon_state = "switchblade_ms"
- desc = "A concealable spring-loaded knife."
- force = 2
- throwforce = 3
- extended_force = 15
- extended_throwforce = 18
- extended_icon_state = "switchblade_ext_ms"
- retracted_icon_state = "switchblade_ms"
-
-/obj/item/switchblade/crafted/attackby(obj/item/I, mob/user, params)
- . = ..()
- if(istype(I, /obj/item/stack/sheet/mineral/silver))
- icon_state = extended ? "switchblade_ext_msf" : "switchblade_msf"
- extended_icon_state = "switchblade_ext_msf"
- retracted_icon_state = "switchblade_msf"
- icon_state = "switchblade_msf"
- to_chat(user, "You use part of the silver to improve your Switchblade. Stylish!")
-
/obj/item/phone
name = "red phone"
desc = "Should anything ever go wrong..."
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 1d36b2b41b..e185defc0a 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -33,7 +33,7 @@
if(structureclimber && structureclimber != user)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
- structureclimber.Knockdown(40)
+ structureclimber.DefaultCombatKnockdown(40)
structureclimber.visible_message("[structureclimber] has been knocked off [src].", "You're knocked off [src]!", "You see [structureclimber] get knocked off [src].")
/obj/structure/ui_act(action, params)
@@ -45,7 +45,8 @@
if(!climbable)
return
if(user == O && iscarbon(O))
- if(user.canmove)
+ var/mob/living/L = O
+ if(CHECK_MOBILITY(L, MOBILITY_MOVE))
climb_structure(user)
return
if(!istype(O, /obj/item) || user.get_active_held_item() != O)
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index 0d38f5eca6..e0c2d6e2c7 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -110,7 +110,7 @@
user.visible_message("[user] pulls [src] out from under [poordude].", "You pull [src] out from under [poordude].")
var/C = new item_chair(loc)
user.put_in_hands(C)
- poordude.Knockdown(20)//rip in peace
+ poordude.DefaultCombatKnockdown(20)//rip in peace
user.adjustStaminaLoss(5)
unbuckle_all_mobs(TRUE)
qdel(src)
@@ -153,7 +153,7 @@
///Material chair
/obj/structure/chair/greyscale
icon_state = "chair_greyscale"
- material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
+ material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
item_chair = /obj/item/chair/greyscale
buildstacktype = null //Custom mats handle this
@@ -226,9 +226,15 @@
/obj/structure/chair/comfy/black
color = rgb(167,164,153)
+/obj/structure/chair/comfy/green
+ color = rgb(81,173,106)
+
/obj/structure/chair/comfy/lime
color = rgb(255,251,0)
+/obj/structure/chair/comfy/purple
+ color = rgb(255,50,230)
+
/obj/structure/chair/comfy/plywood
name = "plywood chair"
desc = "A relaxing plywood chair."
@@ -371,13 +377,13 @@
if(iscarbon(target))
var/mob/living/carbon/C = target
if(C.health < C.maxHealth*0.5)
- C.Knockdown(20)
+ C.DefaultCombatKnockdown(20)
smash(user)
/obj/item/chair/greyscale
icon_state = "chair_greyscale_toppled"
item_state = "chair_greyscale"
- material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
+ material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
origin_type = /obj/structure/chair/greyscale
/obj/item/chair/stool
@@ -576,40 +582,3 @@
. = ..()
if(has_gravity())
playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE)
-
-/obj/structure/chair/sofa
- name = "old ratty sofa"
- icon_state = "sofamiddle"
- icon = 'icons/obj/sofa.dmi'
- buildstackamount = 1
- var/mutable_appearance/armrest
-
-/obj/structure/chair/sofa/Initialize()
- armrest = mutable_appearance(icon, "[icon_state]_armrest", ABOVE_MOB_LAYER)
- return ..()
-
-/obj/structure/chair/sofa/post_buckle_mob(mob/living/M)
- . = ..()
- update_armrest()
-
-/obj/structure/chair/sofa/proc/update_armrest()
- if(has_buckled_mobs())
- add_overlay(armrest)
- else
- cut_overlay(armrest)
-
-/obj/structure/chair/sofa/post_unbuckle_mob()
- . = ..()
- update_armrest()
-
-/obj/structure/chair/sofa/left
- icon_state = "sofaend_left"
-
-/obj/structure/chair/sofa/right
- icon_state = "sofaend_right"
-
-/obj/structure/chair/sofa/corner
- icon_state = "sofacorner"
-
-/obj/structure/chair/sofa/corner/handle_layer() //only the armrest/back of this chair should cover the mob.
- return
diff --git a/code/game/objects/structures/beds_chairs/pew.dm b/code/game/objects/structures/beds_chairs/pew.dm
index 65440fb5d8..ec257a9898 100644
--- a/code/game/objects/structures/beds_chairs/pew.dm
+++ b/code/game/objects/structures/beds_chairs/pew.dm
@@ -10,7 +10,7 @@
item_chair = null
/obj/structure/chair/pew/left
- name = "left wooden pew end"
+ name = "wooden pew end"
icon_state = "pewend_left"
var/mutable_appearance/leftpewarmrest
@@ -41,7 +41,7 @@
update_leftpewarmrest()
/obj/structure/chair/pew/right
- name = "left wooden pew end"
+ name = "wooden pew end"
icon_state = "pewend_right"
var/mutable_appearance/rightpewarmrest
diff --git a/code/game/objects/structures/beds_chairs/sofa.dm b/code/game/objects/structures/beds_chairs/sofa.dm
new file mode 100644
index 0000000000..e138e4d314
--- /dev/null
+++ b/code/game/objects/structures/beds_chairs/sofa.dm
@@ -0,0 +1,52 @@
+/obj/structure/chair/sofa
+ name = "old ratty sofa"
+ icon_state = "sofamiddle"
+ icon = 'icons/obj/sofa.dmi'
+ buildstackamount = 1
+ var/mutable_appearance/armrest
+
+/obj/structure/chair/sofa/Initialize()
+ armrest = mutable_appearance(icon, "[icon_state]_armrest", ABOVE_MOB_LAYER)
+ return ..()
+
+/obj/structure/chair/sofa/post_buckle_mob(mob/living/M)
+ . = ..()
+ update_armrest()
+
+/obj/structure/chair/sofa/proc/update_armrest()
+ if(has_buckled_mobs())
+ add_overlay(armrest)
+ else
+ cut_overlay(armrest)
+
+/obj/structure/chair/sofa/post_unbuckle_mob()
+ . = ..()
+ update_armrest()
+
+/obj/structure/chair/sofa/left
+ icon_state = "sofaend_left"
+
+/obj/structure/chair/sofa/right
+ icon_state = "sofaend_right"
+
+/obj/structure/chair/sofa/corner
+ icon_state = "sofacorner"
+
+/obj/structure/chair/sofa/corner/handle_layer() //only the armrest/back of this chair should cover the mob.
+ return
+
+// Credit for the sprites goes to CEV Eris. The sprites were taken from Hyper Station and modified to fit with armrests which were also added.
+
+/obj/structure/chair/sofa/corp
+ name = "sofa"
+ desc = "Soft, cushy and cozy. These sofas reek of bland faceless corporatism, but they aren't old and ratty at least."
+ icon_state = "corp_sofamiddle"
+
+/obj/structure/chair/sofa/corp/left
+ icon_state = "corp_sofaend_left"
+
+/obj/structure/chair/sofa/corp/right
+ icon_state = "corp_sofaend_right"
+
+/obj/structure/chair/sofa/corp/corner
+ icon_state = "corp_sofacorner"
diff --git a/code/game/objects/structures/chess.dm b/code/game/objects/structures/chess.dm
new file mode 100644
index 0000000000..8254405fee
--- /dev/null
+++ b/code/game/objects/structures/chess.dm
@@ -0,0 +1,76 @@
+/obj/structure/chess
+ anchored = FALSE
+ density = FALSE
+ icon = 'icons/obj/chess.dmi'
+ icon_state = "singularity_s1"
+ name = "Singularity"
+ desc = "You've just been pranked by the Syndicate Chess Grandmaster! Report this to CentCom."
+ max_integrity = 100
+
+/obj/structure/chess/wrench_act(mob/user, obj/item/tool)
+ to_chat(user, "You take apart the chess piece.")
+ var/obj/item/stack/sheet/metal/M = new (drop_location(), 2)
+ M.add_fingerprint(user)
+ tool.play_tool_sound(src)
+ qdel(src)
+ return TRUE
+
+/obj/structure/chess/whitepawn
+ name = "\improper White Pawn"
+ desc = "A white pawn chess piece. Get accused of cheating when executing a sick En Passant."
+ icon_state = "white_pawn"
+
+/obj/structure/chess/whiterook
+ name = "\improper White Rook"
+ desc = "A white rook chess piece. Also known as a castle. Can move any number of tiles in a straight line. It has a special move called castling."
+ icon_state = "white_rook"
+
+/obj/structure/chess/whiteknight
+ name = "\improper White Knight"
+ desc = "A white knight chess piece. Hah. It can hop over other pieces, moving in L shapes."
+ icon_state = "white_knight"
+
+/obj/structure/chess/whitebishop
+ name = "\improper White Bishop"
+ desc = "A white bishop chess piece. It can move any number of tiles in a diagonal line."
+ icon_state = "white_bishop"
+
+/obj/structure/chess/whitequeen
+ name = "\improper White Queen"
+ desc = "A white queen chess piece. It can move any number of tiles in diagonal and straight lines."
+ icon_state = "white_queen"
+
+/obj/structure/chess/whiteking
+ name = "\improper White King"
+ desc = "A white king chess piece. It can move any tile in one direction."
+ icon_state = "white_king"
+
+/obj/structure/chess/blackpawn
+ name = "\improper Black Pawn"
+ desc = "A black pawn chess piece. Get accused of cheating when executing a sick En Passant."
+ icon_state = "black_pawn"
+
+/obj/structure/chess/blackrook
+ name = "\improper Black Rook"
+ desc = "A black rook chess piece. Also known as a castle. Can move any number of tiles in a straight line. It has a special move called castling."
+ icon_state = "black_rook"
+
+/obj/structure/chess/blackknight
+ name = "\improper Black Knight"
+ desc = "A black knight chess piece. It can hop over other pieces, moving in L shapes."
+ icon_state = "black_knight"
+
+/obj/structure/chess/blackbishop
+ name = "\improper Black Bishop"
+ desc = "A black bishop chess piece. It can move any number of tiles in a diagonal line."
+ icon_state = "black_bishop"
+
+/obj/structure/chess/blackqueen
+ name = "\improper Black Queen"
+ desc = "A black queen chess piece. It can move any number of tiles in diagonal and straight lines."
+ icon_state = "black_queen"
+
+/obj/structure/chess/blackking
+ name = "\improper Black King"
+ desc = "A black king chess piece. It can move one tile in any direction."
+ icon_state = "black_king"
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index f95f900a48..c932dd96e8 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -431,7 +431,7 @@
"You hear a loud metal bang.")
var/mob/living/L = O
if(!issilicon(L))
- L.Knockdown(40)
+ L.DefaultCombatKnockdown(40)
O.forceMove(T)
close()
else
@@ -474,8 +474,9 @@
set category = "Object"
set name = "Toggle Open"
- if(!usr.canmove || usr.stat || usr.restrained())
- return
+ var/mob/living/L = usr
+ if(!istype(L) || !CHECK_MOBILITY(L, MOBILITY_USE))
+ return FALSE
if(iscarbon(usr) || issilicon(usr) || isdrone(usr))
return attack_hand(usr)
@@ -510,7 +511,7 @@
user.visible_message("[src] begins to shake violently!", \
"You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)", \
"You hear banging from [src].")
- if(do_after(user,(breakout_time), target = src))
+ if(do_after(user,(breakout_time), target = src, required_mobility_flags = MOBILITY_RESIST))
if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) )
return
//we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting
@@ -603,12 +604,12 @@
step_towards(user, T2)
T1 = get_turf(user)
if(T1 == T2)
- user.resting = TRUE //so people can jump into crates without slamming the lid on their head
+ user.set_resting(TRUE, TRUE)
if(!close(user))
to_chat(user, "You can't get [src] to close!")
- user.resting = FALSE
+ user.set_resting(FALSE, TRUE)
return
- user.resting = FALSE
+ user.set_resting(FALSE, TRUE)
togglelock(user)
T1.visible_message("[user] dives into [src]!")
diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
index 645d1e5d7a..ae2e1a070a 100644
--- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
+++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
@@ -18,8 +18,8 @@
var/egged = 0
var/use_mob_movespeed = FALSE //Citadel adds snowflake box handling
-/obj/structure/closet/cardboard/relaymove(mob/user, direction)
- if(opened || move_delay || user.stat || user.IsStun() || user.IsKnockdown() || user.IsUnconscious() || !isturf(loc) || !has_gravity(loc))
+/obj/structure/closet/cardboard/relaymove(mob/living/user, direction)
+ if(opened || move_delay || !CHECK_MOBILITY(user, MOBILITY_MOVE) || !isturf(loc) || !has_gravity(loc))
return
move_delay = TRUE
var/oldloc = loc
diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm
index a5857029f5..fae3625ccc 100644
--- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm
@@ -216,7 +216,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/suit/toggle/labcoat(src)
for(var/i in 1 to 3)
- new /obj/item/clothing/suit/toggle/labcoat/emt(src)
+ new /obj/item/clothing/suit/toggle/labcoat/paramedic(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/white(src)
for(var/i in 1 to 3)
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index b14303984e..4f6d6729fc 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -83,9 +83,12 @@
desc = "It's a burial receptacle for the dearly departed."
icon_state = "coffin"
resistance_flags = FLAMMABLE
+ can_weld_shut = FALSE
+ breakout_time = 200
max_integrity = 70
material_drop = /obj/item/stack/sheet/mineral/wood
material_drop_amount = 5
+ var/pryLidTimer = 250
/obj/structure/closet/crate/coffin/examine(mob/user)
. = ..()
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index ebac89579b..05a7e1c958 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -139,7 +139,7 @@
src.visible_message(text("[M] falls free of [src]!"))
unbuckle_mob(M,force=1)
M.emote("scream")
- M.AdjustKnockdown(20)
+ M.DefaultCombatKnockdown(20)
/obj/structure/kitchenspike/Destroy()
if(has_buckled_mobs())
diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm
index df6d033af4..bdc7825feb 100644
--- a/code/game/objects/structures/musician.dm
+++ b/code/game/objects/structures/musician.dm
@@ -1,7 +1,7 @@
#define MUSICIAN_HEARCHECK_MINDELAY 4
#define MUSIC_MAXLINES 600
-#define MUSIC_MAXLINECHARS 50
+#define MUSIC_MAXLINECHARS 150
/datum/song
var/name = "Untitled"
@@ -82,7 +82,7 @@
/datum/song/proc/shouldStopPlaying(mob/user)
if(instrumentObj)
- if(!user.canUseTopic(instrumentObj))
+ if(!user.canUseTopic(instrumentObj, TRUE, FALSE, FALSE, FALSE))
return TRUE
return !instrumentObj.anchored // add special cases to stop in subclasses
else
@@ -220,7 +220,7 @@
updateDialog(usr) // make sure updates when complete
/datum/song/Topic(href, href_list)
- if(!usr.canUseTopic(instrumentObj))
+ if(!usr.canUseTopic(instrumentObj, TRUE, FALSE, FALSE, FALSE))
usr << browse(null, "window=instrument")
usr.unset_machine()
return
diff --git a/code/game/objects/structures/petrified_statue.dm b/code/game/objects/structures/petrified_statue.dm
index 65ffb7e2e5..a8a5a577c2 100644
--- a/code/game/objects/structures/petrified_statue.dm
+++ b/code/game/objects/structures/petrified_statue.dm
@@ -49,7 +49,7 @@
if(S.mind)
if(petrified_mob)
S.mind.transfer_to(petrified_mob)
- petrified_mob.Knockdown(100)
+ petrified_mob.DefaultCombatKnockdown(100)
to_chat(petrified_mob, "You slowly come back to your senses. You are in control of yourself again!")
qdel(S)
diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm
index e3cd053d94..7e2922279b 100644
--- a/code/game/objects/structures/table_frames.dm
+++ b/code/game/objects/structures/table_frames.dm
@@ -41,7 +41,7 @@
make_new_table(material.tableVariant)
else
if(material.get_amount() < 1)
- to_chat(user, "You need one metal sheet to do this!")
+ to_chat(user, "You need one sheet to do this!")
return
to_chat(user, "You start adding [material] to [src]...")
if(do_after(user, 20, target = src) && material.use(1))
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 4eba21b8f9..550c0216c6 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -109,8 +109,7 @@
/obj/structure/table/proc/tableplace(mob/living/user, mob/living/pushed_mob)
pushed_mob.forceMove(src.loc)
- pushed_mob.resting = TRUE
- pushed_mob.update_canmove()
+ pushed_mob.set_resting(TRUE, FALSE)
pushed_mob.visible_message("[user] places [pushed_mob] onto [src].", \
"[user] places [pushed_mob] onto [src].")
log_combat(user, pushed_mob, "placed")
@@ -128,7 +127,7 @@
pushed_mob.pass_flags &= ~PASSTABLE
if(pushed_mob.loc != loc) //Something prevented the tabling
return
- pushed_mob.Knockdown(40)
+ pushed_mob.DefaultCombatKnockdown(40)
pushed_mob.visible_message("[user] slams [pushed_mob] onto [src]!", \
"[user] slams you onto [src]!")
log_combat(user, pushed_mob, "tabled", null, "onto [src]")
@@ -138,11 +137,11 @@
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "table", /datum/mood_event/table)
/obj/structure/table/shove_act(mob/living/target, mob/living/user)
- if(!target.resting)
- target.Knockdown(SHOVE_KNOCKDOWN_TABLE)
+ if(CHECK_MOBILITY(target, MOBILITY_STAND))
+ target.DefaultCombatKnockdown(SHOVE_KNOCKDOWN_TABLE)
user.visible_message("[user.name] shoves [target.name] onto \the [src]!",
"You shove [target.name] onto \the [src]!", null, COMBAT_MESSAGE_RANGE)
- target.forceMove(src.loc)
+ target.forceMove(loc)
log_combat(user, target, "shoved", "onto [src] (table)")
return TRUE
@@ -212,7 +211,7 @@
/obj/structure/table/greyscale
icon = 'icons/obj/smooth_structures/table_greyscale.dmi'
icon_state = "table"
- material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
+ material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
buildstack = null //No buildstack, so generate from mat datums
/*
@@ -270,7 +269,7 @@
debris -= AM
if(istype(AM, /obj/item/shard))
AM.throw_impact(L)
- L.Knockdown(100)
+ L.DefaultCombatKnockdown(100)
qdel(src)
/obj/structure/table/glass/deconstruct(disassembled = TRUE, wrench_disassembly = 0)
@@ -568,23 +567,20 @@
break
/obj/structure/table/optable/tablepush(mob/living/user, mob/living/pushed_mob)
- pushed_mob.forceMove(src.loc)
- pushed_mob.resting = 1
- pushed_mob.update_canmove()
+ pushed_mob.forceMove(loc)
+ pushed_mob.set_resting(TRUE, TRUE)
visible_message("[user] has laid [pushed_mob] on [src].")
check_patient()
/obj/structure/table/optable/proc/check_patient()
- var/mob/M = locate(/mob/living/carbon/human, loc)
- if(M)
- if(M.resting)
- patient = M
- return 1
+ var/mob/living/carbon/human/H = locate() in loc
+ if(H)
+ if(!CHECK_MOBILITY(H, MOBILITY_STAND))
+ patient = H
+ return TRUE
else
patient = null
- return 0
-
-
+ return FALSE
/*
* Racks
@@ -644,7 +640,7 @@
. = ..()
if(.)
return
- if(user.IsKnockdown() || user.resting || user.lying || user.get_num_legs() < 2)
+ if(CHECK_MULTIPLE_BITFIELDS(user.mobility_flags, MOBILITY_STAND|MOBILITY_MOVE) || user.get_num_legs() < 2)
return
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src, ATTACK_EFFECT_KICK)
diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm
index c386726f34..17ca178cd9 100644
--- a/code/game/objects/structures/transit_tubes/station.dm
+++ b/code/game/objects/structures/transit_tubes/station.dm
@@ -43,10 +43,10 @@
//pod insertion
-/obj/structure/transit_tube/station/MouseDrop_T(obj/structure/c_transit_tube_pod/R, mob/user)
- if(!user.canmove || user.stat || user.restrained())
+/obj/structure/transit_tube/station/MouseDrop_T(obj/structure/c_transit_tube_pod/R, mob/living/user)
+ if(!istype(user) || !CHECK_MOBILITY(user, MOBILITY_USE))
return
- if (!istype(R) || get_dist(user, src) > 1 || get_dist(src,R) > 1)
+ if(!istype(R) || get_dist(user, src) > 1 || get_dist(src,R) > 1)
return
for(var/obj/structure/transit_tube_pod/pod in loc)
return //no fun allowed
@@ -74,7 +74,7 @@
pod.visible_message("[user] starts putting [GM] into the [pod]!")
if(do_after(user, 15, target = src))
if(open_status == STATION_TUBE_OPEN && GM && user.grab_state >= GRAB_AGGRESSIVE && user.pulling == GM && !GM.buckled && !GM.has_buckled_mobs())
- GM.Knockdown(100)
+ GM.DefaultCombatKnockdown(100)
src.Bumped(GM)
break
else
diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm
index 3f559382f0..fa9c052aa3 100644
--- a/code/game/objects/structures/traps.dm
+++ b/code/game/objects/structures/traps.dm
@@ -83,7 +83,7 @@
/obj/structure/trap/stun/trap_effect(mob/living/L)
L.electrocute_act(30, src, safety=1) // electrocute act does a message.
- L.Knockdown(100)
+ L.DefaultCombatKnockdown(100)
/obj/structure/trap/fire
name = "flame trap"
@@ -92,7 +92,7 @@
/obj/structure/trap/fire/trap_effect(mob/living/L)
to_chat(L, "Spontaneous combustion!")
- L.Knockdown(20)
+ L.DefaultCombatKnockdown(20)
/obj/structure/trap/fire/flare()
..()
@@ -106,7 +106,7 @@
/obj/structure/trap/chill/trap_effect(mob/living/L)
to_chat(L, "You're frozen solid!")
- L.Knockdown(20)
+ L.DefaultCombatKnockdown(20)
L.adjust_bodytemperature(-300)
L.apply_status_effect(/datum/status_effect/freon)
@@ -119,7 +119,7 @@
/obj/structure/trap/damage/trap_effect(mob/living/L)
to_chat(L, "The ground quakes beneath your feet!")
- L.Knockdown(100)
+ L.DefaultCombatKnockdown(100)
L.adjustBruteLoss(35)
/obj/structure/trap/damage/flare()
@@ -147,7 +147,7 @@
/obj/structure/trap/cult/trap_effect(mob/living/L)
to_chat(L, "With a crack, the hostile constructs come out of hiding, stunning you!")
L.electrocute_act(10, src, safety = TRUE) // electrocute act does a message.
- L.Knockdown(20)
+ L.DefaultCombatKnockdown(20)
new /mob/living/simple_animal/hostile/construct/proteon/hostile(loc)
new /mob/living/simple_animal/hostile/construct/proteon/hostile(loc)
- QDEL_IN(src, 30)
\ No newline at end of file
+ QDEL_IN(src, 30)
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 359436dc2e..78df9b5d57 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -444,9 +444,6 @@
C.adjustFireLoss(5)
to_chat(C, "The water is searing!")
-
-
-
/obj/item/bikehorn/rubberducky
name = "rubber ducky"
desc = "Rubber ducky you're so fine, you make bathtime lots of fuuun. Rubber ducky I'm awfully fooooond of yooooouuuu~" //thanks doohl
@@ -454,8 +451,6 @@
icon_state = "rubberducky"
item_state = "rubberducky"
-
-
/obj/structure/sink
name = "sink"
icon = 'icons/obj/watercloset.dmi'
@@ -465,7 +460,6 @@
var/busy = FALSE //Something's being washed at the moment
var/dispensedreagent = /datum/reagent/water // for whenever plumbing happens
-
/obj/structure/sink/attack_hand(mob/living/user)
. = ..()
if(.)
@@ -529,7 +523,7 @@
if(B.cell.charge > 0 && B.status == 1)
flick("baton_active", src)
var/stunforce = B.stamforce
- user.Knockdown(stunforce * 2)
+ user.DefaultCombatKnockdown(stunforce * 2)
user.stuttering = stunforce/20
B.deductcharge(B.hitcost)
user.visible_message("[user] shocks [user.p_them()]self while attempting to wash the active [B.name]!", \
@@ -578,12 +572,82 @@
new /obj/item/stack/sheet/metal (loc, 3)
qdel(src)
-
-
/obj/structure/sink/kitchen
name = "kitchen sink"
icon_state = "sink_alt"
+/obj/structure/sink/well
+ name = "well"
+ desc = "A well, used to get water from an underground reservoir."
+ icon_state = "well"
+
+//The making of the well
+/obj/structure/well_foundation
+ name = "well foundation"
+ desc = "A small patch of dirt, ready for a well to be made over it. Just use a shovel!"
+ icon = 'icons/obj/watercloset.dmi'
+ icon_state = "well_1"
+ density = FALSE
+ anchored = TRUE
+ max_integrity = 1000
+ var/steps = 0
+
+/obj/structure/well_foundation/attackby(obj/item/S, mob/user, params)
+ if(steps == 0 && S.tool_behaviour == TOOL_SHOVEL)
+ S.use_tool(src, user, 80, volume=100)
+ steps = 1
+ desc = "A deep patch of dirt, ready for a well to be made over it. Just add some sandstone!"
+ icon_state = "well_1"
+ return TRUE
+ if(steps == 1 && istype(S, /obj/item/stack/sheet/mineral/sandstone))
+ if(S.use(15))
+ steps = 2
+ desc = "A patch of dirt and bricks. Just add some more sandstone!"
+ icon_state = "well_2"
+ return TRUE
+ else
+ to_chat(user, "You need at least fifteen pieces of sandstone!")
+ return
+ if(steps == 2 && istype(S, /obj/item/stack/sheet/mineral/sandstone))
+ if(S.use(25))
+ steps = 3
+ desc = "A large well foundation ready to be dug out. Just use a shovel!"
+ icon_state = "well_3"
+ return TRUE
+ else
+ to_chat(user, "You need at least tweenty-five pieces of sandstone!")
+ return
+ if(steps == 3 && S.tool_behaviour == TOOL_SHOVEL)
+ S.use_tool(src, user, 80, volume=100)
+ steps = 4
+ desc = "A deep patch of dirt, needs something to hold a bucket and rope. Just add some wood planks!"
+ icon_state = "well_3"
+ return TRUE
+ if(steps == 4 && istype(S, /obj/item/stack/sheet/mineral/wood))
+ if(S.use(3))
+ steps = 5
+ desc = "A dug out well, A dug out well with out rope. Just add some cloth!"
+ icon_state = "well_4"
+ return TRUE
+ else
+ to_chat(user, "You need at least three planks!")
+ return
+ if(steps == 5 && istype(S, /obj/item/stack/sheet/cloth))
+ if(S.use(2))
+ steps = 6
+ desc = "A dug out well with a rope. Just add a wooden bucket!"
+ icon_state = "well_5"
+ return TRUE
+ else
+ to_chat(user, "You need at least two pieces of cloth!")
+ return
+ if(steps == 6 && istype(S, /obj/item/reagent_containers/glass/bucket/wood))
+ new /obj/structure/sink/well(loc)
+ qdel(S)
+ qdel(src)
+ return
+ else
+ return ..()
/obj/structure/sink/puddle //splishy splashy ^_^
name = "puddle"
@@ -616,9 +680,10 @@
icon = 'icons/obj/watercloset.dmi'
icon_state = "open"
color = "#ACD1E9" //Default color, didn't bother hardcoding other colors, mappers can and should easily change it.
- alpha = 200 //Mappers can also just set this to 255 if they want curtains that can't be seen through
+ alpha = 200 //Mappers can also just set this to 255 if they want curtains that can't be seen through <- No longer necessary unless you don't want to see through it no matter what.
layer = SIGN_LAYER
anchored = TRUE
+ max_integrity = 25 //This makes cloth shower curtains as durable as a directional glass window. 300 integrity buildable shower curtains as a cover mechanic is a meta I don't want to see.
opacity = 0
density = FALSE
var/open = TRUE
@@ -633,12 +698,14 @@
layer = WALL_OBJ_LAYER
density = TRUE
open = FALSE
+ opacity = TRUE
else
icon_state = "open"
layer = SIGN_LAYER
density = FALSE
open = TRUE
+ opacity = FALSE
/obj/structure/curtain/attackby(obj/item/W, mob/user)
if (istype(W, /obj/item/toy/crayon))
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index 7f039598cf..e824567b50 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -343,7 +343,8 @@
set name = "Flip Windoor Assembly"
set category = "Object"
set src in oview(1)
- if(usr.stat || !usr.canmove || usr.restrained())
+ var/mob/living/L = usr
+ if(!CHECK_MOBILITY(L, MOBILITY_PULL))
return
if(facing == "l")
@@ -354,4 +355,3 @@
to_chat(usr, "The windoor will now slide to the left.")
update_icon()
- return
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 11e026109a..c285026d5b 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -1,7 +1,6 @@
/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, soundenvwet = -10000, soundenvdry = 0)
if(isarea(source))
- throw EXCEPTION("playsound(): source is an area")
- return
+ CRASH("playsound(): source is an area")
var/turf/turf_source = get_turf(source)
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index c4c7ab2d7b..066249505d 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -272,7 +272,7 @@
var/olddir = C.dir
if(!(lube & SLIDE_ICE))
- C.Knockdown(knockdown_amount)
+ C.DefaultCombatKnockdown(knockdown_amount)
C.stop_pulling()
else
C.Stun(20)
diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm
index 3a474f339c..dd2b9dfa18 100644
--- a/code/game/turfs/simulated/lava.dm
+++ b/code/game/turfs/simulated/lava.dm
@@ -23,6 +23,10 @@
/turf/open/lava/MakeSlippery(wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent)
return
+/turf/open/lava/Melt()
+ to_be_destroyed = FALSE
+ return src
+
/turf/open/lava/acid_act(acidpwr, acid_volume)
return
diff --git a/code/game/turfs/simulated/river.dm b/code/game/turfs/simulated/river.dm
index 83fade33b2..c8ea60c712 100644
--- a/code/game/turfs/simulated/river.dm
+++ b/code/game/turfs/simulated/river.dm
@@ -6,7 +6,7 @@
#define RIVERGEN_SAFETY_LOCK 1000000
-/proc/spawn_rivers(target_z, nodes = 4, turf_type = /turf/open/lava/smooth/lava_land_surface, whitelist_area = /area/lavaland/surface/outdoors/unexplored, min_x = RANDOM_LOWER_X, min_y = RANDOM_LOWER_Y, max_x = RANDOM_UPPER_X, max_y = RANDOM_UPPER_Y)
+/proc/spawn_rivers(target_z, nodes = 4, turf_type = /turf/open/lava/smooth/lava_land_surface, whitelist_area = /area/lavaland/surface/outdoors/unexplored, min_x = RANDOM_LOWER_X, min_y = RANDOM_LOWER_Y, max_x = RANDOM_UPPER_X, max_y = RANDOM_UPPER_Y, new_baseturfs)
var/list/river_nodes = list()
var/num_spawned = 0
var/list/possible_locs = block(locate(min_x, min_y, target_z), locate(max_x, max_y, target_z))
@@ -28,7 +28,7 @@
continue
W.connected = 1
var/turf/cur_turf = get_turf(W)
- cur_turf.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR)
+ cur_turf.ChangeTurf(turf_type, new_baseturfs, CHANGETURF_IGNORE_AIR)
var/turf/target_turf = get_turf(pick(river_nodes - W))
if(!target_turf)
break
@@ -57,7 +57,7 @@
cur_turf = get_step(cur_turf, cur_dir)
continue
else
- var/turf/river_turf = cur_turf.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR)
+ var/turf/river_turf = cur_turf.ChangeTurf(turf_type, new_baseturfs, CHANGETURF_IGNORE_AIR)
river_turf.Spread(25, 11, whitelist_area)
for(var/WP in river_nodes)
@@ -93,16 +93,16 @@
for(var/F in cardinal_turfs) //cardinal turfs are always changed but don't always spread
var/turf/T = F
- if(!istype(T, logged_turf_type) && T.ChangeTurf(type, null, CHANGETURF_IGNORE_AIR) && prob(probability))
+ if(!istype(T, logged_turf_type) && T.ChangeTurf(type, baseturfs, CHANGETURF_IGNORE_AIR) && prob(probability))
T.Spread(probability - prob_loss, prob_loss, whitelisted_area)
for(var/F in diagonal_turfs) //diagonal turfs only sometimes change, but will always spread if changed
var/turf/T = F
- if(!istype(T, logged_turf_type) && prob(probability) && T.ChangeTurf(type, null, CHANGETURF_IGNORE_AIR))
+ if(!istype(T, logged_turf_type) && prob(probability) && T.ChangeTurf(type, baseturfs, CHANGETURF_IGNORE_AIR))
T.Spread(probability - prob_loss, prob_loss, whitelisted_area)
else if(ismineralturf(T))
var/turf/closed/mineral/M = T
- M.ChangeTurf(M.turf_type, null, CHANGETURF_IGNORE_AIR)
+ M.ChangeTurf(M.turf_type, M.baseturfs, CHANGETURF_IGNORE_AIR)
#undef RANDOM_UPPER_X
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index b5127929a7..ef4abeb0ad 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -23,8 +23,7 @@ GLOBAL_PROTECT(protected_ranks)
name = init_name
if(!name)
qdel(src)
- throw EXCEPTION("Admin rank created without name.")
- return
+ CRASH("Admin rank created without name.")
if(init_rights)
rights = init_rights
include_rights = rights
diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm
index 37fe2a41fc..1d0b6b2a79 100644
--- a/code/modules/admin/holder2.dm
+++ b/code/modules/admin/holder2.dm
@@ -39,12 +39,10 @@ GLOBAL_PROTECT(href_token)
return
if(!ckey)
QDEL_IN(src, 0)
- throw EXCEPTION("Admin datum created without a ckey")
- return
+ CRASH("Admin datum created without a ckey")
if(!istype(R))
QDEL_IN(src, 0)
- throw EXCEPTION("Admin datum created without a rank")
- return
+ CRASH("Admin datum created without a rank")
target = ckey
name = "[ckey]'s admin datum ([R])"
rank = R
diff --git a/code/modules/admin/verbs/bluespacearty.dm b/code/modules/admin/verbs/bluespacearty.dm
index 97248b572b..2910d6dd85 100644
--- a/code/modules/admin/verbs/bluespacearty.dm
+++ b/code/modules/admin/verbs/bluespacearty.dm
@@ -21,6 +21,6 @@
target.gib(1, 1)
else
target.adjustBruteLoss(min(99,(target.health - 1)))
- target.Knockdown(400)
+ target.DefaultCombatKnockdown(400)
target.stuttering = 20
diff --git a/code/modules/admin/verbs/borgpanel.dm b/code/modules/admin/verbs/borgpanel.dm
index c0445d588d..8cfd53b300 100644
--- a/code/modules/admin/verbs/borgpanel.dm
+++ b/code/modules/admin/verbs/borgpanel.dm
@@ -47,7 +47,7 @@
"emagged" = borg.emagged,
"active_module" = "[borg.module.type]",
"lawupdate" = borg.lawupdate,
- "lockdown" = borg.lockcharge,
+ "lockdown" = borg.locked_down,
"scrambledcodes" = borg.scrambledcodes
)
.["upgrades"] = list()
@@ -122,8 +122,8 @@
message_admins("[key_name_admin(user)] disabled lawsync on [ADMIN_LOOKUPFLW(borg)].")
log_admin("[key_name(user)] disabled lawsync on [key_name(borg)].")
if ("toggle_lockdown")
- borg.SetLockdown(!borg.lockcharge)
- if (borg.lockcharge)
+ borg.SetLockdown(!borg.locked_down)
+ if (borg.locked_down)
message_admins("[key_name_admin(user)] locked down [ADMIN_LOOKUPFLW(borg)].")
log_admin("[key_name(user)] locked down [key_name(borg)].")
else
diff --git a/code/modules/antagonists/_common/antag_team.dm b/code/modules/antagonists/_common/antag_team.dm
index 027abc7c94..653853cfb5 100644
--- a/code/modules/antagonists/_common/antag_team.dm
+++ b/code/modules/antagonists/_common/antag_team.dm
@@ -4,6 +4,7 @@
var/name = "team"
var/member_name = "member"
var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes.
+ var/show_roundend_report = TRUE
/datum/team/New(starting_members)
. = ..()
@@ -25,6 +26,8 @@
//Display members/victory/failure/objectives for the team
/datum/team/proc/roundend_report()
+ if(!show_roundend_report)
+ return
var/list/report = list()
report += ""
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index 332329a221..c2a3f953f5 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -116,14 +116,13 @@
var/mob/living/carbon/human/M = loc
M.adjustStaminaLoss(-75)
M.SetUnconscious(0)
- M.SetStun(0)
- M.SetKnockdown(0)
+ M.SetAllImmobility(0)
combat_cooldown = 0
START_PROCESSING(SSobj, src)
/obj/item/clothing/suit/armor/abductor/vest/process()
combat_cooldown++
- if(combat_cooldown==initial(combat_cooldown))
+ if(combat_cooldown == initial(combat_cooldown))
STOP_PROCESSING(SSobj, src)
/obj/item/clothing/suit/armor/abductor/Destroy()
@@ -512,7 +511,7 @@
L.lastattackerckey = user.ckey
L.adjustStaminaLoss(35) //because previously it took 5-6 hits to actually "incapacitate" someone for the purposes of the sleep inducement
- L.Knockdown(140)
+ L.DefaultCombatKnockdown(140)
L.apply_effect(EFFECT_STUTTER, 7)
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
diff --git a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
index 182fcea0c2..261677a74b 100644
--- a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
+++ b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
@@ -218,11 +218,16 @@
/mob/living/simple_animal/hostile/blob/blobbernaut/Initialize()
. = ..()
- if(!independent) //no pulling people deep into the blob
- verbs -= /mob/living/verb/pulled
- else
+ if(independent)
pass_flags &= ~PASSBLOB
+/mob/living/simple_animal/hostile/blob/blobbernaut/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE)
+ if(!independent && ismob(AM))
+ if(!supress_message)
+ to_chat(src, "You are unable to grasp people in this form.")
+ return FALSE
+ return ..()
+
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
if(..())
var/list/blobs_in_area = range(2, src)
diff --git a/code/modules/antagonists/blob/blob/overmind.dm b/code/modules/antagonists/blob/blob/overmind.dm
index fe1c700014..18e13118fe 100644
--- a/code/modules/antagonists/blob/blob/overmind.dm
+++ b/code/modules/antagonists/blob/blob/overmind.dm
@@ -157,6 +157,9 @@ GLOBAL_LIST_EMPTY(blob_nodes)
BM.overmind = null
BM.update_icons()
GLOB.overminds -= src
+ blob_mobs = null
+ resource_blobs = null
+ blobs_legit = null
SSshuttle.clearHostileEnvironment(src)
diff --git a/code/modules/antagonists/blob/blob/theblob.dm b/code/modules/antagonists/blob/blob/theblob.dm
index 953b876b35..fc78f859f2 100644
--- a/code/modules/antagonists/blob/blob/theblob.dm
+++ b/code/modules/antagonists/blob/blob/theblob.dm
@@ -303,8 +303,7 @@
/obj/structure/blob/proc/change_to(type, controller)
if(!ispath(type))
- throw EXCEPTION("change_to(): invalid type for blob")
- return
+ CRASH("change_to(): invalid type for blob")
var/obj/structure/blob/B = new type(src.loc, controller)
B.creation_action()
B.update_icon()
diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
index 0179c60ef1..e774cf4250 100644
--- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
+++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
@@ -315,7 +315,7 @@
bloodsuckerdatum.handle_eat_human_food(food_nutrition)
-/datum/antagonist/bloodsucker/proc/handle_eat_human_food(var/food_nutrition) // Called from snacks.dm and drinks.dm
+/datum/antagonist/bloodsucker/proc/handle_eat_human_food(food_nutrition, puke_blood = TRUE, masquerade_override) // Called from snacks.dm and drinks.dm
set waitfor = FALSE
if(!owner.current || !iscarbon(owner.current))
return
@@ -324,14 +324,14 @@
C.nutrition -= food_nutrition
foodInGut += food_nutrition
// Already ate some bad clams? Then we can back out, because we're already sick from it.
- if (foodInGut != food_nutrition)
+ if(foodInGut != food_nutrition)
return
// Haven't eaten, but I'm in a Human Disguise.
- else if (poweron_masquerade)
+ else if(poweron_masquerade && !masquerade_override)
to_chat(C, "Your stomach turns, but your \"human disguise\" keeps the food down...for now.")
// Keep looping until we purge. If we have activated our Human Disguise, we ignore the food. But it'll come up eventually...
var/sickphase = 0
- while (foodInGut)
+ while(foodInGut)
sleep(50)
C.adjust_disgust(10 * sickphase)
// Wait an interval...
@@ -340,24 +340,29 @@
if(C.stat == DEAD)
return
// Put up disguise? Then hold off the vomit.
- if(poweron_masquerade)
+ if(poweron_masquerade && !masquerade_override)
if(sickphase > 0)
to_chat(C, "Your stomach settles temporarily. You regain your composure...for now.")
sickphase = 0
continue
switch(sickphase)
- if (1)
+ if(1)
to_chat(C, "You feel unwell. You can taste ash on your tongue.")
C.Stun(10)
- if (2)
+ if(2)
to_chat(C, "Your stomach turns. Whatever you ate tastes of grave dirt and brimstone.")
C.Dizzy(15)
C.Stun(13)
- if (3)
+ if(3)
to_chat(C, "You purge the food of the living from your viscera! You've never felt worse.")
- C.vomit(foodInGut * 4, foodInGut * 2, 0) // (var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1, var/toxic = 0)
- C.blood_volume = max(0, C.blood_volume - foodInGut * 2)
+ //Puke blood only if puke_blood is true, and loose some blood, else just puke normally.
+ if(puke_blood)
+ C.blood_volume = max(0, C.blood_volume - foodInGut * 2)
+ C.vomit(foodInGut * 4, foodInGut * 2, 0)
+ else
+ C.vomit(foodInGut * 4, FALSE, 0)
C.Stun(30)
//C.Dizzy(50)
foodInGut = 0
+ SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "vampdisgust", /datum/mood_event/bloodsucker_disgust)
sickphase ++
diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm
index 626ad43b10..507e1f2739 100644
--- a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm
+++ b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm
@@ -96,7 +96,7 @@
// Incap?
if(must_be_capacitated)
var/mob/living/L = owner
- if (L.incapacitated(TRUE, TRUE) || L.resting && !can_be_immobilized)
+ if (L.incapacitated(TRUE, TRUE) || !CHECK_MOBILITY(L, MOBILITY_STAND) && !can_be_immobilized)
if(display_error)
to_chat(owner, "Not while you're incapacitated!")
return FALSE
diff --git a/code/modules/antagonists/bloodsucker/items/bloodsucker_stake.dm b/code/modules/antagonists/bloodsucker/items/bloodsucker_stake.dm
index b7c90523b6..b69b851990 100644
--- a/code/modules/antagonists/bloodsucker/items/bloodsucker_stake.dm
+++ b/code/modules/antagonists/bloodsucker/items/bloodsucker_stake.dm
@@ -1,9 +1,5 @@
-
-
// organ_internal.dm -- /obj/item/organ
-
-
// Do I have a stake in my heart?
/mob/living/AmStaked()
var/obj/item/bodypart/BP = get_bodypart("chest")
@@ -13,16 +9,14 @@
if (istype(I,/obj/item/stake/))
return TRUE
return FALSE
+
/mob/proc/AmStaked()
return FALSE
-
/mob/living/proc/StakeCanKillMe()
return IsSleeping() || stat >= UNCONSCIOUS || blood_volume <= 0 || HAS_TRAIT(src, TRAIT_DEATHCOMA) // NOTE: You can't go to sleep in a coffin with a stake in you.
-
-///obj/item/weapon/melee/stake
-/obj/item/stake/
+/obj/item/stake
name = "wooden stake"
desc = "A simple wooden stake carved to a sharp point."
icon = 'icons/obj/items_and_weapons.dmi'
@@ -112,8 +106,7 @@
// Can this target be staked? If someone stands up before this is complete, it fails. Best used on someone stationary.
/mob/living/carbon/proc/can_be_staked()
- //return resting || IsKnockdown() || IsUnconscious() || (stat && (stat != SOFT_CRIT || pulledby)) || (has_trait(TRAIT_FAKEDEATH)) || resting || IsStun() || IsFrozen() || (pulledby && pulledby.grab_state >= GRAB_NECK)
- return (resting || lying || IsUnconscious() || pulledby && pulledby.grab_state >= GRAB_NECK)
+ return !CHECK_MOBILITY(src, MOBILITY_STAND)
// ABOVE: Taken from update_mobility() in living.dm
/obj/item/stake/hardened
diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm
index a25244c48d..debeee3775 100644
--- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm
+++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm
@@ -42,25 +42,18 @@
/obj/structure/closet/crate
var/mob/living/resident // This lets bloodsuckers claim any "closet" as a Coffin, so long as they could get into it and close it. This locks it in place, too.
-/obj/structure/closet/crate/coffin
- var/pryLidTimer = 250
- can_weld_shut = FALSE
- breakout_time = 200
-
-
/obj/structure/closet/crate/coffin/blackcoffin
name = "black coffin"
desc = "For those departed who are not so dear."
icon_state = "coffin"
icon = 'icons/obj/vamp_obj.dmi'
- can_weld_shut = FALSE
- resistance_flags = 0 // Start off with no bonuses.
open_sound = 'sound/bloodsucker/coffin_open.ogg'
close_sound = 'sound/bloodsucker/coffin_close.ogg'
breakout_time = 600
pryLidTimer = 400
resistance_flags = NONE
- integrity_failure = 70
+ max_integrity = 100
+ integrity_failure = 0.5
armor = list("melee" = 50, "bullet" = 20, "laser" = 30, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
/obj/structure/closet/crate/coffin/meatcoffin
@@ -68,8 +61,6 @@
desc = "When you're ready to meat your maker, the steaks can never be too high."
icon_state = "meatcoffin"
icon = 'icons/obj/vamp_obj.dmi'
- can_weld_shut = FALSE
- resistance_flags = 0 // Start off with no bonuses.
open_sound = 'sound/effects/footstep/slime1.ogg'
close_sound = 'sound/effects/footstep/slime1.ogg'
breakout_time = 200
@@ -77,24 +68,23 @@
resistance_flags = NONE
material_drop = /obj/item/reagent_containers/food/snacks/meat/slab
material_drop_amount = 3
- integrity_failure = 40
+ integrity_failure = 0.57
armor = list("melee" = 70, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 100)
-
+
/obj/structure/closet/crate/coffin/metalcoffin
name = "metal coffin"
desc = "A big metal sardine can inside of another big metal sardine can, in space."
icon_state = "metalcoffin"
icon = 'icons/obj/vamp_obj.dmi'
- can_weld_shut = FALSE
resistance_flags = FIRE_PROOF | LAVA_PROOF
open_sound = 'sound/effects/pressureplate.ogg'
close_sound = 'sound/effects/pressureplate.ogg'
breakout_time = 300
pryLidTimer = 200
- resistance_flags = NONE
material_drop = /obj/item/stack/sheet/metal
material_drop_amount = 5
- integrity_failure = 60
+ max_integrity = 200
+ integrity_failure = 0.25
armor = list("melee" = 40, "bullet" = 15, "laser" = 50, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
//////////////////////////////////////////////
diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm
index 9e46203483..db286dd6fe 100644
--- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm
+++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm
@@ -205,7 +205,7 @@
buckled_mob.pixel_y = buckled_mob.get_standard_pixel_y_offset(180)
src.visible_message(text("[buckled_mob][buckled_mob.stat==DEAD?"'s corpse":""] slides off of the rack."))
density = FALSE
- buckled_mob.AdjustKnockdown(30)
+ buckled_mob.DefaultCombatKnockdown(30)
update_icon()
useLock = FALSE // Failsafe
diff --git a/code/modules/antagonists/bloodsucker/powers/brawn.dm b/code/modules/antagonists/bloodsucker/powers/brawn.dm
index 712a15dff9..cf0393ff3a 100644
--- a/code/modules/antagonists/bloodsucker/powers/brawn.dm
+++ b/code/modules/antagonists/bloodsucker/powers/brawn.dm
@@ -72,8 +72,7 @@
if(rand(5 + powerlevel) >= 5)
target.visible_message("[user] lands a vicious punch, sending [target] away!", \
"[user] has landed a horrifying punch on you, sending you flying!!", null, COMBAT_MESSAGE_RANGE)
- target.Knockdown(min(5, rand(10, 10 * powerlevel)) )
-
+ target.DefaultCombatKnockdown(min(5, rand(10, 10 * powerlevel)) )
// Attack!
playsound(get_turf(target), 'sound/weapons/punch4.ogg', 60, 1, -1)
user.do_attack_animation(target, ATTACK_EFFECT_SMASH)
@@ -145,7 +144,7 @@
// Knock Down (if Living)
if (isliving(M))
var/mob/living/L = M
- L.Knockdown(pull_power * 10 + 20)
+ L.DefaultCombatKnockdown(pull_power * 10 + 20)
// Knock Back (before Knockdown, which probably cancels pull)
var/send_dir = get_dir(owner, M)
var/turf/T = get_ranged_target_turf(M, send_dir, pull_power)
diff --git a/code/modules/antagonists/bloodsucker/powers/cloak.dm b/code/modules/antagonists/bloodsucker/powers/cloak.dm
index 23b35d1eaa..1bb7b02357 100644
--- a/code/modules/antagonists/bloodsucker/powers/cloak.dm
+++ b/code/modules/antagonists/bloodsucker/powers/cloak.dm
@@ -10,6 +10,7 @@
amToggle = TRUE
warn_constant_cost = TRUE
var/moveintent_was_run
+ var/runintent
var/walk_threshold = 0.4 // arbitrary number, to be changed. edit in last commit: this is fine after testing on box station for a bit
var/lum
@@ -31,23 +32,25 @@
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
var/mob/living/user = owner
+ moveintent_was_run = (user.m_intent == MOVE_INTENT_RUN)
+
while(bloodsuckerdatum && ContinueActive(user))
// Pay Blood Toll (if awake)
owner.alpha = max(35, owner.alpha - min(75, 10 + 5 * level_current))
bloodsuckerdatum.AddBloodVolume(-0.2)
- moveintent_was_run = (user.m_intent == MOVE_INTENT_RUN)
+ runintent = (user.m_intent == MOVE_INTENT_RUN)
var/turf/T = get_turf(user)
lum = T.get_lumcount()
if(istype(owner.loc))
if(lum > walk_threshold)
- if(moveintent_was_run)
+ if(runintent)
user.toggle_move_intent()
ADD_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness")
if(lum < walk_threshold)
- if(!moveintent_was_run)
+ if(!runintent)
user.toggle_move_intent()
REMOVE_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness")
@@ -65,5 +68,8 @@
..()
REMOVE_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness")
user.alpha = 255
- if(!moveintent_was_run)
+
+ runintent = (user.m_intent == MOVE_INTENT_RUN)
+
+ if(!runintent && moveintent_was_run)
user.toggle_move_intent()
diff --git a/code/modules/antagonists/bloodsucker/powers/feed.dm b/code/modules/antagonists/bloodsucker/powers/feed.dm
index f9ff31d94a..bbce221d91 100644
--- a/code/modules/antagonists/bloodsucker/powers/feed.dm
+++ b/code/modules/antagonists/bloodsucker/powers/feed.dm
@@ -306,7 +306,7 @@
// Bloodsuckers not affected by "the Kiss" of another vampire
if(!target.mind || !target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
target.Unconscious(50,0)
- target.Knockdown(40 + 5 * level_current,1)
+ target.DefaultCombatKnockdown(40 + 5 * level_current,1)
// NOTE: THis is based on level of power!
if(ishuman(target))
target.adjustStaminaLoss(5, forced = TRUE)// Base Stamina Damage
@@ -321,4 +321,4 @@
// My mouth is no longer full
REMOVE_TRAIT(owner, TRAIT_MUTE, "bloodsucker_feed")
// Let me move immediately
- user.update_canmove()
+ user.update_mobility()
diff --git a/code/modules/antagonists/bloodsucker/powers/go_home.dm b/code/modules/antagonists/bloodsucker/powers/go_home.dm
index 3fa8a07299..4788d7639e 100644
--- a/code/modules/antagonists/bloodsucker/powers/go_home.dm
+++ b/code/modules/antagonists/bloodsucker/powers/go_home.dm
@@ -100,8 +100,8 @@
var/mob/living/simple_animal/SA = pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
new SA (owner.loc)
// TELEPORT: Move to Coffin & Close it!
+ user.set_resting(TRUE, TRUE, FALSE)
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM)
- user.resting = TRUE
user.Stun(30,1)
// CLOSE LID: If fail, force me in.
if(!bloodsuckerdatum.coffin.close(owner))
diff --git a/code/modules/antagonists/bloodsucker/powers/haste.dm b/code/modules/antagonists/bloodsucker/powers/haste.dm
index 47c93b794e..143950b32f 100644
--- a/code/modules/antagonists/bloodsucker/powers/haste.dm
+++ b/code/modules/antagonists/bloodsucker/powers/haste.dm
@@ -76,16 +76,17 @@
sleep(speed)
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
hit = null
- user.update_canmove()
+ user.update_mobility()
/datum/action/bloodsucker/targeted/haste/DeactivatePower(mob/living/user = owner, mob/living/target)
..() // activate = FALSE
- user.update_canmove()
+ user.update_mobility()
/datum/action/bloodsucker/targeted/haste/proc/on_move()
for(var/mob/living/L in dview(1, get_turf(owner)))
if(!hit[L] && (L != owner))
hit[L] = TRUE
playsound(L, "sound/weapons/punch[rand(1,4)].ogg", 15, 1, -1)
- L.Knockdown(10 + level_current * 5, override_hardstun = 0.1)
+ L.DefaultCombatKnockdown(10 + level_current * 5)
+ L.Paralyze(0.1)
L.spin(10, 1)
diff --git a/code/modules/antagonists/bloodsucker/powers/lunge.dm b/code/modules/antagonists/bloodsucker/powers/lunge.dm
index c3a3090d55..cc9363bbaf 100644
--- a/code/modules/antagonists/bloodsucker/powers/lunge.dm
+++ b/code/modules/antagonists/bloodsucker/powers/lunge.dm
@@ -7,7 +7,7 @@
button_icon_state = "power_lunge"
bloodcost = 10
cooldown = 120
- target_range = 5
+ target_range = 3
power_activates_immediately = TRUE
message_Trigger = "Whom will you ensnare within your grasp?"
must_be_capacitated = TRUE
@@ -52,6 +52,7 @@
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
var/mob/living/carbon/target = A
var/turf/T = get_turf(target)
+ var/mob/living/L = owner
// Clear Vars
owner.pulling = null
// Will we Knock them Down?
@@ -61,9 +62,9 @@
addtimer(CALLBACK(owner, .proc/_walk, 0), 2 SECONDS)
target.playsound_local(get_turf(owner), 'sound/bloodsucker/lunge_warn.ogg', 60, FALSE, pressure_affected = FALSE) // target-only telegraphing
owner.playsound_local(owner, 'sound/bloodsucker/lunge_warn.ogg', 60, FALSE, pressure_affected = FALSE) // audio feedback to the user
- if(do_mob(owner, owner, 6, TRUE, TRUE))
+ if(do_mob(owner, owner, 7, TRUE, TRUE))
walk_towards(owner, T, 0.1, 10) // yes i know i shouldn't use this but i don't know how to work in anything better
- if(get_turf(owner) != T && !(isliving(target) && target.Adjacent(owner)) && owner.incapacitated() && owner.resting)
+ if(get_turf(owner) != T && !(isliving(target) && target.Adjacent(owner)) && owner.incapacitated() && !CHECK_MOBILITY(L, MOBILITY_STAND))
var/send_dir = get_dir(owner, T)
new /datum/forced_movement(owner, get_ranged_target_turf(owner, send_dir, 1), 1, FALSE)
owner.spin(10)
@@ -80,8 +81,8 @@
target.grabbedby(owner) // Taken from mutations.dm under changelings
target.grippedby(owner, instant = TRUE) //instant aggro grab
break
- sleep(i*3)
+ sleep(3)
/datum/action/bloodsucker/targeted/lunge/DeactivatePower(mob/living/user = owner, mob/living/target)
..() // activate = FALSE
- user.update_canmove()
+ user.update_mobility()
diff --git a/code/modules/antagonists/bloodsucker/powers/mesmerize.dm b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm
index b238c5ba36..d5354c1af9 100644
--- a/code/modules/antagonists/bloodsucker/powers/mesmerize.dm
+++ b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm
@@ -11,7 +11,7 @@
button_icon_state = "power_mez"
bloodcost = 30
cooldown = 300
- target_range = 3
+ target_range = 2
power_activates_immediately = TRUE
message_Trigger = "Whom will you subvert to your will?"
must_be_capacitated = TRUE
@@ -73,7 +73,7 @@
to_chat(owner, "You're too far outside your victim's view.")
return FALSE
- if(target.has_status_effect(STATUS_EFFECT_MESMERIZE)) // ?
+ if(target.has_status_effect(STATUS_EFFECT_MESMERIZE)) // ignores facing once the windup has started
return TRUE
// Check: Facing target?
@@ -82,45 +82,59 @@
to_chat(owner, "You must be facing your victim.")
return FALSE
// Check: Target facing me?
- if(!target.resting && !is_A_facing_B(target,owner))
+ if (CHECK_MOBILITY(target, MOBILITY_STAND) && !is_A_facing_B(target,owner))
if(display_error)
to_chat(owner, "Your victim must be facing you to see into your eyes.")
return FALSE
return TRUE
+/datum/action/bloodsucker/targeted/mesmerize/proc/ContinueTarget(atom/A)
+ var/mob/living/carbon/target = A
+ var/mob/living/user = owner
+
+ var/cancontinue=CheckCanTarget(target)
+ if(!cancontinue)
+ success = FALSE
+ target.remove_status_effect(STATUS_EFFECT_MESMERIZE)
+ user.remove_status_effect(STATUS_EFFECT_MESMERIZE)
+ DeactivatePower()
+ DeactivateRangedAbility()
+ StartCooldown()
+ to_chat(user, "[target] has escaped your gaze!")
+ UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
+
/datum/action/bloodsucker/targeted/mesmerize/FireTargetedPower(atom/A)
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
var/mob/living/carbon/target = A
var/mob/living/user = owner
if(istype(target))
+ success = TRUE
var/power_time = 138 + level_current * 12
target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30)
user.apply_status_effect(STATUS_EFFECT_MESMERIZE, 30)
- if(do_mob(user, target, 30, TRUE, TRUE)) // 3 seconds windup
- success = CheckCanTarget(target)
- if(success) // target just has to be out of view when it is fully charged in order to avoid
- PowerActivatedSuccessfully() // blood & cooldown only altered if power activated successfully - less "fuck you"-y
- target.face_atom(user)
- target.apply_status_effect(STATUS_EFFECT_MESMERIZE, power_time) // pretty much purely cosmetic
- target.Stun(power_time)
- to_chat(user, "[target] is fixed in place by your hypnotic gaze.")
- target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm
- target.notransform = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze.
- else
- to_chat(user, "[target] has escaped your gaze!")
- DeactivatePower()
- DeactivateRangedAbility()
- StartCooldown()
- // oops! if they knew how they could just spam stun the victim and themselves.
+
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/ContinueTarget)
- spawn(power_time)
- if(istype(target) && success)
- target.notransform = FALSE
- // They Woke Up! (Notice if within view)
- if(istype(user) && target.stat == CONSCIOUS && (target in view(10, get_turf(user))) )
+ // 3 second windup
+ sleep(30)
+ if(success)
+ PowerActivatedSuccessfully() // blood & cooldown only altered if power activated successfully - less "fuck you"-y
+ target.face_atom(user)
+ target.apply_status_effect(STATUS_EFFECT_MESMERIZE, power_time) // pretty much purely cosmetic
+ target.Stun(power_time)
+ to_chat(user, "[target] is fixed in place by your hypnotic gaze.")
+ target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm
+ target.notransform = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze.
+
+ UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
+
+ spawn(power_time)
+ if(istype(target) && success)
+ target.notransform = FALSE
+ // They Woke Up! (Notice if within view)
+ if(istype(user) && target.stat == CONSCIOUS && (target in view(10, get_turf(user))) )
to_chat(user, "[target] has snapped out of their trance.")
-
/datum/action/bloodsucker/targeted/mesmerize/ContinueActive(mob/living/user, mob/living/target)
return ..() && CheckCanUse() && CheckCanTarget(target)
diff --git a/code/modules/antagonists/changeling/cellular_emporium.dm b/code/modules/antagonists/changeling/cellular_emporium.dm
index 3cf0a3ee25..b2c1a52a4a 100644
--- a/code/modules/antagonists/changeling/cellular_emporium.dm
+++ b/code/modules/antagonists/changeling/cellular_emporium.dm
@@ -81,7 +81,7 @@
if(istype(our_target, /datum/cellular_emporium))
cellular_emporium = our_target
else
- throw EXCEPTION("cellular_emporium action created with non emporium")
+ CRASH("cellular_emporium action created with non emporium")
/datum/action/innate/cellular_emporium/Activate()
cellular_emporium.ui_interact(owner)
diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm
index 8ed5b5e39c..da626bcf1c 100644
--- a/code/modules/antagonists/changeling/powers/fakedeath.dm
+++ b/code/modules/antagonists/changeling/powers/fakedeath.dm
@@ -18,7 +18,6 @@
user.tod = STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)
user.fakedeath("changeling") //play dead
user.update_stat()
- user.update_canmove()
addtimer(CALLBACK(src, .proc/ready_to_regenerate, user), LING_FAKEDEATH_TIME, TIMER_UNIQUE)
return TRUE
diff --git a/code/modules/antagonists/changeling/powers/headcrab.dm b/code/modules/antagonists/changeling/powers/headcrab.dm
index 4ef0d2f240..867f160081 100644
--- a/code/modules/antagonists/changeling/powers/headcrab.dm
+++ b/code/modules/antagonists/changeling/powers/headcrab.dm
@@ -30,7 +30,7 @@
H.confused += 3
for(var/mob/living/silicon/S in range(2,user))
to_chat(S, "Your sensors are disabled by a shower of blood!")
- S.Knockdown(60)
+ S.DefaultCombatKnockdown(60)
var/turf = get_turf(user)
user.gib()
. = TRUE
diff --git a/code/modules/antagonists/changeling/powers/shriek.dm b/code/modules/antagonists/changeling/powers/shriek.dm
index 65e58ae65b..3de220dbcb 100644
--- a/code/modules/antagonists/changeling/powers/shriek.dm
+++ b/code/modules/antagonists/changeling/powers/shriek.dm
@@ -24,7 +24,7 @@
if(issilicon(M))
SEND_SOUND(M, sound('sound/weapons/flash.ogg'))
- M.Knockdown(rand(100,200))
+ M.DefaultCombatKnockdown(rand(100,200))
for(var/obj/machinery/light/L in range(4, user))
L.on = 1
diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm
index 1f25e06324..a98700683e 100644
--- a/code/modules/antagonists/changeling/powers/strained_muscles.dm
+++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm
@@ -26,7 +26,7 @@
changeling.chem_recharge_slowdown -= 0.5
if(stacks >= 20)
to_chat(user, "We collapse in exhaustion.")
- user.Knockdown(60)
+ user.DefaultCombatKnockdown(60)
user.emote("gasp")
INVOKE_ASYNC(src, .proc/muscle_loop, user)
@@ -40,7 +40,7 @@
if(user.stat != CONSCIOUS || user.staminaloss >= 90)
active = !active
to_chat(user, "Our muscles relax without the energy to strengthen them.")
- user.Knockdown(40)
+ user.DefaultCombatKnockdown(40)
user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
changeling.chem_recharge_slowdown -= 0.5
break
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
index eb7f83735d..1b4d26ac86 100644
--- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
@@ -80,7 +80,7 @@
if(iscultist(L)) //No longer stuns cultists, instead sets them on fire and burns them
to_chat(L, "\"Watch your step, wretch.\"")
L.adjustFireLoss(10)
- L.Knockdown(20, FALSE)
+ L.DefaultCombatKnockdown(20, FALSE)
L.adjust_fire_stacks(5) //Burn!
L.IgniteMob()
else
@@ -155,7 +155,7 @@
if(brutedamage || burndamage)
L.adjustBruteLoss(-(brutedamage * 0.25))
L.adjustFireLoss(-(burndamage * 0.25))
- L.Knockdown(50) //Completely defenseless for five seconds - mainly to give them time to read over the information they've just been presented with
+ L.DefaultCombatKnockdown(50) //Completely defenseless for five seconds - mainly to give them time to read over the information they've just been presented with
if(iscarbon(L))
var/mob/living/carbon/C = L
C.silent += 5
diff --git a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm
index ee1a1233d2..c7c9c42ee9 100644
--- a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm
+++ b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm
@@ -196,7 +196,7 @@
if(!iscultist(L))
L.visible_message("[L]'s eyes blaze with brilliant light!", \
"Your vision suddenly screams with white-hot light!")
- L.Knockdown(15, TRUE, FALSE, 15)
+ L.DefaultCombatKnockdown(15, TRUE, FALSE, 15)
L.apply_status_effect(STATUS_EFFECT_KINDLE)
L.flash_act(1, 1)
if(issilicon(target))
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
index 05516cc6a2..4a10862e28 100644
--- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
@@ -57,15 +57,15 @@
else if(!..())
if(!L.anti_magic_check())
if(issilicon(L))
- L.Knockdown(100)
+ L.DefaultCombatKnockdown(100)
else if(iscultist(L))
L.confused += CLAMP(10 - L.confused, 0, 5) // Spearthrow now confuses enemy cultists + just deals extra damage / sets on fire instead of hardstunning + damage
to_chat(L, "[src] crashes into you with burning force, sending you reeling!")
L.adjust_fire_stacks(2)
- L.Knockdown(1)
+ L.DefaultCombatKnockdown(1)
L.IgniteMob()
else
- L.Knockdown(40)
+ L.DefaultCombatKnockdown(40)
GLOB.clockwork_vitality += L.adjustFireLoss(bonus_burn * 3) //normally a total of 40 damage, 70 with ratvar
break_spear(T)
else
diff --git a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
index 644d9eedd5..6a53097922 100644
--- a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
+++ b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
@@ -176,7 +176,7 @@
var/datum/status_effect/belligerent/B = C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
if(!QDELETED(B))
B.duration = world.time + 30
- C.Knockdown(5) //knocks down for half a second if affected
+ C.DefaultCombatKnockdown(5) //knocks down for half a second if affected
sleep(!GLOB.ratvar_approaches ? 16 : 10)
name = "judicial blast"
layer = ABOVE_ALL_MOB_LAYER
@@ -196,7 +196,7 @@
L.visible_message("Strange energy flows into [L]'s [I.name]!", \
"Your [I.name] shields you from [src]!")
continue
- L.Knockdown(15) //knocks down briefly when exploding
+ L.DefaultCombatKnockdown(15) //knocks down briefly when exploding
if(!iscultist(L))
L.visible_message("[L] is struck by a judicial explosion!", \
"[!issilicon(L) ? "An unseen force slams you into the ground!" : "ERROR: Motor servos disabled by external source!"]")
diff --git a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
index 1158b02a4c..98b3c32b0f 100644
--- a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
@@ -57,5 +57,5 @@
L.confused = min(L.confused + 15, 50)
L.dizziness = min(L.dizziness + 15, 50)
if(L.confused >= 25)
- L.Knockdown(FLOOR(L.confused * 0.8, 1))
+ L.DefaultCombatKnockdown(FLOOR(L.confused * 0.8, 1))
take_damage(max_integrity)
diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm
index 2f0db73bfc..a4b19f2d40 100644
--- a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm
@@ -22,7 +22,7 @@
if(buckled_mobs && LAZYLEN(buckled_mobs))
var/mob/living/L = buckled_mobs[1]
if(iscarbon(L))
- L.Knockdown(100)
+ L.DefaultCombatKnockdown(100)
L.visible_message("[L] is maimed as the skewer shatters while still in [L.p_their()] body!")
L.adjustBruteLoss(15)
unbuckle_mob(L)
@@ -117,6 +117,6 @@
return
skewee.visible_message("[skewee] comes free of [src] with a squelching pop!", \
"You come free of [src]!")
- skewee.Knockdown(30)
+ skewee.DefaultCombatKnockdown(30)
playsound(skewee, 'sound/misc/desceration-03.ogg', 50, TRUE)
unbuckle_mob(skewee)
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index 636061783e..9a086b75a2 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -446,7 +446,7 @@
var/atom/throw_target = get_edge_target_turf(L, user.dir)
L.throw_at(throw_target, 7, 1, user)
else if(!iscultist(L))
- L.Knockdown(160)
+ L.DefaultCombatKnockdown(160)
L.adjustStaminaLoss(140) //Ensures hard stamcrit
L.flash_act(1,1)
if(issilicon(target))
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index f14aeede9a..3dc199b56d 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -46,10 +46,11 @@
/obj/item/melee/cultblade/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 40, 100)
+ AddElement(/datum/element/sword_point)
/obj/item/melee/cultblade/attack(mob/living/target, mob/living/carbon/human/user)
if(!iscultist(user))
- user.Knockdown(100)
+ user.DefaultCombatKnockdown(100)
user.dropItemToGround(src, TRUE)
user.visible_message("A powerful force shoves [user] away from [target]!", \
"\"You shouldn't play with sharp things. You'll poke someone's eye out.\"")
@@ -148,7 +149,7 @@
user.emote("scream")
user.apply_damage(30, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
user.dropItemToGround(src, TRUE)
- user.Knockdown(50)
+ user.DefaultCombatKnockdown(50)
return
force = initial(force)
jaunt.Grant(user, src)
@@ -405,7 +406,7 @@
to_chat(user, "An overwhelming sense of nausea overpowers you!")
user.dropItemToGround(src, TRUE)
user.Dizzy(30)
- user.Knockdown(100)
+ user.DefaultCombatKnockdown(100)
else
to_chat(user, "\"Trying to use things you don't own is bad, you know.\"")
to_chat(user, "The armor squeezes at your body!")
@@ -457,7 +458,7 @@
to_chat(user, "An overwhelming sense of nausea overpowers you!")
user.dropItemToGround(src, TRUE)
user.Dizzy(30)
- user.Knockdown(100)
+ user.DefaultCombatKnockdown(100)
else
to_chat(user, "\"Trying to use things you don't own is bad, you know.\"")
to_chat(user, "The robes squeeze at your body!")
@@ -478,7 +479,7 @@
to_chat(user, "\"You want to be blind, do you?\"")
user.dropItemToGround(src, TRUE)
user.Dizzy(30)
- user.Knockdown(100)
+ user.DefaultCombatKnockdown(100)
user.blind_eyes(30)
/obj/item/reagent_containers/glass/beaker/unholywater
@@ -499,7 +500,7 @@
/obj/item/shuttle_curse/attack_self(mob/living/user)
if(!iscultist(user))
user.dropItemToGround(src, TRUE)
- user.Knockdown(100)
+ user.DefaultCombatKnockdown(100)
to_chat(user, "A powerful force shoves you away from [src]!")
return
if(curselimit > 1)
@@ -705,10 +706,10 @@
if(is_servant_of_ratvar(L))
to_chat(L, "\"Kneel for me, scum\"")
L.confused += CLAMP(10 - L.confused, 0, 5) //confuses and lightly knockdowns + damages hostile cultists instead of hardstunning like before
- L.Knockdown(15)
+ L.DefaultCombatKnockdown(15)
L.adjustBruteLoss(10)
else
- L.Knockdown(50)
+ L.DefaultCombatKnockdown(50)
break_spear(T)
else
..()
@@ -843,7 +844,7 @@
INVOKE_ASYNC(src, .proc/pewpew, user, params)
var/obj/structure/emergency_shield/invoker/N = new(user.loc)
if(do_after(user, 90, target = user))
- user.Knockdown(40)
+ user.DefaultCombatKnockdown(40)
to_chat(user, "You have exhausted the power of this spell!")
firing = FALSE
if(N)
@@ -908,7 +909,7 @@
else
var/mob/living/L = target
if(L.density)
- L.Knockdown(20)
+ L.DefaultCombatKnockdown(20)
L.adjustBruteLoss(45)
playsound(L, 'sound/hallucinations/wail.ogg', 50, 1)
L.emote("scream")
@@ -944,7 +945,7 @@
T.visible_message("The sheer force from [P] shatters the mirror shield!")
new /obj/effect/temp_visual/cult/sparks(T)
playsound(T, 'sound/effects/glassbr3.ogg', 100)
- owner.Knockdown(25)
+ owner.DefaultCombatKnockdown(25)
qdel(src)
return FALSE
if(P.is_reflectable)
@@ -1001,9 +1002,9 @@
else if(!..())
if(!L.anti_magic_check())
if(is_servant_of_ratvar(L))
- L.Knockdown(60)
+ L.DefaultCombatKnockdown(60)
else
- L.Knockdown(30)
+ L.DefaultCombatKnockdown(30)
if(D.thrower)
for(var/mob/living/Next in orange(2, T))
if(!Next.density || iscultist(Next))
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 0111334748..3d27fa942b 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -219,7 +219,7 @@ structure_check() searches for nearby cultist structures required for the invoca
L.visible_message("[L]'s eyes glow a defiant yellow!", \
"\"Stop resisting. You will be mi-\"\n\
\"Give up and you will feel pain unlike anything you've ever felt!\"")
- L.Knockdown(80)
+ L.DefaultCombatKnockdown(80)
else if(is_convertable)
do_convert(L, invokers)
else
@@ -908,7 +908,7 @@ structure_check() searches for nearby cultist structures required for the invoca
if(affecting.key)
affecting.visible_message("[affecting] slowly relaxes, the glow around [affecting.p_them()] dimming.", \
"You are re-united with your physical form. [src] releases its hold over you.")
- affecting.Knockdown(40)
+ affecting.DefaultCombatKnockdown(40)
break
if(affecting.health <= 10)
to_chat(G, "Your body can no longer sustain the connection!")
@@ -970,7 +970,7 @@ structure_check() searches for nearby cultist structures required for the invoca
playsound(T, 'sound/magic/enter_blood.ogg', 100, 1)
visible_message("A colossal shockwave of energy bursts from the rune, disintegrating it in the process!")
for(var/mob/living/L in range(src, 3))
- L.Knockdown(30)
+ L.DefaultCombatKnockdown(30)
empulse(T, 0.42*(intensity), 1)
var/list/images = list()
var/zmatch = T.z
diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm
index 951fe4e18a..84920eba00 100644
--- a/code/modules/antagonists/devil/devil.dm
+++ b/code/modules/antagonists/devil/devil.dm
@@ -477,7 +477,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
if(SOULVALUE >= ARCH_THRESHOLD && ascendable)
A.convert_to_archdevil()
else
- throw EXCEPTION("Unable to find a blobstart landmark for hellish resurrection")
+ CRASH("Unable to find a blobstart landmark for hellish resurrection")
/datum/antagonist/devil/proc/update_hud()
diff --git a/code/modules/antagonists/devil/devil_helpers.dm b/code/modules/antagonists/devil/devil_helpers.dm
index 4d0a781570..d3445eac0f 100644
--- a/code/modules/antagonists/devil/devil_helpers.dm
+++ b/code/modules/antagonists/devil/devil_helpers.dm
@@ -32,7 +32,7 @@
if(BANE_HARVEST)
if(istype(weapon, /obj/item/reagent_containers/food/snacks/grown/))
visible_message("The spirits of the harvest aid in the exorcism.", "The harvest spirits are harming you.")
- Knockdown(40)
+ DefaultCombatKnockdown(40)
qdel(weapon)
return 2
return 1
\ No newline at end of file
diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm
index 12bdbec77a..133bd5ab6a 100644
--- a/code/modules/antagonists/ninja/ninja.dm
+++ b/code/modules/antagonists/ninja/ninja.dm
@@ -70,16 +70,10 @@
O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm."
objectives += O
if(4) //flavor
- if(helping_station)
- var/datum/objective/flavor/ninja_helping/O = new /datum/objective/flavor/ninja_helping
- O.owner = owner
- O.forge_objective()
- objectives += O
- else
- var/datum/objective/flavor/ninja_syndie/O = new /datum/objective/flavor/ninja_helping
- O.owner = owner
- O.forge_objective()
- objectives += O
+ var/datum/objective/flavor/O = helping_station ? new /datum/objective/flavor/ninja_helping : new /datum/objective/flavor/ninja_syndie
+ O.owner = owner
+ O.forge_objective()
+ objectives += O
else
break
var/datum/objective/O = new /datum/objective/survive()
diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm
index 99d12972d8..92852c6c7f 100644
--- a/code/modules/antagonists/swarmer/swarmer.dm
+++ b/code/modules/antagonists/swarmer/swarmer.dm
@@ -191,7 +191,7 @@
return 0
/obj/item/IntegrateAmount() //returns the amount of resources gained when eating this item
- if(custom_materials[getmaterialref(/datum/material/iron)] || custom_materials[getmaterialref(/datum/material/glass)])
+ if(custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)] || custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
return 1
return ..()
@@ -586,7 +586,7 @@
playsound(loc,'sound/effects/snap.ogg',50, 1, -1)
L.electrocute_act(0, src, 1, 1, 1)
if(iscyborg(L))
- L.Knockdown(100)
+ L.DefaultCombatKnockdown(100)
qdel(src)
..()
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index 68963078c5..0352272f70 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -13,6 +13,7 @@
var/should_give_codewords = TRUE
var/should_equip = TRUE
var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment
+ var/datum/contractor_hub/contractor_hub
hijack_speed = 0.5 //10 seconds per hijack stage by default
/datum/antagonist/traitor/on_gain()
@@ -413,6 +414,9 @@
var/special_role_text = lowertext(name)
+ if(contractor_hub)
+ result += contractor_round_end()
+
if(traitorwin)
result += "The [special_role_text] was successful!"
else
@@ -421,12 +425,44 @@
return result.Join("
")
+/// Proc detailing contract kit buys/completed contracts/additional info
+/datum/antagonist/traitor/proc/contractor_round_end()
+ var result = ""
+ var total_spent_rep = 0
+
+ var/completed_contracts = 0
+ var/tc_total = contractor_hub.contract_TC_payed_out + contractor_hub.contract_TC_to_redeem
+ for(var/datum/syndicate_contract/contract in contractor_hub.assigned_contracts)
+ if(contract.status == CONTRACT_STATUS_COMPLETE)
+ completed_contracts++
+
+ var/contractor_item_icons = "" // Icons of purchases
+ var/contractor_support_unit = "" // Set if they had a support unit - and shows appended to their contracts completed
+
+ for(var/datum/contractor_item/contractor_purchase in contractor_hub.purchased_items) // Get all the icons/total cost for all our items bought
+ contractor_item_icons += "\[ [contractor_purchase.name] - [contractor_purchase.cost] Rep
[contractor_purchase.desc] \]"
+ total_spent_rep += contractor_purchase.cost
+ if(istype(contractor_purchase, /datum/contractor_item/contractor_partner)) // Special case for reinforcements, we want to show their ckey and name on round end.
+ var/datum/contractor_item/contractor_partner/partner = contractor_purchase
+ contractor_support_unit += "
[partner.partner_mind.key] played [partner.partner_mind.current.name], their contractor support unit."
+ if (contractor_hub.purchased_items.len)
+ result += "
(used [total_spent_rep] Rep)"
+ result += contractor_item_icons
+ result += "
"
+ if(completed_contracts > 0)
+ var/pluralCheck = "contract"
+ if(completed_contracts > 1)
+ pluralCheck = "contracts"
+ result += "Completed [completed_contracts] [pluralCheck] for a total of \
+ [tc_total] TC!
"
+ return result
+
/datum/antagonist/traitor/roundend_report_footer()
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
var/responses = jointext(GLOB.syndicate_code_response, ", ")
var message = "
The code phrases were: [phrases]
\
- The code responses were: [responses]
"
+ The code responses were: [responses]
"
return message
diff --git a/code/modules/antagonists/traitor/equipment/contractor.dm b/code/modules/antagonists/traitor/equipment/contractor.dm
new file mode 100644
index 0000000000..8569f314d0
--- /dev/null
+++ b/code/modules/antagonists/traitor/equipment/contractor.dm
@@ -0,0 +1,227 @@
+// Support unit gets it's own very basic antag datum for admin logging.
+/datum/antagonist/traitor/contractor_support
+ name = "Contractor Support Unit"
+ antag_moodlet = /datum/mood_event/focused
+ show_in_roundend = FALSE /// We're already adding them in to the contractor's roundend.
+ give_objectives = TRUE /// We give them their own custom objective.
+ show_in_antagpanel = FALSE /// Not a proper/full antag.
+ should_equip = FALSE /// Don't give them an uplink.
+ var/datum/team/contractor_team/contractor_team
+
+/datum/team/contractor_team // Team for storing both the contractor and their support unit - only really for the HUD and admin logging.
+ show_roundend_report = FALSE
+
+/datum/antagonist/traitor/contractor_support/forge_traitor_objectives()
+ var/datum/objective/generic_objective = new
+ generic_objective.name = "Follow Contractor's Orders"
+ generic_objective.explanation_text = "Follow your orders. Assist agents in this mission area."
+ generic_objective.completed = TRUE
+ add_objective(generic_objective)
+
+/datum/contractor_hub
+ var/contract_rep = 0
+ var/list/hub_items = list()
+ var/list/purchased_items = list()
+ var/static/list/contractor_items = typecacheof(/datum/contractor_item/, TRUE)
+ var/datum/syndicate_contract/current_contract
+ var/list/datum/syndicate_contract/assigned_contracts = list()
+ var/list/assigned_targets = list() // used as a blacklist to make sure we're not assigning targets already assigned
+ var/contract_TC_payed_out = 0 // Keeping track for roundend reporting
+ var/contract_TC_to_redeem = 0 // Used internally and roundend reporting - what TC we have available to cashout.
+
+/datum/contractor_hub/proc/create_hub_items()
+ for(var/path in contractor_items)
+ var/datum/contractor_item/contractor_item = new path
+ hub_items.Add(contractor_item)
+
+/datum/contractor_hub/proc/create_contracts(datum/mind/owner) // 6 initial contracts
+ var/list/to_generate = list(
+ CONTRACT_PAYOUT_LARGE,
+ CONTRACT_PAYOUT_MEDIUM,
+ CONTRACT_PAYOUT_SMALL,
+ CONTRACT_PAYOUT_SMALL,
+ CONTRACT_PAYOUT_SMALL,
+ CONTRACT_PAYOUT_SMALL
+ )
+
+ var/lowest_TC_threshold = 30 // We don't want the sum of all the payouts to be under this amount
+ var/total = 0
+ var/lowest_paying_sum = 0
+ var/datum/syndicate_contract/lowest_paying_contract
+
+ to_generate = shuffle(to_generate) // Randomise order, so we don't have contracts always in payout order.
+ var/start_index = 1 // Support contract generation happening multiple times
+ if(assigned_contracts.len != 0)
+ start_index = assigned_contracts.len + 1
+
+ for(var/i = 1; i <= to_generate.len; i++) // Generate contracts, and find the lowest paying.
+ var/datum/syndicate_contract/contract_to_add = new(owner, assigned_targets, to_generate[i])
+ var/contract_payout_total = contract_to_add.contract.payout + contract_to_add.contract.payout_bonus
+ assigned_targets.Add(contract_to_add.contract.target)
+ if(!lowest_paying_contract || (contract_payout_total < lowest_paying_sum))
+ lowest_paying_sum = contract_payout_total
+ lowest_paying_contract = contract_to_add
+ total += contract_payout_total
+ contract_to_add.id = start_index
+ assigned_contracts.Add(contract_to_add)
+ start_index++
+ if(total < lowest_TC_threshold) // If the threshold for TC payouts isn't reached, boost the lowest paying contract
+ lowest_paying_contract.contract.payout_bonus += (lowest_TC_threshold - total)
+
+/datum/contractor_item
+ var/name // Name of item
+ var/desc // description of item
+ var/item // item path, no item path means the purchase needs it's own handle_purchase()
+ var/item_icon = "fa-broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/
+ var/limited = -1 // Any number above 0 for how many times it can be bought in a round for a single traitor. -1 is unlimited.
+ var/cost // Cost of the item in contract rep.
+
+/datum/contractor_item/contract_reroll
+ name = "Contract Reroll"
+ desc = "Request a reroll of your current contract list. Will generate a new target, payment, and dropoff for the contracts you currently have available."
+ item_icon = "fa-dice"
+ limited = 2
+ cost = 0
+
+/datum/contractor_item/contract_reroll/handle_purchase(var/datum/contractor_hub/hub)
+ . = ..()
+ if (.)
+ var/list/new_target_list = list() // We're not regenerating already completed/aborted/extracting contracts, but we don't want to repeat their targets.
+ for(var/datum/syndicate_contract/contract_check in hub.assigned_contracts)
+ if (contract_check.status != CONTRACT_STATUS_ACTIVE && contract_check.status != CONTRACT_STATUS_INACTIVE)
+ if (contract_check.contract.target)
+ new_target_list.Add(contract_check.contract.target)
+ continue
+ for(var/datum/syndicate_contract/rerolling_contract in hub.assigned_contracts) // Reroll contracts without duplicates
+ if (rerolling_contract.status != CONTRACT_STATUS_ACTIVE && rerolling_contract.status != CONTRACT_STATUS_INACTIVE)
+ continue
+ rerolling_contract.generate(new_target_list)
+ new_target_list.Add(rerolling_contract.contract.target)
+ hub.assigned_targets = new_target_list // Set our target list with the new set we've generated.
+
+/datum/contractor_item/contractor_pinpointer
+ name = "Contractor Pinpointer"
+ desc = "A pinpointer that finds targets even without active suit sensors. Due to taking advantage of an exploit within the system, it can't pinpoint to the same accuracy as the traditional models. Becomes permanently locked to the user that first activates it."
+ item = /obj/item/pinpointer/crew/contractor
+ item_icon = "fa-search-location"
+ limited = 2
+ cost = 1
+
+/datum/contractor_item/fulton_extraction_kit
+ name = "Fulton Extraction Kit"
+ desc = "For getting your target across the station to those difficult dropoffs. Place the beacon somewhere secure, and link the pack. Activating the pack on your target in space will send them over to the beacon - make sure they're not just going to run away though!"
+ item = /obj/item/storage/box/contractor/fulton_extraction
+ item_icon = "fa-parachute-box"
+ limited = 1
+ cost = 1
+
+/datum/contractor_item/contractor_partner
+ name = "Reinforcements"
+ desc = "Upon purchase we'll contact available units in the area. Should there be an agent free, we'll send them down to assist you immediately. If no units are free, we give a full refund."
+ item_icon = "fa-user-friends"
+ limited = 1
+ cost = 2
+ var/datum/mind/partner_mind = null
+
+/datum/contractor_item/contractor_partner/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
+ . = ..()
+ if (.)
+ to_chat(user, "The uplink vibrates quietly, connecting to nearby agents...")
+ var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT)
+ if(LAZYLEN(candidates))
+ var/mob/dead/observer/C = pick(candidates)
+ spawn_contractor_partner(user, C.key)
+ else
+ to_chat(user, "No available agents at this time, please try again later.")
+ limited += 1 // refund and add the limit back.
+ hub.contract_rep += cost
+ hub.purchased_items -= src
+
+/datum/outfit/contractor_partner
+ name = "Contractor Support Unit"
+ uniform = /obj/item/clothing/under/chameleon
+ suit = /obj/item/clothing/suit/chameleon
+ back = /obj/item/storage/backpack
+ belt = /obj/item/pda/chameleon
+ mask = /obj/item/clothing/mask/cigarette/syndicate
+ shoes = /obj/item/clothing/shoes/chameleon/noslip
+ ears = /obj/item/radio/headset/chameleon
+ id = /obj/item/card/id/syndicate
+ r_hand = /obj/item/storage/toolbox/syndicate
+ backpack_contents = list(/obj/item/storage/box/survival, /obj/item/implanter/uplink, /obj/item/clothing/mask/chameleon,
+ /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/lighter)
+
+/datum/outfit/contractor_partner/post_equip(mob/living/carbon/human/H, visualsOnly)
+ . = ..()
+ var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(SLOT_WEAR_MASK)
+ cig.light() // pre-light their cig for extra badass
+
+/datum/contractor_item/contractor_partner/proc/spawn_contractor_partner(mob/living/user, key)
+ var/mob/living/carbon/human/partner = new()
+ var/datum/outfit/contractor_partner/partner_outfit = new()
+ partner_outfit.equip(partner)
+ var/obj/structure/closet/supplypod/arrival_pod = new()
+ arrival_pod.style = STYLE_SYNDICATE
+ arrival_pod.explosionSize = list(0,0,0,1)
+ arrival_pod.bluespace = TRUE
+ var/turf/free_location = find_obstruction_free_location(2, user)
+ if (!free_location) // We really want to send them - if we can't find a nice location just land it on top of them.
+ free_location = get_turf(user)
+ partner.forceMove(arrival_pod)
+ partner.ckey = key
+ partner_mind = partner.mind // We give a reference to the mind that'll be the support unit
+ partner_mind.make_Contractor_Support()
+ to_chat(partner_mind.current, "\n[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.")
+ to_chat(partner_mind.current, "Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.\n\n")
+ new /obj/effect/abstract/DPtarget(free_location, arrival_pod)
+
+/datum/contractor_item/blackout
+ name = "Blackout"
+ desc = "Request Syndicate Command to distrupt the station's powernet. Disables power across the station for a short duration."
+ item_icon = "fa-bolt"
+ limited = 2
+ cost = 3
+
+/datum/contractor_item/blackout/handle_purchase(var/datum/contractor_hub/hub)
+ . = ..()
+ if (.)
+ power_fail(35, 50)
+ priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff")
+
+// Subtract cost, and spawn if it's an item.
+/datum/contractor_item/proc/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
+ if (hub.contract_rep >= cost)
+ hub.contract_rep -= cost
+ else
+ return FALSE
+ if (limited >= 1)
+ limited -= 1
+ else if (limited == 0)
+ return FALSE
+ hub.purchased_items.Add(src)
+ if (item && ispath(item))
+ var/atom/item_to_create = new item(get_turf(user))
+
+ if(user.put_in_hands(item_to_create))
+ to_chat(user, "Your purchase materializes into your hands!")
+ else
+ to_chat(user, "Your purchase materializes onto the floor.")
+ return item_to_create
+ return TRUE
+
+/obj/item/pinpointer/crew/contractor
+ name = "contractor pinpointer"
+ desc = "A handheld tracking device that locks onto certain signals. Ignores suit sensors, but is much less accurate."
+ icon_state = "pinpointer_syndicate"
+ minimum_range = 25
+ has_owner = TRUE
+ ignore_suit_sensor_level = TRUE
+
+/obj/item/storage/box/contractor/fulton_extraction
+ name = "Fulton Extraction Kit"
+ icon_state = "syndiebox"
+ illustration = "writing_syndie"
+
+/obj/item/storage/box/contractor/fulton_extraction/PopulateContents()
+ new /obj/item/extraction_pack(src)
+ new /obj/item/fulton_core(src)
\ No newline at end of file
diff --git a/code/modules/antagonists/traitor/syndicate_contract.dm b/code/modules/antagonists/traitor/syndicate_contract.dm
new file mode 100644
index 0000000000..c22012fe87
--- /dev/null
+++ b/code/modules/antagonists/traitor/syndicate_contract.dm
@@ -0,0 +1,144 @@
+/datum/syndicate_contract
+ var/id = 0
+ var/status = CONTRACT_STATUS_INACTIVE
+ var/datum/objective/contract/contract = new()
+ var/ransom = 0
+ var/payout_type = null
+ var/list/victim_belongings = list()
+
+/datum/syndicate_contract/New(contract_owner, blacklist, type=CONTRACT_PAYOUT_SMALL)
+ contract.owner = contract_owner
+ payout_type = type
+ generate(blacklist)
+
+/datum/syndicate_contract/proc/generate(blacklist)
+ contract.find_target(null, blacklist)
+ if (payout_type == CONTRACT_PAYOUT_LARGE)
+ contract.payout_bonus = rand(9,13)
+ else if(payout_type == CONTRACT_PAYOUT_MEDIUM)
+ contract.payout_bonus = rand(6,8)
+ else
+ contract.payout_bonus = rand(2,4)
+ contract.payout = rand(0, 2)
+ contract.generate_dropoff()
+ ransom = 100 * rand(18, 45)
+
+/datum/syndicate_contract/proc/handle_extraction(var/mob/living/user)
+ if (contract.target && contract.dropoff_check(user, contract.target.current))
+ var/turf/free_location = find_obstruction_free_location(3, user, contract.dropoff)
+ if(free_location) // We've got a valid location, launch.
+ launch_extraction_pod(free_location)
+ return TRUE
+ return FALSE
+
+// Launch the pod to collect our victim.
+/datum/syndicate_contract/proc/launch_extraction_pod(turf/empty_pod_turf)
+ var/obj/structure/closet/supplypod/extractionpod/empty_pod = new()
+ RegisterSignal(empty_pod, COMSIG_ATOM_ENTERED, .proc/enter_check)
+ empty_pod.stay_after_drop = TRUE
+ empty_pod.reversing = TRUE
+ empty_pod.explosionSize = list(0,0,0,1)
+ empty_pod.leavingSound = 'sound/effects/podwoosh.ogg'
+ new /obj/effect/abstract/DPtarget(empty_pod_turf, empty_pod)
+
+/datum/syndicate_contract/proc/enter_check(datum/source, sent_mob)
+ if(istype(source, /obj/structure/closet/supplypod/extractionpod))
+ if(isliving(sent_mob))
+ var/mob/living/M = sent_mob
+ var/datum/antagonist/traitor/traitor_data = contract.owner.has_antag_datum(/datum/antagonist/traitor)
+ if(M == contract.target.current)
+ traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout
+ if(M.stat != DEAD)
+ traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout_bonus
+ status = CONTRACT_STATUS_COMPLETE
+ if(traitor_data.contractor_hub.current_contract == src)
+ traitor_data.contractor_hub.current_contract = null
+ traitor_data.contractor_hub.contract_rep += 2
+ else
+ status = CONTRACT_STATUS_ABORTED // Sending a target that wasn't even yours is as good as just aborting it
+ if(traitor_data.contractor_hub.current_contract == src)
+ traitor_data.contractor_hub.current_contract = null
+ if(iscarbon(M))
+ for(var/obj/item/W in M)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(W == H.w_uniform || W == H.shoes)
+ continue //So all they're left with are shoes and uniform.
+ M.transferItemToLoc(W)
+ victim_belongings.Add(W)
+ var/obj/structure/closet/supplypod/extractionpod/pod = source
+ pod.send_up(pod) // Handle the pod returning
+ if(ishuman(M))
+ var/mob/living/carbon/human/target = M // After we remove items, at least give them what they need to live.
+ target.dna.species.give_important_for_life(target)
+ handleVictimExperience(M) // After pod is sent we start the victim narrative/heal.
+ var/points_to_check = SSshuttle.points // This is slightly delayed because of the sleep calls above to handle the narrative. We don't want to tell the station instantly.
+ if(points_to_check >= ransom)
+ SSshuttle.points -= ransom
+ else
+ SSshuttle.points -= points_to_check
+ priority_announce("One of your crew was captured by a rival organisation - we've needed to pay their ransom to bring them back. \
+ As is policy we've taken a portion of the station's funds to offset the overall cost.", null, "attention", null, "Nanotrasen Asset Protection")
+
+/datum/syndicate_contract/proc/handleVictimExperience(var/mob/living/M) // They're off to holding - handle the return timer and give some text about what's going on.
+ addtimer(CALLBACK(src, .proc/returnVictim, M), (60 * 10) * 4) // Ship 'em back - dead or alive... 4 minutes wait.
+ if(M.stat != DEAD) //Even if they weren't the target, we're still treating them the same.
+ M.reagents.add_reagent(/datum/reagent/medicine/omnizine, 20) // Heal them up - gets them out of crit/soft crit.
+ M.flash_act()
+ M.confused += 10
+ M.blur_eyes(5)
+ to_chat(M, "You feel strange...")
+ sleep(60)
+ to_chat(M, "That pod did something to you...")
+ M.Dizzy(35)
+ sleep(65)
+ to_chat(M, "Your head pounds... It feels like it's going to burst out your skull!")
+ M.flash_act()
+ M.confused += 20
+ M.blur_eyes(3)
+ sleep(30)
+ to_chat(M, "Your head pounds...")
+ sleep(100)
+ M.flash_act()
+ M.Unconscious(200)
+ to_chat(M, "A million voices echo in your head... \"Your mind held many valuable secrets - \
+ we thank you for providing them. Your value is expended, and you will be ransomed back to your station. We always get paid, \
+ so it's only a matter of time before we ship you back...\"")
+ M.blur_eyes(10)
+ M.Dizzy(15)
+ M.confused += 20
+
+/datum/syndicate_contract/proc/returnVictim(var/mob/living/M) // We're returning the victim
+ var/list/possible_drop_loc = list()
+ for(var/turf/possible_drop in contract.dropoff.contents)
+ if(!is_blocked_turf(possible_drop))
+ possible_drop_loc.Add(possible_drop)
+ if(possible_drop_loc.len > 0)
+ var/pod_rand_loc = rand(1, possible_drop_loc.len)
+ var/obj/structure/closet/supplypod/return_pod = new()
+ return_pod.bluespace = TRUE
+ return_pod.explosionSize = list(0,0,0,0)
+ return_pod.style = STYLE_SYNDICATE
+ do_sparks(8, FALSE, M)
+ M.visible_message("[M] vanishes...")
+ for(var/obj/item/W in M)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ if(W == H.w_uniform || W == H.shoes)
+ continue //So all they're left with are shoes and uniform.
+ M.dropItemToGround(W)
+ for(var/obj/item/W in victim_belongings)
+ W.forceMove(return_pod)
+ M.forceMove(return_pod)
+ M.flash_act()
+ M.blur_eyes(30)
+ M.Dizzy(35)
+ M.confused += 20
+ new /obj/effect/abstract/DPtarget(possible_drop_loc[pod_rand_loc], return_pod)
+ else
+ to_chat(M, "A million voices echo in your head... \"Seems where you got sent here from won't \
+ be able to handle our pod... You will die here instead.\"")
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(C.can_heartattack())
+ C.set_heartattack(TRUE)
\ No newline at end of file
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 492da73e66..74cfc61d0f 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -261,7 +261,7 @@
GiveHint(target)
else if(is_pointed(I))
to_chat(target, "You feel a stabbing pain in [parse_zone(user.zone_selected)]!")
- target.Knockdown(40)
+ target.DefaultCombatKnockdown(40)
GiveHint(target)
else if(istype(I, /obj/item/bikehorn))
to_chat(target, "HONK")
@@ -377,7 +377,10 @@
/obj/item/warpwhistle/proc/end_effect(mob/living/carbon/user)
user.invisibility = initial(user.invisibility)
user.status_flags &= ~GODMODE
- user.canmove = TRUE
+ REMOVE_TRAIT(user, TRAIT_MOBILITY_NOMOVE, src)
+ REMOVE_TRAIT(user, TRAIT_MOBILITY_NOUSE, src)
+ REMOVE_TRAIT(user, TRAIT_MOBILITY_NOPICKUP, src)
+ user.update_mobility()
/obj/item/warpwhistle/attack_self(mob/living/carbon/user)
if(!istype(user) || on_cooldown)
@@ -390,7 +393,10 @@
on_cooldown = TRUE
last_user = user
playsound(T,'sound/magic/warpwhistle.ogg', 200, 1)
- user.canmove = FALSE
+ ADD_TRAIT(user, TRAIT_MOBILITY_NOMOVE, src)
+ ADD_TRAIT(user, TRAIT_MOBILITY_NOUSE, src)
+ ADD_TRAIT(user, TRAIT_MOBILITY_NOPICKUP, src)
+ user.update_mobility()
new /obj/effect/temp_visual/tornado(T)
sleep(20)
if(interrupted(user))
@@ -412,7 +418,6 @@
return
if(T.z != potential_T.z || abs(get_dist_euclidian(potential_T,T)) > 50 - breakout)
do_teleport(user, potential_T, channel = TELEPORT_CHANNEL_MAGIC)
- user.canmove = 0
T = potential_T
break
breakout += 1
diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm
index 962c2b2da4..0f43dfaf3a 100644
--- a/code/modules/antagonists/wizard/equipment/soulstone.dm
+++ b/code/modules/antagonists/wizard/equipment/soulstone.dm
@@ -83,8 +83,8 @@
/obj/item/soulstone/proc/release_shades(mob/user)
for(var/mob/living/simple_animal/shade/A in src)
A.status_flags &= ~GODMODE
- A.canmove = TRUE
A.forceMove(get_turf(user))
+ A.mobility_flags = MOBILITY_FLAGS_DEFAULT
A.cancel_camera()
icon_state = "soulstone"
name = initial(name)
@@ -173,7 +173,7 @@
else
T.forceMove(src) //put shade in stone
T.status_flags |= GODMODE
- T.canmove = FALSE
+ T.mobility_flags = NONE
T.health = T.maxHealth
icon_state = "soulstone2"
name = "soulstone: Shade of [T.real_name]"
@@ -240,8 +240,8 @@
T.dust_animation()
QDEL_IN(T, 5)
var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src)
- S.status_flags |= GODMODE //So they won't die inside the stone somehow
- S.canmove = FALSE//Can't move out of the soul stone
+ S.status_flags |= GODMODE //So they won't die inside the stone somehow
+ S.mobility_flags = NONE //Can't move out of the soul stone
S.name = "Shade of [T.real_name]"
S.real_name = "Shade of [T.real_name]"
T.transfer_ckey(S)
diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm
index b6afc3cc0b..13ea317b9b 100644
--- a/code/modules/assembly/flash.dm
+++ b/code/modules/assembly/flash.dm
@@ -150,7 +150,7 @@
var/mob/living/silicon/robot/R = M
log_combat(user, R, "flashed", src)
update_icon(1)
- R.Knockdown(rand(80,120))
+ R.DefaultCombatKnockdown(rand(80,120))
var/diff = 5 * CONFUSION_STACK_MAX_MULTIPLIER - M.confused
R.confused += min(5, diff)
R.flash_act(affect_silicon = 1)
@@ -197,14 +197,13 @@
else
to_chat(user, "This mind seems resistant to the flash!")
-
/obj/item/assembly/flash/cyborg
/obj/item/assembly/flash/cyborg/attack(mob/living/M, mob/user)
. = ..()
new /obj/effect/temp_visual/borgflash(get_turf(src))
- if(. && !CONFIG_GET(flag/disable_borg_flash_knockdown) && iscarbon(M) && !M.resting && !M.get_eye_protection())
- M.Knockdown(80)
+ if(. && !CONFIG_GET(flag/disable_borg_flash_knockdown) && iscarbon(M) && CHECK_MOBILITY(M, MOBILITY_STAND) && !M.get_eye_protection())
+ M.DefaultCombatKnockdown(80)
/obj/item/assembly/flash/cyborg/attack_self(mob/user)
..()
diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm
index c701e13a26..90d4662c15 100644
--- a/code/modules/assembly/mousetrap.dm
+++ b/code/modules/assembly/mousetrap.dm
@@ -48,7 +48,7 @@
if("feet")
if(!H.shoes || !(H.shoes.body_parts_covered & FEET))
affecting = H.get_bodypart(pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
- H.Knockdown(60)
+ H.DefaultCombatKnockdown(60)
if(BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND)
if(!H.gloves)
affecting = H.get_bodypart(type)
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index 0904808f51..864edfdbe6 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -314,10 +314,6 @@
user.forceMove(loc)
user.visible_message("You hear something squeezing through the ducts...", "You climb out the ventilation system.")
- user.canmove = FALSE
- addtimer(VARSET_CALLBACK(user, canmove, TRUE), 1)
-
-
/obj/machinery/atmospherics/AltClick(mob/living/L)
if(is_type_in_typecache(src, GLOB.ventcrawl_machinery))
return L.handle_ventcrawl(src)
diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm
index 86e8863b2b..a79beca4ec 100644
--- a/code/modules/atmospherics/machinery/components/components_base.dm
+++ b/code/modules/atmospherics/machinery/components/components_base.dm
@@ -144,7 +144,7 @@
for(var/i in 1 to device_type)
var/datum/pipeline/parent = parents[i]
if(!parent)
- throw EXCEPTION("Component is missing a pipenet! Rebuilding...")
+ stack_trace("Component is missing a pipenet! Rebuilding...")
build_network()
parent.update = 1
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index 1e8cce32c0..e013a86fd2 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -244,7 +244,7 @@
M.forceMove(get_turf(src))
if(isliving(M))
var/mob/living/L = M
- L.update_canmove()
+ L.update_mobility()
occupant = null
update_icon()
@@ -277,10 +277,10 @@
else
. += "[src] seems empty."
-/obj/machinery/atmospherics/components/unary/cryo_cell/MouseDrop_T(mob/target, mob/user)
- if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
+/obj/machinery/atmospherics/components/unary/cryo_cell/MouseDrop_T(mob/living/carbon/target, mob/user)
+ if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !istype(target) || !user.IsAdvancedToolUser())
return
- if (target.IsKnockdown() || target.IsStun() || target.IsSleeping() || target.IsUnconscious())
+ if(!CHECK_MOBILITY(target, MOBILITY_MOVE))
close_machine(target)
else
user.visible_message("[user] starts shoving [target] inside [src].", "You start shoving [target] inside [src].")
diff --git a/code/modules/cargo/exports/materials.dm b/code/modules/cargo/exports/materials.dm
index a9d3b25d90..675cbb2be0 100644
--- a/code/modules/cargo/exports/materials.dm
+++ b/code/modules/cargo/exports/materials.dm
@@ -15,10 +15,10 @@
if(!isitem(O))
return 0
var/obj/item/I = O
- if(!(getmaterialref(material_id) in I.custom_materials))
+ if(!(SSmaterials.GetMaterialRef(material_id) in I.custom_materials))
return 0
- var/amount = I.custom_materials[getmaterialref(material_id)]
+ var/amount = I.custom_materials[SSmaterials.GetMaterialRef(material_id)]
if(istype(I, /obj/item/stack/ore))
amount *= 0.8 // Station's ore redemption equipment is really goddamn good.
diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm
index adfbe3308a..e82a2141eb 100644
--- a/code/modules/cargo/supplypod.dm
+++ b/code/modules/cargo/supplypod.dm
@@ -42,6 +42,8 @@
var/soundVolume = 80 //Volume to play sounds at. Ignores the cap
var/bay //Used specifically for the centcom_podlauncher datum. Holds the current bay the user is launching objects from. Bays are specific rooms on the centcom map.
var/list/explosionSize = list(0,0,2,3)
+ var/stay_after_drop = FALSE
+ var/specialised = TRUE // It's not a general use pod for cargo/admin use
/obj/structure/closet/supplypod/bluespacepod
style = STYLE_BLUESPACE
@@ -49,6 +51,15 @@
explosionSize = list(0,0,1,2)
landingDelay = 15 //Slightly quicker than the supplypod
+/obj/structure/closet/supplypod/extractionpod
+ name = "Syndicate Extraction Pod"
+ desc = "A specalised, blood-red styled pod for extracting high-value targets out of active mission areas."
+ specialised = TRUE
+ style = STYLE_SYNDICATE
+ bluespace = TRUE
+ explosionSize = list(0,0,1,2)
+ landingDelay = 25 //Slightly longer than others
+
/obj/structure/closet/supplypod/centcompod
style = STYLE_CENTCOM
bluespace = TRUE
@@ -56,6 +67,13 @@
landingDelay = 20 //Very speedy!
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+/obj/structure/closet/supplypod/proc/specialisedPod()
+ return 1
+
+/obj/structure/closet/supplypod/extractionpod/specialisedPod(atom/movable/holder)
+ holder.forceMove(pick(GLOB.holdingfacility)) // land in ninja jail
+ open(holder, forced = TRUE)
+
/obj/structure/closet/supplypod/Initialize()
. = ..()
setStyle(style, TRUE) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly
@@ -76,7 +94,7 @@
return
style = chosenStyle
icon_state = POD_STYLES[chosenStyle][POD_ICON_STATE] //POD_STYLES is a 2D array we treat as a dictionary. The style represents the verticle index, with the icon state, name, and desc being stored in the horizontal indexes of the 2D array.
- if (!adminNamed) //We dont want to name it ourselves if it has been specifically named by an admin using the centcom_podlauncher datum
+ if (!adminNamed && !specialised) //We dont want to name it ourselves if it has been specifically named by an admin using the centcom_podlauncher datum
name = POD_STYLES[chosenStyle][POD_NAME]
desc = POD_STYLES[chosenStyle][POD_DESC]
update_icon()
@@ -96,6 +114,30 @@
/obj/structure/closet/supplypod/toggle(mob/living/user) //Supplypods shouldn't be able to be manually opened under any circumstances, as the open() proc generates supply order datums
return
+/obj/structure/closet/supplypod/proc/handleReturningClose(atom/movable/holder, returntobay)
+ opened = FALSE
+ INVOKE_ASYNC(holder, .proc/setClosed) //Use the INVOKE_ASYNC proc to call setClosed() on whatever the holder may be, without giving the atom/movable base class a setClosed() proc definition
+ for(var/atom/movable/O in get_turf(holder))
+ if ((ismob(O) && !isliving(O)) || (is_type_in_typecache(O, GLOB.blacklisted_cargo_types) && !isliving(O))) //We dont want to take ghosts with us, and we don't want blacklisted items going, but we allow mobs.
+ continue
+ O.forceMove(holder) //Put objects inside before we close
+ var/obj/effect/temp_visual/risingPod = new /obj/effect/abstract/DPfall(get_turf(holder), src) //Make a nice animation of flying back up
+ risingPod.pixel_z = 0 //The initial value of risingPod's pixel_z is 200 because it normally comes down from a high spot
+ animate(risingPod, pixel_z = 200, time = 10, easing = LINEAR_EASING) //Animate our rising pod
+ if(returntobay)
+ holder.forceMove(bay) //Move the pod back to centcom, where it belongs
+ QDEL_IN(risingPod, 10)
+ reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open() )
+ bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
+ open(holder, forced = TRUE)
+ else
+ reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open() )
+ bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
+ QDEL_IN(risingPod, 10)
+ audible_message("The pod hisses, closing quickly and launching itself away from the station.", "The ground vibrates, the nearby pod launching away from the station.")
+ stay_after_drop = FALSE
+ specialisedPod(holder) // Do special actions for specialised pods - this is likely if we were already doing manual launches
+
/obj/structure/closet/supplypod/proc/preOpen() //Called before the open() proc. Handles anything that occurs right as the pod lands.
var/turf/T = get_turf(src)
var/list/B = explosionSize //Mostly because B is more readable than explosionSize :p
@@ -172,7 +214,8 @@
if (style == STYLE_SEETHROUGH)
depart(src)
else
- addtimer(CALLBACK(src, .proc/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time
+ if(!stay_after_drop) // Departing should be handled manually
+ addtimer(CALLBACK(src, .proc/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time
/obj/structure/closet/supplypod/proc/depart(atom/movable/holder)
if (leavingSound)
@@ -187,20 +230,18 @@
qdel(holder)
/obj/structure/closet/supplypod/centcompod/close(atom/movable/holder) //Closes the supplypod and sends it back to centcom. Should only ever be called if the "reversing" variable is true
- opened = FALSE
- INVOKE_ASYNC(holder, .proc/setClosed) //Use the INVOKE_ASYNC proc to call setClosed() on whatever the holder may be, without giving the atom/movable base class a setClosed() proc definition
- for (var/atom/movable/O in get_turf(holder))
- if (ismob(O) && !isliving(O)) //We dont want to take ghosts with us
- continue
- O.forceMove(holder) //Put objects inside before we close
- var/obj/effect/temp_visual/risingPod = new /obj/effect/abstract/DPfall(get_turf(holder), src) //Make a nice animation of flying back up
- risingPod.pixel_z = 0 //The initial value of risingPod's pixel_z is 200 because it normally comes down from a high spot
- holder.forceMove(bay) //Move the pod back to centcom, where it belongs
- animate(risingPod, pixel_z = 200, time = 10, easing = LINEAR_EASING) //Animate our rising pod
- QDEL_IN(risingPod, 10)
- reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open() )
- bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
- open(holder, forced = TRUE)
+ handleReturningClose(holder, TRUE)
+
+/obj/structure/closet/supplypod/extractionpod/close(atom/movable/holder) //handles closing, and returns pod - deletes itself when returned
+ . = ..()
+ return
+
+/obj/structure/closet/supplypod/extractionpod/proc/send_up(atom/movable/holder)
+ if(!holder)
+ holder = src
+ if(leavingSound)
+ playsound(get_turf(holder), leavingSound, soundVolume, 0, 0)
+ handleReturningClose(holder, FALSE)
/obj/structure/closet/supplypod/proc/setOpened() //Proc exists here, as well as in any atom that can assume the role of a "holder" of a supplypod. Check the open() proc for more details
update_icon()
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index cdc3fbc5b9..d5f2ae35ed 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -123,7 +123,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"has_cock" = FALSE,
"cock_shape" = "Human",
"cock_length" = 6,
- "cock_girth_ratio" = COCK_GIRTH_RATIO_DEF,
+ "cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF,
"cock_color" = "fff",
"has_sheath" = FALSE,
"sheath_color" = "fff",
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 03c6051c5d..86148ee17c 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -415,7 +415,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_cock_shape"] >> features["cock_shape"]
S["feature_cock_color"] >> features["cock_color"]
S["feature_cock_length"] >> features["cock_length"]
- S["feature_cock_girth"] >> features["cock_girth"]
+ S["feature_cock_diameter"] >> features["cock_diameter"]
S["feature_has_sheath"] >> features["sheath_color"]
//balls features
S["feature_has_balls"] >> features["has_balls"]
diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm
index 255a5a2eec..cae9a54484 100644
--- a/code/modules/client/verbs/suicide.dm
+++ b/code/modules/client/verbs/suicide.dm
@@ -224,7 +224,7 @@
/mob/living/carbon/canSuicide()
if(!..())
return
- if(IsStun() || IsKnockdown()) //just while I finish up the new 'fun' suiciding verb. This is to prevent metagaming via suicide
+ if(!CHECK_MULTIPLE_BITFIELDS(mobility_flags, MOBILITY_MOVE|MOBILITY_USE)) //just while I finish up the new 'fun' suiciding verb. This is to prevent metagaming via suicide
to_chat(src, "You can't commit suicide while stunned! ((You can type Ghost instead however.))")
return
if(restrained())
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 50e458a224..e176943aa9 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -243,7 +243,7 @@
icon_state = "knight_greyscale"
item_state = "knight_greyscale"
armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
- material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR //Can change color and add prefix
+ material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix
/obj/item/clothing/head/helmet/skull
name = "skull helmet"
diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm
index 1acb7628a3..59747d59ba 100644
--- a/code/modules/clothing/shoes/magboots.dm
+++ b/code/modules/clothing/shoes/magboots.dm
@@ -58,6 +58,12 @@
/obj/item/clothing/shoes/magboots/advance/debug/Initialize()
attack_self(src)
+/obj/item/clothing/shoes/magboots/paramedic
+ desc = "A pair of magboots decked in colors matching the equipment of an emergency medical technician."
+ name = "paramedic magboots"
+ icon_state = "para_magboots0"
+ magboot_state = "para_magboots"
+
/obj/item/clothing/shoes/magboots/syndie
desc = "Reverse-engineered magnetic boots that have a heavy magnetic pull. Property of Gorlex Marauders."
name = "blood-red magboots"
diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm
index a8387c5ccc..3d06fba285 100644
--- a/code/modules/clothing/spacesuits/chronosuit.dm
+++ b/code/modules/clothing/spacesuits/chronosuit.dm
@@ -221,7 +221,7 @@
if(user.wear_suit == src)
if(hard_landing)
user.electrocute_act(35, src, safety = 1)
- user.Knockdown(200)
+ user.DefaultCombatKnockdown(200)
if(!silent)
to_chat(user, "\nroot@ChronosuitMK4# chronowalk4 --stop\n")
if(camera)
diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm
index 04aacfc3f5..2f9ded7848 100644
--- a/code/modules/clothing/spacesuits/flightsuit.dm
+++ b/code/modules/clothing/spacesuits/flightsuit.dm
@@ -481,7 +481,7 @@
adjust_momentum(0, 0, 10)
wearer.visible_message("[wearer]'s flight suit crashes into the ground!")
if(knockdown)
- wearer.Knockdown(80)
+ wearer.DefaultCombatKnockdown(80)
momentum_x = 0
momentum_y = 0
calculate_momentum_speed()
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index fab41c9876..d9e4f17649 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -455,6 +455,18 @@
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS | SCAN_REAGENTS
+/obj/item/clothing/head/helmet/space/hardsuit/medical/equipped(mob/living/carbon/human/user, slot)
+ ..()
+ if (slot == SLOT_HEAD)
+ var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
+ DHUD.add_hud_to(user)
+
+/obj/item/clothing/head/helmet/space/hardsuit/medical/dropped(mob/living/carbon/human/user)
+ ..()
+ if (user.head == src)
+ var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
+ DHUD.remove_hud_from(user)
+
/obj/item/clothing/suit/space/hardsuit/medical
icon_state = "hardsuit-medical"
name = "medical hardsuit"
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index f9e35ca37f..8c39427c49 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -465,3 +465,16 @@ Contains:
torn = TRUE
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1)
playsound(loc, 'sound/effects/refill.ogg', 50, 1)
+
+/obj/item/clothing/suit/space/eva/paramedic
+ name = "paramedic EVA suit"
+ icon_state = "paramedic-eva"
+ item_state = "paramedic-eva"
+ desc = "A deep blue space suit decorated with red and white crosses to indicate that the wearer is trained emergency medical personnel."
+ allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/roller)
+
+/obj/item/clothing/head/helmet/space/eva/paramedic
+ name = "paramedic EVA helmet"
+ desc = "A deep blue space helmet with a large red cross on the faceplate to designate the wearer as trained emergency medical personnel."
+ icon_state = "paramedic-eva-helmet"
+ item_state = "paramedic-eva-helmet"
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm
index e9848ae6cd..aca98df232 100644
--- a/code/modules/clothing/spacesuits/syndi.dm
+++ b/code/modules/clothing/spacesuits/syndi.dm
@@ -75,6 +75,22 @@
icon_state = "syndicate-black"
item_state = "syndicate-black"
+//Black-red syndicate contract varient
+/obj/item/clothing/head/helmet/space/syndicate/contract
+ name = "contractor helmet"
+ desc = "A specialised black and gold helmet that's more compact than its standard Syndicate counterpart. Can be ultra-compressed into even the tightest of spaces."
+ slowdown = 0.55
+ w_class = WEIGHT_CLASS_SMALL
+ icon_state = "syndicate-contract-helm"
+ item_state = "syndicate-contract-helm"
+
+/obj/item/clothing/suit/space/syndicate/contract
+ name = "contractor space suit"
+ desc = "A specialised black and gold space suit that's quicker, and more compact than its standard Syndicate counterpart. Can be ultra-compressed into even the tightest of spaces."
+ slowdown = 0.55
+ w_class = WEIGHT_CLASS_SMALL
+ icon_state = "syndicate-contract"
+ item_state = "syndicate-contract"
//Black-green syndicate space suit
/obj/item/clothing/head/helmet/space/syndicate/black/green
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 1f0214cade..3b84a227ef 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -267,7 +267,7 @@
icon_state = "knight_greyscale"
item_state = "knight_greyscale"
armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
- material_flags = MATERIAL_ADD_PREFIX //Can change color and add prefix
+ material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix
/obj/item/clothing/suit/armor/vest/durathread
name = "makeshift vest"
diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm
index 48fd8ccf1c..efadb8a035 100644
--- a/code/modules/clothing/suits/jobs.dm
+++ b/code/modules/clothing/suits/jobs.dm
@@ -195,3 +195,18 @@
body_parts_covered = HEAD
flags_inv = HIDEHAIR|HIDEEARS
mutantrace_variation = STYLE_MUZZLE
+
+
+//Paramedic
+
+/obj/item/clothing/suit/toggle/labcoat/paramedic
+ name = "paramedic vest"
+ desc = "A dark blue vest with reflective strips for emergency medical technicians."
+ icon_state = "paramedic-vest"
+ item_state = "paramedic-vest"
+
+/obj/item/clothing/suit/toggle/labcoat/emt
+ name = "emt vest"
+ desc = "A dark blue vest with reflective strips for emergency medical technicians."
+ icon_state = "labcoat_emt"
+ item_state = "labcoat_emt"
\ No newline at end of file
diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm
index 022bc7c95c..195712b814 100644
--- a/code/modules/clothing/suits/labcoat.dm
+++ b/code/modules/clothing/suits/labcoat.dm
@@ -37,12 +37,6 @@
icon_state = "labcoat_cmo"
item_state = "labcoat_cmo"
-/obj/item/clothing/suit/toggle/labcoat/emt
- name = "\improper EMT's jacket"
- desc = "A dark blue jacket with reflective strips for emergency medical technicians."
- icon_state = "labcoat_emt"
- item_state = "labcoat_cmo"
-
/obj/item/clothing/suit/toggle/labcoat/mad
name = "\proper The Mad's labcoat"
desc = "It makes you look capable of konking someone on the noggin and shooting them into space."
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 4d3e8acb28..6f61bf56cb 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -480,8 +480,6 @@
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
allowed = list(/obj/item/clothing/mask/facehugger/toy)
-
-
// WINTER COATS
/obj/item/clothing/suit/hooded/wintercoat
@@ -521,6 +519,7 @@
/obj/item/clothing/suit/hooded/wintercoat/captain
name = "captain's winter coat"
+ desc = "A luxuriant winter coat, stuffed with the down of the endangered Uka bird and trimmed with genuine sable. The fabric is an indulgently soft micro-fiber, and the deep ultramarine color is only one that could be achieved with minute amounts of crystalline bluespace dust woven into the thread between the plectrums. Extremely lavish, and extremely durable. The tiny flakes of protective material make it nothing short of extremely light lamellar armor."
icon_state = "coatcaptain"
item_state = "coatcaptain"
armor = list("melee" = 25, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
@@ -531,20 +530,24 @@
allowed = GLOB.security_wintercoat_allowed
/obj/item/clothing/head/hooded/winterhood/captain
+ desc = "A blue and yellow hood attached to a heavy winter jacket."
icon_state = "winterhood_captain"
/obj/item/clothing/suit/hooded/wintercoat/hop
name = "head of personnel's winter coat"
+ desc = "A cozy winter coat, covered in thick fur. The breast features a proud yellow chevron, reminding everyone that you're the second banana."
icon_state = "coathop"
item_state = "coathop"
armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 5, "bio" = 5, "rad" = 0, "fire" = 0, "acid" = 5)
hoodtype = /obj/item/clothing/head/hooded/winterhood/hop
/obj/item/clothing/head/hooded/winterhood/hop
+ desc = "A cozy winter hood attached to a heavy winter jacket."
icon_state = "winterhood_hop"
/obj/item/clothing/suit/hooded/wintercoat/security
name = "security winter coat"
+ desc = "A red, armor-padded winter coat. It glitters with a mild ablative coating and a robust air of authority. The zipper tab is a pair of jingly little handcuffs and got annoying after the first ten seconds."
icon_state = "coatsecurity"
item_state = "coatsecurity"
armor = list("melee" = 25, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 45)
@@ -555,10 +558,12 @@
allowed = GLOB.security_wintercoat_allowed
/obj/item/clothing/head/hooded/winterhood/security
+ desc = "A red, armor-padded winter hood."
icon_state = "winterhood_security"
/obj/item/clothing/suit/hooded/wintercoat/hos
name = "head of security's winter coat"
+ desc = "A red, armor-padded winter coat, lovingly woven with a Kevlar interleave and reinforced with semi-ablative polymers and a silver azide fill material. The zipper tab looks like a tiny replica of Beepsky."
icon_state = "coathos"
item_state = "coathos"
armor = list("melee" = 35, "bullet" = 35, "laser" = 35, "energy" = 15, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 55)
@@ -569,10 +574,12 @@
allowed = GLOB.security_wintercoat_allowed
/obj/item/clothing/head/hooded/winterhood/hos
+ desc = "A red, armor-padded winter hood, lovingly woven with a Kevlar interleave. Definitely not bulletproof, especially not the part where your face goes."
icon_state = "winterhood_hos"
/obj/item/clothing/suit/hooded/wintercoat/medical
name = "medical winter coat"
+ desc = "An arctic white winter coat with a small blue caduceus instead of a plastic zipper tab. Snazzy."
icon_state = "coatmedical"
item_state = "coatmedical"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
@@ -580,10 +587,12 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/medical
/obj/item/clothing/head/hooded/winterhood/medical
+ desc = "A white winter coat hood."
icon_state = "winterhood_medical"
/obj/item/clothing/suit/hooded/wintercoat/cmo
name = "chief medical officer's winter coat"
+ desc = "An arctic white winter coat with a small blue caduceus instead of a plastic zipper tab. The normal liner is replaced with an exceptionally thick, soft layer of fur."
icon_state = "coatcmo"
item_state = "coatcmo"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
@@ -591,10 +600,12 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/cmo
/obj/item/clothing/head/hooded/winterhood/cmo
+ desc = "A white winter coat hood."
icon_state = "winterhood_cmo"
/obj/item/clothing/suit/hooded/wintercoat/chemistry
name = "chemistry winter coat"
+ desc = "A lab-grade winter coat made with acid resistant polymers. For the enterprising chemist who was exiled to a frozen wasteland on the go."
icon_state = "coatchemistry"
item_state = "coatchemistry"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
@@ -602,10 +613,12 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/chemistry
/obj/item/clothing/head/hooded/winterhood/chemistry
+ desc = "A white winter coat hood."
icon_state = "winterhood_chemistry"
/obj/item/clothing/suit/hooded/wintercoat/viro
name = "virology winter coat"
+ desc = "A white winter coat with green markings. Warm, but wont fight off the common cold or any other disease. Might make people stand far away from you in the hallway. The zipper tab looks like an oversized bacteriophage."
icon_state = "coatviro"
item_state = "coatviro"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
@@ -613,10 +626,12 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/viro
/obj/item/clothing/head/hooded/winterhood/viro
+ desc = "A white winter coat hood with green markings."
icon_state = "winterhood_viro"
/obj/item/clothing/suit/hooded/wintercoat/science
name = "science winter coat"
+ desc = "A white winter coat with an outdated atomic model instead of a plastic zipper tab."
icon_state = "coatscience"
item_state = "coatscience"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
@@ -624,10 +639,12 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/science
/obj/item/clothing/head/hooded/winterhood/science
+ desc = "A white winter coat hood. This one will keep your brain warm. About as much as the others, really."
icon_state = "winterhood_science"
/obj/item/clothing/suit/hooded/wintercoat/robotics
name = "robotics winter coat"
+ desc = "A black winter coat with a badass flaming robotic skull for the zipper tab. This one has bright red designs and a few useless buttons."
icon_state = "coatrobotics"
item_state = "coatrobotics"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/screwdriver, /obj/item/crowbar, /obj/item/wrench, /obj/item/stack/cable_coil, /obj/item/weldingtool, /obj/item/multitool)
@@ -635,20 +652,24 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/robotics
/obj/item/clothing/head/hooded/winterhood/robotics
+ desc = "A black winter coat hood. You can pull it down over your eyes and pretend that you're an outdated, late 1980s interpretation of a futuristic mechanized police force. They'll fix you. They fix everything."
icon_state = "winterhood_robotics"
/obj/item/clothing/suit/hooded/wintercoat/genetics
name = "genetics winter coat"
+ desc = "A white winter coat with a DNA helix for the zipper tab. "
icon_state = "coatgenetics"
item_state = "coatgenetics"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
hoodtype = /obj/item/clothing/head/hooded/winterhood/genetics
/obj/item/clothing/head/hooded/winterhood/genetics
+ desc = "A white winter coat hood. It's warm."
icon_state = "winterhood_genetics"
/obj/item/clothing/suit/hooded/wintercoat/rd
name = "research director's winter coat"
+ desc = "A thick arctic winter coat with an outdated atomic model instead of a plastic zipper tab. Most in the know are heavily aware that Bohr's model of the atom was outdated by the time of the 1930s when the Heisenbergian and Schrodinger models were generally accepted for true. Nevertheless, we still see its use in anachronism, roleplaying, and, in this case, as a zipper tab. At least it should keep you warm on your ivory pillar."
icon_state = "coatrd"
item_state = "coatrd"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
@@ -656,10 +677,12 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/rd
/obj/item/clothing/head/hooded/winterhood/rd
+ desc = "A white winter coat hood. It smells faintly of hair gel."
icon_state = "winterhood_rd"
/obj/item/clothing/suit/hooded/wintercoat/ce
name = "chief engineer's winter coat"
+ desc = "A white winter coat with reflective green and yellow stripes. Stuffed with asbestos, treated with fire retardant PBDE, lined with a micro thin sheet of lead foil and snugly fitted to your body's measurements. This baby's ready to save you from anything except the thyroid cancer and systemic fibrosis you'll get from wearing it. The zipper tab is a tiny golden wrench."
icon_state = "coatce"
item_state = "coatce"
armor = list("melee" = 0, "bullet" = 0, "laser" = 5, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 30, "fire" = 35, "acid" = 45)
@@ -667,10 +690,12 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/ce
/obj/item/clothing/head/hooded/winterhood/ce
+ desc = "A white winter coat hood. Feels surprisingly heavy. The tag says that it's not child safe."
icon_state = "winterhood_ce"
/obj/item/clothing/suit/hooded/wintercoat/engineering
name = "engineering winter coat"
+ desc = "A surprisingly heavy yellow winter coat with reflective orange stripes. It has a small wrench for its zipper tab, and the inside layer is covered with a radiation-resistant silver-nylon blend. Because you're worth it."
icon_state = "coatengineer"
item_state = "coatengineer"
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 20, "fire" = 30, "acid" = 45)
@@ -678,29 +703,35 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering
/obj/item/clothing/head/hooded/winterhood/engineering
+ desc = "A yellow winter coat hood. Definitely not a replacement for a hard hat."
icon_state = "winterhood_engineer"
/obj/item/clothing/suit/hooded/wintercoat/engineering/atmos
name = "atmospherics winter coat"
+ desc = "A yellow and blue winter coat. The zipper pull-tab is made to look like a miniature breath mask."
icon_state = "coatatmos"
item_state = "coatatmos"
hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering/atmos
/obj/item/clothing/head/hooded/winterhood/engineering/atmos
+ desc = "A yellow and blue winter coat hood."
icon_state = "winterhood_atmos"
/obj/item/clothing/suit/hooded/wintercoat/hydro
name = "hydroponics winter coat"
+ desc = "A green and blue winter coat. The zipper tab looks like the flower from a member of Rosa Hesperrhodos, a pretty pink-and-white rose. The colors absolutely clash."
icon_state = "coathydro"
item_state = "coathydro"
allowed = list(/obj/item/reagent_containers/spray/plantbgone, /obj/item/plant_analyzer, /obj/item/seeds, /obj/item/reagent_containers/glass/bottle, /obj/item/cultivator, /obj/item/reagent_containers/spray/pestspray, /obj/item/hatchet, /obj/item/storage/bag/plants, /obj/item/toy, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
hoodtype = /obj/item/clothing/head/hooded/winterhood/hydro
/obj/item/clothing/head/hooded/winterhood/hydro
+ desc = "A green winter coat hood."
icon_state = "winterhood_hydro"
/obj/item/clothing/suit/hooded/wintercoat/cosmic
name = "cosmic winter coat"
+ desc = "A starry winter coat that even glows softly."
icon_state = "coatcosmic"
item_state = "coatcosmic"
hoodtype = /obj/item/clothing/head/hooded/winterhood/cosmic
@@ -708,48 +739,58 @@
light_range = 1.2
/obj/item/clothing/head/hooded/winterhood/cosmic
+ desc = "A starry winter hood."
icon_state = "winterhood_cosmic"
/obj/item/clothing/suit/hooded/wintercoat/janitor
name = "janitors winter coat"
+ desc = "A purple-and-beige winter coat that smells of space cleaner."
icon_state = "coatjanitor"
item_state = "coatjanitor"
allowed = list(/obj/item/toy, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/storage/fancy/cigarettes, /obj/item/lighter,/obj/item/grenade/chem_grenade,/obj/item/lightreplacer,/obj/item/flashlight,/obj/item/reagent_containers/glass/beaker,/obj/item/reagent_containers/glass/bottle,/obj/item/reagent_containers/spray,/obj/item/soap,/obj/item/holosign_creator,/obj/item/key/janitor,/obj/item/melee/flyswatter,/obj/item/paint/paint_remover,/obj/item/storage/bag/trash,/obj/item/reagent_containers/glass/bucket)
hoodtype = /obj/item/clothing/head/hooded/winterhood/janitor
/obj/item/clothing/head/hooded/winterhood/janitor
+ desc = "A purple hood that smells of space cleaner."
icon_state = "winterhood_janitor"
/obj/item/clothing/suit/hooded/wintercoat/cargo
name = "cargo winter coat"
+ desc = "A tan-and-grey winter coat that has a crate for its zipper pull tab. It fills you with the warmth of a fierce independence."
icon_state = "coatcargo"
item_state = "coatcargo"
hoodtype = /obj/item/clothing/head/hooded/winterhood/cargo
/obj/item/clothing/head/hooded/winterhood/cargo
+ desc = "A grey hood for a winter coat."
icon_state = "winterhood_cargo"
/obj/item/clothing/suit/hooded/wintercoat/qm
name = "quartermaster's winter coat"
+ desc = "A dark brown winter coat that has a golden crate pin for its zipper pully."
icon_state = "coatqm"
item_state = "coatqm"
hoodtype = /obj/item/clothing/head/hooded/winterhood/qm
/obj/item/clothing/head/hooded/winterhood/qm
+ desc = "A dark brown winter hood"
icon_state = "winterhood_qm"
/obj/item/clothing/suit/hooded/wintercoat/aformal
name = "assistant's formal winter coat"
+ desc = "A black button up winter coat."
icon_state = "coataformal"
item_state = "coataformal"
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter,/obj/item/clothing/gloves/color/yellow)
hoodtype = /obj/item/clothing/head/hooded/winterhood/aformal
/obj/item/clothing/head/hooded/winterhood/aformal
+ desc = "A black winter coat hood."
icon_state = "winterhood_aformal"
/obj/item/clothing/suit/hooded/wintercoat/miner
name = "mining winter coat"
+ desc = "A dusty button up winter coat. The zipper tab looks like a tiny pickaxe."
icon_state = "coatminer"
item_state = "coatminer"
allowed = list(/obj/item/pickaxe, /obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
@@ -757,10 +798,12 @@
hoodtype = /obj/item/clothing/head/hooded/winterhood/miner
/obj/item/clothing/head/hooded/winterhood/miner
+ desc = "A dusty winter coat hood."
icon_state = "winterhood_miner"
/obj/item/clothing/suit/hooded/wintercoat/ratvar
name = "ratvarian winter coat"
+ desc = "A brass-plated button up winter coat. Instead of a zipper tab, it has a brass cog with a tiny red gemstone inset."
icon_state = "coatratvar"
item_state = "coatratvar"
armor = list("melee" = 30, "bullet" = 45, "laser" = -10, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 60, "acid" = 60)
@@ -770,6 +813,7 @@
/obj/item/clothing/head/hooded/winterhood/ratvar
icon_state = "winterhood_ratvar"
+ desc = "A brass-plated winter hood that glows softly, hinting at its divinity."
light_range = 3
light_power = 1
light_color = "#B18B25" //clockwork slab background top color
@@ -788,6 +832,7 @@
/obj/item/clothing/suit/hooded/wintercoat/narsie
name = "narsian winter coat"
+ desc = "A somber button-up in tones of grey entropy and a wicked crimson zipper. When pulled all the way up, the zipper looks like a bloody gash. The zipper pull looks like a single drop of blood."
icon_state = "coatnarsie"
item_state = "coatnarsie"
armor = list("melee" = 30, "bullet" = 20, "laser" = 30,"energy" = 10, "bomb" = 30, "bio" = 10, "rad" = 10, "fire" = 30, "acid" = 30)
@@ -808,10 +853,12 @@
user.adjustBruteLoss(rand(10,16))
/obj/item/clothing/head/hooded/winterhood/narsie
+ desc = "A black winter hood full of whispering secrets that only She shall ever know."
icon_state = "winterhood_narsie"
/obj/item/clothing/suit/hooded/wintercoat/ratvar/fake
name = "brass winter coat"
+ desc = "A brass-plated button up winter coat. Instead of a zipper tab, it has a brass cog with a tiny red piece of plastic as an inset."
icon_state = "coatratvar"
item_state = "coatratvar"
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
@@ -820,6 +867,7 @@
/obj/item/clothing/suit/hooded/wintercoat/narsie/fake
name = "runed winter coat"
+ desc = "A dusty button up winter coat in the tones of oblivion and ash. The zipper pull looks like a single drop of blood."
icon_state = "coatnarsie"
item_state = "coatnarsie"
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
@@ -842,7 +890,6 @@
icon_state = "winterhood_durathread"
armor = list("melee" = 20, "bullet" = 8, "laser" = 15, "energy" = 8, "bomb" = 25, "bio" = 10, "rad" = 15, "fire" = 75, "acid" = 37)
-
/obj/item/clothing/suit/spookyghost
name = "spooky ghost"
desc = "This is obviously just a bedsheet, but maybe try it on?"
diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm
index dff62dd2c3..87e7098ebd 100644
--- a/code/modules/clothing/suits/reactive_armour.dm
+++ b/code/modules/clothing/suits/reactive_armour.dm
@@ -252,7 +252,7 @@
return
owner.visible_message("The reactive teleport system flings [H] clear of [attack_text] and slams [H.p_them()] into a fabricated table!")
owner.visible_message("[H] GOES ON THE TABLE!!!")
- owner.Knockdown(40)
+ owner.DefaultCombatKnockdown(40)
var/list/turfs = new/list()
for(var/turf/T in orange(tele_range, H))
if(T.density)
diff --git a/code/modules/clothing/under/jobs/medsci.dm b/code/modules/clothing/under/jobs/medsci.dm
index 971112ac38..3f31fb4717 100644
--- a/code/modules/clothing/under/jobs/medsci.dm
+++ b/code/modules/clothing/under/jobs/medsci.dm
@@ -159,22 +159,36 @@
fitted = FEMALE_UNIFORM_TOP
/obj/item/clothing/under/rank/medical/paramedic
- desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic."
+ desc = "It's made of a special fiber that provides minor protection against biohazards. It has a white cross on the chest denoting that the wearer is a trained paramedic."
name = "paramedic jumpsuit"
- icon_state = "paramedic"
+ icon_state = "paramedic-dark"
item_state = "w_suit"
+ item_color = "paramedic-dark"
permeability_coefficient = 0.5
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ can_adjust = FALSE
+
+/obj/item/clothing/under/rank/medical/paramedic/light
+ desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic."
+ icon_state = "paramedic-light"
+ item_color = "paramedic-light"
+ can_adjust = TRUE
/obj/item/clothing/under/rank/medical/paramedic/skirt
name = "paramedic jumpskirt"
- desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic."
- icon_state = "paramedic_skirt"
+ desc = "It's made of a special fiber that provides minor protection against biohazards. It has a white cross on the chest denoting that the wearer is a trained paramedic."
+ icon_state = "paramedic-dark_skirt"
item_state = "w_suit"
+ item_color = "paramedic-dark_skirt"
body_parts_covered = CHEST|GROIN|ARMS
can_adjust = FALSE
fitted = FEMALE_UNIFORM_TOP
+/obj/item/clothing/under/rank/medical/paramedic/skirt/light
+ desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic."
+ icon_state = "paramedic_skirt"
+ item_color = "paramedic_skirt"
+
/obj/item/clothing/under/rank/nursesuit
desc = "It's a jumpsuit commonly worn by nursing staff in the medical department."
name = "nurse's suit"
@@ -186,6 +200,7 @@
body_parts_covered = CHEST|GROIN|ARMS
fitted = NO_FEMALE_UNIFORM
can_adjust = FALSE
+
/obj/item/clothing/under/rank/medical
desc = "It's made of a special fiber that provides minor protection against biohazards. It has a cross on the chest denoting that the wearer is trained medical personnel."
name = "medical doctor's jumpsuit"
@@ -194,18 +209,21 @@
item_color = "medical"
permeability_coefficient = 0.5
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+
/obj/item/clothing/under/rank/medical/blue
name = "blue medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue."
icon_state = "scrubsblue"
item_color = "scrubsblue"
can_adjust = FALSE
+
/obj/item/clothing/under/rank/medical/green
name = "green medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in dark green."
icon_state = "scrubsgreen"
item_color = "scrubsgreen"
can_adjust = FALSE
+
/obj/item/clothing/under/rank/medical/purple
name = "purple medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in deep purple."
@@ -221,4 +239,4 @@
item_color = "medical_skirt"
body_parts_covered = CHEST|GROIN|ARMS
can_adjust = FALSE
- fitted = FEMALE_UNIFORM_TOP
+ fitted = FEMALE_UNIFORM_TOP
\ No newline at end of file
diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm
index 7df089d49c..68c5d8c5c8 100644
--- a/code/modules/events/disease_outbreak.dm
+++ b/code/modules/events/disease_outbreak.dm
@@ -63,7 +63,7 @@
else
D = new virus_type()
else
- D = new /datum/disease/advance/random(max_severity, max_severity)
+ D = new /datum/disease/advance/random(TRUE, max_severity, max_severity)
D.carrier = TRUE
H.ForceContractDisease(D, FALSE, TRUE)
diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm
index b289c8ae1b..5bb3862422 100644
--- a/code/modules/events/grid_check.dm
+++ b/code/modules/events/grid_check.dm
@@ -13,7 +13,4 @@
/datum/round_event/grid_check/start()
- for(var/P in GLOB.apcs_list)
- var/obj/machinery/power/apc/C = P
- if(C.cell && is_station_level(C.z))
- C.energy_fail(rand(30,120))
\ No newline at end of file
+ power_fail(30, 120)
\ No newline at end of file
diff --git a/code/modules/fields/peaceborg_dampener.dm b/code/modules/fields/peaceborg_dampener.dm
index 79bd866fca..13a2bc0135 100644
--- a/code/modules/fields/peaceborg_dampener.dm
+++ b/code/modules/fields/peaceborg_dampener.dm
@@ -42,7 +42,7 @@
if(R.has_buckled_mobs())
for(var/mob/living/L in R.buckled_mobs)
L.visible_message("[L] is knocked off of [R] by the charge in [R]'s chassis induced by [name]!") //I know it's bad.
- L.Knockdown(10)
+ L.DefaultCombatKnockdown(10)
R.unbuckle_mob(L)
do_sparks(5, 0, L)
..()
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index b0c3121c67..ea475b28d6 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -220,8 +220,8 @@ GLOBAL_LIST_INIT(hallucination_list, list(
/obj/effect/hallucination/simple/xeno/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
update_icon("alienh_pounce")
- if(hit_atom == target && target.stat!=DEAD)
- target.Knockdown(100)
+ if(hit_atom == target && target.stat != DEAD)
+ target.DefaultCombatKnockdown(100)
target.visible_message("[target] flails around wildly.","[name] pounces on you!")
/datum/hallucination/xeno_attack
@@ -308,7 +308,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
shake_camera(target, 2, 1)
if(bubblegum.Adjacent(target) && !charged)
charged = TRUE
- target.Knockdown(80)
+ target.DefaultCombatKnockdown(80)
target.adjustStaminaLoss(40)
step_away(target, bubblegum)
shake_camera(target, 4, 3)
@@ -1106,7 +1106,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
if(istype(target, /obj/effect/dummy/phased_mob))
return
to_chat(target, "You fall into the chasm!")
- target.Knockdown(40)
+ target.DefaultCombatKnockdown(40)
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, target, "It's surprisingly shallow."), 15)
QDEL_IN(src, 30)
@@ -1245,7 +1245,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
/datum/hallucination/shock/proc/shock_drop()
target.jitteriness = max(target.jitteriness - 990, 10) //Still jittery, but vastly less
- target.Knockdown(60)
+ target.DefaultCombatKnockdown(60)
/datum/hallucination/husks
@@ -1318,7 +1318,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
"[G] grabs your wrist and violently wrenches it to the side!")
C.emote("scream")
C.dropItemToGround(C.get_active_held_item())
- C.Knockdown(60)
+ C.DefaultCombatKnockdown(60)
else
to_chat(C,"[G] violently grabs you!")
qdel(src)
diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
index 07026e79de..b38250e39d 100644
--- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
@@ -51,7 +51,7 @@
head_attack_message = " on the head"
//Knockdown the target for the duration that we calculated and divide it by 5.
if(armor_duration)
- target.Knockdown(min(armor_duration, 200)) // Never knockdown more than a flash!
+ target.DefaultCombatKnockdown(min(armor_duration, 200)) // Never knockdown more than a flash!
//Display an attack message.
if(target != user)
diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm
index 9bf95f65db..83a03ed2d9 100644
--- a/code/modules/food_and_drinks/food/snacks_meat.dm
+++ b/code/modules/food_and_drinks/food/snacks_meat.dm
@@ -225,7 +225,7 @@
if(iscarbon(M))
M.visible_message("[src] bursts out of [M]!")
M.emote("scream")
- M.Knockdown(40)
+ M.DefaultCombatKnockdown(40)
M.adjustBruteLoss(60)
Expand()
return ..()
diff --git a/code/modules/food_and_drinks/food/snacks_pie.dm b/code/modules/food_and_drinks/food/snacks_pie.dm
index 1533f067ab..b3ad6b5126 100644
--- a/code/modules/food_and_drinks/food/snacks_pie.dm
+++ b/code/modules/food_and_drinks/food/snacks_pie.dm
@@ -49,7 +49,7 @@
else
creamoverlay.icon_state = "creampie_human"
if(stunning)
- H.Knockdown(20) //splat!
+ H.DefaultCombatKnockdown(20) //splat!
H.adjust_blurriness(1)
H.visible_message("[H] is creamed by [src]!", "You've been creamed by [src]!")
playsound(H, "desceration", 50, TRUE)
@@ -83,7 +83,7 @@
A.throw_at(T, 1, 1)
M.visible_message("[src] bursts out of [M]!")
M.emote("scream")
- M.Knockdown(40)
+ M.DefaultCombatKnockdown(40)
M.adjustBruteLoss(60)
return ..()
diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
index f3b8e466f3..1215dd7ecb 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
@@ -152,6 +152,6 @@ God bless America.
reagents.reaction(C, TOUCH)
C.apply_damage(min(30, reagents.total_volume), BURN, BODY_ZONE_HEAD)
reagents.remove_any((reagents.total_volume/2))
- C.Knockdown(60)
+ C.DefaultCombatKnockdown(60)
user.changeNext_move(CLICK_CD_MELEE)
return ..()
diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm
index eddd1bdc3f..24dd99e5e0 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm
@@ -310,7 +310,7 @@
for(var/obj/item/O in ingredients)
O.microwave_act(src)
if(O.custom_materials?.len)
- metal += O.custom_materials[getmaterialref(/datum/material/iron)]
+ metal += O.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]
if(metal)
spark()
diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
index b81c127523..3fa188fb94 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
@@ -132,7 +132,8 @@
set name = "Eject Contents"
set src in oview(1)
- if(usr.stat || !usr.canmove || usr.restrained())
+ var/mob/living/L = usr
+ if(!istype(L) || !CHECK_MOBILITY(L, MOBILITY_USE))
return
empty()
add_fingerprint(usr)
diff --git a/code/modules/food_and_drinks/recipes/drinks_recipes.dm b/code/modules/food_and_drinks/recipes/drinks_recipes.dm
index 59b2e7838a..2cb0141728 100644
--- a/code/modules/food_and_drinks/recipes/drinks_recipes.dm
+++ b/code/modules/food_and_drinks/recipes/drinks_recipes.dm
@@ -620,7 +620,7 @@
results = list(/datum/reagent/consumable/ethanol/quintuple_sec = 15)
required_reagents = list(/datum/reagent/consumable/ethanol/quadruple_sec = 5, /datum/reagent/consumable/clownstears = 5, /datum/reagent/consumable/ethanol/syndicatebomb = 5)
mix_message = "Judgement is upon you."
- mix_message = 'sound/items/airhorn2.ogg'
+ mix_sound = 'sound/items/airhorn2.ogg'
/datum/chemical_reaction/bastion_bourbon
name = "Bastion Bourbon"
diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm
index 2b116bbfd3..638d1427bc 100644
--- a/code/modules/holiday/halloween/jacqueen.dm
+++ b/code/modules/holiday/halloween/jacqueen.dm
@@ -46,6 +46,8 @@
var/progression = list() //Keep track of where people are in the story.
var/active = TRUE //Turn this to false to keep normal mob behavour
var/cached_z
+ /// I'm busy chatting, don't move.
+ var/busy_chatting = FALSE
/mob/living/simple_animal/jacq/Initialize()
..()
@@ -76,9 +78,9 @@
say("Hello there [gender_check(M)]!")
return ..()
if(!ckey)
- canmove = FALSE
+ busy_chatting = FALSE
chit_chat(M)
- canmove = TRUE
+ busy_chatting = TRUE
..()
/mob/living/simple_animal/jacq/attack_paw(mob/living/carbon/monkey/M)
@@ -86,9 +88,9 @@
say("Hello there [gender_check(M)]!")
return ..()
if(!ckey)
- canmove = FALSE
+ busy_chatting = FALSE
chit_chat(M)
- canmove = TRUE
+ busy_chatting = TRUE
..()
/mob/living/simple_animal/jacq/proc/poof()
@@ -99,7 +101,7 @@
s.set_up(R, 0, loc)
s.start()
visible_message("No container inside, please insert container.
"
@@ -233,14 +233,14 @@
menustat = "void"
/obj/machinery/biogenerator/proc/check_cost(list/materials, multiplier = 1, remove_points = TRUE)
- if(materials.len != 1 || materials[1] != getmaterialref(/datum/material/biomass))
+ if(materials.len != 1 || materials[1] != SSmaterials.GetMaterialRef(/datum/material/biomass))
return FALSE
- if (materials[getmaterialref(/datum/material/biomass)]*multiplier/efficiency > points)
+ if (materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency > points)
menustat = "nopoints"
return FALSE
else
if(remove_points)
- points -= materials[getmaterialref(/datum/material/biomass)]*multiplier/efficiency
+ points -= materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency
update_icon()
updateUsrDialog()
return TRUE
diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm
index c3bd82c624..0979ea483f 100644
--- a/code/modules/hydroponics/grown/nettle.dm
+++ b/code/modules/hydroponics/grown/nettle.dm
@@ -98,7 +98,7 @@
/obj/item/reagent_containers/food/snacks/grown/nettle/death/pickup(mob/living/carbon/user)
if(..())
if(prob(50))
- user.Knockdown(100)
+ user.DefaultCombatKnockdown(100)
to_chat(user, "