[round((health / maxHealth) * 100, 0.5)]%"
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/update_stats()
+ if(GLOB.ratvar_awakens)
+ speed = 0
+ melee_damage_lower = 20
+ melee_damage_upper = 20
+ attack_verb_continuous = "devastates"
+ else
+ var/healthpercent = (health/maxHealth) * 100
+ switch(healthpercent)
+ if(100 to 70) //Bonuses to speed and damage at high health
+ speed = 0
+ melee_damage_lower = 16
+ melee_damage_upper = 16
+ attack_verb_continuous = "viciously slashes"
+ if(70 to 40)
+ speed = initial(speed)
+ melee_damage_lower = initial(melee_damage_lower)
+ melee_damage_upper = initial(melee_damage_upper)
+ attack_verb_continuous = initial(attack_verb_continuous)
+ if(40 to 30) //Damage decrease, but not speed
+ speed = initial(speed)
+ melee_damage_lower = 10
+ melee_damage_upper = 10
+ attack_verb_continuous = "lightly slashes"
+ if(30 to 20) //Speed decrease
+ speed = 2
+ melee_damage_lower = 8
+ melee_damage_upper = 8
+ attack_verb_continuous = "lightly slashes"
+ if(20 to 10) //Massive speed decrease and weak melee attacks
+ speed = 3
+ melee_damage_lower = 6
+ melee_damage_upper = 6
+ attack_verb_continuous = "weakly slashes"
+ if(10 to 0) //We are super weak and going to die
+ speed = 4
+ melee_damage_lower = 4
+ melee_damage_upper = 4
+ attack_verb_continuous = "taps"
+
+//ATTACKING, BLOCKING, and COUNTERING
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/AttackingTarget()
+ if(is_in_host())
+ return FALSE
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/bullet_act(obj/item/projectile/Proj)
+ if(blockOrCounter(null, Proj))
+ return
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/hitby(atom/movable/AM, skipcatch, hitpush, blocked, atom/movable/AM, datum/thrownthing/throwingdatum)
+ if(blockOrCounter(null, AM))
+ return
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_animal(mob/living/simple_animal/M)
+ if(istype(M, /mob/living/simple_animal/hostile/clockwork/marauder/guardian) || !blockOrCounter(M, M)) //we don't want infinite blockcounter loops if fighting another guardian
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_paw(mob/living/carbon/monkey/M)
+ if(!blockOrCounter(M, M))
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_alien(mob/living/carbon/alien/humanoid/M)
+ if(!blockOrCounter(M, M))
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_slime(mob/living/simple_animal/slime/M)
+ if(!blockOrCounter(M, M))
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_hand(mob/living/carbon/human/M)
+ if(!blockOrCounter(M, M))
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/nullrod) || !blockOrCounter(user, I))
+ return ..()
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/blockOrCounter(mob/target, atom/textobject)
+ if(GLOB.ratvar_awakens) //if ratvar has woken, we block nearly everything at a very high chance
+ blockchance = 90
+ counterchance = 90
+ if(prob(blockchance))
+ . = TRUE
+ if(target)
+ target.do_attack_animation(src)
+ target.DelayNextAction(CLICK_CD_MELEE)
+ blockchance = initial(blockchance)
+ playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 30, 1, 0, 1) //clang
+ visible_message("
[src] blocks [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!", \
+ "
You block [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!")
+ if(target && Adjacent(target))
+ if(prob(counterchance))
+ counterchance = initial(counterchance)
+ var/previousattack_verb_continuous = attack_verb_continuous
+ attack_verb_continuous = "counters"
+ UnarmedAttack(target)
+ attack_verb_continuous = previousattack_verb_continuous
+ else
+ counterchance = min(counterchance + initial(counterchance), 100)
+ else
+ blockchance = min(blockchance + initial(blockchance), 100)
+ if(GLOB.ratvar_awakens)
+ blockchance = 90
+ counterchance = 90
+
+//COMMUNICATION and EMERGENCE
+/*
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/handle_inherent_channels(message, message_mode)
+ if(host && (is_in_host() || message_mode == MODE_BINARY))
+ guardian_comms(message)
+ return TRUE
+ return ..()
+*/
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/guardian_comms(message)
+ var/name_part = "
[src] ([true_name])"
+ message = "
\"[message]\"" //Processed output
+ to_chat(src, "[name_part]
: [message]")
+ to_chat(host, "[name_part]
: [message]")
+ for(var/M in GLOB.mob_list)
+ if(isobserver(M))
+ var/link = FOLLOW_LINK(M, src)
+ to_chat(M, "[link] [name_part]
(to [findtextEx(host.name, host.real_name) ? "[host.name]" : "[host.real_name] (as [host.name])"]): [message] ")
+ return TRUE
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/return_to_host()
+ if(is_in_host())
+ return FALSE
+ if(!host)
+ to_chat(src, "
You don't have a host!")
+ return FALSE
+ var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
+ if(iscarbon(host))
+ resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
+ host.visible_message("
[host]'s skin flashes crimson!", "
You feel [true_name]'s consciousness settle in your mind.")
+ visible_message("
[src] suddenly disappears!", "
You return to [host].")
+ forceMove(host)
+ if(resulthealth > GUARDIAN_EMERGE_THRESHOLD && health != maxHealth)
+ recovering = TRUE
+ to_chat(src, "
You have weakened and will need to recover before manifesting again!")
+ to_chat(host, "
[true_name] has weakened and will need to recover before manifesting again!")
+ return TRUE
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/try_emerge()
+ if(!host)
+ to_chat(src, "
You don't have a host!")
+ return FALSE
+ if(!GLOB.ratvar_awakens)
+ var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5)
+ if(iscarbon(host))
+ resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)
+ if(host.stat != DEAD && resulthealth > GUARDIAN_EMERGE_THRESHOLD) //if above 20 health, fails
+ to_chat(src, "
Your host must be at [GUARDIAN_EMERGE_THRESHOLD]% or less health to emerge like this!")
+ return FALSE
+ return emerge_from_host(FALSE)
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/emerge_from_host(hostchosen, force) //Notice that this is a proc rather than a verb - guardians can NOT exit at will, but they CAN return
+ if(!is_in_host())
+ return FALSE
+ if(!force && recovering)
+ if(hostchosen)
+ to_chat(host, "
[true_name] is too weak to come forth!")
+ else
+ to_chat(host, "
[true_name] tries to emerge to protect you, but it's too weak!")
+ to_chat(src, "
You try to come forth, but you're too weak!")
+ return FALSE
+ if(!force)
+ if(hostchosen) //guardian approved
+ to_chat(host, "
Your words echo with power as [true_name] emerges from your body!")
+ else
+ to_chat(host, "
[true_name] emerges from your body to protect you!")
+ forceMove(host.loc)
+ visible_message("
[host]'s skin glows red as [name] emerges from their body!", "
You exit the safety of [host]'s body!")
+ return TRUE
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/get_alt_name()
+ return " ([text2ratvar(true_name)])"
+
+/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/is_in_host() //Checks if the guardian is inside of their host
+ return host && loc == host
+
+//HOST ACTIONS
+
+//Summon guardian action: Calls forth or recalls your guardian
+/datum/action/innate/summon_guardian
+ name = "Force Guardian to Emerge/Recall"
+ desc = "Allows you to force your clockwork guardian to emerge or recall as required."
+ button_icon_state = "clockwork_marauder"
+ background_icon_state = "bg_clock"
+ check_flags = AB_CHECK_CONSCIOUS
+ buttontooltipstyle = "clockcult"
+ var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/linked_guardian
+ var/list/defend_phrases = list("Defend me", "Come forth", "Assist me", "Protect me", "Give aid", "Help me")
+ var/list/return_phrases = list("Return", "Return to me", "Your job is done", "You have served", "Come back", "Retreat")
+
+/datum/action/innate/summon_guardian/IsAvailable()
+ if(!linked_guardian)
+ return FALSE
+ if(isliving(owner))
+ var/mob/living/L = owner
+ if(!L.can_speak_vocal() || L.stat)
+ return FALSE
+ return ..()
+
+/datum/action/innate/summon_guardian/Activate()
+ if(linked_guardian.is_in_host())
+ clockwork_say(owner, text2ratvar("[pick(defend_phrases)], [linked_guardian.true_name]!"))
+ linked_guardian.emerge_from_host(TRUE)
+ else
+ clockwork_say(owner, text2ratvar("[pick(return_phrases)], [linked_guardian.true_name]!"))
+ linked_guardian.return_to_host()
+ return TRUE
+
+//Linked Minds action: talks to your guardian
+/datum/action/innate/linked_minds
+ name = "Linked Minds"
+ desc = "Allows you to silently communicate with your guardian."
+ button_icon_state = "linked_minds"
+ background_icon_state = "bg_clock"
+ check_flags = AB_CHECK_CONSCIOUS
+ buttontooltipstyle = "clockcult"
+ var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/linked_guardian
+
+/datum/action/innate/linked_minds/IsAvailable()
+ if(!linked_guardian)
+ return FALSE
+ return ..()
+
+/datum/action/innate/linked_minds/Activate()
+ var/message = stripped_input(owner, "Enter a message to tell your guardian.", "Telepathy")
+ if(!owner || !message)
+ return FALSE
+ if(!linked_guardian)
+ to_chat(owner, "
Your guardian seems to have been destroyed!")
+ return FALSE
+ var/name_part = "
Servant [findtextEx(owner.name, owner.real_name) ? "[owner.name]" : "[owner.real_name] (as [owner.name])"]"
+ message = "
\"[message]\"" //Processed output
+ to_chat(owner, "[name_part]
: [message]")
+ to_chat(linked_guardian, "[name_part]
: [message]")
+ for(var/M in GLOB.mob_list)
+ if(isobserver(M))
+ var/link = FOLLOW_LINK(M, src)
+ to_chat(M, "[link] [name_part]
(to [linked_guardian] ([linked_guardian.true_name])): [message]")
+ return TRUE
diff --git a/code/modules/antagonists/clockcult/clock_scripture.dm b/code/modules/antagonists/clockcult/clock_scripture.dm
index 1ebefe4d05..a85245e9d0 100644
--- a/code/modules/antagonists/clockcult/clock_scripture.dm
+++ b/code/modules/antagonists/clockcult/clock_scripture.dm
@@ -3,8 +3,9 @@ Tiers and Requirements
Pieces of scripture require certain follower counts, contruction value, and active caches in order to recite.
Drivers: Unlocked by default
-Scripts: 5 servants and a cache
-Applications: 8 servants, 3 caches, and 100 CV
+Scripts: 35k power or one convert
+Applications: 50k or three converts
+Judgement 5 converts
*/
/datum/clockwork_scripture
@@ -129,11 +130,11 @@ Applications: 8 servants, 3 caches, and 100 CV
SEND_SOUND(invoker, sound('sound/magic/clockwork/invoke_general.ogg'))
return TRUE
-/datum/clockwork_scripture/proc/check_offstation_penalty()
+/datum/clockwork_scripture/proc/check_offstation_penalty()//don't cast spells away from the station
var/turf/T = get_turf(invoker)
if(!T || (!is_centcom_level(T.z) && !is_station_level(T.z) && !is_mining_level(T.z) && !is_reebe(T.z)))
- channel_time *= 2
- power_cost *= 2
+ channel_time *= 3
+ power_cost *= 3
return TRUE
/datum/clockwork_scripture/proc/check_special_requirements() //Special requirements for scriptures, checked multiple times during invocation
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm
index ffe9ecfa80..cbf3bdaa38 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm
@@ -1,5 +1,5 @@
//////////////////
-// APPLICATIONS //
+// APPLICATIONS // For various structures and base building, as well as advanced power generation.
//////////////////
@@ -23,6 +23,37 @@
quickbind = TRUE
quickbind_desc = "Creates a Sigil of Transmission, which can drain and will store power for clockwork structures."
+//Prolonging Prism: Creates a prism that will delay the shuttle at a power cost
+/datum/clockwork_scripture/create_object/prolonging_prism
+ descname = "Powered Structure, Delay Emergency Shuttles"
+ name = "Prolonging Prism"
+ desc = "Creates a mechanized prism which will delay the arrival of an emergency shuttle by 2 minutes at a massive power cost."
+ invocations = list("May this prism...", "...grant us time to enact his will!")
+ channel_time = 80
+ power_cost = 300
+ object_path = /obj/structure/destructible/clockwork/powered/prolonging_prism
+ creator_message = "
You form a prolonging prism, which will delay the arrival of an emergency shuttle at a massive power cost."
+ observer_message = "
An onyx prism forms in midair and sprouts tendrils to support itself!"
+ invokers_required = 2
+ multiple_invokers_used = TRUE
+ usage_tip = "The power cost to delay a shuttle increases based on the number of times activated."
+ tier = SCRIPTURE_APPLICATION
+ one_per_tile = TRUE
+ primary_component = VANGUARD_COGWHEEL
+ sort_priority = 4
+ important = TRUE
+ quickbind = TRUE
+ quickbind_desc = "Creates a Prolonging Prism, which will delay the arrival of an emergency shuttle by 2 minutes at a massive power cost."
+
+/datum/clockwork_scripture/create_object/prolonging_prism/check_special_requirements()
+ if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
+ to_chat(invoker, "
\"It is too late to construct one of these, champion.\"")
+ return FALSE
+ var/turf/T = get_turf(invoker)
+ if(!T || !is_station_level(T.z))
+ to_chat(invoker, "
\"You must be on the station to construct one of these, champion.\"")
+ return FALSE
+ return ..()
//Mania Motor: Creates a malevolent transmitter that will broadcast the whispers of Sevtug into the minds of nearby nonservants, causing a variety of mental effects at a power cost.
/datum/clockwork_scripture/create_object/mania_motor
@@ -44,6 +75,7 @@
sort_priority = 2
quickbind = TRUE
quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants."
+ requires_full_power = TRUE
//Clockwork Obelisk: Creates a powerful obelisk that can be used to broadcast messages or open a gateway to any servant or clockwork obelisk at a power cost.
@@ -67,6 +99,64 @@
quickbind = TRUE
quickbind_desc = "Creates a Clockwork Obelisk, which can send messages or open Spatial Gateways with power."
+//Memory Allocation: Finds a willing ghost and makes them into a clockwork guardian for the invoker.
+/datum/clockwork_scripture/memory_allocation
+ descname = "Personal Guardian, A Peice Of Your Mind."
+ name = "Memory Allocation"
+ desc = "Allocates part of your consciousness to a Clockwork Guardian, a variant of Marauder that lives within you, able to be \
+ called forth by Speaking its True Name or if you become exceptionally low on health.
\
+ If it remains close to you, you will gradually regain health up to a low amount, but it will die if it goes too far from you."
+ invocations = list("Fright's will...", "...call forth...")
+ channel_time = 100
+ power_cost = 8000
+ usage_tip = "guardians are useful as personal bodyguards and frontline warriors."
+ tier = SCRIPTURE_APPLICATION
+ primary_component = GEIS_CAPACITOR
+ sort_priority = 5
+
+/datum/clockwork_scripture/memory_allocation/check_special_requirements()
+ for(var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/M in GLOB.all_clockwork_mobs)
+ if(M.host == invoker)
+ to_chat(invoker, "
You can only house one guardian at a time!")
+ return FALSE
+ return TRUE
+
+/datum/clockwork_scripture/memory_allocation/scripture_effects()
+ return create_guardian()
+
+/datum/clockwork_scripture/memory_allocation/proc/create_guardian()
+ invoker.visible_message("
A purple tendril appears from [invoker]'s [slab.name] and impales itself in [invoker.p_their()] forehead!", \
+ "
A tendril flies from [slab] into your forehead. You begin waiting while it painfully rearranges your thought pattern...")
+ //invoker.notransform = TRUE //Vulnerable during the process
+ slab.busy = "Thought Modification in progress"
+ if(!do_after(invoker, 50, target = invoker))
+ invoker.visible_message("
The tendril, covered in blood, retracts from [invoker]'s head and back into the [slab.name]!", \
+ "
Total agony overcomes you as the tendril is forced out early!")
+ invoker.Knockdown(100)
+ invoker.apply_damage(50, BRUTE, "head")//Sevtug leaves a gaping hole in your face if interrupted.
+ slab.busy = null
+ return FALSE
+ clockwork_say(invoker, text2ratvar("...the mind made..."))
+ //invoker.notransform = FALSE
+ slab.busy = "Guardian Selection in progress"
+ if(!check_special_requirements())
+ return FALSE
+ to_chat(invoker, "
The tendril shivers slightly as it selects a guardian...")
+ var/list/marauder_candidates = pollGhostCandidates("Do you want to play as the clockwork guardian of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_HOLOPARASITE)
+ if(!check_special_requirements())
+ return FALSE
+ if(!marauder_candidates.len)
+ invoker.visible_message("
The tendril retracts from [invoker]'s head, sealing the entry wound as it does so!", \
+ "
The tendril was unsuccessful! Perhaps you should try again another time.")
+ return FALSE
+ clockwork_say(invoker, text2ratvar("...sword and shield!"))
+ var/mob/dead/observer/theghost = pick(marauder_candidates)
+ var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/M = new(invoker)
+ M.key = theghost.key
+ M.bind_to_host(invoker)
+ invoker.visible_message("
The tendril retracts from [invoker]'s head, sealing the entry wound as it does so!", \
+ "
[M.true_name], a clockwork guardian, has taken up residence in your mind. Communicate with it via the \"Linked Minds\" action button.")
+ return TRUE
//Clockwork Marauder: Creates a construct shell for a clockwork marauder, a well-rounded frontline fighter.
/datum/clockwork_scripture/create_object/construct/clockwork_marauder
@@ -81,7 +171,7 @@
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = BELLIGERENT_EYE
- sort_priority = 4
+ sort_priority = 6
quickbind = TRUE
quickbind_desc = "Creates a clockwork marauder, used for frontline combat."
object_path = /obj/item/clockwork/construct_chassis/clockwork_marauder
@@ -117,14 +207,13 @@
/datum/clockwork_scripture/create_object/summon_arbiter
descname = "Powerful Assault Mech"
name = "Summon Neovgre, the Anima Bulwark"
- desc = "Calls forth the mighty Anima Bulwark, a weapon of unmatched power,\
- mech with superior defensive and offensive capabilities. It will \
+ desc = "Calls forth the mighty Anima Bulwark, a mech with superior defensive and offensive capabilities. It will \
steadily regenerate HP and triple its regeneration speed while standing \
on a clockwork tile. It will automatically draw power from nearby sigils of \
transmission should the need arise. Its Arbiter laser cannon can decimate foes \
from a range and is capable of smashing through any barrier presented to it. \
- Be warned, choosing to pilot Neovgre is a lifetime commitment, once you are \
- in you cannot leave and when it is destroyed it will explode catastrophically with you inside."
+ Be warned however, choosing to pilot Neovgre is a lifetime commitment, once you are \
+ in you cannot leave and when it is destroyed it will explode catastrophically, with you inside."
invocations = list("By the strength of the alloy...!!", "...call forth the Arbiter!!")
channel_time = 200 // This is a strong fucking weapon, 20 seconds channel time is getting off light I tell ya.
power_cost = 75000 //75 KW
@@ -134,7 +223,7 @@
object_path = /obj/mecha/combat/neovgre
tier = SCRIPTURE_APPLICATION
primary_component = BELLIGERENT_EYE
- sort_priority = 2
+ sort_priority = 7
creator_message = "
Neovgre, the Anima Bulwark towers over you... your enemies reckoning has come."
/datum/clockwork_scripture/create_object/summon_arbiter/check_special_requirements()
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm
index 819dfac72e..3dacecf6b4 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm
@@ -1,5 +1,5 @@
/////////////////
-// CYBORG ONLY //
+// CYBORG ONLY // Cyborgs only, fleshed ones.
/////////////////
//Linked Vanguard: grants Vanguard to the invoker and a target
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
index 6349ecb581..00c4d73428 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
@@ -1,5 +1,5 @@
/////////////
-// DRIVERS //
+// DRIVERS // Starter spells
/////////////
//Stargazer: Creates a stargazer, a cheap power generator that utilizes starlight.
@@ -97,7 +97,7 @@
desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
invocations = list("Divinity, show them your light!")
whispered = TRUE
- channel_time = 20 // I think making kindle channel a third of the time less is a good make up for the fact that it silences people for such a little amount of time.
+ channel_time = 15 // I think making kindle channel a third of the time less is a good make up for the fact that it silences people for such a little amount of time.
power_cost = 125
usage_tip = "The light can be used from up to two tiles away. Damage taken will GREATLY REDUCE the stun's duration."
tier = SCRIPTURE_DRIVER
@@ -113,7 +113,6 @@
quickbind = TRUE
quickbind_desc = "Stuns and mutes a target from a short range."
-
//Hateful Manacles: Applies restraints from melee over several seconds. The restraints function like handcuffs and break on removal.
/datum/clockwork_scripture/ranged_ability/hateful_manacles
descname = "Handcuffs"
@@ -192,43 +191,39 @@
Click your slab to cancel."
+/*//commenting this out until its reworked to actually do random teleports
//Abscond: Used to return to Reebe.
/datum/clockwork_scripture/abscond
- descname = "Return to Reebe"
+ descname = "Safety warp, teleports you somewhere random. moderately high power cost to use."
name = "Abscond"
- desc = "Yanks you through space, returning you to home base."
+ desc = "Yanks you through space, putting you in hopefully a safe location."
invocations = list("As we bid farewell, and return to the stars...", "...we shall find our way home.")
whispered = TRUE
- channel_time = 50
- power_cost = 5
- special_power_text = "POWERCOST to bring pulled creature"
- special_power_cost = ABSCOND_ABDUCTION_COST
+ channel_time = 3.5
+ power_cost = 10000
usage_tip = "This can't be used while on Reebe, for obvious reasons."
tier = SCRIPTURE_DRIVER
primary_component = GEIS_CAPACITOR
sort_priority = 9
important = TRUE
quickbind = TRUE
- quickbind_desc = "Returns you to Reebe."
+ quickbind_desc = "Teleports you somewhere random, or to an active Ark if one exists. Use in emergencies."
var/client_color
requires_full_power = TRUE
/datum/clockwork_scripture/abscond/check_special_requirements()
if(is_reebe(invoker.z))
- to_chat(invoker, "
You're already at Reebe.")
+ to_chat(invoker, "
You're at Reebe, attempting to warp in the void could cause you to share your masters fate of banishment!.")
return
if(!isturf(invoker.loc))
- to_chat(invoker, "
You must be visible to return!")
+ to_chat(invoker, "
You must be visible to warp!")
return
return TRUE
/datum/clockwork_scripture/abscond/recital()
- client_color = invoker.client.color
- animate(invoker.client, color = "#AF0AAF", time = 50)
. = ..()
/datum/clockwork_scripture/abscond/scripture_effects()
- var/mob/living/pulled_mob = (invoker.pulling && isliving(invoker.pulling) && get_clockwork_power(ABSCOND_ABDUCTION_COST)) ? invoker.pulling : null
var/turf/T
if(GLOB.ark_of_the_clockwork_justiciar)
T = get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH)
@@ -237,21 +232,12 @@
if(!do_teleport(invoker, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE))
return
invoker.visible_message("
[invoker] flickers and phases out of existence!", \
- "
You feel a dizzying sense of vertigo as you're yanked back to Reebe!")
+ "
You feel a dizzying sense of vertigo as you're yanked through the fabric of reality!")
T.visible_message("
[invoker] flickers and phases into existence!")
playsound(invoker, 'sound/magic/magic_missile.ogg', 50, TRUE)
playsound(T, 'sound/magic/magic_missile.ogg', 50, TRUE)
do_sparks(5, TRUE, invoker)
- do_sparks(5, TRUE, T)
- if(pulled_mob && do_teleport(pulled_mob, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE))
- adjust_clockwork_power(-special_power_cost)
- invoker.start_pulling(pulled_mob) //forcemove resets pulls, so we need to re-pull
- if(invoker.client)
- animate(invoker.client, color = client_color, time = 25)
-
-/datum/clockwork_scripture/abscond/scripture_fail()
- if(invoker && invoker.client)
- animate(invoker.client, color = client_color, time = 10)
+ do_sparks(5, TRUE, T)*/
//Replicant: Creates a new clockwork slab.
@@ -265,7 +251,7 @@
whispered = TRUE
object_path = /obj/item/clockwork/slab
creator_message = "
You copy a piece of replicant alloy and command it into a new slab."
- usage_tip = "This is inefficient as a way to produce components, as the slab produced must be held by someone with no other slabs to produce components."
+ usage_tip = "This is inefficient as a way to produce power, as the slab produced must be held by someone with no other slabs to produce any."
tier = SCRIPTURE_DRIVER
space_allowed = TRUE
primary_component = GEIS_CAPACITOR
@@ -293,3 +279,50 @@
sort_priority = 11
quickbind = TRUE
quickbind_desc = "Creates a pair of Wraith Spectacles, which grant true sight but cause gradual vision loss."
+
+//Spatial Gateway: Allows the invoker to teleport themselves and any nearby allies to a conscious servant or clockwork obelisk.
+/datum/clockwork_scripture/spatial_gateway
+ descname = "Teleport Gate"
+ name = "Spatial Gateway"
+ desc = "Tears open a miniaturized gateway in spacetime to any conscious servant that can transport objects or creatures to its destination. \
+ Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
+ invocations = list("Spatial Gateway...", "...activate!")
+ channel_time = 30
+ power_cost = 400
+ whispered = TRUE
+ multiple_invokers_used = TRUE
+ multiple_invokers_optional = TRUE
+ usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
+ tier = SCRIPTURE_DRIVER
+ primary_component = GEIS_CAPACITOR
+ sort_priority = 9
+ quickbind = TRUE
+ quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk."
+
+/datum/clockwork_scripture/spatial_gateway/check_special_requirements()
+ if(!isturf(invoker.loc))
+ to_chat(invoker, "
You must not be inside an object to use this scripture!")
+ return FALSE
+ var/other_servants = 0
+ for(var/mob/living/L in GLOB.alive_mob_list)
+ if(is_servant_of_ratvar(L) && !L.stat && L != invoker)
+ other_servants++
+ for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in GLOB.all_clockwork_objects)
+ if(O.anchored)
+ other_servants++
+ if(!other_servants)
+ to_chat(invoker, "
There are no other conscious servants or anchored clockwork obelisks!")
+ return FALSE
+ return TRUE
+
+/datum/clockwork_scripture/spatial_gateway/scripture_effects()
+ var/portal_uses = 0
+ var/duration = 0
+ for(var/mob/living/L in range(1, invoker))
+ if(!L.stat && is_servant_of_ratvar(L))
+ portal_uses++
+ duration += 40 //4 seconds
+ if(GLOB.ratvar_awakens)
+ portal_uses = max(portal_uses, 100) //Very powerful if Ratvar has been summoned
+ duration = max(duration, 100)
+ return slab.procure_gateway(invoker, duration, portal_uses)
\ No newline at end of file
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm
new file mode 100644
index 0000000000..5075840e76
--- /dev/null
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm
@@ -0,0 +1,44 @@
+///////////////
+// JUDGEMENT // For the big game changing things. TODO: Summonable generals, just need mob sprites for them.
+///////////////
+
+//Ark of the Clockwork Justiciar: Creates a Gateway to the Celestial Derelict, summoning ratvar.
+/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar
+ descname = "Structure, Win Condition"
+ name = "Ark of the Clockwork Justiciar"
+ desc = "Tears apart a rift in spacetime to Reebe, the Celestial Derelict, using a massive amount of power.\n\
+ This gateway will, after some time, call forth Ratvar from his exile and massively empower all scriptures and tools."
+ invocations = list("ARMORER! FRIGHT! AMPERAGE! VANGUARD! WE CALL UPON YOU!!", \
+ "THE TIME HAS COME FOR OUR MASTER TO BREAK THE CHAINS OF EXILE!!", \
+ "LEND US YOUR AID! ENGINE COMES!!")
+ channel_time = 150
+ power_cost = 70000 //70 KW. It's literally the thing wrenching the god out of another dimension why wouldn't it be costly.
+ invokers_required = 6
+ multiple_invokers_used = TRUE
+ object_path = /obj/structure/destructible/clockwork/massive/celestial_gateway
+ creator_message = "
The Ark swirls into existance before you with the help of the Generals. After all this time, he shall, finally, be free"
+ usage_tip = "The gateway is completely vulnerable to attack during its five-minute duration. It will periodically give indication of its general position to everyone on the station \
+ as well as being loud enough to be heard throughout the entire sector. Defend it with your life!"
+ tier = SCRIPTURE_APPLICATION
+ sort_priority = 8
+ requires_full_power = TRUE
+
+/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar/check_special_requirements()
+ if(!slab.no_cost)
+ if(GLOB.ratvar_awakens)
+ to_chat(invoker, "
\"I am already here, there is no point in that.\"")
+ return FALSE
+ for(var/obj/structure/destructible/clockwork/massive/celestial_gateway/G in GLOB.all_clockwork_objects)
+ var/area/gate_area = get_area(G)
+ to_chat(invoker, "
There is already an Ark at [gate_area.map_name]!")
+ return FALSE
+ var/area/A = get_area(invoker)
+ var/turf/T = get_turf(invoker)
+ if(!T || !is_station_level(T.z) || istype(A, /area/shuttle) || !A.blob_allowed)
+ to_chat(invoker, "
You must be on the station to activate the Ark!")
+ return FALSE
+ if(GLOB.clockwork_gateway_activated)
+ to_chat(invoker, "
Ratvar's recent banishment renders him too weak to be wrung forth from Reebe!")
+ return FALSE
+ return ..()
+
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm
index d22a2f69b7..8819544928 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm
@@ -1,5 +1,5 @@
/////////////
-// SCRIPTS //
+// SCRIPTS // Various miscellanious spells for offense/defense/construction.
/////////////
@@ -81,6 +81,25 @@
return /obj/effect/clockwork/sigil/vitality/neutered
return ..()
+//Sigil of Rites: Creates a sigil that allows to perform certain rites on it. More information on these can be found in clock_rites.dm, they usually require power, materials and sometimes a target.
+/datum/clockwork_scripture/create_object/sigil_of_rites
+ descname = "Sigil, Access to rites"
+ name = "Sigil of Rites"
+ desc = "Places a sigil that, when interacted with, will allow for a variety of rites to be performed on the sigil. These usually require power cells, clockwork power, and some other components."
+ invocations = list("Engine, allow us..", ".. to be blessed with your rites.")
+ channel_time = 80
+ power_cost = 1400
+ invokers_required = 2
+ multiple_invokers_used = TRUE
+ whispered = TRUE
+ object_path = /obj/effect/clockwork/sigil/rite
+ creator_message = "
A sigil of Rites appears beneath you. It will allow you to perform certain rites, given sufficient materials and power."
+ usage_tip = "It may be useful to coordinate to acquire needed materials quickly."
+ tier = SCRIPTURE_SCRIPT
+ one_per_tile = TRUE
+ primary_component = HIEROPHANT_ANSIBLE
+ sort_priority = 4
+
//Judicial Visor: Creates a judicial visor, which can smite an area.
/datum/clockwork_scripture/create_object/judicial_visor
descname = "Delayed Area Knockdown Glasses"
@@ -96,7 +115,7 @@
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
primary_component = BELLIGERENT_EYE
- sort_priority = 4
+ sort_priority = 5
quickbind = TRUE
quickbind_desc = "Creates a Judicial Visor, which can smite an area, applying Belligerent and briefly stunning."
@@ -115,7 +134,7 @@
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
primary_component = VANGUARD_COGWHEEL
- sort_priority = 6
+ sort_priority = 7
quickbind = TRUE
quickbind_desc = "Creates a Ratvarian shield, which can absorb energy from attacks for use in powerful bashes."
@@ -131,7 +150,7 @@
usage_tip = "Throwing the spear at a mob will do massive damage and knock them down, but break the spear. You will need to wait for 30 seconds before resummoning it."
tier = SCRIPTURE_SCRIPT
primary_component = VANGUARD_COGWHEEL
- sort_priority = 7
+ sort_priority = 8
important = TRUE
quickbind = TRUE
quickbind_desc = "Permanently binds clockwork armor and a Ratvarian spear to you."
@@ -217,53 +236,6 @@
weapon_type = /obj/item/clockwork/weapon/ratvarian_spear
-//Spatial Gateway: Allows the invoker to teleport themselves and any nearby allies to a conscious servant or clockwork obelisk.
-/datum/clockwork_scripture/spatial_gateway
- descname = "Teleport Gate"
- name = "Spatial Gateway"
- desc = "Tears open a miniaturized gateway in spacetime to any conscious servant that can transport objects or creatures to its destination. \
- Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
- invocations = list("Spatial Gateway...", "...activate!")
- channel_time = 80
- power_cost = 400
- multiple_invokers_used = TRUE
- multiple_invokers_optional = TRUE
- usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
- tier = SCRIPTURE_SCRIPT
- primary_component = GEIS_CAPACITOR
- sort_priority = 9
- quickbind = TRUE
- quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk."
-
-/datum/clockwork_scripture/spatial_gateway/check_special_requirements()
- if(!isturf(invoker.loc))
- to_chat(invoker, "
You must not be inside an object to use this scripture!")
- return FALSE
- var/other_servants = 0
- for(var/mob/living/L in GLOB.alive_mob_list)
- if(is_servant_of_ratvar(L) && !L.stat && L != invoker)
- other_servants++
- for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in GLOB.all_clockwork_objects)
- if(O.anchored)
- other_servants++
- if(!other_servants)
- to_chat(invoker, "
There are no other conscious servants or anchored clockwork obelisks!")
- return FALSE
- return TRUE
-
-/datum/clockwork_scripture/spatial_gateway/scripture_effects()
- var/portal_uses = 0
- var/duration = 0
- for(var/mob/living/L in range(1, invoker))
- if(!L.stat && is_servant_of_ratvar(L))
- portal_uses++
- duration += 40 //4 seconds
- if(GLOB.ratvar_awakens)
- portal_uses = max(portal_uses, 100) //Very powerful if Ratvar has been summoned
- duration = max(duration, 100)
- return slab.procure_gateway(invoker, duration, portal_uses)
-
-
//Mending Mantra: Channeled for up to ten times over twenty seconds to repair structures and heal allies
/datum/clockwork_scripture/channeled/mending_mantra
descname = "Channeled, Area Healing and Repair"
@@ -276,7 +248,7 @@
usage_tip = "This is a very effective way to rapidly reinforce a base after an attack."
tier = SCRIPTURE_SCRIPT
primary_component = VANGUARD_COGWHEEL
- sort_priority = 8
+ sort_priority = 9
quickbind = TRUE
quickbind_desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed.
Maximum 10 chants."
var/heal_attempts = 4
@@ -389,7 +361,7 @@
usage_tip = "Though it requires you to stand still, this scripture can do massive damage."
tier = SCRIPTURE_SCRIPT
primary_component = BELLIGERENT_EYE
- sort_priority = 5
+ sort_priority = 6
quickbind = TRUE
quickbind_desc = "Allows you to fire energy rays at target locations.
Maximum 5 chants."
var/static/list/nzcrentr_insults = list("You're not very good at aiming.", "You hunt badly.", "What a waste of energy.", "Almost funny to watch.",
@@ -438,7 +410,7 @@
usage_tip = "It may be useful to end channelling early if the burning becomes too much to handle.."
tier = SCRIPTURE_SCRIPT
primary_component = GEIS_CAPACITOR
- sort_priority = 10
+ sort_priority = 11
quickbind = TRUE
quickbind_desc = "Quickly drains power in an area around the invoker, causing burns proportional to the amount of energy drained.
Maximum of 20 chants."
@@ -487,3 +459,26 @@
invoker.light_range = 0
invoker.update_light()
return ..()
+
+//Belligerent: Channeled for up to fifteen times over thirty seconds. Forces non-servants that can hear the chant to walk, doing minor damage. Nar-Sian cultists are burned.
+/datum/clockwork_scripture/channeled/belligerent
+ descname = "Channeled, Area Slowdown"
+ name = "Belligerent"
+ desc = "Forces all nearby non-servants to walk rather than run, doing minor damage. Chanted every two seconds for up to thirty seconds."
+ chant_invocations = list("Punish their blindness!", "Take time, make slow!", "Kneel before The Justiciar!", "Halt their charges!", "Cease the tides!")
+ chant_amount = 15
+ chant_interval = 20
+ channel_time = 20
+ power_cost = 300
+ usage_tip = "Useful for crowd control in a populated area and disrupting mass movement."
+ tier = SCRIPTURE_DRIVER
+ primary_component = BELLIGERENT_EYE
+ sort_priority = 1
+ quickbind = TRUE
+ quickbind_desc = "Forces nearby non-Servants to walk, doing minor damage with each chant.
Maximum 15 chants."
+
+/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
+ for(var/mob/living/carbon/C in hearers(7, invoker))
+ C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
+ new /obj/effect/temp_visual/ratvar/belligerent(get_turf(invoker))
+ return TRUE
diff --git a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
index 297856f531..7478d45b08 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
@@ -1,5 +1,3 @@
-#define ARK_GRACE_PERIOD 300 //In seconds, how long the crew has before the Ark truly "begins"
-
/proc/clockwork_ark_active() //A helper proc so the Ark doesn't have to be typecast every time it's checked; returns null if there is no Ark and its active var otherwise
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(!G)
@@ -11,7 +9,7 @@
name = "\improper Ark of the Clockwork Justicar"
desc = "A massive, hulking amalgamation of parts. It seems to be maintaining a very unstable bluespace anomaly."
clockwork_desc = "Nezbere's magnum opus: a hulking clockwork machine capable of combining bluespace and steam power to summon Ratvar. Once activated, \
- its instability will cause one-way bluespace rifts to open across the station to the City of Cogs, so be prepared to defend it at all costs."
+ its instability will alert the entire area, so be prepared to defend it at all costs."
max_integrity = 500
mouse_opacity = MOUSE_OPACITY_OPAQUE
icon = 'icons/effects/clockwork_effects.dmi'
@@ -22,9 +20,8 @@
immune_to_servant_attacks = TRUE
var/active = FALSE
var/progress_in_seconds = 0 //Once this reaches GATEWAY_RATVAR_ARRIVAL, it's game over
- var/grace_period = ARK_GRACE_PERIOD //This exists to allow the crew to gear up and prepare for the invasion
- var/initial_activation_delay = -1 //How many seconds the Ark will have initially taken to activate
- var/seconds_until_activation = -1 //How many seconds until the Ark activates; if it should never activate, set this to -1
+ var/initial_activation_delay = 5 //How many seconds the Ark will have initially taken to activate
+ var/seconds_until_activation = 5 //How many seconds until the Ark activates; if it should never activate, set this to -1
var/purpose_fulfilled = FALSE
var/first_sound_played = FALSE
var/second_sound_played = FALSE
@@ -38,10 +35,21 @@
/obj/structure/destructible/clockwork/massive/celestial_gateway/Initialize()
. = ..()
+ INVOKE_ASYNC(src, .proc/spawn_animation)
glow = new(get_turf(src))
if(!GLOB.ark_of_the_clockwork_justiciar)
GLOB.ark_of_the_clockwork_justiciar = src
- START_PROCESSING(SSprocessing, src)
+
+/obj/structure/destructible/clockwork/massive/celestial_gateway/on_attack_hand(mob/user, act_intent, unarmed_attack_flags)
+ if(!active && is_servant_of_ratvar(user) && user.canUseTopic(src, !issilicon(user), NO_DEXTERY))
+ if(alert(user, "Are you sure you want to activate the ark? Once enabled, there will be no turning back.", "Enabling the ark", "Activate!", "Cancel") == "Activate!")
+ if(active)
+ return
+ log_game("[key_name(user)] has activated an Ark of the Clockwork Justicar at [COORD(src)].")
+ START_PROCESSING(SSprocessing, src)
+ SSshuttle.registerHostileEnvironment(src)
+ else
+ to_chat(user, "
You decide against activating the ark.. for now.")
/obj/structure/destructible/clockwork/massive/celestial_gateway/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..()
@@ -49,7 +57,7 @@
flick("clockwork_gateway_damaged", glow)
playsound(src, 'sound/machines/clockcult/ark_damage.ogg', 75, FALSE)
if(last_scream < world.time)
- audible_message("
An unearthly screaming sound resonates throughout Reebe!")
+ audible_message("
An unearthly screaming sound resonates throughout the area!")
for(var/V in GLOB.player_list)
var/mob/M = V
var/turf/T = get_turf(M)
@@ -60,31 +68,19 @@
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/final_countdown(ark_time) //WE'RE LEAVING TOGETHEEEEEEEEER
if(!ark_time)
- ark_time = 30 //minutes
- initial_activation_delay = ark_time * 60
- seconds_until_activation = ark_time * 60 //60 seconds in a minute * number of minutes
+ ark_time = 5 //5 minutes
for(var/obj/item/clockwork/construct_chassis/cogscarab/C in GLOB.all_clockwork_objects)
C.infinite_resources = FALSE
GLOB.servants_active = TRUE
SSshuttle.registerHostileEnvironment(src)
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/cry_havoc()
- visible_message("
[src] shudders and roars to life, its parts beginning to whirr and screech!")
- hierophant_message("
The Ark is activating! You will be transported there soon!")
- for(var/mob/M in GLOB.player_list)
- var/turf/T = get_turf(M)
- if(is_servant_of_ratvar(M) || isobserver(M) || (T && T.z == z))
- M.playsound_local(M, 'sound/magic/clockwork/ark_activation_sequence.ogg', 30, FALSE, pressure_affected = FALSE)
- addtimer(CALLBACK(src, .proc/let_slip_the_dogs), 300)
-
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/let_slip_the_dogs()
- spawn_animation()
first_sound_played = TRUE
active = TRUE
+ visible_message("
[src] shudders and roars to life, its parts beginning to whirr and screech!")
priority_announce("Massive [Gibberish("bluespace", 100)] anomaly detected on all frequencies. All crew are directed to \
@!$, [text2ratvar("PURGE ALL UNTRUTHS")] <&. the anomalies and destroy their source to prevent further damage to corporate property. This is \
- not a drill.[grace_period ? " Estimated time of appearance: [grace_period] seconds. Use this time to prepare for an attack on [station_name()]." : ""]", \
- "Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ark_activation.ogg')
+ not a drill.", "Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ark_activation_sequence.ogg')
set_security_level("delta")
for(var/V in SSticker.mode.servants_of_ratvar)
var/datum/mind/M = V
@@ -92,15 +88,6 @@
continue
if(ishuman(M.current))
M.current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
- for(var/V in GLOB.brass_recipes)
- var/datum/stack_recipe/R = V
- if(!R)
- continue
- if(R.title == "wall gear")
- R.time *= 2 //Building walls becomes slower when the Ark activates
- mass_recall()
- recalls_remaining++ //So it doesn't use up a charge
-
var/turf/T = get_turf(src)
var/list/open_turfs = list()
for(var/turf/open/OT in orange(1, T))
@@ -110,14 +97,35 @@
for(var/mob/living/L in T)
L.forceMove(pick(open_turfs))
-/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/open_portal(turf/T)
- new/obj/effect/clockwork/city_of_cogs_rift(T)
-
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/spawn_animation()
- hierophant_message("
The Ark has activated! [grace_period ? "You have [round(grace_period / 60)] minutes until the crew invades! " : ""]Defend it at all costs!", FALSE, src)
- sound_to_playing_players(volume = 10, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE))
- seconds_until_activation = 0
- SSshuttle.registerHostileEnvironment(src)
+ var/turf/T = get_turf(src)
+ new/obj/effect/clockwork/general_marker/inathneq(T)
+ hierophant_message("
\"[text2ratvar("Engine, come forth and show your servants your mercy")]!\"")
+ playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 30, 0)
+ sleep(10)
+ new/obj/effect/clockwork/general_marker/sevtug(T)
+ hierophant_message("
\"[text2ratvar("Engine, come forth and show this station your decorating skills")]!\"")
+ playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 45, 0)
+ sleep(10)
+ new/obj/effect/clockwork/general_marker/nezbere(T)
+ hierophant_message("
\"[text2ratvar("Engine, come forth and shine your light across this realm")]!!\"")
+ playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 60, 0)
+ sleep(10)
+ new/obj/effect/clockwork/general_marker/nzcrentr(T)
+ hierophant_message("
\"[text2ratvar("Engine, come forth")].\"")
+ playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 75, 0)
+ sleep(10)
+ playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 100, 0)
+ var/list/open_turfs = list()
+ for(var/turf/open/OT in orange(1, T))
+ if(!is_blocked_turf(OT, TRUE))
+ open_turfs |= OT
+ if(open_turfs.len)
+ for(var/mob/living/L in T)
+ L.forceMove(pick(open_turfs))
+ glow = new(get_turf(src))
+ var/area/gate_area = get_area(src)
+ hierophant_message("
An Ark of the Clockwork Justicar has been created in [gate_area.map_name]!", FALSE, src)
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/initiate_mass_recall()
recalling = TRUE
@@ -141,35 +149,22 @@
transform = matrix() * 2
animate(src, transform = matrix() * 0.5, time = 30, flags = ANIMATION_END_NOW)
-/obj/structure/destructible/clockwork/massive/celestial_gateway/Destroy()
+obj/structure/destructible/clockwork/massive/celestial_gateway/Destroy()
STOP_PROCESSING(SSprocessing, src)
+ if(!purpose_fulfilled)
+ var/area/gate_area = get_area(src)
+ hierophant_message("
An Ark of the Clockwork Justicar has fallen at [gate_area.map_name]!")
+ send_to_playing_players(sound(null, 0, channel = CHANNEL_JUSTICAR_ARK))
+ var/was_stranded = SSshuttle.emergency.mode == SHUTTLE_STRANDED
SSshuttle.clearHostileEnvironment(src)
- if(!purpose_fulfilled && istype(SSticker.mode, /datum/game_mode/clockwork_cult))
- hierophant_message("
The Ark has fallen!")
- sound_to_playing_players(null, channel = CHANNEL_JUSTICAR_ARK)
- SSticker.force_ending = TRUE //rip
+ if(!was_stranded && !purpose_fulfilled)
+ priority_announce("Massive energy anomaly no longer on short-range scanners, bluespace distortions still detected.","Central Command Higher Dimensional Affairs")
if(glow)
qdel(glow)
glow = null
if(countdown)
qdel(countdown)
countdown = null
- for(var/mob/L in GLOB.player_list)
- var/turf/T = get_turf(L)
- if(T && T.z == z)
- var/atom/movable/target = L
- if(isobj(L.loc))
- target = L.loc
- target.forceMove(get_turf(pick(GLOB.generic_event_spawns)))
- L.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
- L.clear_fullscreen("flash", 30)
- if(isliving(L))
- var/mob/living/LI = L
- LI.Stun(50)
- for(var/obj/effect/clockwork/city_of_cogs_rift/R in GLOB.all_clockwork_objects)
- qdel(R)
- if(GLOB.ark_of_the_clockwork_justiciar == src)
- GLOB.ark_of_the_clockwork_justiciar = null
. = ..()
/obj/structure/destructible/clockwork/massive/celestial_gateway/deconstruct(disassembled = TRUE)
@@ -203,8 +198,6 @@
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_time(var/deciseconds = TRUE)
if(seconds_until_activation)
. = seconds_until_activation
- else if(grace_period)
- . = grace_period
else if(GATEWAY_RATVAR_ARRIVAL - progress_in_seconds > 0)
. = round(max((GATEWAY_RATVAR_ARRIVAL - progress_in_seconds) / (GATEWAY_SUMMON_RATE), 0), 1)
if(deciseconds)
@@ -213,8 +206,6 @@
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_text(s_on_time)
if(seconds_until_activation)
return "[get_arrival_time()][s_on_time ? "S" : ""]"
- if(grace_period)
- return "[get_arrival_time()][s_on_time ? "S" : ""]"
. = "IMMINENT"
if(!obj_integrity)
. = "DETONATING"
@@ -229,17 +220,14 @@
if(!active)
. += "
Time until the Ark's activation: [DisplayTimeText(get_arrival_time())]"
else
- if(grace_period)
- . += "
Crew grace period time remaining: [DisplayTimeText(get_arrival_time())]"
- else
- . += "
Time until Ratvar's arrival: [DisplayTimeText(get_arrival_time())]"
- switch(progress_in_seconds)
- if(-INFINITY to GATEWAY_REEBE_FOUND)
- . += "
The Ark is feeding power into the bluespace field."
- if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
- . += "
The field is ripping open a copy of itself in Ratvar's prison."
- if(GATEWAY_RATVAR_COMING to INFINITY)
- . += "
With the bluespace field established, Ratvar is preparing to come through!"
+ . += "
Time until Ratvar's arrival: [DisplayTimeText(get_arrival_time())]"
+ switch(progress_in_seconds)
+ if(-INFINITY to GATEWAY_REEBE_FOUND)
+ . += "
The Ark is feeding power into the bluespace field."
+ if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
+ . += "
The field is ripping open a copy of itself in Ratvar's prison."
+ if(GATEWAY_RATVAR_COMING to INFINITY)
+ . += "
With the bluespace field established, Ratvar is preparing to come through!"
else
if(!active)
. += "
Whatever it is, it doesn't seem to be active."
@@ -253,20 +241,14 @@
. += "
The anomaly is stable! Something is coming through!"
/obj/structure/destructible/clockwork/massive/celestial_gateway/process()
- if(seconds_until_activation == -1) //we never do anything
- return
adjust_clockwork_power(2.5) //Provides weak power generation on its own
if(seconds_until_activation)
if(!countdown)
countdown = new(src)
countdown.start()
seconds_until_activation--
- if(!GLOB.script_scripture_unlocked && initial_activation_delay * 0.5 > seconds_until_activation)
- GLOB.script_scripture_unlocked = TRUE
- hierophant_message("
The Ark is halfway prepared. Script scripture is now available!")
if(!seconds_until_activation)
- cry_havoc()
- seconds_until_activation = -1 //we'll set this after cry_havoc()
+ let_slip_the_dogs()
return
if(!first_sound_played || prob(7))
for(var/mob/M in GLOB.player_list)
@@ -285,6 +267,9 @@
if(!step_away(O, src, 2) || get_dist(O, src) < 2)
O.take_damage(50, BURN, "bomb")
O.update_icon()
+
+ conversion_pulse() //Converts the nearby area into clockcult-style
+
for(var/V in GLOB.player_list)
var/mob/M = V
var/turf/T = get_turf(M)
@@ -292,29 +277,24 @@
M.forceMove(get_step(src, SOUTH))
M.overlay_fullscreen("flash", /obj/screen/fullscreen/flash)
M.clear_fullscreen("flash", 5)
- if(grace_period)
- grace_period--
- return
progress_in_seconds += GATEWAY_SUMMON_RATE
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
if(!second_sound_played)
- for(var/V in GLOB.generic_event_spawns)
- addtimer(CALLBACK(src, .proc/open_portal, get_turf(V)), rand(100, 600))
sound_to_playing_players('sound/magic/clockwork/invoke_general.ogg', 30, FALSE)
- sound_to_playing_players(volume = 20, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE))
+ sound_to_playing_players(volume = 10, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE))
second_sound_played = TRUE
make_glow()
glow.icon_state = "clockwork_gateway_charging"
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
if(!third_sound_played)
- sound_to_playing_players(volume = 25, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_active.ogg', TRUE))
+ sound_to_playing_players(volume = 30, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_active.ogg', TRUE))
third_sound_played = TRUE
make_glow()
glow.icon_state = "clockwork_gateway_active"
if(GATEWAY_RATVAR_COMING to GATEWAY_RATVAR_ARRIVAL)
if(!fourth_sound_played)
- sound_to_playing_players(volume = 30, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_closing.ogg', TRUE))
+ sound_to_playing_players(volume = 70, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_closing.ogg', TRUE))
fourth_sound_played = TRUE
make_glow()
glow.icon_state = "clockwork_gateway_closing"
@@ -334,7 +314,6 @@
GLOB.clockwork_gateway_activated = TRUE
var/turf/T = SSmapping.get_station_center()
new /obj/structure/destructible/clockwork/massive/ratvar(T)
- SSticker.force_ending = TRUE
var/x0 = T.x
var/y0 = T.y
for(var/I in spiral_range_turfs(255, T, tick_checked = TRUE))
@@ -349,6 +328,17 @@
T.ratvar_act(dist)
CHECK_TICK
+//Converts nearby turfs into their clockwork equivalent, with ever-increasing range the closer the ark is to summoning Ratvar
+/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/conversion_pulse()
+ var/convert_dist = 1 + (round(FLOOR(progress_in_seconds, 15) * 0.067))
+ for(var/t in RANGE_TURFS(convert_dist, loc))
+ var/turf/T = t
+ if(!T)
+ continue
+ var/dist = cheap_hypotenuse(T.x, T.y, x, y)
+ if(dist < convert_dist)
+ T.ratvar_act(FALSE, TRUE, 3)
+
//ATTACK GHOST IGNORING PARENT RETURN VALUE
/obj/structure/destructible/clockwork/massive/celestial_gateway/attack_ghost(mob/user)
if(!IsAdminGhost(user))
@@ -361,9 +351,9 @@
if(alert(user, "You're REALLY SURE? This cannot be undone.", name, "Yes - Activate the Ark", "No") == "Yes - Activate the Ark")
message_admins("
Admin [key_name_admin(user)] started the Ark's countdown!")
log_admin("Admin [key_name(user)] started the Ark's countdown on a non-clockcult mode!")
- to_chat(user, "
The gamemode is now being treated as clockwork cult, and the Ark is counting down from 30 \
+ to_chat(user, "The gamemode is now being treated as clockwork cult, and the Ark is counting down from 5 \
minutes. You will need to create servant players yourself.")
- final_countdown(35)
+ final_countdown(5)
diff --git a/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm b/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm
index 8c529d43a6..2b4b797b4d 100644
--- a/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm
@@ -41,14 +41,19 @@
affected += try_use_power(MIN_CLOCKCULT_POWER*4)
return affected
-/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/destructible/clockwork/powered/clockwork_obelisk/Destroy()
+ for(var/obj/effect/clockwork/spatial_gateway/SG in loc)
+ SG.ex_act(EXPLODE_DEVASTATE)
+ return ..()
+
+/obj/structure/destructible/clockwork/powered/clockwork_obelisk/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
if(!is_servant_of_ratvar(user) || !can_access_clockwork_power(src, hierophant_cost) || !anchored)
to_chat(user, "You place your hand on [src], but it doesn't react.")
return
- var/choice = alert(user,"You place your hand on [src]...",,"Hierophant Broadcast","Spatial Gateway","Cancel")
+ var/choice = alert(user,"You place your hand on [src]...",,"Hierophant Broadcast","Spatial Gateway","Cancel") //Will create a stable gateway instead if between two obelisks one of which is onstation and the other on reebe
switch(choice)
if("Hierophant Broadcast")
if(active)
@@ -96,7 +101,7 @@
if(!anchored)
return
var/obj/effect/clockwork/spatial_gateway/SG = locate(/obj/effect/clockwork/spatial_gateway) in loc
- if(SG && SG.timerid) //it's a valid gateway, we're active
+ if(SG && (SG.timerid || SG.is_stable)) //it's a valid gateway, we're active
icon_state = active_icon
density = FALSE
active = TRUE
diff --git a/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm b/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm
index 2c84a5b332..5302153b9c 100644
--- a/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm
@@ -11,7 +11,7 @@
var/selection_timer //Timer ID; this is canceled if the vote is canceled
var/kingmaking
-/obj/structure/destructible/clockwork/eminence_spire/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/destructible/clockwork/eminence_spire/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -27,9 +27,6 @@
if(C.clock_team.eminence)
to_chat(user, "There's already an Eminence!")
return
- if(!GLOB.servants_active)
- to_chat(user, "The Ark isn't active!")
- return
if(eminence_nominee) //This could be one large proc, but is split into three for ease of reading
if(eminence_nominee == user)
cancelation(user)
diff --git a/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm b/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm
index 385b9a5431..f8a3afbf91 100644
--- a/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm
@@ -1,3 +1,5 @@
+
+
//Used to "declare war" against the station. The servants' equipment will be permanently supercharged, and the Ark given extra time to prepare.
//This will send an announcement to the station, meaning that they will be warned very early in advance about the impending attack.
/obj/structure/destructible/clockwork/heralds_beacon
@@ -58,7 +60,7 @@
. += "There are [time_remaining] second[time_remaining != 1 ? "s" : ""] remaining to vote."
. += "There are [voters.len]/[votes_needed] votes to activate the beacon!"
-/obj/structure/destructible/clockwork/heralds_beacon/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/destructible/clockwork/heralds_beacon/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -108,5 +110,4 @@
to_chat(H, "The beacon's power warps your body into a clockwork form! You are now immune to many hazards, and your body is more robust against damage!")
H.set_species(/datum/species/golem/clockwork/no_scrap)
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
- G.grace_period = FALSE //no grace period if we've declared war
G.recalls_remaining++
diff --git a/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm b/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm
index 24d0651444..40cadb53a2 100644
--- a/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm
@@ -30,7 +30,7 @@
toggle()
return TRUE
-/obj/structure/destructible/clockwork/powered/mania_motor/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/destructible/clockwork/powered/mania_motor/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm b/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm
new file mode 100644
index 0000000000..73488d736a
--- /dev/null
+++ b/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm
@@ -0,0 +1,134 @@
+//Prolonging Prism: A prism that consumes power to delay the shuttle
+/obj/structure/destructible/clockwork/powered/prolonging_prism
+ name = "prolonging prism"
+ desc = "A dark onyx prism, held in midair by spiraling tendrils of stone."
+ clockwork_desc = "A powerful prism that will delay the arrival of an emergency shuttle."
+ icon_state = "prolonging_prism_inactive"
+ active_icon = "prolonging_prism"
+ inactive_icon = "prolonging_prism_inactive"
+ unanchored_icon = "prolonging_prism_unwrenched"
+ construction_value = 20
+ max_integrity = 125
+ break_message = "The prism falls to the ground with a heavy thud!"
+ debris = list(/obj/item/clockwork/alloy_shards/small = 3, \
+ /obj/item/clockwork/alloy_shards/medium = 1, \
+ /obj/item/clockwork/alloy_shards/large = 1, \
+ /obj/item/clockwork/component/vanguard_cogwheel/onyx_prism = 1)
+ var/static/power_refund = 250
+ var/static/delay_cost = 2000 //Updated power values for new-newclock. Easier to activate and sustain, you are quite literally pointing the entire station towards you as opposed to blood-delay after all.
+ var/static/delay_cost_increase = 1000
+ var/static/delay_remaining = 0
+
+/obj/structure/destructible/clockwork/powered/prolonging_prism/examine(mob/user)
+ . = ..()
+ if(is_servant_of_ratvar(user) || isobserver(user))
+ if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
+ . += "An emergency shuttle has arrived and this prism is no longer useful; attempt to activate it to gain a partial refund of components used."
+ else
+ var/efficiency = get_efficiency_mod(TRUE)
+ . += "It requires at least [DisplayPower(get_delay_cost())] of power to attempt to delay the arrival of an emergency shuttle by [2 * efficiency] minutes."
+ . += "This cost increases by [DisplayPower(delay_cost_increase)] for every previous activation."
+
+/obj/structure/destructible/clockwork/powered/prolonging_prism/forced_disable(bad_effects)
+ if(active)
+ if(bad_effects)
+ try_use_power(MIN_CLOCKCULT_POWER*4)
+ visible_message("[src] emits an airy chuckling sound and falls dark!")
+ toggle()
+ return TRUE
+
+/obj/structure/destructible/clockwork/powered/prolonging_prism/on_attack_hand(mob/living/user)
+ if(user.canUseTopic(src, !issilicon(user), NO_DEXTERY) && is_servant_of_ratvar(user))
+ if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
+ to_chat(user, "You break [src] apart, refunding some of the power used.")
+ adjust_clockwork_power(power_refund)
+ take_damage(max_integrity)
+ return 0
+ if(active)
+ return 0
+ var/turf/T = get_turf(src)
+ if(!T || !is_station_level(T.z))
+ to_chat(user, "[src] must be on the station to function!")
+ return 0
+ if(SSshuttle.emergency.mode != SHUTTLE_CALL)
+ to_chat(user, "No emergency shuttles are attempting to arrive at the station!")
+ return 0
+ if(!try_use_power(get_delay_cost()))
+ to_chat(user, "[src] needs more power to function!")
+ return 0
+ delay_cost += delay_cost_increase
+ delay_remaining += PRISM_DELAY_DURATION
+ toggle(0, user)
+
+/obj/structure/destructible/clockwork/powered/prolonging_prism/process()
+ var/turf/own_turf = get_turf(src)
+ if(SSshuttle.emergency.mode != SHUTTLE_CALL || delay_remaining <= 0 || !own_turf || !is_station_level(own_turf.z))
+ forced_disable(FALSE)
+ return
+ . = ..()
+ var/delay_amount = 40
+ delay_remaining -= delay_amount
+ var/efficiency = get_efficiency_mod()
+ SSshuttle.emergency.setTimer(SSshuttle.emergency.timeLeft(1) + (delay_amount * efficiency))
+ var/highest_y
+ var/highest_x
+ var/lowest_y
+ var/lowest_x
+ var/list/prism_turfs = list()
+ for(var/t in SSshuttle.emergency.ripple_area(SSshuttle.getDock("emergency_home")))
+ prism_turfs[t] = TRUE
+ var/turf/T = t
+ if(!highest_y || T.y > highest_y)
+ highest_y = T.y
+ if(!highest_x || T.x > highest_x)
+ highest_x = T.x
+ if(!lowest_y || T.y < lowest_y)
+ lowest_y = T.y
+ if(!lowest_x || T.x < lowest_x)
+ lowest_x = T.x
+ var/mean_y = LERP(lowest_y, highest_y, 0.5)
+ var/mean_x = LERP(lowest_x, highest_x, 0.5)
+ if(prob(50))
+ mean_y = CEILING(mean_y, 1)
+ else
+ mean_y = FLOOR(mean_y, 1) //Yes, I know round(mean_y) does the same, just left as FLOOR for consistancy sake
+ if(prob(50))
+ mean_x = CEILING(mean_x, 1)
+ else
+ mean_x = FLOOR(mean_x, 1)
+ var/turf/semi_random_center_turf = locate(mean_x, mean_y, z)
+ for(var/t in getline(src, semi_random_center_turf))
+ prism_turfs[t] = TRUE
+ var/placement_style = prob(50)
+ for(var/t in prism_turfs)
+ var/turf/T = t
+ if(placement_style)
+ if(ISODD(T.x + T.y))
+ seven_random_hexes(T, efficiency)
+ else if(prob(50 * efficiency))
+ new /obj/effect/temp_visual/ratvar/prolonging_prism(T)
+ else
+ if(ISEVEN(T.x + T.y))
+ seven_random_hexes(T, efficiency)
+ else if(prob(50 * efficiency))
+ new /obj/effect/temp_visual/ratvar/prolonging_prism(T)
+ CHECK_TICK //we may be going over a hell of a lot of turfs
+
+/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/get_delay_cost()
+ return FLOOR(delay_cost, MIN_CLOCKCULT_POWER)
+
+/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/seven_random_hexes(turf/T, efficiency)
+ var/static/list/hex_states = list("prismhex1", "prismhex2", "prismhex3", "prismhex4", "prismhex5", "prismhex6", "prismhex7")
+ var/mutable_appearance/hex_combo
+ for(var/n in hex_states) //BUILD ME A HEXAGON
+ if(prob(50 * efficiency))
+ if(!hex_combo)
+ hex_combo = mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER)
+ else
+ hex_combo.add_overlay(mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER))
+ if(hex_combo) //YOU BUILT A HEXAGON
+ hex_combo.pixel_x = -16
+ hex_combo.pixel_y = -16
+ hex_combo.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ hex_combo.plane = GAME_PLANE
+ new /obj/effect/temp_visual/ratvar/prolonging_prism(T, hex_combo)
diff --git a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm
index c17885315f..73ae89a19b 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm
@@ -101,8 +101,8 @@
return
clashing = TRUE
GLOB.cult_narsie.clashing = TRUE
- to_chat(world, "\"YOU.\"")
- to_chat(world, "\"Ratvar?!\"")
+ to_chat(world, "\"[pick("YOU.", "BLOOD GOD!!", "FACE ME, COWARD!")]\"")
+ to_chat(world, "\"[pick("Ratvar?! How?!", "YOU. BANISHED ONCE. KILLED NOW.", "SCRAP HEAP!!")]\"")
clash_of_the_titans(GLOB.cult_narsie) // >:(
return TRUE
@@ -137,15 +137,16 @@
base_victory_chance *= 2 //The clash has a higher chance of resolving each time both gods attack one another
switch(winner)
if("Ratvar")
- send_to_playing_players("\"[pick("DIE.", "ROT.")]\"\n\
+ send_to_playing_players("\"[pick("DIE.", "ROT FOR CENTURIES, AS I HAVE!.","PERISH, HEATHEN.", "DIE, MONSTER, YOU DON'T BELONG IN THIS WORLD.")]\"\n\
\"[pick("Nooooo...", "Not die. To y-", "Die. Ratv-", "Sas tyen re-")]\"") //Nar'Sie get out
sound_to_playing_players('sound/magic/clockwork/anima_fragment_attack.ogg')
- sound_to_playing_players('sound/magic/demon_dies.ogg', 50)
+ sound_to_playing_players('sound/magic/abomscream.ogg', 50)
clashing = FALSE
qdel(narsie)
if("Nar'Sie")
- send_to_playing_players("\"[pick("Ha.", "Ra'sha fonn dest.", "You fool. To come here.")]\"") //Broken English
- sound_to_playing_players('sound/magic/demon_attack1.ogg')
- sound_to_playing_players('sound/magic/clockwork/anima_fragment_death.ogg', 62)
+ send_to_playing_players("\"[pick("Ha.", "Ra'sha fonn dest.", "You fool. To come here.")]\"\n\
+ \"[pick("NO, YOUR SHADOWS SHALL NO-", "ZNL GUR FGERNZF BS GVZR PNEEL ZL RKVFG-", "MY LIGHT CANNO-")]\"")
+ sound_to_playing_players('sound/magic/demon_attack1.ogg', 50)
+ sound_to_playing_players('sound/machines/clockcult/ratvar_scream.ogg', 80)
narsie.clashing = FALSE
qdel(src)
diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm
index d4a02cc3e1..55347685f4 100644
--- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm
@@ -6,7 +6,7 @@
max_integrity = 75
icon_state = "lever"
-/obj/structure/destructible/clockwork/trap/trigger/lever/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/destructible/clockwork/trap/trigger/lever/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm
index e7d4e18c43..7a528786e2 100644
--- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm
@@ -6,7 +6,7 @@
max_integrity = 15 //Fragile!
icon_state = "repeater"
-/obj/structure/destructible/clockwork/trap/trigger/repeater/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/destructible/clockwork/trap/trigger/repeater/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 4e9d40d91c..35151953a0 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -53,7 +53,7 @@
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
flags_1 = CONDUCT_1
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
w_class = WEIGHT_CLASS_BULKY
force = 30 // whoever balanced this got beat in the head by a bible too many times good lord
throwforce = 10
@@ -114,7 +114,7 @@
armour_penetration = 45
throw_speed = 1
throw_range = 3
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
light_color = "#ff0000"
attack_verb = list("cleaved", "slashed", "torn", "hacked", "ripped", "diced", "carved")
icon_state = "cultbastard"
@@ -258,7 +258,7 @@
/datum/action/innate/cult/spin2win/Activate()
cooldown = world.time + sword.spin_cooldown
- holder.changeNext_move(50)
+ holder.DelayNextAction(50)
holder.apply_status_effect(/datum/status_effect/sword_spin)
sword.spinning = TRUE
sword.block_chance = 100
@@ -708,7 +708,7 @@
armour_penetration = 30
block_chance = 30
attack_verb = list("attacked", "impaled", "stabbed", "torn", "gored")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
hitsound = 'sound/weapons/bladeslice.ogg'
var/datum/action/innate/cult/spear/spear_act
var/wielded = FALSE // track wielded status on item
diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm
index 6f340b9271..5803941f36 100644
--- a/code/modules/antagonists/cult/cult_structures.dm
+++ b/code/modules/antagonists/cult/cult_structures.dm
@@ -44,15 +44,16 @@
/obj/structure/destructible/cult/attack_animal(mob/living/simple_animal/M)
if(istype(M, /mob/living/simple_animal/hostile/construct/builder))
if(obj_integrity < max_integrity)
- M.changeNext_move(CLICK_CD_MELEE)
+ M.DelayNextAction(CLICK_CD_MELEE)
obj_integrity = min(max_integrity, obj_integrity + 5)
Beam(M, icon_state="sendbeam", time=4)
M.visible_message("[M] repairs \the [src].", \
"You repair [src], leaving [p_they()] at [round(obj_integrity * 100 / max_integrity)]% stability.")
+ return TRUE
else
to_chat(M, "You cannot repair [src], as [p_theyre()] undamaged!")
else
- ..()
+ return ..()
/obj/structure/destructible/cult/attackby(obj/I, mob/user, params)
if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user))
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 9b77e70a73..3ea160c5cc 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -67,7 +67,7 @@ Runes can either be invoked by one's self or with many different cultists. Each
to_chat(user, "You disrupt the magic of [src] with [I].")
qdel(src)
-/obj/effect/rune/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/effect/rune/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index 7d7031dad4..272b154828 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -144,7 +144,7 @@
/mob/living/carbon/true_devil/resist_fire()
//They're immune to fire.
-/mob/living/carbon/true_devil/attack_hand(mob/living/carbon/human/M)
+/mob/living/carbon/true_devil/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.)
switch(M.a_intent)
diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm
index e876beb5dc..6a05d07b38 100644
--- a/code/modules/antagonists/disease/disease_mob.dm
+++ b/code/modules/antagonists/disease/disease_mob.dm
@@ -291,16 +291,19 @@ the new instance inside the host to be updated to the template's stats.
/mob/camera/disease/ClickOn(var/atom/A, params)
if(freemove && ishuman(A))
- var/mob/living/carbon/human/H = A
- if(alert(src, "Select [H.name] as your initial host?", "Select Host", "Yes", "No") != "Yes")
- return
- if(!freemove)
- return
- if(QDELETED(H) || !force_infect(H))
- to_chat(src, "[H ? H.name : "Host"] cannot be infected.")
+ confirm_initial_infection(A)
else
..()
+/mob/camera/disease/proc/confirm_initial_infection(mob/living/carbon/human/H)
+ set waitfor = FALSE
+ if(alert(src, "Select [H.name] as your initial host?", "Select Host", "Yes", "No") != "Yes")
+ return
+ if(!freemove)
+ return
+ if(QDELETED(H) || !force_infect(H))
+ to_chat(src, "[H ? H.name : "Host"] cannot be infected.")
+
/mob/camera/disease/proc/adapt_cooldown()
to_chat(src, "You have altered your genetic structure. You will be unable to adapt again for [DisplayTimeText(adaptation_cooldown)].")
next_adaptation_time = world.time + adaptation_cooldown
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index d0ef5a83ce..21ccd425a3 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -112,7 +112,7 @@
if(stasis)
return
if(revealed && essence <= 0)
- death()
+ INVOKE_ASYNC(src, .proc/death)
if(unreveal_time && world.time >= unreveal_time)
unreveal_time = 0
revealed = FALSE
diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm
index 2d84ed7c22..7a2f661fd9 100644
--- a/code/modules/antagonists/revenant/revenant_abilities.dm
+++ b/code/modules/antagonists/revenant/revenant_abilities.dm
@@ -17,6 +17,7 @@
//Harvest; activated ly clicking the target, will try to drain their essence.
/mob/living/simple_animal/revenant/proc/Harvest(mob/living/carbon/human/target)
+ set waitfor = FALSE
if(!castcheck(0))
return
if(draining)
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index 35a674fb0e..3ae9cfcfb0 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -38,7 +38,7 @@
melee_damage_upper = 22.5
wound_bonus = -10
bare_wound_bonus = 0
- sharpness = TRUE
+ sharpness = SHARP_EDGED
see_in_dark = 8
blood_volume = 0 //No bleeding on getting shot, for skeddadles
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm
index 9a8b9c8d59..b7503f4b22 100644
--- a/code/modules/antagonists/swarmer/swarmer.dm
+++ b/code/modules/antagonists/swarmer/swarmer.dm
@@ -36,7 +36,7 @@
if(A)
notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
-/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/effect/mob_spawn/swarmer/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -158,10 +158,11 @@
face_atom(A)
if(!isturf(loc))
return
- if(next_move > world.time)
+ if(!CheckActionCooldown())
return
if(!A.Adjacent(src))
return
+ DelayNextAction()
A.swarmer_act(src)
/atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
@@ -497,7 +498,7 @@
if(resource_gain)
resources += resource_gain
do_attack_animation(target)
- changeNext_move(CLICK_CD_MELEE)
+ DelayNextAction(CLICK_CD_MELEE)
var/obj/effect/temp_visual/swarmer/integrate/I = new /obj/effect/temp_visual/swarmer/integrate(get_turf(target))
I.pixel_x = target.pixel_x
I.pixel_y = target.pixel_y
@@ -517,10 +518,9 @@
/mob/living/simple_animal/hostile/swarmer/proc/DisIntegrate(atom/movable/target)
new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
do_attack_animation(target)
- changeNext_move(CLICK_CD_MELEE)
+ DelayNextAction(CLICK_CD_MELEE)
target.ex_act(EXPLODE_LIGHT)
-
/mob/living/simple_animal/hostile/swarmer/proc/DisperseTarget(mob/living/target)
if(target == src)
return
diff --git a/code/modules/antagonists/traitor/IAA/internal_affairs.dm b/code/modules/antagonists/traitor/IAA/internal_affairs.dm
index 19144d67c9..ff012e556a 100644
--- a/code/modules/antagonists/traitor/IAA/internal_affairs.dm
+++ b/code/modules/antagonists/traitor/IAA/internal_affairs.dm
@@ -167,10 +167,10 @@
return
if(last_man_standing)
if(syndicate)
- to_chat(owner.current," All the loyalist agents are dead, and no more is required of you. Die a glorious death, agent. ")
+ to_chat(owner.current,"All the suspected agents are dead, and no more is required of you. Die a glorious death, agent.")
+ replace_escape_objective(owner)
else
- to_chat(owner.current," All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.")
- replace_escape_objective(owner)
+ to_chat(owner.current,"All the other agents are dead. You have done us all a great service and shall be honorably exiled upon returning to base.")
/datum/antagonist/traitor/internal_affairs/proc/iaa_process()
if(owner&&owner.current&&owner.current.stat!=DEAD)
@@ -193,7 +193,7 @@
if(syndicate)
fail_msg += " You no longer have permission to die. "
else
- fail_msg += " The truth could still slip out! Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated."
+ fail_msg += " The truth could still slip out! Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to great shame."
reinstate_escape_objective(owner)
last_man_standing = FALSE
to_chat(owner.current, fail_msg)
@@ -226,18 +226,20 @@
add_objective(escape_objective)
/datum/antagonist/traitor/internal_affairs/proc/greet_iaa()
- var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
+ var/crime = pick("distribution of contraband" , "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
to_chat(owner.current, "You are the [special_role].")
if(syndicate)
- to_chat(owner.current, "Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.")
- to_chat(owner.current, "Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.")
- to_chat(owner.current, " You have been provided with a standard uplink to accomplish your task. ")
- to_chat(owner.current, "By no means reveal that you, or any other NT employees, are undercover agents.")
+ to_chat(owner.current, "GREAT LEADER IS DEAD. NANOTRASEN MUST FALL.")
+ to_chat(owner.current, "Your have infiltrated this vessel to cause chaos and assassinate targets known to have conspired against the Syndicate.")
+ to_chat(owner.current, "Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.")
+ to_chat(owner.current, "You have been provided with a standard uplink to accomplish your task. ")
+ to_chat(owner.current, "By no means reveal that you are a Syndicate agent. By no means reveal that your targets are being hunted.")
else
- to_chat(owner.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.")
- to_chat(owner.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.")
- to_chat(owner.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.")
+ to_chat(owner.current, "CAUTION: Your legal status as a citizen of NanoTrasen will be permanently revoked upon completion of your first contract.")
+ to_chat(owner.current, "Your target has been suspected of [crime], and must be removed from this plane.")
+ to_chat(owner.current, "While you have a license to kill, you are to eliminate your targets with no collateral or unrelated deaths.")
+ to_chat(owner.current, "For the sake of plausable deniability, you have been equipped with captured Syndicate equipment via uplink.")
to_chat(owner.current, "By no means reveal that you, or any other NT employees, are undercover agents.")
to_chat(owner.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.")
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 2701a2d006..d8a8e9a1be 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -259,7 +259,7 @@
to_chat(target, "You suddenly feel very hot")
target.adjust_bodytemperature(50)
GiveHint(target)
- else if(is_pointed(I))
+ else if(I.get_sharpness() == SHARP_POINTY)
to_chat(target, "You feel a stabbing pain in [parse_zone(user.zone_selected)]!")
target.DefaultCombatKnockdown(40)
GiveHint(target)
diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm
index 36c444f02d..1c814fa193 100644
--- a/code/modules/assembly/bomb.dm
+++ b/code/modules/assembly/bomb.dm
@@ -62,6 +62,7 @@
/obj/item/onetankbomb/analyzer_act(mob/living/user, obj/item/I)
bombtank.analyzer_act(user, I)
+ return TRUE
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
bombassembly.attack_self(user, TRUE)
@@ -90,7 +91,7 @@
if(bombassembly)
bombassembly.on_found(finder)
-/obj/item/onetankbomb/attack_hand() //also for mousetraps
+/obj/item/onetankbomb/on_attack_hand() //also for mousetraps
. = ..()
if(.)
return
diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm
index c960a7f039..bf56449a0c 100644
--- a/code/modules/assembly/holder.dm
+++ b/code/modules/assembly/holder.dm
@@ -87,7 +87,7 @@
if(a_right)
a_right.dropped(user)
-/obj/item/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
+/obj/item/assembly_holder/on_attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
. = ..()
if(.)
return
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 8cb6eb66fb..6e8e2846a2 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -125,7 +125,7 @@
return
refreshBeam()
-/obj/item/assembly/infra/attack_hand()
+/obj/item/assembly/infra/on_attack_hand()
. = ..()
refreshBeam()
diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm
index 90d4662c15..2c005b971d 100644
--- a/code/modules/assembly/mousetrap.dm
+++ b/code/modules/assembly/mousetrap.dm
@@ -84,8 +84,7 @@
playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/assembly/mousetrap/attack_hand(mob/living/carbon/human/user)
+/obj/item/assembly/mousetrap/on_attack_hand(mob/living/carbon/human/user)
if(armed)
if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
var/which_hand = BODY_ZONE_PRECISE_L_HAND
diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
index e230ae55bb..2b43319904 100644
--- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
+++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
@@ -198,24 +198,27 @@
//////////////////////////SPACEWIND/////////////////////////////
/turf/open/proc/consider_pressure_difference(turf/T, difference)
- SSair.high_pressure_delta[src] = TRUE
if(difference > pressure_difference)
pressure_direction = get_dir(src, T)
pressure_difference = difference
+ SSair.high_pressure_delta[src] = TRUE
/turf/open/proc/high_pressure_movements()
- var/atom/movable/M
- var/multiplier = 1
+ var/diff = pressure_difference
if(locate(/obj/structure/rack) in src)
- multiplier *= 0.1
+ diff *= 0.1
else if(locate(/obj/structure/table) in src)
- multiplier *= 0.2
- for(var/thing in src)
- M = thing
- if (!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired)
- M.experience_pressure_difference(pressure_difference * multiplier, pressure_direction, 0, pressure_specific_target)
+ diff *= 0.2
+ for(var/obj/M in src)
+ if(!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired)
+ M.experience_pressure_difference(diff, pressure_direction, 0, pressure_specific_target)
+ for(var/mob/M in src)
+ if(!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired)
+ M.experience_pressure_difference(diff, pressure_direction, 0, pressure_specific_target)
+ /*
if(pressure_difference > 100)
new /obj/effect/temp_visual/dir_setting/space_wind(src, pressure_direction, clamp(round(sqrt(pressure_difference) * 2), 10, 255))
+ */
/atom/movable/var/pressure_resistance = 10
/atom/movable/var/last_high_pressure_movement_air_cycle = 0
diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm
index dc7c106035..a8d9586fc4 100644
--- a/code/modules/atmospherics/machinery/components/components_base.dm
+++ b/code/modules/atmospherics/machinery/components/components_base.dm
@@ -170,3 +170,4 @@
/obj/machinery/atmospherics/components/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(airs, user, src)
+ return TRUE
\ No newline at end of file
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index ae80825694..0f849af0e3 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -276,8 +276,6 @@
return occupant
/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/living/user)
- user.changeNext_move(CLICK_CD_BREAKOUT)
- user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("You see [user] kicking against the glass of [src]!", \
"You struggle inside [src], kicking the release with your foot... (this will take about [DisplayTimeText(breakout_time)].)", \
"You hear a thump from [src].")
diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm
index 4a6170c251..23fd2292ff 100644
--- a/code/modules/atmospherics/machinery/pipes/pipes.dm
+++ b/code/modules/atmospherics/machinery/pipes/pipes.dm
@@ -64,6 +64,7 @@
/obj/machinery/atmospherics/pipe/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(parent.air, user, src)
+ return TRUE
/obj/machinery/atmospherics/pipe/returnPipenet()
return parent
diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
index 445cc686f3..fa57e683c4 100644
--- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
+++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
@@ -145,6 +145,7 @@
/obj/machinery/portable_atmospherics/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(air_contents, user, src)
+ return TRUE
/obj/machinery/portable_atmospherics/attacked_by(obj/item/I, mob/user, attackchain_flags = NONE, damage_multiplier = 1)
if(I.force < 10 && !(stat & BROKEN))
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index 03c0f5178a..3426208fae 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -53,8 +53,7 @@
to_chat(M, "\The [src] has been returned to base!")
STOP_PROCESSING(SSobj, src)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/ctf/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/ctf/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_ctf_target(user) && !anyonecanpickup)
to_chat(user, "Non players shouldn't be moving the flag!")
return
@@ -679,10 +678,7 @@
/obj/machinery/control_point/attackby(mob/user, params)
capture(user)
-/obj/machinery/control_point/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/control_point/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
capture(user)
/obj/machinery/control_point/proc/capture(mob/user)
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index 4b2f1e9962..e68c45a84c 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -594,8 +594,7 @@
assignedrole = "Space Bar Patron"
job_description = "Space Bar Patron"
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/effect/mob_spawn/human/alive/space_bar_patron/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/effect/mob_spawn/human/alive/space_bar_patron/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
var/despawn = alert("Return to cryosleep? (Warning, Your mob will be deleted!)",,"Yes","No")
if(despawn == "No" || !loc || !Adjacent(user))
return
diff --git a/code/modules/cargo/coupon.dm b/code/modules/cargo/coupon.dm
index c77050c530..1c1f2a36e1 100644
--- a/code/modules/cargo/coupon.dm
+++ b/code/modules/cargo/coupon.dm
@@ -8,6 +8,7 @@
icon = 'icons/obj/card.dmi'
item_flags = NOBLUDGEON
w_class = WEIGHT_CLASS_TINY
+ attack_speed = CLICK_CD_RAPID
var/datum/supply_pack/discounted_pack
var/discount_pct_off = 0.05
var/obj/machinery/computer/cargo/inserted_console
@@ -34,6 +35,7 @@
if(discount_pct_off == COUPON_OMEN)
to_chat(user, "\The [O] validates the coupon as authentic, but refuses to accept it...")
O.say("Coupon fulfillment already in progress...")
+ user.DelayNextAction()
return
inserted_console = O
diff --git a/code/modules/cargo/packs/goodies.dm b/code/modules/cargo/packs/goodies.dm
index 2ff02d0473..86a7c73a34 100644
--- a/code/modules/cargo/packs/goodies.dm
+++ b/code/modules/cargo/packs/goodies.dm
@@ -81,3 +81,9 @@
desc = "Contains one hellgun, an old pattern of laser gun infamous for its ability to horribly disfigure targets with burns. Technically violates the Space Geneva Convention when used on humanoids."
cost = 1500
contains = list(/obj/item/gun/energy/laser/hellgun)
+
+/datum/supply_pack/goody/medipen_twopak
+ name = "Medipen Two-Pak"
+ desc = "Contains one standard epinephrine medipen and one standard emergency first-aid kit medipen. For when you want to prepare for the worst."
+ cost = 500
+ contains = list(/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/hypospray/medipen/ekit)
diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm
index 5eacc2f583..6a4165f840 100644
--- a/code/modules/cargo/packs/medical.dm
+++ b/code/modules/cargo/packs/medical.dm
@@ -218,3 +218,18 @@
/obj/item/storage/box/beakers)
crate_name = "virus containment unit crate"
crate_type = /obj/structure/closet/crate/secure/plasma
+
+/datum/supply_pack/medical/medipen_variety
+ name = "Medipen Variety-Pak"
+ desc = "Contains eight different medipens in three different varieties, to assist in quickly treating seriously injured patients."
+ cost = 2000
+ contains = list(/obj/item/reagent_containers/hypospray/medipen/,
+ /obj/item/reagent_containers/hypospray/medipen/,
+ /obj/item/reagent_containers/hypospray/medipen/ekit,
+ /obj/item/reagent_containers/hypospray/medipen/ekit,
+ /obj/item/reagent_containers/hypospray/medipen/ekit,
+ /obj/item/reagent_containers/hypospray/medipen/blood_loss,
+ /obj/item/reagent_containers/hypospray/medipen/blood_loss,
+ /obj/item/reagent_containers/hypospray/medipen/blood_loss)
+
+ crate_name = "medipen crate"
diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm
index 249faae33d..0f01dfd5d9 100644
--- a/code/modules/cargo/packs/organic.dm
+++ b/code/modules/cargo/packs/organic.dm
@@ -361,6 +361,7 @@
/obj/item/seeds/reishi,
/obj/item/seeds/banana,
/obj/item/seeds/eggplant/eggy,
+ /obj/item/seeds/poppy/lily/trumpet,
/obj/item/seeds/random,
/obj/item/seeds/random)
crate_name = "exotic seeds crate"
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 7f1ba86ff5..ae48fddfb4 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -30,6 +30,9 @@
var/move_delay = 0
var/area = null
+ /// Last time we Click()ed. No clicking twice in one tick!
+ var/last_click = 0
+
///////////////
//SOUND STUFF//
///////////////
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 1da69f197f..5c9b1eec2e 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -471,6 +471,11 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
//////////////
/client/Del()
+ if(!gc_destroyed)
+ Destroy()
+ return ..()
+
+/client/Destroy()
if(credits)
QDEL_LIST(credits)
log_access("Logout: [key_name(src)]")
@@ -504,9 +509,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
movingmob.client_mobs_in_contents -= mob
UNSETEMPTY(movingmob.client_mobs_in_contents)
Master.UpdateTickRate()
- return ..()
-
-/client/Destroy()
+ . = ..()
return QDEL_HINT_HARDDEL_NOW
/client/proc/set_client_age_from_db(connectiontopic)
@@ -771,6 +774,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
ip_intel = res.intel
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE)
+ if(last_click > world.time - world.tick_lag)
+ return
+ last_click = world.time
var/ab = FALSE
var/list/L = params2list(params)
if (object && object == middragatom && L["left"])
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 7f29efddb1..7c30381161 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -40,7 +40,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
//If it's 0, that's good, if it's anything but 0, the owner of this prefs file's antag choices were,
//autocorrected this round, not that you'd need to check that.
-
var/UI_style = null
var/buttons_locked = FALSE
var/hotkeys = FALSE
@@ -230,7 +229,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/gear_points = 10
var/list/gear_categories
var/list/chosen_gear = list()
- var/gear_tab
+ var/gear_category
+ var/gear_subcategory
var/screenshake = 100
var/damagescreenshake = 2
@@ -832,7 +832,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Socks Color: Change
"
dat += "Backpack:[backbag]"
dat += "Jumpsuit:
[jumpsuit_style]
"
- if(CAN_SCAR in pref_species.species_traits)
+ if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits))
dat += "
Temporal Scarring:
[(persistent_scars) ? "Enabled" : "Disabled"]"
dat += "Clear scar slots"
dat += "Uplink Location:[uplink_spawn_loc]"
@@ -1059,58 +1059,83 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "
"
if(3)
- if(!gear_tab)
- gear_tab = GLOB.loadout_items[1]
dat += ""
dat += "| [gear_points] loadout points remaining. \[Clear Loadout\] |
"
dat += "| You can only choose one item per category, unless it's an item that spawns in your backpack or hands. |
"
dat += "| "
- var/firstcat = TRUE
- for(var/i in GLOB.loadout_items)
- if(firstcat)
- firstcat = FALSE
+
+ if(!length(GLOB.loadout_items))
+ dat += "ERROR: No loadout categories - something is horribly wrong!"
+ else
+ if(!GLOB.loadout_categories[gear_category])
+ gear_category = GLOB.loadout_categories[1]
+ var/firstcat = TRUE
+ for(var/category in GLOB.loadout_categories)
+ if(firstcat)
+ firstcat = FALSE
+ else
+ dat += " |"
+ if(category == gear_category)
+ dat += " [category] "
+ else
+ dat += " [category] "
+
+ dat += " |
"
+ dat += "
|
"
+
+ dat += "| "
+
+ if(!length(GLOB.loadout_categories[gear_category]))
+ dat += "No subcategories detected. Something is horribly wrong!"
else
- dat += " |"
- if(i == gear_tab)
- dat += " [i] "
- else
- dat += " [i] "
- dat += " |
"
- dat += "
|
"
- dat += "| [gear_tab] |
"
- dat += "
|
"
- dat += "| Name | "
- dat += "Cost | "
- dat += "Restrictions | "
- dat += "Description |
"
- for(var/j in GLOB.loadout_items[gear_tab])
- var/datum/gear/gear = GLOB.loadout_items[gear_tab][j]
- var/donoritem = gear.donoritem
- if(donoritem && !gear.donator_ckey_check(user.ckey))
- continue
- var/class_link = ""
- if(gear.type in chosen_gear)
- class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(j)];toggle_gear=0'"
- else if(gear_points <= 0)
- class_link = "style='white-space:normal;' class='linkOff'"
- else if(donoritem)
- class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(j)];toggle_gear=1'"
- else
- class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(j)];toggle_gear=1'"
- dat += "| [j] | "
- dat += "[gear.cost] | "
- if(islist(gear.restricted_roles))
- if(gear.restricted_roles.len)
- if(gear.restricted_desc)
- dat += ""
- dat += gear.restricted_desc
- dat += ""
+ var/list/subcategories = GLOB.loadout_categories[gear_category]
+ if(!subcategories.Find(gear_subcategory))
+ gear_subcategory = subcategories[1]
+
+ var/firstsubcat = FALSE
+ for(var/subcategory in subcategories)
+ if(firstsubcat)
+ firstsubcat = FALSE
else
- dat += ""
- dat += gear.restricted_roles.Join(";")
- dat += ""
- dat += " | [gear.description] |
"
- dat += "
"
+ dat += " |"
+ if(gear_subcategory == subcategory)
+ dat += " [subcategory] "
+ else
+ dat += " [subcategory] "
+ dat += ""
+
+ dat += "| Name | "
+ dat += "Cost | "
+ dat += "Restrictions | "
+ dat += "Description |
"
+ for(var/name in GLOB.loadout_items[gear_category][gear_subcategory])
+ var/datum/gear/gear = GLOB.loadout_items[gear_category][gear_subcategory][name]
+ var/donoritem = gear.donoritem
+ if(donoritem && !gear.donator_ckey_check(user.ckey))
+ continue
+ var/class_link = ""
+ if(gear.type in chosen_gear)
+ class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'"
+ else if(gear_points <= 0)
+ class_link = "style='white-space:normal;' class='linkOff'"
+ else if(donoritem)
+ class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'"
+ else
+ class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'"
+ dat += "| [name] | "
+ dat += "[gear.cost] | "
+ if(islist(gear.restricted_roles))
+ if(gear.restricted_roles.len)
+ if(gear.restricted_desc)
+ dat += ""
+ dat += gear.restricted_desc
+ dat += ""
+ else
+ dat += ""
+ dat += gear.restricted_roles.Join(";")
+ dat += ""
+ dat += " | [gear.description] |
"
+ dat += ""
if(4) // Content preferences
dat += ""
dat += "
"
if(5) // Custom keybindings
@@ -1798,11 +1824,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
//Now that we changed our species, we must verify that the mutant colour is still allowed.
var/temp_hsv = RGBtoHSV(features["mcolor"])
- if(features["mcolor"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
+ if(features["mcolor"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
features["mcolor"] = pref_species.default_color
- if(features["mcolor2"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
+ if(features["mcolor2"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
features["mcolor2"] = pref_species.default_color
- if(features["mcolor3"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
+ if(features["mcolor3"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
features["mcolor3"] = pref_species.default_color
if("custom_species")
@@ -2644,6 +2670,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("bimbo")
cit_toggles ^= BIMBOFICATION
+ if("auto_wag")
+ cit_toggles ^= NO_AUTO_WAG
+
//END CITADEL EDIT
if("ambientocclusion")
@@ -2687,11 +2716,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
gear_points = CONFIG_GET(number/initial_gear_points)
save_preferences()
if(href_list["select_category"])
- for(var/i in GLOB.loadout_items)
- if(i == href_list["select_category"])
- gear_tab = i
+ gear_category = html_decode(href_list["select_category"])
+ gear_subcategory = GLOB.loadout_categories[gear_category][1]
+ if(href_list["select_subcategory"])
+ gear_subcategory = html_decode(href_list["select_subcategory"])
if(href_list["toggle_gear_path"])
- var/datum/gear/G = GLOB.loadout_items[gear_tab][html_decode(href_list["toggle_gear_path"])]
+ var/name = html_decode(href_list["toggle_gear_path"])
+ var/datum/gear/G = GLOB.loadout_items[gear_category][gear_subcategory][name]
if(!G)
return
var/toggle = text2num(href_list["toggle_gear"])
@@ -2796,6 +2827,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(custom_tongue != "default")
var/new_tongue = GLOB.roundstart_tongues[custom_tongue]
if(new_tongue)
+ character.dna.species.mutanttongue = new_tongue //this means we get our tongue when we clone
var/obj/item/organ/tongue/T = character.getorganslot(ORGAN_SLOT_TONGUE)
if(T)
qdel(T)
@@ -2870,17 +2902,17 @@ GLOBAL_LIST_EMPTY(preferences_datums)
LAZYINITLIST(L)
for(var/i in chosen_gear)
var/datum/gear/G = i
- var/occupied_slots = L[slot_to_string(initial(G.category))] ? L[slot_to_string(initial(G.category))] + 1 : 1
- LAZYSET(L, slot_to_string(initial(G.category)), occupied_slots)
+ var/occupied_slots = L[initial(G.category)] ? L[initial(G.category)] + 1 : 1
+ LAZYSET(L, initial(G.category), occupied_slots)
switch(slot)
if(SLOT_IN_BACKPACK)
- if(L[slot_to_string(SLOT_IN_BACKPACK)] < BACKPACK_SLOT_AMT)
+ if(L[LOADOUT_CATEGORY_BACKPACK] < BACKPACK_SLOT_AMT)
return TRUE
if(SLOT_HANDS)
- if(L[slot_to_string(SLOT_HANDS)] < HANDS_SLOT_AMT)
+ if(L[LOADOUT_CATEGORY_HANDS] < HANDS_SLOT_AMT)
return TRUE
else
- if(L[slot_to_string(slot)] < DEFAULT_SLOT_AMT)
+ if(L[slot] < DEFAULT_SLOT_AMT)
return TRUE
#undef DEFAULT_SLOT_AMT
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 59d99674eb..dffab645a4 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -224,7 +224,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
var/needs_update = savefile_needs_update(S)
if(needs_update == -2) //fatal, can't load any data
return 0
-
+
. = TRUE
//general preferences
@@ -443,7 +443,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
return 0
. = TRUE
-
+
//Species
var/species_id
S["species"] >> species_id
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index d2553c4d7c..d540336b86 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -58,6 +58,10 @@
var/limb_integrity = 0
// How many zones (body parts, not precise) we have disabled so far, for naming purposes
var/zones_disabled
+ ///These are armor values that protect the wearer, taken from the clothing's armor datum. List updates on examine because it's currently only used to print armor ratings to chat in Topic().
+ var/list/armor_list = list()
+ ///These are armor values that protect the clothing, taken from its armor datum. List updates on examine because it's currently only used to print armor ratings to chat in Topic().
+ var/list/durability_list = list()
/obj/item/clothing/Initialize()
. = ..()
@@ -85,7 +89,7 @@
tastes = list("dust" = 1, "lint" = 1)
/obj/item/clothing/attack(mob/M, mob/user, def_zone)
- if(user.a_intent != INTENT_HARM && ismoth(M))
+ if(user.a_intent != INTENT_HARM && isinsect(M))
var/obj/item/reagent_containers/food/snacks/clothing/clothing_as_food = new
clothing_as_food.name = name
if(clothing_as_food.attack(M, user, def_zone))
@@ -115,7 +119,7 @@
// Set the clothing's integrity back to 100%, remove all damage to bodyparts, and generally fix it up
/obj/item/clothing/proc/repair(mob/user, params)
damaged_clothes = CLOTHING_PRISTINE
- update_clothes_damaged_state()
+ update_clothes_damaged_state(FALSE)
obj_integrity = max_integrity
name = initial(name) // remove "tattered" or "shredded" if there's a prefix
body_parts_covered = initial(body_parts_covered)
@@ -253,6 +257,87 @@
how_cool_are_your_threads += "Adding or removing items from [src] makes no noise.\n"
how_cool_are_your_threads += ""
. += how_cool_are_your_threads.Join()
+
+ if(LAZYLEN(armor_list))
+ armor_list.Cut()
+ if(armor.bio)
+ armor_list += list("TOXIN" = armor.bio)
+ if(armor.bomb)
+ armor_list += list("EXPLOSIVE" = armor.bomb)
+ if(armor.bullet)
+ armor_list += list("BULLET" = armor.bullet)
+ if(armor.energy)
+ armor_list += list("ENERGY" = armor.energy)
+ if(armor.laser)
+ armor_list += list("LASER" = armor.laser)
+ if(armor.magic)
+ armor_list += list("MAGIC" = armor.magic)
+ if(armor.melee)
+ armor_list += list("MELEE" = armor.melee)
+ if(armor.rad)
+ armor_list += list("RADIATION" = armor.rad)
+
+ if(LAZYLEN(durability_list))
+ durability_list.Cut()
+ if(armor.fire)
+ durability_list += list("FIRE" = armor.fire)
+ if(armor.acid)
+ durability_list += list("ACID" = armor.acid)
+
+ if(LAZYLEN(armor_list) || LAZYLEN(durability_list))
+ . += "
It has a tag listing its protection classes."
+
+/obj/item/clothing/Topic(href, href_list)
+ . = ..()
+
+ if(href_list["list_armor"])
+ var/list/readout = list("
PROTECTION CLASSES (I-X)")
+ if(LAZYLEN(armor_list))
+ readout += "\nARMOR"
+ for(var/dam_type in armor_list)
+ var/armor_amount = armor_list[dam_type]
+ readout += "\n[dam_type] [armor_to_protection_class(armor_amount)]" //e.g. BOMB IV
+ if(LAZYLEN(durability_list))
+ readout += "\nDURABILITY"
+ for(var/dam_type in durability_list)
+ var/durability_amount = durability_list[dam_type]
+ readout += "\n[dam_type] [armor_to_protection_class(durability_amount)]" //e.g. FIRE II
+ readout += ""
+
+ to_chat(usr, "[readout.Join()]")
+
+/**
+ * Rounds armor_value to nearest 10, divides it by 10 and then expresses it in roman numerals up to 10
+ *
+ * Rounds armor_value to nearest 10, divides it by 10
+ * and then expresses it in roman numerals up to 10
+ * Arguments:
+ * * armor_value - Number we're converting
+ */
+/obj/item/clothing/proc/armor_to_protection_class(armor_value)
+ armor_value = round(armor_value,10) / 10
+ switch (armor_value)
+ if (1)
+ . = "I"
+ if (2)
+ . = "II"
+ if (3)
+ . = "III"
+ if (4)
+ . = "IV"
+ if (5)
+ . = "V"
+ if (6)
+ . = "VI"
+ if (7)
+ . = "VII"
+ if (8)
+ . = "VIII"
+ if (9)
+ . = "IX"
+ if (10 to INFINITY)
+ . = "X"
+ return .
/obj/item/clothing/obj_break(damage_flag)
damaged_clothes = CLOTHING_DAMAGED
@@ -265,7 +350,6 @@
var/index = "[REF(initial(icon))]-[initial(icon_state)]"
var/static/list/damaged_clothes_icons = list()
if(damaging)
- damaged_clothes = 1
var/icon/damaged_clothes_icon = damaged_clothes_icons[index]
if(!damaged_clothes_icon)
damaged_clothes_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply damaged effect to the initial icon_state for each object
@@ -273,12 +357,10 @@
damaged_clothes_icon.Blend(icon('icons/effects/item_damage.dmi', "itemdamaged"), ICON_MULTIPLY) //adds damage effect and the remaining white areas become transparant
damaged_clothes_icon = fcopy_rsc(damaged_clothes_icon)
damaged_clothes_icons[index] = damaged_clothes_icon
- add_overlay(damaged_clothes_icon, 1)
+ add_overlay(damaged_clothes_icon, TRUE)
else
- damaged_clothes = 0
cut_overlay(damaged_clothes_icons[index], TRUE)
-
/*
SEE_SELF // can see self, no matter what
SEE_MOBS // can see all mobs, no matter what
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 01effea6f2..350a577fb1 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -96,7 +96,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/clothing/glasses/meson/eyepatch
name = "eyepatch mesons"
@@ -180,7 +180,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
vision_correction = 1
glass_colour_type = /datum/client_colour/glass_colour/lightgreen
@@ -237,7 +237,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/clothing/glasses/sunglasses/garb/supergarb
name = "black giga gar glasses"
@@ -257,7 +257,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
glass_colour_type = /datum/client_colour/glass_colour/orange
/obj/item/clothing/glasses/sunglasses/gar/supergar
diff --git a/code/modules/clothing/glasses/disablerglasses.dm b/code/modules/clothing/glasses/disablerglasses.dm
index a46e4c8339..51fb1cec87 100644
--- a/code/modules/clothing/glasses/disablerglasses.dm
+++ b/code/modules/clothing/glasses/disablerglasses.dm
@@ -4,7 +4,9 @@
var/beamtype = /obj/item/projectile/beam/disabler //change for adminbus
/obj/item/clothing/glasses/hud/security/sunglasses/disablers/ranged_attack(mob/living/carbon/human/user,atom/A, params)
- user.changeNext_move(CLICK_CD_RANGE)
+ if(!user.CheckActionCooldown(CLICK_CD_RANGE))
+ return
+ user.last_action = world.time
var/obj/item/projectile/beam/disabler/LE = new beamtype( loc )
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
LE.firer = src
@@ -12,4 +14,4 @@
LE.preparePixelProjectile(A, src, params)
LE.fire()
return TRUE
- //shamelessly copied
\ No newline at end of file
+ //shamelessly copied
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index c745cd74f0..9ca98b0bca 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -70,7 +70,7 @@
flash_protect = -2
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
-
+
/obj/item/clothing/glasses/hud/health/night/syndicate
name = "combat night vision health scanner HUD"
desc = "An advanced shielded medical heads-up display that allows soldiers to approximate how much lead poisoning their allies have suffered in complete darkness."
@@ -221,7 +221,7 @@
throw_speed = 4
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/clothing/glasses/hud/security/sunglasses/gars/supergars
name = "giga HUD gar glasses"
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index b06636ea2e..1c3ac0f340 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -45,8 +45,8 @@
REMOVE_TRAIT(user, secondary_trait, GLOVE_TRAIT)
if(ishuman(user))
var/mob/living/carbon/human/H = user
- H.dna.species.punchdamagehigh = initial(H.dna.species.punchdamagehigh)
- H.dna.species.punchdamagelow = initial(H.dna.species.punchdamagelow)
+ H.dna.species.punchdamagehigh -= enhancement
+ H.dna.species.punchdamagelow -= enhancement
return ..()
/obj/item/clothing/gloves/fingerless/pugilist/chaplain
@@ -105,11 +105,11 @@
return
var/mob/living/M = loc
- M.changeNext_move(CLICK_CD_RAPID)
+ M.SetNextAction(CLICK_CD_RAPID)
if(warcry)
M.say("[warcry]", ignore_spam = TRUE, forced = TRUE)
- return FALSE
+ return NO_AUTO_CLICKDELAY_HANDLING | ATTACK_IGNORE_ACTION
/obj/item/clothing/gloves/fingerless/pugilist/rapid/AltClick(mob/user)
var/input = stripped_input(user,"What do you want your battlecry to be? Max length of 6 characters.", ,"", 7)
@@ -135,9 +135,9 @@
if(target.stat != CONSCIOUS) //Can't hug people who are dying/dead
return FALSE
else
- M.changeNext_move(CLICK_CD_RAPID)
+ M.SetNextAction(CLICK_CD_RAPID)
- return FALSE
+ return NO_AUTO_CLICKDELAY_HANDLING | ATTACK_IGNORE_ACTION
/obj/item/clothing/gloves/botanic_leather
name = "botanist's leather gloves"
diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm
index 9682787de5..dc07d5e050 100644
--- a/code/modules/clothing/head/_head.dm
+++ b/code/modules/clothing/head/_head.dm
@@ -8,6 +8,7 @@
var/blockTracking = 0 //For AI tracking
var/can_toggle = null
dynamic_hair_suffix = "+generic"
+ var/datum/beepsky_fashion/beepsky_fashion //the associated datum for applying this to a secbot
/obj/item/clothing/head/Initialize()
. = ..()
diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm
index 314142d0cc..20cb7cc824 100644
--- a/code/modules/clothing/head/collectable.dm
+++ b/code/modules/clothing/head/collectable.dm
@@ -27,7 +27,9 @@
icon_state = "chef"
item_state = "chef"
dynamic_hair_suffix = ""
+
dog_fashion = /datum/dog_fashion/head/chef
+ beepsky_fashion = /datum/beepsky_fashion/chef
/obj/item/clothing/head/collectable/paper
name = "collectable paper hat"
@@ -42,6 +44,8 @@
icon_state = "tophat"
item_state = "that"
+ beepsky_fashion = /datum/beepsky_fashion/tophat
+
/obj/item/clothing/head/collectable/captain
name = "collectable captain's hat"
desc = "A collectable hat that'll make you look just like a real comdom!"
@@ -49,6 +53,7 @@
item_state = "caphat"
dog_fashion = /datum/dog_fashion/head/captain
+ beepsky_fashion = /datum/beepsky_fashion/captain
/obj/item/clothing/head/collectable/police
name = "collectable police officer's hat"
@@ -91,6 +96,7 @@
item_state = "pirate"
dog_fashion = /datum/dog_fashion/head/pirate
+ beepsky_fashion = /datum/beepsky_fashion/pirate
/obj/item/clothing/head/collectable/kitty
name = "collectable kitty ears"
@@ -100,6 +106,7 @@
dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/kitty
+ beepsky_fashion = /datum/beepsky_fashion/cat
/obj/item/clothing/head/collectable/rabbitears
name = "collectable rabbit ears"
@@ -116,6 +123,7 @@
icon_state = "wizard"
dog_fashion = /datum/dog_fashion/head/blue_wizard
+ beepsky_fashion = /datum/beepsky_fashion/wizard
/obj/item/clothing/head/collectable/hardhat
name = "collectable hard hat"
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 80d0b7c8a8..12a4a43ca7 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -15,6 +15,7 @@
dynamic_hair_suffix = "+generic"
dog_fashion = /datum/dog_fashion/head
+ beepsky_fashion = /datum/beepsky_fashion/engineer
/obj/item/clothing/head/hardhat/ComponentInitialize()
diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm
index 638a0c2f23..5af694ea1b 100644
--- a/code/modules/clothing/head/jobs.dm
+++ b/code/modules/clothing/head/jobs.dm
@@ -13,7 +13,9 @@
strip_delay = 10
equip_delay_other = 10
dynamic_hair_suffix = ""
+
dog_fashion = /datum/dog_fashion/head/chef
+ beepsky_fashion = /datum/beepsky_fashion/chef
/obj/item/clothing/head/chefhat/suicide_act(mob/user)
user.visible_message("
[user] is donning [src]! It looks like [user.p_theyre()] trying to become a chef.")
@@ -33,7 +35,9 @@
flags_inv = 0
armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
strip_delay = 60
+
dog_fashion = /datum/dog_fashion/head/captain
+ beepsky_fashion = /datum/beepsky_fashion/captain
//Captain: This is no longer space-worthy
/obj/item/clothing/head/caphat/parade
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 416d0d2383..124ece8fdc 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -20,9 +20,11 @@
desc = "It's an amish looking hat."
icon_state = "tophat"
item_state = "that"
- dog_fashion = /datum/dog_fashion/head
throwforce = 1
+ dog_fashion = /datum/dog_fashion/head
+ beepsky_fashion = /datum/beepsky_fashion/tophat
+
/obj/item/clothing/head/canada
name = "striped red tophat"
desc = "It smells like fresh donut holes. /
Il sent comme des trous de beignets frais."
@@ -126,7 +128,9 @@
desc = "Yarr."
icon_state = "pirate"
item_state = "pirate"
+
dog_fashion = /datum/dog_fashion/head/pirate
+ beepsky_fashion = /datum/beepsky_fashion/pirate
/obj/item/clothing/head/pirate/captain
name = "pirate captain hat"
@@ -189,6 +193,8 @@
desc = "A really cool hat if you're a mobster. A really lame hat if you're not."
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small
+ beepsky_fashion = /datum/beepsky_fashion/fedora
+
/obj/item/clothing/head/fedora/suicide_act(mob/user)
if(user.gender == FEMALE)
return 0
@@ -205,7 +211,9 @@
item_state = "sombrero"
desc = "You can practically taste the fiesta."
flags_inv = HIDEHAIR
+
dog_fashion = /datum/dog_fashion/head/sombrero
+ beepsky_fashion = /datum/beepsky_fashion/sombrero
/obj/item/clothing/head/sombrero/green
name = "green sombrero"
@@ -213,6 +221,7 @@
item_state = "greensombrero"
desc = "As elegant as a dancing cactus."
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
+
dog_fashion = null
/obj/item/clothing/head/sombrero/shamebrero
@@ -220,6 +229,7 @@
icon_state = "shamebrero"
item_state = "shamebrero"
desc = "Once it's on, it never comes off."
+
dog_fashion = null
/obj/item/clothing/head/sombrero/shamebrero/Initialize()
@@ -248,7 +258,9 @@
item_state = "that"
cold_protection = HEAD
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
+
dog_fashion = /datum/dog_fashion/head/santa
+ beepsky_fashion = /datum/beepsky_fashion/santa
/obj/item/clothing/head/jester
name = "jester hat"
@@ -286,6 +298,8 @@
resistance_flags = FIRE_PROOF
dynamic_hair_suffix = ""
+ beepsky_fashion = /datum/beepsky_fashion/king
+
/obj/item/clothing/head/crown/fancy
name = "magnificent crown"
desc = "A crown worn by only the highest emperors of the
land space."
@@ -391,7 +405,9 @@
name = "cowboy hat"
desc = "A standard brown cowboy hat, yeehaw."
icon_state = "cowboyhat"
- item_state= "cowboyhat"
+ item_state = "cowboyhat"
+
+ beepsky_fashion = /datum/beepsky_fashion/cowboy
/obj/item/clothing/head/cowboyhat/black
name = "black cowboy hat"
@@ -453,3 +469,16 @@
icon_state = "maid"
item_state = "maid"
dynamic_hair_suffix = ""
+
+/obj/item/clothing/head/widered
+ name = "Wide red hat"
+ desc = "It is both wide, and red. Stylish!"
+ icon_state = "widehat_red"
+ item_state = "widehat_red"
+
+/obj/item/clothing/head/kabuto
+ name = "Kabuto helmet"
+ desc = "A traditional kabuto helmet."
+ icon_state = "kabuto"
+ item_state = "kabuto"
+ flags_inv = HIDEHAIR|HIDEEARS
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index 54561c8a24..3774ce575f 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -50,6 +50,8 @@
flags_cover = HEADCOVERSEYES
heat = 1000
+ beepsky_fashion = /datum/beepsky_fashion/cake
+
/obj/item/clothing/head/hardhat/cakehat/process()
var/turf/location = src.loc
if(ishuman(location))
@@ -131,6 +133,7 @@
dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/kitty
+ beepsky_fashion = /datum/beepsky_fashion/cat
/obj/item/clothing/head/kitty/equipped(mob/living/carbon/human/user, slot)
if(ishuman(user) && slot == SLOT_HEAD)
@@ -287,7 +290,7 @@
if(!target.IsUnconscious())
to_chat(target, "
Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare.")
-/obj/item/clothing/head/foilhat/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/clothing/head/foilhat/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!warped && iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.head)
diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm
index 7a5a031e79..94f7ee179a 100644
--- a/code/modules/clothing/masks/_masks.dm
+++ b/code/modules/clothing/masks/_masks.dm
@@ -8,6 +8,7 @@
var/modifies_speech = FALSE
var/mask_adjusted = 0
var/adjusted_flags = null
+ var/datum/beepsky_fashion/beepsky_fashion //the associated datum for applying this to a secbot
/obj/item/clothing/mask/attack_self(mob/user)
if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE))
diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm
index c3934aa78c..51a526d089 100644
--- a/code/modules/clothing/neck/_neck.dm
+++ b/code/modules/clothing/neck/_neck.dm
@@ -219,7 +219,7 @@
lock = TRUE
return
-/obj/item/clothing/neck/petcollar/locked/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/clothing/neck/petcollar/locked/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user && user.get_item_by_slot(SLOT_NECK) && lock != FALSE)
to_chat(user, "
The collar is locked! You'll need unlock the collar before you can take it off!")
return
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index d67aea11a1..49256b490d 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -20,6 +20,15 @@
var/last_blood_DNA = "" //same as last one
var/last_blood_color = ""
+ ///Whether these shoes have laces that can be tied/untied
+ var/can_be_tied = TRUE
+ ///Are we currently tied? Can either be SHOES_UNTIED, SHOES_TIED, or SHOES_KNOTTED
+ var/tied = SHOES_TIED
+ ///How long it takes to lace/unlace these shoes
+ var/lace_time = 5 SECONDS
+ ///any alerts we have active
+ var/obj/screen/alert/our_alert
+
/obj/item/clothing/shoes/ComponentInitialize()
. = ..()
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /atom.proc/clean_blood)
@@ -43,6 +52,15 @@
playsound(user, 'sound/weapons/genhit2.ogg', 50, 1)
return(BRUTELOSS)
+/obj/item/clothing/shoes/examine(mob/user)
+ . = ..()
+
+ if(!ishuman(loc))
+ return ..()
+ if(tied == SHOES_UNTIED)
+ . += "The shoelaces are untied."
+ else if(tied == SHOES_KNOTTED)
+ . += "The shoelaces are all knotted together."
/obj/item/clothing/shoes/transfer_blood_dna(list/blood_dna, diseases)
..()
@@ -74,6 +92,9 @@
worn_y_dimension -= (offset * 2)
user.update_inv_shoes()
equipped_before_drop = TRUE
+ if(can_be_tied && tied == SHOES_UNTIED)
+ our_alert = user.throw_alert("shoealert", /obj/screen/alert/shoes/untied)
+ RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_trip, override=TRUE)
/obj/item/clothing/shoes/proc/restore_offsets(mob/user)
equipped_before_drop = FALSE
@@ -81,6 +102,8 @@
worn_y_dimension = world.icon_size
/obj/item/clothing/shoes/dropped(mob/user)
+ if(our_alert && (our_alert.mob_viewer == user))
+ user.clear_alert("shoealert")
if(offset && equipped_before_drop)
restore_offsets(user)
. = ..()
@@ -101,3 +124,165 @@
/obj/item/proc/negates_gravity()
return FALSE
+
+/**
+ * adjust_laces adjusts whether our shoes (assuming they can_be_tied) and tied, untied, or knotted
+ *
+ * In addition to setting the state, it will deal with getting rid of alerts if they exist, as well as registering and unregistering the stepping signals
+ *
+ * Arguments:
+ * *
+ * * state: SHOES_UNTIED, SHOES_TIED, or SHOES_KNOTTED, depending on what you want them to become
+ * * user: used to check to see if we're the ones unknotting our own laces
+ */
+/obj/item/clothing/shoes/proc/adjust_laces(state, mob/user)
+ if(!can_be_tied)
+ return
+
+ var/mob/living/carbon/human/our_guy
+ if(ishuman(loc))
+ our_guy = loc
+
+ tied = state
+ if(tied == SHOES_TIED)
+ if(our_guy)
+ our_guy.clear_alert("shoealert")
+ UnregisterSignal(src, COMSIG_SHOES_STEP_ACTION)
+ else
+ if(tied == SHOES_UNTIED && our_guy && user == our_guy)
+ our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/untied) // if we're the ones unknotting our own laces, of course we know they're untied
+ RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_trip, override=TRUE)
+
+/**
+ * handle_tying deals with all the actual tying/untying/knotting, inferring your intent from who you are in relation to the state of the laces
+ *
+ * If you're the wearer, you want them to move towards tied-ness (knotted -> untied -> tied). If you're not, you're pranking them, so you're moving towards knotted-ness (tied -> untied -> knotted)
+ *
+ * Arguments:
+ * *
+ * * user: who is the person interacting with the shoes?
+ */
+/obj/item/clothing/shoes/proc/handle_tying(mob/user)
+ ///our_guy here is the wearer, if one exists (and he must exist, or we don't care)
+ var/mob/living/carbon/human/our_guy = loc
+ if(!istype(our_guy))
+ return
+
+ if(!in_range(user, our_guy))
+ to_chat(user, "
You aren't close enough to interact with [src]'s laces!")
+ return
+
+ if(user == loc && tied != SHOES_TIED) // if they're our own shoes, go tie-wards
+ if(INTERACTING_WITH(user, our_guy))
+ to_chat(user, "
You're already interacting with [src]!")
+ return
+ user.visible_message("
[user] begins [tied ? "unknotting" : "tying"] the laces of [user.p_their()] [src.name].", "
You begin [tied ? "unknotting" : "tying"] the laces of your [src.name]...")
+
+ if(do_after(user, lace_time, needhand=TRUE, target=our_guy, extra_checks=CALLBACK(src, .proc/still_shoed, our_guy)))
+ to_chat(user, "
You [tied ? "unknot" : "tie"] the laces of your [src.name].")
+ if(tied == SHOES_UNTIED)
+ adjust_laces(SHOES_TIED, user)
+ else
+ adjust_laces(SHOES_UNTIED, user)
+
+ else // if they're someone else's shoes, go knot-wards
+ var/mob/living/L = user
+ if(istype(L) && (L.mobility_flags & MOBILITY_STAND))
+ to_chat(user, "
You must be on the floor to interact with [src]!")
+ return
+ if(tied == SHOES_KNOTTED)
+ to_chat(user, "
The laces on [loc]'s [src.name] are already a hopelessly tangled mess!")
+ return
+ if(INTERACTING_WITH(user, our_guy))
+ to_chat(user, "
You're already interacting with [src]!")
+ return
+
+ var/mod_time = lace_time
+ to_chat(user, "
You quietly set to work [tied ? "untying" : "knotting"] [loc]'s [src.name]...")
+ if(HAS_TRAIT(user, TRAIT_CLUMSY)) // based clowns trained their whole lives for this
+ mod_time *= 0.75
+
+ if(do_after(user, mod_time, needhand=TRUE, target=our_guy, extra_checks=CALLBACK(src, .proc/still_shoed, our_guy)))
+ to_chat(user, "
You [tied ? "untie" : "knot"] the laces on [loc]'s [src.name].")
+ if(tied == SHOES_UNTIED)
+ adjust_laces(SHOES_KNOTTED, user)
+ else
+ adjust_laces(SHOES_UNTIED, user)
+ else // if one of us moved
+ user.visible_message("
[our_guy] stamps on [user]'s hand, mid-shoelace [tied ? "knotting" : "untying"]!", "
Ow! [our_guy] stamps on your hand!", list(our_guy))
+ to_chat(our_guy, "
You stamp on [user]'s hand! What the- [user.p_they()] [user.p_were()] [tied ? "knotting" : "untying"] your shoelaces!")
+ user.emote("scream")
+ if(istype(L))
+ var/obj/item/bodypart/ouchie = L.get_bodypart(pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
+ if(ouchie)
+ ouchie.receive_damage(brute = 10, stamina = 40)
+ L.Paralyze(10)
+
+///checking to make sure we're still on the person we're supposed to be, for lacing do_after's
+/obj/item/clothing/shoes/proc/still_shoed(mob/living/carbon/our_guy)
+ return (loc == our_guy)
+
+///check_trip runs on each step to see if we fall over as a result of our lace status. Knotted laces are a guaranteed trip, while untied shoes are just a chance to stumble
+/obj/item/clothing/shoes/proc/check_trip()
+ var/mob/living/carbon/human/our_guy = loc
+ if(!istype(our_guy)) // are they REALLY /our guy/?
+ return
+
+ if(tied == SHOES_KNOTTED)
+ our_guy.Paralyze(5)
+ our_guy.Knockdown(10)
+ our_guy.visible_message("
[our_guy] trips on [our_guy.p_their()] knotted shoelaces and falls! What a klutz!", "
You trip on your knotted shoelaces and fall over!")
+ SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "trip", /datum/mood_event/tripped) // well we realized they're knotted now!
+ our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/knotted)
+
+ else if(tied == SHOES_UNTIED)
+ var/wiser = TRUE // did we stumble and realize our laces are undone?
+ switch(rand(1, 1000))
+ if(1) // .1% chance to trip and fall over (note these are per step while our laces are undone)
+ our_guy.Paralyze(5)
+ our_guy.Knockdown(10)
+ SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "trip", /datum/mood_event/tripped) // well we realized they're knotted now!
+ our_guy.visible_message("
[our_guy] trips on [our_guy.p_their()] untied shoelaces and falls! What a klutz!", "
You trip on your untied shoelaces and fall over!")
+
+ if(2 to 5) // .4% chance to stumble and lurch forward
+ our_guy.throw_at(get_step(our_guy, our_guy.dir), 3, 2)
+ to_chat(our_guy, "
You stumble on your untied shoelaces and lurch forward!")
+
+ if(6 to 13) // .7% chance to stumble and fling what we're holding
+ var/have_anything = FALSE
+ for(var/obj/item/I in our_guy.held_items)
+ have_anything = TRUE
+ our_guy.accident(I)
+ to_chat(our_guy, "
You trip on your shoelaces a bit[have_anything ? ", flinging what you were holding" : ""]!")
+
+ if(14 to 25) // 1.3ish% chance to stumble and be a bit off balance (like being disarmed)
+ to_chat(our_guy, "
You stumble a bit on your untied shoelaces!")
+ our_guy.ShoveOffBalance(SHOVE_OFFBALANCE_DURATION)
+ our_guy.Stagger(SHOVE_OFFBALANCE_DURATION) //yes, same.
+ if(26 to 1000)
+ wiser = FALSE
+ if(wiser)
+ SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "untied", /datum/mood_event/untied) // well we realized they're untied now!
+ our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/untied)
+
+
+/obj/item/clothing/shoes/on_attack_hand(mob/living/user, act_intent, unarmed_attack_flags)
+ if(!istype(user))
+ return ..()
+ if(loc == user && tied != SHOES_TIED && (user.mobility_flags & MOBILITY_USE))
+ handle_tying(user)
+ return
+ return ..()
+
+/obj/item/clothing/shoes/attack_self(mob/user)
+ . = ..()
+
+ if(INTERACTING_WITH(user, src))
+ to_chat(user, "
You're already interacting with [src]!")
+ return
+
+ to_chat(user, "
You begin [tied ? "untying" : "tying"] the laces on [src]...")
+
+ if(do_after(user, lace_time, needhand=TRUE, target=src,extra_checks=CALLBACK(src, .proc/still_shoed, user)))
+ to_chat(user, "
You [tied ? "untie" : "tie"] the laces on [src].")
+ adjust_laces(tied ? SHOES_TIED : SHOES_UNTIED, user)
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index b68bef6329..b0d760ebd9 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -17,6 +17,7 @@
resistance_flags = NONE
permeability_coefficient = 0.05 //Thick soles, and covers the ankle
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
+ lace_time = 12 SECONDS
/obj/item/clothing/shoes/combat/sneakboots
name = "insidious sneakboots"
@@ -49,6 +50,7 @@
strip_delay = 50
equip_delay_other = 50
permeability_coefficient = 0.9
+ can_be_tied = FALSE
/obj/item/clothing/shoes/sandal/marisa
desc = "A pair of magic black shoes."
@@ -73,6 +75,7 @@
resistance_flags = NONE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 40, "acid" = 75)
custom_price = PRICE_ABOVE_EXPENSIVE
+ can_be_tied = FALSE
/obj/item/clothing/shoes/galoshes/dry
name = "absorbent galoshes"
@@ -99,6 +102,7 @@
icon_state = "clown_shoes"
slowdown = SHOES_SLOWDOWN+1
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes/clown
+ lace_time = 20 SECONDS // how the hell do these laces even work??
/obj/item/clothing/shoes/clown_shoes/Initialize()
. = ..()
@@ -130,6 +134,7 @@
resistance_flags = NONE
permeability_coefficient = 0.05 //Thick soles, and covers the ankle
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
+ lace_time = 12 SECONDS
/obj/item/clothing/shoes/jackboots/fast
slowdown = -1
@@ -144,6 +149,7 @@
heat_protection = FEET|LEGS
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
+ lace_time = 8 SECONDS
/obj/item/clothing/shoes/winterboots/ice_boots
name = "ice hiking boots"
@@ -177,6 +183,7 @@
strip_delay = 40
equip_delay_other = 40
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
+ lace_time = 8 SECONDS
/obj/item/clothing/shoes/workboots/mining
name = "mining boots"
@@ -196,6 +203,7 @@
min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
heat_protection = FEET
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
+ lace_time = 10 SECONDS
/obj/item/clothing/shoes/cult/alt
name = "cultist boots"
@@ -226,12 +234,14 @@
strip_delay = 100
equip_delay_other = 100
permeability_coefficient = 0.9
+ can_be_tied = FALSE
/obj/item/clothing/shoes/griffin
name = "griffon boots"
desc = "A pair of costume boots fashioned after bird talons."
icon_state = "griffinboots"
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
+ lace_time = 8 SECONDS
/obj/item/clothing/shoes/bhop
name = "jump boots"
@@ -284,6 +294,7 @@
desc = "A giant, clunky pair of shoes crudely made out of bronze. Why would anyone wear these?"
icon = 'icons/obj/clothing/clockwork_garb.dmi'
icon_state = "clockwork_treads"
+ lace_time = 8 SECONDS
/obj/item/clothing/shoes/bronze/Initialize()
. = ..()
@@ -358,6 +369,7 @@
icon_state = "rus_shoes"
item_state = "rus_shoes"
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
+ lace_time = 8 SECONDS
// kevin is into feet
/obj/item/clothing/shoes/wraps
@@ -365,6 +377,7 @@
desc = "Ankle coverings. These ones have a golden design."
icon_state = "gildedcuffs"
body_parts_covered = FALSE
+ can_be_tied = FALSE
/obj/item/clothing/shoes/wraps/silver
name = "silver leg wraps"
@@ -385,6 +398,7 @@
name = "cowboy boots"
desc = "A standard pair of brown cowboy boots."
icon_state = "cowboyboots"
+ can_be_tied = FALSE
/obj/item/clothing/shoes/cowboyboots/black
name = "black cowboy boots"
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index 82dd3142ed..cba27845f1 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -7,7 +7,7 @@
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS
item_state = "spaceold"
permeability_coefficient = 0.01
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70, "wound" = 5)
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
dynamic_hair_suffix = ""
dynamic_fhair_suffix = ""
@@ -36,7 +36,7 @@
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/flashlight, /obj/item/tank/internals)
slowdown = 1
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70, "wound" = 5)
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAUR
cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm
index 4590d46219..3f77a2befc 100644
--- a/code/modules/clothing/spacesuits/chronosuit.dm
+++ b/code/modules/clothing/spacesuits/chronosuit.dm
@@ -4,7 +4,7 @@
icon_state = "chronohelmet"
item_state = "chronohelmet"
slowdown = 1
- armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 100)
+ armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 100, "wound" = 80)
resistance_flags = FIRE_PROOF | ACID_PROOF
var/obj/item/clothing/suit/space/chronos/suit = null
@@ -19,7 +19,7 @@
icon_state = "chronosuit"
item_state = "chronosuit"
actions_types = list(/datum/action/item_action/toggle)
- armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 1000)
+ armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 1000, "wound" = 80)
resistance_flags = FIRE_PROOF | ACID_PROOF
mutantrace_variation = STYLE_DIGITIGRADE
var/list/chronosafe_items = list(/obj/item/chrono_eraser, /obj/item/gun/energy/chrono_gun)
@@ -80,7 +80,7 @@
if(to_turf)
user.forceMove(to_turf)
user.SetStun(0)
- user.next_move = 1
+ user.SetNextAction(0, considered_action = FALSE, immediate = FALSE)
user.alpha = 255
user.update_atom_colour()
user.animate_movement = FORWARD_STEPS
@@ -124,8 +124,8 @@
for(var/obj/item/I in user.held_items)
ADD_TRAIT(I, TRAIT_NODROP, CHRONOSUIT_TRAIT)
user.animate_movement = NO_STEPS
- user.changeNext_move(8 + phase_in_ds)
- user.mob_transforming = 1
+ user.DelayNextAction(8 + phase_in_ds, considered_action = FALSE, immediate = FALSE)
+ user.mob_transforming = TRUE
user.anchored = TRUE
user.Stun(INFINITY)
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index f563c1029d..40797b97ed 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -5,7 +5,7 @@
icon_state = "hardsuit0-engineering"
item_state = "eng_helm"
max_integrity = 300
- armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75)
+ armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75, "wound" = 10)
var/basestate = "hardsuit"
var/brightness_on = 4 //luminosity when on
var/on = FALSE
@@ -107,11 +107,7 @@
/obj/item/clothing/suit/space/hardsuit/Initialize()
if(jetpack && ispath(jetpack))
jetpack = new jetpack(src)
- . = ..()
-
-/obj/item/clothing/suit/space/hardsuit/attack_self(mob/user)
- user.changeNext_move(CLICK_CD_MELEE)
- ..()
+ return ..()
/obj/item/clothing/suit/space/hardsuit/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/tank/jetpack/suit))
@@ -721,7 +717,7 @@
item_state = "rig0-soviet"
hardsuit_type = "soviet"
icon_state = "rig0-soviet"
- armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75)
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75, "wound" = 15)
mutantrace_variation = NONE
/obj/item/clothing/suit/space/hardsuit/soviet
@@ -730,7 +726,7 @@
item_state = "rig-soviet"
icon_state = "rig-soviet"
slowdown = 0.8
- armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75)
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75, "wound" = 15)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/soviet
mutantrace_variation = NONE
@@ -775,7 +771,7 @@
item_state = "ert_medical"
hardsuit_type = "ert_medical"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf
- armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95)
+ armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95, "wound" = 30)
slowdown = 0
max_charges = 5
@@ -804,7 +800,7 @@
icon_state = "hardsuit0-ert_medical"
item_state = "hardsuit0-ert_medical"
hardsuit_type = "ert_medical"
- armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95)
+ armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95, "wound" = 30)
/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red
icon_state = "hardsuit0-ert_security"
@@ -883,7 +879,7 @@
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF | LAVA_PROOF
heat_protection = HEAD
- armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100)
+ armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100, "wound" = 30)
brightness_on = 7
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator)
var/energy_color = "#35FFF0"
@@ -927,7 +923,7 @@
item_state = "swat_suit"
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF | LAVA_PROOF
- armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100)
+ armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100, "wound" = 30)
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/lavaknight
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index ee70f54ed0..5124c5d62e 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -51,7 +51,7 @@ Contains:
icon_state = "heavy"
item_state = "swat_suit"
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat)
- armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 50, "bio" = 90, "rad" = 20, "fire" = 100, "acid" = 100)
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 50, "bio" = 90, "rad" = 20, "fire" = 100, "acid" = 100, "wound" = 25)
strip_delay = 120
resistance_flags = FIRE_PROOF | ACID_PROOF
mutantrace_variation = STYLE_DIGITIGRADE
@@ -63,7 +63,7 @@ Contains:
dynamic_hair_suffix = "+generic"
dynamic_fhair_suffix = "+generic"
flags_inv = 0
- armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
+ armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF | ACID_PROOF
@@ -79,7 +79,7 @@ Contains:
flags_inv = 0
w_class = WEIGHT_CLASS_NORMAL
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
- armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
+ armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF | ACID_PROOF
@@ -140,7 +140,7 @@ Contains:
desc = "A thick, space-proof tricorne from the royal Space Queen. It's lined with a layer of reflective kevlar."
icon_state = "pirate"
item_state = "pirate"
- armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75)
+ armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75, "wound" = 30)
flags_inv = HIDEHAIR
strip_delay = 40
equip_delay_other = 20
@@ -163,7 +163,7 @@ Contains:
flags_inv = 0
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/melee/transforming/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum)
slowdown = 0
- armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75)
+ armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75, "wound" = 30)
strip_delay = 40
equip_delay_other = 20
mutantrace_variation = STYLE_DIGITIGRADE
@@ -175,7 +175,7 @@ Contains:
icon_state = "hardsuit0-ert_commander"
item_state = "hardsuit0-ert_commander"
hardsuit_type = "ert_commander"
- armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80)
+ armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 30)
strip_delay = 130
brightness_on = 7
resistance_flags = ACID_PROOF
@@ -191,7 +191,7 @@ Contains:
item_state = "ert_command"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
- armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80)
+ armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 30)
slowdown = 0
strip_delay = 130
resistance_flags = ACID_PROOF
@@ -244,7 +244,7 @@ Contains:
icon_state = "hardsuit0-ert_commander-alert"
item_state = "hardsuit0-ert_commander-alert"
hardsuit_type = "ert_commander-alert"
- armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
+ armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 50)
brightness_on = 8
resistance_flags = FIRE_PROOF | ACID_PROOF
@@ -254,7 +254,7 @@ Contains:
icon_state = "ert_command-alert"
item_state = "ert_command-alert"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert
- armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
+ armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 50)
resistance_flags = FIRE_PROOF | ACID_PROOF
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC
@@ -303,7 +303,7 @@ Contains:
icon_state = "space"
item_state = "s_suit"
desc = "A lightweight space suit with the basic ability to protect the wearer from the vacuum of space during emergencies."
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65, "wound" = 10)
/obj/item/clothing/head/helmet/space/eva
name = "EVA helmet"
@@ -311,7 +311,7 @@ Contains:
item_state = "space"
desc = "A lightweight space helmet with the basic ability to protect the wearer from the vacuum of space during emergencies."
flash_protect = 0
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65, "wound" = 10)
//Radiation
/obj/item/clothing/head/helmet/space/rad
@@ -319,7 +319,7 @@ Contains:
desc = "A special helmet that protects against radiation and space. Not much else unfortunately."
icon_state = "cespace_helmet"
item_state = "nothing"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0, "wound" = 5)
resistance_flags = FIRE_PROOF
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
actions_types = list()
@@ -329,7 +329,7 @@ Contains:
desc = "A special suit that protects against radiation and space. Not much else unfortunately."
icon_state = "hardsuit-rad"
item_state = "nothing"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0, "wound" = 5)
resistance_flags = FIRE_PROOF
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
mutantrace_variation = NONE
@@ -339,7 +339,7 @@ Contains:
desc = "An advanced, space-proof helmet. It appears to be modeled after an old-world eagle."
icon_state = "griffinhat"
item_state = "griffinhat"
- armor = list("melee" = 20, "bullet" = 40, "laser" = 30, "energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80)
+ armor = list("melee" = 20, "bullet" = 40, "laser" = 30, "energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 20)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = ACID_PROOF | FIRE_PROOF
@@ -351,7 +351,7 @@ Contains:
icon_state = "freedom"
item_state = "freedom"
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
- armor = list("melee" = 20, "bullet" = 40, "laser" = 30,"energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80)
+ armor = list("melee" = 20, "bullet" = 40, "laser" = 30,"energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 20)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = ACID_PROOF | FIRE_PROOF
@@ -364,7 +364,7 @@ Contains:
desc = "Spaceworthy and it looks like a space carp's head, smells like one too."
icon_state = "carp_helm"
item_state = "syndicate"
- armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75) //As whimpy as a space carp
+ armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75, "wound" = 5) //As whimpy as a space carp
brightness_on = 0 //luminosity when on
actions_types = list()
mutantrace_variation = NONE
@@ -380,7 +380,7 @@ Contains:
icon_state = "carp_suit"
item_state = "space_suit_syndicate"
slowdown = 0 //Space carp magic, never stop believing
- armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75) //As whimpy whimpy whoo
+ armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75, "wound" = 5) //As whimpy whimpy whoo
allowed = list(/obj/item/tank/internals, /obj/item/gun/ballistic/automatic/speargun) //I'm giving you a hint here
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/carp
mutantrace_variation = STYLE_DIGITIGRADE
@@ -442,14 +442,14 @@ Contains:
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor/old
desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats. Alas, this one looks pretty worn out and rusted."
- armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60)
+ armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20)
slowdown = 0.8
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old
charges = 12
/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old
desc = "A helmet worn by those who deal with paranormal threats for a living. Alas, this one looks pretty worn out and rusted."
- armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60)
+ armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20)
charges = 12
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker
@@ -467,14 +467,14 @@ Contains:
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old
desc = "Voices echo from the hardsuit, driving the user insane. This one is pretty battle-worn, but still fearsome."
- armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60)
+ armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20)
slowdown = 0.8
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/beserker/old
charges = 6
/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/beserker/old
desc = "Peering into the eyes of the helmet is enough to seal damnation. This one is pretty battle-worn, but still fearsome."
- armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60)
+ armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20)
charges = 6
/obj/item/clothing/head/helmet/space/fragile
@@ -482,7 +482,7 @@ Contains:
desc = "A bulky, air-tight helmet meant to protect the user during emergency situations. It doesn't look very durable."
icon_state = "syndicate-helm-orange"
item_state = "syndicate-helm-orange"
- armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0, "wound" = 5)
strip_delay = 65
/obj/item/clothing/suit/space/fragile
@@ -492,7 +492,7 @@ Contains:
icon_state = "syndicate-orange"
item_state = "syndicate-orange"
slowdown = 2
- armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0, "wound" = 5)
strip_delay = 65
/obj/item/clothing/suit/space/fragile/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
@@ -525,7 +525,7 @@ Contains:
icon_state = "hunter"
item_state = "swat_suit"
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat)
- armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
+ armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wpound" = 25)
strip_delay = 130
resistance_flags = FIRE_PROOF | ACID_PROOF
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index f17eb91b74..5128f77433 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -5,7 +5,7 @@
name = "EVA plasma envirosuit"
desc = "A special plasma containment suit designed to be space-worthy, as well as worn over other clothing. Like its smaller counterpart, it can automatically extinguish the wearer in a crisis, and holds twice as many charges."
allowed = list(/obj/item/gun, /obj/item/ammo_casing, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank)
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10)
resistance_flags = FIRE_PROOF
icon_state = "plasmaman_suit"
item_state = "plasmaman_suit"
@@ -40,7 +40,7 @@
icon_state = "plasmaman-helm"
item_state = "plasmaman-helm"
strip_delay = 80
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10)
resistance_flags = FIRE_PROOF
var/brightness_on = 4 //luminosity when the light is on
var/on = FALSE
@@ -77,7 +77,7 @@
desc = "A plasmaman containment helmet designed for security officers, protecting them from being flashed and burning alive, along-side other undesirables."
icon_state = "security_envirohelm"
item_state = "security_envirohelm"
- armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75)
+ armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 20)
/obj/item/clothing/head/helmet/space/plasmaman/security/warden
name = "warden's plasma envirosuit helmet"
@@ -132,7 +132,7 @@
desc = "A sturdier plasmaman envirohelmet designed for research directors."
icon_state = "rd_envirohelm"
item_state = "rd_envirohelm"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10)
/obj/item/clothing/head/helmet/space/plasmaman/robotics
name = "robotics plasma envirosuit helmet"
@@ -145,7 +145,7 @@
desc = "A space-worthy helmet specially designed for engineer plasmamen, the usual purple stripes being replaced by engineering's orange."
icon_state = "engineer_envirohelm"
item_state = "engineer_envirohelm"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 75)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 75, "wound" = 10)
/obj/item/clothing/head/helmet/space/plasmaman/engineering/ce
name = "chief engineer's plasma envirosuit helmet"
@@ -194,7 +194,7 @@
desc = "A blue and gold envirohelm designed for the station's captain, nonetheless. Made of superior materials to protect them from the station hazards and more."
icon_state = "captain_envirohelm"
item_state = "captain_envirohelm"
- armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 85)
+ armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 85, "wound" = 15)
/obj/item/clothing/head/helmet/space/plasmaman/curator
name = "curator's plasma envirosuit helmet"
diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm
index 662e333f59..f55379da2f 100644
--- a/code/modules/clothing/spacesuits/syndi.dm
+++ b/code/modules/clothing/spacesuits/syndi.dm
@@ -4,7 +4,7 @@
icon_state = "syndicate"
item_state = "syndicate"
desc = "Has a tag on it: Totally not property of an enemy corporation, honest!"
- armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85)
+ armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85, "wound" = 20)
/obj/item/clothing/suit/space/syndicate
name = "red space suit"
@@ -13,7 +13,7 @@
desc = "Has a tag on it: Totally not property of an enemy corporation, honest!"
w_class = WEIGHT_CLASS_NORMAL
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
- armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85)
+ armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85, "wound" = 20)
mutantrace_variation = STYLE_DIGITIGRADE
//Green syndicate space suit
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index b61743729f..cf7dbc7462 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -8,7 +8,7 @@
equip_delay_other = 40
max_integrity = 250
resistance_flags = NONE
- armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 15)
+ armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 10)
/obj/item/clothing/suit/armor/Initialize()
@@ -58,7 +58,7 @@
icon_state = "hos"
item_state = "greatcoat"
body_parts_covered = CHEST|GROIN|ARMS|LEGS
- armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 90, "wound" = 20)
+ armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 90, "wound" = 10)
cold_protection = CHEST|GROIN|LEGS|ARMS
heat_protection = CHEST|GROIN|LEGS|ARMS
strip_delay = 80
@@ -148,7 +148,7 @@
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80, "wound" = 30)
+ armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80, "wound" = 20)
blocks_shove_knockdown = TRUE
strip_delay = 80
equip_delay_other = 60
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 05abed603c..607a8ecb55 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -402,6 +402,30 @@
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
+/obj/item/clothing/suit/jacket/flannel
+ name = "black flannel jacket"
+ desc = "Comfy and supposedly flammable."
+ icon_state = "flannel"
+ item_state = "flannel"
+
+/obj/item/clothing/suit/jacket/flannel/red
+ name = "red flannel jacket"
+ desc = "Comfy and supposedly flammable."
+ icon_state = "flannel_red"
+ item_state = "flannel_red"
+
+/obj/item/clothing/suit/jacket/flannel/aqua
+ name = "aqua flannel jacket"
+ desc = "Comfy and supposedly flammable."
+ icon_state = "flannel_aqua"
+ item_state = "flannel_aqua"
+
+/obj/item/clothing/suit/jacket/flannel/brown
+ name = "brown flannel jacket"
+ desc = "Comfy and supposedly flammable."
+ icon_state = "flannel_brown"
+ item_state = "flannel_brown"
+
/obj/item/clothing/suit/jacket/leather
name = "leather jacket"
desc = "Pompadour not included."
@@ -760,6 +784,17 @@
desc = "A green winter coat hood."
icon_state = "winterhood_hydro"
+/obj/item/clothing/suit/hooded/wintercoat/bar
+ name = "bartender winter coat"
+ desc = "A fancy winter coat with a waistcoat and flamboyant bowtie stuck onto it. The zipper tab is actually the bowtie."
+ icon_state = "coatbar"
+ item_state = "coatbar"
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/bar
+
+/obj/item/clothing/head/hooded/winterhood/bar
+ desc = "A fancy winter coat hood."
+ icon_state = "winterhood_bar"
+
/obj/item/clothing/suit/hooded/wintercoat/cosmic
name = "cosmic winter coat"
desc = "A starry winter coat that even glows softly."
@@ -1022,3 +1057,9 @@
desc = "Reminds you of someone, but you just can't put your finger on it..."
icon_state = "waldo_shirt"
item_state = "waldo_shirt"
+
+/obj/item/clothing/suit/samurai
+ name = "Samurai outfit"
+ desc = "An outfit used by traditional japanese warriors."
+ icon_state = "samurai"
+ item_state = "samurai"
\ No newline at end of file
diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm
index 94273d2c73..977e916f87 100644
--- a/code/modules/clothing/suits/wiz_robe.dm
+++ b/code/modules/clothing/suits/wiz_robe.dm
@@ -9,6 +9,7 @@
equip_delay_other = 50
resistance_flags = FIRE_PROOF | ACID_PROOF
dog_fashion = /datum/dog_fashion/head/blue_wizard
+ beepsky_fashion = /datum/beepsky_fashion/wizard
var/magic_flags = SPELL_WIZARD_HAT
/obj/item/clothing/head/wizard/ComponentInitialize()
diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm
index 3e7bc755cb..18cd104ff8 100644
--- a/code/modules/clothing/under/costume.dm
+++ b/code/modules/clothing/under/costume.dm
@@ -329,3 +329,29 @@
desc = "cloud"
icon_state = "cloud"
can_adjust = FALSE
+
+/obj/item/clothing/under/costume/kimono
+ name = "Kimono"
+ desc = "A traditional piece of clothing from japan"
+ icon_state = "kimono"
+ item_state = "kimono"
+
+/obj/item/clothing/under/costume/kimono/black
+ name = "Black Kimono"
+ icon_state = "kimono_a"
+ item_state = "kimono_a"
+
+/obj/item/clothing/under/costume/kimono/kamishimo
+ name = "Kamishimo"
+ icon_state = "kamishimo"
+ item_state = "kamishimo"
+
+/obj/item/clothing/under/costume/kimono/fancy
+ name = "Fancy Kimono"
+ icon_state = "fancy_kimono"
+ item_state = "fancy_kimono"
+
+/obj/item/clothing/under/costume/kimono/sakura
+ name = "Sakura Kimono'"
+ icon_state = "sakura_kimono"
+ item_state = "sakura_kimono"
diff --git a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm
index 5928819b16..082d783bea 100644
--- a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm
+++ b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm
@@ -57,7 +57,7 @@
desc = "An expensive piece of plasmaman envirosuit fashion. guaranteed to keep you cool while the station goes down in fierceful fires."
icon_state = "captain_envirosuit"
item_state = "captain_envirosuit"
- armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95)
+ armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 15)
sensor_mode = SENSOR_COORDS
random_sensor = FALSE
diff --git a/code/modules/clothing/under/jobs/Plasmaman/engineering.dm b/code/modules/clothing/under/jobs/Plasmaman/engineering.dm
index 15eb189fa8..4850a605e7 100644
--- a/code/modules/clothing/under/jobs/Plasmaman/engineering.dm
+++ b/code/modules/clothing/under/jobs/Plasmaman/engineering.dm
@@ -3,7 +3,7 @@
desc = "An air-tight suit designed to be used by plasmamen exployed as engineers, the usual purple stripes being replaced by engineer's orange. It protects the user from fire and acid damage."
icon_state = "engineer_envirosuit"
item_state = "engineer_envirosuit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 95, "acid" = 95)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 95, "acid" = 95, "wound" = 5)
/obj/item/clothing/under/plasmaman/engineering/ce
name = "chief engineer's plasma envirosuit"
diff --git a/code/modules/clothing/under/jobs/Plasmaman/medsci.dm b/code/modules/clothing/under/jobs/Plasmaman/medsci.dm
index 03d089c10d..52f817dcce 100644
--- a/code/modules/clothing/under/jobs/Plasmaman/medsci.dm
+++ b/code/modules/clothing/under/jobs/Plasmaman/medsci.dm
@@ -21,7 +21,7 @@
desc = "A plasmaman envirosuit designed for the research director to aid them in their job of directing research into the right direction."
icon_state = "rd_envirosuit"
item_state = "rd_envirosuit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 5)
/obj/item/clothing/under/plasmaman/robotics
name = "robotics plasma envirosuit"
diff --git a/code/modules/clothing/under/jobs/Plasmaman/security.dm b/code/modules/clothing/under/jobs/Plasmaman/security.dm
index ddbda041f3..3330d72844 100644
--- a/code/modules/clothing/under/jobs/Plasmaman/security.dm
+++ b/code/modules/clothing/under/jobs/Plasmaman/security.dm
@@ -3,7 +3,7 @@
desc = "A plasmaman containment suit designed for security officers, offering a limited amount of extra protection."
icon_state = "security_envirosuit"
item_state = "security_envirosuit"
- armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95)
+ armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 10)
sensor_mode = SENSOR_COORDS
random_sensor = FALSE
diff --git a/code/modules/clothing/under/jobs/civilian/civilian.dm b/code/modules/clothing/under/jobs/civilian/civilian.dm
index 4eb6a18258..5dffc8f88d 100644
--- a/code/modules/clothing/under/jobs/civilian/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian/civilian.dm
@@ -110,7 +110,7 @@
desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards."
name = "janitor's jumpsuit"
icon_state = "janitor"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/civilian/janitor/skirt
name = "janitor's jumpskirt"
diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm
index 3eaaa42620..5693468b3b 100644
--- a/code/modules/clothing/under/jobs/engineering.dm
+++ b/code/modules/clothing/under/jobs/engineering.dm
@@ -4,7 +4,7 @@
name = "chief engineer's jumpsuit"
icon_state = "chiefengineer"
item_state = "gy_suit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 80, "acid" = 40)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 80, "acid" = 40, "wound" = 5)
resistance_flags = NONE
/obj/item/clothing/under/rank/engineering/chief_engineer/skirt
@@ -39,7 +39,7 @@
name = "engineer's jumpsuit"
icon_state = "engine"
item_state = "engi_suit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20, "wound" = 5)
resistance_flags = NONE
/obj/item/clothing/under/rank/engineering/engineer/hazard
diff --git a/code/modules/clothing/under/jobs/medical.dm b/code/modules/clothing/under/jobs/medical.dm
index c4eedf93a4..c66b972624 100644
--- a/code/modules/clothing/under/jobs/medical.dm
+++ b/code/modules/clothing/under/jobs/medical.dm
@@ -4,7 +4,7 @@
icon_state = "cmo"
item_state = "w_suit"
permeability_coefficient = 0.5
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/medical/chief_medical_officer/skirt
name = "chief medical officer's jumpskirt"
@@ -30,7 +30,7 @@
icon_state = "genetics"
item_state = "w_suit"
permeability_coefficient = 0.5
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/medical/geneticist/skirt
name = "geneticist's jumpskirt"
@@ -48,7 +48,7 @@
icon_state = "virology"
item_state = "w_suit"
permeability_coefficient = 0.5
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/medical/virologist/skirt
name = "virologist's jumpskirt"
@@ -66,7 +66,7 @@
icon_state = "chemistry"
item_state = "w_suit"
permeability_coefficient = 0.5
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65, "wound" = 5)
/obj/item/clothing/under/rank/medical/chemist/skirt
name = "chemist's jumpskirt"
@@ -84,7 +84,7 @@
icon_state = "paramedic-dark"
item_state = "w_suit"
permeability_coefficient = 0.5
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/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."
@@ -110,7 +110,7 @@
icon_state = "nursesuit"
item_state = "w_suit"
permeability_coefficient = 0.5
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
body_parts_covered = CHEST|GROIN|ARMS
fitted = NO_FEMALE_UNIFORM
can_adjust = FALSE
@@ -122,7 +122,7 @@
icon_state = "medical"
item_state = "w_suit"
permeability_coefficient = 0.5
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/medical/doctor/blue
name = "blue medical scrubs"
diff --git a/code/modules/clothing/under/jobs/rnd.dm b/code/modules/clothing/under/jobs/rnd.dm
index f7bd6d5e33..03eb910736 100644
--- a/code/modules/clothing/under/jobs/rnd.dm
+++ b/code/modules/clothing/under/jobs/rnd.dm
@@ -3,7 +3,7 @@
name = "research director's vest suit"
icon_state = "director"
item_state = "lb_suit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 35)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 35, "wound" = 5)
can_adjust = FALSE
/obj/item/clothing/under/rank/rnd/research_director/skirt
@@ -20,7 +20,7 @@
name = "research director's tan suit"
icon_state = "rdwhimsy"
item_state = "rdwhimsy"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
can_adjust = TRUE
alt_covers_chest = TRUE
@@ -39,7 +39,7 @@
name = "research director's turtleneck"
icon_state = "rdturtle"
item_state = "p_suit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
can_adjust = TRUE
alt_covers_chest = TRUE
@@ -59,7 +59,7 @@
icon_state = "toxins"
item_state = "w_suit"
permeability_coefficient = 0.5
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/rnd/scientist/skirt
name = "scientist's jumpskirt"
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 997f10a379..27fb0cc00d 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -66,7 +66,7 @@
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
+ armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 1000) //wound defense at 100 wont stop wounds
cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
@@ -308,3 +308,21 @@
icon_state = "polyfemtankpantsu"
poly_states = 2
poly_colors = list("#808080", "#FF3535")
+
+/obj/item/clothing/under/misc/black_dress
+ name = "little black dress"
+ desc = "A small black dress"
+ icon_state = "littleblackdress_s"
+ item_state = "littleblackdress_s"
+
+/obj/item/clothing/under/misc/pinktutu
+ name = "pink tutu"
+ desc = "A pink tutu"
+ icon_state = "pinktutu_s"
+ item_state = "pinktutu_s"
+
+/obj/item/clothing/under/misc/bathrobe
+ name = "bathrobe"
+ desc = "A blue bathrobe."
+ icon_state = "bathrobe"
+ item_state = "bathrobe"
diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm
index 8a88e99d05..72af4e9572 100644
--- a/code/modules/clothing/under/syndicate.dm
+++ b/code/modules/clothing/under/syndicate.dm
@@ -4,7 +4,7 @@
icon_state = "syndicate"
item_state = "bl_suit"
has_sensor = NO_SENSORS
- armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40)
+ armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5)
alt_covers_chest = TRUE
/obj/item/clothing/under/syndicate/skirt
@@ -13,7 +13,7 @@
icon_state = "syndicate_skirt"
item_state = "bl_suit"
has_sensor = NO_SENSORS
- armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40)
+ armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5)
alt_covers_chest = TRUE
fitted = FEMALE_UNIFORM_TOP
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
@@ -24,7 +24,7 @@
icon_state = "bloodred_pajamas"
item_state = "bl_suit"
dummy_thick = TRUE
- armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 50, "acid" = 40)
+ armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 50, "acid" = 40, "wound" = 10)
resistance_flags = FIRE_PROOF | ACID_PROOF
can_adjust = FALSE
@@ -33,21 +33,21 @@
desc = "Do operatives dream of nuclear sheep?"
icon_state = "bloodred_pajamas"
item_state = "bl_suit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5)
/obj/item/clothing/under/syndicate/tacticool
name = "tacticool turtleneck"
desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-."
icon_state = "tactifool"
item_state = "bl_suit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5)
/obj/item/clothing/under/syndicate/tacticool/skirt
name = "tacticool skirtleneck"
desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-."
icon_state = "tactifool_skirt"
item_state = "bl_suit"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5)
fitted = FEMALE_UNIFORM_TOP
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
@@ -57,7 +57,7 @@
icon_state = "tactifool"
item_state = "bl_suit"
has_sensor = TRUE
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/syndicate/sniper
name = "Tactical turtleneck suit"
@@ -73,12 +73,15 @@
item_state = "g_suit"
can_adjust = FALSE
+/obj/item/clothing/under/syndicate/camo/cosmetic
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+
/obj/item/clothing/under/syndicate/soviet
name = "Ratnik 5 tracksuit"
desc = "Badly translated labels tell you to clean this in Vodka. Great for squatting in."
icon_state = "trackpants"
can_adjust = FALSE
- armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
resistance_flags = NONE
/obj/item/clothing/under/syndicate/combat
@@ -93,7 +96,7 @@
desc = "Military grade tracksuits for frontline squatting."
icon_state = "rus_under"
can_adjust = FALSE
- armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
resistance_flags = NONE
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
@@ -103,7 +106,7 @@
icon_state = "syndicatebaseball"
item_state = "syndicatebaseball"
has_sensor = NO_SENSORS
- armor = list("melee" = 15, "bullet" = 5, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40)
+ armor = list("melee" = 15, "bullet" = 5, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 10)
alt_covers_chest = TRUE
mutantrace_variation = USE_TAUR_CLIP_MASK
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index 3ee1990d14..70e85a9cfb 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -143,6 +143,8 @@
add_log("
Blood:")
found_something = TRUE
for(var/B in blood)
+ if(B == "color")
+ continue
add_log("Type:
[blood[B]] DNA:
[B]")
//Fibers
diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm
index cf2ac93360..06318df4f5 100644
--- a/code/modules/events/immovable_rod.dm
+++ b/code/modules/events/immovable_rod.dm
@@ -42,6 +42,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
name = "immovable rod"
desc = "What the fuck is that?"
icon = 'icons/obj/objects.dmi'
+ movement_type = FLOATING
icon_state = "immrod"
throwforce = 100
move_force = INFINITY
@@ -143,7 +144,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
if(L && (L.density || prob(10)))
L.ex_act(EXPLODE_HEAVY)
-obj/effect/immovablerod/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+obj/effect/immovablerod/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(ishuman(user))
var/mob/living/carbon/human/U = user
if(U.job in list("Research Director"))
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index ad786561f4..7cf11848e8 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -324,7 +324,7 @@
damage_dealt *= 4
if(I.damtype == BURN)
damage_dealt *= 4
-
+ user.DelayNextAction()
for(var/datum/spacevine_mutation/SM in mutations)
damage_dealt = SM.on_hit(src, user, I, damage_dealt) //on_hit now takes override damage as arg and returns new value for other mutations to permutate further
take_damage(damage_dealt, I.damtype, "melee", 1)
@@ -345,8 +345,7 @@
for(var/datum/spacevine_mutation/SM in mutations)
SM.on_cross(src, AM)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/structure/spacevine/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/spacevine/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
for(var/datum/spacevine_mutation/SM in mutations)
SM.on_hit(src, user)
user_unbuckle_mob(user, user)
@@ -356,6 +355,7 @@
for(var/datum/spacevine_mutation/SM in mutations)
SM.on_hit(src, user)
user_unbuckle_mob(user,user)
+ return ..()
/obj/structure/spacevine/attack_alien(mob/living/user)
eat(user)
diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm
index b7afc3440e..c7b982eda8 100644
--- a/code/modules/events/travelling_trader.dm
+++ b/code/modules/events/travelling_trader.dm
@@ -1,8 +1,8 @@
/datum/round_event_control/travelling_trader
name = "Travelling Trader"
typepath = /datum/round_event/travelling_trader
- weight = 10
- max_occurrences = 3
+ weight = 8
+ max_occurrences = 2
earliest_start = 0 MINUTES
/datum/round_event/travelling_trader
@@ -52,6 +52,14 @@
var/acceptance_speech = "This is exactly what I wanted! I shall be on my way now, thank you.!"
var/refusal_speech = "A given_item? I wanted a requested_item!" //what they say when refusing an item
var/active = TRUE
+ var/examine_text = list("
You attempt to look directly at the being's face, but it's just a blur!")
+ move_resist = MOVE_FORCE_VERY_STRONG
+ mob_size = MOB_SIZE_LARGE
+ alpha = 200
+
+/mob/living/carbon/human/dummy/travelling_trader/examine(mob/user)
+ SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, examine_text)
+ return examine_text
/mob/living/carbon/human/dummy/travelling_trader/proc/setup_speech(var/input_speech, var/obj/item/given_item)
if(requested_item)
@@ -60,7 +68,7 @@
input_speech = replacetext(input_speech, "given_item", given_item.name)
return input_speech
-/mob/living/carbon/human/dummy/travelling_trader/attack_hand(mob/living/carbon/human/H)
+/mob/living/carbon/human/dummy/travelling_trader/on_attack_hand(mob/living/carbon/human/H)
if(active && last_speech + 3 < world.realtime) //can only talk once per 3 seconds, to avoid spam
last_speech = world.realtime
if(initial_speech)
@@ -92,6 +100,8 @@
/mob/living/carbon/human/dummy/travelling_trader/Initialize()
..()
+ add_atom_colour("#570d6b", FIXED_COLOUR_PRIORITY) //make them purple (otherworldly!)
+ set_light(1, -0.7, "#AAD84B")
ADD_TRAIT(src,TRAIT_PIERCEIMMUNE, "trader_pierce_immune") //don't let people take their blood
equipOutfit(trader_outfit, TRUE)
for(var/obj/item/item in src.get_equipped_items())
@@ -159,15 +169,11 @@
trader_name = "Otherworldly Animal Specialist"
trader_outfit = /datum/outfit/job/doctor
initial_speech = "Greetings, lifeform. I am here to locate a special creature aboard your station."
- request_speech = "Find me the creature known as 'requested_item' and you shall be rewarded for your efforts."
+ request_speech = "Find me the creature known as 'requested_item' and hand it to me, preferably in a suitable container."
refusal_speech = "Do you think me to be a fool, lifeform? I know a requested_item when I see one."
- possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi/Ian = 1,
- /mob/living/simple_animal/sloth/paperwork = 1,
- /mob/living/carbon/monkey/punpun = 1,
- /mob/living/simple_animal/pet/fox/Renault = 1,
- /mob/living/simple_animal/hostile/carp/cayenne = 1,
- /mob/living/simple_animal/pet/bumbles = 1,
- /mob/living/simple_animal/parrot/Poly = 1)
+ possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi = 4,
+ /mob/living/carbon/monkey = 1,
+ /mob/living/simple_animal/mouse = 2)
possible_rewards = list(/mob/living/simple_animal/pet/dog/corgi/exoticcorgi = 1, //rewards are animals, friendly to only the person who handed the reward in!
/mob/living/simple_animal/cockroach = 1,
/mob/living/simple_animal/hostile/skeleton = 1,
@@ -184,13 +190,6 @@
mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize()
acceptance_speech = pick(list("This lifeform shall make for a great stew, thank you.", "This lifeform shall be of a true use to our cause, thank you.", "The lifeform is adequate. Goodbye.", "This lifeform shall make a great addition to my collection."))
- //make sure they only ask for animals that are still alive
- for(var/mob/living/animal in possible_wanted_items)
- if(!(animal in GLOB.mob_living_list))
- possible_wanted_items -= animal
- if(!possible_wanted_items)
- //all the pets are dead, so ask for a monkey, or sometimes a corgi (corgis are more annoying to get a hold of)
- possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi = 1, /mob/living/carbon/monkey = 3)
..()
/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/check_item(var/obj/item/supplied_item) //item is likely to be in contents of whats supplied
@@ -282,6 +281,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize()
..()
/datum/outfit/artifact_dealer
+ name = "Artifact Dealer"
uniform = /obj/item/clothing/under/suit/black_really
shoes = /obj/item/clothing/shoes/combat
head = /obj/item/clothing/head/that
@@ -323,6 +323,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize()
reward.insert_organ(new_implant)
/datum/outfit/otherworldly_surgeon
+ name = "Otherworldly Surgeon"
uniform = /obj/item/clothing/under/pants/white
shoes = /obj/item/clothing/shoes/sneakers/white
gloves = /obj/item/clothing/gloves/color/latex
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index 2e68c57abd..a3ee8c5228 100644
--- a/code/modules/food_and_drinks/drinks/drinks.dm
+++ b/code/modules/food_and_drinks/drinks/drinks.dm
@@ -23,7 +23,6 @@
gulp_size = max(round(reagents.total_volume / 5), 5)
/obj/item/reagent_containers/food/drinks/attack(mob/living/M, mob/user, def_zone)
-
if(!reagents || !reagents.total_volume)
to_chat(user, "[src] is empty!")
return 0
@@ -37,9 +36,6 @@
if(M == user)
user.visible_message("[user] swallows a gulp of [src].", "You swallow a gulp of [src].")
- if(HAS_TRAIT(M, TRAIT_VORACIOUS))
- M.changeNext_move(CLICK_CD_MELEE * 0.5) //chug! chug! chug!
-
else
M.visible_message("[user] attempts to feed the contents of [src] to [M].", "[user] attempts to feed the contents of [src] to [M].")
if(!do_mob(user, M))
@@ -56,6 +52,10 @@
playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1)
return 1
+/obj/item/reagent_containers/food/drinks/CheckAttackCooldown(mob/user, atom/target)
+ var/fast = HAS_TRAIT(user, TRAIT_VORACIOUS) && (user == target)
+ return user.CheckActionCooldown(fast? CLICK_CD_RANGE : CLICK_CD_MELEE)
+
/obj/item/reagent_containers/food/drinks/afterattack(obj/target, mob/user , proximity)
. = ..()
if(!proximity)
@@ -299,6 +299,31 @@
desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea."
list_reagents = list(/datum/reagent/consumable/tea = 30)
+/obj/item/reagent_containers/food/drinks/mug/tea/red
+ name = "Dutchess Red tea"
+ icon_state = "tea"
+ desc = "Duchess Red's personal blend of red tea leaves and hot water. Great addition to any meal."
+ list_reagents = list(/datum/reagent/consumable/tea/red = 30)
+
+/obj/item/reagent_containers/food/drinks/mug/tea/green
+ name = "Prince Green tea"
+ icon_state = "tea"
+ desc = "Prince Green's brew of tea. The blend may be different from time to time, but Prince Green swears by it!"
+ list_reagents = list(/datum/reagent/consumable/tea/green = 30)
+
+/obj/item/reagent_containers/food/drinks/mug/tea/forest
+ name = "Royal Forest tea"
+ icon_state = "tea"
+ desc = "Tea fit for anyone with a sweet tooth like Royal Forest."
+ list_reagents = list(/datum/reagent/consumable/tea/forest = 30)
+
+/obj/item/reagent_containers/food/drinks/mug/tea/mush
+ name = "Rebel Mush tea"
+ icon_state = "tea"
+ desc = "Rebel Mush, a hallucinogenic tea to help people find their inner self."
+ list_reagents = list(/datum/reagent/consumable/tea/mush = 30)
+
+
/obj/item/reagent_containers/food/drinks/mug/coco
name = "Dutch hot coco"
desc = "Made in Space South America."
diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
index d87eb8fbc0..e31a9704df 100644
--- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
@@ -87,7 +87,7 @@
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("stabbed", "slashed", "attacked")
var/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/broken_bottle/Initialize()
. = ..()
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index adb8e47c94..895699434a 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -129,8 +129,6 @@ All foods are distributed among various categories. Use common sense.
else if(fullness > (600 * (1 + M.overeatduration / 2000))) // The more you eat - the more you can eat
user.visible_message("[user] cannot force any more of \the [src] to go down [user.p_their()] throat!", "You cannot force any more of \the [src] to go down your throat!")
return 0
- if(HAS_TRAIT(M, TRAIT_VORACIOUS))
- M.changeNext_move(CLICK_CD_MELEE * 0.5) //nom nom nom
else
if(!isbrain(M)) //If you're feeding it to someone else.
if(fullness <= (600 * (1 + M.overeatduration / 1000)))
@@ -167,6 +165,10 @@ All foods are distributed among various categories. Use common sense.
return 0
+/obj/item/reagent_containers/food/snacks/CheckAttackCooldown(mob/user, atom/target)
+ var/fast = HAS_TRAIT(user, TRAIT_VORACIOUS) && (user == target)
+ return user.CheckActionCooldown(fast? CLICK_CD_RANGE : CLICK_CD_MELEE)
+
/obj/item/reagent_containers/food/snacks/examine(mob/user)
. = ..()
if(food_quality >= 70)
@@ -247,21 +249,9 @@ All foods are distributed among various categories. Use common sense.
to_chat(user, "You cannot slice [src] here! You need a table or at least a tray.")
return FALSE
- var/slices_lost = 0
- if (accuracy >= IS_SHARP_ACCURATE)
- user.visible_message( \
- "[user] slices [src].", \
- "You slice [src]." \
- )
- else
- user.visible_message( \
- "[user] inaccurately slices [src] with [W]!", \
- "You inaccurately slice [src] with your [W]!" \
- )
- slices_lost = rand(1,min(1,round(slices_num/2)))
-
+ user.visible_message("[user] slices [src].", "You slice [src].")
var/reagents_per_slice = reagents.total_volume/slices_num
- for(var/i=1 to (slices_num-slices_lost))
+ for(var/i=1 to slices_num)
var/obj/item/reagent_containers/food/snacks/slice = new slice_path (loc)
initialize_slice(slice, reagents_per_slice)
qdel(src)
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 f3c63c1ba2..fecc9467a1 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
@@ -130,7 +130,7 @@ God bless America.
/obj/machinery/deepfryer/attack_ai(mob/user)
return
-/obj/machinery/deepfryer/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/deepfryer/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(frying)
if(frying.loc == src)
to_chat(user, "You eject [frying] from [src].")
@@ -146,6 +146,8 @@ God bless America.
fry_loop.stop()
return
else if(user.pulling && user.a_intent == "grab" && iscarbon(user.pulling) && reagents.total_volume)
+ if(!user.CheckActionCooldown(CLICK_CD_MELEE))
+ return
if(user.grab_state < GRAB_AGGRESSIVE)
to_chat(user, "You need a better grip to do that!")
return
@@ -155,5 +157,5 @@ God bless America.
C.apply_damage(min(30, reagents.total_volume), BURN, BODY_ZONE_HEAD)
reagents.remove_any((reagents.total_volume/2))
C.DefaultCombatKnockdown(60)
- user.changeNext_move(CLICK_CD_MELEE)
+ user.DelayNextAction()
return ..()
diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
index 53da7326a2..e4148d849a 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
@@ -63,10 +63,7 @@
/obj/machinery/gibber/relaymove(mob/living/user)
go_out()
-/obj/machinery/gibber/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/gibber/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(stat & (NOPOWER|BROKEN))
return
if(operating)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/grill.dm b/code/modules/food_and_drinks/kitchen_machinery/grill.dm
index a5a90b33e4..09e1d7b1c6 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/grill.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/grill.dm
@@ -107,7 +107,7 @@
/obj/machinery/grill/attack_ai(mob/user)
return
-/obj/machinery/grill/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/grill/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(grilled_item)
to_chat(user, "You take out [grilled_item] from [src].")
grilled_item.forceMove(drop_location())
diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm
index 006c3fb6ad..a2603d07ab 100644
--- a/code/modules/food_and_drinks/pizzabox.dm
+++ b/code/modules/food_and_drinks/pizzabox.dm
@@ -106,8 +106,7 @@
START_PROCESSING(SSobj, src)
update_icon()
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/pizzabox/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/pizzabox/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.get_inactive_held_item() != src)
return ..()
if(open)
diff --git a/code/modules/food_and_drinks/recipes/drinks_recipes.dm b/code/modules/food_and_drinks/recipes/drinks_recipes.dm
index 8d8049194b..972f9a8cc3 100644
--- a/code/modules/food_and_drinks/recipes/drinks_recipes.dm
+++ b/code/modules/food_and_drinks/recipes/drinks_recipes.dm
@@ -18,12 +18,6 @@
results = list(/datum/reagent/consumable/ethanol/bilk = 2)
required_reagents = list(/datum/reagent/consumable/milk = 1, /datum/reagent/consumable/ethanol/beer = 1)
-/datum/chemical_reaction/icetea
- name = "Iced Tea"
- id = /datum/reagent/consumable/icetea
- results = list(/datum/reagent/consumable/icetea = 4)
- required_reagents = list(/datum/reagent/consumable/ice = 1, /datum/reagent/consumable/tea = 3)
-
/datum/chemical_reaction/icecoffee
name = "Iced Coffee"
id = /datum/reagent/consumable/icecoffee
@@ -581,13 +575,6 @@
required_reagents = list(/datum/reagent/consumable/lemonjuice = 2, /datum/reagent/water = 2, /datum/reagent/consumable/sugar = 1, /datum/reagent/consumable/ice = 1)
mix_message = "You're suddenly reminded of home."
-/datum/chemical_reaction/arnold_palmer
- name = "Arnold Palmer"
- id = /datum/reagent/consumable/tea/arnold_palmer
- results = list(/datum/reagent/consumable/tea/arnold_palmer = 2)
- required_reagents = list(/datum/reagent/consumable/tea = 1, /datum/reagent/consumable/lemonade = 1)
- mix_message = "The smells of fresh green grass and sand traps waft through the air as the mixture turns a friendly yellow-orange."
-
/datum/chemical_reaction/chocolate_milk
name = "chocolate milk"
id = /datum/reagent/consumable/milk/chocolate_milk
@@ -756,12 +743,6 @@
results = list(/datum/reagent/consumable/pinkmilk = 2)
required_reagents = list(/datum/reagent/consumable/strawberryjuice = 1, /datum/reagent/consumable/milk = 1)
-/datum/chemical_reaction/pinktea
- name = "Strawberry Tea"
- id = /datum/reagent/consumable/pinktea
- results = list(/datum/reagent/consumable/pinktea = 5)
- required_reagents = list(/datum/reagent/consumable/strawberryjuice = 1, /datum/reagent/consumable/tea/arnold_palmer = 1, /datum/reagent/consumable/sugar = 1)
-
/datum/chemical_reaction/blank_paper
name = "Blank Paper"
id = /datum/reagent/consumable/ethanol/blank_paper
@@ -903,12 +884,6 @@
results = list(/datum/reagent/consumable/ethanol/mauna_loa = 5)
required_reagents = list(/datum/reagent/consumable/capsaicin = 2, /datum/reagent/consumable/ethanol/kahlua = 1, /datum/reagent/consumable/ethanol/bahama_mama = 2)
-/datum/chemical_reaction/catnip_tea
- name = "Catnip Tea"
- id = /datum/reagent/consumable/catnip_tea
- results = list(/datum/reagent/consumable/catnip_tea = 3)
- required_reagents = list(/datum/reagent/consumable/tea = 5, /datum/reagent/pax/catnip = 2)
-
/datum/chemical_reaction/commander_and_chief
name = "Commander and Chief"
id = /datum/reagent/consumable/ethanol/commander_and_chief
@@ -916,79 +891,149 @@
required_reagents = list(/datum/reagent/consumable/ethanol/alliescocktail = 50, /datum/reagent/consumable/ethanol/champagne = 20, /datum/reagent/consumable/doctor_delight = 10, /datum/reagent/consumable/ethanol/quintuple_sec = 10, /datum/reagent/consumable/ethanol/screwdrivercocktail = 10)
mix_message = "When your powers combine, I am Captain Pl-..."
+////////////////////////////////////////// Tea Base Drinks //////////////////////////////////////
+
+/datum/chemical_reaction/mush
+ name = "Mush Tea"
+ id = /datum/reagent/consumable/tea/mush
+ results = list(/datum/reagent/consumable/tea/mush = 3)
+ required_reagents = list(/datum/reagent/drug/mushroomhallucinogen = 3, /datum/reagent/consumable/tea = 3)
+
+/datum/chemical_reaction/foresttea1
+ name = "Forest Tea"
+ id = /datum/reagent/consumable/tea/forest
+ results = list(/datum/reagent/consumable/tea/forest = 3)
+ required_reagents = list(/datum/reagent/consumable/buzz_fuzz= 3, /datum/reagent/consumable/tea = 3)
+
+/datum/chemical_reaction/foresttea2
+ name = "Forest Tea"
+ id = /datum/reagent/consumable/tea/forest
+ results = list(/datum/reagent/consumable/tea/forest = 3)
+ required_reagents = list(/datum/reagent/consumable/honey = 1, /datum/reagent/consumable/tea = 3)
+
+/datum/chemical_reaction/redtea1
+ name = "Red Tea"
+ id = /datum/reagent/consumable/tea/red
+ results = list(/datum/reagent/consumable/tea/red = 3)
+ required_reagents = list(/datum/reagent/colorful_reagent/crayonpowder/red = 1, /datum/reagent/consumable/tea = 3)
+
+/datum/chemical_reaction/greentea1
+ name = "Green Tea"
+ id = /datum/reagent/consumable/tea/green
+ results = list(/datum/reagent/consumable/tea/green = 3)
+ required_reagents = list(/datum/reagent/colorful_reagent/crayonpowder/green = 1, /datum/reagent/consumable/tea = 3)
+
+/datum/chemical_reaction/redtea2
+ name = "Red Tea"
+ id = /datum/reagent/consumable/tea/red
+ results = list(/datum/reagent/consumable/tea/red = 3)
+ required_reagents = list(/datum/reagent/toxin/teapowder/red = 1, /datum/reagent/water = 3)
+
+/datum/chemical_reaction/greentea2
+ name = "Green Tea"
+ id = /datum/reagent/consumable/tea/green
+ results = list(/datum/reagent/consumable/tea/green = 3)
+ required_reagents = list(/datum/reagent/toxin/teapowder/green = 1, /datum/reagent/water = 3)
+
+/datum/chemical_reaction/arnold_palmer
+ name = "Arnold Palmer"
+ id = /datum/reagent/consumable/tea/arnold_palmer
+ results = list(/datum/reagent/consumable/tea/arnold_palmer = 2)
+ required_reagents = list(/datum/reagent/consumable/tea = 1, /datum/reagent/consumable/lemonade = 1)
+ mix_message = "The smells of fresh green grass and sand traps waft through the air as the mixture turns a friendly yellow-orange."
+
+/datum/chemical_reaction/icetea
+ name = "Iced Tea"
+ id = /datum/reagent/consumable/icetea
+ results = list(/datum/reagent/consumable/icetea = 4)
+ required_reagents = list(/datum/reagent/consumable/ice = 1, /datum/reagent/consumable/tea = 3)
+
+/datum/chemical_reaction/pinktea
+ name = "Strawberry Tea"
+ id = /datum/reagent/consumable/pinktea
+ results = list(/datum/reagent/consumable/pinktea = 5)
+ required_reagents = list(/datum/reagent/consumable/strawberryjuice = 1, /datum/reagent/consumable/tea/arnold_palmer = 1, /datum/reagent/consumable/sugar = 1)
+
+/datum/chemical_reaction/catnip_tea
+ name = "Catnip Tea"
+ id = /datum/reagent/consumable/catnip_tea
+ results = list(/datum/reagent/consumable/catnip_tea = 3)
+ required_reagents = list(/datum/reagent/consumable/tea = 5, /datum/reagent/pax/catnip = 2)
+
+
////////////////////////////////////////// Race Base Drinks //////////////////////////////////////
/datum/chemical_reaction/coldscales
name = "Cold Scales"
- id = /datum/reagent/consumable/ethanol/coldscales
- results = list(/datum/reagent/consumable/ethanol/coldscales = 3)
+ id = /datum/reagent/consumable/ethanol/species_drink/coldscales
+ results = list(/datum/reagent/consumable/ethanol/species_drink/coldscales = 3)
required_reagents = list(/datum/reagent/consumable/tea = 1, /datum/reagent/toxin/slimejelly = 1, /datum/reagent/consumable/menthol = 1)
/datum/chemical_reaction/oil_drum
name = "Oil Drum"
- id = /datum/reagent/consumable/ethanol/oil_drum
- results = list(/datum/reagent/consumable/ethanol/oil_drum = 3)
+ id = /datum/reagent/consumable/ethanol/species_drink/oil_drum
+ results = list(/datum/reagent/consumable/ethanol/species_drink/oil_drum = 3)
required_reagents = list(/datum/reagent/consumable/ethanol = 1, /datum/reagent/oil = 1, /datum/reagent/consumable/ethanol/champagne = 12)
/datum/chemical_reaction/nord_king
name = "Nord King"
- id = /datum/reagent/consumable/ethanol/nord_king
- results = list(/datum/reagent/consumable/ethanol/nord_king = 10)
+ id = /datum/reagent/consumable/ethanol/species_drink/nord_king
+ results = list(/datum/reagent/consumable/ethanol/species_drink/nord_king = 10)
required_reagents = list(/datum/reagent/consumable/ethanol = 5, /datum/reagent/consumable/honey = 1, /datum/reagent/consumable/ethanol/red_mead = 10)
/datum/chemical_reaction/velvet_kiss
name = "Velvet Kiss"
- id = /datum/reagent/consumable/ethanol/velvet_kiss
- results = list(/datum/reagent/consumable/ethanol/velvet_kiss = 15) //Limited races use this
+ id = /datum/reagent/consumable/ethanol/species_drink/velvet_kiss
+ results = list(/datum/reagent/consumable/ethanol/species_drink/velvet_kiss = 15) //Limited races use this
required_reagents = list(/datum/reagent/blood = 5, /datum/reagent/consumable/tea = 1, /datum/reagent/consumable/ethanol/wine = 10)
/datum/chemical_reaction/abduction_fruit
name = "Abduction Fruit"
- id = /datum/reagent/consumable/ethanol/abduction_fruit
- results = list(/datum/reagent/consumable/ethanol/abduction_fruit = 3)
+ id = /datum/reagent/consumable/ethanol/species_drink/abduction_fruit
+ results = list(/datum/reagent/consumable/ethanol/species_drink/abduction_fruit = 3)
required_reagents = list(/datum/reagent/consumable/limejuice = 10, /datum/reagent/consumable/strawberryjuice = 5, /datum/reagent/consumable/watermelonjuice = 10)
/datum/chemical_reaction/bug_zapper
name = "Bug Zapper"
- id = /datum/reagent/consumable/ethanol/bug_zapper
- results = list(/datum/reagent/consumable/ethanol/bug_zapper = 20) //Harder to make
+ id = /datum/reagent/consumable/ethanol/species_drink/bug_zapper
+ results = list(/datum/reagent/consumable/ethanol/species_drink/bug_zapper = 20) //Harder to make
required_reagents = list(/datum/reagent/consumable/lemonjuice = 10, /datum/reagent/teslium = 1, /datum/reagent/copper = 10)
/datum/chemical_reaction/mush_crush
name = "Mush Crush"
- id = /datum/reagent/consumable/ethanol/mush_crush
- results = list(/datum/reagent/consumable/ethanol/mush_crush = 10)
+ id = /datum/reagent/consumable/ethanol/species_drink/mush_crush
+ results = list(/datum/reagent/consumable/ethanol/species_drink/mush_crush = 10)
required_reagents = list(/datum/reagent/iron = 5, /datum/reagent/ash = 5, /datum/reagent/toxin/coffeepowder = 10)
/datum/chemical_reaction/darkbrew
name = "Darkbrew"
- id = /datum/reagent/consumable/ethanol/darkbrew
- results = list(/datum/reagent/consumable/ethanol/darkbrew = 20)//Limited races use this
+ id = /datum/reagent/consumable/ethanol/species_drink/darkbrew
+ results = list(/datum/reagent/consumable/ethanol/species_drink/darkbrew = 20)//Limited races use this
required_reagents = list(/datum/reagent/liquid_dark_matter = 5, /datum/reagent/toxin/bungotoxin = 5, /datum/reagent/toxin/coffeepowder = 10)
/datum/chemical_reaction/hollow_bone
name = "Hollow Bone"
- id = /datum/reagent/consumable/ethanol/hollow_bone
- results = list(/datum/reagent/consumable/ethanol/hollow_bone = 10)
+ id = /datum/reagent/consumable/ethanol/species_drink/hollow_bone
+ results = list(/datum/reagent/consumable/ethanol/species_drink/hollow_bone = 10)
required_reagents = list(/datum/reagent/toxin/bonehurtingjuice = 5, /datum/reagent/consumable/milk = 10, /datum/reagent/consumable/coconutmilk = 10)
/datum/chemical_reaction/frisky_kitty
name = "Frisky Kitty"
- id = /datum/reagent/consumable/ethanol/frisky_kitty
- results = list(/datum/reagent/consumable/ethanol/frisky_kitty = 2)
+ id = /datum/reagent/consumable/ethanol/species_drink/frisky_kitty
+ results = list(/datum/reagent/consumable/ethanol/species_drink/frisky_kitty = 2)
required_reagents = list(/datum/reagent/consumable/catnip_tea = 1, /datum/reagent/consumable/milk = 1)
required_temp = 296 //Just above room temp (22.85'C)
/datum/chemical_reaction/jell_wyrm
name = "Jell Wyrm"
- id = /datum/reagent/consumable/ethanol/jell_wyrm
- results = list(/datum/reagent/consumable/ethanol/jell_wyrm = 2)
+ id = /datum/reagent/consumable/ethanol/species_drink/jell_wyrm
+ results = list(/datum/reagent/consumable/ethanol/species_drink/jell_wyrm = 2)
required_reagents = list(/datum/reagent/toxin/slimejelly = 1, /datum/reagent/toxin/carpotoxin = 1, /datum/reagent/carbondioxide = 5)
required_temp = 333 // (59.85'C)
/datum/chemical_reaction/laval_spit
name = "Laval Spit"
- id = /datum/reagent/consumable/ethanol/laval_spit
- results = list(/datum/reagent/consumable/ethanol/laval_spit = 20) //Limited use
+ id = /datum/reagent/consumable/ethanol/species_drink/laval_spit
+ results = list(/datum/reagent/consumable/ethanol/species_drink/laval_spit = 20) //Limited use
required_reagents = list(/datum/reagent/iron = 5, /datum/reagent/consumable/ethanol/mauna_loa = 10, /datum/reagent/sulfur = 5)
required_temp = 900 // (626.85'C)
diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css
index 93c733391e..2669a3634a 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput.css
@@ -303,7 +303,10 @@ h1.alert, h2.alert {color: #000000;}
.passive {color: #660000;}
.userdanger {color: #ff0000; font-weight: bold; font-size: 185%;}
+.bolddanger {color: #c51e1e;font-weight: bold;}
.danger {color: #ff0000;}
+.tinydanger {color: #c51e1e; font-size: 85%;}
+.smalldanger {color: #c51e1e; font-size: 90%;}
.warning {color: #ff0000; font-style: italic;}
.alertwarning {color: #FF0000; font-weight: bold}
.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
@@ -313,8 +316,9 @@ h1.alert, h2.alert {color: #000000;}
.rose {color: #ff5050;}
.info {color: #0000CC;}
.notice {color: #000099;}
-.tinynotice {color: #6685f5; font-style: italic; font-size: 85%;}
-.smallnotice {color: #6685f5; font-style: italic; font-size: 90%;}
+.tinynotice {color: #6685f5; font-style: italic; font-size: 85%;}
+.smallnotice {color: #6685f5; font-size: 90%;}
+.smallnoticeital {color: #6685f5; font-style: italic; font-size: 90%;}
.boldnotice {color: #000099; font-weight: bold;}
.adminnotice {color: #0000ff;}
.adminhelp {color: #ff0000; font-weight: bold;}
diff --git a/code/modules/holiday/halloween/bartholomew.dm b/code/modules/holiday/halloween/bartholomew.dm
index eb90a0c82d..c9a4a946a3 100644
--- a/code/modules/holiday/halloween/bartholomew.dm
+++ b/code/modules/holiday/halloween/bartholomew.dm
@@ -31,7 +31,7 @@
return
say("It doesn't seem like that's magical enough!")
-/obj/item/barthpot/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/barthpot/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!active)
say("Meow!")
return
diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm
index 01e71d1129..4561e0ae3e 100644
--- a/code/modules/holiday/halloween/jacqueen.dm
+++ b/code/modules/holiday/halloween/jacqueen.dm
@@ -76,7 +76,7 @@
health = 25
poof()
-/mob/living/simple_animal/jacq/attack_hand(mob/living/carbon/human/M)
+/mob/living/simple_animal/jacq/on_attack_hand(mob/living/carbon/human/M)
if(!active)
say("Hello there [gender_check(M)]!")
return ..()
@@ -406,14 +406,14 @@
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, GLUED_ITEM_TRAIT)
-/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/clothing/suit/ghost_sheet/sticky/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
to_chat(user, "Boooooo~!")
return
else
..()
-/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/clothing/suit/ghost_sheet/sticky/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
to_chat(user, "Boooooo~!")
return
diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm
index b6c89bcf0e..e4564ecb7e 100644
--- a/code/modules/holodeck/items.dm
+++ b/code/modules/holodeck/items.dm
@@ -105,10 +105,7 @@
if(user.transferItemToLoc(W, drop_location()))
visible_message(" [user] dunks [W] into \the [src]!")
-/obj/structure/holohoop/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/structure/holohoop/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling))
var/mob/living/L = user.pulling
if(user.grab_state < GRAB_AGGRESSIVE)
@@ -164,7 +161,7 @@
/obj/machinery/readybutton/attackby(obj/item/W as obj, mob/user as mob, params)
to_chat(user, "The device is a solid button, there's nothing you can do with it!")
-/obj/machinery/readybutton/attack_hand(mob/user as mob)
+/obj/machinery/readybutton/on_attack_hand(mob/user as mob)
. = ..()
if(.)
return
diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm
index f686bee63a..169c9061d3 100644
--- a/code/modules/holodeck/turfs.dm
+++ b/code/modules/holodeck/turfs.dm
@@ -134,7 +134,7 @@
tiled_dirt = FALSE
baseturfs = /turf/open/floor/holofloor/snow
-/turf/open/floor/holofloor/snow/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/turf/open/floor/holofloor/snow/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/hydroponics/fermenting_barrel.dm b/code/modules/hydroponics/fermenting_barrel.dm
index 70e204a14f..76e36a1725 100644
--- a/code/modules/hydroponics/fermenting_barrel.dm
+++ b/code/modules/hydroponics/fermenting_barrel.dm
@@ -56,7 +56,7 @@
else
return ..()
-/obj/structure/fermenting_barrel/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/fermenting_barrel/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
open = !open
if(open)
DISABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index 0411a80443..81318f8fe1 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -27,6 +27,12 @@
juice_results = list(/datum/reagent/consumable/banana = 0)
distill_reagent = /datum/reagent/consumable/ethanol/bananahonk
+/obj/item/reagent_containers/food/snacks/grown/banana/generate_trash(atom/location)
+ . = ..()
+ var/obj/item/grown/bananapeel/peel = .
+ if(istype(peel))
+ peel.grind_results = list(/datum/reagent/consumable/banana_peel = seed.potency * 0.2)
+
/obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user)
user.visible_message("[user] is aiming [src] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!")
playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1)
diff --git a/code/modules/hydroponics/grown/chili.dm b/code/modules/hydroponics/grown/chili.dm
index 42674029fb..001a90b441 100644
--- a/code/modules/hydroponics/grown/chili.dm
+++ b/code/modules/hydroponics/grown/chili.dm
@@ -80,11 +80,9 @@
foodtype = FRUIT
wine_power = 50
-/obj/item/reagent_containers/food/snacks/grown/ghost_chili/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/reagent_containers/food/snacks/grown/ghost_chili/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
- if(.)
- return
- if( ismob(loc) )
+ if(ishuman(loc))
held_mob = loc
START_PROCESSING(SSobj, src)
diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm
index 78fddbd989..328b4c391c 100644
--- a/code/modules/hydroponics/grown/replicapod.dm
+++ b/code/modules/hydroponics/grown/replicapod.dm
@@ -29,6 +29,28 @@
create_reagents(volume, INJECTABLE | DRAWABLE)
+/obj/item/seeds/replicapod/pre_attack(obj/machinery/hydroponics/I)
+ if(istype(I, /obj/machinery/hydroponics))
+ if(!I.myseed)
+ START_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/seeds/replicapod/proc/check_mind_orbiting(atom/A)
+ for(var/mob/M in A.orbiters?.orbiters)
+ if(mind && M.mind && ckey(M.mind.key) == ckey(mind.key) && M.ckey && M.client && M.stat == DEAD && !M.suiciding && isobserver(M))
+ return TRUE
+ return FALSE
+
+/obj/item/seeds/replicapod/process()
+ var/obj/machinery/hydroponics/parent = loc
+ if(parent.harvest != 1)
+ return
+ if (check_mind_orbiting(parent))
+ icon_harvest = "replicapod-orbit"
+ else
+ icon_harvest = "replicapod-harvest"
+ parent.update_icon_plant()
+
/obj/item/seeds/replicapod/on_reagent_change(changetype)
if(changetype == ADD_REAGENT)
var/datum/reagent/blood/B = reagents.has_reagent(/datum/reagent/blood)
@@ -59,8 +81,11 @@
/obj/item/seeds/replicapod/get_analyzer_text()
var/text = ..()
+ var/obj/machinery/hydroponics/parent = loc
if(contains_sample)
text += "\n It contains a blood sample!"
+ if (parent && istype(parent) && check_mind_orbiting(parent))
+ text += "\n The soul is ready to enter the body."
return text
@@ -115,7 +140,7 @@
features["mcolor"] = "#59CE00"
for(var/V in quirks)
new V(podman)
- podman.hardset_dna(null,null,null,podman.real_name,blood_type, new /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
+ podman.hardset_dna(null,null,podman.real_name,blood_type, new /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
podman.set_cloned_appearance()
else //else, one packet of seeds. maybe two
diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm
index 164c27d105..ecbfa7584b 100644
--- a/code/modules/hydroponics/grown/towercap.dm
+++ b/code/modules/hydroponics/grown/towercap.dm
@@ -207,10 +207,7 @@
return ..()
-/obj/structure/bonfire/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/structure/bonfire/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(burning)
to_chat(user, "You need to extinguish [src] before removing the logs!")
return
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 9b5983c8e9..abf6632939 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -82,7 +82,7 @@
custom_materials = list(/datum/material/iron = 15000)
attack_verb = list("chopped", "torn", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/hatchet/Initialize()
. = ..()
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index b673937c9c..06179d1087 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -888,10 +888,7 @@
return ..()
-/obj/machinery/hydroponics/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/hydroponics/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(issilicon(user)) //How does AI know what plant is?
return
if(harvest)
diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm
index 463398d2f2..d842dbc003 100644
--- a/code/modules/instruments/songs/_song.dm
+++ b/code/modules/instruments/songs/_song.dm
@@ -303,3 +303,19 @@
return TRUE
var/obj/structure/musician/M = parent
return M.should_stop_playing(user)
+
+/datum/song/holoparasite
+ var/mob/living/simple_animal/hostile/guardian/stand
+
+/datum/song/holoparasite/New(atom/parent, list/instrument_ids)
+ . = ..()
+ stand = istype(parent, /mob/living/simple_animal/hostile/guardian) && parent
+
+/datum/song/holoparasite/updateDialog()
+ stand.ui_interact(src)
+
+/datum/song/holoparasite/should_stop_playing(mob/user)
+ return FALSE
+
+/datum/song/holoparasite/check_can_use(mob/user)
+ return (user == stand)
diff --git a/code/modules/instruments/songs/editor.dm b/code/modules/instruments/songs/editor.dm
index d9595797d7..8c5171667a 100644
--- a/code/modules/instruments/songs/editor.dm
+++ b/code/modules/instruments/songs/editor.dm
@@ -109,8 +109,11 @@
linenum++
updateDialog(usr) // make sure updates when complete
+/datum/song/proc/check_can_use(mob/user)
+ return user.canUseTopic(parent, TRUE, FALSE, FALSE, FALSE)
+
/datum/song/Topic(href, href_list)
- if(!usr.canUseTopic(parent, TRUE, FALSE, FALSE, FALSE))
+ if(!check_can_use(usr))
usr << browse(null, "window=instrument")
usr.unset_machine()
return
diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm
index c3e0a7abcc..903ff13fa8 100644
--- a/code/modules/integrated_electronics/core/assemblies.dm
+++ b/code/modules/integrated_electronics/core/assemblies.dm
@@ -519,6 +519,7 @@
/obj/item/electronic_assembly/attack_self(mob/user)
+ set waitfor = FALSE
if(!check_interactivity(user))
return
if(opened)
@@ -611,7 +612,7 @@
return
..()
-/obj/item/electronic_assembly/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/electronic_assembly/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(anchored)
attack_self(user)
return
@@ -650,11 +651,6 @@
icon_state = "setup_small_pda"
desc = "It's a case, for building small electronics with. This one resembles a PDA."
-/obj/item/electronic_assembly/dildo
- name = "type-g electronic assembly"
- icon_state = "setup_dildo_medium"
- desc = "It's a case, for building small electronics with. This one has a phallic design."
-
/obj/item/electronic_assembly/small
name = "electronic device"
icon_state = "setup_device"
@@ -686,11 +682,6 @@
icon_state = "setup_device_box"
desc = "It's a case, for building tiny-sized electronics with. This one has a boxy design."
-/obj/item/electronic_assembly/small/dildo
- name = "type-f electronic device"
- icon_state = "setup_dildo_small"
- desc = "It's a case, for building tiny-sized electronics with. This one has a phallic design."
-
/obj/item/electronic_assembly/medium
name = "electronic mechanism"
icon_state = "setup_medium"
@@ -731,12 +722,6 @@
icon_state = "setup_medium_radio"
desc = "It's a case, for building medium-sized electronics with. This one resembles an old radio."
-/obj/item/electronic_assembly/medium/dildo
- name = "type-g electronic mechanism"
- icon_state = "setup_dildo_large"
- desc = "It's a case, for building medium-sized electronics with. This one has a phallic design."
-
-
/obj/item/electronic_assembly/large
name = "electronic machine"
icon_state = "setup_large"
diff --git a/code/modules/integrated_electronics/subtypes/weaponized.dm b/code/modules/integrated_electronics/subtypes/weaponized.dm
index 950525ab7f..96a732d08f 100644
--- a/code/modules/integrated_electronics/subtypes/weaponized.dm
+++ b/code/modules/integrated_electronics/subtypes/weaponized.dm
@@ -45,6 +45,9 @@
/obj/item/integrated_circuit/weaponized/weapon_firing/attackby(var/obj/O, var/mob/user)
if(istype(O, /obj/item/gun/energy))
var/obj/item/gun/gun = O
+ if(!gun.can_circuit)
+ to_chat(user, "[gun] does not fit into circuits.")
+ return
if(installed_gun)
to_chat(user, "There's already a weapon installed.")
return
diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm
index e5afe7e1b3..463113f14c 100644
--- a/code/modules/jobs/job_types/detective.dm
+++ b/code/modules/jobs/job_types/detective.dm
@@ -23,7 +23,7 @@
mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM)
display_order = JOB_DISPLAY_ORDER_DETECTIVE
- blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic)
+ blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/monophobia)
threat = 1
/datum/outfit/job/detective
diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm
index 69ed63a514..3d7d07d894 100644
--- a/code/modules/jobs/job_types/head_of_security.dm
+++ b/code/modules/jobs/job_types/head_of_security.dm
@@ -31,7 +31,7 @@
paycheck_department = ACCOUNT_SEC
display_order = JOB_DISPLAY_ORDER_HEAD_OF_SECURITY
- blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/insanity)
+ blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/insanity)
threat = 3
/datum/outfit/job/hos
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index bc6f6a94c7..7e71b2d1f4 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -23,7 +23,7 @@
mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM)
display_order = JOB_DISPLAY_ORDER_SECURITY_OFFICER
- blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic)
+ blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia)
threat = 2
/datum/job/officer/get_access()
diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm
index 5762731f62..22e3f9b0f1 100644
--- a/code/modules/jobs/job_types/warden.dm
+++ b/code/modules/jobs/job_types/warden.dm
@@ -24,7 +24,7 @@
mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM)
display_order = JOB_DISPLAY_ORDER_WARDEN
- blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic)
+ blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia)
threat = 2
/datum/job/warden/get_access()
diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm
index 6e3d27f2b8..55e9352843 100644
--- a/code/modules/language/language_holder.dm
+++ b/code/modules/language/language_holder.dm
@@ -276,7 +276,8 @@ Key procs
/datum/language/draconic = list(LANGUAGE_ATOM))
/datum/language_holder/lizard/ash
- selected_language = /datum/language/draconic
+ understood_languages = list(/datum/language/draconic = list(LANGUAGE_ATOM))
+ spoken_languages = list(/datum/language/draconic = list(LANGUAGE_ATOM))
/datum/language_holder/monkey
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index e5d9672d4a..80ce2522ff 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -112,7 +112,7 @@
else
return ..()
-/obj/structure/bookcase/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/bookcase/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(. || !istype(user))
return
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index f65ea27216..f777246453 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -523,10 +523,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
else
return ..()
-/obj/machinery/libraryscanner/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/libraryscanner/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
usr.set_machine(src)
var/dat = "" //
if(cache)
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index d2da0f779e..8c9b0b53e1 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -149,8 +149,7 @@
if(100)
new /obj/item/clothing/head/bearpelt(src)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/structure/closet/crate/secure/loot/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/closet/crate/secure/loot/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(locked)
to_chat(user, "The crate is locked with a Deca-code lock.")
var/input = input(usr, "Enter [codelen] digits. All digits must be unique.", "Deca-Code Lock", "") as text
diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm
index bf7a966f7d..006065d048 100644
--- a/code/modules/mining/aux_base.dm
+++ b/code/modules/mining/aux_base.dm
@@ -99,7 +99,6 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
say("Shuttle interface failed.")
if(href_list["random"] && !possible_destinations)
- usr.changeNext_move(CLICK_CD_RAPID) //Anti-spam
var/list/all_mining_turfs = list()
for (var/z_level in SSmapping.levels_by_trait(ZTRAIT_MINING))
all_mining_turfs += Z_TURFS(z_level)
@@ -275,10 +274,7 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
var/anti_spam_cd = 0 //The linking process might be a bit intensive, so this here to prevent over use.
var/console_range = 15 //Wifi range of the beacon to find the aux base console
-/obj/structure/mining_shuttle_beacon/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/structure/mining_shuttle_beacon/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(anchored)
to_chat(user, "Landing zone already set.")
return
diff --git a/code/modules/mining/aux_base_camera.dm b/code/modules/mining/aux_base_camera.dm
index d461523744..be0a41427f 100644
--- a/code/modules/mining/aux_base_camera.dm
+++ b/code/modules/mining/aux_base_camera.dm
@@ -187,7 +187,7 @@
if(LAZYLEN(S.rcd_vals(owner,B.RCD)))
rcd_target = S //If we don't break out of this loop we'll get the last placed thing
- owner.changeNext_move(CLICK_CD_RANGE)
+ owner.DelayNextAction(CLICK_CD_RANGE)
B.RCD.afterattack(rcd_target, owner, TRUE) //Activate the RCD and force it to work remotely!
playsound(target_turf, 'sound/items/deconstruct.ogg', 60, 1)
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index 745c46b131..bc368b635b 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -17,7 +17,7 @@
custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075)
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
actions_types = list(/datum/action/item_action/toggle_light)
var/list/trophies = list()
var/charged = TRUE
@@ -175,6 +175,49 @@
if(light_on)
. += "[icon_state]_lit"
+/obj/item/kinetic_crusher/glaive
+ name = "proto-kinetic glaive"
+ desc = "A modified design of a proto-kinetic crusher, it is still little more of a combination of various mining tools cobbled together \
+ and kit-bashed into a high-tech cleaver on a stick - with a handguard and a goliath hide grip. While it is still of little use to any \
+ but the most skilled and/or suicidal miners against local fauna, it's an elegant weapon for a more civilized hunter."
+ attack_verb = list("stabbed", "diced", "sliced", "cleaved", "chopped", "lacerated", "cut", "jabbed", "punctured")
+ icon_state = "crusher-glaive"
+ item_state = "crusher0-glaive"
+ item_flags = ITEM_CAN_PARRY
+ block_parry_data = /datum/block_parry_data/crusherglaive
+ //ideas: altclick that lets you pummel people with the handguard/handle?
+ //parrying functionality?
+
+/datum/block_parry_data/crusherglaive // it's like quickparry, without the damage multiplier
+ parry_time_windup = 0
+ parry_time_active = 5
+ parry_time_spindown = 0
+ parry_time_perfect = 1.5
+ parry_time_perfect_leeway = 0.5
+ parry_imperfect_falloff_percent = 30
+ parry_efficiency_perfect = 100
+ parry_failed_stagger_duration = 1 SECONDS
+ parry_failed_clickcd_duration = 1 SECONDS
+
+/obj/item/kinetic_crusher/glaive/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) // if you're dumb enough to go for a parry...
+ var/turf/proj_turf = owner.loc // destabilizer bolt, ignoring cooldown
+ if(!isturf(proj_turf))
+ return
+ var/obj/item/projectile/destabilizer/D = new /obj/item/projectile/destabilizer(proj_turf)
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.on_projectile_fire(D, owner)
+ D.preparePixelProjectile(attacker, owner)
+ D.firer = owner
+ D.hammer_synced = src
+ playsound(owner, 'sound/weapons/plasma_cutter.ogg', 100, 1)
+ D.fire()
+ if((!attacker.anchored || ismegafauna(attacker))) // free backstab, if you perfect parry
+ attacker.dir = get_dir(owner,attacker)
+
+/obj/item/kinetic_crusher/glaive/update_icon_state()
+ item_state = "crusher[wielded]-glaive" // this is not icon_state and not supported by 2hcomponent
+
//destablizing force
/obj/item/projectile/destabilizer
name = "destabilizing force"
diff --git a/code/modules/mining/equipment/marker_beacons.dm b/code/modules/mining/equipment/marker_beacons.dm
index ae2889e8a2..296513af8d 100644
--- a/code/modules/mining/equipment/marker_beacons.dm
+++ b/code/modules/mining/equipment/marker_beacons.dm
@@ -19,7 +19,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
singular_name = "marker beacon"
desc = "Prism-brand path illumination devices. Used by miners to mark paths and warn of danger."
icon = 'icons/obj/lighting.dmi'
- icon_state = "markerbronze"
+ icon_state = "marker"
merge_type = /obj/item/stack/marker_beacon
max_amount = 100
novariants = TRUE
@@ -103,7 +103,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
icon_state = "[initial(icon_state)][lowertext(picked_color)]-on"
set_light(light_range, light_power, GLOB.marker_beacon_colors[picked_color])
-/obj/structure/marker_beacon/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/marker_beacon/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm
index 50a3dec9dd..27259ce812 100644
--- a/code/modules/mining/equipment/mining_tools.dm
+++ b/code/modules/mining/equipment/mining_tools.dm
@@ -143,7 +143,7 @@
w_class = WEIGHT_CLASS_NORMAL
custom_materials = list(/datum/material/iron=350)
attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/shovel/Initialize()
. = ..()
@@ -181,4 +181,4 @@
w_class = WEIGHT_CLASS_NORMAL
toolspeed = 0.7
attack_verb = list("slashed", "impaled", "stabbed", "sliced")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
diff --git a/code/modules/mining/equipment/resonator.dm b/code/modules/mining/equipment/resonator.dm
index 133cb41c33..16dd893c3a 100644
--- a/code/modules/mining/equipment/resonator.dm
+++ b/code/modules/mining/equipment/resonator.dm
@@ -41,7 +41,7 @@
return
if(LAZYLEN(fields) < fieldlimit)
new /obj/effect/temp_visual/resonance(T, user, src, burst_time)
- user.changeNext_move(CLICK_CD_MELEE)
+ user.DelayNextAction(CLICK_CD_MELEE)
/obj/item/resonator/pre_attack(atom/target, mob/user, params)
if(check_allowed_items(target, 1))
diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm
index 2ca5f88ac8..c69e990033 100644
--- a/code/modules/mining/equipment/survival_pod.dm
+++ b/code/modules/mining/equipment/survival_pod.dm
@@ -167,10 +167,7 @@
qdel(src)
return TRUE
-/obj/item/gps/computer/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/item/gps/computer/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
attack_self(user)
//Bed
diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm
index c0d63fab9c..4d0b7dff21 100644
--- a/code/modules/mining/laborcamp/laborstacker.dm
+++ b/code/modules/mining/laborcamp/laborstacker.dm
@@ -141,10 +141,7 @@ GLOBAL_LIST(labor_sheet_values)
icon_state = "console"
density = FALSE
-/obj/machinery/mineral/labor_points_checker/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/mineral/labor_points_checker/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
user.examinate(src)
/obj/machinery/mineral/labor_points_checker/attackby(obj/item/I, mob/user, params)
diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm
index e39b833793..9710773309 100644
--- a/code/modules/mining/lavaland/ash_flora.dm
+++ b/code/modules/mining/lavaland/ash_flora.dm
@@ -62,10 +62,7 @@
else
return ..()
-/obj/structure/flora/ash/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/structure/flora/ash/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!harvested && !needs_sharp_harvest)
user.visible_message("[user] starts to harvest from [src].","You begin to harvest from [src].")
if(do_after(user, harvest_time, target = src))
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index bfdb731869..e03de83e02 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -659,7 +659,7 @@
hitsound = 'sound/weapons/bladeslice.ogg'
hitsound_on = 'sound/weapons/bladeslice.ogg'
w_class = WEIGHT_CLASS_BULKY
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
faction_bonus_force = 30
nemesis_factions = list("mining", "boss")
var/transform_cooldown
@@ -667,6 +667,8 @@
var/bleed_stacks_per_hit = 3
total_mass = 2.75
total_mass_on = 5
+ attack_speed = 0
+ attack_unwieldlyness = CLICK_CD_MELEE * 0.5
/obj/item/melee/transforming/cleaving_saw/examine(mob/user)
. = ..()
@@ -685,8 +687,12 @@
return FALSE
. = ..()
if(.)
+ if(active)
+ attack_unwieldlyness = CLICK_CD_MELEE
+ else
+ attack_unwieldlyness = CLICK_CD_MELEE * 0.5
transform_cooldown = world.time + (CLICK_CD_MELEE * 0.5)
- user.changeNext_move(CLICK_CD_MELEE * 0.25)
+ user.SetNextAction(CLICK_CD_MELEE * 0.25, considered_action = FALSE, flush = TRUE)
/obj/item/melee/transforming/cleaving_saw/transform_messages(mob/living/user, supress_message_text)
if(!supress_message_text)
@@ -701,11 +707,6 @@
to_chat(user, "You accidentally cut yourself with [src], like a doofus!")
user.take_bodypart_damage(10)
-/obj/item/melee/transforming/cleaving_saw/melee_attack_chain(mob/user, atom/target, params)
- ..()
- if(!active)
- user.changeNext_move(CLICK_CD_MELEE * 0.5) //when closed, it attacks very rapidly
-
/obj/item/melee/transforming/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target)
var/datum/status_effect/stacking/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED)
if(!B)
@@ -765,7 +766,7 @@
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
flags_1 = CONDUCT_1
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
w_class = WEIGHT_CLASS_BULKY
force = 1
throwforce = 1
@@ -929,6 +930,9 @@
/obj/item/lava_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
+ INVOKE_ASYNC(src, .proc/attempt_lava, target, user, proximity_flag, click_parameters)
+
+/obj/item/lava_staff/proc/attempt_lava(atom/target, mob/user, proximity_flag, click_parameters)
if(timer > world.time)
return
diff --git a/code/modules/mining/lavaland/ruins/gym.dm b/code/modules/mining/lavaland/ruins/gym.dm
index d454c3d118..c26631be74 100644
--- a/code/modules/mining/lavaland/ruins/gym.dm
+++ b/code/modules/mining/lavaland/ruins/gym.dm
@@ -8,7 +8,7 @@
var/list/hit_sounds = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg',\
'sound/weapons/punch1.ogg', 'sound/weapons/punch2.ogg', 'sound/weapons/punch3.ogg', 'sound/weapons/punch4.ogg')
-/obj/structure/punching_bag/attack_hand(mob/user as mob)
+/obj/structure/punching_bag/on_attack_hand(mob/user as mob)
. = ..()
if(.)
return
@@ -29,7 +29,7 @@
/obj/structure/weightmachine/proc/AnimateMachine(mob/living/user)
return
-/obj/structure/weightmachine/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/weightmachine/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index b00e291685..564d554319 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -32,7 +32,7 @@
new /datum/data/mining_equipment("500 Point Transfer Card", /obj/item/card/mining_point_card/mp500, 500),
new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600),
new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750),
- new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/kinetic_crusher, 750),
+ new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/kinetic_crusher, 750),
new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750),
new /datum/data/mining_equipment("Survival Medipen", /obj/item/reagent_containers/hypospray/medipen/survival, 750),
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 800),
@@ -68,6 +68,7 @@
new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 150),
new /datum/data/mining_equipment("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 250),
new /datum/data/mining_equipment("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 300),
+ new /datum/data/mining_equipment("Kinetic Glaive", /obj/item/kinetic_crusher/glaive, 1500),
new /datum/data/mining_equipment("KA Range Increase", /obj/item/borg/upgrade/modkit/range, 1000),
new /datum/data/mining_equipment("KA Damage Increase", /obj/item/borg/upgrade/modkit/damage, 1000),
new /datum/data/mining_equipment("KA Cooldown Decrease", /obj/item/borg/upgrade/modkit/cooldown, 1000),
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index 6567793b80..143aba3fe4 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -79,8 +79,7 @@
no_destination_swap = 1
var/static/list/dumb_rev_heads = list()
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/machinery/computer/shuttle/mining/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/computer/shuttle/mining/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(is_station_level(user.z) && user.mind && is_head_revolutionary(user) && !(user.mind in dumb_rev_heads))
to_chat(user, "You get a feeling that leaving the station might be a REALLY dumb idea...")
dumb_rev_heads += user.mind
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index fb37dcbca0..627d79d6ba 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -118,7 +118,7 @@
deathmessage = "blows apart!"
..()
-/mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M)
+/mob/living/simple_animal/hostile/mining_drone/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.)
return
diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm
index f9d18fecc2..ae42ca4745 100644
--- a/code/modules/mining/satchel_ore_boxdm.dm
+++ b/code/modules/mining/satchel_ore_boxdm.dm
@@ -38,10 +38,7 @@
ui_interact(user)
. = ..()
-/obj/structure/ore_box/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/structure/ore_box/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(Adjacent(user))
ui_interact(user)
diff --git a/code/modules/mob/clickdelay.dm b/code/modules/mob/clickdelay.dm
new file mode 100644
index 0000000000..b1df87303e
--- /dev/null
+++ b/code/modules/mob/clickdelay.dm
@@ -0,0 +1,200 @@
+/**
+ * CLICKDELAY HANDLING SYSTEM
+ * How this works is mobs can never do actions until their next_action is at or below world.time, but things can specify extra cooldown
+ * to check for either from the time of last_action or from the end of next_action.
+ *
+ * Clickdelay should always be checked via [CheckActionCooldown()], never manually!
+ */
+
+/mob
+ // CLICKDELAY AND RELATED
+ // Generic clickdelay - Hybrid time-since-last-attack and time-to-next-attack system.
+ // next_action is a hard cooldown, as Click()s will not pass unless it is passed.
+ // last_action is not a hard cooldown and different items can check for different delays.
+ /// Generic clickdelay variable. Marks down the last world.time we did something that should cause or impact generic clickdelay. This should be directly set or set using [DelayNextAction()]. This should only be checked using [CheckActionCooldown()].
+ var/last_action = 0
+ /**
+ * The difference between the above and this is this is set immediately before even the pre-attack begins to ensure clickdelay is respected.
+ * Then, it is flushed or discarded using [FlushLastAttack()] or [DiscardLastAttack()] respectively.
+ */
+
+ var/last_action_immediate = 0
+ /// Generic clickdelay variable. Next world.time we should be able to do something that respects generic clickdelay. This should be set using [DelayNextAction()] This should only be checked using [CheckActionCooldown()].
+ var/next_action = 0
+ /// Ditto
+ var/next_action_immediate = 0
+ /// Default clickdelay for an UnarmedAttack() that successfully passes. Respects action_cooldown_mod.
+ var/unarmed_attack_speed = CLICK_CD_MELEE
+ /// Simple modification variable multiplied to next action modifier on adjust and on checking time since last action using [CheckActionCooldown()].
+ /// This should only be manually modified using multipliers.
+ var/action_cooldown_mod = 1
+ /// Simple modification variable added to amount on adjust and on checking time since last action using [CheckActionCooldown()].
+ /// This should only be manually modified via addition.
+ var/action_cooldown_adjust = 0
+
+ // Resisting - While resisting will give generic clickdelay, it is also on its own resist delay system. However, resisting does not check generic movedelay.
+ // Resist cooldown should only be set at the start of a resist chain - whether this is clicking an alert button, pressing or hotkeying the resist button, or moving to resist out of a locker.
+ /*
+ * Special clickdelay variable for resisting. Last time we did a special action like resisting. This should only be set using [MarkResistTime()].
+ * Use [CheckResistCooldown()] to check cooldowns, this should only be used for the resist action bar visual.
+ */
+ var/last_resist = 0
+ /// How long we should wait before allowing another resist. This should only be manually modified using multipliers.
+ var/resist_cooldown = CLICK_CD_RESIST
+ /// Minimum world time for another resist. This should only be checked using [CheckResistCooldown()].
+ var/next_resist = 0
+
+/**
+ * Applies a delay to next_action before we can do our next action.
+ *
+ * @params
+ * * amount - Amount to delay by
+ * * ignore_mod - ignores next action adjust and mult
+ * * considered_action - Defaults to TRUE - If TRUE, sets last_action to world.time.
+ * * immediate - defaults to TRUE - if TRUE, writes to cached/last_attack_immediate instead of last_attack. This ensures it can't collide with any delay checks in the actual attack.
+ * * flush - defaults to FALSE - Use this while using this proc outside of clickcode to ensure everything is set properly. This should never be set to TRUE if this is called from clickcode.
+ */
+/mob/proc/DelayNextAction(amount = 0, ignore_mod = FALSE, considered_action = TRUE, immediate = TRUE, flush = FALSE)
+ if(immediate)
+ if(considered_action)
+ last_action_immediate = world.time
+ next_action_immediate = max(next_action, world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust())))
+ else
+ if(considered_action)
+ last_action = world.time
+ next_action = max(next_action, world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust())))
+ if(flush)
+ FlushCurrentAction()
+ else
+ hud_used?.clickdelay?.mark_dirty()
+
+/**
+ * Get estimated time of next attack.
+ */
+/mob/proc/EstimatedNextActionTime()
+ var/attack_speed = unarmed_attack_speed * GetActionCooldownMod() + GetActionCooldownAdjust()
+ var/obj/item/I = get_active_held_item()
+ if(I)
+ attack_speed = I.GetEstimatedAttackSpeed()
+ if(!I.clickdelay_mod_bypass)
+ attack_speed = attack_speed * GetActionCooldownMod() + GetActionCooldownAdjust()
+ return max(next_action, next_action_immediate, max(last_action, last_action_immediate) + attack_speed)
+
+/**
+ * Sets our next action to. The difference is DelayNextAction cannot reduce next_action under any circumstances while this can.
+ */
+/mob/proc/SetNextAction(amount = 0, ignore_mod = FALSE, considered_action = TRUE, immediate = TRUE, flush = FALSE)
+ if(immediate)
+ if(considered_action)
+ last_action_immediate = world.time
+ next_action_immediate = world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust()))
+ else
+ if(considered_action)
+ last_action = world.time
+ next_action = world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust()))
+ if(flush)
+ FlushCurrentAction()
+ else
+ hud_used?.clickdelay?.mark_dirty()
+
+/**
+ * Checks if we can do another action.
+ * Returns TRUE if we can and FALSE if we cannot.
+ *
+ * @params
+ * * cooldown - Time required since last action. Defaults to 0.5
+ * * from_next_action - Defaults to FALSE. Should we check from the tail end of next_action instead of last_action?
+ * * ignore_mod - Defaults to FALSE. Ignore all adjusts and multipliers. Do not use this unless you know what you are doing and have a good reason.
+ * * ignore_next_action - Defaults to FALSE. Ignore next_action and only care about cooldown param and everything else. Generally unused.
+ * * immediate - Defaults to FALSE. Checks last action using immediate, used on the head end of an attack. This is to prevent colliding attacks in case of sleep. Not that you should sleep() in an attack but.. y'know.
+ */
+/mob/proc/CheckActionCooldown(cooldown = 0.5, from_next_action = FALSE, ignore_mod = FALSE, ignore_next_action = FALSE, immediate = FALSE)
+ return (ignore_next_action || (world.time >= (immediate? next_action_immediate : next_action))) && \
+ (world.time >= ((from_next_action? (immediate? next_action_immediate : next_action) : (immediate? last_action_immediate : last_action)) + max(0, ignore_mod? cooldown : (cooldown * GetActionCooldownMod() + GetActionCooldownAdjust()))))
+
+/**
+ * Gets action_cooldown_mod.
+ */
+/mob/proc/GetActionCooldownMod()
+ return action_cooldown_mod
+
+/**
+ * Gets action_cooldown_adjust
+ */
+/mob/proc/GetActionCooldownAdjust()
+ return action_cooldown_adjust
+
+/**
+ * Flushes last_action and next_action
+ */
+/mob/proc/FlushCurrentAction()
+ last_action = last_action_immediate
+ next_action = next_action_immediate
+ hud_used?.clickdelay?.mark_dirty()
+
+/**
+ * Discards last_action and next_action
+ */
+/mob/proc/DiscardCurrentAction()
+ last_action_immediate = last_action
+ next_action_immediate = next_action
+ hud_used?.clickdelay?.mark_dirty()
+
+/**
+ * Checks if we can resist again.
+ */
+/mob/proc/CheckResistCooldown()
+ return (world.time >= next_resist)
+
+/**
+ * Mark the last resist as now.
+ *
+ * @params
+ * * extra_cooldown - Extra cooldown to apply to next_resist. Defaults to this mob's resist_cooldown.
+ * * override - Defaults to FALSE - if TRUE, extra_cooldown will replace the old next_resist even if the old is longer.
+ */
+/mob/proc/MarkResistTime(extra_cooldown = resist_cooldown, override = FALSE)
+ last_resist = world.time
+ next_resist = override? (world.time + extra_cooldown) : max(next_resist, world.time + extra_cooldown)
+ hud_used?.resistdelay?.mark_dirty()
+
+/atom
+ // Standard clickdelay variables
+ // These 3 are all handled at base of atom/attack_hand so uh.. yeah. Make sure that's called.
+ /// Amount of time to check for from a mob's last attack to allow an attack_hand().
+ var/attack_hand_speed = CLICK_CD_MELEE
+ /// Amount of time to hard stagger (no clicking at all) the mob post attack_hand(). Lower = better
+ var/attack_hand_unwieldlyness = 0
+ /// Should we set last action for attack hand? This implies that attack_hands to this atom should flush to clickdelay buffers instead of discarding.
+ var/attack_hand_is_action = FALSE
+
+/obj/item
+ // Standard clickdelay variables
+ /// Amount of time to check for from a mob's last attack, checked before an attack happens. Lower = faster attacks
+ var/attack_speed = CLICK_CD_MELEE
+ /// Amount of time to hard-stagger (no clicking at all) the mob when attacking. Lower = better
+ var/attack_unwieldlyness = 0
+ /// This item bypasses any click delay mods
+ var/clickdelay_mod_bypass = FALSE
+ /// This item checks clickdelay from a user's delayed next action variable rather than the last time they attacked.
+ var/clickdelay_from_next_action = FALSE
+ /// This item ignores next action delays.
+ var/clickdelay_ignores_next_action = FALSE
+
+/**
+ * Checks if a user's clickdelay is met for a standard attack, this is called before an attack happens.
+ */
+/obj/item/proc/CheckAttackCooldown(mob/user, atom/target)
+ return user.CheckActionCooldown(attack_speed, clickdelay_from_next_action, clickdelay_mod_bypass, clickdelay_ignores_next_action)
+
+/**
+ * Called after a successful attack to set a mob's clickdelay.
+ */
+/obj/item/proc/ApplyAttackCooldown(mob/user, atom/target, attackchain_flags)
+ user.DelayNextAction(attack_unwieldlyness, clickdelay_mod_bypass, !(attackchain_flags & ATTACK_IGNORE_ACTION))
+
+/**
+ * Get estimated time that a user has to not attack for to use us
+ */
+/obj/item/proc/GetEstimatedAttackSpeed()
+ return attack_speed
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 49a3bffd42..768c4c943e 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -557,7 +557,6 @@
if(frn)
client.prefs.random_character()
client.prefs.real_name = client.prefs.pref_species.random_name(gender,1)
- client.prefs.copy_to(H)
var/cur_scar_index = client.prefs.scars_index
if(client.prefs.persistent_scars && client.prefs.scars_list["[cur_scar_index]"])
var/scar_string = client.prefs.scars_list["[cur_scar_index]"]
@@ -568,7 +567,6 @@
client.prefs.scars_list["[cur_scar_index]"] = valid_scars
client.prefs.save_character()
-
client.prefs.copy_to(H)
H.dna.update_dna_identity()
if(mind)
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 83cc09a624..caebb9cf10 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -5,13 +5,11 @@
/mob/proc/get_active_held_item()
return get_item_for_held_index(active_hand_index)
-
//Finds the opposite limb for the active one (eg: upper left arm will find the item in upper right arm)
//So we're treating each "pair" of limbs as a team, so "both" refers to them
/mob/proc/get_inactive_held_item()
return get_item_for_held_index(get_inactive_hand_index())
-
//Finds the opposite index for the active one (eg: upper left arm will find the item in upper right arm)
//So we're treating each "pair" of limbs as a team, so "both" refers to them
/mob/proc/get_inactive_hand_index()
@@ -24,12 +22,9 @@
other_hand = 0
return other_hand
-
/mob/proc/get_item_for_held_index(i)
if(i > 0 && i <= held_items.len)
return held_items[i]
- return FALSE
-
//Odd = left. Even = right
/mob/proc/held_index_to_dir(i)
@@ -37,17 +32,14 @@
return "r"
return "l"
-
//Check we have an organ for this hand slot (Dismemberment), Only relevant for humans
/mob/proc/has_hand_for_held_index(i)
return TRUE
-
//Check we have an organ for our active hand slot (Dismemberment),Only relevant for humans
/mob/proc/has_active_hand()
return has_hand_for_held_index(active_hand_index)
-
//Finds the first available (null) index OR all available (null) indexes in held_items based on a side.
//Lefts: 1, 3, 5, 7...
//Rights:2, 4, 6, 8...
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
index 478599e2c0..cf1a158fc5 100644
--- a/code/modules/mob/living/blood.dm
+++ b/code/modules/mob/living/blood.dm
@@ -14,7 +14,8 @@
var/obj/item/bodypart/BP = X
temp_bleed += BP.get_bleed_rate()
BP.generic_bleedstacks = max(0, BP.generic_bleedstacks - 1)
- bleed(temp_bleed)
+ if(temp_bleed)
+ bleed(temp_bleed)
//Blood regeneration if there is some space
if(blood_volume < BLOOD_VOLUME_NORMAL)
@@ -28,20 +29,15 @@
to_chat(src, "The blood soaks through your bandage.")
-/mob/living/carbon/monkey/handle_blood()
- if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE))) //cryosleep or husked people do not pump the blood.
- //Blood regeneration if there is some space
- if(blood_volume < (BLOOD_VOLUME_NORMAL * blood_ratio))
- blood_volume += 0.1 // regenerate blood VERY slowly
- if(blood_volume < (BLOOD_VOLUME_OKAY * blood_ratio))
- adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.02, 1))
-
// Takes care blood loss and regeneration
/mob/living/carbon/human/handle_blood()
if(NOBLOOD in dna.species.species_traits || bleedsuppress || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
return
+ if(HAS_TRAIT(src, TRAIT_NOMARROW)) //Bloodsuckers don't need to be here.
+ return
+
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood.
//Blood regeneration if there is some space
@@ -66,10 +62,6 @@
//Effects of bloodloss
var/word = pick("dizzy","woozy","faint")
switch(blood_volume)
- if(BLOOD_VOLUME_EXCESS to BLOOD_VOLUME_MAX_LETHAL)
- if(prob(15))
- to_chat(src, "Blood starts to tear your skin apart. You're going to burst!")
- gib()
if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS)
if(prob(10))
to_chat(src, "You feel terribly bloated.")
diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm
index d3dbfac8c8..24d456bf8f 100644
--- a/code/modules/mob/living/bloodcrawl.dm
+++ b/code/modules/mob/living/bloodcrawl.dm
@@ -73,7 +73,7 @@
if(victim.stat == CONSCIOUS)
src.visible_message("[victim] kicks free of the blood pool just before entering it!", null, "You hear splashing and struggling.")
- else if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/demonsblood))
+ else if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/demonsblood))
visible_message("Something prevents [victim] from entering the pool!", "A strange force is blocking [victim] from entering!", "You hear a splash and a thud.")
else
victim.forceMove(src)
@@ -104,7 +104,7 @@
if(!victim)
return FALSE
- if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/devilskiss))
+ if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/devilskiss))
to_chat(src, "AAH! THEIR FLESH! IT BURNS!")
adjustBruteLoss(25) //I can't use adjustHealth() here because bloodcrawl affects /mob/living and adjustHealth() only affects simple mobs
var/found_bloodpool = FALSE
diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm
index d1258ce6e4..891243496a 100644
--- a/code/modules/mob/living/brain/MMI.dm
+++ b/code/modules/mob/living/brain/MMI.dm
@@ -39,7 +39,9 @@
laws.set_laws_config()
/obj/item/mmi/attackby(obj/item/O, mob/user, params)
- user.changeNext_move(CLICK_CD_MELEE)
+ if(!user.CheckActionCooldown(CLICK_CD_MELEE))
+ return
+ user.DelayNextAction()
if(istype(O, /obj/item/organ/brain)) //Time to stick a brain in it --NEO
var/obj/item/organ/brain/newbrain = O
if(brain)
diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm
index b6f8dd349b..a853416e6f 100644
--- a/code/modules/mob/living/brain/brain_item.dm
+++ b/code/modules/mob/living/brain/brain_item.dm
@@ -102,7 +102,7 @@
to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a brain.")
/obj/item/organ/brain/attackby(obj/item/O, mob/user, params)
- user.changeNext_move(CLICK_CD_MELEE)
+ user.DelayNextAction(CLICK_CD_MELEE)
if(brainmob)
O.attack(brainmob, user) //Oh noooeeeee
diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm
index 5b92bf3dea..5081fd8a14 100644
--- a/code/modules/mob/living/carbon/alien/alien_defense.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defense.dm
@@ -45,7 +45,7 @@ In all, this is a lot like the monkey code. /N
return attack_alien(L)
-/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M)
+/mob/living/carbon/alien/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //To allow surgery to return properly.
return
@@ -74,7 +74,6 @@ In all, this is a lot like the monkey code. /N
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(rand(1, 3), BRUTE, affecting)
-
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
. = ..()
if(.)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index 727a22f844..d0addbab21 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -57,8 +57,17 @@
/mob/living/carbon/alien/humanoid/Topic(href, href_list)
..()
- //strip panel
+ //strip panel & embeds
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
+ if(href_list["embedded_object"])
+ var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
+ if(!L)
+ return
+ var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
+ if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the alien anymore
+ return
+ SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
+ return
if(href_list["pouches"])
visible_message("[usr] tries to empty [src]'s pouches.", \
"[usr] tries to empty [src]'s pouches.")
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm
index 5ebf6210d0..8177360d4a 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm
@@ -21,7 +21,7 @@
"[user] has [hitverb] [src]!", null, COMBAT_MESSAGE_RANGE)
return 1
-/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
+/mob/living/carbon/alien/humanoid/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //To allow surgery to return properly.
return
diff --git a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm
index 7dabcf5abf..5832996a2c 100644
--- a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm
+++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm
@@ -1,6 +1,6 @@
-/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
+/mob/living/carbon/alien/larva/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(. || M.a_intent == INTENT_HELP || M.a_intent == INTENT_GRAB)
return
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index c5a69553aa..ad8828572c 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -58,8 +58,7 @@
/obj/item/clothing/mask/facehugger/attack_alien(mob/user) //can be picked up by aliens
return attack_hand(user)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/clothing/mask/facehugger/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/clothing/mask/facehugger/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if((stat == CONSCIOUS && !sterile) && !isalien(user))
if(Leap(user))
return
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 4b7e27656b..edb681e60f 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -92,17 +92,8 @@
if(!all_wounds || !(user.a_intent == INTENT_HELP || user == src))
return ..()
- // The following priority/nonpriority searching is so that if we have two wounds on a limb that use the same item for treatment (gauze can bandage cuts AND splint broken bones),
- // we prefer whichever wound is not already treated (ignore the splinted broken bone for the open cut). If there's no priority wounds that this can treat, go through the
- // non-priority ones randomly.
- var/list/nonpriority_wounds = list()
- for(var/datum/wound/W in shuffle(all_wounds))
- if(!W.treat_priority)
- nonpriority_wounds += W
- else if(W.treat_priority && W.try_treating(I, user))
- return 1
-
- for(var/datum/wound/W in shuffle(nonpriority_wounds))
+ for(var/i in shuffle(all_wounds))
+ var/datum/wound/W = i
if(W.try_treating(I, user))
return 1
@@ -320,14 +311,11 @@
return
if(restrained())
// too soon.
- if(last_special > world.time)
- return
var/buckle_cd = 600
if(handcuffed)
var/obj/item/restraints/O = src.get_item_by_slot(SLOT_HANDCUFFED)
buckle_cd = O.breakouttime
- changeNext_move(min(CLICK_CD_BREAKOUT, buckle_cd))
- last_special = world.time + min(CLICK_CD_BREAKOUT, buckle_cd)
+ MarkResistTime()
visible_message("[src] attempts to unbuckle [p_them()]self!", \
"You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)")
if(do_after(src, buckle_cd, 0, target = src, required_mobility_flags = MOBILITY_RESIST))
@@ -341,39 +329,26 @@
buckled.user_unbuckle_mob(src,src)
/mob/living/carbon/resist_fire()
- if(last_special > world.time)
- return
fire_stacks -= 5
DefaultCombatKnockdown(60, TRUE, TRUE)
spin(32,2)
visible_message("[src] rolls on the floor, trying to put [p_them()]self out!", \
"You stop, drop, and roll!")
- last_special = world.time + 30
+ MarkResistTime(30)
sleep(30)
if(fire_stacks <= 0)
visible_message("[src] has successfully extinguished [p_them()]self!", \
"You extinguish yourself.")
ExtinguishMob()
-/mob/living/carbon/resist_restraints(ignore_delay = FALSE)
+/mob/living/carbon/resist_restraints()
var/obj/item/I = null
- var/type = 0
- if(!ignore_delay && (last_special > world.time))
- to_chat(src, "You don't have the energy to resist your restraints that fast!")
- return
if(handcuffed)
I = handcuffed
- type = 1
else if(legcuffed)
I = legcuffed
- type = 2
if(I)
- if(type == 1)
- changeNext_move(min(CLICK_CD_BREAKOUT, I.breakouttime))
- last_special = world.time + CLICK_CD_BREAKOUT
- if(type == 2)
- changeNext_move(min(CLICK_CD_RANGE, I.breakouttime))
- last_special = world.time + CLICK_CD_RANGE
+ MarkResistTime()
cuff_resist(I)
/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0)
@@ -418,7 +393,7 @@
if (W)
W.layer = initial(W.layer)
W.plane = initial(W.plane)
- changeNext_move(0)
+ SetNextAction(0)
if (legcuffed)
var/obj/item/W = legcuffed
legcuffed = null
@@ -431,7 +406,7 @@
if (W)
W.layer = initial(W.layer)
W.plane = initial(W.plane)
- changeNext_move(0)
+ SetNextAction(0)
update_equipment_speed_mods() // In case cuffs ever change speed
/mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break)
@@ -1225,16 +1200,16 @@
/**
* generate_fake_scars()- for when you want to scar someone, but you don't want to hurt them first. These scars don't count for temporal scarring (hence, fake)
*
- * If you want a specific wound scar, pass that wound type as the second arg, otherwise you can pass a list like WOUND_LIST_CUT to generate a random cut scar.
+ * If you want a specific wound scar, pass that wound type as the second arg, otherwise you can pass a list like WOUND_LIST_SLASH to generate a random cut scar.
*
* Arguments:
* * num_scars- A number for how many scars you want to add
- * * forced_type- Which wound or category of wounds you want to choose from, WOUND_LIST_BONE, WOUND_LIST_CUT, or WOUND_LIST_BURN (or some combination). If passed a list, picks randomly from the listed wounds. Defaults to all 3 types
+ * * forced_type- Which wound or category of wounds you want to choose from, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN (or some combination). If passed a list, picks randomly from the listed wounds. Defaults to all 3 types
*/
/mob/living/carbon/proc/generate_fake_scars(num_scars, forced_type)
for(var/i in 1 to num_scars)
- var/datum/scar/S = new
- var/obj/item/bodypart/BP = pick(bodyparts)
+ var/datum/scar/scaries = new
+ var/obj/item/bodypart/scar_part = pick(bodyparts)
var/wound_type
if(forced_type)
@@ -1243,9 +1218,17 @@
else
wound_type = forced_type
else
- wound_type = pick(WOUND_LIST_BONE + WOUND_LIST_CUT + WOUND_LIST_BURN)
+ wound_type = pick(GLOB.global_all_wound_types)
- var/datum/wound/W = new wound_type
- S.generate(BP, W)
- S.fake = TRUE
- QDEL_NULL(W)
+ var/datum/wound/phantom_wound = new wound_type
+ scaries.generate(scar_part, phantom_wound)
+ scaries.fake = TRUE
+ QDEL_NULL(phantom_wound)
+
+/**
+ * get_biological_state is a helper used to see what kind of wounds we roll for. By default we just assume carbons (read:monkeys) are flesh and bone, but humans rely on their species datums
+ *
+ * go look at the species def for more info [/datum/species/proc/get_biological_state]
+ */
+/mob/living/carbon/proc/get_biological_state()
+ return BIO_FLESH_BONE
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 196cec849d..566c004142 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -69,14 +69,14 @@
var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
var/list/block_return = list()
- if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, block_return) & BLOCK_SUCCESS))
+ if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, block_return) & BLOCK_SUCCESS))
return FALSE
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
var/obj/item/bodypart/affecting = get_bodypart(impacting_zone)
if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest)
affecting = bodyparts[1]
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
- send_item_attack_message(I, user, affecting.name, totitemdamage)
+ send_item_attack_message(I, user, affecting.name, affecting, totitemdamage)
I.do_stagger_action(src, user, totitemdamage)
if(I.force)
apply_damage(totitemdamage, I.damtype, affecting, wound_bonus = I.wound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness()) //CIT CHANGE - replaces I.force with totitemdamage
@@ -100,19 +100,12 @@
head.add_mob_blood(src)
update_inv_head()
- //dismemberment
- var/probability = I.get_dismemberment_chance(affecting)
- if(prob(probability))
- if(affecting.dismember(I.damtype))
- I.add_mob_blood(src)
- playsound(get_turf(src), I.get_dismember_sound(), 80, 1)
return TRUE //successful attack
/mob/living/carbon/attack_drone(mob/living/simple_animal/drone/user)
return //so we don't call the carbon's attack_hand().
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/mob/living/carbon/attack_hand(mob/living/carbon/human/user, act_intent, unarmed_attack_flags)
+/mob/living/carbon/on_attack_hand(mob/living/carbon/human/user, act_intent, unarmed_attack_flags)
. = ..()
if(.) //was the attack blocked?
return
@@ -132,9 +125,10 @@
if(S.next_step(user, act_intent))
return TRUE
- for(var/datum/wound/W in all_wounds)
+ for(var/i in all_wounds)
+ var/datum/wound/W = i
if(W.try_handling(user))
- return 1
+ return TRUE
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
@@ -151,15 +145,14 @@
if(M.a_intent == INTENT_HELP)
help_shake_act(M)
- return 0
+ return TRUE
. = ..()
if(.) //successful monkey bite.
for(var/thing in M.diseases)
var/datum/disease/D = thing
ForceContractDisease(D)
- return 1
-
+ return TRUE
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
. = ..()
@@ -298,12 +291,12 @@
target_message = "[M] gives you a pat on the head to make you feel better!")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat)
friendly_check = TRUE
- if(S?.can_wag_tail(src) && !dna.species.is_wagging_tail())
- var/static/list/many_tails = list("tail_human", "tail_lizard", "mam_tail")
- for(var/T in many_tails)
- if(S.mutant_bodyparts[T] && dna.features[T] != "None")
- emote("wag")
- break
+ if(!(client?.prefs.cit_toggles & NO_AUTO_WAG))
+ if(S?.can_wag_tail(src) && !dna.species.is_wagging_tail())
+ var/static/list/many_tails = list("tail_human", "tail_lizard", "mam_tail")
+ for(var/T in many_tails)
+ if(S.mutant_bodyparts[T] && dna.features[T] != "None")
+ emote("wag")
else if(check_zone(M.zone_selected) == BODY_ZONE_R_ARM || check_zone(M.zone_selected) == BODY_ZONE_L_ARM)
M.visible_message( \
@@ -400,7 +393,7 @@
to_chat(src, "Your eyes are really starting to hurt. This can't be good for you!")
if(has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
- return 1
+ return TRUE
else if(damage == 0) // just enough protection
if(prob(20))
to_chat(src, "Something bright flashes in the corner of your vision!")
@@ -475,3 +468,35 @@
var/obj/item/bodypart/limb = get_bodypart(zone)
if(!limb)
return
+
+/mob/living/carbon/send_item_attack_message(obj/item/I, mob/living/user, hit_area, obj/item/bodypart/hit_bodypart, totitemdamage)
+ var/message_verb = "attacked"
+ if(length(I.attack_verb))
+ message_verb = "[pick(I.attack_verb)]"
+ else if(!I.force)
+ return
+
+ var/extra_wound_details = ""
+ if(I.damtype == BRUTE && hit_bodypart.can_dismember())
+ var/mangled_state = hit_bodypart.get_mangled_state()
+ var/bio_state = get_biological_state()
+ if(mangled_state == BODYPART_MANGLED_BOTH)
+ extra_wound_details = ", threatening to sever it entirely"
+ else if((mangled_state == BODYPART_MANGLED_FLESH && I.get_sharpness()) || (mangled_state & BODYPART_MANGLED_BONE && bio_state == BIO_JUST_BONE))
+ extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] through to the bone"
+ else if((mangled_state == BODYPART_MANGLED_BONE && I.get_sharpness()) || (mangled_state & BODYPART_MANGLED_FLESH && bio_state == BIO_JUST_FLESH))
+ extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] at the remaining tissue"
+
+ var/message_hit_area = ""
+ if(hit_area)
+ message_hit_area = " in the [hit_area]"
+ var/attack_message = "[src] is [message_verb][message_hit_area] with [I][extra_wound_details]!"
+ var/attack_message_local = "You're [message_verb][message_hit_area] with [I][extra_wound_details]!"
+ if(user in viewers(src, null))
+ attack_message = "[user] [message_verb] [src][message_hit_area] with [I][extra_wound_details]!"
+ attack_message_local = "[user] [message_verb] you[message_hit_area] with [I][extra_wound_details]!"
+ if(user == src)
+ attack_message_local = "You [message_verb] yourself[message_hit_area] with [I][extra_wound_details]"
+ visible_message("[attack_message]",\
+ "[attack_message_local]", null, COMBAT_MESSAGE_RANGE)
+ return TRUE
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index a05480ee01..2ce59fb790 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -24,7 +24,7 @@
var/obj/item/head = null
var/obj/item/gloves = null //only used by humans
- var/obj/item/shoes = null //only used by humans.
+ var/obj/item/clothing/shoes/shoes = null //only used by humans.
var/obj/item/clothing/glasses/glasses = null //only used by humans.
var/obj/item/ears = null //only used by humans.
diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm
index ddf1019f2a..5c5a1d6d52 100644
--- a/code/modules/mob/living/carbon/damage_procs.dm
+++ b/code/modules/mob/living/carbon/damage_procs.dm
@@ -1,6 +1,6 @@
-/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
var/hit_percent = (100-blocked)/100
if(!forced && hit_percent <= 0)
@@ -202,7 +202,7 @@
//Damages ONE bodypart randomly selected from damagable ones.
//It automatically updates damage overlays if necessary
//It automatically updates health status
-/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
if(!parts.len)
return
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index be046a3713..5eabae16f7 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -44,7 +44,8 @@
msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!\n"
else
msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n"
- for(var/datum/wound/W in BP.wounds)
+ for(var/i in BP.wounds)
+ var/datum/wound/W = i
msg += "[W.get_examine_description(user)]\n"
for(var/X in disabled)
@@ -109,7 +110,7 @@
switch(scar_severity)
if(1 to 2)
- msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n"
+ msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n"
if(3 to 4)
msg += "[t_He] [t_has] several bad scars, you can look again to take a closer look...\n"
if(5 to 6)
diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm
index 5cd00b7e6a..04ec1196fd 100644
--- a/code/modules/mob/living/carbon/human/damage_procs.dm
+++ b/code/modules/mob/living/carbon/human/damage_procs.dm
@@ -1,5 +1,5 @@
// depending on the species, it will run the corresponding apply_damage code there
-/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness)
diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm
index 24eb5d7234..1e2a375b39 100644
--- a/code/modules/mob/living/carbon/human/dummy.dm
+++ b/code/modules/mob/living/carbon/human/dummy.dm
@@ -4,6 +4,10 @@
status_flags = GODMODE|CANPUSH
mouse_drag_pointer = MOUSE_INACTIVE_POINTER
var/in_use = FALSE
+ vore_flags = NO_VORE
+
+/mob/living/carbon/human/vore
+ vore_flags = DEVOURABLE | DIGESTABLE | FEEDING
INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
@@ -43,6 +47,5 @@ GLOBAL_LIST_EMPTY(dummy_mob_list)
return
var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotnumber]
if(istype(D))
- D.set_species(/datum/species/human,icon_update = TRUE, pref_load = TRUE) //for some fucking reason, if you don't change the species every time, some species will dafault certain things when it's their own species on the mannequin two times in a row, like lizards losing spines and tails setting to smooth. If you can find a fix for this that isn't this, good on you
D.wipe_state()
D.in_use = FALSE
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 77137c7239..65b2931e08 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -163,8 +163,9 @@
msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!\n"
else
msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n"
- for(var/datum/wound/W in BP.wounds)
- msg += "[W.get_examine_description(user)]\n"
+ for(var/i in BP.wounds)
+ var/datum/wound/iter_wound = i
+ msg += "[iter_wound.get_examine_description(user)]\n"
for(var/X in disabled)
var/obj/item/bodypart/BP = X
@@ -249,7 +250,7 @@
msg += "[t_He] look[p_s()] extremely disgusted.\n"
var/apparent_blood_volume = blood_volume
- if(skin_tone == "albino")
+ if(dna.species.use_skintones && skin_tone == "albino")
apparent_blood_volume -= 150 // enough to knock you down one tier
switch(apparent_blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
@@ -270,7 +271,12 @@
bleeding_limbs += BP
var/num_bleeds = LAZYLEN(bleeding_limbs)
- var/bleed_text = "[t_He] [t_is] bleeding from [t_his]"
+ var/list/bleed_text
+ if(appears_dead)
+ bleed_text = list("Blood is visible in [t_his] open")
+ else
+ bleed_text = list("[t_He] [t_is] bleeding from [t_his]")
+
switch(num_bleeds)
if(1 to 2)
bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]"
@@ -280,8 +286,15 @@
bleed_text += " [BP.name],"
bleed_text += " and [bleeding_limbs[num_bleeds].name]"
- bleed_text += "!\n"
- msg += bleed_text
+
+ if(appears_dead)
+ bleed_text += ", but it has pooled and is not flowing.\n"
+ else
+ if(reagents.has_reagent(/datum/reagent/toxin/heparin))
+ bleed_text += " incredibly quickly"
+
+ bleed_text += "!\n"
+ msg += bleed_text.Join()
if(reagents.has_reagent(/datum/reagent/teslium))
msg += "[t_He] [t_is] emitting a gentle blue glow!\n"
@@ -365,7 +378,7 @@
switch(scar_severity)
if(1 to 2)
- msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n"
+ msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n"
if(3 to 4)
msg += "[t_He] [t_has] several bad scars, you can look again to take a closer look...\n"
if(5 to 6)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 2802ac9e3b..b402260611 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -170,7 +170,11 @@
if(SLOT_SHOES in obscured)
dat += "| Shoes: | Obscured |
"
else
- dat += "| Shoes: | [(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "Empty"] |
"
+ dat += "| Shoes: | [(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "Empty"]"
+ if(shoes && shoes.can_be_tied && shoes.tied != SHOES_KNOTTED)
+ dat += " [shoes.tied ? "Untie shoes" : "Knot shoes"]"
+
+ dat += " |
"
if(SLOT_GLOVES in obscured)
dat += "| Gloves: | Obscured |
"
@@ -294,6 +298,12 @@
if (!strip_silence)
to_chat(src, "You feel your [pocket_side] pocket being fumbled with!")
+ if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY, null, FALSE))
+ // separate from first canusetopic
+ var/mob/living/user = usr
+ if(istype(user) && href_list["shoes"] && (user.mobility_flags & MOBILITY_USE)) // we need to be on the ground, so we'll be a bit looser
+ shoes.handle_tying(usr)
+
..() //CITADEL CHANGE - removes a tab from behind this ..() so that flavortext can actually be examined
@@ -390,7 +400,7 @@
// Checks the user has security clearence before allowing them to change arrest status via hud, comment out to enable all access
var/allowed_access = null
var/obj/item/clothing/glasses/G = H.glasses
- if (!(G.obj_flags |= EMAGGED))
+ if (!(G.obj_flags & EMAGGED))
if(H.wear_id)
var/list/access = H.wear_id.GetAccess()
if(ACCESS_SEC_DOORS in access)
@@ -735,8 +745,7 @@
/mob/living/carbon/human/resist_restraints()
if(wear_suit && wear_suit.breakouttime)
- changeNext_move(CLICK_CD_BREAKOUT)
- last_special = world.time + CLICK_CD_BREAKOUT
+ MarkResistTime()
cuff_resist(wear_suit)
else
..()
@@ -1031,12 +1040,6 @@
return TRUE
return FALSE
-/mob/living/carbon/human/proc/clear_shove_slowdown()
- remove_movespeed_modifier(/datum/movespeed_modifier/shove)
- var/active_item = get_active_held_item()
- if(is_type_in_typecache(active_item, GLOB.shove_disarming_types))
- visible_message("[src.name] regains their grip on \the [active_item]!", "You regain your grip on \the [active_item]", null, COMBAT_MESSAGE_RANGE)
-
/mob/living/carbon/human/updatehealth()
. = ..()
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 6737176d09..1673c57a80 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -122,7 +122,7 @@
apply_damage(15, BRUTE, wound_bonus=10)
return 1
-/mob/living/carbon/human/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/mob/living/carbon/human/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.) //To allow surgery to return properly.
return
@@ -131,6 +131,9 @@
dna.species.spec_attack_hand(H, src, null, act_intent, unarmed_attack_flags)
/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M)
+ if(!M.CheckActionCooldown(CLICK_CD_MELEE))
+ return
+ M.DelayNextAction()
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index aea4ee2ead..13456ed61c 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -102,7 +102,7 @@
"HUMAN_PARRY_MININUM_EFFICIENCY" = 0.9
)
-/mob/living/carbon/human/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time)
+/mob/living/carbon/human/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
var/datum/block_parry_data/D = return_block_parry_datum(block_parry_data)
if(!owner.Adjacent(attacker))
return ..()
@@ -110,7 +110,7 @@
return ..()
visible_message("[src] strikes back perfectly at [attacker], staggering them!")
if(D.parry_data["HUMAN_PARRY_PUNCH"])
- UnarmedAttack(attacker, TRUE, INTENT_HARM, UNARMED_ATTACK_PARRY)
+ UnarmedAttack(attacker, TRUE, INTENT_HARM, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_ACTION | ATTACK_IGNORE_CLICKDELAY | NO_AUTO_CLICKDELAY_HANDLING)
var/mob/living/L = attacker
if(istype(L))
L.Stagger(D.parry_data["HUMAN_PARRY_STAGGER"])
diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm
index 8672c0e83d..af95b9e1b7 100644
--- a/code/modules/mob/living/carbon/human/human_helpers.dm
+++ b/code/modules/mob/living/carbon/human/human_helpers.dm
@@ -154,19 +154,29 @@
/// For use formatting all of the scars this human has for saving for persistent scarring
/mob/living/carbon/human/proc/format_scars()
- if(!all_scars)
+ var/list/missing_bodyparts = get_missing_limbs()
+ if(!all_scars && !length(missing_bodyparts))
return
var/scars = ""
+ for(var/i in missing_bodyparts)
+ var/datum/scar/scaries = new
+ scars += "[scaries.format_amputated(i)]"
for(var/i in all_scars)
- var/datum/scar/S = i
- scars += "[S.format()];"
+ var/datum/scar/scaries = i
+ scars += "[scaries.format()];"
return scars
/// Takes a single scar from the persistent scar loader and recreates it from the saved data
/mob/living/carbon/human/proc/load_scar(scar_line)
var/list/scar_data = splittext(scar_line, "|")
- if(LAZYLEN(scar_data) != 4)
+ if(LAZYLEN(scar_data) != SCAR_SAVE_LENGTH)
return // invalid, should delete
- var/obj/item/bodypart/BP = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
- var/datum/scar/S = new
- return S.load(BP, scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]))
+ var/version = text2num(scar_data[SCAR_SAVE_VERS])
+ if(!version || version < SCAR_CURRENT_VERSION) // get rid of old scars
+ return
+ var/obj/item/bodypart/the_part = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
+ var/datum/scar/scaries = new
+ return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]))
+
+/mob/living/carbon/human/get_biological_state()
+ return dna.species.get_biological_state()
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index d703f6a4e2..22cb10026b 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -91,6 +91,7 @@
return " (as [get_id_name("Unknown")])"
/mob/living/carbon/human/proc/forcesay(list/append) //this proc is at the bottom of the file because quote fuckery makes notepad++ cri
+ set waitfor = FALSE // WINGET IS A SLEEP. DO. NOT. SLEEP.
if(stat == CONSCIOUS)
if(client)
var/temp = winget(client, "input", "text")
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index db0fa8d6c6..dc7fe86aca 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -7,7 +7,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this
var/limbs_id //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans.
var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
- var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
+ var/default_color = "#FFFFFF" // if alien colors are disabled, this is the color that will be used by that race
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
var/has_field_of_vision = TRUE
@@ -73,7 +73,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/datum/outfit/outfit_important_for_life // A path to an outfit that is important for species life e.g. plasmaman outfit
// species-only traits. Can be found in DNA.dm
- var/list/species_traits = list(CAN_SCAR) //by default they can scar unless set to something else
+ var/list/species_traits = list(HAS_FLESH,HAS_BONE) //by default they can scar and have bones/flesh unless set to something else
// generic traits tied to having the species
var/list/inherent_traits = list()
var/inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID
@@ -105,6 +105,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/whitelisted = 0 //Is this species restricted to certain players?
var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both.
var/icon_limbs //Overrides the icon used for the limbs of this species. Mainly for downstream, and also because hardcoded icons disgust me. Implemented and maintained as a favor in return for a downstream's implementation of synths.
+ var/species_type
+
+ var/tail_type //type of tail i.e. mam_tail
+ var/wagging_type //type of wagging i.e. waggingtail_lizard
/// Our default override for typing indicator state
var/typing_indicator_state
@@ -113,14 +117,12 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
// PROCS //
///////////
-
/datum/species/New()
if(!limbs_id) //if we havent set a limbs id to use, just use our own id
limbs_id = id
..()
-
/proc/generate_selectable_species(clear = FALSE)
if(clear)
GLOB.roundstart_races = list()
@@ -854,10 +856,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m"
var/list/colorlist = list()
var/husk = HAS_TRAIT(H, TRAIT_HUSK)
- colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor"]]0")
- colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor2"]]0")
- colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]0")
- colorlist += list(0,0,0, hair_alpha)
+ colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor"]]00")
+ colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor2"]]00")
+ colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]00")
+ colorlist += husk ? list(0, 0, 0) : list(0, 0, 0, hair_alpha)
for(var/index in 1 to colorlist.len)
colorlist[index] /= 255
@@ -1031,7 +1033,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.apply_overlay(BODY_FRONT_LAYER)
H.apply_overlay(HORNS_LAYER)
-
/*
* Equip the outfit required for life. Replaces items currently worn.
*/
@@ -1062,7 +1063,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.adjustBruteLoss(1)
/datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H)
- return
+ if(H)
+ stop_wagging_tail(H)
/datum/species/proc/auto_equip(mob/living/carbon/human/H)
// handles the equipping of species-specific gear
@@ -1285,9 +1287,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/check_weakness(obj/item, mob/living/attacker)
return FALSE
-////////
- //LIFE//
- ////////
+/////////////
+////LIFE////
+////////////
/datum/species/proc/handle_digestion(mob/living/carbon/human/H)
if(HAS_TRAIT(src, TRAIT_NOHUNGER))
@@ -1446,7 +1448,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target.grabbedby(user)
return 1
-/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style, unarmed_attack_flags = NONE)
+/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style, attackchain_flags = NONE)
if(!attacker_style && HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "You don't want to harm [target]!")
return FALSE
@@ -1458,7 +1460,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target_message = "[target] blocks your attack!")
return FALSE
- if(!(unarmed_attack_flags & UNARMED_ATTACK_PARRY))
+ if(!(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK))
if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount
user.adjustStaminaLossBuffered(1.5)
else
@@ -1490,17 +1492,17 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage
if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- damage *= 1.5
+ damage *= 1.2
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
- damage *= 0.5
+ damage *= 0.8
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
- damage *= 0.25
+ damage *= 0.8
//END OF CITADEL CHANGES
var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected))
var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases
- if(unarmed_attack_flags & UNARMED_ATTACK_PARRY)
+ if(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)
miss_chance = 0
else
if(user.dna.species.punchdamagelow)
@@ -1687,7 +1689,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
return
-/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags)
+/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, attackchain_flags)
if(!istype(M))
return
CHECK_DNA_AND_SPECIES(M)
@@ -1707,7 +1709,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
grab(M, H, attacker_style)
if("harm")
- harm(M, H, attacker_style, unarmed_attack_flags)
+ harm(M, H, attacker_style, attackchain_flags)
if("disarm")
disarm(M, H, attacker_style)
@@ -1717,7 +1719,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
// Allows you to put in item-specific reactions based on species
if(user != H)
var/list/block_return = list()
- if(H.mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, block_return) & BLOCK_SUCCESS)
+ if(H.mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, block_return) & BLOCK_SUCCESS)
return 0
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
if(H.check_martial_melee_block())
@@ -1744,20 +1746,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H, wound_bonus = Iwound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness())
- H.send_item_attack_message(I, user, hit_area, totitemdamage)
+ H.send_item_attack_message(I, user, hit_area, affecting, totitemdamage)
I.do_stagger_action(H, user, totitemdamage)
if(!totitemdamage)
return 0 //item force is zero
- //dismemberment
- var/probability = I.get_dismemberment_chance(affecting)
- if(prob(probability) || (HAS_TRAIT(H, TRAIT_EASYDISMEMBER) && prob(probability))) //try twice
- if(affecting.dismember(I.damtype))
- I.add_mob_blood(H)
- playsound(get_turf(H), I.get_dismember_sound(), 80, 1)
-
var/bloody = 0
if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2))))
if(affecting.status == BODYPART_ORGANIC)
@@ -1828,6 +1823,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return TRUE
CHECK_DNA_AND_SPECIES(M)
CHECK_DNA_AND_SPECIES(H)
+ if(!M.CheckActionCooldown())
+ return
+ M.DelayNextAction(CLICK_CD_MELEE)
if(!istype(M)) //sanity check for drones.
return TRUE
@@ -1937,11 +1935,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target.visible_message("[user.name] shoves [target.name]!",
"[user.name] shoves you!", null, COMBAT_MESSAGE_RANGE, null,
user, "You shove [target.name]!")
+ target.Stagger(SHOVE_STAGGER_DURATION)
var/obj/item/target_held_item = target.get_active_held_item()
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
target_held_item = null
- if(!target.has_movespeed_modifier(/datum/movespeed_modifier/shove))
- target.add_movespeed_modifier(/datum/movespeed_modifier/shove)
+ if(!target.has_status_effect(STATUS_EFFECT_OFF_BALANCE))
if(target_held_item)
if(!HAS_TRAIT(target_held_item, TRAIT_NODROP))
target.visible_message("[target.name]'s grip on \the [target_held_item] loosens!",
@@ -1949,15 +1947,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
append_message += ", loosening their grip on [target_held_item]"
else
append_message += ", but couldn't loose their grip on [target_held_item]"
- addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH)
else if(target_held_item)
if(target.dropItemToGround(target_held_item))
target.visible_message("[target.name] drops \the [target_held_item]!!",
"You drop \the [target_held_item]!!", null, COMBAT_MESSAGE_RANGE)
append_message += ", causing them to drop [target_held_item]"
+ target.ShoveOffBalance(SHOVE_OFFBALANCE_DURATION)
log_combat(user, target, "shoved", append_message)
-/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness) // make sure putting wound_bonus here doesn't screw up other signals or uses for this signal
var/hit_percent = (100-(blocked+armor))/100
hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100
@@ -2033,6 +2031,25 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
// called before a projectile hit
return
+/**
+
+
+
+ * The human species version of [/mob/living/carbon/proc/get_biological_state]. Depends on the HAS_FLESH and HAS_BONE species traits, having bones lets you have bone wounds, having flesh lets you have burn, slash, and piercing wounds
+
+
+
+ */
+
+
+
+/datum/species/proc/get_biological_state(mob/living/carbon/human/H)
+ . = BIO_INORGANIC
+ if(HAS_FLESH in species_traits)
+ . |= BIO_JUST_FLESH
+ if(HAS_BONE in species_traits)
+ . |= BIO_JUST_BONE
+
/////////////
//BREATHING//
/////////////
@@ -2226,12 +2243,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/ExtinguishMob(mob/living/carbon/human/H)
return
-
////////////
//Stun//
////////////
/datum/species/proc/spec_stun(mob/living/carbon/human/H,amount)
+ if(H)
+ stop_wagging_tail(H)
+
. = stunmod * H.physiology.stun_mod * amount
//////////////
@@ -2249,11 +2268,30 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
////////////////
/datum/species/proc/can_wag_tail(mob/living/carbon/human/H)
- return FALSE
+ if(!tail_type || !wagging_type)
+ return FALSE
+ else
+ return mutant_bodyparts[tail_type] || mutant_bodyparts[wagging_type]
/datum/species/proc/is_wagging_tail(mob/living/carbon/human/H)
- return FALSE
+ return mutant_bodyparts[wagging_type]
/datum/species/proc/start_wagging_tail(mob/living/carbon/human/H)
+ if(tail_type && wagging_type)
+ if(mutant_bodyparts[tail_type])
+ mutant_bodyparts[wagging_type] = mutant_bodyparts[tail_type]
+ mutant_bodyparts -= tail_type
+ if(tail_type == "tail_lizard") //special lizard thing
+ mutant_bodyparts["waggingspines"] = mutant_bodyparts["spines"]
+ mutant_bodyparts -= "spines"
+ H.update_body()
/datum/species/proc/stop_wagging_tail(mob/living/carbon/human/H)
+ if(tail_type && wagging_type)
+ if(mutant_bodyparts[wagging_type])
+ mutant_bodyparts[tail_type] = mutant_bodyparts[wagging_type]
+ mutant_bodyparts -= wagging_type
+ if(tail_type == "tail_lizard") //special lizard thing
+ mutant_bodyparts["spines"] = mutant_bodyparts["waggingspines"]
+ mutant_bodyparts -= "waggingspines"
+ H.update_body()
diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm
index 409781efb2..38e10e8662 100644
--- a/code/modules/mob/living/carbon/human/species_types/abductors.dm
+++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm
@@ -3,9 +3,10 @@
id = "abductor"
say_mod = "gibbers"
sexes = FALSE
- species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL,CAN_SCAR)
+ species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_CHUNKYFINGERS,TRAIT_NOHUNGER,TRAIT_NOBREATH)
mutanttongue = /obj/item/organ/tongue/abductor
+ species_type = "alien"
/datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm
index 94f64ceacb..c5b57b82ab 100644
--- a/code/modules/mob/living/carbon/human/species_types/android.dm
+++ b/code/modules/mob/living/carbon/human/species_types/android.dm
@@ -11,6 +11,7 @@
mutanttongue = /obj/item/organ/tongue/robot
species_language_holder = /datum/language_holder/synthetic
limbs_id = "synth"
+ species_type = "robotic"
/datum/species/android/on_species_gain(mob/living/carbon/C)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm
index 2d43c9964e..2cf054c7b9 100644
--- a/code/modules/mob/living/carbon/human/species_types/angel.dm
+++ b/code/modules/mob/living/carbon/human/species_types/angel.dm
@@ -2,13 +2,14 @@
name = "Angel"
id = "angel"
default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,CAN_SCAR)
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "wings" = "Angel")
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
no_equip = list(SLOT_BACK)
blacklisted = 1
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
+ species_type = "human" //they're a kind of human
var/datum/action/innate/flight/fly
diff --git a/code/modules/mob/living/carbon/human/species_types/bugmen.dm b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
index 6a9e9d0b13..2a955e28a4 100644
--- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
@@ -3,9 +3,9 @@
id = "insect"
say_mod = "chitters"
default_color = "00FF00"
- species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,CAN_SCAR)
+ species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
- mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None",
+ mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None",
"insect_wings" = "None", "insect_fluff" = "None", "mam_snouts" = "None", "taur" = "None", "insect_markings" = "None")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
@@ -17,32 +17,6 @@
exotic_bloodtype = "BUG"
exotic_blood_color = BLOOD_COLOR_BUG
-/datum/species/insect/spec_death(gibbed, mob/living/carbon/human/H)
- if(H)
- stop_wagging_tail(H)
-
-/datum/species/insect/spec_stun(mob/living/carbon/human/H,amount)
- if(H)
- stop_wagging_tail(H)
- . = ..()
-
-/datum/species/insect/can_wag_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/insect/is_wagging_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/insect/start_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_tail"])
- mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"]
- mutant_bodyparts -= "mam_tail"
- H.update_body()
-
-/datum/species/insect/stop_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_waggingtail"])
- mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"]
- mutant_bodyparts -= "mam_waggingtail"
- H.update_body()
-
-/datum/species/insect/qualifies_for_rank(rank, list/features)
- return TRUE
+ tail_type = "mam_tail"
+ wagging_type = "mam_waggingtail"
+ species_type = "insect"
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species_types/corporate.dm b/code/modules/mob/living/carbon/human/species_types/corporate.dm
index e062e1cbf7..a2597ed286 100644
--- a/code/modules/mob/living/carbon/human/species_types/corporate.dm
+++ b/code/modules/mob/living/carbon/human/species_types/corporate.dm
@@ -17,4 +17,5 @@
species_traits = list(NOBLOOD,EYECOLOR,NOGENITALS)
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER)
sexes = 0
- gib_types = /obj/effect/gibspawner/robot
\ No newline at end of file
+ gib_types = /obj/effect/gibspawner/robot
+ species_type = "robotic"
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
index 4e5aa57b0a..d8dfe63b35 100644
--- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
@@ -2,8 +2,8 @@
name = "Dullahan"
id = "dullahan"
default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
- inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH,CAN_SCAR)
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
+ inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "deco_wings" = "None")
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
mutant_brain = /obj/item/organ/brain/dullahan
@@ -14,6 +14,7 @@
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
has_field_of_vision = FALSE //Too much of a trouble, their vision is already bound to their severed head.
+ species_type = "undead"
var/pumpkin = FALSE
var/obj/item/dullahan_relay/myhead
diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
index 009dba7707..a465e7c3a9 100644
--- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
@@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
name = "Dwarf"
id = "dwarf" //Also called Homo sapiens pumilionis
default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,CAN_SCAR)
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB)
limbs_id = "human"
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
@@ -18,6 +18,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
mutant_organs = list(/obj/item/organ/dwarfgland) //Dwarven alcohol gland, literal gland warrior
mutantliver = /obj/item/organ/liver/dwarf //Dwarven super liver (Otherwise they r doomed)
species_language_holder = /datum/language_holder/dwarf
+ species_type = "human" //a kind of human
/mob/living/carbon/human/species/dwarf //species admin spawn path
race = /datum/species/dwarf //and the race the path is set to.
diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm
index 2f0595e2c0..b760fd0aee 100644
--- a/code/modules/mob/living/carbon/human/species_types/felinid.dm
+++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm
@@ -9,37 +9,9 @@
mutantears = /obj/item/organ/ears/cat
mutanttail = /obj/item/organ/tail/cat
-/datum/species/human/felinid/qualifies_for_rank(rank, list/features)
- return TRUE
-
-//Curiosity killed the cat's wagging tail.
-/datum/species/human/felinid/spec_death(gibbed, mob/living/carbon/human/H)
- if(H)
- stop_wagging_tail(H)
-
-/datum/species/human/felinid/spec_stun(mob/living/carbon/human/H,amount)
- if(H)
- stop_wagging_tail(H)
- . = ..()
-
-
-/datum/species/human/felinid/can_wag_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/human/felinid/is_wagging_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/human/felinid/start_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_tail"])
- mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"]
- mutant_bodyparts -= "mam_tail"
- H.update_body()
-
-/datum/species/human/felinid/stop_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_waggingtail"])
- mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"]
- mutant_bodyparts -= "mam_waggingtail"
- H.update_body()
+ tail_type = "mam_tail"
+ wagging_type = "mam_waggingtail"
+ species_type = "furry"
/datum/species/human/felinid/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
if(ishuman(C))
diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
index c3ec8b42ea..c56adaf1b0 100644
--- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
@@ -2,7 +2,7 @@
name = "Anthromorphic Fly"
id = "fly"
say_mod = "buzzes"
- species_traits = list(NOEYES,CAN_SCAR)
+ species_traits = list(NOEYES,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
mutanttongue = /obj/item/organ/tongue/fly
mutantliver = /obj/item/organ/liver/fly
@@ -12,6 +12,7 @@
liked_food = GROSS
exotic_bloodtype = "BUG"
exotic_blood_color = BLOOD_COLOR_BUG
+ species_type = "insect"
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(istype(chem, /datum/reagent/toxin/pestkiller))
diff --git a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
index 203f8fa289..7706d4a9d5 100644
--- a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
@@ -3,9 +3,9 @@
id = "mammal"
default_color = "4B4B4B"
icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
- species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,CAN_SCAR)
+ species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST
- mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None",
+ mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None",
"mam_body_markings" = "Husky", "taur" = "None", "horns" = "None", "legs" = "Plantigrade", "meat_type" = "Mammalian")
attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
@@ -14,67 +14,6 @@
liked_food = MEAT | FRIED
disliked_food = TOXIC
-//Curiosity killed the cat's wagging tail.
-/datum/species/mammal/spec_death(gibbed, mob/living/carbon/human/H)
- if(H)
- stop_wagging_tail(H)
-
-/datum/species/mammal/spec_stun(mob/living/carbon/human/H,amount)
- if(H)
- stop_wagging_tail(H)
- . = ..()
-
-/datum/species/mammal/can_wag_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/mammal/is_wagging_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/mammal/start_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_tail"])
- mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"]
- mutant_bodyparts -= "mam_tail"
- H.update_body()
-
-/datum/species/mammal/stop_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_waggingtail"])
- mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"]
- mutant_bodyparts -= "mam_waggingtail"
- H.update_body()
-
-
-/datum/species/mammal/qualifies_for_rank(rank, list/features)
- return TRUE
-
-
-//Alien//
-/datum/species/xeno
- // A cloning mistake, crossing human and xenomorph DNA
- name = "Xenomorph Hybrid"
- id = "xeno"
- say_mod = "hisses"
- default_color = "00FF00"
- icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
- species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
- mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade")
- attack_verb = "slash"
- attack_sound = 'sound/weapons/slash.ogg'
- miss_sound = 'sound/weapons/slashmiss.ogg'
- meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
- gib_types = list(/obj/effect/gibspawner/xeno/xenoperson, /obj/effect/gibspawner/xeno/xenoperson/bodypartless)
- skinned_type = /obj/item/stack/sheet/animalhide/xeno
- exotic_bloodtype = "X*"
- damage_overlay_type = "xeno"
- liked_food = MEAT
-
-//Praise the Omnissiah, A challange worthy of my skills - HS
-
-//EXOTIC//
-//These races will likely include lots of downsides and upsides. Keep them relatively balanced.//
-
-//misc
-/mob/living/carbon/human/dummy
- vore_flags = NO_VORE
-
-/mob/living/carbon/human/vore
- vore_flags = DEVOURABLE | DIGESTABLE | FEEDING
+ tail_type = "mam_tail"
+ wagging_type = "mam_waggingtail"
+ species_type = "furry"
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 7100caf178..438eaf1eea 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -32,6 +32,8 @@
var/special_name_chance = 5
var/owner //dobby is a free golem
+ species_type = "golem"
+
/datum/species/golem/random_name(gender,unique,lastname)
var/golem_surname = pick(GLOB.golem_names)
// 3% chance that our golem has a human surname, because
diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm
index 1868bd22df..f175ddb921 100644
--- a/code/modules/mob/living/carbon/human/species_types/humans.dm
+++ b/code/modules/mob/living/carbon/human/species_types/humans.dm
@@ -3,15 +3,16 @@
id = "human"
default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,CAN_SCAR)
- mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None")
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,HAS_FLESH,HAS_BONE)
+ mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None")
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
skinned_type = /obj/item/stack/sheet/animalhide/human
disliked_food = GROSS | RAW
liked_food = JUNKFOOD | FRIED
-/datum/species/human/qualifies_for_rank(rank, list/features)
- return TRUE //Pure humans are always allowed in all roles.
+ tail_type = "tail_human"
+ wagging_type = "waggingtail_human"
+ species_type = "human"
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
@@ -21,21 +22,3 @@
if(H)
stop_wagging_tail(H)
. = ..()
-
-/datum/species/human/can_wag_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["tail_human"] || mutant_bodyparts["waggingtail_human"]
-
-/datum/species/human/is_wagging_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["waggingtail_human"]
-
-/datum/species/human/start_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["tail_human"])
- mutant_bodyparts["waggingtail_human"] = mutant_bodyparts["tail_human"]
- mutant_bodyparts -= "tail_human"
- H.update_body()
-
-/datum/species/human/stop_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["waggingtail_human"])
- mutant_bodyparts["tail_human"] = mutant_bodyparts["waggingtail_human"]
- mutant_bodyparts -= "waggingtail_human"
- H.update_body()
diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm
index 96efaebd74..3aef14c256 100644
--- a/code/modules/mob/living/carbon/human/species_types/ipc.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -6,7 +6,7 @@
icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
blacklisted = 0
sexes = 0
- species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING)
+ species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
@@ -21,6 +21,7 @@
exotic_bloodtype = "HF"
exotic_blood_color = BLOOD_COLOR_OIL
+ species_type = "robotic"
var/datum/action/innate/monitor_change/screen
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 31f326fd53..9d7f99c14e 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -4,10 +4,10 @@
id = "jelly"
default_color = "00FF90"
say_mod = "chirps"
- species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR)
+ species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR,HAS_FLESH)
mutantlungs = /obj/item/organ/lungs/slime
mutant_heart = /obj/item/organ/heart/slime
- mutant_bodyparts = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None")
+ mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None")
inherent_traits = list(TRAIT_TOXINLOVER)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
gib_types = list(/obj/effect/gibspawner/slime, /obj/effect/gibspawner/slime/bodypartless)
@@ -25,6 +25,10 @@
species_language_holder = /datum/language_holder/jelly
mutant_brain = /obj/item/organ/brain/jelly
+ tail_type = "mam_tail"
+ wagging_type = "mam_waggingtail"
+ species_type = "jelly"
+
/obj/item/organ/brain/jelly
name = "slime nucleus"
desc = "A slimey membranous mass from a slime person"
@@ -128,33 +132,6 @@
return
to_chat(H, "...but there is not enough of you to go around! You must attain more mass to heal!")
-/datum/species/jelly/spec_death(gibbed, mob/living/carbon/human/H)
- if(H)
- stop_wagging_tail(H)
-
-/datum/species/jelly/spec_stun(mob/living/carbon/human/H,amount)
- if(H)
- stop_wagging_tail(H)
- . = ..()
-
-/datum/species/jelly/can_wag_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/jelly/is_wagging_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/jelly/start_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_tail"])
- mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"]
- mutant_bodyparts -= "mam_tail"
- H.update_body()
-
-/datum/species/jelly/stop_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_waggingtail"])
- mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"]
- mutant_bodyparts -= "mam_waggingtail"
- H.update_body()
-
////////////////////////////////////////////////////////SLIMEPEOPLE///////////////////////////////////////////////////////////////////
@@ -443,7 +420,7 @@
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
inherent_traits = list(TRAIT_TOXINLOVER)
- mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
+ mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
say_mod = "says"
hair_color = "mutcolor"
hair_alpha = 160 //a notch brighter so it blends better.
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index a424969175..d768788e87 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -4,7 +4,7 @@
id = "lizard"
say_mod = "hisses"
default_color = "00FF00"
- species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,CAN_SCAR)
+ species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur", "deco_wings")
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
mutanttongue = /obj/item/organ/tongue/lizard
@@ -27,6 +27,10 @@
inert_mutation = FIREBREATH
species_language_holder = /datum/language_holder/lizard
+ tail_type = "tail_lizard"
+ wagging_type = "waggingtail_lizard"
+ species_type = "lizard"
+
/datum/species/lizard/random_name(gender,unique,lastname)
if(unique)
return random_unique_lizard_name(gender)
@@ -38,41 +42,6 @@
return randname
-/datum/species/lizard/qualifies_for_rank(rank, list/features)
- return TRUE
-
-//I wag in death
-/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H)
- if(H)
- stop_wagging_tail(H)
-
-/datum/species/lizard/spec_stun(mob/living/carbon/human/H,amount)
- if(H)
- stop_wagging_tail(H)
- . = ..()
-
-/datum/species/lizard/can_wag_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["tail_lizard"] || mutant_bodyparts["waggingtail_lizard"]
-
-/datum/species/lizard/is_wagging_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["waggingtail_lizard"]
-
-/datum/species/lizard/start_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["tail_lizard"])
- mutant_bodyparts["waggingtail_lizard"] = mutant_bodyparts["tail_lizard"]
- mutant_bodyparts["waggingspines"] = mutant_bodyparts["spines"]
- mutant_bodyparts -= "tail_lizard"
- mutant_bodyparts -= "spines"
- H.update_body()
-
-/datum/species/lizard/stop_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["waggingtail_lizard"])
- mutant_bodyparts["tail_lizard"] = mutant_bodyparts["waggingtail_lizard"]
- mutant_bodyparts["spines"] = mutant_bodyparts["waggingspines"]
- mutant_bodyparts -= "waggingtail_lizard"
- mutant_bodyparts -= "waggingspines"
- H.update_body()
-
/*
Lizard subspecies: ASHWALKERS
*/
diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
index 8e8c65b15e..f91c3518a3 100644
--- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
@@ -8,7 +8,7 @@
nojumpsuit = TRUE
say_mod = "poofs" //what does a mushroom sound like
- species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL,CAN_SCAR)
+ species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_NOBREATH)
speedmod = 1.5 //faster than golems but not by much
@@ -21,6 +21,8 @@
burnmod = 1.25
heatmod = 1.5
+ species_type = "plant"
+
mutanteyes = /obj/item/organ/eyes/night_vision/mushroom
var/datum/martial_art/mushpunch/mush
species_language_holder = /datum/language_holder/mushroom
diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
index 91d3135ae1..b61e29b685 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -4,7 +4,7 @@
say_mod = "rattles"
sexes = 0
meat = /obj/item/stack/sheet/mineral/plasma
- species_traits = list(NOBLOOD,NOTRANSSTING,NOGENITALS)
+ species_traits = list(NOBLOOD,NOTRANSSTING,NOGENITALS,HAS_BONE)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_NOHUNGER,TRAIT_CALCIUM_HEALER)
inherent_biotypes = MOB_HUMANOID|MOB_MINERAL
mutantlungs = /obj/item/organ/lungs/plasmaman
@@ -22,6 +22,8 @@
liked_food = VEGETABLES
outfit_important_for_life = /datum/outfit/plasmaman
+ species_type = "skeleton"
+
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H)
var/datum/gas_mixture/environment = H.loc.return_air()
var/atmos_sealed = FALSE
diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index 36a1d52cba..f5a2f807e4 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -3,7 +3,7 @@
name = "Anthromorphic Plant"
id = "pod"
default_color = "59CE00"
- species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR)
+ species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR,HAS_FLESH,HAS_BONE)
attack_verb = "slash"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
@@ -19,6 +19,8 @@
var/light_burnheal = -1
var/light_bruteheal = -1
+ species_type = "plant"
+
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.faction |= "plants"
@@ -64,36 +66,12 @@
name = "Anthromorphic Plant"
id = "podweak"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
- mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
+ mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
limbs_id = "pod"
light_nutrition_gain_factor = 3
light_bruteheal = -0.2
light_burnheal = -0.2
light_toxheal = -0.7
-/datum/species/pod/pseudo_weak/spec_death(gibbed, mob/living/carbon/human/H)
- if(H)
- stop_wagging_tail(H)
-
-/datum/species/pod/pseudo_weak/spec_stun(mob/living/carbon/human/H,amount)
- if(H)
- stop_wagging_tail(H)
- . = ..()
-
-/datum/species/pod/pseudo_weak/can_wag_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/pod/pseudo_weak/is_wagging_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/pod/pseudo_weak/start_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_tail"])
- mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"]
- mutant_bodyparts -= "mam_tail"
- H.update_body()
-
-/datum/species/pod/pseudo_weak/stop_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_waggingtail"])
- mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"]
- mutant_bodyparts -= "mam_waggingtail"
- H.update_body()
+ tail_type = "mam_tail"
+ wagging_type = "mam_waggingtail"
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index 2776c6d919..b9864bce16 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -9,12 +9,14 @@
blacklisted = 1
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
- species_traits = list(NOBLOOD,NOEYES,CAN_SCAR)
- inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH,CAN_SCAR)
+ species_traits = list(NOBLOOD,NOEYES,HAS_FLESH,HAS_BONE)
+ inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH)
dangerous_existence = 1
mutanteyes = /obj/item/organ/eyes/night_vision
+ species_type = "shadow"
+
/datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.AddElement(/datum/element/photosynthesis, 1, 1, 0, 0, 0, 0, SHADOW_SPECIES_LIGHT_THRESHOLD, SHADOW_SPECIES_LIGHT_THRESHOLD)
@@ -164,7 +166,7 @@
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
item_flags = ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_HUGE
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/light_eater/Initialize()
diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
index 78efddf70d..51d81bd4d3 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -5,7 +5,7 @@
blacklisted = 0
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
- species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL)
+ species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,HAS_BONE)
inherent_traits = list(TRAIT_NOBREATH,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutanttongue = /obj/item/organ/tongue/bone
@@ -15,6 +15,8 @@
brutemod = 1.25
burnmod = 1.25
+ species_type = "skeleton" //they have their own category that's disassociated from undead, paired with plasmapeople
+
/datum/species/skeleton/New()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) //skeletons are stronger during the spooky season!
inherent_traits |= list(TRAIT_RESISTHEAT,TRAIT_RESISTCOLD)
diff --git a/code/modules/mob/living/carbon/human/species_types/synthliz.dm b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
index af2e83ee0f..5ed806b302 100644
--- a/code/modules/mob/living/carbon/human/species_types/synthliz.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
@@ -4,7 +4,7 @@
icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
say_mod = "beeps"
default_color = "00FF00"
- species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR)
+ species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_antenna" = "Synthetic Lizard - Antennae","mam_tail" = "Synthetic Lizard", "mam_snouts" = "Synthetic Lizard - Snout", "legs" = "Digitigrade", "mam_body_markings" = "Synthetic Lizard - Plates", "taur" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
@@ -20,33 +20,6 @@
exotic_bloodtype = "S"
exotic_blood_color = BLOOD_COLOR_OIL
-/datum/species/synthliz/qualifies_for_rank(rank, list/features)
- return TRUE
-
-//I wag in death
-/datum/species/synthliz/spec_death(gibbed, mob/living/carbon/human/H)
- if(H)
- stop_wagging_tail(H)
-
-/datum/species/synthliz/spec_stun(mob/living/carbon/human/H,amount)
- if(H)
- stop_wagging_tail(H)
- . = ..()
-
-/datum/species/synthliz/can_wag_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/synthliz/is_wagging_tail(mob/living/carbon/human/H)
- return mutant_bodyparts["mam_waggingtail"]
-
-/datum/species/synthliz/start_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_tail"])
- mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"]
- mutant_bodyparts -= "mam_tail"
- H.update_body()
-
-/datum/species/synthliz/stop_wagging_tail(mob/living/carbon/human/H)
- if(mutant_bodyparts["mam_waggingtail"])
- mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"]
- mutant_bodyparts -= "mam_waggingtail"
- H.update_body()
+ tail_type = "mam_tail"
+ wagging_type = "mam_waggingtail"
+ species_type = "robotic"
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm
index 85f1fbf386..a1a2a33c54 100644
--- a/code/modules/mob/living/carbon/human/species_types/synths.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synths.dm
@@ -17,6 +17,7 @@
var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
species_language_holder = /datum/language_holder/synthetic
+ species_type = "robotic"
/datum/species/synth/military
name = "Military Synth"
@@ -43,7 +44,6 @@
return TRUE
return ..()
-
/datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H)
if(S && !istype(S, type))
name = S.name
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index f720aa7f8a..723c4848fe 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -2,10 +2,10 @@
name = "Vampire"
id = "vampire"
default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD)
+ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
- mutant_bodyparts = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
+ mutant_bodyparts = list("mcolor" = "FFFFFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
exotic_bloodtype = "U"
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
mutant_heart = /obj/item/organ/heart/vampire
@@ -14,6 +14,7 @@
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
var/info_text = "You are a Vampire. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
+ species_type = "undead"
/datum/species/vampire/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
diff --git a/code/modules/mob/living/carbon/human/species_types/xeno.dm b/code/modules/mob/living/carbon/human/species_types/xeno.dm
new file mode 100644
index 0000000000..db34d1ae45
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/species_types/xeno.dm
@@ -0,0 +1,19 @@
+/datum/species/xeno
+ // A cloning mistake, crossing human and xenomorph DNA
+ name = "Xenomorph Hybrid"
+ id = "xeno"
+ say_mod = "hisses"
+ default_color = "00FF00"
+ icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
+ species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
+ mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade")
+ attack_verb = "slash"
+ attack_sound = 'sound/weapons/slash.ogg'
+ miss_sound = 'sound/weapons/slashmiss.ogg'
+ meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
+ gib_types = list(/obj/effect/gibspawner/xeno/xenoperson, /obj/effect/gibspawner/xeno/xenoperson/bodypartless)
+ skinned_type = /obj/item/stack/sheet/animalhide/xeno
+ exotic_bloodtype = "X*"
+ damage_overlay_type = "xeno"
+ liked_food = MEAT
+ species_type = "alien"
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index ab0838c873..81a7f6e2e7 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -8,13 +8,14 @@
sexes = 0
blacklisted = 1
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
- species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING,CAN_SCAR)
+ species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH)
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
mutanttongue = /obj/item/organ/tongue/zombie
var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
disliked_food = NONE
liked_food = GROSS | MEAT | RAW
+ species_type = "undead"
/datum/species/zombie/notspaceproof
id = "notspaceproofzombie"
@@ -44,7 +45,7 @@
/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount)
. = min(20, amount)
-/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
. = ..()
if(.)
regen_cooldown = world.time + REGENERATION_DELAY
@@ -62,9 +63,9 @@
C.heal_overall_damage(heal_amt,heal_amt)
C.adjustToxLoss(-heal_amt)
for(var/i in C.all_wounds)
- var/datum/wound/W = i
- if(prob(4-W.severity))
- W.remove_wound()
+ var/datum/wound/iter_wound = i
+ if(prob(4-iter_wound.severity))
+ iter_wound.remove_wound()
if(!C.InCritical() && prob(4))
playsound(C, pick(spooks), 50, TRUE, 10)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 725feb214c..e29c6b9ffe 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -1,6 +1,8 @@
/mob/living/carbon/BiologicalLife(seconds, times_fired)
//Updates the number of stored chemicals for powers
handle_changeling()
+ //Handles the unique mentabolism of bloodsuckers, look at /datum/antagonist/bloodsucker/proc/LifeTick()
+ handle_bloodsucker()
//Reagent processing needs to come before breathing, to prevent edge cases.
handle_organs()
. = ..() // if . is false, we are dead.
@@ -422,6 +424,12 @@
hud_used.lingchemdisplay.invisibility = INVISIBILITY_ABSTRACT
+/mob/living/carbon/proc/handle_bloodsucker()
+ if(mind && AmBloodsucker(src))
+ var/datum/antagonist/bloodsucker/B = mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
+ B.LifeTick()
+
+
/mob/living/carbon/handle_mutations_and_radiation()
if(dna && dna.temporary_mutations.len)
for(var/mut in dna.temporary_mutations)
diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm
index 149ec5f0e3..13d234092c 100644
--- a/code/modules/mob/living/carbon/monkey/combat.dm
+++ b/code/modules/mob/living/carbon/monkey/combat.dm
@@ -90,8 +90,7 @@
else if(legcuffed)
I = legcuffed
if(I)
- changeNext_move(CLICK_CD_BREAKOUT)
- last_special = world.time + CLICK_CD_BREAKOUT
+ MarkResistTime()
cuff_resist(I)
/mob/living/carbon/monkey/proc/should_target(var/mob/living/L)
@@ -354,7 +353,7 @@
battle_screech()
a_intent = INTENT_HARM
-/mob/living/carbon/monkey/attack_hand(mob/living/L)
+/mob/living/carbon/monkey/on_attack_hand(mob/living/L)
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(L)
else if(L.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm
index 8f862af8fa..16b3c1a79e 100644
--- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm
@@ -42,7 +42,7 @@
adjustBruteLoss(15)
return TRUE
-/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
+/mob/living/carbon/monkey/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //To allow surgery to return properly.
return
diff --git a/code/modules/mob/living/clickdelay.dm b/code/modules/mob/living/clickdelay.dm
new file mode 100644
index 0000000000..dfdb9104bf
--- /dev/null
+++ b/code/modules/mob/living/clickdelay.dm
@@ -0,0 +1,4 @@
+/mob/living/GetActionCooldownMod()
+ . = ..()
+ for(var/datum/status_effect/S in status_effects)
+ . *= S.action_cooldown_mod()
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index 012808647e..47c9062148 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -14,7 +14,7 @@
*
* Returns TRUE if damage applied
*/
-/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
var/hit_percent = (100-blocked)/100
if(!damage || (hit_percent <= 0))
return 0
@@ -245,7 +245,7 @@
update_stamina()
// damage ONE external organ, organ gets randomly selected from damaged ones.
-/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
adjustBruteLoss(brute, FALSE) //zero as argument for no instant health update
adjustFireLoss(burn, FALSE)
adjustStaminaLoss(stamina, FALSE)
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index 7d0a701e8f..bae2d2106b 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -226,7 +226,7 @@
'sound/voice/catpeople/nyahehe.ogg'),
50, 1)
return
- else if(ismoth(C))
+ else if(isinsect(C))
playsound(C, 'sound/voice/moth/mothlaugh.ogg', 50, 1)
else if(ishumanbasic(C))
if(user.gender == FEMALE)
@@ -244,7 +244,7 @@
. = ..()
if(. && iscarbon(user)) //Citadel Edit because this is hilarious
var/mob/living/carbon/C = user
- if(ismoth(C))
+ if(isinsect(C))
playsound(C, 'sound/voice/moth/mothchitter.ogg', 50, 1)
/datum/emote/living/look
@@ -441,7 +441,7 @@
to_chat(user, "You cannot send IC messages (muted).")
return FALSE
else if(!params)
- var/custom_emote = stripped_multiline_input(user, "Choose an emote to display.", "Custom Emote", null, MAX_MESSAGE_LEN)
+ var/custom_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Custom Emote", null, MAX_MESSAGE_LEN)
if(custom_emote && !check_invalid(user, custom_emote))
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
switch(type)
@@ -531,3 +531,29 @@
to_chat(user, "You ready your slapping hand.")
else
to_chat(user, "You're incapable of slapping in your current state.")
+
+/datum/emote/living/audio_emote/blorble
+ key = "blorble"
+ key_third_person = "blorbles"
+ message = "blorbles."
+ message_param = "blorbles at %t."
+
+/datum/emote/living/audio_emote/blorble/run_emote(mob/user, params)
+ . = ..()
+ if(. && iscarbon(user))
+ var/mob/living/carbon/C = user
+ if(isjellyperson(C))
+ pick(playsound(C, 'sound/effects/attackblob.ogg', 50, 1),playsound(C, 'sound/effects/blobattack.ogg', 50, 1))
+
+/datum/emote/living/audio_emote/blurp
+ key = "blurp"
+ key_third_person = "blurps"
+ message = "blurps."
+ message_param = "blurps at %t."
+
+/datum/emote/living/audio_emote/blurp/run_emote(mob/user, params)
+ . = ..()
+ if(. && iscarbon(user))
+ var/mob/living/carbon/C = user
+ if(isjellyperson(C))
+ pick(playsound(C, 'sound/effects/meatslap.ogg', 50, 1),playsound(C, 'sound/effects/gib_step.ogg', 50, 1))
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index e20567121e..89321082c9 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -3,7 +3,7 @@
* Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this.
*/
/mob/living/proc/Life(seconds, times_fired)
- set waitfor = FALSE // yeah hey we're kind of on a subsystem, no sleeping will be tolerated here!
+ SHOULD_NOT_SLEEP(TRUE)
if(mob_transforming)
return
@@ -82,7 +82,7 @@
handle_diginvis() //AI becomes unable to see mob
if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
- float(on = TRUE)
+ INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE)
if(!loc)
return FALSE
@@ -139,7 +139,7 @@
ExtinguishMob()
return
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
- if(G.get_moles(/datum/gas/oxygen, 1))
+ if(!G.get_moles(/datum/gas/oxygen, 1))
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
return
var/turf/location = get_turf(src)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index ad243883d7..0f55d5c408 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -273,7 +273,7 @@
return
stop_pulling()
- changeNext_move(CLICK_CD_GRABBING)
+ DelayNextAction(CLICK_CD_GRABBING)
if(AM.pulledby)
if(!supress_message)
@@ -605,41 +605,55 @@
SEND_SIGNAL(item, COMSIG_ITEM_WEARERCROSSED, AM)
/mob/living/proc/makeTrail(turf/target_turf, turf/start, direction)
- if(!has_gravity())
+ if(!has_gravity() || !isturf(start) || !blood_volume)
return
- var/blood_exists = FALSE
+ var/blood_exists = locate(/obj/effect/decal/cleanable/trail_holder) in start
- for(var/obj/effect/decal/cleanable/trail_holder/C in start) //checks for blood splatter already on the floor
- blood_exists = TRUE
- if(isturf(start))
- var/trail_type = getTrail()
- if(trail_type)
- var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1)
- if(blood_volume && blood_volume > max((BLOOD_VOLUME_NORMAL*blood_ratio)*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold
- blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage.
- var/newdir = get_dir(target_turf, start)
- if(newdir != direction)
- newdir = newdir | direction
- if(newdir == 3) //N + S
- newdir = NORTH
- else if(newdir == 12) //E + W
- newdir = EAST
- if((newdir in GLOB.cardinals) && (prob(50)))
- newdir = turn(get_dir(target_turf, start), 180)
- if(!blood_exists)
- new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses())
+ var/trail_type = getTrail()
+ if(!trail_type)
+ return
- for(var/obj/effect/decal/cleanable/trail_holder/TH in start)
- if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled)
- TH.existing_dirs += newdir
- TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir))
- TH.transfer_mob_blood_dna(src)
+ var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1)
+ if(blood_volume < max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold
+ return
+
+ var/bleed_amount = bleedDragAmount()
+ blood_volume = max(blood_volume - bleed_amount, 0) //that depends on our brute damage.
+ var/newdir = get_dir(target_turf, start)
+ if(newdir != direction)
+ newdir = newdir | direction
+ if(newdir == (NORTH|SOUTH))
+ newdir = NORTH
+ else if(newdir == (EAST|WEST))
+ newdir = EAST
+ if((newdir in GLOB.cardinals) && (prob(50)))
+ newdir = turn(get_dir(target_turf, start), 180)
+ if(!blood_exists)
+ new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses())
+
+ for(var/obj/effect/decal/cleanable/trail_holder/TH in start)
+ if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled)
+ TH.existing_dirs += newdir
+ TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir))
+ TH.transfer_mob_blood_dna(src)
/mob/living/carbon/human/makeTrail(turf/T)
if((NOBLOOD in dna.species.species_traits) || !is_bleeding() || bleedsuppress)
return
..()
+///Returns how much blood we're losing from being dragged a tile, from [mob/living/proc/makeTrail]
+/mob/living/proc/bleedDragAmount()
+ var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1)
+ return max(1, brute_ratio * 2)
+
+/mob/living/carbon/bleedDragAmount()
+ var/bleed_amount = 0
+ for(var/i in all_wounds)
+ var/datum/wound/iter_wound = i
+ bleed_amount += iter_wound.drag_bleed_amount()
+ return bleed_amount
+
/mob/living/proc/getTrail()
if(getBruteLoss() < 300)
return pick("ltrails_1", "ltrails_2")
@@ -676,7 +690,7 @@
..(pressure_difference, direction, pressure_resistance_prob_delta)
/mob/living/can_resist()
- return !((next_move > world.time) || !CHECK_MOBILITY(src, MOBILITY_RESIST))
+ return CheckResistCooldown() && CHECK_MOBILITY(src, MOBILITY_RESIST)
/// Resist verb for attempting to get out of whatever is restraining your motion. Gives you resist clickdelay if do_resist() returns true.
/mob/living/verb/resist()
@@ -687,10 +701,12 @@
return
if(do_resist())
- changeNext_move(CLICK_CD_RESIST)
+ MarkResistTime()
+ DelayNextAction(CLICK_CD_RESIST)
-/// The actual proc for resisting. Return TRUE to give clickdelay.
+/// The actual proc for resisting. Return TRUE to give CLICK_CD_RESIST clickdelay.
/mob/living/proc/do_resist()
+ set waitfor = FALSE // some of these sleep.
SEND_SIGNAL(src, COMSIG_LIVING_RESIST, src)
//resisting grabs (as if it helps anyone...)
// only works if you're not cuffed.
@@ -701,7 +717,7 @@
return old_gs? TRUE : FALSE
// unbuckling yourself. stops the chain if you try it.
- if(buckled && last_special <= world.time)
+ if(buckled)
log_combat(src, buckled, "resisted buckle")
return resist_buckle()
@@ -730,13 +746,12 @@
if(CHECK_MOBILITY(src, MOBILITY_USE) && resist_embedded()) //Citadel Change for embedded removal memes - requires being able to use items.
// DO NOT GIVE DEFAULT CLICKDELAY - This is a combat action.
- changeNext_move(CLICK_CD_MELEE)
+ DelayNextAction(CLICK_CD_MELEE)
return FALSE
- if(last_special <= world.time)
- resist_restraints() //trying to remove cuffs.
- // DO NOT GIVE CLICKDELAY - last_special handles this.
- return FALSE
+ resist_restraints() //trying to remove cuffs.
+ // DO NOT GIVE CLICKDELAY
+ return FALSE
/// Proc to resist a grab. moving_resist is TRUE if this began by someone attempting to move. Return FALSE if still grabbed/failed to break out. Use this instead of resist_grab() directly.
/mob/proc/attempt_resist_grab(moving_resist, forced, log = TRUE)
@@ -802,7 +817,7 @@
else
throw_alert("gravity", /obj/screen/alert/weightless)
if(!override && !is_flying())
- float(!has_gravity)
+ INVOKE_ASYNC(src, /atom/movable.proc/float, !has_gravity)
/mob/living/float(on)
if(throwing)
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index 4211b2cfd9..729e7d3d7a 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -10,8 +10,7 @@
REMOVE_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_BLOCK_TRAIT)
remove_movespeed_modifier(/datum/movespeed_modifier/active_block)
var/datum/block_parry_data/data = I.get_block_parry_data()
- if(timeToNextMove() < data.block_end_click_cd_add)
- changeNext_move(data.block_end_click_cd_add)
+ DelayNextAction(data.block_end_click_cd_add)
return TRUE
/mob/living/proc/ACTIVE_BLOCK_START(obj/item/I)
@@ -97,7 +96,7 @@
return
// QOL: Attempt to toggle on combat mode if it isn't already
SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
- if(!SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
+ if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
to_chat(src, "You must be in combat mode to actively block!")
return FALSE
var/datum/block_parry_data/data = I.get_block_parry_data()
diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm
index 8141603f64..4a9c4e6311 100644
--- a/code/modules/mob/living/living_active_parry.dm
+++ b/code/modules/mob/living/living_active_parry.dm
@@ -59,14 +59,14 @@
return FALSE
//QOL: Try to enable combat mode if it isn't already
SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
- if(!SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
+ if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
to_chat(src, "You must be in combat mode to parry!")
return FALSE
data = return_block_parry_datum(data)
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
// can always implement it later, whatever.
- if((data.parry_respect_clickdelay && (next_move > world.time)) || ((parry_end_time_last + data.parry_cooldown) > world.time))
+ if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time))
to_chat(src, "You are not ready to parry (again)!")
return
// Point of no return, make sure everything is set.
@@ -121,7 +121,7 @@
Stagger(data.parry_failed_stagger_duration)
effect_text += "staggering themselves"
if(data.parry_failed_clickcd_duration)
- changeNext_move(data.parry_failed_clickcd_duration)
+ DelayNextAction(data.parry_failed_clickcd_duration, flush = TRUE)
effect_text += "throwing themselves off balance"
handle_parry_ending_effects(data, effect_text)
parrying = NOT_PARRYING
@@ -160,17 +160,17 @@
/**
* Called when an attack is parried using this, whether or not the parry was successful.
*/
-/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time)
+/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/**
* Called when an attack is parried innately, whether or not the parry was successful.
*/
-/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time)
+/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/**
* Called when an attack is parried using this, whether or not the parry was successful.
*/
-/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time)
+/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/**
* Called when an attack is parried and block_parra_data indicates to use a proc to handle counterattack.
@@ -256,7 +256,7 @@
var/datum/block_parry_data/data = get_parry_data()
if(data.parry_sounds)
playsound(src, pick(data.parry_sounds), 75)
- visible_message("[src] parries \the [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""]!")
+ visible_message("[src] parries [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""]!")
/// Run counterattack if any
/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency)
@@ -277,7 +277,7 @@
if(data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN])
switch(parrying)
if(ITEM_PARRY)
- active_parry_item.melee_attack_chain(src, attacker, null, ATTACKCHAIN_PARRY_COUNTERATTACK, data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN])
+ active_parry_item.melee_attack_chain(src, attacker, null, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_CLICKDELAY | ATTACK_IGNORE_ACTION | NO_AUTO_CLICKDELAY_HANDLING, data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN])
effect_text += "reflexively counterattacking with [active_parry_item]"
if(UNARMED_PARRY) // WARNING: If you are using these two, the attackchain parry counterattack flags and damage multipliers are unimplemented. Be careful with how you handle this.
UnarmedAttack(attacker)
diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm
index 9f1ad1c27a..47dae8849d 100644
--- a/code/modules/mob/living/living_blocking_parrying.dm
+++ b/code/modules/mob/living/living_blocking_parrying.dm
@@ -126,6 +126,8 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/list/parry_imperfect_falloff_percent_override
/// Efficiency in percent on perfect parry.
var/parry_efficiency_perfect = 120
+ /// Override for attack types, list("[ATTACK_TYPE_DEFINE]" = perecntage) for perfect efficiency.
+ var/parry_efficiency_perfect_override
/// Parry effect data.
var/list/parry_data = list(
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 1
@@ -180,7 +182,11 @@ GLOBAL_LIST_EMPTY(block_parry_data)
if(isnull(leeway))
leeway = parry_time_perfect_leeway
difference -= leeway
- . = parry_efficiency_perfect
+ var/perfect = attack_type_list_scan(parry_efficiency_perfect_override, attack_type)
+ if(isnull(perfect))
+ . = parry_efficiency_perfect
+ else
+ . = perfect
if(difference <= 0)
return
var/falloff = attack_type_list_scan(parry_imperfect_falloff_percent_override, attack_type)
@@ -276,6 +282,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
RENDER_VARIABLE_SIMPLE(parry_imperfect_falloff_percent, "Linear falloff in percent per decisecond for attacks parried outside of perfect window.")
RENDER_OVERRIDE_LIST(parry_imperfect_falloff_percent_override, "Override for the above for each attack type")
RENDER_VARIABLE_SIMPLE(parry_efficiency_perfect, "Efficiency in percentage a parry in the perfect window is considered.")
+ RENDER_OVERRIDE_LIST(parry_efficiency_perfect_override, "Override for the above for each attack type")
// parry_data
dat += ""
RENDER_VARIABLE_SIMPLE(parry_efficiency_considered_successful, "Minimum parry efficiency to be considered a successful parry.")
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index e24e9641bf..19adb7b787 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -77,6 +77,7 @@
final_percent = returnlist[BLOCK_RETURN_PROJECTILE_BLOCK_PERCENTAGE]
if(returned & BLOCK_SHOULD_REDIRECT)
handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD])
+ return BULLET_ACT_FORCE_PIERCE
if(returned & BLOCK_REDIRECTED)
return BULLET_ACT_FORCE_PIERCE
if(returned & BLOCK_SUCCESS)
@@ -85,7 +86,7 @@
totaldamage = block_calculate_resultant_damage(totaldamage, returnlist)
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
if(!P.nodamage)
- apply_damage(totaldamage, P.damage_type, def_zone, armor, wound_bonus=P.wound_bonus, bare_wound_bonus=P.bare_wound_bonus, sharpness=P.sharpness)
+ apply_damage(totaldamage, P.damage_type, def_zone, armor, wound_bonus = P.wound_bonus, bare_wound_bonus = P.bare_wound_bonus, sharpness = P.sharpness)
if(P.dismemberment)
check_projectile_dismemberment(P, def_zone)
var/missing = 100 - final_percent
@@ -135,12 +136,13 @@
dtype = I.damtype
if(!blocked)
- visible_message("[src] has been hit by [I].", \
- "You have been hit by [I].")
- var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration)
- apply_damage(total_damage, dtype, impacting_zone, armor, sharpness=I.sharpness)
- if(I.thrownby)
- log_combat(I.thrownby, src, "threw and hit", I)
+ if(!nosell_hit)
+ visible_message("[src] is hit by [I]!", \
+ "You're hit by [I]!")
+ if(!I.throwforce)
+ return
+ var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration)
+ apply_damage(I.throwforce, dtype, impacting_zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND))
else
return 1
else
@@ -215,8 +217,8 @@
//proc to upgrade a simple pull into a more aggressive grab.
/mob/living/proc/grippedby(mob/living/carbon/user, instant = FALSE)
if(user.grab_state < GRAB_KILL)
- user.changeNext_move(CLICK_CD_GRABBING)
- playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ user.DelayNextAction(CLICK_CD_GRABBING, flush = TRUE)
+ playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(user.grab_state) //only the first upgrade is instantaneous
var/old_grab_state = user.grab_state
@@ -270,10 +272,10 @@
user.set_pull_offsets(src, grab_state)
return 1
-/mob/living/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/mob/living/on_attack_hand(mob/user, act_intent = user.a_intent, attackchain_flags)
..() //Ignoring parent return value here.
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user)
- if((user != src) && act_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE | ((unarmed_attack_flags & UNARMED_ATTACK_PARRY)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE), null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
+ if((user != src) && act_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE | ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE), null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
log_combat(user, src, "attempted to touch")
visible_message("[user] attempted to touch [src]!",
"[user] attempted to touch you!", target = user,
@@ -323,6 +325,9 @@
/mob/living/attack_animal(mob/living/simple_animal/M)
M.face_atom(src)
+ if(!M.CheckActionCooldown(CLICK_CD_MELEE))
+ return
+ M.DelayNextAction()
if(M.melee_damage_upper == 0)
M.visible_message("\The [M] [M.friendly_verb_continuous] [src]!",
"You [M.friendly_verb_simple] [src]!", target = src,
@@ -338,7 +343,7 @@
return 0
damage = block_calculate_resultant_damage(damage, return_list)
if(M.attack_sound)
- playsound(loc, M.attack_sound, 50, 1, 1)
+ playsound(src, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src)
visible_message("\The [M] [M.attack_verb_continuous] [src]!", \
"\The [M] [M.attack_verb_continuous] you!", null, COMBAT_MESSAGE_RANGE, null,
@@ -347,6 +352,9 @@
return damage
/mob/living/attack_paw(mob/living/carbon/monkey/M)
+ if(!M.CheckActionCooldown(CLICK_CD_MELEE))
+ return
+ M.DelayNextAction()
if (M.a_intent == INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "You don't want to hurt anyone!")
@@ -368,6 +376,7 @@
visible_message("[M.name] has attempted to bite [src]!", \
"[M.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE, null,
M, "You have attempted to bite [src]!")
+ return TRUE
return FALSE
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index b037221e2c..5495d37297 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -53,7 +53,6 @@
var/hallucination = 0 //Directly affects how long a mob will hallucinate for
- var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out.
var/timeofdeath = 0
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm
index b89f249c80..7530630d74 100644
--- a/code/modules/mob/living/silicon/damage_procs.dm
+++ b/code/modules/mob/living/silicon/damage_procs.dm
@@ -1,5 +1,5 @@
-/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
+/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
var/hit_percent = (100-blocked)/100
if(!damage || (!forced && hit_percent <= 0))
return 0
diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm
index dcb7ac66c9..64509d2deb 100644
--- a/code/modules/mob/living/silicon/pai/pai_defense.dm
+++ b/code/modules/mob/living/silicon/pai/pai_defense.dm
@@ -28,8 +28,7 @@
fold_in(force = 1)
DefaultCombatKnockdown(200)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user)
+/mob/living/silicon/pai/on_attack_hand(mob/living/carbon/human/user)
switch(user.a_intent)
if(INTENT_HELP)
visible_message("[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.",
diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm
index 65e1047cdc..c0fca997f5 100644
--- a/code/modules/mob/living/silicon/robot/emote.dm
+++ b/code/modules/mob/living/silicon/robot/emote.dm
@@ -3,8 +3,14 @@
emote_type = EMOTE_AUDIBLE
/datum/emote/sound/silicon
- mob_type_allowed_typecache = list(/mob/living/silicon)
+ mob_type_allowed_typecache = list(/mob/living/silicon, /mob/living/carbon/human)
emote_type = EMOTE_AUDIBLE
+ var/unrestricted = FALSE
+
+/datum/emote/sound/silicon/run_emote(mob/user, params)
+ if(!unrestricted && !(issilicon(user) || isipcperson(user)))
+ return
+ return ..()
/datum/emote/silicon/boop
key = "boop"
diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm
index 0d8a0880a8..a063d090db 100644
--- a/code/modules/mob/living/silicon/robot/inventory.dm
+++ b/code/modules/mob/living/silicon/robot/inventory.dm
@@ -16,8 +16,6 @@
return item
return module_active
-
-
/mob/living/silicon/robot/proc/uneq_module(obj/item/O)
if(!O)
return 0
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 51cff93ceb..4fcd6d1dbd 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -289,7 +289,7 @@
/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool) && (user.a_intent != INTENT_HARM || user == src))
- user.changeNext_move(CLICK_CD_MELEE)
+ user.DelayNextAction(CLICK_CD_MELEE)
if (!getBruteLoss())
to_chat(user, "[src] is already in good condition!")
return
@@ -311,7 +311,7 @@
return
else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
- user.changeNext_move(CLICK_CD_MELEE)
+ user.DelayNextAction(CLICK_CD_MELEE)
if (getFireLoss() > 0 || getToxLoss() > 0)
if(src == user)
to_chat(user, "You start fixing yourself...")
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index e337618e4b..746c4f469d 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -62,8 +62,7 @@
return
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user)
+/mob/living/silicon/robot/on_attack_hand(mob/living/carbon/human/user)
add_fingerprint(user)
if(opened && !wiresexposed && cell && !issilicon(user))
cell.update_icon()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index badbcc4ed5..7c4125fbc6 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -361,8 +361,7 @@
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmed"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamed"),
"Eyebot" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "eyebotmed"),
- "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed"),
- "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_med")
+ "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed")
)
var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed")
for(var/a in L)
@@ -378,8 +377,6 @@
switch(med_borg_icon)
if("Default")
cyborg_base_icon = "medical"
- if("Zoomba")
- cyborg_base_icon = "zoomba_med"
if("Droid")
cyborg_base_icon = "medical"
cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi'
@@ -481,8 +478,7 @@
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "caneng"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinaeng"),
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidereng"),
- "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng"),
- "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_engi")
+ "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng")
)
var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng")
for(var/a in L)
@@ -498,8 +494,6 @@
switch(engi_borg_icon)
if("Default")
cyborg_base_icon = "engineer"
- if("Zoomba")
- cyborg_base_icon = "zoomba_engi"
if("Default - Treads")
cyborg_base_icon = "engi-tread"
special_light_key = "engineer"
@@ -580,8 +574,7 @@
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "cansec"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinasec"),
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidersec"),
- "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec"),
- "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_sec")
+ "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec")
)
var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark")
for(var/a in L)
@@ -597,8 +590,6 @@
switch(sec_borg_icon)
if("Default")
cyborg_base_icon = "sec"
- if("Zoomba")
- cyborg_base_icon = "zoomba_sec"
if("Default - Treads")
cyborg_base_icon = "sec-tread"
special_light_key = "sec"
@@ -836,8 +827,7 @@
"(Janitor) Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinajan"),
"(Janitor) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekjan"),
"(Janitor) Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canjan"),
- "(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan"),
- "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_jani")
+ "(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan")
)
var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark",
"(Janitor) Scrubpuppy" = "scrubpup")
@@ -852,8 +842,6 @@
service_icons = sortList(service_icons)
var/service_robot_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(service_robot_icon)
- if("Zoomba")
- cyborg_base_icon = "zoomba_jani"
if("(Service) Waitress")
cyborg_base_icon = "service_f"
special_light_key = "service"
@@ -956,8 +944,7 @@
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmin"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamin"),
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canmin"),
- "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin"),
- "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_miner")
+ "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin")
)
var/list/L = list("Blade" = "blade", "Vale" = "valemine")
for(var/a in L)
@@ -1001,8 +988,6 @@
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "valeminesleeper"
dogborg = TRUE
- if("Zoomba")
- cyborg_base_icon = "zoomba_miner"
else
return FALSE
return ..()
diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm
index 0850f0f886..8be2183d3b 100644
--- a/code/modules/mob/living/silicon/silicon_defense.dm
+++ b/code/modules/mob/living/silicon/silicon_defense.dm
@@ -70,7 +70,7 @@
return TRUE
return FALSE
-/mob/living/silicon/attack_hand(mob/living/carbon/human/M)
+/mob/living/silicon/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //the attack was blocked
return
diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm
index 278bb37d0d..b003e066ef 100644
--- a/code/modules/mob/living/simple_animal/animal_defense.dm
+++ b/code/modules/mob/living/simple_animal/animal_defense.dm
@@ -1,6 +1,6 @@
-/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
+/mob/living/simple_animal/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //the attack was blocked
return
diff --git a/code/modules/mob/living/simple_animal/astral.dm b/code/modules/mob/living/simple_animal/astral.dm
index eee42c214f..f79a2b5b3e 100644
--- a/code/modules/mob/living/simple_animal/astral.dm
+++ b/code/modules/mob/living/simple_animal/astral.dm
@@ -41,7 +41,11 @@
to_chat(src, "Your astral projection is interrupted and your mind is sent back to your body with a shock!")
/mob/living/simple_animal/astral/ClickOn(var/atom/A, var/params)
- ..()
+ . = ..()
+ attempt_possess(A)
+
+/mob/living/simple_animal/astral/proc/attempt_possess(atom/A)
+ set waitfor = FALSE
if(pseudo_death == FALSE)
if(isliving(A))
if(ishuman(A))
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index a347b04e50..fe6792b5c2 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -102,6 +102,10 @@
var/can_salute = TRUE
var/salute_delay = 60 SECONDS
+ //emotes/speech stuff
+ var/patrol_emote = "Engaging patrol mode."
+ var/patrol_fail_emote = "Unable to start patrol."
+
/mob/living/simple_animal/bot/proc/get_mode()
if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
if(paicard)
@@ -286,7 +290,7 @@
return TRUE //Successful completion. Used to prevent child process() continuing if this one is ended early.
-/mob/living/simple_animal/bot/attack_hand(mob/living/carbon/human/H)
+/mob/living/simple_animal/bot/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_HELP)
interact(H)
else
@@ -331,7 +335,6 @@
user.visible_message("[user] uses [W] to pull [paicard] out of [bot_name]!","You pull [paicard] out of [bot_name] with [W].")
ejectpai(user)
else
- user.changeNext_move(CLICK_CD_MELEE)
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
if(health >= maxHealth)
to_chat(user, "[src] does not need a repair!")
@@ -612,7 +615,7 @@ Pass a positive integer as an argument to override a bot's default speed.
if(tries >= BOT_STEP_MAX_RETRIES) //Bot is trapped, so stop trying to patrol.
auto_patrol = 0
tries = 0
- speak("Unable to start patrol.")
+ speak(patrol_fail_emote)
return
@@ -628,7 +631,7 @@ Pass a positive integer as an argument to override a bot's default speed.
return
mode = BOT_PATROL
else // no patrol target, so need a new one
- speak("Engaging patrol mode.")
+ speak(patrol_emote)
find_patrol_target()
tries++
return
diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
index 1f81e8db29..91462a6713 100644
--- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm
@@ -177,7 +177,7 @@ Auto Patrol[]"},
target = H
mode = BOT_HUNT
-/mob/living/simple_animal/bot/ed209/attack_hand(mob/living/carbon/human/H)
+/mob/living/simple_animal/bot/ed209/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_HARM)
retaliate(H)
return ..()
@@ -532,8 +532,10 @@ Auto Patrol[]"},
/mob/living/simple_animal/bot/ed209/RangedAttack(atom/A)
if(!on)
- return
+ return ..()
shootAt(A)
+ DelayNextAction()
+ return TRUE
/mob/living/simple_animal/bot/ed209/proc/stun_attack(mob/living/carbon/C)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm
index 43f18d3890..0ee600ed1d 100644
--- a/code/modules/mob/living/simple_animal/bot/honkbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm
@@ -112,7 +112,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
target = H
mode = BOT_HUNT
-/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H)
+/mob/living/simple_animal/bot/honkbot/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_HARM)
retaliate(H)
addtimer(CALLBACK(src, .proc/react_buzz), 5)
diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm
index f998f58f02..fb5a889d89 100644
--- a/code/modules/mob/living/simple_animal/bot/medbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/medbot.dm
@@ -604,7 +604,7 @@
/mob/living/simple_animal/bot/medbot/proc/get_healchem_toxin(mob/M)
return HAS_TRAIT(M, TRAIT_TOXINLOVER)? treatment_tox_toxlover : treatment_tox
-/mob/living/simple_animal/bot/medbot/attack_hand(mob/living/carbon/human/H)
+/mob/living/simple_animal/bot/medbot/on_attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_DISARM && mode != BOT_TIPPED)
H.visible_message("[H] begins tipping over [src].", "You begin tipping over [src]...")
diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm
index cfff3eb751..cf9698655b 100644
--- a/code/modules/mob/living/simple_animal/bot/secbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/secbot.dm
@@ -33,6 +33,20 @@
var/check_records = TRUE //Does it check security records?
var/arrest_type = FALSE //If true, don't handcuff
+ var/obj/item/clothing/head/bot_accessory
+ var/datum/beepsky_fashion/stored_fashion
+
+ //emotes (BOT is replaced with bot name, CRIMINAL with criminal name, THREAT_LEVEL with threat level)
+ var/death_emote = "BOT blows apart!"
+ var/capture_one = "BOT is trying to put zipties on CRIMINAL!"
+ var/capture_two = "BOT is trying to put zipties on you!"
+ var/infraction = "Level THREAT_LEVEL infraction alert!"
+ var/taunt = "BOT points at CRIMINAL!"
+ var/attack_one = "BOT has stunned CRIMINAL!"
+ var/attack_two = "BOT has stunned you!"
+ var/list/arrest_texts = list("Detaining", "Arresting")
+ var/arrest_emote = "ARREST_TYPE level THREAT_LEVEL scumbag CRIMINAL in LOCATION."
+
/mob/living/simple_animal/bot/secbot/beepsky
name = "Officer Beep O'sky"
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
@@ -49,6 +63,103 @@
resize = 0.8
update_transform()
+/mob/living/simple_animal/bot/secbot/proc/process_emote(var/emote_type, var/atom/criminal, var/threat, var/arrest = -1, var/location)
+ var/emote = "The continuity of space itself collapses around [src]. You should probably report that to someone higher up."
+ switch(emote_type)
+ if("DEATH")
+ emote = death_emote
+ if("CAPTURE_ONE")
+ emote = capture_one
+ if("CAPTURE_TWO")
+ emote = capture_two
+ if("INFRACTION")
+ emote = infraction
+ if("TAUNT")
+ emote = taunt
+ if("ATTACK_ONE")
+ emote = attack_one
+ if("ATTACK_TWO")
+ emote = attack_two
+ if("ARREST")
+ emote = arrest_emote
+
+ //now replace pieces of the text with the information we have
+ if(emote_type != "TAUNT" && emote_type != "ARREST")
+ emote = replacetext(emote, "BOT", name)
+ else
+ emote = replacetext(emote, "BOT", "[name]") //needs to be bold if its a taunt or an arrest text
+ if(criminal)
+ emote = replacetext(emote, "CRIMINAL", criminal.name)
+ if(num2text(threat)) //because a threat of 0 will be false
+ emote = replacetext(emote, "THREAT_LEVEL", threat)
+ if(arrest > -1)
+ emote = replacetext(emote, "ARREST_TYPE", arrest_texts[arrest + 1])
+ if(location)
+ emote = replacetext(emote, "LOCATION", location)
+ return emote
+
+/mob/living/simple_animal/bot/secbot/proc/apply_fashion(var/datum/beepsky_fashion/fashion)
+ stored_fashion = new fashion
+ if(stored_fashion.name)
+ name = stored_fashion.name
+
+ if(stored_fashion.desc)
+ desc = stored_fashion.desc
+
+ if(stored_fashion.death_emote)
+ death_emote = stored_fashion.death_emote
+
+ if(stored_fashion.capture_one)
+ capture_one = stored_fashion.capture_one
+
+ if(stored_fashion.capture_two)
+ capture_two = stored_fashion.capture_two
+
+ if(stored_fashion.infraction)
+ infraction = stored_fashion.infraction
+
+ if(stored_fashion.taunt)
+ taunt = stored_fashion.taunt
+
+ if(stored_fashion.attack_one)
+ attack_one = stored_fashion.attack_one
+
+ if(stored_fashion.attack_two)
+ attack_two = stored_fashion.attack_two
+
+ if(stored_fashion.patrol_emote)
+ patrol_emote = stored_fashion.patrol_emote
+
+ if(stored_fashion.patrol_fail_emote)
+ patrol_fail_emote = stored_fashion.patrol_fail_emote
+
+ if(stored_fashion.arrest_texts)
+ arrest_texts = stored_fashion.arrest_texts
+
+ if(stored_fashion.arrest_emote)
+ arrest_emote = stored_fashion.arrest_emote
+
+ regenerate_icons()
+
+/mob/living/simple_animal/bot/secbot/proc/reset_fashion()
+ bot_accessory.forceMove(get_turf(src))
+ //reset all emotes/sounds and name/desc
+ name = initial(name)
+ desc = initial(desc)
+ death_emote = initial(death_emote)
+ capture_one = initial(capture_one)
+ capture_two = initial(capture_two)
+ infraction = initial(infraction)
+ taunt = initial(taunt)
+ attack_one = initial(attack_one)
+ attack_two = initial(attack_two)
+ arrest_texts = initial(arrest_texts)
+ arrest_emote = initial(arrest_emote)
+ patrol_emote = initial(patrol_emote)
+ arrest_texts = initial(arrest_texts)
+ arrest_emote = initial(arrest_emote)
+ bot_accessory = null
+ regenerate_icons()
/mob/living/simple_animal/bot/secbot/beepsky/explode()
var/atom/Tsec = drop_location()
@@ -173,11 +284,16 @@ Auto Patrol: []"},
/mob/living/simple_animal/bot/secbot/proc/special_retaliate_after_attack(mob/user) //allows special actions to take place after being attacked.
return
-/mob/living/simple_animal/bot/secbot/attack_hand(mob/living/carbon/human/H)
+/mob/living/simple_animal/bot/secbot/on_attack_hand(mob/living/carbon/human/H)
if((H.a_intent == INTENT_HARM) || (H.a_intent == INTENT_DISARM))
retaliate(H)
if(special_retaliate_after_attack(H))
return
+ if(H.a_intent == INTENT_HELP && bot_accessory)
+
+ to_chat(H, "You knock [bot_accessory] off of [src]'s head!")
+ reset_fashion()
+ return
return ..()
@@ -185,11 +301,48 @@ Auto Patrol: []"},
..()
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry.
return
+ if(istype(W, /obj/item/clothing/head))
+ attempt_place_on_head(user, W)
+ return
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
retaliate(user)
if(special_retaliate_after_attack(user))
return
+/mob/living/simple_animal/bot/secbot/proc/attempt_place_on_head(mob/user, obj/item/clothing/head/H)
+ if(user && !user.temporarilyRemoveItemFromInventory(H))
+ to_chat(user, "\The [H] is stuck to your hand, you cannot put it on [src]'s head!")
+ return
+ if(bot_accessory)
+ to_chat("\[src] already has an accessory, and the laws of physics disallow him from wearing a second!")
+ return
+
+ if(H.beepsky_fashion)
+ to_chat(user, "You set [H] on [src].")
+ bot_accessory = H
+ H.forceMove(src)
+ apply_fashion(H.beepsky_fashion)
+ else
+ to_chat(user, "You set [H] on [src]'s head, but it falls off!")
+ H.forceMove(drop_location())
+
+/mob/living/simple_animal/bot/secbot/regenerate_icons()
+ ..()
+ if(bot_accessory)
+ if(!stored_fashion)
+ stored_fashion = new bot_accessory.beepsky_fashion
+ if(!stored_fashion.obj_icon_state)
+ stored_fashion.obj_icon_state = bot_accessory.icon_state
+ if(!stored_fashion.obj_alpha)
+ stored_fashion.obj_alpha = bot_accessory.alpha
+ if(!stored_fashion.obj_color)
+ stored_fashion.obj_color = bot_accessory.color
+ add_overlay(stored_fashion.get_overlay())
+ else
+ if(stored_fashion)
+ cut_overlay(stored_fashion.get_overlay())
+ stored_fashion = null
+
/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
. = ..()
if(emagged == 2)
@@ -233,8 +386,8 @@ Auto Patrol: []"},
/mob/living/simple_animal/bot/secbot/proc/cuff(mob/living/carbon/C)
mode = BOT_ARREST
playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2)
- C.visible_message("[src] is trying to put zipties on [C]!",\
- "[src] is trying to put zipties on you!")
+ C.visible_message("[process_emote("CAPTURE_ONE", C)]",\
+ "[process_emote("CAPTURE_TWO", C)]")
if(do_after(src, 60, FALSE, C))
attempt_handcuff(C)
@@ -249,16 +402,22 @@ Auto Patrol: []"},
/mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C)
var/judgement_criteria = judgement_criteria()
- playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
icon_state = "secbot-c"
addtimer(CALLBACK(src, /atom/.proc/update_icon), 2)
var/threat = 5
if(ishuman(C))
+ if(stored_fashion)
+ stored_fashion.stun_attack(C)
+ if(stored_fashion.stun_sounds && !stored_fashion.ignore_sound)
+ playsound(src, pick(stored_fashion.stun_sounds), 50, TRUE, -1)
+ else
+ playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
C.stuttering = 5
C.DefaultCombatKnockdown(100)
var/mob/living/carbon/human/H = C
threat = H.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
else
+ playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
C.DefaultCombatKnockdown(100)
C.stuttering = 5
threat = C.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
@@ -266,9 +425,9 @@ Auto Patrol: []"},
log_combat(src,C,"stunned")
if(declare_arrests)
var/area/location = get_area(src)
- speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag [C] in [location].", radio_channel)
- C.visible_message("[src] has stunned [C]!",\
- "[src] has stunned you!")
+ speak(process_emote("ARREST", C, threat, arrest_type, location), radio_channel)
+ C.visible_message("[process_emote("ATTACK_ONE", C)]",\
+ "[process_emote("ATTACK_TWO", C)]")
/mob/living/simple_animal/bot/secbot/handle_automated_action()
if(!..())
@@ -355,7 +514,6 @@ Auto Patrol: []"},
look_for_perp()
bot_patrol()
-
return
/mob/living/simple_animal/bot/secbot/proc/back_to_idle()
@@ -391,9 +549,9 @@ Auto Patrol: []"},
else if(threatlevel >= 4)
target = C
oldtarget_name = C.name
- speak("Level [threatlevel] infraction alert!")
+ speak(process_emote("INFRACTION", target, threatlevel))
playsound(loc, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE)
- visible_message("[src] points at [C.name]!")
+ visible_message(process_emote("TAUNT", target, threatlevel))
mode = BOT_HUNT
INVOKE_ASYNC(src, .proc/handle_automated_action)
break
@@ -408,7 +566,7 @@ Auto Patrol: []"},
/mob/living/simple_animal/bot/secbot/explode()
walk_to(src,0)
- visible_message("[src] blows apart!")
+ visible_message("[process_emote("DEATH")]")
var/atom/Tsec = drop_location()
var/obj/item/bot_assembly/secbot/Sa = new (Tsec)
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index d30fa1b49f..c21875d1db 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -283,7 +283,7 @@
if(!D.is_decorated)
D.decorate_donut()
-/mob/living/simple_animal/pet/cat/cak/attack_hand(mob/living/L)
+/mob/living/simple_animal/pet/cat/cak/on_attack_hand(mob/living/L)
. = ..()
if(.) //the attack was blocked
return
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index 1f733a4d55..51e7ee6c03 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -166,7 +166,7 @@
if(stat == CONSCIOUS)
udder.generateMilk(milk_reagent)
-/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M)
+/mob/living/simple_animal/cow/on_attack_hand(mob/living/carbon/M)
if(!stat && M.a_intent == INTENT_DISARM && icon_state != icon_dead)
M.visible_message("[M] tips over [src].",
"You tip over [src].")
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 73ebfa7c77..fb24b0fc09 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -60,11 +60,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
var/magic_fluff_string = "You draw the Coder, symbolizing bugs and errors. This shouldn't happen! Submit a bug report!"
var/tech_fluff_string = "BOOT SEQUENCE COMPLETE. ERROR MODULE LOADED. THIS SHOULDN'T HAPPEN. Submit a bug report!"
var/carp_fluff_string = "CARP CARP CARP SOME SORT OF HORRIFIC BUG BLAME THE CODERS CARP CARP CARP"
+ /// sigh, fine.
+ var/datum/song/holoparasite/music_datum
/mob/living/simple_animal/hostile/guardian/Initialize(mapload, theme)
GLOB.parasites += src
updatetheme(theme)
-
+ music_datum = new(src, get_allowed_instrument_ids())
. = ..()
/mob/living/simple_animal/hostile/guardian/med_hud_set_health()
@@ -84,8 +86,16 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
/mob/living/simple_animal/hostile/guardian/Destroy()
GLOB.parasites -= src
+ QDEL_NULL(music_datum)
return ..()
+/mob/living/simple_animal/hostile/guardian/verb/music_interact()
+ set name = "Access Internal Synthesizer"
+ set desc = "Access your internal musical synthesizer"
+ set category = "IC"
+
+ music_datum.ui_interact(src)
+
/mob/living/simple_animal/hostile/guardian/proc/updatetheme(theme) //update the guardian's theme
if(!theme)
theme = pick("magic", "tech", "carp")
@@ -638,6 +648,12 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
/obj/item/guardiancreator/tech/choose/dextrous
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
+/obj/item/guardiancreator/tech/choose/nukie // lacks support and protector as encouraging nukies to play turtle isnt fun and dextrous is epic
+ possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Ranged", "Standard")
+
+/obj/item/guardiancreator/tech/choose/nukie/check_uplink_validity()
+ return !used
+
/obj/item/paper/guides/antag/guardian
name = "Holoparasite Guide"
icon_state = "paper_words"
@@ -677,7 +693,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
Charger: Moves extremely fast, does medium damage on attack, and can charge at targets, damaging the first target hit and forcing them to drop any items they are holding.
- Dexterous: Does low damage on attack, but is capable of holding items and storing a single item within it. It will drop items held in its hands when it recalls, but it will retain the stored item.
+ Dextrous: Does low damage on attack, but is capable of holding items and storing a single item within it. It will drop items held in its hands when it recalls, but it will retain the stored item.
Explosive: High damage resist and medium power attack that may explosively teleport targets. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay.
@@ -691,6 +707,29 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
"}
+/obj/item/paper/guides/antag/guardian/nukie
+ name = "Guardian Guide"
+ info = {"A list of Guardian Types
+
+
+ Assassin: Does medium damage and takes full damage, but can enter stealth, causing its next attack to do massive damage and ignore armor. However, it becomes briefly unable to recall after attacking from stealth.
+
+ Chaos: Ignites enemies on touch and causes them to hallucinate all nearby people as the guardian. Automatically extinguishes the user if they catch on fire.
+
+ Charger: Moves extremely fast, does medium damage on attack, and can charge at targets, damaging the first target hit and forcing them to drop any items they are holding.
+
+ Dextrous: Does low damage on attack, but is capable of holding items and storing a single item within it. It will drop items held in its hands when it recalls, but it will retain the stored item.
+
+ Explosive: High damage resist and medium power attack that may explosively teleport targets. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay.
+
+ Lightning: Attacks apply lightning chains to targets. Has a lightning chain to the user. Lightning chains shock everything near them, doing constant damage.
+
+ Ranged: Has two modes. Ranged; which fires a constant stream of weak, armor-ignoring projectiles. Scout; Cannot attack, but can move through walls and is quite hard to see. Can lay surveillance snares, which alert it when crossed, in either mode.
+
+ Standard: Devastating close combat attacks and high damage resist. Can smash through weak walls.
+
+"}
+
/obj/item/storage/box/syndie_kit/guardian
name = "holoparasite injector kit"
@@ -699,6 +738,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
new /obj/item/guardiancreator/tech/choose/traitor(src)
new /obj/item/paper/guides/antag/guardian(src)
+/obj/item/storage/box/syndie_kit/nukieguardian
+ name = "holoparasite injector kit"
+
+/obj/item/storage/box/syndie_kit/nukieguardian/PopulateContents()
+ new /obj/item/guardiancreator/tech/choose/nukie(src)
+ new /obj/item/paper/guides/antag/guardian/nukie(src)
+
/obj/item/guardiancreator/carp
name = "holocarp fishsticks"
desc = "Using the power of Carp'sie, you can catch a carp from byond the veil of Carpthulu, and bind it to your fleshy flesh form."
diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm
index d396434708..26e5d791f3 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm
@@ -36,61 +36,21 @@
return
if(isobj(A) && Adjacent(A))
if(bomb_cooldown <= world.time && !stat)
- var/obj/guardian_bomb/B = new /obj/guardian_bomb(get_turf(A))
+ var/datum/component/killerqueen/K = A.AddComponent(/datum/component/killerqueen, EXPLODE_HEAVY, CALLBACK(src, .proc/on_explode), CALLBACK(src, .proc/on_failure), \
+ examine_message = "It glows with a strange light!")
+ QDEL_IN(K, 1 MINUTES)
to_chat(src, "Success! Bomb armed!")
bomb_cooldown = world.time + 200
- B.spawner = src
- B.disguise(A)
else
to_chat(src, "Your powers are on cooldown! You must wait 20 seconds between bombs.")
-/obj/guardian_bomb
- name = "bomb"
- desc = "You shouldn't be seeing this!"
- var/obj/stored_obj
- var/mob/living/simple_animal/hostile/guardian/spawner
+/mob/living/simple_animal/hostile/guardian/bomb/proc/on_explode(atom/bomb, atom/victim)
+ if((victim == src) || (victim == summoner) || (hasmatchingsummoner(victim)))
+ to_chat(victim, "[src] glows with a strange light, and you don't touch it.")
+ return FALSE
+ to_chat(src, "One of your explosive traps caught [victim]!")
+ to_chat(victim, "[bomb] was boobytrapped!")
+ return TRUE
-
-/obj/guardian_bomb/proc/disguise(obj/A)
- A.forceMove(src)
- stored_obj = A
- opacity = A.opacity
- anchored = A.anchored
- density = A.density
- appearance = A.appearance
- addtimer(CALLBACK(src, .proc/disable), 600)
-
-/obj/guardian_bomb/proc/disable()
- stored_obj.forceMove(get_turf(src))
- to_chat(spawner, "Failure! Your trap didn't catch anyone this time.")
- qdel(src)
-
-/obj/guardian_bomb/proc/detonate(mob/living/user)
- if(isliving(user))
- if(user != spawner && user != spawner.summoner && !spawner.hasmatchingsummoner(user))
- to_chat(user, "[src] was boobytrapped!")
- to_chat(spawner, "Success! Your trap caught [user]")
- var/turf/T = get_turf(src)
- stored_obj.forceMove(T)
- playsound(T,'sound/effects/explosion2.ogg', 200, 1)
- new /obj/effect/temp_visual/explosion(T)
- user.ex_act(EXPLODE_HEAVY)
- qdel(src)
- else
- to_chat(user, "[src] glows with a strange light, and you don't touch it.")
-
-/obj/guardian_bomb/Bump(atom/A)
- detonate(A)
- ..()
-
-/obj/guardian_bomb/attackby(mob/living/user)
- detonate(user)
-
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/guardian_bomb/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
- detonate(user)
-
-/obj/guardian_bomb/examine(mob/user)
- . = stored_obj.examine(user)
- if(get_dist(user,src)<=2)
- . += "It glows with a strange light!"
+/mob/living/simple_animal/hostile/guardian/bomb/proc/on_failure(atom/bomb)
+ to_chat(src, "Failure! Your trap didn't catch anyone this time.")
diff --git a/code/modules/mob/living/simple_animal/guardian/types/standard.dm b/code/modules/mob/living/simple_animal/guardian/types/standard.dm
index 2285167df5..d7970daa29 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/standard.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/standard.dm
@@ -3,7 +3,7 @@
melee_damage_lower = 20
melee_damage_upper = 20
obj_damage = 80
- next_move_modifier = 0.5 //attacks 50% faster
+ action_cooldown_mod = 0.5 //attacks 50% faster
environment_smash = ENVIRONMENT_SMASH_WALLS
playstyle_string = "As a standard type you have no special abilities, but take half damage and have powerful attack capable of smashing through walls."
magic_fluff_string = "..And draw the Assistant, faceless and generic, but never to be underestimated."
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index dc3c90cc64..da16ec581b 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -33,7 +33,7 @@
melee_damage_upper = 15
wound_bonus = -5
bare_wound_bonus = 10 // BEAR wound bonus am i right
- sharpness = TRUE
+ sharpness = SHARP_EDGED
attack_verb_continuous = "claws"
attack_verb_simple = "claw"
attack_sound = 'sound/weapons/bladeslice.ogg'
@@ -136,7 +136,7 @@ mob/living/simple_animal/hostile/bear/butter //The mighty companion to Cak. Seve
if(health < maxHealth)
heal_overall_damage(10) //Fast life regen, makes it hard for you to get eaten to death.
-/mob/living/simple_animal/hostile/bear/butter/attack_hand(mob/living/L) //Borrowed code from Cak, feeds people if they hit you. More nutriment but less vitamin to represent BUTTER.
+/mob/living/simple_animal/hostile/bear/butter/on_attack_hand(mob/living/L) //Borrowed code from Cak, feeds people if they hit you. More nutriment but less vitamin to represent BUTTER.
..()
if(L.a_intent == INTENT_HARM && L.reagents && !stat)
L.reagents.add_reagent(/datum/reagent/consumable/nutriment, 1)
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 945842d5ed..5ed3cd0cdd 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -523,9 +523,9 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
if(ranged && ranged_cooldown <= world.time)
target = A
OpenFire(A)
- ..()
-
-
+ DelayNextAction()
+ . = ..()
+ return TRUE
////// AI Status ///////
/mob/living/simple_animal/hostile/proc/AICanContinue(var/list/possible_targets)
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
index 51f61fa158..55046d6555 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
@@ -81,7 +81,7 @@
/obj/structure/leaper_bubble/Initialize()
. = ..()
- float(on = TRUE)
+ INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE)
QDEL_IN(src, 100)
/obj/structure/leaper_bubble/Destroy()
@@ -136,7 +136,7 @@
target = A
if(!isturf(loc))
return
- if(next_move > world.time)
+ if(!CheckActionCooldown())
return
if(hopping)
return
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index 3ef4ef9be9..5c1229c130 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -70,7 +70,7 @@ Difficulty: Medium
/obj/item/melee/transforming/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user)
target.add_stun_absorption("miner", 10, INFINITY)
- ..()
+ . = ..()
target.stun_absorption -= "miner"
/obj/item/projectile/kinetic/miner
@@ -86,8 +86,8 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
var/adjustment_amount = amount * 0.1
- if(world.time + adjustment_amount > next_move)
- changeNext_move(adjustment_amount) //attacking it interrupts it attacking, but only briefly
+ if(world.time + adjustment_amount > next_action)
+ DelayNextAction(adjustment_amount, considered_action = FALSE, flush = TRUE) //attacking it interrupts it attacking, but only briefly
. = ..()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/death()
@@ -109,7 +109,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/AttackingTarget()
if(QDELETED(target))
return
- if(next_move > world.time || !Adjacent(target)) //some cheating
+ if(!CheckActionCooldown() || !Adjacent(target)) //some cheating
INVOKE_ASYNC(src, .proc/quick_attack_loop)
return
face_atom(target)
@@ -125,8 +125,8 @@ Difficulty: Medium
adjustHealth(-(L.maxHealth * 0.5))
L.gib()
return TRUE
- changeNext_move(CLICK_CD_MELEE)
- miner_saw.melee_attack_chain(src, target)
+ miner_saw.melee_attack_chain(src, target, null, ATTACK_IGNORE_CLICKDELAY)
+ FlushCurrentAction()
if(guidance)
adjustHealth(-2)
transform_weapon()
@@ -161,19 +161,19 @@ Difficulty: Medium
face_atom(target)
new /obj/effect/temp_visual/dir_setting/firing_effect(loc, dir)
Shoot(target)
- changeNext_move(CLICK_CD_RANGE)
+ DelayNextAction(CLICK_CD_RANGE, flush = TRUE)
//I'm still of the belief that this entire proc needs to be wiped from existence.
// do not take my touching of it to be endorsement of it. ~mso
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop()
- while(!QDELETED(target) && next_move <= world.time) //this is done this way because next_move can change to be sooner while we sleep.
+ while(!QDELETED(target) && !CheckActionCooldown()) //this is done this way because next_move can change to be sooner while we sleep.
stoplag(1)
- sleep((next_move - world.time) * 1.5) //but don't ask me what the fuck this is about
+ sleep((next_action - world.time) * 1.5) //but don't ask me what the fuck this is about
if(QDELETED(target))
return
- if(dashing || next_move > world.time || !Adjacent(target))
- if(dashing && next_move <= world.time)
- next_move = world.time + 1
+ if(dashing || !CheckActionCooldown() || !Adjacent(target))
+ if(dashing && next_action <= world.time)
+ SetNextAction(1, considered_action = FALSE, immediate = FALSE, flush = TRUE)
INVOKE_ASYNC(src, .proc/quick_attack_loop) //lets try that again.
return
AttackingTarget()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index aa4ff328b5..18abb019d3 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -385,10 +385,7 @@ Difficulty: Very Hard
if(isliving(speaker))
ActivationReaction(speaker, ACTIVATE_SPEECH)
-/obj/machinery/anomalous_crystal/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/anomalous_crystal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
ActivationReaction(user, ACTIVATE_TOUCH)
/obj/machinery/anomalous_crystal/attackby(obj/item/I, mob/user, params)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
index c4f78b6e26..11cc0fe67e 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
@@ -105,7 +105,7 @@ IGNORE_PROC_IF_NOT_TARGET(attack_slime)
/mob/living/simple_animal/hostile/asteroid/curseblob/attacked_by(obj/item/I, mob/living/L, attackchain_flags = NONE, damage_multiplier = 1)
if(L != set_target)
- L.changeNext_move(I.click_delay) //pre_attacked_by not called
+ I.ApplyAttackCooldown(L, src)
return
return ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
index 982b91c2c9..87ec79abcf 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
@@ -148,7 +148,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
desc = "You're not quite sure how a signal can be menacing."
invisibility = 100
-/obj/structure/elite_tumor/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/elite_tumor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(ishuman(user))
switch(activity)
diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm
index 4c9afd3784..9101430ccc 100644
--- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm
@@ -170,7 +170,7 @@
Bruise()
..()
-/mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M)
+/mob/living/simple_animal/hostile/mushroom/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) // the attack was blocked
return
diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
index 3620e3ee5f..e21e3e0693 100644
--- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm
+++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
@@ -86,7 +86,7 @@
.=..()
START_PROCESSING(SSprocessing, src)
-/obj/structure/spawner/nether/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/spawner/nether/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
user.visible_message("[user] is violently pulled into the link!", \
"Touching the portal, you are quickly pulled through into a world of unimaginable horror!")
contents.Add(user)
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index 03aac4037a..dec2159dc0 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -37,6 +37,10 @@
var/banana_type = /obj/item/grown/bananapeel
var/attack_reagent
+/mob/living/simple_animal/hostile/retaliate/clown/Initialize(mapload)
+ . = ..()
+ faction |= "clown"
+
/mob/living/simple_animal/hostile/retaliate/clown/handle_temperature_damage()
if(bodytemperature < minbodytemp)
adjustBruteLoss(10)
@@ -47,7 +51,7 @@
else
clear_alert("temp")
-/mob/living/simple_animal/hostile/retaliate/clown/attack_hand(mob/living/carbon/human/M)
+/mob/living/simple_animal/hostile/retaliate/clown/on_attack_hand(mob/living/carbon/human/M)
..()
playsound(src.loc, 'sound/items/bikehorn.ogg', 50, TRUE)
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 4ea8a3c5dc..fd37bb26aa 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -79,7 +79,7 @@
melee_damage_upper = 15
wound_bonus = -10
bare_wound_bonus = 20
- sharpness = TRUE
+ sharpness = SHARP_EDGED
icon_state = "syndicate_knife"
icon_living = "syndicate_knife"
loot = list(/obj/effect/gibspawner/human)
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index de8a6fb6a0..4fcb1ed5bf 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -271,7 +271,7 @@
* Attack responces
*/
//Humans, monkeys, aliens
-/mob/living/simple_animal/parrot/attack_hand(mob/living/carbon/M)
+/mob/living/simple_animal/parrot/on_attack_hand(mob/living/carbon/M)
..()
if(client)
return
diff --git a/code/modules/mob/living/simple_animal/pickle.dm b/code/modules/mob/living/simple_animal/pickle.dm
index c5469024e6..78c524fed9 100644
--- a/code/modules/mob/living/simple_animal/pickle.dm
+++ b/code/modules/mob/living/simple_animal/pickle.dm
@@ -20,12 +20,12 @@
laugher.emote("laugh")
/mob/living/simple_animal/pickle/death()
- ..()
if(original_body)
original_body.adjustOrganLoss(ORGAN_SLOT_BRAIN, 200) //to be fair, you have to have a very high iq to understand-
original_body.forceMove(get_turf(src))
if(mind)
mind.transfer_to(original_body)
+ ..()
/mob/living/simple_animal/pickle/wabbajack_act() //restore users name before its used on the new mob
if(original_body)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 1102559aca..706bcc46f5 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -145,7 +145,7 @@
//How much bare wounding power it has
var/bare_wound_bonus = 0
//If the attacks from this are sharp
- var/sharpness = FALSE
+ var/sharpness = SHARP_NONE
/mob/living/simple_animal/Initialize()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index f7876b3516..1bdd988694 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -296,7 +296,7 @@
discipline_slime(user)
return ..()
-/mob/living/simple_animal/slime/attack_hand(mob/living/carbon/human/M)
+/mob/living/simple_animal/slime/on_attack_hand(mob/living/carbon/human/M)
if(buckled)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if(buckled == M)
@@ -356,7 +356,7 @@
attacked += 10
if(prob(25))
user.do_attack_animation(src)
- user.changeNext_move(CLICK_CD_MELEE)
+ W.ApplyAttackCooldown(user, src)
to_chat(user, "[W] passes right through [src]!")
return
if(Discipline && prob(50)) // wow, buddy, why am I getting attacked??
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index 0029300936..87fd0cf609 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -500,6 +500,15 @@
S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating)
return S
+///////////////////////////////// OFF BALANCE/SHOVIES ////////////////////////
+/mob/living/proc/ShoveOffBalance(amount)
+ var/datum/status_effect/off_balance/B = has_status_effect(STATUS_EFFECT_OFF_BALANCE)
+ if(B)
+ B.duration = max(world.time + amount, B.duration)
+ else if(amount > 0)
+ B = apply_status_effect(STATUS_EFFECT_OFF_BALANCE, amount)
+ return B
+
///////////////////////////////// FROZEN /////////////////////////////////////
/mob/living/proc/IsFrozen()
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index b7546becd8..31bfb5621f 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -13,9 +13,7 @@
hud_used.show_hud(hud_used.hud_version)
hud_used.update_ui_style(ui_style2icon(client.prefs.UI_style))
- next_move = 1
-
- ..()
+ . = ..()
reset_perspective(loc)
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 0eff65fda3..03a3ab1001 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -11,6 +11,10 @@
blocks_emissive = EMISSIVE_BLOCK_GENERIC
vis_flags = VIS_INHERIT_PLANE //when this be added to vis_contents of something it inherit something.plane, important for visualisation of mob in openspace.
+
+ attack_hand_is_action = TRUE
+ attack_hand_unwieldlyness = CLICK_CD_MELEE
+ attack_hand_speed = 0
/// What receives our keyboard input. src by default.
var/datum/focus
@@ -35,7 +39,6 @@
var/list/logging = list()
var/atom/machine = null
- var/next_move = null
var/create_area_cooldown
/// Whether or not the mob is currently being transformed into another mob or into another state of being. This will prevent it from moving or doing realistically anything.
/// Don't you DARE use this for a cheap way to ensure someone is stunned in your code.
@@ -158,4 +161,4 @@
/// The timer that will remove our indicator for early aborts (like when an user finishes their message)
var/typing_indicator_timerid
/// Current state of our typing indicator. Used for cut overlay, DO NOT RUNTIME ASSIGN OTHER THAN FROM SHOW/CLEAR. Used to absolutely ensure we do not get stuck overlays.
- var/typing_indicator_current
+ var/mutable_appearance/typing_indicator_current
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index 3ceafe4a11..7d97270808 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -43,6 +43,11 @@
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "Speech is currently admin-disabled.")
return
+
+ if(length(message) > MAX_MESSAGE_LEN)
+ to_chat(usr, message)
+ to_chat(usr, "^^^----- The preceeding message has been DISCARDED for being over the maximum length of [MAX_MESSAGE_LEN]. It has NOT been sent! -----^^^")
+ return
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
clear_typing_indicator() // clear it immediately!
diff --git a/code/modules/mob/say_vr.dm b/code/modules/mob/say_vr.dm
index 5ed24af726..5db3ccf216 100644
--- a/code/modules/mob/say_vr.dm
+++ b/code/modules/mob/say_vr.dm
@@ -37,7 +37,7 @@ proc/get_top_level_mob(var/mob/S)
to_chat(user, "You cannot send IC messages (muted).")
return FALSE
else if(!params)
- var/subtle_emote = stripped_multiline_input(user, "Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN)
+ var/subtle_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN)
if(subtle_emote && !check_invalid(user, subtle_emote))
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
switch(type)
@@ -98,7 +98,7 @@ proc/get_top_level_mob(var/mob/S)
to_chat(user, "You cannot send IC messages (muted).")
return FALSE
else if(!params)
- var/subtle_emote = stripped_multiline_input(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN)
+ var/subtle_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN)
if(subtle_emote && !check_invalid(user, subtle_emote))
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
switch(type)
diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm
index f28cbe4385..6154828f4d 100644
--- a/code/modules/mob/typing_indicator.dm
+++ b/code/modules/mob/typing_indicator.dm
@@ -15,13 +15,23 @@ GLOBAL_LIST_EMPTY(typing_indicator_overlays)
/mob/proc/get_typing_indicator_icon_state()
return typing_indicator_state
+/// Generates the mutable appearance for typing indicator. Should prevent stuck overlays.
+/mob/proc/generate_typing_indicator()
+ var/state = get_typing_indicator_icon_state()
+ if(ispath(state))
+ var/atom/thing = new state(null)
+ var/mutable_appearance/generated = new(thing)
+ return generated
+ else
+ CRASH("Unsupported typing indicator state: [state]")
+
/**
* Displays typing indicator.
* @param timeout_override - Sets how long until this will disappear on its own without the user finishing their message or logging out. Defaults to src.typing_indicator_timeout
* @param state_override - Sets the state that we will fetch. Defaults to src.get_typing_indicator_icon_state()
* @param force - shows even if src.typing_indcator_enabled is FALSE.
*/
-/mob/proc/display_typing_indicator(timeout_override = TYPING_INDICATOR_TIMEOUT, state_override = get_typing_indicator_icon_state(), force = FALSE)
+/mob/proc/display_typing_indicator(timeout_override = TYPING_INDICATOR_TIMEOUT, state_override = generate_typing_indicator(), force = FALSE)
if((!typing_indicator_enabled && !force) || typing_indicator_current)
return
typing_indicator_current = state_override
diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm
index 4e4c1fcdce..da4bd3a463 100644
--- a/code/modules/modular_computers/computers/item/laptop.dm
+++ b/code/modules/modular_computers/computers/item/laptop.dm
@@ -64,10 +64,8 @@
return
M.put_in_hand(src, H.held_index)
-/obj/item/modular_computer/laptop/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/modular_computer/laptop/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
- if(.)
- return
if(screen_on && isturf(loc))
return attack_self(user)
diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm
index 89c6166a0d..7e384c3ddd 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -100,7 +100,6 @@
if(cpu)
return cpu.AltClick(user)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
// On-click handling. Turns on the computer if it's off and opens the GUI.
/obj/machinery/modular_computer/interact(mob/user)
if(cpu)
diff --git a/code/modules/movespeed/_movespeed_modifier.dm b/code/modules/movespeed/_movespeed_modifier.dm
index a338919c4b..3bc4463531 100644
--- a/code/modules/movespeed/_movespeed_modifier.dm
+++ b/code/modules/movespeed/_movespeed_modifier.dm
@@ -199,7 +199,13 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
else
continue
. += amt
+ var/old = cached_multiplicative_slowdown // CITAEDL EDIT - To make things a bit less jarring, when in situations where
+ // your delay decreases, "give" the delay back to the client
cached_multiplicative_slowdown = .
+ var/diff = old - cached_multiplicative_slowdown
+ if((diff > 0) && client)
+ if(client.move_delay > world.time + 1.5)
+ client.move_delay -= diff
/// Get the move speed modifiers list of the mob
/mob/proc/get_movespeed_modifiers()
diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm
index a2176ca95e..d17767bb1f 100644
--- a/code/modules/movespeed/modifiers/mobs.dm
+++ b/code/modules/movespeed/modifiers/mobs.dm
@@ -78,9 +78,6 @@
blacklisted_movetypes = FLOATING
variable = TRUE
-/datum/movespeed_modifier/shove
- multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH
-
/datum/movespeed_modifier/human_carry
variable = TRUE
diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm
index e6d53d914f..00cfa94893 100644
--- a/code/modules/ninja/energy_katana.dm
+++ b/code/modules/ninja/energy_katana.dm
@@ -14,7 +14,7 @@
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
block_chance = 50
slot_flags = ITEM_SLOT_BELT
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
max_integrity = 200
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/datum/effect_system/spark_spread/spark_system
diff --git a/code/modules/ninja/suit/gloves.dm b/code/modules/ninja/suit/gloves.dm
index dbe4c80579..a06b753402 100644
--- a/code/modules/ninja/suit/gloves.dm
+++ b/code/modules/ninja/suit/gloves.dm
@@ -67,6 +67,7 @@
to_chat(H, "Gained [DisplayEnergy(.)] of energy from [A].")
else
to_chat(H, "\The [A] has run dry of energy, you must find another source!")
+ . = INTERRUPT_UNARMED_ATTACK
else
. = FALSE //as to not cancel attack_hand()
diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm
index 508722ecf2..57faad9493 100644
--- a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm
+++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm
@@ -14,5 +14,5 @@
/obj/item/throwing_star/ninja
name = "ninja throwing star"
- throwforce = 30
+ throwforce = 20
embedding = list("pain_mult" = 6, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15)
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index b368589bc3..b8f2c95762 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -137,7 +137,7 @@
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
-/obj/structure/filingcabinet/security/attack_hand()
+/obj/structure/filingcabinet/security/on_attack_hand()
populate()
. = ..()
@@ -170,8 +170,7 @@
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/structure/filingcabinet/medical/attack_hand()
+/obj/structure/filingcabinet/medical/on_attack_hand()
populate()
. = ..()
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 462d50eb45..01c25b57f1 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -297,6 +297,7 @@
var/datum/ui_state/default/paper_state/state = new
state.edit_mode = MODE_STAMPING // we are read only becausse the sheet is full
state.stamp_icon_state = P.icon_state
+ state.stamp_name = P.name
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper)
state.stamp_class = sheet.icon_class_name(P.icon_state)
diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm
index 770a6682e0..3937720f74 100644
--- a/code/modules/paperwork/paper_cutter.dm
+++ b/code/modules/paperwork/paper_cutter.dm
@@ -66,10 +66,7 @@
return
..()
-/obj/item/papercutter/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/item/papercutter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
add_fingerprint(user)
if(!storedcutter)
to_chat(user, "The cutting blade is gone! You can't use [src] now.")
diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm
index d1141c9f70..28cb5ffae9 100644
--- a/code/modules/paperwork/paperbin.dm
+++ b/code/modules/paperwork/paperbin.dm
@@ -11,6 +11,8 @@
throw_speed = 3
throw_range = 7
pressure_resistance = 8
+ attack_hand_speed = CLICK_CD_RAPID
+ attack_hand_is_action = TRUE
var/papertype = /obj/item/paper
var/total_paper = 30
var/list/papers = list()
@@ -60,11 +62,9 @@
/obj/item/paper_bin/attack_paw(mob/user)
return attack_hand(user)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/paper_bin/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/paper_bin/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.lying)
return
- user.changeNext_move(CLICK_CD_MELEE)
if(bin_pen)
var/obj/item/pen/P = bin_pen
P.add_fingerprint(user)
@@ -148,7 +148,7 @@
papertype = /obj/item/paper/natural
resistance_flags = FLAMMABLE
-/obj/item/paper_bin/bundlenatural/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/paper_bin/bundlenatural/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
..()
if(total_paper < 1)
qdel(src)
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 08252d4e05..997ada6b21 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -28,6 +28,7 @@
var/degrees = 0
var/font = PEN_FONT
embedding = list()
+ sharpness = SHARP_POINTY
/obj/item/pen/suicide_act(mob/user)
user.visible_message("[user] is scribbling numbers all over [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit sudoku...")
@@ -84,7 +85,7 @@
throw_speed = 4
colour = "crimson"
custom_materials = list(/datum/material/gold = 750)
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
resistance_flags = FIRE_PROOF
unique_reskin = list("Oak" = "pen-fountain-o",
"Gold" = "pen-fountain-g",
@@ -180,7 +181,7 @@
*/
/obj/item/pen/edagger
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") //these wont show up if the pen is off
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
var/on = FALSE
embedding = list(embed_chance = EMBED_CHANCE)
diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm
index 3e76fc874a..b925c67940 100644
--- a/code/modules/photography/camera/camera.dm
+++ b/code/modules/photography/camera/camera.dm
@@ -221,4 +221,4 @@
p.set_picture(picture, TRUE, TRUE)
if(CONFIG_GET(flag/picture_logging_camera))
- picture.log_to_file()
\ No newline at end of file
+ picture.log_to_file()
diff --git a/code/modules/photography/photos/frame.dm b/code/modules/photography/photos/frame.dm
index 6f7bc643c8..d306c46815 100644
--- a/code/modules/photography/photos/frame.dm
+++ b/code/modules/photography/photos/frame.dm
@@ -21,8 +21,7 @@
to_chat(user, "\The [src] already contains a photo.")
..()
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/wallframe/picture/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/wallframe/picture/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.get_inactive_held_item() != src)
..()
return
@@ -141,10 +140,7 @@
..()
-/obj/structure/sign/picture_frame/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/structure/sign/picture_frame/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(framed)
framed.show(user)
diff --git a/code/modules/pool/pool_drain.dm b/code/modules/pool/pool_drain.dm
index 8deb9b1ffe..527c25b9f0 100644
--- a/code/modules/pool/pool_drain.dm
+++ b/code/modules/pool/pool_drain.dm
@@ -154,7 +154,7 @@
else
new /mob/living/simple_animal/hostile/shark/laser(loc)
-/obj/machinery/pool/filter/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/pool/filter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
to_chat(user, "You search the filter.")
for(var/obj/O in contents)
O.forceMove(loc)
diff --git a/code/modules/pool/pool_main.dm b/code/modules/pool/pool_main.dm
index 30d1744b57..98189cc8a4 100644
--- a/code/modules/pool/pool_main.dm
+++ b/code/modules/pool/pool_main.dm
@@ -177,7 +177,7 @@
else
return ..()
-/turf/open/pool/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/turf/open/pool/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/pool/pool_structures.dm b/code/modules/pool/pool_structures.dm
index 6b71e95639..ec5d455958 100644
--- a/code/modules/pool/pool_structures.dm
+++ b/code/modules/pool/pool_structures.dm
@@ -11,7 +11,7 @@
layer = ABOVE_MOB_LAYER
dir = EAST
-/obj/structure/pool/ladder/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/pool/ladder/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
@@ -52,7 +52,7 @@
user.pixel_x = initial_px
user.pixel_y = initial_py
-/obj/structure/pool/Lboard/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/pool/Lboard/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
var/mob/living/carbon/jumper = user
if(jumping)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 3f9ca4f1b7..ba51eb3bef 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -38,6 +38,8 @@
#define APC_CHARGING 1
#define APC_FULLY_CHARGED 2
+#define MAXIMUM_COG_REGAIN 100 //How much charge drained by an integration cog can be priority-recharged in one processing-tick
+
// the Area Power Controller (APC), formerly Power Distribution Unit (PDU)
// one per area, needs wire connection to power network through a terminal
@@ -94,6 +96,7 @@
var/mob/living/silicon/ai/occupier = null
var/transfer_in_progress = FALSE //Is there an AI being transferred out of us?
var/obj/item/clockwork/integration_cog/integration_cog //Is there a cog siphoning power?
+ var/cog_drained = 0 //How much of the cell's charge was drained by an integration cog, recovering this amount takes priority over the normal APC cell recharge calculations, but comes after powering Essentials.
var/longtermpower = 10
var/auto_name = 0
var/failure_timer = 0
@@ -499,6 +502,7 @@
cell.forceMove(T)
cell.update_icon()
cell = null
+ cog_drained = 0 //No more cell means no more averting celldrain
charging = APC_NOT_CHARGING
update_icon()
return
@@ -701,7 +705,7 @@
START_PROCESSING(SSfastprocess, W)
playsound(src, 'sound/machines/clockcult/steam_whoosh.ogg', 50, FALSE)
opened = APC_COVER_CLOSED
- locked = FALSE
+ locked = TRUE //Clockies get full APC access on cogged APCs, but they can't lock or unlock em unless they steal some ID to give all of them APC access, soo this is pretty much just QoL for them and makes cogs a tiny bit more stealthy
update_icon()
return
else if(panel_open && !opened && is_wire_tool(W))
@@ -833,10 +837,7 @@
// attack with hand - remove cell (if cover open) or interact with the APC
-/obj/machinery/power/apc/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/power/apc/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(opened && (!issilicon(user)))
if(cell)
user.visible_message("[user] removes \the [cell] from [src]!","You remove \the [cell].")
@@ -1314,6 +1315,11 @@
cur_used -= lastused_light
lighting_satisfied = TRUE
+ //If drained by an integration cog: Forcefully avert as much of the powerdrain as possible, though a maximum of MAXIMUM_COG_REGAIN
+ if(cur_excess && cog_drained && cell)
+ var/cog_regain = cell.give(min(min(cog_drained, cur_excess), MAXIMUM_COG_REGAIN))
+ cur_excess -= cog_regain
+ cog_drained = max(0, cog_drained - cog_regain)
// next: take from or charge to the cell, depending on how much is left
if(cell && !shorted)
@@ -1576,6 +1582,8 @@
#undef APC_UPOVERLAY_LOCKED
#undef APC_UPOVERLAY_OPERATING
+#undef MAXIMUM_COG_REGAIN
+
/*Power module, used for APC construction*/
/obj/item/electronics/apc
name = "power control module"
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index c8b02669e8..6dcb08512c 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -564,10 +564,7 @@ By design, d1 is the smallest direction and d2 is the highest
icon_state = "[initial(item_state)][amount < 3 ? amount : ""]"
name = "cable [amount < 3 ? "piece" : "coil"]"
-/obj/item/stack/cable_coil/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/item/stack/cable_coil/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
var/obj/item/stack/cable_coil/new_cable = ..()
if(istype(new_cable))
new_cable.color = color
diff --git a/code/modules/power/floodlight.dm b/code/modules/power/floodlight.dm
index 2bd4c04402..466030b83c 100644
--- a/code/modules/power/floodlight.dm
+++ b/code/modules/power/floodlight.dm
@@ -92,10 +92,7 @@
else
. = ..()
-/obj/machinery/power/floodlight/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/power/floodlight/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
var/current = setting
if(current == 1)
current = light_setting_list.len
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index 76154907ae..30a7aa152b 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -80,7 +80,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
/obj/machinery/gravity_generator/part/get_status()
return main_part?.get_status()
-/obj/machinery/gravity_generator/part/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/gravity_generator/part/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
return main_part.attack_hand(user)
/obj/machinery/gravity_generator/part/set_broken()
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index f911a6a4e4..20f7ce099a 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -595,11 +595,9 @@
// attack with hand - remove tube/bulb
// if hands aren't protected and the light is on, burn the player
-/obj/machinery/light/attack_hand(mob/living/carbon/human/user)
+/obj/machinery/light/on_attack_hand(mob/living/carbon/human/user)
. = ..()
- if(.)
- return
- user.changeNext_move(CLICK_CD_MELEE)
+ user.DelayNextAction(CLICK_CD_MELEE)
add_fingerprint(user)
if(status == LIGHT_EMPTY)
@@ -812,11 +810,11 @@
return
/obj/item/light/attack(mob/living/M, mob/living/user, def_zone)
- ..()
+ . = ..()
shatter()
/obj/item/light/attack_obj(obj/O, mob/living/user)
- ..()
+ . = ..()
shatter()
/obj/item/light/proc/shatter()
diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm
index 4cc9cbe34f..256b13ee72 100644
--- a/code/modules/power/singularity/collector.dm
+++ b/code/modules/power/singularity/collector.dm
@@ -176,6 +176,7 @@
/obj/machinery/power/rad_collector/analyzer_act(mob/living/user, obj/item/I)
if(loaded_tank)
loaded_tank.analyzer_act(user, I)
+ return TRUE
/obj/machinery/power/rad_collector/examine(mob/user)
. = ..()
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm
index 5ef66e26d9..dfb51df9cf 100644
--- a/code/modules/power/singularity/containment_field.dm
+++ b/code/modules/power/singularity/containment_field.dm
@@ -21,8 +21,7 @@
FG2.fields -= src
return ..()
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/machinery/field/containment/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/field/containment/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(get_dist(src, user) > 1)
return FALSE
else
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 0d182e0a1b..50dae7d6bb 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -315,6 +315,9 @@
/obj/machinery/power/emitter/proc/integrate(obj/item/gun/energy/E,mob/user)
if(istype(E, /obj/item/gun/energy))
+ if(!E.can_emitter)
+ to_chat(user, "[E] cannot fit into emitters.")
+ return
if(!user.transferItemToLoc(E, src))
return
gun = E
diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
index e33116b02c..528a3abb8b 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
@@ -103,7 +103,6 @@
did_something = TRUE
if(did_something)
- user.changeNext_move(CLICK_CD_MELEE)
update_state()
update_icon()
return
diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm
index beaf4bfc43..912fc0a72b 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_control.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm
@@ -246,7 +246,6 @@
did_something = TRUE
if(did_something)
- user.changeNext_move(CLICK_CD_MELEE)
update_state()
update_icon()
return
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 96f8b4e996..cc3a19cf55 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -59,7 +59,7 @@
last_failed_movement = direct
return 0
-/obj/singularity/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/singularity/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
consume(user)
return TRUE
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 823ba75e43..8559b8ba45 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -571,7 +571,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
/obj/machinery/power/supermatter_crystal/attack_ai(mob/user)
return
-/obj/machinery/power/supermatter_crystal/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/power/supermatter_crystal/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/projectiles/ammunition/_ammunition.dm b/code/modules/projectiles/ammunition/_ammunition.dm
index ee6a25d8e4..6a73d9a366 100644
--- a/code/modules/projectiles/ammunition/_ammunition.dm
+++ b/code/modules/projectiles/ammunition/_ammunition.dm
@@ -16,7 +16,8 @@
var/variance = 0 //Variance for inaccuracy fundamental to the casing
var/randomspread = 0 //Randomspread for automatics
var/delay = 0 //Delay for energy weapons
- var/click_cooldown_override = 0 //Override this to make your gun have a faster fire rate, in tenths of a second. 4 is the default gun cooldown.
+ /// Override this to make the gun check for a different cooldown rather than CLICK_CD_RANGE, which is 4 deciseconds.
+ var/click_cooldown_override
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the ammo is fired.
var/heavy_metal = TRUE
var/harmful = TRUE //pacifism check for boolet, set to FALSE if bullet is non-lethal
diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm
index 340cfc2e98..0ef4c680aa 100644
--- a/code/modules/projectiles/ammunition/_firing.dm
+++ b/code/modules/projectiles/ammunition/_firing.dm
@@ -16,10 +16,7 @@
AddComponent(/datum/component/pellet_cloud, projectile_type, pellets)
SEND_SIGNAL(src, COMSIG_PELLET_CLOUD_INIT, target, user, fired_from, randomspread, spread, zone_override, params, distro)
- if(click_cooldown_override)
- user.changeNext_move(click_cooldown_override)
- else
- user.changeNext_move(CLICK_CD_RANGE)
+ user.DelayNextAction(considered_action = TRUE, immediate = FALSE)
user.newtonian_move(get_dir(target, user))
update_icon()
return 1
diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
index e4674f4f4c..987efc0404 100644
--- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
+++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
@@ -47,7 +47,7 @@
/obj/item/ammo_box/c38/dumdum
name = "speed loader (.38 DumDum)"
- desc = "Designed to quickly reload revolvers. DumDum bullets shatter on impact and shred the target's innards, likely getting caught inside."
+ desc = "Designed to quickly reload revolvers. These rounds expand on impact, allowing them to shred the target and cause massive bleeding. Very weak against armor and distant targets."
ammo_type = /obj/item/ammo_casing/c38/dumdum
/obj/item/ammo_box/c38/match
diff --git a/code/modules/projectiles/boxes_magazines/external/shotgun.dm b/code/modules/projectiles/boxes_magazines/external/shotgun.dm
index 1001937678..ed41375aee 100644
--- a/code/modules/projectiles/boxes_magazines/external/shotgun.dm
+++ b/code/modules/projectiles/boxes_magazines/external/shotgun.dm
@@ -1,5 +1,5 @@
/obj/item/ammo_box/magazine/m12g
- name = "shotgun magazine (12g buckshot slugs)"
+ name = "shotgun magazine (12g buckshot)"
desc = "A drum magazine."
icon_state = "m12gb"
ammo_type = /obj/item/ammo_casing/shotgun/buckshot
@@ -17,7 +17,7 @@
/obj/item/ammo_box/magazine/m12g/slug
name = "shotgun magazine (12g slugs)"
- icon_state = "m12gb" //this may need an unique sprite
+ icon_state = "m12gsl"
ammo_type = /obj/item/ammo_casing/shotgun
/obj/item/ammo_box/magazine/m12g/dragon
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index f34343debd..c3248bab2f 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -17,6 +17,7 @@
force = 5
item_flags = NEEDS_PERMIT
attack_verb = list("struck", "hit", "bashed")
+ attack_speed = CLICK_CD_RANGE
var/fire_sound = "gunshot"
var/suppressed = null //whether or not a message is displayed when fired
@@ -28,6 +29,13 @@
trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers
var/sawn_desc = null //description change if weapon is sawn-off
var/sawn_off = FALSE
+
+ /// can we be put into a turret
+ var/can_turret = TRUE
+ /// can we be put in a circuit
+ var/can_circuit = TRUE
+ /// can we be put in an emitter
+ var/can_emitter = TRUE
/// Weapon is burst fire if this is above 1
var/burst_size = 1
@@ -166,6 +174,8 @@
/obj/item/gun/afterattack(atom/target, mob/living/user, flag, params)
. = ..()
+ if(!CheckAttackCooldown(user, target))
+ return
process_afterattack(target, user, flag, params)
/obj/item/gun/proc/process_afterattack(atom/target, mob/living/user, flag, params)
@@ -174,19 +184,17 @@
if(firing)
return
var/stamloss = user.getStaminaLoss()
- if(stamloss >= STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
- var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_GUN_DELAY
- user.changeNext_move(CLICK_CD_RANGE+(CLICK_CD_RANGE*penalty))
if(flag) //It's adjacent, is the user, or is on the user's person
if(target in user.contents) //can't shoot stuff inside us.
return
if(!ismob(target) || user.a_intent == INTENT_HARM) //melee attack
return
- if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected)
+ if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH && (user.a_intent != INTENT_DISARM)) //so we can't shoot ourselves (unless mouth selected or disarm intent)
return
if(iscarbon(target))
var/mob/living/carbon/C = target
- for(var/datum/wound/W in C.all_wounds)
+ for(var/i in C.all_wounds)
+ var/datum/wound/W = i
if(W.try_treating(src, user))
return // another coward cured!
@@ -218,6 +226,8 @@
to_chat(user, "You need both hands free to fire \the [src]!")
return
+ user.DelayNextAction()
+
//DUAL (or more!) WIELDING
var/bonus_spread = 0
var/loop_counter = 0
@@ -248,6 +258,17 @@
to_chat(user, " [src] is lethally chambered! You don't want to risk harming anyone...")
return FALSE
+/obj/item/gun/CheckAttackCooldown(mob/user, atom/target)
+ if((user.a_intent == INTENT_HARM) && user.Adjacent(target)) //melee
+ return user.CheckActionCooldown(CLICK_CD_MELEE)
+ return user.CheckActionCooldown(get_clickcd())
+
+/obj/item/gun/proc/get_clickcd()
+ return isnull(chambered?.click_cooldown_override)? CLICK_CD_RANGE : chambered.click_cooldown_override
+
+/obj/item/gun/GetEstimatedAttackSpeed()
+ return get_clickcd()
+
/obj/item/gun/proc/handle_pins(mob/living/user)
if(no_pin_required)
return TRUE
@@ -362,17 +383,14 @@
if(user.a_intent == INTENT_HARM) //Flogging
if(bayonet)
M.attackby(bayonet, user)
- attack_delay_done = TRUE
return
else
return ..()
- attack_delay_done = TRUE //we are firing the gun, not bashing people with its butt.
/obj/item/gun/attack_obj(obj/O, mob/user)
if(user.a_intent == INTENT_HARM)
if(bayonet)
- O.attackby(bayonet, user)
- return TRUE
+ return O.attackby(bayonet, user)
return ..()
/obj/item/gun/attackby(obj/item/I, mob/user, params)
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index e5dc056011..fa8099a257 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -97,8 +97,7 @@
w_class += S.w_class //so pistols do not fit in pockets when suppressed
update_icon()
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/gun/ballistic/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/gun/ballistic/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc == user)
if(suppressed && can_unsuppress)
var/obj/item/suppressor/S = suppressed
@@ -180,13 +179,11 @@
#undef BRAINS_BLOWN_THROW_SPEED
#undef BRAINS_BLOWN_THROW_RANGE
-
-
/obj/item/gun/ballistic/proc/sawoff(mob/user)
if(sawn_off)
to_chat(user, "\The [src] is already shortened!")
return
- user.changeNext_move(CLICK_CD_MELEE)
+ user.DelayNextAction(CLICK_CD_MELEE)
user.visible_message("[user] begins to shorten \the [src].", "You begin to shorten \the [src]...")
//if there's any live ammo inside the gun, makes it go off
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index 89e30e765b..b31fd2d1e0 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -327,8 +327,7 @@
. = ..()
update_icon()
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/gun/ballistic/automatic/l6_saw/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/gun/ballistic/automatic/l6_saw/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(loc != user)
..()
return //let them pick it up
diff --git a/code/modules/projectiles/guns/ballistic/laser_gatling.dm b/code/modules/projectiles/guns/ballistic/laser_gatling.dm
index c2dd5bb42d..244bc5b124 100644
--- a/code/modules/projectiles/guns/ballistic/laser_gatling.dm
+++ b/code/modules/projectiles/guns/ballistic/laser_gatling.dm
@@ -29,8 +29,7 @@
/obj/item/minigunpack/process()
overheat = max(0, overheat - heat_diffusion)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/minigunpack/attack_hand(var/mob/living/carbon/user)
+/obj/item/minigunpack/on_attack_hand(var/mob/living/carbon/user)
if(src.loc == user)
if(!armed)
if(user.get_item_by_slot(SLOT_BACK) == src)
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index 289b43a669..a5ed45dd48 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -84,6 +84,11 @@
. = ..()
. += "[get_ammo(0,0)] of those are live rounds."
+/obj/item/gun/ballistic/revolver/syndicate
+ unique_reskin = list("Default" = "revolver",
+ "Silver" = "russianrevolver",
+ "Robust" = "revolvercit")
+
/obj/item/gun/ballistic/revolver/detective
name = "\improper .38 Mars Special"
desc = "A cheap Martian knock-off of a classic law enforcement firearm. Uses .38-special rounds."
@@ -486,4 +491,4 @@
for(var/i = 0, i < ratio, i++)
var/mutable_appearance/charge_bar = mutable_appearance(icon, "[initial(icon_state)]_charge", color = batt_color)
charge_bar.pixel_x = i
- . += charge_bar
\ No newline at end of file
+ . += charge_bar
diff --git a/code/modules/projectiles/guns/ballistic/toy.dm b/code/modules/projectiles/guns/ballistic/toy.dm
index 5cdd773894..1f66cfdf8a 100644
--- a/code/modules/projectiles/guns/ballistic/toy.dm
+++ b/code/modules/projectiles/guns/ballistic/toy.dm
@@ -56,6 +56,7 @@
item_flags = NONE
casing_ejector = FALSE
can_suppress = FALSE
+ weapon_weight = WEAPON_MEDIUM
/obj/item/gun/ballistic/shotgun/toy/process_chamber(mob/living/user, empty_chamber = 0)
..()
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index 6489920b98..20e847326e 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -125,7 +125,7 @@
flags_1 = CONDUCT_1
attack_verb = list("attacked", "slashed", "cut", "sliced")
force = 12
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
inaccuracy_modifier = 0.25
can_charge = 0
diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm
index d700db817c..6c75ac2d4d 100644
--- a/code/modules/projectiles/guns/energy/stun.dm
+++ b/code/modules/projectiles/guns/energy/stun.dm
@@ -24,7 +24,7 @@
ammo_x_offset = 2
// Not enough guns have altfire systems like this yet for this to be a universal framework.
var/last_altfire = 0
- var/altfire_delay = 15
+ var/altfire_delay = CLICK_CD_RANGE
/obj/item/gun/energy/e_gun/advtaser/altafterattack(atom/target, mob/user, proximity_flag, params)
. = TRUE
diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm
index b23b059d89..6ebdc5e7b8 100644
--- a/code/modules/projectiles/guns/magic/staff.dm
+++ b/code/modules/projectiles/guns/magic/staff.dm
@@ -83,7 +83,7 @@
force = 20
armour_penetration = 75
block_chance = 50
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
max_charges = 4
/obj/item/gun/magic/staff/spellblade/Initialize()
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index bcb074023f..fd09aa7f9d 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -29,6 +29,8 @@
ammo_type = list(/obj/item/ammo_casing/energy/beam_rifle/hitscan)
cell_type = /obj/item/stock_parts/cell/beam_rifle
canMouseDown = TRUE
+ can_turret = FALSE
+ can_circuit = FALSE
//Cit changes: beam rifle stats.
slowdown = 1
item_flags = NO_MAT_REDEMPTION | SLOWS_WHILE_IN_HAND | NEEDS_PERMIT
@@ -418,10 +420,10 @@
var/wall_devastate = 0
var/aoe_structure_range = 0
var/aoe_structure_damage = 0
- var/aoe_fire_range = 0
- var/aoe_fire_chance = 0
- var/aoe_mob_range = 0
- var/aoe_mob_damage = 0
+ var/aoe_fire_range = 2
+ var/aoe_fire_chance = 100
+ var/aoe_mob_range = 2
+ var/aoe_mob_damage = 30
var/impact_structure_damage = 0
var/impact_direct_damage = 0
var/turf/cached
diff --git a/code/modules/projectiles/guns/misc/medbeam.dm b/code/modules/projectiles/guns/misc/medbeam.dm
index e841422893..6864dad33e 100644
--- a/code/modules/projectiles/guns/misc/medbeam.dm
+++ b/code/modules/projectiles/guns/misc/medbeam.dm
@@ -47,7 +47,7 @@
if(current_target)
LoseTarget()
- if(!isliving(target))
+ if(!isliving(target) || (user == target))
return
current_target = target
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 1e1559fc6a..43384280d4 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -149,19 +149,25 @@
var/temporary_unstoppable_movement = FALSE
- ///If defined, on hit we create an item of this type then call hitby() on the hit target with this
+ ///If defined, on hit we create an item of this type then call hitby() on the hit target with this, mainly used for embedding items (bullets) in targets
var/shrapnel_type
///If TRUE, hit mobs even if they're on the floor and not our target
var/hit_stunned_targets = FALSE
wound_bonus = CANT_WOUND
+ ///How much we want to drop both wound_bonus and bare_wound_bonus (to a minimum of 0 for the latter) per tile, for falloff purposes
+ var/wound_falloff_tile
+ ///How much we want to drop the embed_chance value, if we can embed, per tile, for falloff purposes
+ var/embed_falloff_tile
/// For telling whether we want to roll for bone breaking or lacerations if we're bothering with wounds
- sharpness = FALSE
+ sharpness = SHARP_NONE
/obj/item/projectile/Initialize()
. = ..()
permutated = list()
decayedRange = range
+ if(embedding)
+ updateEmbedding()
/**
* Artificially modified to be called at around every world.icon_size pixels of movement.
@@ -169,6 +175,11 @@
*/
/obj/item/projectile/proc/Range()
range--
+ if(wound_bonus != CANT_WOUND)
+ wound_bonus += wound_falloff_tile
+ bare_wound_bonus = max(0, bare_wound_bonus + wound_falloff_tile)
+ if(embedding)
+ embedding["embed_chance"] += embed_falloff_tile
if(range <= 0 && loc)
on_range()
@@ -623,7 +634,7 @@
pixel_x = trajectory.return_px()
pixel_y = trajectory.return_py()
else if(T != loc)
- var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 2 + 1
+ var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 5 + 1
while(T != loc)
if(!--safety)
CRASH("[type] took too long (allowed: [CEILING(pixel_increment_amount/world.icon_size,1)*2] moves) to get to its location.")
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 6a081f9b03..b408957aa7 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -8,4 +8,12 @@
flag = "bullet"
hitsound_wall = "ricochet"
impact_effect_type = /obj/effect/temp_visual/impact_effect
- sharpness = TRUE
\ No newline at end of file
+ sharpness = SHARP_POINTY
+ shrapnel_type = /obj/item/shrapnel/bullet
+ embedding = list(embed_chance=15, fall_chance=2, jostle_chance=0, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.5, pain_mult=3, rip_time=10)
+ wound_falloff_tile = -5
+ embed_falloff_tile = -5
+
+/obj/item/projectile/bullet/smite
+ name = "divine retribution"
+ damage = 10
diff --git a/code/modules/projectiles/projectile/bullets/lmg.dm b/code/modules/projectiles/projectile/bullets/lmg.dm
index 2ea1fe7c9a..e3eff6dcb0 100644
--- a/code/modules/projectiles/projectile/bullets/lmg.dm
+++ b/code/modules/projectiles/projectile/bullets/lmg.dm
@@ -25,8 +25,10 @@
/obj/item/projectile/bullet/mm195x129
name = "1.95x129mm bullet"
- damage = 45
+ damage = 40
armour_penetration = 5
+ wound_bonus = -50
+ wound_falloff_tile = 0
/obj/item/projectile/bullet/mm195x129_ap
name = "1.95x129mm armor-piercing bullet"
@@ -35,8 +37,12 @@
/obj/item/projectile/bullet/mm195x129_hp
name = "1.95x129mm hollow-point bullet"
- damage = 60
+ damage = 50
armour_penetration = -60
+ sharpness = SHARP_EDGED
+ wound_bonus = -40
+ bare_wound_bonus = 30
+ wound_falloff_tile = -8
/obj/item/projectile/bullet/incendiary/mm195x129
name = "1.95x129mm incendiary bullet"
diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm
index 38c9c9f7d9..23a749415c 100644
--- a/code/modules/projectiles/projectile/bullets/pistol.dm
+++ b/code/modules/projectiles/projectile/bullets/pistol.dm
@@ -3,11 +3,13 @@
/obj/item/projectile/bullet/c9mm
name = "9mm bullet"
damage = 20
+ embedding = list(embed_chance=15, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
/obj/item/projectile/bullet/c9mm_ap
name = "9mm armor-piercing bullet"
damage = 15
armour_penetration = 40
+ embedding = null
/obj/item/projectile/bullet/incendiary/c9mm
name = "9mm incendiary bullet"
diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm
index c793e9f95e..95d43ba1ce 100644
--- a/code/modules/projectiles/projectile/bullets/revolver.dm
+++ b/code/modules/projectiles/projectile/bullets/revolver.dm
@@ -19,8 +19,9 @@
ricochet_chance = 50
ricochet_auto_aim_angle = 10
ricochet_auto_aim_range = 3
- wound_bonus = -35
- sharpness = TRUE
+ wound_bonus = -20
+ bare_wound_bonus = 10
+ embedding = list(embed_chance=15, fall_chance=2, jostle_chance=2, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=5, rip_time=10)
/obj/item/projectile/bullet/c38/match
name = ".38 Match bullet"
@@ -43,13 +44,21 @@
ricochet_chance = 130
ricochet_decay_damage = 0.8
shrapnel_type = NONE
+ sharpness = SHARP_NONE
+ embedding = null
+// premium .38 ammo from cargo, weak against armor, lower base damage, but excellent at embedding and causing slice wounds at close range
/obj/item/projectile/bullet/c38/dumdum
name = ".38 DumDum bullet"
damage = 15
armour_penetration = -30
ricochets_max = 0
- shrapnel_type = /obj/item/shrapnel/bullet/c38/dumdum
+ sharpness = SHARP_EDGED
+ wound_bonus = 20
+ bare_wound_bonus = 20
+ embedding = list(embed_chance=75, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
+ wound_falloff_tile = -5
+ embed_falloff_tile = -15
/obj/item/projectile/bullet/c38/rubber
name = ".38 rubber bullet"
@@ -102,6 +111,7 @@
/obj/item/projectile/bullet/a357
name = ".357 bullet"
damage = 60
+ wound_bonus = -70
/obj/item/projectile/bullet/a357/ap
name = ".357 armor-piercing bullet"
diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm
index ae1611cb00..ce30f5e787 100644
--- a/code/modules/projectiles/projectile/bullets/rifle.dm
+++ b/code/modules/projectiles/projectile/bullets/rifle.dm
@@ -3,12 +3,15 @@
/obj/item/projectile/bullet/a556
name = "5.56mm bullet"
damage = 35
+ wound_bonus = -40
// 7.62 (Nagant Rifle)
/obj/item/projectile/bullet/a762
name = "7.62 bullet"
damage = 60
+ wound_bonus = -35
+ wound_falloff_tile = 0
/obj/item/projectile/bullet/a762_enchanted
name = "enchanted 7.62 bullet"
diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm
index 6e4a72aff0..69f976d213 100644
--- a/code/modules/projectiles/projectile/bullets/shotgun.dm
+++ b/code/modules/projectiles/projectile/bullets/shotgun.dm
@@ -1,23 +1,26 @@
/obj/item/projectile/bullet/shotgun_slug
name = "12g shotgun slug"
- damage = 60
+ damage = 50
+ sharpness = SHARP_POINTY
+ wound_bonus = 0
/obj/item/projectile/bullet/shotgun_slug/executioner
name = "executioner slug" // admin only, can dismember limbs
- sharpness = TRUE
- wound_bonus = 0
+ sharpness = SHARP_EDGED
+ wound_bonus = 80
/obj/item/projectile/bullet/shotgun_slug/pulverizer
name = "pulverizer slug" // admin only, can crush bones
- sharpness = FALSE
- wound_bonus = 0
+ sharpness = SHARP_NONE
+ wound_bonus = 80
/obj/item/projectile/bullet/shotgun_beanbag
name = "beanbag slug"
damage = 10
stamina = 70
wound_bonus = 20
- sharpness = FALSE
+ sharpness = SHARP_NONE
+ embedding = null
/obj/item/projectile/bullet/incendiary/shotgun
name = "incendiary slug"
@@ -83,18 +86,22 @@
return BULLET_ACT_HIT
/obj/item/projectile/bullet/pellet
- var/tile_dropoff = 0.75
+ var/tile_dropoff = 0.45
var/tile_dropoff_s = 1.25
/obj/item/projectile/bullet/pellet/shotgun_buckshot
name = "buckshot pellet"
- damage = 12.5
- wound_bonus = -10
+ damage = 7.5
+ wound_bonus = 5
+ bare_wound_bonus = 5
+ wound_falloff_tile = -2.5 // low damage + additional dropoff will already curb wounding potential anything past point blank
/obj/item/projectile/bullet/pellet/shotgun_rubbershot
name = "rubbershot pellet"
damage = 2
stamina = 15
+ sharpness = SHARP_NONE
+ embedding = null
/obj/item/projectile/bullet/pellet/Range()
..()
@@ -106,8 +113,10 @@
qdel(src)
/obj/item/projectile/bullet/pellet/shotgun_improvised
- tile_dropoff = 0.55 //Come on it does 6 damage don't be like that.
+ tile_dropoff = 0.35 //Come on it does 6 damage don't be like that.
damage = 6
+ wound_bonus = 0
+ bare_wound_bonus = 7.5
/obj/item/projectile/bullet/pellet/shotgun_improvised/Initialize()
. = ..()
diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm
index eb4c8e9776..5c9d5b92a3 100644
--- a/code/modules/projectiles/projectile/bullets/smg.dm
+++ b/code/modules/projectiles/projectile/bullets/smg.dm
@@ -3,6 +3,8 @@
/obj/item/projectile/bullet/c45
name = ".45 bullet"
damage = 30
+ wound_bonus = -10
+ wound_falloff_tile = -10
/obj/item/projectile/bullet/c45_cleaning
name = ".45 bullet"
@@ -51,11 +53,15 @@
/obj/item/projectile/bullet/c46x30mm
name = "4.6x30mm bullet"
damage = 15
+ wound_bonus = -5
+ bare_wound_bonus = 5
+ embed_falloff_tile = -4
/obj/item/projectile/bullet/c46x30mm_ap
name = "4.6x30mm armor-piercing bullet"
damage = 12.5
armour_penetration = 40
+ embedding = null
/obj/item/projectile/bullet/incendiary/c46x30mm
name = "4.6x30mm incendiary bullet"
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index 385a82baa5..4034759c72 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -1962,12 +1962,12 @@ All effects don't start immediately, but rather get worse over time; the rate is
/datum/reagent/consumable/ethanol/bug_spray/on_mob_life(mob/living/carbon/M)
//Bugs should not drink Bug spray.
- if(ismoth(M) || isflyperson(M))
+ if(isinsect(M) || isflyperson(M))
M.adjustToxLoss(1,0)
return ..()
/datum/reagent/consumable/ethanol/bug_spray/on_mob_add(mob/living/carbon/M)
- if(ismoth(M) || isflyperson(M))
+ if(isinsect(M) || isflyperson(M))
M.emote("scream")
return ..()
@@ -2270,25 +2270,29 @@ All effects don't start immediately, but rather get worse over time; the rate is
////////////////////
//Race-Base-Drinks//
////////////////////
+/datum/reagent/consumable/ethanol/species_drink
+ var/species_required
+ var/disgust = 25
+ boozepwr = 50
-/datum/reagent/consumable/ethanol/coldscales
+/datum/reagent/consumable/ethanol/species_drink/on_mob_life(mob/living/carbon/C)
+ if(C.dna.species && C.dna.species.species_type == species_required) //species have a species_type variable that refers to one of the drinks
+ quality = RACE_DRINK
+ else
+ C.adjust_disgust(disgust)
+
+/datum/reagent/consumable/ethanol/species_drink/coldscales
name = "Coldscales"
color = "#5AEB52" //(90, 235, 82)
description = "A cold looking drink made for people with scales."
- boozepwr = 50 //strong!
taste_description = "dead flies"
glass_icon_state = "coldscales"
glass_name = "glass of Coldscales"
glass_desc = "A soft green drink that looks inviting!"
-/datum/reagent/consumable/ethanol/coldscales/on_mob_life(mob/living/carbon/M)
- if(islizard(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "lizard"
-/datum/reagent/consumable/ethanol/oil_drum
+/datum/reagent/consumable/ethanol/species_drink/oil_drum
name = "Oil Drum"
color = "#000000" //(0, 0, 0)
description = "Industrial grade oil mixed with some ethanol to make it a drink. Somehow not known to be toxic."
@@ -2298,31 +2302,20 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Drum of oil"
glass_desc = "A gray can of booze and oil..."
-/datum/reagent/consumable/ethanol/oil_drum/on_mob_life(mob/living/carbon/M)
- if(isipcperson(M) || issynthliz(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "robot"
-/datum/reagent/consumable/ethanol/nord_king
+/datum/reagent/consumable/ethanol/species_drink/nord_king
name = "Nord King"
color = "#EB1010" //(235, 16, 16)
description = "Strong mead mixed with more honey and ethanol. Beloved by its human patrons."
- boozepwr = 50 //strong!
taste_description = "honey and red wine"
glass_icon_state = "nord_king"
glass_name = "Keg of Nord King"
glass_desc = "A dripping keg of red mead."
-/datum/reagent/consumable/ethanol/nord_king/on_mob_life(mob/living/carbon/M)
- if(ishumanbasic(M) || isdwarf(M) || isangel(M)) //Humans and angel races are rare
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "basic"
-/datum/reagent/consumable/ethanol/velvet_kiss
+/datum/reagent/consumable/ethanol/species_drink/velvet_kiss
name = "Velvet Kiss"
color = "#EB1010" //(235, 16, 16)
description = "A bloody drink mixed with wine."
@@ -2332,14 +2325,9 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of Velvet Kiss"
glass_desc = "Red and white drink for the upper classes or undead."
-/datum/reagent/consumable/ethanol/velvet_kiss/on_mob_life(mob/living/carbon/M)
- if(iszombie(M) || isvampire(M) || isdullahan(M)) //Rare races!
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "undead"
-/datum/reagent/consumable/ethanol/abduction_fruit
+/datum/reagent/consumable/ethanol/species_drink/abduction_fruit
name = "Abduction Fruit"
color = "#DEFACD" //(222, 250, 205)
description = "Mixing of juices to make an alien taste."
@@ -2349,14 +2337,9 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of Abduction Fruit"
glass_desc = "Mixed fruits that were never meant to be mixed..."
-/datum/reagent/consumable/ethanol/abduction_fruit/on_mob_life(mob/living/carbon/M)
- if(isabductor(M) || isxenoperson(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "alien"
-/datum/reagent/consumable/ethanol/bug_zapper
+/datum/reagent/consumable/ethanol/species_drink/bug_zapper
name = "Bug Zapper"
color = "#F5882A" //(222, 250, 205)
description = "Copper and lemon juice. Hardly even a drink."
@@ -2366,14 +2349,9 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of Bug Zapper"
glass_desc = "An odd mix of copper, lemon juice and power meant for non-human consumption."
-/datum/reagent/consumable/ethanol/bug_zapper/on_mob_life(mob/living/carbon/M)
- if(isinsect(M) || isflyperson(M) || ismoth(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "bug"
-/datum/reagent/consumable/ethanol/mush_crush
+/datum/reagent/consumable/ethanol/species_drink/mush_crush
name = "Mush Crush"
color = "#F5882A" //(222, 250, 205)
description = "Soil in a glass."
@@ -2383,14 +2361,9 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of Mush Crush"
glass_desc = "Popular among people that want to grow their own food rather than drink the soil."
-/datum/reagent/consumable/ethanol/mush_crush/on_mob_life(mob/living/carbon/M)
- if(ispodperson(M) || ismush(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "plant"
-/datum/reagent/consumable/ethanol/darkbrew
+/datum/reagent/consumable/ethanol/species_drink/darkbrew
name = "Darkbrew"
color = "#000000" //(0, 0, 0)
description = "Contained dark matter mixed with coffee."
@@ -2400,31 +2373,21 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of Darkbrew"
glass_desc = "A pitch black drink that's commonly confused with a type of coffee."
-/datum/reagent/consumable/ethanol/darkbrew/on_mob_life(mob/living/carbon/M)
- if(isshadow(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "shadow"
-/datum/reagent/consumable/ethanol/hollow_bone
+/datum/reagent/consumable/ethanol/species_drink/hollow_bone
name = "Hollow Bone"
color = "#FCF7D4" //(252, 247, 212)
- description = "Shockingly none-harmful mix of toxins and milk."
+ description = "Shockingly non-harmful mix of toxins and milk."
boozepwr = 15
taste_description = "Milk and salt"
glass_icon_state = "hollow_bone"
glass_name = "skull of Hollow Bone"
- glass_desc = "Mixing of milk and bone hurting juice for enjoyment for rather skinny people."
+ glass_desc = "Mixing of milk and bone hurting juice for the enjoyment of rather skinny people."
-/datum/reagent/consumable/ethanol/hollow_bone/on_mob_life(mob/living/carbon/M)
- if(isplasmaman(M) || isskeleton(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "skeleton"
-/datum/reagent/consumable/ethanol/frisky_kitty
+/datum/reagent/consumable/ethanol/species_drink/frisky_kitty
name = "Frisky Kitty"
color = "#FCF7D4" //(252, 247, 212)
description = "Warm milk mixed with a catnip."
@@ -2434,14 +2397,9 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "cup of Drisky Kitty"
glass_desc = "Warm milk and some catnip."
-/datum/reagent/consumable/ethanol/frisky_kitty/on_mob_life(mob/living/carbon/M)
- if(ismammal(M) || iscatperson(M)) //well its not to bad for mammals
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "furry"
-/datum/reagent/consumable/ethanol/jell_wyrm
+/datum/reagent/consumable/ethanol/species_drink/jell_wyrm
name = "Jell Wyrm"
color = "#FF6200" //(255, 98, 0)
description = "Horrible mix of Co2, toxins and heat. Meant for slime based life."
@@ -2451,15 +2409,9 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of Jell Wyrm"
glass_desc = "A bubbly drink that is rather inviting to those that don't know who it's meant for."
-/datum/reagent/consumable/ethanol/jell_wyrm/on_mob_life(mob/living/carbon/M)
- if(isjellyperson(M) || isstartjelly(M) || isslimeperson(M) || isluminescent(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- M.adjustToxLoss(1, 0) //Low tox due to being carp + jell toxins.
- return ..()
+ species_required = "jelly"
-/datum/reagent/consumable/ethanol/laval_spit //Yes Laval
+/datum/reagent/consumable/ethanol/species_drink/laval_spit //Yes Laval
name = "Laval Spit"
color = "#DE3009" //(222, 48, 9)
description = "Heat minerals and some mauna loa. Meant for rock based life."
@@ -2469,15 +2421,10 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of Laval Spit"
glass_desc = "Piping hot drink for those who can stomach the heat of lava."
-/datum/reagent/consumable/ethanol/laval_spit/on_mob_life(mob/living/carbon/M)
- if(isgolem(M))
- quality = RACE_DRINK
- else
- M.adjust_disgust(25)
- return ..()
+ species_required = "golem"
///////////////
-//Barrle Wine//
+//Barrel Wine//
///////////////
/datum/reagent/consumable/ethanol/fruit_wine
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index 0c3de579b6..103061088e 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -217,6 +217,9 @@
/datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M)
if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER))
M.heal_bodypart_damage(1.5,0, 0)
+ for(var/i in M.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(2)
. = 1
else
if(M.getBruteLoss() && prob(20))
@@ -320,6 +323,83 @@
..()
. = 1
+/datum/reagent/consumable/tea/red
+ name = "Red Tea"
+ description = "Tasty red tea, helps the body digest food. Drink in moderation!"
+ color = "#101000" // rgb: 16, 16, 0
+ nutriment_factor = 0
+ taste_description = "sweet red tea"
+ glass_icon_state = "teaglass"
+ glass_name = "glass of red tea"
+ glass_desc = "A piping hot tea that helps with the digestion of food."
+
+/datum/reagent/consumable/tea/red/on_mob_life(mob/living/carbon/M)
+ if(M.nutrition > NUTRITION_LEVEL_HUNGRY)
+ M.adjust_nutrition(-3)
+ M.dizziness = max(0,M.dizziness-2)
+ M.drowsyness = max(0,M.drowsyness-1)
+ M.jitteriness = max(0,M.jitteriness-3)
+ M.adjust_bodytemperature(23 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
+ . = 1
+
+/datum/reagent/consumable/tea/green
+ name = "Green Tea"
+ description = "Tasty green tea, known to heal livers, it's good for you!"
+ color = "#101000" // rgb: 16, 16, 0
+ nutriment_factor = 0
+ taste_description = "tart green tea"
+ glass_icon_state = "teaglass"
+ glass_name = "glass of tea"
+ glass_desc = "A calming glass of green tea to help get you through the day."
+
+/datum/reagent/consumable/tea/green/on_mob_life(mob/living/carbon/M)
+ M.adjustOrganLoss(ORGAN_SLOT_LIVER, -0.5) //Detox!
+ M.dizziness = max(0,M.dizziness-2)
+ M.drowsyness = max(0,M.drowsyness-1)
+ M.jitteriness = max(0,M.jitteriness-3)
+ M.adjust_bodytemperature(15 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
+ . = 1
+
+/datum/reagent/consumable/tea/forest
+ name = "Forest Tea"
+ description = "Tea mixed with honey, has both antitoxins and sweetness in one!"
+ color = "#101000" // rgb: 16, 16, 0
+ nutriment_factor = 0
+ quality = DRINK_NICE
+ taste_description = "sweet tea"
+ glass_icon_state = "teaglass"
+ glass_name = "glass of forest tea"
+ glass_desc = "A lovely glass of tea and honey."
+
+/datum/reagent/consumable/tea/forest/on_mob_life(mob/living/carbon/M)
+ if(M.getToxLoss() && prob(40))//Two anti-toxins working here
+ M.adjustToxLoss(-1, 0, TRUE) //heals TOXINLOVERs
+ //Reminder that honey heals toxin lovers
+ M.dizziness = max(0,M.dizziness-2)
+ M.drowsyness = max(0,M.drowsyness-1)
+ M.jitteriness = max(0,M.jitteriness-3)
+ M.adjust_bodytemperature(15 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
+ . = 1
+
+/datum/reagent/consumable/tea/mush
+ name = "Mush Tea"
+ description = "Tea mixed with mushroom hallucinogen, used for fun rides or self reflection."
+ color = "#101000" // rgb: 16, 16, 0
+ nutriment_factor = 0
+ quality = DRINK_NICE
+ taste_description = "fungal infections"
+ glass_icon_state = "teaglass"
+ glass_name = "glass of mush tea"
+ glass_desc = "A cold merky brown tea."
+
+/datum/reagent/consumable/tea/mush/on_mob_life(mob/living/carbon/M)
+ M.set_drugginess(20) //Little better then space drugs
+ if(prob(20))
+ M.Dizzy(10)
+ if(prob(10))
+ M.disgust = 0
+ . = 1
+
/datum/reagent/consumable/lemonade
name = "Lemonade"
description = "Sweet, tangy lemonade. Good for the soul."
@@ -1013,4 +1093,23 @@
if(M.getToxLoss() && prob(30))
M.adjustToxLoss(-1, 0)
..()
- . = TRUE
\ No newline at end of file
+ . = TRUE
+
+// i googled "natural coagulant" and a couple of results came up for banana peels, so after precisely 30 more seconds of research, i now dub grinding banana peels good for your blood
+/datum/reagent/consumable/banana_peel
+ name = "Pulped Banana Peel"
+ description = "Okay, so you put a banana peel in a grinder... Why, exactly?"
+ color = "#863333" // rgb: 175, 175, 0
+ reagent_state = SOLID
+ taste_description = "stringy, bitter pulp"
+ glass_name = "glass of banana peel pulp"
+ glass_desc = "Okay, so you put a banana peel in a grinder... Why, exactly?"
+
+/datum/reagent/consumable/baked_banana_peel
+ name = "Baked Banana Peel Powder"
+ description = "You took a banana peel... pulped it... baked it... Where are you going with this?"
+ color = "#863333" // rgb: 175, 175, 0
+ reagent_state = SOLID
+ taste_description = "bitter powder"
+ glass_name = "glass of banana peel powder"
+ description = "You took a banana peel... pulped it... baked it... Where are you going with this?"
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index f1e45d0717..96f2c04598 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -467,7 +467,7 @@
/datum/reagent/drug/skooma/on_mob_metabolize(mob/living/L)
. = ..()
L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/skooma)
- L.next_move_modifier *= 2
+ L.action_cooldown_mod *= 2
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.physiology)
@@ -480,7 +480,7 @@
/datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L)
. = ..()
L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/skooma)
- L.next_move_modifier *= 0.5
+ L.action_cooldown_mod *= 0.5
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.physiology)
@@ -542,13 +542,13 @@
/datum/reagent/syndicateadrenals/on_mob_metabolize(mob/living/M)
. = ..()
if(istype(M))
- M.next_move_modifier *= 0.5
+ M.action_cooldown_mod *= 0.5
to_chat(M, "You feel an intense surge of energy rushing through your veins.")
/datum/reagent/syndicateadrenals/on_mob_end_metabolize(mob/living/M)
. = ..()
if(istype(M))
- M.next_move_modifier *= 2
+ M.action_cooldown_mod *= 2
to_chat(M, "You feel as though the world around you is going faster.")
/datum/reagent/syndicateadrenals/overdose_start(mob/living/M)
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 050b1f29b5..8bb34c0a82 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -145,8 +145,8 @@
M.adjustToxLoss(-power, 0, TRUE) //heals TOXINLOVERs
M.adjustCloneLoss(-power, 0)
for(var/i in M.all_wounds)
- var/datum/wound/W = i
- W.on_xadone(power)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(power)
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) //fixes common causes for disfiguration
. = 1
metabolization_rate = REAGENTS_METABOLISM * (0.00001 * (M.bodytemperature ** 2) + 0.5)
@@ -196,8 +196,8 @@
M.adjustToxLoss(-power, 0, TRUE)
M.adjustCloneLoss(-power, 0)
for(var/i in M.all_wounds)
- var/datum/wound/W = i
- W.on_xadone(power)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_xadone(power)
REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC)
. = 1
..()
@@ -365,7 +365,7 @@
/datum/reagent/medicine/salglu_solution
name = "Saline-Glucose Solution"
- description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute."
+ description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute, as well as slowly speeding blood regeneration."
reagent_state = LIQUID
color = "#DCDCDC"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
@@ -373,6 +373,7 @@
taste_description = "sweetness and salt"
var/last_added = 0
var/maximum_reachable = BLOOD_VOLUME_NORMAL - 10 //So that normal blood regeneration can continue with salglu active
+ var/extra_regen = 0.25 // in addition to acting as temporary blood, also add this much to their actual blood per tick
pH = 5.5
/datum/reagent/medicine/salglu_solution/on_mob_life(mob/living/carbon/M)
@@ -385,7 +386,7 @@
var/amount_to_add = min(M.blood_volume, volume*5)
var/new_blood_level = min(M.blood_volume + amount_to_add, maximum_reachable)
last_added = new_blood_level - M.blood_volume
- M.blood_volume = new_blood_level
+ M.blood_volume = new_blood_level + extra_regen
if(prob(33))
M.adjustBruteLoss(-0.5*REM, 0)
M.adjustFireLoss(-0.5*REM, 0)
@@ -471,8 +472,9 @@
else if(method in list(PATCH, TOUCH))
M.adjustBruteLoss(-1 * reac_volume)
M.adjustFireLoss(-1 * reac_volume)
- for(var/datum/wound/burn/burn_wound in C.all_wounds)
- burn_wound.regenerate_flesh(reac_volume)
+ for(var/i in C.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.on_synthflesh(reac_volume)
if(show_message)
to_chat(M, "You feel your burns and bruises healing! It stings like hell!")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine)
@@ -1592,10 +1594,56 @@
to_chat(C, "[pick(GLOB.wisdoms)]") //give them a random wisdom
..()
-// handled in cut wounds process
+// helps bleeding wounds clot faster
/datum/reagent/medicine/coagulant
name = "Sanguirite"
- description = "A coagulant used to help open cuts clot faster."
+ description = "A proprietary coagulant used to help bleeding wounds clot faster."
reagent_state = LIQUID
color = "#bb2424"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
+ overdose_threshold = 20
+ /// How much base clotting we do per bleeding wound, multiplied by the below number for each bleeding wound
+ var/clot_rate = 0.25
+ /// If we have multiple bleeding wounds, we count the number of bleeding wounds, then multiply the clot rate by this^(n) before applying it to each cut, so more cuts = less clotting per cut (though still more total clotting)
+ var/clot_coeff_per_wound = 0.9
+
+/datum/reagent/medicine/coagulant/on_mob_life(mob/living/carbon/M)
+ . = ..()
+ if(!M.blood_volume || !M.all_wounds)
+ return
+
+ var/effective_clot_rate = clot_rate
+
+ for(var/i in M.all_wounds)
+ var/datum/wound/iter_wound = i
+ if(iter_wound.blood_flow)
+ effective_clot_rate *= clot_coeff_per_wound
+
+ for(var/i in M.all_wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.blood_flow = max(0, iter_wound.blood_flow - effective_clot_rate)
+
+/datum/reagent/medicine/coagulant/overdose_process(mob/living/M)
+ . = ..()
+ if(!M.blood_volume)
+ return
+
+ if(prob(15))
+ M.losebreath += rand(2,4)
+ M.adjustOxyLoss(rand(1,3))
+ if(prob(30))
+ to_chat(M, "You can feel your blood clotting up in your veins!")
+ else if(prob(10))
+ to_chat(M, "You feel like your blood has stopped moving!")
+ if(prob(50))
+ var/obj/item/organ/lungs/our_lungs = M.getorganslot(ORGAN_SLOT_LUNGS)
+ our_lungs.applyOrganDamage(1)
+ else
+ var/obj/item/organ/heart/our_heart = M.getorganslot(ORGAN_SLOT_HEART)
+ our_heart.applyOrganDamage(1)
+
+// can be synthesized on station rather than bought. made by grinding a banana peel, heating it up, then mixing the banana peel powder with salglu
+/datum/reagent/medicine/coagulant/weak
+ name = "Synthi-Sanguirite"
+ description = "A synthetic coagulant used to help bleeding wounds clot faster. Not quite as effective as name brand Sanguirite, especially on patients with lots of cuts."
+ clot_coeff_per_wound = 0.8
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 5c5821381e..81ad676613 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -244,6 +244,11 @@
glass_desc = "The father of all refreshments."
shot_glass_icon_state = "shotglassclear"
+/datum/reagent/water/on_mob_life(mob/living/carbon/M)
+ . = ..()
+ if(M.blood_volume)
+ M.blood_volume += 0.1 // water is good for you!
+
/*
* Water reaction to turf
*/
@@ -334,6 +339,8 @@
return ..()
/datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M)
+ if(M.blood_volume)
+ M.blood_volume += 0.1 // water is good for you!
if(!data)
data = list("misc" = 1)
data["misc"]++
@@ -2304,6 +2311,7 @@
metabolization_rate = 0.75 * REAGENTS_METABOLISM // 5u (WOUND_DETERMINATION_CRITICAL) will last for ~17 ticks
/// Whether we've had at least WOUND_DETERMINATION_SEVERE (2.5u) of determination at any given time. No damage slowdown immunity or indication we're having a second wind if it's just a single moderate wound
var/significant = FALSE
+ self_consuming = TRUE
/datum/reagent/determination/on_mob_end_metabolize(mob/living/carbon/M)
if(significant)
@@ -2336,3 +2344,52 @@
reagent_state = SOLID
color = "#E6E6DA"
taste_mult = 0
+
+/datum/reagent/hairball
+ name = "Hairball"
+ description = "A bundle of keratinous bits and fibers, not easily digestible."
+ reagent_state = SOLID
+ can_synth = FALSE
+ metabolization_rate = 0.05 * REAGENTS_METABOLISM
+ taste_description = "wet hair"
+ var/amount = 0
+ var/knotted = FALSE
+
+/datum/reagent/hairball/on_mob_life(mob/living/carbon/M)
+ amount = M.reagents.get_reagent_amount(/datum/reagent/hairball)
+
+ if(amount < 10)
+ if(prob(10))
+ M.losebreath += 1
+ M.emote("cough")
+ to_chat(M, "You clear your throat.")
+ else
+ if(!knotted)
+ to_chat(M, "You feel a knot in your stomach.")
+ knotted = TRUE
+
+ if(prob(5 + amount * 0.5)) // don't want this to cause too much damage
+ M.losebreath += 2
+ to_chat(M, "You feel a knot in your throat.")
+ M.emote("cough")
+
+ else if(prob(amount - 4))
+ to_chat(M, "Your stomach feels awfully bloated.")
+ playsound(M,'sound/voice/catpeople/distressed.ogg', 50, FALSE)
+ M.visible_message("[M] seems distressed!.", ignored_mobs=M)
+
+ else if(prob(amount - 8))
+ knotted = FALSE
+ playsound(M,'sound/voice/catpeople/puking.ogg', 110, FALSE)
+ M.Immobilize(30)
+ sleep(30) //snowflake but it works, don't wanna proc this
+ if(QDELETED(M) || QDELETED(src)) //this handles race conditions about m or src not existing.
+ return
+ M.visible_message("[M] throws up a hairball! Disgusting!", ignored_mobs=M)
+ new /obj/item/toy/plush/hairball(get_turf(M))
+ to_chat(M, "Aaaah that's better!")
+ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "cleared_stomach", /datum/mood_event/cleared_stomach, name)
+ M.reagents.del_reagent(/datum/reagent/hairball)
+ return
+ ..()
+
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 7da734e9c4..8dca028b4a 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -373,6 +373,14 @@
pH = 4.9
value = REAGENT_VALUE_VERY_COMMON
+/datum/reagent/toxin/teapowder/red
+ name = "Ground Red Tea Leaves"
+ toxpwr = 0.4
+
+/datum/reagent/toxin/teapowder/green
+ name = "Ground Green Tea Leaves"
+ toxpwr = 0.6
+
/datum/reagent/toxin/mutetoxin //the new zombie powder.
name = "Mute Toxin"
description = "A nonlethal poison that inhibits speech in its victim."
diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index e591daeb8e..bb9a951cac 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -50,6 +50,18 @@
results = list(/datum/reagent/medicine/salglu_solution = 3)
required_reagents = list(/datum/reagent/consumable/sodiumchloride = 1, /datum/reagent/water = 1, /datum/reagent/consumable/sugar = 1)
+/datum/chemical_reaction/baked_banana_peel
+ results = list(/datum/reagent/consumable/baked_banana_peel = 1)
+ required_temp = 413.15 // if it's good enough for caramel it's good enough for this
+ required_reagents = list(/datum/reagent/consumable/banana_peel = 1)
+ mix_message = "The pulp dries up and takes on a powdery state!"
+ mob_react = FALSE
+
+/datum/chemical_reaction/coagulant_weak
+ results = list(/datum/reagent/medicine/coagulant/weak = 3)
+ required_reagents = list(/datum/reagent/medicine/salglu_solution = 2, /datum/reagent/consumable/baked_banana_peel = 1)
+ mob_react = FALSE
+
/datum/chemical_reaction/mine_salve
name = "Miner's Salve"
id = /datum/reagent/medicine/mine_salve
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index fbdbb5f656..b71584982c 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -69,7 +69,8 @@
to_chat(user, "[src]'s transfer amount is now [amount_per_transfer_from_this] units.")
return
-/obj/item/reagent_containers/attack(mob/M, mob/user, def_zone)
+/obj/item/reagent_containers/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
+ . = ..()
if(user.a_intent == INTENT_HARM)
return ..()
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index 37ea2ca70d..ec26182813 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -9,6 +9,11 @@
container_HP = 2
/obj/item/reagent_containers/glass/attack(mob/M, mob/user, obj/target)
+ // WARNING: This entire section is shitcode and prone to breaking at any time.
+ INVOKE_ASYNC(src, .proc/attempt_feed, M, user, target) // for example, the arguments in this proc are wrong
+ // but i don't have time to properly fix it right now.
+
+/obj/item/reagent_containers/glass/proc/attempt_feed(mob/M, mob/user, obj/target)
if(!canconsume(M, user))
return
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 7dcf996cab..835ffe2d89 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -135,11 +135,18 @@
/obj/item/reagent_containers/hypospray/medipen/ekit
name = "emergency first-aid autoinjector"
- desc = "An epinephrine medipen with trace amounts of coagulants and antibiotics to help stabilize bad cuts and burns."
+ desc = "An epinephrine medipen with extra coagulant and antibiotics to help stabilize bad cuts and burns."
volume = 15
amount_per_transfer_from_this = 15
list_reagents = list(/datum/reagent/medicine/epinephrine = 12, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/medicine/spaceacillin = 0.5)
+/obj/item/reagent_containers/hypospray/medipen/blood_loss
+ name = "hypovolemic-response autoinjector"
+ desc = "A medipen designed to stabilize and rapidly reverse severe bloodloss."
+ volume = 15
+ amount_per_transfer_from_this = 15
+ list_reagents = list(/datum/reagent/medicine/epinephrine = 5, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/iron = 3.5, /datum/reagent/medicine/salglu_solution = 4)
+
/obj/item/reagent_containers/hypospray/medipen/stimulants
name = "illegal stimpack medipen"
desc = "A highly illegal medipen due to its load and small injections, allow for five uses before being drained"
@@ -361,13 +368,17 @@
obj_flags |= EMAGGED
return TRUE
-/obj/item/hypospray/mkii/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/hypospray/mkii/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..() //Don't bother changing this or removing it from containers will break.
/obj/item/hypospray/mkii/attack(obj/item/I, mob/user, params)
return
/obj/item/hypospray/mkii/afterattack(atom/target, mob/user, proximity)
+ . = ..()
+ INVOKE_ASYNC(src, .proc/attempt_inject, target, user, proximity)
+
+/obj/item/hypospray/mkii/proc/attempt_inject(atom/target, mob/user, proximity)
if(!vial || !proximity || !isliving(target))
return
var/mob/living/L = target
diff --git a/code/modules/reagents/reagent_containers/maunamug.dm b/code/modules/reagents/reagent_containers/maunamug.dm
index 1600699226..3dfac8a631 100644
--- a/code/modules/reagents/reagent_containers/maunamug.dm
+++ b/code/modules/reagents/reagent_containers/maunamug.dm
@@ -88,7 +88,7 @@
user.visible_message("[user] inserts a power cell into [src].", "You insert the power cell into [src].")
update_icon()
-/obj/item/reagent_containers/glass/maunamug/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/reagent_containers/glass/maunamug/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
if(cell && open)
cell.update_icon()
user.put_in_hands(cell)
diff --git a/code/modules/reagents/reagent_containers/medspray.dm b/code/modules/reagents/reagent_containers/medspray.dm
index 02a3f987bc..40ad167531 100644
--- a/code/modules/reagents/reagent_containers/medspray.dm
+++ b/code/modules/reagents/reagent_containers/medspray.dm
@@ -32,6 +32,9 @@
to_chat(user, "You will now apply the medspray's contents in [squirt_mode ? "short bursts":"extended sprays"]. You'll now use [amount_per_transfer_from_this] units per use.")
/obj/item/reagent_containers/medspray/attack(mob/living/L, mob/user, def_zone)
+ INVOKE_ASYNC(src, .proc/attempt_spray, L, user, def_zone) // this is shitcode because the params for attack aren't even right but i'm not in the mood to refactor right now.
+
+/obj/item/reagent_containers/medspray/proc/attempt_spray(mob/living/L, mob/user, def_zone)
if(!reagents || !reagents.total_volume)
to_chat(user, "[src] is empty!")
return
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index ec1e7823ed..3c23794e5a 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -28,22 +28,24 @@
/obj/item/reagent_containers/pill/get_w_volume() // DEFAULT_VOLUME_TINY at 25u, DEFAULT_VOLUME_SMALL at 50u
return DEFAULT_VOLUME_TINY/2 + reagents.total_volume / reagents.maximum_volume * DEFAULT_VOLUME_TINY
-/obj/item/reagent_containers/pill/attack(mob/M, mob/user, def_zone)
+/obj/item/reagent_containers/pill/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
+ INVOKE_ASYNC(src, .proc/attempt_feed, M, user)
+
+/obj/item/reagent_containers/pill/proc/attempt_feed(mob/living/M, mob/living/user)
if(!canconsume(M, user))
- return 0
+ return FALSE
if(M == user)
M.visible_message("[user] attempts to [apply_method] [src].")
if(self_delay)
if(!do_mob(user, M, self_delay))
- return 0
+ return FALSE
to_chat(M, "You [apply_method] [src].")
-
else
M.visible_message("[user] attempts to force [M] to [apply_method] [src].", \
"[user] attempts to force [M] to [apply_method] [src].")
if(!do_mob(user, M))
- return 0
+ return FALSE
M.visible_message("[user] forces [M] to [apply_method] [src].", \
"[user] forces [M] to [apply_method] [src].")
@@ -56,8 +58,7 @@
reagents.reaction(M, apply_type)
reagents.trans_to(M, reagents.total_volume)
qdel(src)
- return 1
-
+ return TRUE
/obj/item/reagent_containers/pill/afterattack(obj/target, mob/user , proximity)
. = ..()
@@ -77,6 +78,7 @@
"You dissolve [src] in [target].", vision_distance = 2)
reagents.trans_to(target, reagents.total_volume)
qdel(src)
+ return STOP_ATTACK_PROC_CHAIN
/obj/item/reagent_containers/pill/tox
name = "toxins pill"
diff --git a/code/modules/reagents/reagent_containers/rags.dm b/code/modules/reagents/reagent_containers/rags.dm
index afa188e9f6..469a8ef907 100644
--- a/code/modules/reagents/reagent_containers/rags.dm
+++ b/code/modules/reagents/reagent_containers/rags.dm
@@ -55,11 +55,10 @@
if(do_after(user, action_speed, target = A))
user.visible_message("[user] finishes wiping off [A]!", "You finish wiping off [A].")
SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
- return
/obj/item/reagent_containers/rag/alt_pre_attack(mob/living/M, mob/living/user, params)
if(istype(M) && user.a_intent == INTENT_HELP)
- user.changeNext_move(CLICK_CD_MELEE)
+ user.DelayNextAction(CLICK_CD_MELEE)
if(M.on_fire)
user.visible_message("\The [user] uses \the [src] to pat out [M == user ? "[user.p_their()]" : "\the [M]'s"] flames!")
if(hitsound)
@@ -193,4 +192,4 @@
extinguish_efficiency = 5
action_speed = 15
damp_threshold = 0.8
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 50, "acid" = 50) //items don't provide armor to wearers unlike clothing yet.
\ No newline at end of file
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 50, "acid" = 50) //items don't provide armor to wearers unlike clothing yet.
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 7fea8250d9..9b25a80680 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -27,6 +27,8 @@
/obj/item/reagent_containers/spray/afterattack(atom/A, mob/user)
. = ..()
+ if(!user.CheckActionCooldown(CLICK_CD_MELEE))
+ return
if(istype(A, /obj/structure/sink) || istype(A, /obj/structure/janitorialcart) || istype(A, /obj/machinery/hydroponics))
return
@@ -50,7 +52,7 @@
spray(A)
playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6)
- user.changeNext_move(CLICK_CD_RANGE*2)
+ user.last_action = world.time
user.newtonian_move(get_dir(A, user))
var/turf/T = get_turf(src)
if(reagents.has_reagent(/datum/reagent/toxin/acid))
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 4ab1470667..f42ae668c7 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -16,6 +16,7 @@
custom_materials = list(/datum/material/iron=10, /datum/material/glass=20)
reagent_flags = TRANSPARENT
custom_price = PRICE_CHEAP_AS_FREE
+ sharpness = SHARP_POINTY
/obj/item/reagent_containers/syringe/Initialize()
. = ..()
@@ -42,8 +43,7 @@
mode = !mode
update_icon()
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/reagent_containers/syringe/attack_hand()
+/obj/item/reagent_containers/syringe/on_attack_hand()
. = ..()
update_icon()
@@ -53,8 +53,14 @@
/obj/item/reagent_containers/syringe/attackby(obj/item/I, mob/user, params)
return
-/obj/item/reagent_containers/syringe/afterattack(atom/target, mob/user , proximity)
+/obj/item/reagent_containers/syringe/attack()
+ return // no bludgeoning.
+
+/obj/item/reagent_containers/syringe/afterattack(atom/target, mob/user, proximity)
. = ..()
+ INVOKE_ASYNC(src, .proc/attempt_inject, target, user, proximity)
+
+/obj/item/reagent_containers/syringe/proc/attempt_inject(atom/target, mob/user, proximity)
if(busy)
return
if(!proximity)
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index 0131e6d028..819012a61a 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -79,7 +79,7 @@
else
. += "There are no paper cups left."
-/obj/structure/reagent_dispensers/water_cooler/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/reagent_dispensers/water_cooler/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm
index d8cb462c97..b81c3b88f8 100644
--- a/code/modules/recycling/conveyor2.dm
+++ b/code/modules/recycling/conveyor2.dm
@@ -174,10 +174,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
return ..()
// attack with hand, move pulled object onto conveyor
-/obj/machinery/conveyor/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
+/obj/machinery/conveyor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
user.Move_Pulled(src)
// make the conveyor broken
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 64fe786219..ba4870903e 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -375,7 +375,6 @@
log_combat(user, target, "shoved", "into [src] (disposal bin)")
return TRUE
-
/obj/machinery/disposal/bin/flush()
..()
full_pressure = FALSE
diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm
index 551d6fa0e3..4fe07cb02f 100644
--- a/code/modules/research/designs/tool_designs.dm
+++ b/code/modules/research/designs/tool_designs.dm
@@ -92,6 +92,16 @@
category = list("Tool Designs")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_CARGO
+/datum/design/ranged_analyzer
+ name = "Long-range Analyzer"
+ desc = "A new advanced atmospheric analyzer design, capable of performing scans at long range."
+ id = "ranged_analyzer"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 400, /datum/material/glass = 1000, /datum/material/uranium = 800, /datum/material/gold = 200, /datum/material/plastic = 200)
+ build_path = /obj/item/analyzer/ranged
+ category = list("Tool Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
+
/////////////////////////////////////////
//////////////Alien Tools////////////////
/////////////////////////////////////////
diff --git a/code/modules/research/nanites/nanite_chamber.dm b/code/modules/research/nanites/nanite_chamber.dm
index 4a980a0436..01513a0b41 100644
--- a/code/modules/research/nanites/nanite_chamber.dm
+++ b/code/modules/research/nanites/nanite_chamber.dm
@@ -150,8 +150,6 @@
return
if(busy)
return
- user.changeNext_move(CLICK_CD_BREAKOUT)
- user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("You see [user] kicking against the door of [src]!", \
"You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)", \
"You hear a metallic creaking from [src].")
diff --git a/code/modules/research/nanites/public_chamber.dm b/code/modules/research/nanites/public_chamber.dm
index 76392c66e9..b7a8db4080 100644
--- a/code/modules/research/nanites/public_chamber.dm
+++ b/code/modules/research/nanites/public_chamber.dm
@@ -130,8 +130,6 @@
return
if(busy)
return
- user.changeNext_move(CLICK_CD_BREAKOUT)
- user.last_special = world.time + CLICK_CD_BREAKOUT
user.visible_message("You see [user] kicking against the door of [src]!", \
"You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)", \
"You hear a metallic creaking from [src].")
diff --git a/code/modules/research/techweb/nodes/tools_nodes.dm b/code/modules/research/techweb/nodes/tools_nodes.dm
index b084979116..180cdb5778 100644
--- a/code/modules/research/techweb/nodes/tools_nodes.dm
+++ b/code/modules/research/techweb/nodes/tools_nodes.dm
@@ -44,7 +44,7 @@
id = "exp_tools"
display_name = "Experimental Tools"
description = "Highly advanced construction tools."
- design_ids = list("exwelder", "jawsoflife", "handdrill", "holosigncombifan")
+ design_ids = list("exwelder", "jawsoflife", "handdrill", "holosigncombifan", "ranged_analyzer")
prereq_ids = list("adv_engi")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750)
diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm
index 996b84131f..1ac09652b5 100644
--- a/code/modules/research/xenobiology/crossbreeding/_clothing.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm
@@ -57,7 +57,7 @@ Slimecrossing Armor
light_color = newcolor
set_light(5)
-/obj/structure/light_prism/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/light_prism/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
to_chat(user, "You dispel [src]")
qdel(src)
@@ -118,7 +118,7 @@ Slimecrossing Armor
..()
REMOVE_TRAIT(user, TRAIT_PACIFISM, "peaceflower_[REF(src)]")
-/obj/item/clothing/head/peaceflower/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/clothing/head/peaceflower/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.head)
diff --git a/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm
index 65530031c0..088683ccd2 100644
--- a/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm
+++ b/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm
@@ -73,7 +73,7 @@
create_reagents(20)
reagents.add_reagent(dispensedreagent, 20)
-/obj/structure/sink/oil_well/attack_hand(mob/M)
+/obj/structure/sink/oil_well/on_attack_hand(mob/M)
flick("puddle-oil-splash",src)
reagents.reaction(M, TOUCH, 20) //Covers target in 20u of oil.
to_chat(M, "You touch the pool of oil, only to get oil all over yourself. It would be wise to wash this off with water.")
diff --git a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
index e6f87eea13..fd2f4377e7 100644
--- a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
+++ b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
@@ -87,8 +87,7 @@
else
return QDEL_HINT_LETMELIVE
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/structure/necropolis_gate/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/necropolis_gate/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(locked || uses == 0)
to_chat(user, "It's [open ? "stuck open":"locked"].")
return
@@ -166,8 +165,7 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate)
else
return QDEL_HINT_LETMELIVE
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/structure/necropolis_gate/legion_gate/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/necropolis_gate/legion_gate/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!open && !changing_openness)
var/safety = alert(user, "You think this might be a bad idea...", "Knock on the door?", "Proceed", "Abort")
if(safety == "Abort" || !in_range(src, user) || !src || open || changing_openness || user.incapacitated())
diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm
index 8a98a1939f..e87382cd6a 100644
--- a/code/modules/ruins/objects_and_mobs/sin_ruins.dm
+++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm
@@ -57,7 +57,7 @@
canvas rotting away and contents vanishing.")
qdel(src)
-/obj/structure/cursed_money/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/structure/cursed_money/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
index b74b32009f..d97eae5766 100644
--- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm
+++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
@@ -263,7 +263,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
/turf/closed/indestructible/hoteldoor/attack_tk(mob/user)
return //need to be close.
-/turf/closed/indestructible/hoteldoor/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/turf/closed/indestructible/hoteldoor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
promptExit(user)
/turf/closed/indestructible/hoteldoor/attack_animal(mob/user)
diff --git a/code/modules/shuttle/custom_shuttle.dm b/code/modules/shuttle/custom_shuttle.dm
index 6ff15c628e..c71b6ba9a8 100644
--- a/code/modules/shuttle/custom_shuttle.dm
+++ b/code/modules/shuttle/custom_shuttle.dm
@@ -257,7 +257,7 @@
return
..()
-/obj/machinery/computer/camera_advanced/shuttle_docker/custom/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/computer/camera_advanced/shuttle_docker/custom/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!shuttleId)
to_chat(user, "
You must link the console to a shuttle first.")
return
diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm
index 0cf348a95b..195e87720c 100644
--- a/code/modules/shuttle/navigation_computer.dm
+++ b/code/modules/shuttle/navigation_computer.dm
@@ -29,7 +29,7 @@
. = ..()
GLOB.navigation_computers -= src
-/obj/machinery/computer/camera_advanced/shuttle_docker/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/computer/camera_advanced/shuttle_docker/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(jammed)
to_chat(user, "
The Syndicate is jamming the console!")
return
diff --git a/code/modules/shuttle/shuttle_creation/shuttle_creator_console.dm b/code/modules/shuttle/shuttle_creation/shuttle_creator_console.dm
index 9af6d7fe9f..314d5e8b80 100644
--- a/code/modules/shuttle/shuttle_creation/shuttle_creator_console.dm
+++ b/code/modules/shuttle/shuttle_creation/shuttle_creator_console.dm
@@ -61,7 +61,7 @@
if(user?.client)
user.client.images -= eyeobj.user_image
-/obj/machinery/computer/camera_advanced/shuttle_creator/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/machinery/computer/camera_advanced/shuttle_creator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_operational()) //you cant use broken machine you chumbis
return
if(current_user)
diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm
index 440e6cb03b..0076f584e9 100644
--- a/code/modules/shuttle/syndicate.dm
+++ b/code/modules/shuttle/syndicate.dm
@@ -1,4 +1,4 @@
-#define SYNDICATE_CHALLENGE_TIMER 12000 //20 minutes
+#define SYNDICATE_CHALLENGE_TIMER 9000 // 15 minutes
/obj/machinery/computer/shuttle/syndicate
name = "syndicate shuttle terminal"
@@ -21,8 +21,8 @@
/obj/machinery/computer/shuttle/syndicate/Topic(href, href_list)
if(href_list["move"])
var/obj/item/circuitboard/computer/syndicate_shuttle/board = circuit
- if(board.challenge && world.time < SYNDICATE_CHALLENGE_TIMER)
- to_chat(usr, "
You've issued a combat challenge to the station! You've got to give them at least [DisplayTimeText(SYNDICATE_CHALLENGE_TIMER - world.time)] more to allow them to prepare.")
+ if(board.challenge && ((world.time - SSticker.round_start_time) < SYNDICATE_CHALLENGE_TIMER))
+ to_chat(usr, "
You've issued a combat challenge to the station! You've got to give them at least [DisplayTimeText(SYNDICATE_CHALLENGE_TIMER - (world.time - SSticker.round_start_time))] more to allow them to prepare.")
return 0
board.moved = TRUE
..()
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index 21552f7e87..57502e2cd5 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -56,11 +56,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
to_chat(caller, "
[caller.ranged_ability.name] has been disabled.")
caller.ranged_ability.remove_ranged_ability()
return TRUE //TRUE for failed, FALSE for passed.
- if(ranged_clickcd_override >= 0)
- ranged_ability_user.next_click = world.time + ranged_clickcd_override
- else
- ranged_ability_user.next_click = world.time + CLICK_CD_CLICK_ABILITY
- ranged_ability_user.face_atom(A)
return FALSE
/obj/effect/proc_holder/proc/add_ranged_ability(mob/living/user, msg, forced)
diff --git a/code/modules/spells/spell_types/spacetime_distortion.dm b/code/modules/spells/spell_types/spacetime_distortion.dm
index bec0f7871a..5797cbf8b7 100644
--- a/code/modules/spells/spell_types/spacetime_distortion.dm
+++ b/code/modules/spells/spell_types/spacetime_distortion.dm
@@ -110,8 +110,7 @@
else
walk_link(user)
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/effect/cross_action/spacetime_dist/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/effect/cross_action/spacetime_dist/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
walk_link(user)
/obj/effect/cross_action/spacetime_dist/attack_paw(mob/user)
diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm
index 40fb066fe1..6d8ab9cc7f 100644
--- a/code/modules/station_goals/dna_vault.dm
+++ b/code/modules/station_goals/dna_vault.dm
@@ -279,5 +279,5 @@
H.add_movespeed_modifier(/datum/movespeed_modifier/dna_vault_speedup)
if(VAULT_QUICK)
to_chat(H, "
Your arms move as fast as lightning.")
- H.next_move_modifier = 0.5
+ H.action_cooldown_mod = 0.5
power_lottery[H] = list()
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 711f90a629..3d88282937 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -86,12 +86,12 @@
/// A hat won't cover your face, but a shirt covering your chest will cover your... you know, chest
var/scars_covered_by_clothes = TRUE
- /// Descriptions for the locations on the limb for scars to be assigned, just cosmetic
- var/list/specific_locations = list("general area")
/// So we know if we need to scream if this limb hits max damage
var/last_maxed
/// How much generic bleedstacks we have on this bodypart
var/generic_bleedstacks
+ /// If we have a gauze wrapping currently applied (not including splints)
+ var/obj/item/stack/current_gauze
/obj/item/bodypart/examine(mob/user)
. = ..()
@@ -151,8 +151,20 @@
var/turf/T = get_turf(src)
if(status != BODYPART_ROBOTIC)
playsound(T, 'sound/misc/splort.ogg', 50, 1, -1)
- for(var/obj/item/I in src)
- I.forceMove(T)
+ if(current_gauze)
+ QDEL_NULL(current_gauze)
+ for(var/obj/item/organ/drop_organ in get_organs())
+ drop_organ.transfer_to_limb(src, owner)
+
+///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have
+/obj/item/bodypart/proc/get_organs()
+ if(!owner)
+ return
+ . = list()
+ for(var/i in owner.internal_organs) //internal organs inside the dismembered limb are dropped.
+ var/obj/item/organ/organ_check = i
+ if(check_zone(organ_check.zone) == body_zone)
+ . += organ_check
/obj/item/bodypart/proc/consider_processing()
if(stamina_dam > DAMAGE_PRECISION)
@@ -171,7 +183,7 @@
//Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all.
//Damage will not exceed max_damage using this proc
//Cannot apply negative damage
-/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) // maybe separate BRUTE_SHARP and BRUTE_OTHER eventually somehow hmm
+/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) // maybe separate BRUTE_SHARP and BRUTE_OTHER eventually somehow hmm
if(owner && (owner.status_flags & GODMODE))
return FALSE //godmode
var/dmg_mlt = CONFIG_GET(number/damage_multiplier)
@@ -192,16 +204,64 @@
if(ALIEN_BODYPART,LARVA_BODYPART) //aliens take some additional burn //nothing can burn with so much snowflake code around
burn *= 1.2
- var/wounding_type = (brute > burn ? WOUND_BRUTE : WOUND_BURN)
+ /*
+ // START WOUND HANDLING
+ */
+
+ // what kind of wounds we're gonna roll for, take the greater between brute and burn, then if it's brute, we subdivide based on sharpness
+ var/wounding_type = (brute > burn ? WOUND_BLUNT : WOUND_BURN)
var/wounding_dmg = max(brute, burn)
- if(wounding_type == WOUND_BRUTE && sharpness)
- wounding_type = WOUND_SHARP
- // i know this is effectively the same check as above but i don't know if those can null the damage by rounding and want to be safe
- if(owner && wounding_dmg > 4 && wound_bonus != CANT_WOUND)
- // if you want to make tox wounds or some other type, this will need to be expanded and made more modular
- // handle all our wounding stuff
+ var/mangled_state = get_mangled_state()
+ var/bio_state = owner.get_biological_state()
+ var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
+
+ if(wounding_type == WOUND_BLUNT)
+ if(sharpness == SHARP_EDGED)
+ wounding_type = WOUND_SLASH
+ else if(sharpness == SHARP_POINTY)
+ wounding_type = WOUND_PIERCE
+
+ //Handling for bone only/flesh only(none right now)/flesh and bone targets
+ switch(bio_state)
+ // if we're bone only, all cutting attacks go straight to the bone
+ if(BIO_JUST_BONE)
+ if(wounding_type == WOUND_SLASH)
+ wounding_type = WOUND_BLUNT
+ wounding_dmg *= (easy_dismember ? 1 : 0.5)
+ else if(wounding_type == WOUND_PIERCE)
+ wounding_type = WOUND_BLUNT
+ wounding_dmg *= (easy_dismember ? 1 : 0.75)
+ if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+ // note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
+ // standard humanoids
+ if(BIO_FLESH_BONE)
+ // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
+ // So a big sharp weapon is still all you need to destroy a limb
+ if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
+ playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
+ if(wounding_type == WOUND_SLASH && !easy_dismember)
+ wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area
+ if(wounding_type == WOUND_PIERCE && !easy_dismember)
+ wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
+ wounding_type = WOUND_BLUNT
+ else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+
+ // now we have our wounding_type and are ready to carry on with wounds and dealing the actual damage
+ if(owner && wounding_dmg >= WOUND_MINIMUM_DAMAGE && wound_bonus != CANT_WOUND)
check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
+ for(var/i in wounds)
+ var/datum/wound/iter_wound = i
+ iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus)
+
+ /*
+ // END WOUND HANDLING
+ */
+
+ //back to our regularly scheduled program, we now actually apply damage if there's room below limb damage cap
+
var/can_inflict = max_damage - get_damage()
var/total_damage = brute + burn
@@ -213,10 +273,6 @@
if(can_inflict <= 0)
return FALSE
- for(var/i in wounds)
- var/datum/wound/W = i
- W.receive_damage(wounding_type, wounding_dmg, wound_bonus)
-
brute_dam += brute
burn_dam += burn
@@ -236,14 +292,58 @@
update_disabled()
return update_bodypart_damage_state()
+/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds
+/obj/item/bodypart/proc/painless_wound_roll(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus, sharpness=SHARP_NONE)
+ if(!owner || phantom_wounding_dmg <= WOUND_MINIMUM_DAMAGE || wound_bonus == CANT_WOUND)
+ return
+
+ var/mangled_state = get_mangled_state()
+ var/bio_state = owner.get_biological_state()
+ var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
+
+ if(wounding_type == WOUND_BLUNT)
+ if(sharpness == SHARP_EDGED)
+ wounding_type = WOUND_SLASH
+ else if(sharpness == SHARP_POINTY)
+ wounding_type = WOUND_PIERCE
+
+ //Handling for bone only/flesh only(none right now)/flesh and bone targets
+ switch(bio_state)
+ // if we're bone only, all cutting attacks go straight to the bone
+ if(BIO_JUST_BONE)
+ if(wounding_type == WOUND_SLASH)
+ wounding_type = WOUND_BLUNT
+ phantom_wounding_dmg *= (easy_dismember ? 1 : 0.5)
+ else if(wounding_type == WOUND_PIERCE)
+ wounding_type = WOUND_BLUNT
+ phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75)
+ if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+ // note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday)
+ // standard humanoids
+ if(BIO_FLESH_BONE)
+ // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
+ // So a big sharp weapon is still all you need to destroy a limb
+ if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
+ playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
+ if(wounding_type == WOUND_SLASH && !easy_dismember)
+ phantom_wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area
+ if(wounding_type == WOUND_PIERCE && !easy_dismember)
+ phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated
+ wounding_type = WOUND_BLUNT
+ else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus))
+ return
+
+ check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)
+
/**
* check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria
*
- * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [check_wounding_mods()], then go down the list from most severe to least severe wounds in that category.
+ * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [/obj/item/bodypart/proc/check_wounding_mods], then go down the list from most severe to least severe wounds in that category.
* We can promote a wound from a lesser to a higher severity this way, but we give up if we have a wound of the given type and fail to roll a higher severity, so no sidegrades/downgrades
*
* Arguments:
- * * woundtype- Either WOUND_SHARP, WOUND_BRUTE, or WOUND_BURN based on the attack type.
+ * * woundtype- Either WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE, or WOUND_BURN based on the attack type.
* * damage- How much damage is tied to this attack, since wounding potential scales with damage in an attack (see: WOUND_DAMAGE_EXPONENT)
* * wound_bonus- The wound_bonus of an attack
* * bare_wound_bonus- The bare_wound_bonus of an attack
@@ -252,19 +352,24 @@
// actually roll wounds if applicable
if(HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE))
damage *= 1.5
+ else
+ damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE)
- var/base_roll = rand(1, round(damage ** WOUND_DAMAGE_EXPONENT))
+ var/base_roll = rand(max(damage/1.5,25), round(damage ** WOUND_DAMAGE_EXPONENT))
var/injury_roll = base_roll
injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus)
- var/list/wounds_checking
+ var/list/wounds_checking = GLOB.global_wound_types[woundtype]
- switch(woundtype)
- if(WOUND_SHARP)
- wounds_checking = WOUND_LIST_CUT
- if(WOUND_BRUTE)
- wounds_checking = WOUND_LIST_BONE
- if(WOUND_BURN)
- wounds_checking = WOUND_LIST_BURN
+ // quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow
+ if(ishuman(owner))
+ var/mob/living/carbon/human/human_wearer = owner
+ var/list/clothing = human_wearer.clothingonpart(src)
+ for(var/i in clothing)
+ var/obj/item/clothing/clothes_check = i
+ // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
+ if(clothes_check.armor.getRating("wound"))
+ bare_wound_bonus = 0
+ break
//cycle through the wounds of the relevant category from the most severe down
for(var/PW in wounds_checking)
@@ -279,21 +384,22 @@
replaced_wound = existing_wound
if(initial(possible_wound.threshold_minimum) < injury_roll)
+ var/datum/wound/new_wound
if(replaced_wound)
- var/datum/wound/new_wound = replaced_wound.replace_wound(possible_wound)
- log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll)
+ new_wound = replaced_wound.replace_wound(possible_wound)
+ log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) // dismembering wounds are logged in the apply_wound() for loss wounds since they delete themselves immediately, these will be immediately returned
else
- var/datum/wound/new_wound = new possible_wound
+ new_wound = new possible_wound
new_wound.apply_wound(src)
log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll)
- return
+ return new_wound
// try forcing a specific wound, but only if there isn't already a wound of that severity or greater for that type on this bodypart
/obj/item/bodypart/proc/force_wound_upwards(specific_woundtype, smited = FALSE)
var/datum/wound/potential_wound = specific_woundtype
for(var/i in wounds)
var/datum/wound/existing_wound = i
- if(existing_wound.type in (initial(potential_wound.wound_type)))
+ if(existing_wound.wound_type == initial(potential_wound.wound_type))
if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force
existing_wound.replace_wound(potential_wound, smited)
return
@@ -301,12 +407,20 @@
var/datum/wound/new_wound = new potential_wound
new_wound.apply_wound(src, smited = smited)
+/**
+ * check_wounding_mods() is where we handle the various modifiers of a wound roll
+ *
+ * A short list of things we consider: any armor a human target may be wearing, and if they have no wound armor on the limb, if we have a bare_wound_bonus to apply, plus the plain wound_bonus
+ * We also flick through all of the wounds we currently have on this limb and add their threshold penalties, so that having lots of bad wounds makes you more liable to get hurt worse
+ * Lastly, we add the inherent wound_resistance variable the bodypart has (heads and chests are slightly harder to wound), and a small bonus if the limb is already disabled
+ *
+ * Arguments:
+ * * It's the same ones on [receive_damage]
+ */
/obj/item/bodypart/proc/check_woundings_mods(wounding_type, damage, wound_bonus, bare_wound_bonus)
var/armor_ablation = 0
var/injury_mod = 0
- //var/bwb = 0
-
if(owner && ishuman(owner))
var/mob/living/carbon/human/H = owner
var/list/clothing = H.clothingonpart(src)
@@ -314,7 +428,7 @@
var/obj/item/clothing/C = c
// unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary
armor_ablation += C.armor.getRating("wound")
- if(wounding_type == WOUND_SHARP)
+ if(wounding_type == WOUND_SLASH)
C.take_damage_zone(body_zone, damage, BRUTE, armour_penetration)
else if(wounding_type == WOUND_BURN && damage >= 10) // lazy way to block freezing from shredding clothes without adding another var onto apply_damage()
C.take_damage_zone(body_zone, damage, BURN, armour_penetration)
@@ -330,7 +444,7 @@
injury_mod += W.threshold_penalty
var/part_mod = -wound_resistance
- if(is_disabled())
+ if(get_damage(TRUE) >= max_damage)
part_mod += disabled_wound_penalty
injury_mod += part_mod
@@ -383,11 +497,11 @@
return BODYPART_DISABLED_WOUND
if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER))
. = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
- if((get_damage(TRUE) >= max_damage) || (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) && (get_damage(TRUE) >= (max_damage * 0.6)))) //Easy limb disable disables the limb at 40% health instead of 0%
+ if(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0%
if(!last_maxed)
owner.emote("scream")
last_maxed = TRUE
- if(!is_organic_limb())
+ if(!is_organic_limb() || stamina_dam >= max_damage)
return BODYPART_DISABLED_DAMAGE
else if(disabled && (get_damage(TRUE) <= (max_damage * 0.8))) // reenabled at 80% now instead of 50% as of wounds update
last_maxed = FALSE
@@ -490,9 +604,9 @@
//body marking memes
var/list/colorlist = list()
colorlist.Cut()
- colorlist += ReadRGB("[H.dna.features["mcolor"]]0")
- colorlist += ReadRGB("[H.dna.features["mcolor2"]]0")
- colorlist += ReadRGB("[H.dna.features["mcolor3"]]0")
+ colorlist += ReadRGB("[H.dna.features["mcolor"]]00")
+ colorlist += ReadRGB("[H.dna.features["mcolor2"]]00")
+ colorlist += ReadRGB("[H.dna.features["mcolor3"]]00")
colorlist += list(0,0,0, S.hair_alpha)
for(var/index=1, index<=colorlist.len, index++)
colorlist[index] = colorlist[index]/255
@@ -741,17 +855,29 @@
/obj/item/bodypart/proc/get_wound_type(checking_type)
if(isnull(wounds))
return
- for(var/thing in wounds)
- var/datum/wound/W = thing
- if(istype(W, checking_type))
- return W
+ for(var/i in wounds)
+ if(istype(i, checking_type))
+ return i
-/// very rough start for updating efficiency and other stats on a body part whenever a wound is gained/lost
-/obj/item/bodypart/proc/update_wounds()
+/**
+ * update_wounds() is called whenever a wound is gained or lost on this bodypart, as well as if there's a change of some kind on a bone wound possibly changing disabled status
+ *
+ * Covers tabulating the damage multipliers we have from wounds (burn specifically), as well as deleting our gauze wrapping if we don't have any wounds that can use bandaging
+ *
+ * Arguments:
+ * * replaced- If true, this is being called from the remove_wound() of a wound that's being replaced, so the bandage that already existed is still relevant, but the new wound hasn't been added yet
+ */
+/obj/item/bodypart/proc/update_wounds(replaced = FALSE)
var/dam_mul = 1 //initial(wound_damage_multiplier)
// we can only have one wound per type, but remember there's multiple types
- for(var/datum/wound/W in wounds)
- dam_mul *= W.damage_mulitplier_penalty
+ // we can (normally) only have one wound per type, but remember there's multiple types (smites like :B:loodless can generate multiple cuts on a limb)
+ for(var/i in wounds)
+ var/datum/wound/iter_wound = i
+ dam_mul *= iter_wound.damage_mulitplier_penalty
+
+ if(!LAZYLEN(wounds) && current_gauze && !replaced)
+ owner.visible_message("
\The [current_gauze] on [owner]'s [name] fall away.", "
The [current_gauze] on your [name] fall away.")
+ QDEL_NULL(current_gauze)
wound_damage_multiplier = dam_mul
update_disabled()
@@ -761,8 +887,6 @@
var/bleed_rate = 0
if(generic_bleedstacks > 0)
bleed_rate++
- if(brute_dam >= 40)
- bleed_rate += (brute_dam * 0.008)
//We want an accurate reading of .len
listclearnulls(embedded_objects)
@@ -773,5 +897,40 @@
for(var/thing in wounds)
var/datum/wound/W = thing
bleed_rate += W.blood_flow
-
+ if(owner.mobility_flags & ~MOBILITY_STAND)
+ bleed_rate *= 0.75
return bleed_rate
+
+/**
+ * apply_gauze() is used to- well, apply gauze to a bodypart
+ *
+ * As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons).
+ * The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze
+ * applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared,
+ * the gauze falls off.
+ *
+ * Arguments:
+ * * gauze- Just the gauze stack we're taking a sheet from to apply here
+ */
+/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze)
+ if(!istype(gauze) || !gauze.absorption_capacity)
+ return
+ QDEL_NULL(current_gauze)
+ current_gauze = new gauze.type(src, 1)
+ gauze.use(1)
+
+/**
+ * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity.
+ *
+ * The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandages fall off and we're left with nothing.
+ *
+ * Arguments:
+ * * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?)
+ */
+/obj/item/bodypart/proc/seep_gauze(seep_amt = 0)
+ if(!current_gauze)
+ return
+ current_gauze.absorption_capacity -= seep_amt
+ if(current_gauze.absorption_capacity < 0)
+ owner.visible_message("
\The [current_gauze] on [owner]'s [name] fall away in rags.", "
\The [current_gauze] on your [name] fall away in rags.", vision_distance=COMBAT_MESSAGE_RANGE)
+ QDEL_NULL(current_gauze)
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 2ce6ca8862..fa003e3f3c 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -4,7 +4,7 @@
return TRUE
//Dismember a limb
-/obj/item/bodypart/proc/dismember(dam_type = BRUTE)
+/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE)
if(!owner)
return FALSE
var/mob/living/carbon/C = owner
@@ -16,7 +16,8 @@
return FALSE
var/obj/item/bodypart/affecting = C.get_bodypart(BODY_ZONE_CHEST)
affecting.receive_damage(clamp(brute_dam/2 * affecting.body_damage_coeff, 15, 50), clamp(burn_dam/2 * affecting.body_damage_coeff, 0, 50), wound_bonus=CANT_WOUND) //Damage the chest based on limb's existing damage
- C.visible_message("
[C]'s [src.name] has been violently dismembered!")
+ if(!silent)
+ C.visible_message("
[C]'s [name] is violently dismembered!")
C.emote("scream")
SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "dismembered", /datum/mood_event/dismembered)
drop_limb()
@@ -30,6 +31,7 @@
burn()
return TRUE
add_mob_blood(C)
+ C.bleed(rand(20, 40))
var/direction = pick(GLOB.cardinals)
var/t_range = rand(2,max(throw_range/2, 2))
var/turf/target_turf = get_turf(src)
@@ -80,8 +82,6 @@
if(organ_spilled)
C.visible_message("
[C]'s internal organs spill out onto the floor!")
-
-
//limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in.
/obj/item/bodypart/proc/drop_limb(special, dismembered)
if(!owner)
@@ -153,7 +153,52 @@
forceMove(Tsec)
+/**
+ * get_mangled_state() is relevant for flesh and bone bodyparts, and returns whether this bodypart has mangled skin, mangled bone, or both (or neither i guess)
+ *
+ * Dismemberment for flesh and bone requires the victim to have the skin on their bodypart destroyed (either a critical cut or piercing wound), and at least a hairline fracture
+ * (severe bone), at which point we can start rolling for dismembering. The attack must also deal at least 10 damage, and must be a brute attack of some kind (sorry for now, cakehat, maybe later)
+ *
+ * Returns: BODYPART_MANGLED_NONE if we're fine, BODYPART_MANGLED_FLESH if our skin is broken, BODYPART_MANGLED_BONE if our bone is broken, or BODYPART_MANGLED_BOTH if both are broken and we're up for dismembering
+ */
+/obj/item/bodypart/proc/get_mangled_state()
+ . = BODYPART_MANGLED_NONE
+ for(var/i in wounds)
+ var/datum/wound/iter_wound = i
+ if((iter_wound.wound_flags & MANGLES_BONE))
+ . |= BODYPART_MANGLED_BONE
+ if((iter_wound.wound_flags & MANGLES_FLESH))
+ . |= BODYPART_MANGLED_FLESH
+
+/**
+ * try_dismember() is used, once we've confirmed that a flesh and bone bodypart has both the skin and bone mangled, to actually roll for it
+ *
+ * Mangling is described in the above proc, [/obj/item/bodypart/proc/get_mangled_state()]. This simply makes the roll for whether we actually dismember or not
+ * using how damaged the limb already is, and how much damage this blow was for. If we have a critical bone wound instead of just a severe, we add +10% to the roll.
+ * Lastly, we choose which kind of dismember we want based on the wounding type we hit with. Note we don't care about all the normal mods or armor for this
+ *
+ * Arguments:
+ * * wounding_type: Either WOUND_BLUNT, WOUND_SLASH, or WOUND_PIERCE, basically only matters for the dismember message
+ * * wounding_dmg: The damage of the strike that prompted this roll, higher damage = higher chance
+ * * wound_bonus: Not actually used right now, but maybe someday
+ * * bare_wound_bonus: ditto above
+ */
+/obj/item/bodypart/proc/try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)
+ if(wounding_dmg < DISMEMBER_MINIMUM_DAMAGE)
+ return
+
+ var/base_chance = wounding_dmg + (get_damage() / max_damage * 50) // how much damage we dealt with this blow, + 50% of the damage percentage we already had on this bodypart
+ if(locate(/datum/wound/blunt/critical) in wounds) // we only require a severe bone break, but if there's a critical bone break, we'll add 10% more
+ base_chance += 10
+
+ if(!prob(base_chance))
+ return
+
+ var/datum/wound/loss/dismembering = new
+ dismembering.apply_dismember(src, wounding_type)
+
+ return TRUE
//when a limb is dropped, the internal organs are removed from the mob and put into the limb
/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C)
@@ -378,7 +423,7 @@
/mob/living/carbon/regenerate_limb(limb_zone, noheal)
var/obj/item/bodypart/L
if(get_bodypart(limb_zone))
- return 0
+ return FALSE
L = newBodyPart(limb_zone, 0, 0)
if(L)
if(!noheal)
@@ -386,6 +431,8 @@
L.burn_dam = 0
L.brutestate = 0
L.burnstate = 0
-
+ var/datum/scar/scaries = new
+ var/datum/wound/loss/phantom_loss = new // stolen valor, really
+ scaries.generate(L, phantom_loss)
L.attach_limb(src, 1)
- return 1
+ return TRUE
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index a67f16b934..13b1140527 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -36,11 +36,10 @@
var/custom_head
wound_resistance = 10
- specific_locations = list("left eyebrow", "cheekbone", "neck", "throat", "jawline", "entire face")
scars_covered_by_clothes = FALSE
/obj/item/bodypart/head/can_dismember(obj/item/I)
- if(!((owner.stat == DEAD) || owner.InFullCritical()))
+ if(owner && !((owner.stat == DEAD) || owner.InFullCritical()))
return FALSE
return ..()
diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm
index a18b31e4c1..5a887ee6b7 100644
--- a/code/modules/surgery/bodyparts/parts.dm
+++ b/code/modules/surgery/bodyparts/parts.dm
@@ -12,7 +12,7 @@
var/obj/item/cavity_item
/obj/item/bodypart/chest/can_dismember(obj/item/I)
- if(!((owner.stat == DEAD) || owner.InFullCritical()))
+ if(!((owner.stat == DEAD) || owner.InFullCritical()) || !get_organs())
return FALSE
return ..()
diff --git a/code/modules/surgery/bone_mending.dm b/code/modules/surgery/bone_mending.dm
index 81d9fa8d97..0c0083575b 100644
--- a/code/modules/surgery/bone_mending.dm
+++ b/code/modules/surgery/bone_mending.dm
@@ -8,7 +8,7 @@
target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
- targetable_wound = /datum/wound/brute/bone/severe
+ targetable_wound = /datum/wound/blunt/severe
/datum/surgery/repair_bone_hairline/can_start(mob/living/user, mob/living/carbon/target)
if(..())
@@ -23,7 +23,7 @@
target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
- targetable_wound = /datum/wound/brute/bone/critical
+ targetable_wound = /datum/wound/blunt/critical
/datum/surgery/repair_bone_compound/can_start(mob/living/user, mob/living/carbon/target)
if(..())
diff --git a/code/modules/surgery/burn_dressing.dm b/code/modules/surgery/burn_dressing.dm
index 1688f7b5d1..8bfa52d245 100644
--- a/code/modules/surgery/burn_dressing.dm
+++ b/code/modules/surgery/burn_dressing.dm
@@ -94,7 +94,8 @@
log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]")
burn_wound.sanitization += 3
burn_wound.flesh_healing += 5
- burn_wound.force_bandage(tool)
+ var/obj/item/bodypart/the_part = target.get_bodypart(target_zone)
+ the_part.apply_gauze(tool)
else
to_chat(user, "
[target] has no burns there!")
return ..()
diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm
index 2465b63800..f0f98a5fa5 100755
--- a/code/modules/surgery/organs/liver.dm
+++ b/code/modules/surgery/organs/liver.dm
@@ -73,8 +73,8 @@
/obj/item/organ/liver/proc/sizeMoveMod(value, mob/living/carbon/C)
if(cachedmoveCalc == value)
return
- C.next_move_modifier /= cachedmoveCalc
- C.next_move_modifier *= value
+ C.action_cooldown_mod /= cachedmoveCalc
+ C.action_cooldown_mod *= value
cachedmoveCalc = value
/obj/item/organ/liver/fly
diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm
index 55a656f42d..289e9df9d4 100644
--- a/code/modules/surgery/organs/tails.dm
+++ b/code/modules/surgery/organs/tails.dm
@@ -45,14 +45,20 @@
/obj/item/organ/tail/lizard/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = TRUE)
..()
if(istype(H))
- // Checks here are necessary so it wouldn't overwrite the tail of a lizard it spawned in
+ // Checks here are necessary so it wouldn't overwrite the tail of a lizard it spawned in //yes, the if checks may cause snowflakes so that you can't insert another person's tail (haven't actually tested it but I assume that's the result of my addition) but it makes it so never again will lizards break their spine if set_species is called twice in a row (hopefully)
if(!H.dna.species.mutant_bodyparts["tail_lizard"])
- H.dna.features["tail_lizard"] = tail_type
- H.dna.species.mutant_bodyparts["tail_lizard"] = tail_type
+ if (!H.dna.features["tail_lizard"])
+ H.dna.features["tail_lizard"] = tail_type
+ H.dna.species.mutant_bodyparts["tail_lizard"] = tail_type
+ else
+ H.dna.species.mutant_bodyparts["tail_lizard"] = H.dna.features["tail_lizard"]
if(!H.dna.species.mutant_bodyparts["spines"])
- H.dna.features["spines"] = spines
- H.dna.species.mutant_bodyparts["spines"] = spines
+ if (!H.dna.features["spines"])
+ H.dna.features["spines"] = spines
+ H.dna.species.mutant_bodyparts["spines"] = spines
+ else
+ H.dna.species.mutant_bodyparts["spines"] = H.dna.features["spines"]
H.update_body()
/obj/item/organ/tail/lizard/Remove(special = FALSE)
diff --git a/code/modules/surgery/repair_puncture.dm b/code/modules/surgery/repair_puncture.dm
new file mode 100644
index 0000000000..12aefefc82
--- /dev/null
+++ b/code/modules/surgery/repair_puncture.dm
@@ -0,0 +1,108 @@
+
+/////BURN FIXING SURGERIES//////
+
+//the step numbers of each of these two, we only currently use the first to switch back and forth due to advancing after finishing steps anyway
+#define REALIGN_INNARDS 1
+#define WELD_VEINS 2
+
+///// Repair puncture wounds
+/datum/surgery/repair_puncture
+ name = "Repair puncture"
+ steps = list(/datum/surgery_step/incise, /datum/surgery_step/repair_innards, /datum/surgery_step/seal_veins, /datum/surgery_step/close) // repeat between steps 2 and 3 until healed
+ target_mobtypes = list(/mob/living/carbon)
+ possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
+ requires_real_bodypart = TRUE
+ targetable_wound = /datum/wound/pierce
+
+/datum/surgery/repair_puncture/can_start(mob/living/user, mob/living/carbon/target)
+ . = ..()
+ if(.)
+ var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected)
+ var/datum/wound/burn/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound)
+ return(pierce_wound && pierce_wound.blood_flow > 0)
+
+//SURGERY STEPS
+
+///// realign the blood vessels so we can reweld them
+/datum/surgery_step/repair_innards
+ name = "realign blood vessels"
+ implements = list(TOOL_HEMOSTAT = 100, TOOL_SCALPEL = 85, TOOL_WIRECUTTER = 40)
+ time = 3 SECONDS
+
+/datum/surgery_step/repair_innards/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/datum/wound/pierce/pierce_wound = surgery.operated_wound
+ if(!pierce_wound)
+ user.visible_message("
[user] looks for [target]'s [parse_zone(user.zone_selected)].", "
You look for [target]'s [parse_zone(user.zone_selected)]...")
+ return
+
+ if(pierce_wound.blood_flow <= 0)
+ to_chat(user, "
[target]'s [parse_zone(user.zone_selected)] has no puncture to repair!")
+ surgery.status++
+ return
+
+ display_results(user, target, "
You begin to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)]...",
+ "
[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].",
+ "
[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)].")
+
+/datum/surgery_step/repair_innards/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
+ var/datum/wound/pierce/pierce_wound = surgery.operated_wound
+ if(!pierce_wound)
+ to_chat(user, "
[target] has no puncture wound there!")
+ return ..()
+
+ display_results(user, target, "
You successfully realign some of the blood vessels in [target]'s [parse_zone(target_zone)].",
+ "
[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!",
+ "
[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)]!")
+ log_combat(user, target, "excised infected flesh in", addition="INTENT: [uppertext(user.a_intent)]")
+ surgery.operated_bodypart.receive_damage(brute=3, wound_bonus=CANT_WOUND)
+ pierce_wound.blood_flow -= 0.25
+ return ..()
+
+/datum/surgery_step/repair_innards/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
+ . = ..()
+ display_results(user, target, "
You jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)].",
+ "
[user] jerks apart some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!",
+ "
[user] jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)]!")
+ surgery.operated_bodypart.receive_damage(brute=rand(4,8), sharpness=SHARP_EDGED, wound_bonus = 10)
+
+///// Sealing the vessels back together
+/datum/surgery_step/seal_veins
+ name = "weld veins" // if your doctor says they're going to weld your blood vessels back together, you're either A) on SS13, or B) in grave mortal peril
+ implements = list(TOOL_CAUTERY = 100, /obj/item/gun/energy/laser = 90, TOOL_WELDER = 70, /obj/item = 30)
+ time = 4 SECONDS
+
+/datum/surgery_step/seal_veins/tool_check(mob/user, obj/item/tool)
+ if(implement_type == TOOL_WELDER || implement_type == /obj/item)
+ return tool.get_temperature()
+
+ return TRUE
+
+/datum/surgery_step/seal_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/datum/wound/pierce/pierce_wound = surgery.operated_wound
+ if(!pierce_wound)
+ user.visible_message("
[user] looks for [target]'s [parse_zone(user.zone_selected)].", "
You look for [target]'s [parse_zone(user.zone_selected)]...")
+ return
+ display_results(user, target, "
You begin to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)]...",
+ "
[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].",
+ "
[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)].")
+
+/datum/surgery_step/seal_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
+ var/datum/wound/pierce/pierce_wound = surgery.operated_wound
+ if(!pierce_wound)
+ to_chat(user, "
[target] has no puncture there!")
+ return ..()
+
+ display_results(user, target, "
You successfully meld some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool].",
+ "
[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!",
+ "
[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)]!")
+ log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]")
+ pierce_wound.blood_flow -= 0.5
+ if(pierce_wound.blood_flow > 0)
+ surgery.status = REALIGN_INNARDS
+ to_chat(user, "
There still seems to be misaligned blood vessels to finish...")
+ else
+ to_chat(user, "
You've repaired all the internal damage in [target]'s [parse_zone(target_zone)]!")
+ return ..()
+
+#undef REALIGN_INNARDS
+#undef WELD_VEINS
diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm
index 150016f570..c4ded65e9c 100644
--- a/code/modules/surgery/tools.dm
+++ b/code/modules/surgery/tools.dm
@@ -163,7 +163,7 @@
item_flags = SURGICAL_TOOL
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP_ACCURATE
+ sharpness = SHARP_POINTY
tool_behaviour = TOOL_SCALPEL
toolspeed = 1
bare_wound_bonus = 20
@@ -181,7 +181,7 @@
force = 16
toolspeed = 0.7
light_color = LIGHT_COLOR_GREEN
- sharpness = IS_SHARP_ACCURATE
+ sharpness = SHARP_POINTY
/obj/item/scalpel/advanced/Initialize()
. = ..()
@@ -221,7 +221,7 @@
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
toolspeed = 0.5
hitsound = 'sound/weapons/bladeslice.ogg'
- sharpness = IS_SHARP_ACCURATE
+ sharpness = SHARP_POINTY
/obj/item/scalpel/suicide_act(mob/user)
user.visible_message("
[user] is slitting [user.p_their()] [pick("wrists", "throat", "stomach")] with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -245,11 +245,11 @@
throw_range = 5
custom_materials = list(/datum/material/iron=10000, /datum/material/glass=6000)
attack_verb = list("attacked", "slashed", "sawed", "cut")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
tool_behaviour = TOOL_SAW
toolspeed = 1
- wound_bonus = 10
- bare_wound_bonus = 15
+ wound_bonus = 5
+ bare_wound_bonus = 10
/obj/item/circular_saw/Initialize()
. = ..()
@@ -272,7 +272,7 @@
custom_materials = list(/datum/material/iron=10000, /datum/material/glass=6000)
toolspeed = 0.5
attack_verb = list("attacked", "slashed", "sawed", "cut")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
/obj/item/surgical_drapes
name = "surgical drapes"
diff --git a/code/modules/uplink/uplink_items/uplink_ammo.dm b/code/modules/uplink/uplink_items/uplink_ammo.dm
index ce74773f8d..853f6111b2 100644
--- a/code/modules/uplink/uplink_items/uplink_ammo.dm
+++ b/code/modules/uplink/uplink_items/uplink_ammo.dm
@@ -291,10 +291,17 @@
/datum/uplink_item/ammo/bolt_action
name = "Surplus Rifle Clip"
desc = "A stripper clip used to quickly load bolt action rifles. Contains 5 rounds."
- item = /obj/item/ammo_box/a762
+ item = /obj/item/ammo_box/a762
cost = 1
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/ammo/bolt_action_bulk
+ name = "Surplus Rifle Clip Box"
+ desc = "An ammo box we found in a warehouse, holding 7 clips of 5 rounds for bolt-action rifles. Yes, the cheap ones."
+ item = /obj/item/storage/toolbox/ammo
+ cost = 4
+ include_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/ammo/dark_gygax/bag
name = "Dark Gygax Ammo Bag"
desc = "A duffel bag containing ammo for three full reloads of the incendiary carbine and flash bang launcher that are equipped on a standard Dark Gygax exosuit."
diff --git a/code/modules/uplink/uplink_items/uplink_bundles.dm b/code/modules/uplink/uplink_items/uplink_bundles.dm
index d40e2fcbda..fbeaee8939 100644
--- a/code/modules/uplink/uplink_items/uplink_bundles.dm
+++ b/code/modules/uplink/uplink_items/uplink_bundles.dm
@@ -50,7 +50,7 @@
Combines with all martial arts, but the user will be unable to bring themselves to use guns, nor remove the armbands."
item = /obj/item/storage/box/syndie_kit/northstar
cost = 20
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/suits/infiltrator_bundle
name = "Insidious Infiltration Gear Case"
@@ -117,7 +117,7 @@
you will receive. May contain discontinued and/or exotic items."
item = /obj/item/storage/box/syndicate
cost = 20
- exclude_modes = list(/datum/game_mode/nuclear)
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/traitor/internal_affairs)
cant_discount = TRUE
/datum/uplink_item/bundles_TC/surplus
@@ -127,7 +127,7 @@
item = /obj/structure/closet/crate
cost = 20
player_minimum = 25
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
cant_discount = TRUE
var/starting_crate_value = 50
@@ -163,7 +163,7 @@
/datum/uplink_item/bundles_TC/reroll
name = "Renegotiate Contract"
- desc = "Selecting this will inform the syndicate that you wish to change employers. Can only be done once; no take-backs."
+ desc = "Selecting this will inform your employers that you wish for new objectives. Can only be done once; no take-backs."
item = /obj/effect/gibspawner/generic
cost = 0
cant_discount = TRUE
@@ -184,6 +184,7 @@
item = /obj/effect/gibspawner/generic // non-tangible item because techwebs use this path to determine illegal tech
cost = 0
cant_discount = TRUE
+ exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/bundles_TC/random/purchase(mob/user, datum/component/uplink/U)
var/list/uplink_items = U.uplink_items
diff --git a/code/modules/uplink/uplink_items/uplink_dangerous.dm b/code/modules/uplink/uplink_items/uplink_dangerous.dm
index 7d96390115..a43e3fc2ce 100644
--- a/code/modules/uplink/uplink_items/uplink_dangerous.dm
+++ b/code/modules/uplink/uplink_items/uplink_dangerous.dm
@@ -21,7 +21,7 @@
item = /obj/item/storage/box/syndie_kit/revolver
cost = 13
surplus = 50
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/dangerous/rawketlawnchair
name = "84mm Rocket Propelled Grenade Launcher"
@@ -112,7 +112,7 @@
item = /obj/item/dualsaber
player_minimum = 25
cost = 16
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/dangerous/doublesword/get_discount()
return pick(4;0.8,2;0.65,1;0.5)
@@ -123,7 +123,7 @@
pocketed when inactive. Activating it produces a loud, distinctive noise."
item = /obj/item/melee/transforming/energy/sword/saber
cost = 8
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/dangerous/shield
name = "Energy Shield"
@@ -141,7 +141,7 @@
However, due to the size of the blade and obvious nature of the sheath, the weapon stands out as being obviously nefarious."
item = /obj/item/storage/belt/sabre/rapier
cost = 8
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/dangerous/flamethrower
name = "Flamethrower"
@@ -180,11 +180,22 @@
refundable = TRUE
cant_discount = TRUE
surplus = 0
- exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
player_minimum = 25
restricted = TRUE
refund_path = /obj/item/guardiancreator/tech/choose/traitor
+/datum/uplink_item/dangerous/nukieguardian // just like the normal holoparasites but without the support or deffensive stands because nukies shouldnt turtle
+ name = "Holoparasites"
+ desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \
+ organic host as a home base and source of fuel. Holoparasites come in various types and share damage with their host."
+ item = /obj/item/storage/box/syndie_kit/nukieguardian
+ cost = 15
+ refundable = TRUE
+ surplus = 50
+ refund_path = /obj/item/guardiancreator/tech/choose/nukie
+ include_modes = list(/datum/game_mode/nuclear)
+
/datum/uplink_item/dangerous/machinegun
name = "L6 Squad Automatic Weapon"
desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \
@@ -211,6 +222,7 @@
deal extra damage and hit targets further. Use a screwdriver to take out any attached tanks."
item = /obj/item/melee/powerfist
cost = 8
+ exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/dangerous/sniper
name = "Sniper Rifle"
@@ -250,4 +262,4 @@
darts effective at incapacitating a target."
item = /obj/item/gun/ballistic/automatic/toy/pistol/riot
cost = 3
- surplus = 10
\ No newline at end of file
+ surplus = 10
diff --git a/code/modules/uplink/uplink_items/uplink_devices.dm b/code/modules/uplink/uplink_items/uplink_devices.dm
index ccaa998cf7..5f5eb91a04 100644
--- a/code/modules/uplink/uplink_items/uplink_devices.dm
+++ b/code/modules/uplink/uplink_items/uplink_devices.dm
@@ -147,6 +147,12 @@
item = /obj/item/aiModule/syndicate
cost = 9
+/datum/uplink_item/device_tools/damaged_module
+ name = "Damaged AI Law Upload Module"
+ desc = "This AI law upload module has been laying around our warehouse for god knows how long. We do not know why you would ever use this."
+ item = /obj/item/aiModule/core/full/damaged
+ cost = 5
+
/datum/uplink_item/device_tools/headsetupgrade
name = "Headset Upgrader"
desc = "A device that can be used to make one headset immune to flashbangs."
@@ -200,16 +206,14 @@
this primer of questionable worth and value is rumored to increase your rifle-bolt-working and/or shotgun \
racking fivefold. Then again, the techniques here only work on bolt-actions and pump-actions..."
item = /obj/item/book/granter/trait/rifleman
- cost = 3
- restricted_roles = list("Operative") // i want it to be surplusable but i also want it to be mostly nukie only, please advise
- surplus = 90
+ cost = 3 // fuck it available for everyone
/datum/uplink_item/device_tools/stimpack
name = "Stimpack"
- desc = "Stimpacks, the tool of many great heroes, make you nearly immune to stuns and knockdowns for about \
+ desc = "Stimpacks, the tool of many great heroes. Makes you nearly immune to non-lethal weaponry for about \
5 minutes after injection."
item = /obj/item/reagent_containers/syringe/stimulants
- cost = 3
+ cost = 5
surplus = 90
/datum/uplink_item/device_tools/medkit
diff --git a/code/modules/uplink/uplink_items/uplink_explosives.dm b/code/modules/uplink/uplink_items/uplink_explosives.dm
index c52651fee9..6cc1c9fe05 100644
--- a/code/modules/uplink/uplink_items/uplink_explosives.dm
+++ b/code/modules/uplink/uplink_items/uplink_explosives.dm
@@ -58,6 +58,7 @@
item = /obj/item/storage/backpack/duffelbag/syndie/x4
cost = 4 //
cant_discount = TRUE
+ exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/explosives/clown_bomb_clownops
name = "Clown Bomb"
@@ -123,6 +124,7 @@
be defused, and some crew may attempt to do so."
item = /obj/item/sbeacondrop/bomb
cost = 11
+ exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/explosives/syndicate_detonator
name = "Syndicate Detonator"
@@ -140,7 +142,7 @@
in addition to dealing high amounts of damage to nearby personnel."
item = /obj/item/grenade/syndieminibomb
cost = 6
- exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+ exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/explosives/tearstache
name = "Teachstache Grenade"
diff --git a/code/modules/uplink/uplink_items/uplink_implants.dm b/code/modules/uplink/uplink_items/uplink_implants.dm
index 02b8b1e01d..bb4e0c7960 100644
--- a/code/modules/uplink/uplink_items/uplink_implants.dm
+++ b/code/modules/uplink/uplink_items/uplink_implants.dm
@@ -29,6 +29,13 @@
item = /obj/item/storage/box/syndie_kit/imp_freedom
cost = 5
+/datum/uplink_item/implants/warp
+ name = "Warp Implant"
+ desc = "An implant injected into the body and later activated at the user's will. It will inject eigenstasium which saves the user's location and teleports them there after five seconds. Lasts only fifteen times."
+ item = /obj/item/storage/box/syndie_kit/imp_warp
+ cost = 6
+ exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+
/datum/uplink_item/implants/hijack
name = "Hijack Implant"
desc = "An implant that will let you hack into the APCs on station, allowing you to control them at will and the machinery within those rooms."
diff --git a/code/modules/uplink/uplink_items/uplink_roles.dm b/code/modules/uplink/uplink_items/uplink_roles.dm
index 859c8c0bd7..b8eaf41371 100644
--- a/code/modules/uplink/uplink_items/uplink_roles.dm
+++ b/code/modules/uplink/uplink_items/uplink_roles.dm
@@ -30,6 +30,7 @@
item = /obj/item/gun/blastcannon
cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist.
restricted_roles = list("Research Director", "Scientist")
+ exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/role_restricted/alientech
name = "Alien Research Disk"
@@ -100,6 +101,7 @@
player_minimum = 20
refundable = TRUE
restricted_roles = list("Chaplain")
+ exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/role_restricted/arcane_tome
name = "Arcane Tome"
@@ -109,6 +111,7 @@
player_minimum = 20
refundable = TRUE
restricted_roles = list("Chaplain")
+ exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/role_restricted/explosive_hot_potato
name = "Exploding Hot Potato"
diff --git a/code/modules/uplink/uplink_items/uplink_stealth.dm b/code/modules/uplink/uplink_items/uplink_stealth.dm
index c60d4ef177..ff6d66a483 100644
--- a/code/modules/uplink/uplink_items/uplink_stealth.dm
+++ b/code/modules/uplink/uplink_items/uplink_stealth.dm
@@ -65,6 +65,16 @@
surplus = 0
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/stealthy_weapons/martialartsthree
+ name = "Krav Maga Scroll"
+ desc = "This scroll contains the secrets of an ancient martial arts technique. You will gain special unarmed attacks for \
+ stealthy takedowns."
+ item = /obj/item/book/granter/martial/krav_maga
+ cost = 16
+ player_minimum = 25
+ surplus = 0
+ include_modes = list(/datum/game_mode/traitor/internal_affairs)
+
/datum/uplink_item/stealthy_weapons/crossbow
name = "Miniature Energy Crossbow"
desc = "A short bow mounted across a tiller in miniature. Small enough to \
diff --git a/code/modules/vehicles/cars/car.dm b/code/modules/vehicles/cars/car.dm
index fb30e66f97..4545fab2a7 100644
--- a/code/modules/vehicles/cars/car.dm
+++ b/code/modules/vehicles/cars/car.dm
@@ -57,7 +57,7 @@
return FALSE
return ..()
-/obj/vehicle/sealed/car/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/vehicle/sealed/car/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(!(car_traits & CAN_KIDNAP))
return
diff --git a/code/modules/vehicles/pimpin_ride.dm b/code/modules/vehicles/pimpin_ride.dm
index 547eef7af2..8f9d553ec7 100644
--- a/code/modules/vehicles/pimpin_ride.dm
+++ b/code/modules/vehicles/pimpin_ride.dm
@@ -62,11 +62,8 @@
if(floorbuffer)
. += "cart_buffer"
-/obj/vehicle/ridden/janicart/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
- . = ..()
- if(.)
- return
- else if(mybag)
+/obj/vehicle/ridden/janicart/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+ if(mybag)
mybag.forceMove(get_turf(user))
user.put_in_hands(mybag)
mybag = null
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index a7b9b6a298..a42fe97cb4 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -530,8 +530,7 @@ GLOBAL_LIST_EMPTY(vending_products)
for(var/i in C.bodyparts)
var/obj/item/bodypart/squish_part = i
if(squish_part.is_organic_limb())
- //var/type_wound = pick(WOUND_LIST_BONE)
- var/type_wound = pick(list(/datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/moderate))
+ var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
squish_part.force_wound_upwards(type_wound)
else
squish_part.receive_damage(brute=30)
@@ -577,7 +576,7 @@ GLOBAL_LIST_EMPTY(vending_products)
"
You right [src].")
unbuckle_all_mobs(TRUE)
-
+ anchored = FALSE //so you can push it back into position
tilted = FALSE
layer = initial(layer)
diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm
index 260b124283..bc824cc994 100644
--- a/code/modules/vending/autodrobe.dm
+++ b/code/modules/vending/autodrobe.dm
@@ -116,7 +116,8 @@
/obj/item/gun/magic/wand = 2,
/obj/item/clothing/glasses/sunglasses/garb = 2,
/obj/item/clothing/glasses/sunglasses/blindfold = 1,
- /obj/item/clothing/mask/muzzle = 2)
+ /obj/item/clothing/mask/muzzle = 2,
+ /obj/item/clothing/under/syndicate/camo/cosmetic = 3)
premium = list(/obj/item/clothing/suit/pirate/captain = 2,
/obj/item/clothing/head/pirate/captain = 2,
/obj/item/clothing/head/helmet/roman/fake = 1,
diff --git a/code/modules/vending/cartridge.dm b/code/modules/vending/cartridge.dm
index beaf6bb873..69635007c9 100644
--- a/code/modules/vending/cartridge.dm
+++ b/code/modules/vending/cartridge.dm
@@ -10,6 +10,7 @@
/obj/item/cartridge/security = 10,
/obj/item/cartridge/janitor = 10,
/obj/item/cartridge/signal/toxins = 10,
+ /obj/item/cartridge/roboticist = 10,
/obj/item/pda/heads = 10)
premium = list(/obj/item/cartridge/captain = 2,
/obj/item/cartridge/quartermaster = 2)
diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm
index 2691906af4..7005a0b02f 100644
--- a/code/modules/vending/clothesmate.dm
+++ b/code/modules/vending/clothesmate.dm
@@ -14,6 +14,10 @@
/obj/item/clothing/head/beret/blue = 3,
/obj/item/clothing/glasses/monocle = 3,
/obj/item/clothing/suit/jacket = 4,
+ /obj/item/clothing/suit/jacket/flannel = 4,
+ /obj/item/clothing/suit/jacket/flannel/red = 4,
+ /obj/item/clothing/suit/jacket/flannel/aqua = 4,
+ /obj/item/clothing/suit/jacket/flannel/brown = 4,
/obj/item/clothing/suit/jacket/puffer/vest = 4,
/obj/item/clothing/suit/jacket/puffer = 4,
/obj/item/clothing/suit/hooded/cloak/david = 4,
diff --git a/code/modules/vending/coffee.dm b/code/modules/vending/coffee.dm
index ab64756868..fd555526c6 100644
--- a/code/modules/vending/coffee.dm
+++ b/code/modules/vending/coffee.dm
@@ -1,16 +1,20 @@
/obj/machinery/vending/coffee
name = "\improper Solar's Best Hot Drinks"
desc = "A vending machine which dispenses hot drinks."
- product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies"
+ product_ads = "Just what you need!;Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies"
icon_state = "coffee"
icon_vend = "coffee-vend"
products = list(/obj/item/reagent_containers/food/drinks/coffee = 25,
/obj/item/reagent_containers/food/drinks/mug/tea = 25,
+ /obj/item/reagent_containers/food/drinks/mug/tea/red = 10,
+ /obj/item/reagent_containers/food/drinks/mug/tea/green = 10,
/obj/item/reagent_containers/food/drinks/mug/coco = 25)
- contraband = list(/obj/item/reagent_containers/food/drinks/ice = 12)
+ contraband = list(/obj/item/reagent_containers/food/drinks/ice = 12,
+ /obj/item/reagent_containers/food/drinks/mug/tea/mush = 3,)
premium = list(/obj/item/reagent_containers/food/condiment/milk = 2,
/obj/item/reagent_containers/food/drinks/bottle/cream = 2,
- /obj/item/reagent_containers/food/condiment/sugar = 1)
+ /obj/item/reagent_containers/food/condiment/sugar = 1,
+ /obj/item/reagent_containers/food/drinks/mug/tea/forest = 3,)
refill_canister = /obj/item/vending_refill/coffee
default_price = PRICE_REALLY_CHEAP
diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm
index 8552d52b04..26beccaac0 100644
--- a/code/modules/vending/wardrobes.dm
+++ b/code/modules/vending/wardrobes.dm
@@ -248,6 +248,7 @@
vend_reply = "Thank you for using the BarDrobe!"
products = list(/obj/item/clothing/head/that = 3,
/obj/item/radio/headset/headset_srv = 3,
+ /obj/item/clothing/suit/hooded/wintercoat/bar = 3,
/obj/item/clothing/under/suit/sl = 3,
/obj/item/clothing/under/rank/civilian/bartender = 3,
/obj/item/clothing/under/rank/civilian/bartender/skirt = 2,
diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm
index 50cdc32bf6..a367abb098 100644
--- a/code/modules/vore/eating/belly_obj.dm
+++ b/code/modules/vore/eating/belly_obj.dm
@@ -542,8 +542,6 @@
if (!(R in contents))
return // User is not in this belly
- R.changeNext_move(CLICK_CD_BREAKOUT*0.5)
-
if(owner.stat) //If owner is stat (dead, KO) we can actually escape
to_chat(R,"You attempt to climb out of \the [lowertext(name)]. (This will take around [escapetime/10] seconds.)")
to_chat(owner,"Someone is attempting to climb out of your [lowertext(name)]!")
diff --git a/code/modules/vore/eating/living.dm b/code/modules/vore/eating/living.dm
index 1c9bf029ea..9395cef952 100644
--- a/code/modules/vore/eating/living.dm
+++ b/code/modules/vore/eating/living.dm
@@ -349,7 +349,7 @@
if(incapacitated(ignore_restraints = TRUE))
to_chat(src, "You can't do that while incapacitated.")
return
- if(next_move > world.time)
+ if(!CheckActionCooldown())
to_chat(src, "You can't do that so fast, slow down.")
return
@@ -366,11 +366,10 @@
if(QDELETED(tasted) || (tasted.ckey && !(tasted.client?.prefs.vore_flags & LICKABLE)) || !Adjacent(tasted) || incapacitated(ignore_restraints = TRUE))
return
- changeNext_move(CLICK_CD_MELEE)
+ DelayNextAction(CLICK_CD_MELEE)
visible_message("[src] licks [tasted]!","You lick [tasted]. They taste rather like [tasted.get_taste_message()].","Slurp!")
-
/mob/living/proc/get_taste_message(allow_generic = TRUE, datum/species/mrace)
if(!vore_taste && !allow_generic)
return FALSE
diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm
index 7038e9df7c..3a7cd4b03f 100644
--- a/code/modules/zombie/items.dm
+++ b/code/modules/zombie/items.dm
@@ -12,10 +12,10 @@
var/icon_right = "bloodhand_right"
hitsound = 'sound/hallucinations/growl1.ogg'
force = 18
- sharpness = IS_SHARP_ACCURATE //it's a claw, they're sharp.
+ sharpness = SHARP_POINTY //it's a claw, they're sharp.
damtype = "brute"
total_mass = TOTAL_MASS_HAND_REPLACEMENT
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
wound_bonus = -30
bare_wound_bonus = 15
@@ -37,11 +37,11 @@
if(!proximity_flag)
return
else
- if(istype(target, /obj/)) //do far more damage to non mobs so we can get through airlocks
+ if(istype(target, /obj)) //do far more damage to non mobs so we can get through airlocks
var/obj/target_object = target
target_object.take_damage(force * 3, BRUTE, "melee", 0)
- else
- if(isliving(target) && ishuman(target))
+ else if(isliving(target))
+ if(ishuman(target))
try_to_zombie_infect(target)
else
check_feast(target, user)
diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm
index 3d045ba31e..2681f781a9 100644
--- a/code/modules/zombie/organs.dm
+++ b/code/modules/zombie/organs.dm
@@ -93,7 +93,8 @@
playsound(owner.loc, 'sound/hallucinations/far_noise.ogg', 50, 1)
owner.do_jitter_animation(living_transformation_time)
owner.Stun(living_transformation_time)
- to_chat(owner, "You are now a zombie!")
+ to_chat(owner, "You are now a zombie! You claw and bite, turning your fellow crewmembers into friends that help spread the plague.")
+ to_chat(owner, "You are a zombie. Please act like one. Letting the crew remove the tumor inside your brain is a dick move to whoever infected you. Please do not do it.")
/obj/item/organ/zombie_infection/nodamage
causes_damage = FALSE
diff --git a/config/config.txt b/config/config.txt
index d6d0097c21..46f9a0cdc4 100644
--- a/config/config.txt
+++ b/config/config.txt
@@ -525,3 +525,7 @@ FAIL2TOPIC_RULE_NAME _dd_fail2topic
## Enable automatic profiling - Byond 513.1506 and newer only.
#AUTO_PROFILE
+
+## Uncomment to enable global ban DB using the provided URL. The API should expect to receive a ckey at the end of the URL.
+## More API details can be found here: https://centcom.melonmesa.com
+CENTCOM_BAN_DB https://centcom.melonmesa.com/ban/search
diff --git a/html/changelog.html b/html/changelog.html
index d0731d740c..58a5dcd1b7 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -50,6 +50,449 @@
-->
+
09 August 2020
+
Hatterhat updated:
+
+ - Proto-kinetic glaives (not crushers) can parry now.
+
+
MrJWhit updated:
+
+ - Adds a second shutter on the top of the hop line
+
+
silicons updated:
+
+ - immovable rods no longer drop down chasms
+ - fun removal: squeaking objects now have an 1 second cooldown between squeaks, and will have a 33% chance of interrupting any other squeaking object when Cross()ing, meaning no more ear-fuck conveyor belts.
+
+
+
08 August 2020
+
DeltaFire15 updated:
+
+ - Roundstart cultists now start with a replica fabricator - no brass though, make your own.
+ - Kindle cast time: 10 > 15, mute after stun end: 2 > 5, slur after mute end: 3 > 5
+ - The ratvarian spear no longer adds negative vitality under very specific circumstances.
+ - The Ratvarian Spear can parry now! Short parries with low leeway, but low cooldown.
+ - The brass claw, a implant-based weapon which gains combo on consecutive hits against the same target.
+ - The sigil of rites, a sigil used to perform various rites with a cost of power and materials
+ - The Rite of Advancement: Used to add a organ or cyberimplant to a clockie without need for surgery.
+ - The Rite of Woundmending: Used to heal all wounds on another cultist, causing toxins damage in return.
+ - The Rite of the Claw: Used to summon a brass claw implant. Maximum of 4 uses per round.
+
+
Hatterhat updated:
+
+ - You can now buy a toolbox's worth of Mosin-Nagant ammo for a fairly discounted price.
+ - Revolvers from the dedicated kit now have reskinning capabilities.
+ - You can now actually buy the riflery primer, which lets you pump shotguns and work the Mosin's bolt faster.
+ - Bulldog slug magazines now have a unique sprite.
+
+
Ludox235 updated:
+
+ - Removed an abductee objective that told you to remove all oxygen.
+ - Added a new abductee objective to replace the removed one.
+
+
Sishen1542 updated:
+
+ - 🅱️oneless
+ - squishy slime emotes
+
+
timothyteakettle updated:
+
+ - heparin makes you bleed half as much now
+ - cuts make you bleed 25% less now
+ - more items in the loadout and loadout has subcategories now for easier searching
+
+
+
07 August 2020
+
dapnee updated:
+
+ - fixed active tufs on some space ruins, murderdome VR, and a few on pubby, changed cargo autolathe to techfab, messed with pipe room leading to monastery.
+
+
lolman360 updated:
+
+ - vendors are now unanchored when tipped. it just fell over it's not bolted to the ground anymore.
+ - podpeople no fat when sunbathing.
+
+
silicons updated:
+
+ - explosions only recurse one level into storage before dropping 1 level per storage layer.
+ - volumetric storage is now minimum 16 pixels per item because 8 was ridiculous
+ - shieldbash balanace --> balance
+ - attempting to send too long of an emote will now reflect it back to you instead of cutting it off and discarding the overflow.
+ - holoparasites can now play music
+ - lethal blood now causes damaging bleeding instead of outright gibbing
+
+
+
06 August 2020
+
Auris456852 updated:
+
+ - Added B.O.O.P. Remote Control cartridges to the PTech.
+
+
Hatterhat updated:
+
+ - Proto-kinetic glaives! Essentially a proto-kinetic crusher with a different blade, handguard, and goliath hide grip. Expensive, but elegant.
+ - Door charges no longer knock people out.
+
+
Ludox235 updated:
+
+ - You can now buy damaged AI upload modules in the traitor's uplink.
+
+
Seris02 updated:
+
+
Trilbyspaceclone updated:
+
+ - 4 New blends of tea have been shipped to the station, and how to make them has been leaked!
+
+
b1tt3r1n0 updated:
+
+ - Added the warp implant
+
+
dapnee updated:
+
+ - added a hallway to telecoms for engineers to get there on meta
+
+
kappa-sama updated:
+
+ - dildo circuit assemblies
+
+
lolman360 updated:
+
+ - The Tendril-Mother on Lavaland has remembered how to make ashwalkers who know how to speak Draconic again.
+
+
timothyteakettle updated:
+
+ - nanotrasen has decided to fire all disabled members of the security division and confiscate certain sentimental items from doctors
+ - the custom tongue preference now passes through cloning so you spawn with your selected tongue
+ - several changes to travelling traders so they look better and spawn slightly less often
+
+
zeroisthebiggay updated:
+
+ - nukies can buy holoparasites
+
+
+
04 August 2020
+
Seris02 updated:
+
+
timothyteakettle updated:
+
+ - due to further advancements in medical technology, you can now have holes poked into your body for fun and enjoyment
+
+
zeroisthebiggay updated:
+
+ - prefs for headpat wagging
+
+
+
03 August 2020
+
KeRSedChaplain updated:
+
+ - fixed clockwork guardians being able to reflect ranged weapons
+
+
Linzolle updated:
+
+ - uv penlight no longer invisible
+
+
dapnee updated:
+
+ - active turfs on box and xenohive, maintenance bar APC not being stringed correctly, turned a monitor to face a direction that makes sense, changed tag of camera in gravgen being misnamed
+
+
silicons updated:
+
+ - shoves have been buffed to apply a status effect rather than a 0.85 movespeed modifier, meaning repeatedly shoving someone now renews the debuff
+ - shoves now stagger for 3.5 seconds.
+ - war operatives now actually time 20 minutes since roundstart to depart instead of 15.
+ - explosive stand bombs can now be examined from any distance
+ - explosive stand bombs are now a component.
+
+
+
02 August 2020
+
Auris456852 updated:
+
+ - Added B.O.O.P. Remote Control cartridges to the PTech.
+
+
Hatterhat updated:
+
+ - Durathread reinforcement kits! Sprites by Toriate, sets jumpsuit armor to durathread levels, craft in the crafting menu.
+
+
KeRSedChaplain updated:
+
+ - The belligerent scripture and a brass multitool, and a new marauder variant which act similar to holoparasites/guardian spirits.
+ - Removed the abductor teleport consoles they get, removes abscond for the time being as I've not seen much use for it other than just spamming it and hoping you end up in the armory.
+ - moved around scriptures to make the cult work better as being based around the station, makes the Ark scream more often and work as a summonable object, clockwork armor now has a flat 0 defense up to 10 instead of negatives against laser damage. Makes the Ark work better in a station based setting, as well as the Heralds beacon in case It works for the mode.
+ - added powerloaderstep.ogg for Neovgre
+ - changes 'Dread_Ipad.dmi' to 'clockwork_slab.dmi'
+
+
MrJWhit updated:
+
+ - Adjusts abductor spawntext
+
+
Seris02 updated:
+
+
dapnee updated:
+
+ - fixed active turfs on wizard ruin and space hermit, fixed missing APC's and added a light on Delta
+
+
ike709 and bobbahbrown updated:
+
+ - Admins can now see your bans on (some) other servers.
+
+
kappa-sama updated:
+
+ - chaplain cultists being able to convert people to full clockwork cult status
+
+
timothyteakettle updated:
+
+ - combat mode now has weaker buffs in terms of damage dealt and took for being or not being in the mode
+ - damage debuff for laying down has been decreased from 0.5x to 0.7x
+
+
+
01 August 2020
+
dapnee updated:
+
+ - added cake hat to bar, adds another atmostech spawn
+ - sinks point in the right direction, APC won't spawn off the wall in circuits
+ - changes commissary APC so it actually powers the room, adds a missing AIR alarm, arrivals no longer has active atmos tiles.
+
+
silicons updated:
+
+ - toy shotguns no longer need 2 hands to fire
+ - being on fire works again.
+
+
timothyteakettle updated:
+
+ - monkeys no longer continuously bleed everywhere
+
+
+
30 July 2020
+
Adelphon updated:
+
+ - Created a Cosmetic version of the camo.
+
+
Arturlang updated:
+
+ - Bloodsucker LifeTick runs from BiologicalLife now
+
+
Ryll-Ryll ported by silicons updated:
+
+ - Shoelaces are now a thing. You can untie them by laying down next to someone.
+ - shoes now have lace delays and some can't be laced at all
+ - do after now tracks who's interacting with who, meaning some actions now break when the target moves away.
+
+
SiliconMain updated:
+
+ - Ported the long range atmos analyzer from sk*rat, credit to NotRanged
+
+
silicons updated:
+
+ - energy sword perfect parries now reflect projectiles back at their shooters.
+ - any mob can now parry if they have the right item
+ - beam rifles now go into emitters properly
+ - clickdelay has been refactored into an experimental hybrid system. Check code/modules/mob/clickdelay.dm for more information.
+ - Resisting no longer checks clickdelay, but is standardized to a 2 second per resist system for most forms of resisting. It still sets clickdelay, though.
+ - Meters have been added for estimating time until next attack/resist. Won't be that useful due to our clickdelay currently being very short, though. They're visible from your hand and resist HUD elements. experimental: Most attacks and forms of attacking (minus unarmed because it's too much of a pain to refactor how hugs/gloves of the north star works) now check for time-since-last-attack rather than making it so you can't attack for said time. This means you can very quickly switch to a gun from a melee weapon, whereas in the old system a melee weapon would put you on lockout for 0.8 seconds, in the new system all the gun cares about is that you did not attack for at least 0.4 seconds.
+ - All clickdelay setting/reading are now procs, so it should be trivial to implement another system where drawing/switching to a weapon requires you to have it out for x seconds before using it. I am not personally doing it at this point in time though because it will likely just annoy everyone with no real gain unless we do something like putting a 0.8 second switch-to cooldown for guns (which I did not, yet)
+ - attack_hand has been refactored to on_attack_hand remove: sexchems no longer impact click delay
+ - turrets now automatically stagger their shots. Happy parrying/blocking.
+ - turrets now speed_process, they were shooting slower than they should be
+ - anything can now block with the right items
+
+
timothyteakettle updated:
+
+ - some crafted crates won't contain items now, and thus have stopped breaking the laws of physics
+ - beepskys hats now follow the laws of gravity and move up/down when he bobs up and down
+
+
+
29 July 2020
+
DeltaFire15 updated:
+
+ - The 'Naked' outfit is no longer broken.
+
+
Ghommie updated:
+
+ - fixed cremator trays, paleness examination strings, chat message for stamping paper, looping sounds, load away missions/VR admin verb, access requirements for using the sechuds.
+ - Alt-Clicking a cigarette packet should pull the lighter out first if present, then cigarettes.
+
+
Hatterhat updated:
+
+ - Directional windows can now be rotated counterclockwise properly again.
+
+
NecromancerAnne, Sirich96 updated:
+
+ - Stunbaton sprites by Sirich96.
+ - New sprites for the stunsword.
+
+
necromanceranne updated:
+
+ - Adds some in-hands for the rapier sheath.
+
+
timothyteakettle updated:
+
+ - tail wagging should work in all cases now
+ - bluespace jars work as intended now
+ - aliens can remove embeds now
+ - bloodsuckers are not affected by bloodloss
+
+
zeroisthebiggay updated:
+
+ - Flannel jackets and bartender winter coat
+
+
+
28 July 2020
+
Cacogen updated:
+
+ - OSHA has more pull than anyone could have expected. All armor provided by Nanotrasen and the syndicate now have tags that accurately lists defenses and resistances of a piece of clothing.
+
+
CameronWoof updated:
+
+ - Exotic seed crates now contain a spaceman's trumpet seed packet.
+
+
EmeraldSundisk updated:
+
+ - Renovates Snow Taxi's northeast bathroom to have multiple non-urinal toilets and showers
+ - Adds signage/labeling to improve map readability
+ - Adds a bathroom to the northwest station
+ - Adds a filing cabinet to the cargo department
+ - Area designation adjustments to account for the above changes
+ - Adds a missing airlock cyclelink near medical
+
+
Ludox235 updated:
+
+ - Makes the flavour text that appears when you become a zombie tell you to act like one.
+
+
MrJWhit updated:
+
+ - Decluttered toxins and hid the yellow mix line in atmos, for metastation
+
+
SiliconMain updated:
+
+ - Paramedic heirloom is now a zippo
+ - Durathread belts now protect their contents from radiation, and can hold full sized extinguishers
+
+
Sishen1542 updated:
+
+
dapnee updated:
+
+ - added a fan to the listening outpost
+ - added two missing r-walls near the SM, removed random light and wire node below the engine, and fixed the missing cable in the courtroom on Kilo
+
+
kappa-sama updated:
+
+ - Stimpaks cost 5tc once more, up from 3tc.
+
+
silicons updated:
+
+ - polychromatic cloaks to loadout
+ - no more self healing with medibeam guns
+ - oh no, taser buff. alt fire delay dropped to 0.4 seconds.
+ - you can now shoot yourself by disarm-intenting yourself with a gun.
+
+
timothyteakettle updated:
+
+ - species code is now slightly less messy
+ - slight tweak to how material crafting works
+ - changed up pet carriers / bluespace jars a bit so you can't fit certain things inside them and also the text shown for resist times is accurate
+
+
zeroisthebiggay updated:
+
+ - Black Box theft objective
+
+
+
27 July 2020
+
Hatterhat updated:
+
+ - Training bokkens! Make 'em from wood, use 'em in-hand to toggle between harmful and not-so-harmful, practice your parrying with them!
+ - Marker beacons should have a sprite again.
+
+
silicons updated:
+
+ - clownops and clown mobs now share the same faction. HONK!
+
+
timothyteakettle updated:
+
+ - modern pickle technology now allows people who have been turned into pickles, to be retrieved through the medical course of dying
+
+
+
26 July 2020
+
DeltaFire15 updated:
+
+ - Organs now decay again.
+
+
Iatots updated:
+
+ - Licking wounds now may cause you to spit out a hairball once in a while!
+ - You can now craft a catgirl plushie with 3 of a new ingredient occasionally found in medbay!
+
+
dapnee updated:
+
+ - removed legacy public mining shuttle area and remade lounge
+
+
+
25 July 2020
+
CameronWoof updated:
+
+ - Aloe now has an icon.
+
+
timothyteakettle updated:
+
+ - beepsky replaces the word THREAT_LEVEL with the actual threat level
+
+
+
24 July 2020
+
EmeraldSundisk updated:
+
+ - Adds a CMO office, along with Virology and Genetics labs to Omega Station
+ - Adds a second chemistry station to the chemistry lab
+ - Adjusts the locations of some objects in medical to accommodate these new additions
+ - Relocates the morgue
+ - Relocates items in impacted areas of maintenance as well as the library
+ - Fixes an air line Bartholomew somehow knocked out
+
+
Linzolle updated:
+
+ - wounds now have a description on examine
+
+
Owai-Seek updated:
+
+ - Meatball Sub, Meatloaf + Meatloaf Slices, Bear Chili, Mashed Potatoes
+ - Buttered Potatoes, Fancy Cracker Pack, Spiral Soup, Sweet and Sour Chicken
+ - Organised the Food DMI a bit.
+ - Deleted some stray pixels on some sprites.
+ - Nuggie boxes are now centered correctly.
+ - Icons for the the food items in this PR.
+
+
Sneakyrat6 updated:
+
+ - Fixes dressers not giving you undies
+ - Fixes Snaxi not loading properly because of typos
+ - You can now burn photos
+
+
Zandario updated:
+
+ - Murdered **tipes** and gave birth to **is**.
+
+
silicons updated:
+
+ - sanitization now doesn't cut off 15.7 or something million possible colors from character preferences (instead of only allowing 16 values for R G and B, it now allows 256 each)
+ - projectiles are by default 17.5 tiles per second instead of 12.5
+
+
timothyteakettle updated:
+
+ - due to recent innovative research in the medical field, you now have bones
+ - zombie claws are now sharp and do less damage, but can destroy non-lifeforms far faster
+ - zombies now take less stamina damage
+ - beepsky can now wear hats
+
+
zeroisthebiggay updated:
+
+ - rad and kravglove sprites
+
+
23 July 2020
DeltaFire15 updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 45d8e6ebe5..55bb782766 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -26476,3 +26476,345 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- bugfix: tendril chests being empty
zeroisthebiggay:
- rscadd: fetish content
+2020-07-24:
+ EmeraldSundisk:
+ - rscadd: Adds a CMO office, along with Virology and Genetics labs to Omega Station
+ - rscadd: Adds a second chemistry station to the chemistry lab
+ - tweak: Adjusts the locations of some objects in medical to accommodate these new
+ additions
+ - tweak: Relocates the morgue
+ - tweak: Relocates items in impacted areas of maintenance as well as the library
+ - bugfix: Fixes an air line Bartholomew somehow knocked out
+ Linzolle:
+ - bugfix: wounds now have a description on examine
+ Owai-Seek:
+ - rscadd: Meatball Sub, Meatloaf + Meatloaf Slices, Bear Chili, Mashed Potatoes
+ - rscadd: Buttered Potatoes, Fancy Cracker Pack, Spiral Soup, Sweet and Sour Chicken
+ - tweak: Organised the Food DMI a bit.
+ - tweak: Deleted some stray pixels on some sprites.
+ - tweak: Nuggie boxes are now centered correctly.
+ - imageadd: Icons for the the food items in this PR.
+ Sneakyrat6:
+ - bugfix: Fixes dressers not giving you undies
+ - bugfix: Fixes Snaxi not loading properly because of typos
+ - rscadd: You can now burn photos
+ Zandario:
+ - spellcheck: Murdered **tipes** and gave birth to **is**.
+ silicons:
+ - tweak: sanitization now doesn't cut off 15.7 or something million possible colors
+ from character preferences (instead of only allowing 16 values for R G and B,
+ it now allows 256 each)
+ - balance: projectiles are by default 17.5 tiles per second instead of 12.5
+ timothyteakettle:
+ - rscadd: due to recent innovative research in the medical field, you now have bones
+ - tweak: zombie claws are now sharp and do less damage, but can destroy non-lifeforms
+ far faster
+ - tweak: zombies now take less stamina damage
+ - rscadd: beepsky can now wear hats
+ zeroisthebiggay:
+ - imageadd: rad and kravglove sprites
+2020-07-25:
+ CameronWoof:
+ - bugfix: Aloe now has an icon.
+ timothyteakettle:
+ - bugfix: beepsky replaces the word THREAT_LEVEL with the actual threat level
+2020-07-26:
+ DeltaFire15:
+ - bugfix: Organs now decay again.
+ Iatots:
+ - tweak: Licking wounds now may cause you to spit out a hairball once in a while!
+ - rscadd: You can now craft a catgirl plushie with 3 of a new ingredient occasionally
+ found in medbay!
+ dapnee:
+ - tweak: removed legacy public mining shuttle area and remade lounge
+2020-07-27:
+ Hatterhat:
+ - rscadd: Training bokkens! Make 'em from wood, use 'em in-hand to toggle between
+ harmful and not-so-harmful, practice your parrying with them!
+ - bugfix: Marker beacons should have a sprite again.
+ silicons:
+ - rscadd: clownops and clown mobs now share the same faction. HONK!
+ timothyteakettle:
+ - bugfix: modern pickle technology now allows people who have been turned into pickles,
+ to be retrieved through the medical course of dying
+2020-07-28:
+ Cacogen:
+ - rscadd: OSHA has more pull than anyone could have expected. All armor provided
+ by Nanotrasen and the syndicate now have tags that accurately lists defenses
+ and resistances of a piece of clothing.
+ CameronWoof:
+ - tweak: Exotic seed crates now contain a spaceman's trumpet seed packet.
+ EmeraldSundisk:
+ - rscadd: Renovates Snow Taxi's northeast bathroom to have multiple non-urinal toilets
+ and showers
+ - rscadd: Adds signage/labeling to improve map readability
+ - rscadd: Adds a bathroom to the northwest station
+ - rscadd: Adds a filing cabinet to the cargo department
+ - tweak: Area designation adjustments to account for the above changes
+ - bugfix: Adds a missing airlock cyclelink near medical
+ Ludox235:
+ - tweak: Makes the flavour text that appears when you become a zombie tell you to
+ act like one.
+ MrJWhit:
+ - tweak: Decluttered toxins and hid the yellow mix line in atmos, for metastation
+ SiliconMain:
+ - tweak: Paramedic heirloom is now a zippo
+ - tweak: Durathread belts now protect their contents from radiation, and can hold
+ full sized extinguishers
+ Sishen1542:
+ - rscdel: removed zoomba
+ dapnee:
+ - tweak: added a fan to the listening outpost
+ - bugfix: added two missing r-walls near the SM, removed random light and wire node
+ below the engine, and fixed the missing cable in the courtroom on Kilo
+ kappa-sama:
+ - balance: Stimpaks cost 5tc once more, up from 3tc.
+ silicons:
+ - rscadd: polychromatic cloaks to loadout
+ - rscdel: no more self healing with medibeam guns
+ - balance: oh no, taser buff. alt fire delay dropped to 0.4 seconds.
+ - rscadd: you can now shoot yourself by disarm-intenting yourself with a gun.
+ timothyteakettle:
+ - tweak: species code is now slightly less messy
+ - bugfix: slight tweak to how material crafting works
+ - bugfix: changed up pet carriers / bluespace jars a bit so you can't fit certain
+ things inside them and also the text shown for resist times is accurate
+ zeroisthebiggay:
+ - rscadd: Black Box theft objective
+2020-07-29:
+ DeltaFire15:
+ - bugfix: The 'Naked' outfit is no longer broken.
+ Ghommie:
+ - bugfix: fixed cremator trays, paleness examination strings, chat message for stamping
+ paper, looping sounds, load away missions/VR admin verb, access requirements
+ for using the sechuds.
+ - tweak: Alt-Clicking a cigarette packet should pull the lighter out first if present,
+ then cigarettes.
+ Hatterhat:
+ - bugfix: Directional windows can now be rotated counterclockwise properly again.
+ NecromancerAnne, Sirich96:
+ - rscadd: Stunbaton sprites by Sirich96.
+ - rscadd: New sprites for the stunsword.
+ necromanceranne:
+ - rscadd: Adds some in-hands for the rapier sheath.
+ timothyteakettle:
+ - bugfix: tail wagging should work in all cases now
+ - bugfix: bluespace jars work as intended now
+ - bugfix: aliens can remove embeds now
+ - bugfix: bloodsuckers are not affected by bloodloss
+ zeroisthebiggay:
+ - rscadd: Flannel jackets and bartender winter coat
+2020-07-30:
+ Adelphon:
+ - rscadd: Created a Cosmetic version of the camo.
+ Arturlang:
+ - code_imp: Bloodsucker LifeTick runs from BiologicalLife now
+ Ryll-Ryll ported by silicons:
+ - rscadd: Shoelaces are now a thing. You can untie them by laying down next to someone.
+ - tweak: shoes now have lace delays and some can't be laced at all
+ - refactor: do after now tracks who's interacting with who, meaning some actions
+ now break when the target moves away.
+ SiliconMain:
+ - rscadd: Ported the long range atmos analyzer from sk*rat, credit to NotRanged
+ silicons:
+ - rscadd: energy sword perfect parries now reflect projectiles back at their shooters.
+ - balance: any mob can now parry if they have the right item
+ - rscadd: beam rifles now go into emitters properly
+ - refactor: clickdelay has been refactored into an experimental hybrid system. Check
+ code/modules/mob/clickdelay.dm for more information.
+ - balance: Resisting no longer checks clickdelay, but is standardized to a 2 second
+ per resist system for most forms of resisting. It still sets clickdelay, though.
+ - rscadd: 'Meters have been added for estimating time until next attack/resist.
+ Won''t be that useful due to our clickdelay currently being very short, though.
+ They''re visible from your hand and resist HUD elements. experimental: Most
+ attacks and forms of attacking (minus unarmed because it''s too much of a pain
+ to refactor how hugs/gloves of the north star works) now check for time-since-last-attack
+ rather than making it so you can''t attack for said time. This means you can
+ very quickly switch to a gun from a melee weapon, whereas in the old system
+ a melee weapon would put you on lockout for 0.8 seconds, in the new system all
+ the gun cares about is that you did not attack for at least 0.4 seconds.'
+ - code_imp: All clickdelay setting/reading are now procs, so it should be trivial
+ to implement another system where drawing/switching to a weapon requires you
+ to have it out for x seconds before using it. I am not personally doing it at
+ this point in time though because it will likely just annoy everyone with no
+ real gain unless we do something like putting a 0.8 second switch-to cooldown
+ for guns (which I did not, yet)
+ - refactor: 'attack_hand has been refactored to on_attack_hand remove: sexchems
+ no longer impact click delay'
+ - rscadd: turrets now automatically stagger their shots. Happy parrying/blocking.
+ - bugfix: turrets now speed_process, they were shooting slower than they should
+ be
+ - balance: anything can now block with the right items
+ timothyteakettle:
+ - bugfix: some crafted crates won't contain items now, and thus have stopped breaking
+ the laws of physics
+ - tweak: beepskys hats now follow the laws of gravity and move up/down when he bobs
+ up and down
+2020-08-01:
+ dapnee:
+ - tweak: added cake hat to bar, adds another atmostech spawn
+ - bugfix: sinks point in the right direction, APC won't spawn off the wall in circuits
+ - bugfix: changes commissary APC so it actually powers the room, adds a missing
+ AIR alarm, arrivals no longer has active atmos tiles.
+ silicons:
+ - tweak: toy shotguns no longer need 2 hands to fire
+ - bugfix: being on fire works again.
+ timothyteakettle:
+ - bugfix: monkeys no longer continuously bleed everywhere
+2020-08-02:
+ Auris456852:
+ - rscadd: Added B.O.O.P. Remote Control cartridges to the PTech.
+ Hatterhat:
+ - rscadd: Durathread reinforcement kits! Sprites by Toriate, sets jumpsuit armor
+ to durathread levels, craft in the crafting menu.
+ KeRSedChaplain:
+ - rscadd: The belligerent scripture and a brass multitool, and a new marauder variant
+ which act similar to holoparasites/guardian spirits.
+ - rscdel: Removed the abductor teleport consoles they get, removes abscond for the
+ time being as I've not seen much use for it other than just spamming it and
+ hoping you end up in the armory.
+ - tweak: moved around scriptures to make the cult work better as being based around
+ the station, makes the Ark scream more often and work as a summonable object,
+ clockwork armor now has a flat 0 defense up to 10 instead of negatives against
+ laser damage. Makes the Ark work better in a station based setting, as well
+ as the Heralds beacon in case It works for the mode.
+ - soundadd: added powerloaderstep.ogg for Neovgre
+ - tweak: changes 'Dread_Ipad.dmi' to 'clockwork_slab.dmi'
+ MrJWhit:
+ - tweak: Adjusts abductor spawntext
+ Seris02:
+ - bugfix: fixed replica pods
+ dapnee:
+ - bugfix: fixed active turfs on wizard ruin and space hermit, fixed missing APC's
+ and added a light on Delta
+ ike709 and bobbahbrown:
+ - rscadd: Admins can now see your bans on (some) other servers.
+ kappa-sama:
+ - bugfix: chaplain cultists being able to convert people to full clockwork cult
+ status
+ timothyteakettle:
+ - tweak: combat mode now has weaker buffs in terms of damage dealt and took for
+ being or not being in the mode
+ - tweak: damage debuff for laying down has been decreased from 0.5x to 0.7x
+2020-08-03:
+ KeRSedChaplain:
+ - bugfix: fixed clockwork guardians being able to reflect ranged weapons
+ Linzolle:
+ - bugfix: uv penlight no longer invisible
+ dapnee:
+ - bugfix: active turfs on box and xenohive, maintenance bar APC not being stringed
+ correctly, turned a monitor to face a direction that makes sense, changed tag
+ of camera in gravgen being misnamed
+ silicons:
+ - rscadd: shoves have been buffed to apply a status effect rather than a 0.85 movespeed
+ modifier, meaning repeatedly shoving someone now renews the debuff
+ - balance: shoves now stagger for 3.5 seconds.
+ - tweak: war operatives now actually time 20 minutes since roundstart to depart
+ instead of 15.
+ - balance: explosive stand bombs can now be examined from any distance
+ - code_imp: explosive stand bombs are now a component.
+2020-08-04:
+ Seris02:
+ - bugfix: lizard spines
+ timothyteakettle:
+ - rscadd: due to further advancements in medical technology, you can now have holes
+ poked into your body for fun and enjoyment
+ zeroisthebiggay:
+ - rscadd: prefs for headpat wagging
+2020-08-06:
+ Auris456852:
+ - rscadd: Added B.O.O.P. Remote Control cartridges to the PTech.
+ Hatterhat:
+ - rscadd: Proto-kinetic glaives! Essentially a proto-kinetic crusher with a different
+ blade, handguard, and goliath hide grip. Expensive, but elegant.
+ - balance: Door charges no longer knock people out.
+ Ludox235:
+ - rscadd: You can now buy damaged AI upload modules in the traitor's uplink.
+ Seris02:
+ - bugfix: fixed ghost chilis
+ Trilbyspaceclone:
+ - rscadd: 4 New blends of tea have been shipped to the station, and how to make
+ them has been leaked!
+ b1tt3r1n0:
+ - rscadd: Added the warp implant
+ dapnee:
+ - tweak: added a hallway to telecoms for engineers to get there on meta
+ kappa-sama:
+ - rscdel: dildo circuit assemblies
+ lolman360:
+ - bugfix: The Tendril-Mother on Lavaland has remembered how to make ashwalkers who
+ know how to speak Draconic again.
+ timothyteakettle:
+ - tweak: nanotrasen has decided to fire all disabled members of the security division
+ and confiscate certain sentimental items from doctors
+ - tweak: the custom tongue preference now passes through cloning so you spawn with
+ your selected tongue
+ - tweak: several changes to travelling traders so they look better and spawn slightly
+ less often
+ zeroisthebiggay:
+ - rscadd: nukies can buy holoparasites
+2020-08-07:
+ dapnee:
+ - bugfix: fixed active tufs on some space ruins, murderdome VR, and a few on pubby,
+ changed cargo autolathe to techfab, messed with pipe room leading to monastery.
+ lolman360:
+ - bugfix: vendors are now unanchored when tipped. it just fell over it's not bolted
+ to the ground anymore.
+ - bugfix: podpeople no fat when sunbathing.
+ silicons:
+ - balance: explosions only recurse one level into storage before dropping 1 level
+ per storage layer.
+ - tweak: volumetric storage is now minimum 16 pixels per item because 8 was ridiculous
+ - spellcheck: shieldbash balanace --> balance
+ - rscadd: attempting to send too long of an emote will now reflect it back to you
+ instead of cutting it off and discarding the overflow.
+ - rscadd: holoparasites can now play music
+ - balance: lethal blood now causes damaging bleeding instead of outright gibbing
+2020-08-08:
+ DeltaFire15:
+ - balance: Roundstart cultists now start with a replica fabricator - no brass though,
+ make your own.
+ - balance: 'Kindle cast time: 10 > 15, mute after stun end: 2 > 5, slur after mute
+ end: 3 > 5'
+ - bugfix: The ratvarian spear no longer adds negative vitality under very specific
+ circumstances.
+ - balance: The Ratvarian Spear can parry now! Short parries with low leeway, but
+ low cooldown.
+ - rscadd: The brass claw, a implant-based weapon which gains combo on consecutive
+ hits against the same target.
+ - rscadd: The sigil of rites, a sigil used to perform various rites with a cost
+ of power and materials
+ - rscadd: 'The Rite of Advancement: Used to add a organ or cyberimplant to a clockie
+ without need for surgery.'
+ - rscadd: 'The Rite of Woundmending: Used to heal all wounds on another cultist,
+ causing toxins damage in return.'
+ - rscadd: 'The Rite of the Claw: Used to summon a brass claw implant. Maximum of
+ 4 uses per round.'
+ Hatterhat:
+ - rscadd: You can now buy a toolbox's worth of Mosin-Nagant ammo for a fairly discounted
+ price.
+ - rscadd: Revolvers from the dedicated kit now have reskinning capabilities.
+ - bugfix: You can now actually buy the riflery primer, which lets you pump shotguns
+ and work the Mosin's bolt faster.
+ - imageadd: Bulldog slug magazines now have a unique sprite.
+ Ludox235:
+ - rscdel: Removed an abductee objective that told you to remove all oxygen.
+ - rscadd: Added a new abductee objective to replace the removed one.
+ Sishen1542:
+ - tweak: "\U0001F171\uFE0Foneless"
+ - rscadd: squishy slime emotes
+ timothyteakettle:
+ - tweak: heparin makes you bleed half as much now
+ - tweak: cuts make you bleed 25% less now
+ - rscadd: more items in the loadout and loadout has subcategories now for easier
+ searching
+2020-08-09:
+ Hatterhat:
+ - rscadd: Proto-kinetic glaives (not crushers) can parry now.
+ MrJWhit:
+ - rscadd: Adds a second shutter on the top of the hop line
+ silicons:
+ - bugfix: immovable rods no longer drop down chasms
+ - rscdel: 'fun removal: squeaking objects now have an 1 second cooldown between
+ squeaks, and will have a 33% chance of interrupting any other squeaking object
+ when Cross()ing, meaning no more ear-fuck conveyor belts.'
diff --git a/html/changelogs/AutoChangeLog-pr-12816.yml b/html/changelogs/AutoChangeLog-pr-12816.yml
deleted file mode 100644
index a984be4d5f..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12816.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "timothyteakettle"
-delete-after: True
-changes:
- - rscadd: "due to recent innovative research in the medical field, you now have bones"
diff --git a/html/changelogs/AutoChangeLog-pr-12821.yml b/html/changelogs/AutoChangeLog-pr-12821.yml
deleted file mode 100644
index 7861bbc536..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12821.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "silicons"
-delete-after: True
-changes:
- - balance: "projectiles are by default 17.5 tiles per second instead of 12.5"
diff --git a/html/changelogs/AutoChangeLog-pr-12828.yml b/html/changelogs/AutoChangeLog-pr-12828.yml
deleted file mode 100644
index 411f16a545..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12828.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-author: "Owai-Seek"
-delete-after: True
-changes:
- - rscadd: "Meatball Sub, Meatloaf + Meatloaf Slices, Bear Chili, Mashed Potatoes"
- - rscadd: "Buttered Potatoes, Fancy Cracker Pack, Spiral Soup, Sweet and Sour Chicken"
- - tweak: "Organised the Food DMI a bit."
- - tweak: "Deleted some stray pixels on some sprites."
- - tweak: "Nuggie boxes are now centered correctly."
- - imageadd: "Icons for the the food items in this PR."
diff --git a/html/changelogs/AutoChangeLog-pr-12848.yml b/html/changelogs/AutoChangeLog-pr-12848.yml
deleted file mode 100644
index 0e9bc70dbb..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12848.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "silicons"
-delete-after: True
-changes:
- - tweak: "sanitization now doesn't cut off 15.7 or something million possible colors from character preferences (instead of only allowing 16 values for R G and B, it now allows 256 each)"
diff --git a/html/changelogs/AutoChangeLog-pr-12854.yml b/html/changelogs/AutoChangeLog-pr-12854.yml
deleted file mode 100644
index 01f47e4c48..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12854.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Zandario"
-delete-after: True
-changes:
- - spellcheck: "Murdered **tipes** and gave birth to **is**."
diff --git a/html/changelogs/AutoChangeLog-pr-12856.yml b/html/changelogs/AutoChangeLog-pr-12856.yml
deleted file mode 100644
index 5fb888910b..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12856.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "zeroisthebiggay"
-delete-after: True
-changes:
- - imageadd: "rad and kravglove sprites"
diff --git a/html/changelogs/AutoChangeLog-pr-12860.yml b/html/changelogs/AutoChangeLog-pr-12860.yml
deleted file mode 100644
index 9703a35a80..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12860.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Sneakyrat6"
-delete-after: True
-changes:
- - rscadd: "You can now burn photos"
diff --git a/html/changelogs/AutoChangeLog-pr-12861.yml b/html/changelogs/AutoChangeLog-pr-12861.yml
deleted file mode 100644
index 448a343017..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12861.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Sneakyrat6"
-delete-after: True
-changes:
- - bugfix: "Fixes dressers not giving you undies"
diff --git a/html/changelogs/AutoChangeLog-pr-12866.yml b/html/changelogs/AutoChangeLog-pr-12866.yml
deleted file mode 100644
index 3a7e6d6972..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12866.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Sneakyrat6"
-delete-after: True
-changes:
- - bugfix: "Fixes Snaxi not loading properly because of typos"
diff --git a/html/changelogs/AutoChangeLog-pr-12867.yml b/html/changelogs/AutoChangeLog-pr-12867.yml
deleted file mode 100644
index 8f06bc7a06..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12867.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-author: "EmeraldSundisk"
-delete-after: True
-changes:
- - rscadd: "Adds a CMO office, along with Virology and Genetics labs to Omega Station"
- - rscadd: "Adds a second chemistry station to the chemistry lab"
- - tweak: "Adjusts the locations of some objects in medical to accommodate these new additions"
- - tweak: "Relocates the morgue"
- - tweak: "Relocates items in impacted areas of maintenance as well as the library"
- - bugfix: "Fixes an air line Bartholomew somehow knocked out"
diff --git a/html/changelogs/AutoChangeLog-pr-12869.yml b/html/changelogs/AutoChangeLog-pr-12869.yml
deleted file mode 100644
index c83506457b..0000000000
--- a/html/changelogs/AutoChangeLog-pr-12869.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: "timothyteakettle"
-delete-after: True
-changes:
- - tweak: "zombie claws are now sharp and do less damage, but can destroy non-lifeforms far faster"
- - tweak: "zombies now take less stamina damage"
diff --git a/icons/mob/clockwork_mobs.dmi b/icons/mob/clockwork_mobs.dmi
index 5985adf12d..54690f6cac 100644
Binary files a/icons/mob/clockwork_mobs.dmi and b/icons/mob/clockwork_mobs.dmi differ
diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi
index 00cffd9006..9490595484 100644
Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ
diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi
index fd3016ac89..52ef75020c 100644
Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ
diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi
index a2a8fcede6..0ad9452994 100644
Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ
diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi
index c361563da3..ecc6e2dd2c 100644
Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ
diff --git a/icons/mob/clothing/suit.dmi b/icons/mob/clothing/suit.dmi
index 9d97ae36b5..c94e8a46d3 100644
Binary files a/icons/mob/clothing/suit.dmi and b/icons/mob/clothing/suit.dmi differ
diff --git a/icons/mob/clothing/suit_digi.dmi b/icons/mob/clothing/suit_digi.dmi
index 2616c0b893..dd00713770 100644
Binary files a/icons/mob/clothing/suit_digi.dmi and b/icons/mob/clothing/suit_digi.dmi differ
diff --git a/icons/mob/clothing/uniform.dmi b/icons/mob/clothing/uniform.dmi
index fa376635f9..3d24a9addd 100644
Binary files a/icons/mob/clothing/uniform.dmi and b/icons/mob/clothing/uniform.dmi differ
diff --git a/icons/mob/clothing/uniform_digi.dmi b/icons/mob/clothing/uniform_digi.dmi
index af72ac0e7b..bcb894033e 100644
Binary files a/icons/mob/clothing/uniform_digi.dmi and b/icons/mob/clothing/uniform_digi.dmi differ
diff --git a/icons/mob/inhands/antag/clockwork_lefthand.dmi b/icons/mob/inhands/antag/clockwork_lefthand.dmi
index 88bd8ab710..080d7fdc83 100644
Binary files a/icons/mob/inhands/antag/clockwork_lefthand.dmi and b/icons/mob/inhands/antag/clockwork_lefthand.dmi differ
diff --git a/icons/mob/inhands/antag/clockwork_righthand.dmi b/icons/mob/inhands/antag/clockwork_righthand.dmi
index 20190e4add..42715d6e92 100644
Binary files a/icons/mob/inhands/antag/clockwork_righthand.dmi and b/icons/mob/inhands/antag/clockwork_righthand.dmi differ
diff --git a/icons/mob/inhands/equipment/belt_lefthand.dmi b/icons/mob/inhands/equipment/belt_lefthand.dmi
index beac56725a..81b12c60f9 100644
Binary files a/icons/mob/inhands/equipment/belt_lefthand.dmi and b/icons/mob/inhands/equipment/belt_lefthand.dmi differ
diff --git a/icons/mob/inhands/equipment/belt_righthand.dmi b/icons/mob/inhands/equipment/belt_righthand.dmi
index da31cc9710..42ed3a30c6 100644
Binary files a/icons/mob/inhands/equipment/belt_righthand.dmi and b/icons/mob/inhands/equipment/belt_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/hammers_lefthand.dmi b/icons/mob/inhands/weapons/hammers_lefthand.dmi
index 306fd0db8a..b753a1f181 100644
Binary files a/icons/mob/inhands/weapons/hammers_lefthand.dmi and b/icons/mob/inhands/weapons/hammers_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/hammers_righthand.dmi b/icons/mob/inhands/weapons/hammers_righthand.dmi
index 674e4d510b..7650f6c760 100644
Binary files a/icons/mob/inhands/weapons/hammers_righthand.dmi and b/icons/mob/inhands/weapons/hammers_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi
index 1e48d57ac7..0ca36ad43d 100644
Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi
index 5a5ee6f3db..59d7bbce69 100644
Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ
diff --git a/icons/mob/robots.dmi b/icons/mob/robots.dmi
index 2bb8af7c61..082bfb3c3e 100644
Binary files a/icons/mob/robots.dmi and b/icons/mob/robots.dmi differ
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index 60fe2f9839..30c23601a5 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/icons/mob/secbot_accessories.dmi b/icons/mob/secbot_accessories.dmi
new file mode 100644
index 0000000000..944aac44f3
Binary files /dev/null and b/icons/mob/secbot_accessories.dmi differ
diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi
index bebb625440..e1caad8279 100644
Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ
diff --git a/icons/obj/clockwork_objects.dmi b/icons/obj/clockwork_objects.dmi
index 1948bb605c..156d4fa0c6 100644
Binary files a/icons/obj/clockwork_objects.dmi and b/icons/obj/clockwork_objects.dmi differ
diff --git a/icons/obj/clothing/belt_overlays.dmi b/icons/obj/clothing/belt_overlays.dmi
index 7e09d425fb..1c22a0ad1b 100644
Binary files a/icons/obj/clothing/belt_overlays.dmi and b/icons/obj/clothing/belt_overlays.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index b982d450e4..60304999fa 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/reinf_kits.dmi b/icons/obj/clothing/reinf_kits.dmi
new file mode 100644
index 0000000000..3b23d53342
Binary files /dev/null and b/icons/obj/clothing/reinf_kits.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index fed81adfcc..e8a360bc87 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 57424c7b99..76f5722c8b 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index c27e03bb2a..5a9e1e54b6 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi
index 8c50e7da27..9c6df36f49 100644
Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ
diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi
index c93865ca77..5415f47528 100644
Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ
diff --git a/icons/obj/implants.dmi b/icons/obj/implants.dmi
index a6d4697673..b7cb90e9f4 100644
Binary files a/icons/obj/implants.dmi and b/icons/obj/implants.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index cf7a87d28b..57105cc089 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/lighting.dmi b/icons/obj/lighting.dmi
index 675005da91..0e262895fd 100644
Binary files a/icons/obj/lighting.dmi and b/icons/obj/lighting.dmi differ
diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi
index 43bc9c48aa..e7063b71db 100644
Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ
diff --git a/icons/obj/plushes.dmi b/icons/obj/plushes.dmi
index 3abb25d8b2..11d02a46cc 100644
Binary files a/icons/obj/plushes.dmi and b/icons/obj/plushes.dmi differ
diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi
index 67c1a59c51..16efcf262e 100644
Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 3996f0ead2..8db1156dea 100755
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi
index f1a8cf3c02..0a457777c2 100644
Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index 9f3d8911ec..9c35ddb75f 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -66,7 +66,9 @@ h1.alert, h2.alert {color: #000000;}
.passive {color: #660000;}
.userdanger {color: #ff0000; font-weight: bold; font-size: 3;}
-.danger {color: #ff0000;}
+.danger {color: #ff0000; font-weight: bold;}
+.tinydanger {color: #ff0000; font-size: 85%;}
+.smalldanger {color: #ff0000; font-size: 90%;}
.warning {color: #ff0000; font-style: italic;}
.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
.announce {color: #228b22; font-weight: bold;}
@@ -75,6 +77,9 @@ h1.alert, h2.alert {color: #000000;}
.rose {color: #ff5050;}
.info {color: #0000CC;}
.notice {color: #000099;}
+.tinynotice {color: #000099; font-size: 85%;}
+.smallnotice {color: #000099; font-size: 90%;}
+.smallnoticeital {color: #000099; font-style: italic; font-size: 90%;}
.boldnotice {color: #000099; font-weight: bold;}
.adminnotice {color: #0000ff;}
.adminhelp {color: #ff0000; font-weight: bold;}
diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm
index 5356214438..4fa2a51fac 100644
--- a/modular_citadel/code/datums/status_effects/chems.dm
+++ b/modular_citadel/code/datums/status_effects/chems.dm
@@ -53,7 +53,6 @@
if(last_checked_size != B.cached_size)
H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/breast_hypertrophy, multiplicative_slowdown = moveCalc)
- sizeMoveMod(moveCalc)
if (B.size == "huge")
if(prob(1))
@@ -70,16 +69,8 @@
log_reagent("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]")
to_chat(owner, "Your expansive chest has become a more managable size, liberating your movements.")
owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/breast_hypertrophy)
- sizeMoveMod(1)
return ..()
-/datum/status_effect/chem/breast_enlarger/proc/sizeMoveMod(var/value)
- if(cachedmoveCalc == value)
- return
- owner.next_move_modifier /= cachedmoveCalc
- owner.next_move_modifier *= value
- cachedmoveCalc = value
-
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/status_effect/chem/penis_enlarger
diff --git a/modular_citadel/code/game/objects/cit_screenshake.dm b/modular_citadel/code/game/objects/cit_screenshake.dm
index 188b8a48f9..222de37f82 100644
--- a/modular_citadel/code/game/objects/cit_screenshake.dm
+++ b/modular_citadel/code/game/objects/cit_screenshake.dm
@@ -45,18 +45,6 @@
. = ..()
shake_camera(user, (pressureSetting * 0.75 + 1), (pressureSetting * 0.75))
-/obj/item/attack(mob/living/M, mob/living/user)
- . = ..()
- if(force >= 15)
- shake_camera(user, ((force - 10) * 0.01 + 1), ((force - 10) * 0.01))
- if(M.client)
- switch (M.client.prefs.damagescreenshake)
- if (1)
- shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015))
- if (2)
- if(!CHECK_MOBILITY(M, MOBILITY_MOVE))
- shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015))
-
/obj/item/attack_obj(obj/O, mob/living/user)
. = ..()
if(force >= 20)
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index d428fc290a..378c70d187 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -1,496 +1,497 @@
//This is the file that handles donator loadout items.
-/datum/gear/pingcoderfailsafe
+/datum/gear/donator
name = "IF YOU SEE THIS, PING A CODER RIGHT NOW!"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/bikehorn/golden
+ category = LOADOUT_CATEGORY_DONATOR
ckeywhitelist = list("This entry should never appear with this variable set.") //If it does, then that means somebody fucked up the whitelist system pretty hard
-/datum/gear/donortestingbikehorn
+/datum/gear/donator/donortestingbikehorn
name = "Donor item testing bikehorn"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/bikehorn
geargroupID = list("DONORTEST") //This is a list mainly for the sake of testing, but geargroupID works just fine with ordinary strings
-/datum/gear/kevhorn
+/datum/gear/donator/kevhorn
name = "Airhorn"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/bikehorn/airhorn
ckeywhitelist = list("kevinz000")
-/datum/gear/cebusoap
+/datum/gear/donator/cebusoap
name = "Cebutris' soap"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/custom/ceb_soap
ckeywhitelist = list("cebutris")
-/datum/gear/kiaracloak
+/datum/gear/donator/kiaracloak
name = "Kiara's cloak"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/cloak/inferno
ckeywhitelist = list("inferno707")
-/datum/gear/kiaracollar
+/datum/gear/donator/kiaracollar
name = "Kiara's collar"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/petcollar/inferno
ckeywhitelist = list("inferno707")
-/datum/gear/kiaramedal
+/datum/gear/donator/kiaramedal
name = "Insignia of Steele"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/clothing/accessory/medal/steele
ckeywhitelist = list("inferno707")
-/datum/gear/hheart
+/datum/gear/donator/hheart
name = "The Hollow Heart"
- category = SLOT_WEAR_MASK
+ slot = SLOT_WEAR_MASK
path = /obj/item/clothing/mask/hheart
ckeywhitelist = list("inferno707")
-/datum/gear/engravedzippo
+/datum/gear/donator/engravedzippo
name = "Engraved zippo"
- category = SLOT_HANDS
+ slot = SLOT_HANDS
path = /obj/item/lighter/gold
ckeywhitelist = list("dirtyoldharry")
-/datum/gear/geisha
+/datum/gear/donator/geisha
name = "Geisha suit"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/geisha
ckeywhitelist = list("atiefling")
-/datum/gear/specialscarf
+/datum/gear/donator/specialscarf
name = "Special scarf"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/scarf/zomb
ckeywhitelist = list("zombierobin")
-/datum/gear/redmadcoat
+/datum/gear/donator/redmadcoat
name = "The Mad's labcoat"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/toggle/labcoat/mad/red
ckeywhitelist = list("zombierobin")
-/datum/gear/santahat
+/datum/gear/donator/santahat
name = "Santa hat"
- category = SLOT_HEAD
+ slot = SLOT_HEAD
path = /obj/item/clothing/head/santa/fluff
ckeywhitelist = list("illotafv")
-/datum/gear/reindeerhat
+/datum/gear/donator/reindeerhat
name = "Reindeer hat"
- category = SLOT_HEAD
+ slot = SLOT_HEAD
path = /obj/item/clothing/head/hardhat/reindeer/fluff
ckeywhitelist = list("illotafv")
-/datum/gear/treeplushie
+/datum/gear/donator/treeplushie
name = "Christmas tree plushie"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/tree
ckeywhitelist = list("illotafv")
-/datum/gear/santaoutfit
+/datum/gear/donator/santaoutfit
name = "Santa costume"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/space/santa/fluff
ckeywhitelist = list("illotafv")
-/datum/gear/treecloak
+/datum/gear/donator/treecloak
name = "Christmas tree cloak"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/cloak/festive
ckeywhitelist = list("illotafv")
-/datum/gear/carrotplush
+/datum/gear/donator/carrotplush
name = "Carrot plushie"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/carrot
ckeywhitelist = list("improvedname")
-/datum/gear/carrotcloak
+/datum/gear/donator/carrotcloak
name = "Carrot cloak"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/cloak/carrot
ckeywhitelist = list("improvedname")
-/datum/gear/albortorosamask
+/datum/gear/donator/albortorosamask
name = "Alborto Rosa mask"
- category = SLOT_WEAR_MASK
+ slot = SLOT_WEAR_MASK
path = /obj/item/clothing/mask/luchador/zigfie
ckeywhitelist = list("zigfie")
-/datum/gear/mankini
+/datum/gear/donator/mankini
name = "Mankini"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/stripper/mankini
ckeywhitelist = list("zigfie")
-/datum/gear/pinkshoes
+/datum/gear/donator/pinkshoes
name = "Pink shoes"
- category = SLOT_SHOES
+ slot = SLOT_SHOES
path = /obj/item/clothing/shoes/sneakers/pink
ckeywhitelist = list("zigfie")
-/datum/gear/reecesgreatcoat
+/datum/gear/donator/reecesgreatcoat
name = "Reece's Great Coat"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/trenchcoat/green
ckeywhitelist = list("geemiesif")
-/datum/gear/russianflask
+/datum/gear/donator/russianflask
name = "Russian flask"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/reagent_containers/food/drinks/flask/russian
cost = 2
ckeywhitelist = list("slomka")
-/datum/gear/stalkermask
+/datum/gear/donator/stalkermask
name = "S.T.A.L.K.E.R. mask"
- category = SLOT_WEAR_MASK
+ slot = SLOT_WEAR_MASK
path = /obj/item/clothing/mask/gas/stalker
ckeywhitelist = list("slomka")
-/datum/gear/stripedcollar
+/datum/gear/donator/stripedcollar
name = "Striped collar"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/petcollar/stripe
ckeywhitelist = list("jademanique")
-/datum/gear/performersoutfit
+/datum/gear/donator/performersoutfit
name = "Bluish performer's outfit"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/singer/yellow/custom
ckeywhitelist = list("killer402402")
-/datum/gear/vermillion
+/datum/gear/donator/vermillion
name = "Vermillion clothing"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/suit/vermillion
ckeywhitelist = list("fractious")
-/datum/gear/AM4B
+/datum/gear/donator/AM4B
name = "Foam Force AM4-B"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/gun/ballistic/automatic/AM4B
ckeywhitelist = list("zeronetalpha")
-/datum/gear/carrotsatchel
+/datum/gear/donator/carrotsatchel
name = "Carrot Satchel"
- category = SLOT_HANDS
+ slot = SLOT_HANDS
path = /obj/item/storage/backpack/satchel/carrot
ckeywhitelist = list("improvedname")
-/datum/gear/naomisweater
+/datum/gear/donator/naomisweater
name = "worn black sweater"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/sweater/black/naomi
ckeywhitelist = list("technicalmagi")
-/datum/gear/naomicollar
+/datum/gear/donator/naomicollar
name = "worn pet collar"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/petcollar/naomi
ckeywhitelist = list("technicalmagi")
-/datum/gear/gladiator
+/datum/gear/donator/gladiator
name = "Gladiator Armor"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/under/costume/gladiator
ckeywhitelist = list("aroche")
-/datum/gear/bloodredtie
+/datum/gear/donator/bloodredtie
name = "Blood Red Tie"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/tie/bloodred
ckeywhitelist = list("kyutness")
-/datum/gear/puffydress
+/datum/gear/donator/puffydress
name = "Puffy Dress"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/puffydress
ckeywhitelist = list("stallingratt")
-/datum/gear/labredblack
+/datum/gear/donator/labredblack
name = "Black and Red Coat"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/toggle/labcoat/labredblack
ckeywhitelist = list("blakeryan", "durandalphor")
-/datum/gear/torisword
+/datum/gear/donator/torisword
name = "Rainbow Zweihander"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/dualsaber/hypereutactic/toy/rainbow
ckeywhitelist = list("annoymous35")
-/datum/gear/darksabre
+/datum/gear/donator/darksabre
name = "Dark Sabre"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/toy/darksabre
ckeywhitelist = list("inferno707")
-datum/gear/darksabresheath
+/datum/gear/donator/darksabresheath
name = "Dark Sabre Sheath"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/storage/belt/sabre/darksabre
ckeywhitelist = list("inferno707")
-/datum/gear/toriball
+/datum/gear/donator/toriball
name = "Rainbow Tennis Ball"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis/rainbow
ckeywhitelist = list("annoymous35")
-/datum/gear/izzyball
+/datum/gear/donator/izzyball
name = "Katlin's Ball"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis/rainbow/izzy
ckeywhitelist = list("izzyinbox")
-/datum/gear/cloak
+/datum/gear/donator/cloak
name = "Green Cloak"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/cloak/green
ckeywhitelist = list("killer402402")
-/datum/gear/steelflask
+/datum/gear/donator/steelflask
name = "Steel Flask"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/reagent_containers/food/drinks/flask/steel
cost = 2
ckeywhitelist = list("nik707")
-/datum/gear/paperhat
+/datum/gear/donator/paperhat
name = "Paper Hat"
- category = SLOT_HEAD
+ slot = SLOT_HEAD
path = /obj/item/clothing/head/paperhat
ckeywhitelist = list("kered2")
-/datum/gear/cloakce
+/datum/gear/donator/cloakce
name = "Polychromic CE Cloak"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/clothing/neck/cloak/polychromic/polyce
ckeywhitelist = list("worksbythesea", "blakeryan")
-/datum/gear/ssk
+/datum/gear/donator/ssk
name = "Stun Sword Kit"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/ssword_kit
ckeywhitelist = list("phillip458")
-/datum/gear/techcoat
+/datum/gear/donator/techcoat
name = "Techomancers Labcoat"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/clothing/suit/toggle/labcoat/mad/techcoat
ckeywhitelist = list("wilchen")
-/datum/gear/leechjar
+/datum/gear/donator/leechjar
name = "Jar of Leeches"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/custom/leechjar
ckeywhitelist = list("sgtryder")
-/datum/gear/darkarmor
+/datum/gear/donator/darkarmor
name = "Dark Armor"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/clothing/suit/armor/vest/darkcarapace
ckeywhitelist = list("inferno707")
-/datum/gear/devilwings
+/datum/gear/donator/devilwings
name = "Strange Wings"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/devilwings
ckeywhitelist = list("kitsun")
-/datum/gear/flagcape
+/datum/gear/donator/flagcape
name = "US Flag Cape"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/clothing/neck/flagcape
ckeywhitelist = list("darnchacha")
-/datum/gear/luckyjack
+/datum/gear/donator/luckyjack
name = "Lucky Jackboots"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/clothing/shoes/lucky
ckeywhitelist = list("donaldtrumpthecommunist")
-/datum/gear/raiqbawks
+/datum/gear/donator/raiqbawks
name = "Miami Boombox"
- category = SLOT_HANDS
+ slot = SLOT_HANDS
cost = 2
path = /obj/item/boombox/raiq
ckeywhitelist = list("chefferz")
-/datum/gear/m41
+/datum/gear/donator/m41
name = "Toy M41"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/toy/gun/m41
ckeywhitelist = list("thalverscholen")
-/datum/gear/Divine_robes
+/datum/gear/donator/Divine_robes
name = "Divine robes"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/custom/lunasune
ckeywhitelist = list("invader4352")
-/datum/gear/gothcoat
+/datum/gear/donator/gothcoat
name = "Goth Coat"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/gothcoat
ckeywhitelist = list("norko")
-/datum/gear/corgisuit
+/datum/gear/donator/corgisuit
name = "Corgi Suit"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/ian_costume
ckeywhitelist = list("cathodetherobot")
-/datum/gear/sharkcloth
+/datum/gear/donator/sharkcloth
name = "Leon's Skimpy Outfit"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/under/custom/leoskimpy
ckeywhitelist = list("spectrosis")
-/datum/gear/mimemask
+/datum/gear/donator/mimemask
name = "Mime Mask"
- category = SLOT_WEAR_MASK
+ slot = SLOT_WEAR_MASK
path = /obj/item/clothing/mask/gas/mime
ckeywhitelist = list("pireamaineach")
-/datum/gear/mimeoveralls
+/datum/gear/donator/mimeoveralls
name = "Mime's Overalls"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/under/custom/mimeoveralls
ckeywhitelist = list("pireamaineach")
-/datum/gear/soulneck
+/datum/gear/donator/soulneck
name = "Soul Necklace"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/undertale
ckeywhitelist = list("twilightic")
-/datum/gear/frenchberet
+/datum/gear/donator/frenchberet
name = "French Beret"
- category = SLOT_HEAD
+ slot = SLOT_HEAD
path = /obj/item/clothing/head/frenchberet
ckeywhitelist = list("notazoltan")
-/datum/gear/zuliecloak
+/datum/gear/donator/zuliecloak
name = "Project: Zul-E"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/cloak/zuliecloak
ckeywhitelist = list("asky")
-/datum/gear/blackredgold
+/datum/gear/donator/blackredgold
name = "Black, Red, and Gold Coat"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/blackredgold
ckeywhitelist = list("ttbnc")
-/datum/gear/fritzplush
+/datum/gear/donator/fritzplush
name = "Fritz Plushie"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/mammal/dog/fritz
ckeywhitelist = list("analwerewolf")
-/datum/gear/kimono
+/datum/gear/donator/kimono
name = "Kimono"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/kimono
ckeywhitelist = list("sfox63")
-/datum/gear/commjacket
+/datum/gear/donator/commjacket
name = "Dusty Commisar's Cloak"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/commjacket
ckeywhitelist = list("sadisticbatter")
-/datum/gear/mw2_russian_para
+/datum/gear/donator/mw2_russian_para
name = "Russian Paratrooper Jumper"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/custom/mw2_russian_para
ckeywhitelist = list("investigator77")
-/datum/gear/longblackgloves
+/datum/gear/donator/longblackgloves
name = "Luna's Gauntlets"
- category = SLOT_GLOVES
+ slot = SLOT_GLOVES
path = /obj/item/clothing/gloves/longblackgloves
ckeywhitelist = list("bigmanclancy")
-/datum/gear/trendy_fit
+/datum/gear/donator/trendy_fit
name = "Trendy Fit"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/custom/trendy_fit
ckeywhitelist = list("midgetdragon")
-/datum/gear/singery
+/datum/gear/donator/singery
name = "Yellow Performer Outfit"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/singer/yellow
ckeywhitelist = list("maxlynchy")
-/datum/gear/csheet
+/datum/gear/donator/csheet
name = "NT Bedsheet"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/bedsheet/captain
ckeywhitelist = list("tikibomb")
-/datum/gear/borgplush
+/datum/gear/donator/borgplush
name = "Robot Plush"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/borgplushie
ckeywhitelist = list("nicholaiavenicci")
-/datum/gear/donorberet
+/datum/gear/donator/donorberet
name = "Atmos Beret"
- category = SLOT_HEAD
+ slot = SLOT_HEAD
path = /obj/item/clothing/head/blueberet
ckeywhitelist = list("foxystalin")
-/datum/gear/donorgoggles
+/datum/gear/donator/donorgoggles
name = "Flight Goggles"
- category = SLOT_HEAD
+ slot = SLOT_HEAD
path = /obj/item/clothing/head/flight
ckeywhitelist = list("maxlynchy")
-/datum/gear/onionneck
+/datum/gear/donator/onionneck
name = "Onion Necklace"
- category = SLOT_NECK
+ slot = SLOT_NECK
path = /obj/item/clothing/neck/necklace/onion
ckeywhitelist = list("cdrcross")
-/datum/gear/mikubikini
+/datum/gear/donator/mikubikini
name = "starlight singer bikini"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/under/custom/mikubikini
ckeywhitelist = list("grandvegeta")
-/datum/gear/mikujacket
+/datum/gear/donator/mikujacket
name = "starlight singer jacket"
- category = SLOT_WEAR_SUIT
+ slot = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/mikujacket
ckeywhitelist = list("grandvegeta")
-/datum/gear/mikuhair
+/datum/gear/donator/mikuhair
name = "starlight singer hair"
- category = SLOT_W_UNIFORM
+ slot = SLOT_W_UNIFORM
path = /obj/item/clothing/head/mikuhair
ckeywhitelist = list("grandvegeta")
-/datum/gear/mikugloves
+/datum/gear/donator/mikugloves
name = "starlight singer gloves"
- category = SLOT_GLOVES
+ slot = SLOT_GLOVES
path = /obj/item/clothing/gloves/mikugloves
ckeywhitelist = list("grandvegeta")
-/datum/gear/mikuleggings
+/datum/gear/donator/mikuleggings
name = "starlight singer leggings"
- category = SLOT_SHOES
+ slot = SLOT_SHOES
path = /obj/item/clothing/shoes/sneakers/mikuleggings
ckeywhitelist = list("grandvegeta")
-/datum/gear/cosmos
+/datum/gear/donator/cosmos
name = "cosmic space bedsheet"
- category = SLOT_IN_BACKPACK
+ slot = SLOT_IN_BACKPACK
path = /obj/item/bedsheet/cosmos
ckeywhitelist = list("grunnyyy")
diff --git a/modular_citadel/code/modules/client/loadout/_loadout.dm b/modular_citadel/code/modules/client/loadout/_loadout.dm
index 51256f8cde..0ebfa060f2 100644
--- a/modular_citadel/code/modules/client/loadout/_loadout.dm
+++ b/modular_citadel/code/modules/client/loadout/_loadout.dm
@@ -27,8 +27,13 @@ GLOBAL_LIST_EMPTY(loadout_whitelist_ids)
/proc/initialize_global_loadout_items()
load_loadout_config()
for(var/item in subtypesof(/datum/gear))
- var/datum/gear/I = new item
- LAZYSET(GLOB.loadout_items[slot_to_string(I.category)], I.name, I)
+ var/datum/gear/I = item
+ if(!initial(I.name))
+ continue
+ I = new item
+ LAZYINITLIST(GLOB.loadout_items[I.category])
+ LAZYINITLIST(GLOB.loadout_items[I.category][I.subcategory])
+ GLOB.loadout_items[I.category][I.subcategory][I.name] = I
if(islist(I.geargroupID))
var/list/ggidlist = I.geargroupID
I.ckeywhitelist = list()
@@ -41,7 +46,9 @@ GLOBAL_LIST_EMPTY(loadout_whitelist_ids)
/datum/gear
var/name
- var/category
+ var/category = LOADOUT_CATEGORY_NONE
+ var/subcategory = LOADOUT_SUBCATEGORY_NONE
+ var/slot
var/description
var/path //item-to-spawn path
var/cost = 1 //normally, each loadout costs a single point.
diff --git a/modular_citadel/code/modules/client/loadout/_medical.dm b/modular_citadel/code/modules/client/loadout/_medical.dm
index 604a0f96ae..e371db94fc 100644
--- a/modular_citadel/code/modules/client/loadout/_medical.dm
+++ b/modular_citadel/code/modules/client/loadout/_medical.dm
@@ -1,47 +1,45 @@
-/datum/gear/medicbriefcase
+/datum/gear/hands/medicbriefcase
name = "Medical Briefcase"
- category = SLOT_HANDS
path = /obj/item/storage/briefcase/medical
restricted_roles = list("Medical Doctor", "Chief Medical Officer")
restricted_desc = "MD, CMO"
-/datum/gear/stethoscope
+/datum/gear/neck/stethoscope
name = "Stethoscope"
- category = SLOT_NECK
path = /obj/item/clothing/neck/stethoscope
restricted_roles = list("Medical Doctor", "Chief Medical Officer")
-/datum/gear/bluescrubs
+/datum/gear/uniform/bluescrubs
name = "Blue Scrubs"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/rank/medical/doctor/blue
restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist")
restricted_desc = "Medical"
-
-/datum/gear/greenscrubs
+
+/datum/gear/uniform/greenscrubs
name = "Green Scrubs"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/rank/medical/doctor/green
restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist")
restricted_desc = "Medical"
-/datum/gear/purplescrubs
+/datum/gear/uniform/purplescrubs
name = "Purple Scrubs"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/rank/medical/doctor/purple
restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist")
restricted_desc = "Medical"
-/datum/gear/nursehat
+/datum/gear/head/nursehat
name = "Nurse Hat"
- category = SLOT_HEAD
path = /obj/item/clothing/head/nursehat
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist")
restricted_desc = "Medical"
-/datum/gear/nursesuit
+/datum/gear/uniform/nursesuit
name = "Nurse Suit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/rank/medical/doctor/nurse
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist")
- restricted_desc = "Medical"
\ No newline at end of file
+ restricted_desc = "Medical"
diff --git a/modular_citadel/code/modules/client/loadout/_security.dm b/modular_citadel/code/modules/client/loadout/_security.dm
index 72a6aab394..ab316d577b 100644
--- a/modular_citadel/code/modules/client/loadout/_security.dm
+++ b/modular_citadel/code/modules/client/loadout/_security.dm
@@ -1,71 +1,70 @@
-/datum/gear/navyblueuniformhos
+/datum/gear/uniform/navyblueuniformhos
name = "Head of Security navyblue uniform"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/rank/security/head_of_security/formal
restricted_roles = list("Head of Security")
-/datum/gear/navybluehosberet
+/datum/gear/head/navybluehosberet
name = "Head of security's navyblue beret"
- category = SLOT_HEAD
path = /obj/item/clothing/head/beret/sec/navyhos
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_roles = list("Head of Security")
-/datum/gear/navybluejackethos
+/datum/gear/suit/navybluejackethos
name = "head of security's navyblue jacket"
- category = SLOT_WEAR_SUIT
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
path = /obj/item/clothing/suit/armor/hos/navyblue
restricted_roles = list("Head of Security")
-/datum/gear/navybluejacketofficer
+/datum/gear/suit/navybluejacketofficer
name = "security officer's navyblue jacket"
- category = SLOT_WEAR_SUIT
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
path = /obj/item/clothing/suit/armor/navyblue
restricted_roles = list("Security Officer")
-/datum/gear/navyblueofficerberet
+/datum/gear/head/navyblueofficerberet
name = "Security officer's Navyblue beret"
- category = SLOT_HEAD
path = /obj/item/clothing/head/beret/sec/navyofficer
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_roles = list("Security Officer")
-/datum/gear/navyblueuniformofficer
+/datum/gear/uniform/navyblueuniformofficer
name = "Security officer navyblue uniform"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/rank/security/officer/formal
restricted_roles = list("Security Officer")
-/datum/gear/navybluejacketwarden
+/datum/gear/suit/navybluejacketwarden
name = "warden navyblue jacket"
- category = SLOT_WEAR_SUIT
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
path = /obj/item/clothing/suit/armor/vest/warden/navyblue
restricted_roles = list("Warden")
-/datum/gear/navybluewardenberet
+/datum/gear/head/navybluewardenberet
name = "Warden's navyblue beret"
- category = SLOT_HEAD
path = /obj/item/clothing/head/beret/sec/navywarden
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_roles = list("Warden")
-/datum/gear/navyblueuniformwarden
+/datum/gear/uniform/navyblueuniformwarden
name = "Warden navyblue uniform"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/rank/security/warden/formal
restricted_roles = list("Warden")
-/datum/gear/secskirt
+/datum/gear/uniform/secskirt
name = "Security skirt"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/rank/security/officer/skirt
restricted_roles = list("Security Officer", "Warden", "Head of Security")
-/datum/gear/hosskirt
+/datum/gear/uniform/hosskirt
name = "Head of security's skirt"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/rank/security/head_of_security/skirt
restricted_roles = list("Head of Security")
-/datum/gear/sechud
+/datum/gear/glasses/sechud
name = "Security Hud"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/hud/security
- restricted_roles = list("Security Officer", "Warden", "Head of Security")
\ No newline at end of file
+ restricted_roles = list("Security Officer", "Warden", "Head of Security")
diff --git a/modular_citadel/code/modules/client/loadout/_service.dm b/modular_citadel/code/modules/client/loadout/_service.dm
index ab3daa5f3c..848ad6233c 100644
--- a/modular_citadel/code/modules/client/loadout/_service.dm
+++ b/modular_citadel/code/modules/client/loadout/_service.dm
@@ -1,33 +1,33 @@
-/datum/gear/greytidestationwide
+/datum/gear/uniform/greytidestationwide
name = "Staff Assistant's jumpsuit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/staffassistant
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Assistant")
-/datum/gear/neetsuit
+/datum/gear/suit/neetsuit
name = "D.A.B. suit"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/assu_suit
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Assistant")
cost = 2
-/datum/gear/neethelm
+/datum/gear/head/neethelm
name = "D.A.B. helmet"
- category = SLOT_HEAD
path = /obj/item/clothing/head/assu_helmet
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_roles = list("Assistant")
cost = 2
-/datum/gear/plushvar
+/datum/gear/backpack/plushvar
name = "Ratvar Plushie"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/plushvar
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS
cost = 5
restricted_roles = list("Chaplain")
-/datum/gear/narplush
+/datum/gear/backpack/narplush
name = "Narsie Plushie"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/plush/narplush
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS
cost = 5
restricted_roles = list("Chaplain")
diff --git a/modular_citadel/code/modules/client/loadout/backpack.dm b/modular_citadel/code/modules/client/loadout/backpack.dm
index 690e012840..fbc498df64 100644
--- a/modular_citadel/code/modules/client/loadout/backpack.dm
+++ b/modular_citadel/code/modules/client/loadout/backpack.dm
@@ -1,112 +1,100 @@
-/datum/gear/plushbox
+/datum/gear/backpack
+ category = LOADOUT_CATEGORY_BACKPACK
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_GENERAL
+ slot = SLOT_IN_BACKPACK
+
+/datum/gear/backpack/plushbox
name = "Plushie Choice Box"
- category = SLOT_IN_BACKPACK
path = /obj/item/choice_beacon/box/plushie
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS
-/datum/gear/tennis
+/datum/gear/backpack/tennis
name = "Classic Tennis Ball"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS
-/datum/gear/tennisred
+/datum/gear/backpack/tennis/red
name = "Red Tennis Ball"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis/red
-/datum/gear/tennisyellow
+/datum/gear/backpack/tennis/yellow
name = "Yellow Tennis Ball"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis/yellow
-/datum/gear/tennisgreen
+/datum/gear/backpack/tennis/green
name = "Green Tennis Ball"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis/green
-/datum/gear/tenniscyan
+/datum/gear/backpack/tennis/cyan
name = "Cyan Tennis Ball"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis/cyan
-/datum/gear/tennisblue
+/datum/gear/backpack/tennis/blue
name = "Blue Tennis Ball"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis/blue
-/datum/gear/tennispurple
+/datum/gear/backpack/tennis/purple
name = "Purple Tennis Ball"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/tennis/purple
-/datum/gear/dildo
+/datum/gear/backpack/dildo
name = "Customizable dildo"
- category = SLOT_IN_BACKPACK
path = /obj/item/dildo/custom
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS
-/datum/gear/toykatana
+/datum/gear/backpack/toykatana
name = "Toy Katana"
- category = SLOT_IN_BACKPACK
path = /obj/item/toy/katana
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS
cost = 3
-/datum/gear/tapeplayer
+/datum/gear/backpack/tapeplayer
name = "Taperecorder"
- category = SLOT_IN_BACKPACK
path = /obj/item/taperecorder
-/datum/gear/tape
+/datum/gear/backpack/tape
name = "Spare cassette tape"
- category = SLOT_IN_BACKPACK
path = /obj/item/tape/random
-/datum/gear/newspaper
+/datum/gear/backpack/newspaper
name = "Newspaper"
- category = SLOT_IN_BACKPACK
path = /obj/item/newspaper
-/datum/gear/crayons
+/datum/gear/backpack/crayons
name = "Box of crayons"
- category = SLOT_IN_BACKPACK
path = /obj/item/storage/crayons
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS
-/datum/gear/multipen
+/datum/gear/backpack/multipen
name = "A multicolored pen"
- category = SLOT_IN_BACKPACK
path = /obj/item/pen/fourcolor
-/datum/gear/fountainpen
+/datum/gear/backpack/fountainpen
name = "A fancy pen"
- category = SLOT_IN_BACKPACK
path = /obj/item/pen/fountain
cost = 2
-/datum/gear/modular_tablet
+/datum/gear/backpack/modular_tablet
name = "A modular tablet"
- category = SLOT_IN_BACKPACK
path = /obj/item/modular_computer/tablet/preset/cheap/
cost = 4
-/datum/gear/modular_laptop
+/datum/gear/backpack/modular_laptop
name = "A modular laptop"
- category = SLOT_IN_BACKPACK
path = /obj/item/modular_computer/laptop/preset/civilian
cost = 7
-/datum/gear/ringbox_gold
+/datum/gear/backpack/ringbox_gold
name = "A gold ring box"
- category = SLOT_IN_BACKPACK
path = /obj/item/storage/fancy/ringbox
cost = 3
-/datum/gear/ringbox_silver
+/datum/gear/backpack/ringbox_silver
name = "A silver ring box"
- category = SLOT_IN_BACKPACK
path = /obj/item/storage/fancy/ringbox/silver
cost = 3
-/datum/gear/ringbox_diamond
+/datum/gear/backpack/ringbox_diamond
name = "A diamond ring box"
- category = SLOT_IN_BACKPACK
path = /obj/item/storage/fancy/ringbox/diamond
cost = 5
-
diff --git a/modular_citadel/code/modules/client/loadout/glasses.dm b/modular_citadel/code/modules/client/loadout/glasses.dm
index 57270d8e57..b0eecbbf28 100644
--- a/modular_citadel/code/modules/client/loadout/glasses.dm
+++ b/modular_citadel/code/modules/client/loadout/glasses.dm
@@ -1,49 +1,43 @@
-/datum/gear/blindfold
+/datum/gear/glasses
+ category = LOADOUT_CATEGORY_GLASSES
+ slot = SLOT_GLASSES
+
+/datum/gear/glasses/blindfold
name = "Blindfold"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/sunglasses/blindfold
-/datum/gear/cold
+/datum/gear/glasses/cold
name = "Cold goggles"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/cold
-/datum/gear/eyepatch
+/datum/gear/glasses/eyepatch
name = "Eyepatch"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/eyepatch
-/datum/gear/heat
+/datum/gear/glasses/heat
name = "Heat goggles"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/heat
-/datum/gear/hipster
+/datum/gear/glasses/hipster
name = "Hipster glasses"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/regular/hipster
-/datum/gear/jamjar
+/datum/gear/glasses/jamjar
name = "Jamjar glasses"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/regular/jamjar
-/datum/gear/monocle
+/datum/gear/glasses/monocle
name = "Monocle"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/monocle
-/datum/gear/orange
+/datum/gear/glasses/orange
name = "Orange glasses"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/orange
-/datum/gear/red
+/datum/gear/glasses/red
name = "Red Glasses"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/red
-/datum/gear/prescription
+/datum/gear/glasses/prescription
name = "Prescription glasses"
- category = SLOT_GLASSES
path = /obj/item/clothing/glasses/regular
diff --git a/modular_citadel/code/modules/client/loadout/gloves.dm b/modular_citadel/code/modules/client/loadout/gloves.dm
index e9e8e3939b..85be8bd487 100644
--- a/modular_citadel/code/modules/client/loadout/gloves.dm
+++ b/modular_citadel/code/modules/client/loadout/gloves.dm
@@ -1,28 +1,26 @@
-/datum/gear/fingerless
+/datum/gear/gloves
+ category = LOADOUT_CATEGORY_GLOVES
+ slot = SLOT_GLOVES
+
+/datum/gear/gloves/fingerless
name = "Fingerless Gloves"
- category = SLOT_GLOVES
path = /obj/item/clothing/gloves/fingerless
-/datum/gear/evening
+/datum/gear/gloves/evening
name = "Evening gloves"
- category = SLOT_GLOVES
path = /obj/item/clothing/gloves/evening
-/datum/gear/goldring
+/datum/gear/gloves/goldring
name = "A gold ring"
- category = SLOT_GLOVES
path = /obj/item/clothing/gloves/ring
cost = 2
-/datum/gear/silverring
+/datum/gear/gloves/silverring
name = "A silver ring"
- category = SLOT_GLOVES
path = /obj/item/clothing/gloves/ring/silver
cost = 2
-/datum/gear/diamondring
+/datum/gear/gloves/diamondring
name = "A diamond ring"
- category = SLOT_GLOVES
path = /obj/item/clothing/gloves/ring/diamond
cost = 4
-
diff --git a/modular_citadel/code/modules/client/loadout/hands.dm b/modular_citadel/code/modules/client/loadout/hands.dm
index 2f03bd3b07..db57fb466b 100644
--- a/modular_citadel/code/modules/client/loadout/hands.dm
+++ b/modular_citadel/code/modules/client/loadout/hands.dm
@@ -1,67 +1,54 @@
-/datum/gear/cane
+/datum/gear/hands
+ category = LOADOUT_CATEGORY_HANDS
+ slot = SLOT_HANDS
+
+/datum/gear/hands/cane
name = "Cane"
- category = SLOT_HANDS
path = /obj/item/cane
-/datum/gear/cigarettes
+/datum/gear/hands/cigarettes
name = "Cigarette pack"
- category = SLOT_HANDS
path = /obj/item/storage/fancy/cigarettes
-/datum/gear/dice
+/datum/gear/hands/dice
name = "Dice bag"
- category = SLOT_HANDS
path = /obj/item/storage/box/dice
-/datum/gear/eightball
+/datum/gear/hands/eightball
name = "Magic eightball"
- category = SLOT_HANDS
path = /obj/item/toy/eightball
-/datum/gear/matches
+/datum/gear/hands/matches
name = "Matchbox"
- category = SLOT_HANDS
path = /obj/item/storage/box/matches
-/datum/gear/cheaplighter
+/datum/gear/hands/cheaplighter
name = "Cheap lighter"
- category = SLOT_HANDS
path = /obj/item/lighter/greyscale
-/datum/gear/cards
+/datum/gear/hands/cards
name = "Playing cards"
- category = SLOT_HANDS
path = /obj/item/toy/cards/deck
-/datum/gear/skub
+/datum/gear/hands/skub
name = "Skub"
- category = SLOT_HANDS
path = /obj/item/skub
-/datum/gear/carpplushie
- name = "Space carp plushie"
- category = SLOT_HANDS
- path = /obj/item/toy/plush/carpplushie
-
-/datum/gear/wallet
+/datum/gear/hands/wallet
name = "Wallet"
- category = SLOT_HANDS
path = /obj/item/storage/wallet
-/datum/gear/flask
+/datum/gear/hands/flask
name = "Flask"
- category = SLOT_HANDS
path = /obj/item/reagent_containers/food/drinks/flask
cost = 2
-/datum/gear/zippolighter
+/datum/gear/hands/zippolighter
name = "Zippo Lighter"
- category = SLOT_HANDS
path = /obj/item/lighter
cost = 2
-/datum/gear/cigar
+/datum/gear/hands/cigar
name = "Cigar"
- category = SLOT_HANDS
path = /obj/item/clothing/mask/cigarette/cigar
cost = 4 //smoking is bad mkay
diff --git a/modular_citadel/code/modules/client/loadout/head.dm b/modular_citadel/code/modules/client/loadout/head.dm
index 2156c9c481..fd03e2279f 100644
--- a/modular_citadel/code/modules/client/loadout/head.dm
+++ b/modular_citadel/code/modules/client/loadout/head.dm
@@ -1,146 +1,136 @@
-/datum/gear/baseball
+/datum/gear/head
+ category = LOADOUT_CATEGORY_HEAD
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_GENERAL
+ slot = SLOT_HEAD
+
+/datum/gear/head/baseball
name = "Ballcap"
- category = SLOT_HEAD
path = /obj/item/clothing/head/soft/mime
-/datum/gear/beanie
+/datum/gear/head/beanie
name = "Beanie"
- category = SLOT_HEAD
path = /obj/item/clothing/head/beanie
-/datum/gear/beret
+/datum/gear/head/beret
name = "Black beret"
- category = SLOT_HEAD
path = /obj/item/clothing/head/beret/black
-/datum/gear/flatcap
+/datum/gear/head/flatcap
name = "Flat cap"
- category = SLOT_HEAD
path = /obj/item/clothing/head/flatcap
-/datum/gear/pirate
+/datum/gear/head/pirate
name = "Pirate hat"
- category = SLOT_HEAD
path = /obj/item/clothing/head/pirate
-/datum/gear/rice_hat
+/datum/gear/head/rice_hat
name = "Rice hat"
- category = SLOT_HEAD
path = /obj/item/clothing/head/rice_hat
-/datum/gear/ushanka
- name = "Ushanka"
- category = SLOT_HEAD
+/datum/gear/head/ushanka
path = /obj/item/clothing/head/ushanka
-/datum/gear/slime
+/datum/gear/head/slime
name = "Slime hat"
- category = SLOT_HEAD
path = /obj/item/clothing/head/collectable/slime
-/datum/gear/fedora
+/datum/gear/head/fedora
name = "Fedora"
- category = SLOT_HEAD
path = /obj/item/clothing/head/fedora
-/datum/gear/that
+/datum/gear/head/that
name = "Top Hat"
- category = SLOT_HEAD
path = /obj/item/clothing/head/that
-/datum/gear/maidband
+/datum/gear/head/maidband
name = "Maid headband"
- category = SLOT_HEAD
path= /obj/item/clothing/head/maid
-/datum/gear/flakhelm
+/datum/gear/head/flakhelm
name = "Flak Helmet"
- category = SLOT_HEAD
path = /obj/item/clothing/head/flakhelm
cost = 2
-/datum/gear/bunnyears
+/datum/gear/head/bunnyears
name = "Bunny Ears"
- category = SLOT_HEAD
path = /obj/item/clothing/head/rabbitears
-/datum/gear/mailmanhat
+/datum/gear/head/mailmanhat
name = "Mailman's Hat"
- category = SLOT_HEAD
path = /obj/item/clothing/head/mailman
//trek fancy Hats!
-/datum/gear/trekcap
+/datum/gear/head/trekcap
name = "Federation Officer's Cap (White)"
- category = SLOT_HEAD
path = /obj/item/clothing/head/caphat/formal/fedcover
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_roles = list("Captain","Head of Personnel")
-/datum/gear/trekcapcap
+/datum/gear/head/trekcapcap
name = "Federation Officer's Cap (Black)"
- category = SLOT_HEAD
path = /obj/item/clothing/head/caphat/formal/fedcover/black
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_roles = list("Captain","Head of Personnel")
-/datum/gear/trekcapmedisci
+/datum/gear/head/trekcapmedisci
name = "Federation Officer's Cap (Blue)"
- category = SLOT_HEAD
path = /obj/item/clothing/head/caphat/formal/fedcover/medsci
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist")
-/datum/gear/trekcapeng
+/datum/gear/head/trekcapeng
name = "Federation Officer's Cap (Yellow)"
- category = SLOT_HEAD
path = /obj/item/clothing/head/caphat/formal/fedcover/eng
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_desc = "Engineering, Security, and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
-/datum/gear/trekcapsec
+/datum/gear/head/trekcapsec
name = "Federation Officer's Cap (Red)"
- category = SLOT_HEAD
path = /obj/item/clothing/head/caphat/formal/fedcover/sec
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_desc = "Engineering, Security, and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
// orvilike "original" kepi
-/datum/gear/orvkepicom
+/datum/gear/head/orvkepicom
name = "Federation Kepi, command"
description = "A visored cap. Intended to be used with ORV uniform."
- category = SLOT_HEAD
path = /obj/item/clothing/head/kepi/orvi/command
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_desc = "Heads of Staff"
restricted_roles = list("Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer", "Quartermaster")
-/datum/gear/orvkepiops
+/datum/gear/head/orvkepiops
name = "Federation Kepi, ops/sec"
description = "A visored cap. Intended to be used with ORV uniform."
- category = SLOT_HEAD
path = /obj/item/clothing/head/kepi/orvi/engsec
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_desc = "Engineering, Security and Cargo"
restricted_roles = list("Chief Engineer", "Atmospheric Technician", "Station Engineer", "Warden", "Detective", "Security Officer", "Head of Security", "Cargo Technician", "Shaft Miner", "Quartermaster")
-/datum/gear/orvkepimedsci
+/datum/gear/head/orvkepimedsci
name = "Federation Kepi, medsci"
description = "A visored cap. Intended to be used with ORV uniform."
- category = SLOT_HEAD
path = /obj/item/clothing/head/kepi/orvi/medsci
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Paramedic", "Geneticist", "Research Director", "Scientist", "Roboticist")
-/datum/gear/orvkepisrv
+/datum/gear/head/orvkepisrv
name = "Federation Kepi, service"
description = "A visored cap. Intended to be used with ORV uniform."
- category = SLOT_HEAD
path = /obj/item/clothing/head/kepi/orvi/service
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer"
restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain")
-/datum/gear/orvkepiass
+/datum/gear/head/orvkepiass
name = "Federation Kepi, assistant"
description = "A visored cap. Intended to be used with ORV uniform."
- category = SLOT_HEAD
path = /obj/item/clothing/head/kepi/orvi
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_roles = list("Assistant")
/*Commenting out Until next Christmas or made automatic
@@ -156,35 +146,37 @@
*/
//Cowboy Stuff
-/datum/gear/cowboyhat
+/datum/gear/head/cowboyhat
name = "Cowboy Hat, Brown"
- category = SLOT_HEAD
path = /obj/item/clothing/head/cowboyhat
-/datum/gear/cowboyhat/black
+/datum/gear/head/cowboyhat/black
name = "Cowboy Hat, Black"
- category = SLOT_HEAD
path = /obj/item/clothing/head/cowboyhat/black
-/datum/gear/cowboyhat/white
+/datum/gear/head/cowboyhat/white
name = "Cowboy Hat, White"
- category = SLOT_HEAD
path = /obj/item/clothing/head/cowboyhat/white
-/datum/gear/cowboyhat/pink
+/datum/gear/head/cowboyhat/pink
name = "Cowboy Hat, Pink"
- category = SLOT_HEAD
path = /obj/item/clothing/head/cowboyhat/pink
-/datum/gear/cowboyhat/sec
+/datum/gear/head/cowboyhat/sec
name = "Cowboy Hat, Security"
- category = SLOT_HEAD
path = /obj/item/clothing/head/cowboyhat/sec
+ subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS
restricted_desc = "Security"
restricted_roles = list("Warden","Detective","Security Officer","Head of Security")
-// Misc
-/datum/gear/wkepi
+/datum/gear/head/wkepi
name = "white kepi"
- category = SLOT_HEAD
path = /obj/item/clothing/head/kepi
+
+/datum/gear/head/widered
+ name = "Wide red hat"
+ path = /obj/item/clothing/head/widered
+
+/datum/gear/head/kabuto
+ name = "Kabuto helmet"
+ path = /obj/item/clothing/head/kabuto
diff --git a/modular_citadel/code/modules/client/loadout/mask.dm b/modular_citadel/code/modules/client/loadout/mask.dm
index eeba06cad4..0d7e32552e 100644
--- a/modular_citadel/code/modules/client/loadout/mask.dm
+++ b/modular_citadel/code/modules/client/loadout/mask.dm
@@ -1,16 +1,16 @@
-/datum/gear/balaclava
+/datum/gear/mask
+ category = LOADOUT_CATEGORY_MASK
+ slot = SLOT_WEAR_MASK
+
+/datum/gear/mask/balaclava
name = "Balaclava"
- category = SLOT_WEAR_MASK
path = /obj/item/clothing/mask/balaclava
-/datum/gear/moustache
+/datum/gear/mask/moustache
name = "Fake moustache"
- category = SLOT_WEAR_MASK
path = /obj/item/clothing/mask/fakemoustache
-/datum/gear/joy
+/datum/gear/mask/joy
name = "Joy mask"
- category = SLOT_WEAR_MASK
path = /obj/item/clothing/mask/joy
cost = 3
-
diff --git a/modular_citadel/code/modules/client/loadout/neck.dm b/modular_citadel/code/modules/client/loadout/neck.dm
index 320a83b87d..19311f703a 100644
--- a/modular_citadel/code/modules/client/loadout/neck.dm
+++ b/modular_citadel/code/modules/client/loadout/neck.dm
@@ -1,94 +1,88 @@
-/datum/gear/bluetie
+/datum/gear/neck
+ category = LOADOUT_CATEGORY_NECK
+ subcategory = LOADOUT_SUBCATEGORY_NECK_GENERAL
+ slot = SLOT_NECK
+
+/datum/gear/neck/bluetie
name = "Blue tie"
- category = SLOT_NECK
+ subcategory = LOADOUT_SUBCATEGORY_NECK_TIE
path = /obj/item/clothing/neck/tie/blue
-/datum/gear/redtie
+/datum/gear/neck/redtie
name = "Red tie"
- category = SLOT_NECK
+ subcategory = LOADOUT_SUBCATEGORY_NECK_TIE
path = /obj/item/clothing/neck/tie/red
-/datum/gear/blacktie
+/datum/gear/neck/blacktie
name = "Black tie"
- category = SLOT_NECK
+ subcategory = LOADOUT_SUBCATEGORY_NECK_TIE
path = /obj/item/clothing/neck/tie/black
-/datum/gear/collar
+/datum/gear/neck/collar
name = "Collar"
- category = SLOT_NECK
path = /obj/item/clothing/neck/petcollar
-/datum/gear/leathercollar
+/datum/gear/neck/leathercollar
name = "Leather collar"
- category = SLOT_NECK
path = /obj/item/clothing/neck/petcollar/leather
-/datum/gear/choker
+/datum/gear/neck/choker
name = "Choker"
- category = SLOT_NECK
path = /obj/item/clothing/neck/petcollar/choker
-/datum/gear/scarf
+/datum/gear/neck/scarf
name = "White scarf"
- category = SLOT_NECK
+ subcategory = LOADOUT_SUBCATEGORY_NECK_SCARVES
path = /obj/item/clothing/neck/scarf
-/datum/gear/blackscarf
+/datum/gear/neck/scarf/black
name = "Black scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/scarf/black
-/datum/gear/redscarf
+/datum/gear/neck/scarf/red
name = "Red scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/scarf/red
-/datum/gear/greenscarf
+/datum/gear/neck/scarf/green
name = "Green scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/scarf/green
-/datum/gear/darkbluescarf
+/datum/gear/neck/scarf/darkblue
name = "Dark blue scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/scarf/darkblue
-/datum/gear/purplescarf
+/datum/gear/neck/scarf/purple
name = "Purple scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/scarf/purple
-/datum/gear/yellowscarf
+/datum/gear/neck/scarf/yellow
name = "Yellow scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/scarf/yellow
-/datum/gear/orangescarf
+/datum/gear/neck/scarf/orange
name = "Orange scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/scarf/orange
-/datum/gear/cyanscarf
+/datum/gear/neck/scarf/cyan
name = "Cyan scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/scarf/cyan
-/datum/gear/stripedredscarf
+/datum/gear/neck/scarf/stripedred
name = "Striped red scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/stripedredscarf
-/datum/gear/stripedbluescarf
+/datum/gear/neck/scarf/stripedblue
name = "Striped blue scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/stripedbluescarf
-/datum/gear/stripedgreenscarf
+/datum/gear/neck/scarf/stripedgreen
name = "Striped green scarf"
- category = SLOT_NECK
path = /obj/item/clothing/neck/stripedgreenscarf
-/datum/gear/headphones
+/datum/gear/neck/headphones
name = "Headphones"
- category = SLOT_NECK
path = /obj/item/clothing/ears/headphones
+
+/datum/gear/neck/polycloak
+ name = "Polychromatic Cloak"
+ path = /obj/item/clothing/neck/cloak/polychromic
diff --git a/modular_citadel/code/modules/client/loadout/shoes.dm b/modular_citadel/code/modules/client/loadout/shoes.dm
index 3531e69cfd..76d7305971 100644
--- a/modular_citadel/code/modules/client/loadout/shoes.dm
+++ b/modular_citadel/code/modules/client/loadout/shoes.dm
@@ -1,84 +1,71 @@
-/datum/gear/laceup
+/datum/gear/shoes
+ category = LOADOUT_CATEGORY_SHOES
+ slot = SLOT_SHOES
+
+/datum/gear/shoes/laceup
name = "Laceup shoes"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/laceup
-/datum/gear/workboots
+/datum/gear/shoes/workboots
name = "Work boots"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/workboots
-/datum/gear/jackboots
+/datum/gear/shoes/jackboots
name = "Jackboots"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/jackboots
-/datum/gear/winterboots
+/datum/gear/shoes/winterboots
name = "Winter boots"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/winterboots
-/datum/gear/sandals
+/datum/gear/shoes/sandals
name = "Sandals"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/sandal
-/datum/gear/blackshoes
+/datum/gear/shoes/blackshoes
name = "Black shoes"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/sneakers/black
-/datum/gear/brownshoes
+/datum/gear/shoes/brownshoes
name = "Brown shoes"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/sneakers/brown
-/datum/gear/whiteshoes
+/datum/gear/shoes/whiteshoes
name = "White shoes"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/sneakers/white
-/datum/gear/gildedcuffs
+/datum/gear/shoes/gildedcuffs
name = "Gilded leg wraps"
- category = SLOT_SHOES
path= /obj/item/clothing/shoes/wraps
-/datum/gear/silvercuffs
+/datum/gear/shoes/silvercuffs
name = "Silver leg wraps"
- category = SLOT_SHOES
path= /obj/item/clothing/shoes/wraps/silver
-/datum/gear/redcuffs
+/datum/gear/shoes/redcuffs
name = "Red leg wraps"
- category = SLOT_SHOES
path= /obj/item/clothing/shoes/wraps/red
-/datum/gear/bluecuffs
+/datum/gear/shoes/bluecuffs
name = "Blue leg wraps"
- category = SLOT_SHOES
path= /obj/item/clothing/shoes/wraps/blue
-/datum/gear/christmasbootsr
+/datum/gear/shoes/christmasbootsr
name = "Red Christmas Boots"
- category = SLOT_SHOES
path= /obj/item/clothing/shoes/winterboots/christmasbootsr
-/datum/gear/christmasbootsg
+/datum/gear/shoes/christmasbootsg
name = "Green Christmas Boots"
- category = SLOT_SHOES
path= /obj/item/clothing/shoes/winterboots/christmasbootsg
-/datum/gear/santaboots
+/datum/gear/shoes/santaboots
name = "Santa Boots"
- category = SLOT_SHOES
path= /obj/item/clothing/shoes/winterboots/santaboots
-/datum/gear/cowboyboots
+/datum/gear/shoes/cowboyboots
name = "Cowboy Boots, Brown"
- category = SLOT_SHOES
path = /obj/item/clothing/shoes/cowboyboots
-/datum/gear/cowboyboots/black
+/datum/gear/shoes/cowboyboots/black
name = "Cowboy Boots, Black"
- category = SLOT_SHOES
- path = /obj/item/clothing/shoes/cowboyboots/black
\ No newline at end of file
+ path = /obj/item/clothing/shoes/cowboyboots/black
diff --git a/modular_citadel/code/modules/client/loadout/suit.dm b/modular_citadel/code/modules/client/loadout/suit.dm
index fecf2a4dce..d0be26a8a4 100644
--- a/modular_citadel/code/modules/client/loadout/suit.dm
+++ b/modular_citadel/code/modules/client/loadout/suit.dm
@@ -1,235 +1,250 @@
-/datum/gear/poncho
+/datum/gear/suit
+ category = LOADOUT_CATEGORY_SUIT
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_GENERAL
+ slot = SLOT_WEAR_SUIT
+
+/datum/gear/suit/poncho
name = "Poncho"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/poncho
-/datum/gear/ponchogreen
+/datum/gear/suit/ponchogreen
name = "Green poncho"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/poncho/green
-/datum/gear/ponchored
+/datum/gear/suit/ponchored
name = "Red poncho"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/poncho/red
-/datum/gear/redhood
+/datum/gear/suit/redhood
name = "Red cloak"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/cloak/david
cost = 3
-/datum/gear/jacketbomber
+/datum/gear/suit/jacketbomber
name = "Bomber jacket"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/jacketleather
+/datum/gear/suit/jacketflannelblack // all of these are reskins of bomber jackets but with the vibe to make you look like a true lumberjack
+ name = "Black flannel jacket"
+ path = /obj/item/clothing/suit/jacket/flannel
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
+
+/datum/gear/suit/jacketflannelred
+ name = "Red flannel jacket"
+ path = /obj/item/clothing/suit/jacket/flannel/red
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
+
+/datum/gear/suit/jacketflannelaqua
+ name = "Aqua flannel jacket"
+ path = /obj/item/clothing/suit/jacket/flannel/aqua
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
+
+/datum/gear/suit/jacketflannelbrown
+ name = "Brown flannel jacket"
+ path = /obj/item/clothing/suit/jacket/flannel/brown
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
+
+/datum/gear/suit/jacketleather
name = "Leather jacket"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket/leather
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/overcoatleather
+/datum/gear/suit/overcoatleather
name = "Leather overcoat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket/leather/overcoat
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/jacketpuffer
+/datum/gear/suit/jacketpuffer
name = "Puffer jacket"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket/puffer
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/vestpuffer
+/datum/gear/suit/vestpuffer
name = "Puffer vest"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket/puffer/vest
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/jacketlettermanbrown
+/datum/gear/suit/jacketlettermanbrown
name = "Brown letterman jacket"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket/letterman
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/jacketlettermanred
+/datum/gear/suit/jacketlettermanred
name = "Red letterman jacket"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket/letterman_red
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/jacketlettermanNT
+/datum/gear/suit/jacketlettermanNT
name = "Nanotrasen letterman jacket"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket/letterman_nanotrasen
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/coat
+/datum/gear/suit/coat
name = "Winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS
-/datum/gear/coat/aformal
+/datum/gear/suit/coat/aformal
name = "Assistant's formal winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/aformal
-/datum/gear/coat/runed
+/datum/gear/suit/coat/runed
name = "Runed winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/narsie/fake
-/datum/gear/coat/brass
+/datum/gear/suit/coat/brass
name = "Brass winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/ratvar/fake
-/datum/gear/coat/polycoat
+/datum/gear/suit/coat/polycoat
name = "Polychromic winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/polychromic
cost = 4 //too many people with neon green coats is hard on the eyes
-/datum/gear/coat/med
+/datum/gear/suit/coat/med
name = "Medical winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/medical
restricted_roles = list("Chief Medical Officer", "Medical Doctor") // Reserve it to Medical Doctors and their boss, the Chief Medical Officer
-/datum/gear/coat/paramedic
+/datum/gear/suit/coat/paramedic
name = "Paramedic winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/paramedic
restricted_roles = list("Chief Medical Officer", "Paramedic") // Reserve it to Paramedics and their boss, the Chief Medical Officer
-/datum/gear/coat/robotics
+/datum/gear/suit/coat/robotics
name = "Robotics winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/robotics
restricted_roles = list("Research Director", "Roboticist")
-/datum/gear/coat/sci
+/datum/gear/suit/coat/sci
name = "Science winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/science
restricted_roles = list("Research Director", "Scientist", "Roboticist") // Reserve it to the Science Departement
-/datum/gear/coat/eng
+/datum/gear/suit/coat/eng
name = "Engineering winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/engineering
restricted_roles = list("Chief Engineer", "Station Engineer") // Reserve it to Station Engineers and their boss, the Chief Engineer
-/datum/gear/coat/eng/atmos
+/datum/gear/suit/coat/eng/atmos
name = "Atmospherics winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos
restricted_roles = list("Chief Engineer", "Atmospheric Technician") // Reserve it to Atmos Techs and their boss, the Chief Engineer
-/datum/gear/coat/hydro
+/datum/gear/suit/coat/hydro
name = "Hydroponics winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/hydro
restricted_roles = list("Head of Personnel", "Botanist") // Reserve it to Botanists and their boss, the Head of Personnel
-/datum/gear/coat/cargo
+/datum/gear/suit/coat/bar
+ name = "Bar winter coat"
+ path = /obj/item/clothing/suit/hooded/wintercoat/bar
+ restricted_roles = list("Bartender") // Reserve it to Bartenders and not the Head of Personnel because he doesnt deserve to look as fancy as them
+
+/datum/gear/suit/coat/cargo
name = "Cargo winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/cargo
restricted_roles = list("Quartermaster", "Cargo Technician") // Reserve it to Cargo Techs and their boss, the Quartermaster
-/datum/gear/coat/miner
+/datum/gear/suit/coat/miner
name = "Mining winter coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/miner
restricted_roles = list("Quartermaster", "Shaft Miner") // Reserve it to Miners and their boss, the Quartermaster
-/datum/gear/militaryjacket
+/datum/gear/suit/militaryjacket
name = "Military Jacket"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/jacket/miljacket
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-/datum/gear/ianshirt
+/datum/gear/suit/ianshirt
name = "Ian Shirt"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/ianshirt
-/datum/gear/flakjack
+/datum/gear/suit/flakjack
name = "Flak Jacket"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/flakjack
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
cost = 2
-/datum/gear/trekds9_coat
+/datum/gear/suit/trekds9_coat
name = "DS9 Overcoat (use uniform)"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/trek/ds9
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
restricted_desc = "All, barring Service and Civilian"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster",
"Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Scientist", "Roboticist",
"Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer",
"Cargo Technician", "Shaft Miner") //everyone who actually deserves a job.
//Federation jackets from movies
-/datum/gear/trekcmdcap
+/datum/gear/suit/trekcmdcap
name = "Fed (movie) uniform, Black"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/fluff/fedcoat/capt
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
restricted_roles = list("Captain","Head of Personnel")
-/datum/gear/trekcmdmov
+/datum/gear/suit/trekcmdmov
name = "Fed (movie) uniform, Red"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/fluff/fedcoat
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
restricted_desc = "Heads of Staff and Security"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster","Warden","Detective","Security Officer")
-/datum/gear/trekmedscimov
+/datum/gear/suit/trekmedscimov
name = "Fed (movie) uniform, Blue"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/fluff/fedcoat/medsci
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist")
-/datum/gear/trekengmov
+/datum/gear/suit/trekengmov
name = "Fed (movie) uniform, Yellow"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/fluff/fedcoat/eng
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
restricted_desc = "Engineering and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Cargo Technician", "Shaft Miner", "Quartermaster")
-/datum/gear/trekcmdcapmod
+/datum/gear/suit/trekcmdcapmod
name = "Fed (Modern) uniform, White"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/fluff/modernfedcoat
restricted_roles = list("Captain","Head of Personnel")
-/datum/gear/trekcmdmod
+/datum/gear/suit/trekcmdmod
name = "Fed (Modern) uniform, Red"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/fluff/modernfedcoat/sec
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
restricted_desc = "Heads of Staff and Security"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster","Warden","Detective","Security Officer")
-/datum/gear/trekmedscimod
+/datum/gear/suit/trekmedscimod
name = "Fed (Modern) uniform, Blue"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/fluff/modernfedcoat/medsci
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist")
-/datum/gear/trekengmod
+/datum/gear/suit/trekengmod
name = "Fed (Modern) uniform, Yellow"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/storage/fluff/modernfedcoat/eng
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS
restricted_desc = "Engineering and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Cargo Technician", "Shaft Miner", "Quartermaster")
-/datum/gear/christmascoatr
+/datum/gear/suit/christmascoatr
name = "Red Christmas Coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/christmascoatr
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS
-/datum/gear/christmascoatg
+/datum/gear/suit/christmascoatg
name = "Green Christmas Coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/christmascoatg
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS
-/datum/gear/christmascoatrg
+/datum/gear/suit/christmascoatrg
name = "Red and Green Christmas Coat"
- category = SLOT_WEAR_SUIT
path = /obj/item/clothing/suit/hooded/wintercoat/christmascoatrg
+ subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS
+
+/datum/gear/suit/samurai
+ name = "Samurai outfit"
+ path = /obj/item/clothing/suit/samurai
diff --git a/modular_citadel/code/modules/client/loadout/uniform.dm b/modular_citadel/code/modules/client/loadout/uniform.dm
index e667626968..5ce73d1cfd 100644
--- a/modular_citadel/code/modules/client/loadout/uniform.dm
+++ b/modular_citadel/code/modules/client/loadout/uniform.dm
@@ -1,562 +1,542 @@
-/datum/gear/suitblack
- name = "Black suit"
- category = SLOT_W_UNIFORM
- path = /obj/item/clothing/under/suit/black
+/datum/gear/uniform
+ category = LOADOUT_CATEGORY_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_GENERAL
+ slot = SLOT_W_UNIFORM
-/datum/gear/suitgreen
+/datum/gear/uniform/suit
+ name = "Black suit"
+ path = /obj/item/clothing/under/suit/black
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SUITS
+
+/datum/gear/uniform/suit/green
name = "Green suit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/suit/green
-/datum/gear/suitred
+/datum/gear/uniform/suit/red
name = "Red suit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/suit/red
-/datum/gear/suitcharcoal
+/datum/gear/uniform/suit/charcoal
name = "Charcoal suit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/suit/charcoal
-/datum/gear/suitnavy
+/datum/gear/uniform/suit/navy
name = "Navy suit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/suit/navy
-/datum/gear/suitburgundy
+/datum/gear/uniform/suit/burgundy
name = "Burgundy suit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/suit/burgundy
-/datum/gear/suittan
+/datum/gear/uniform/suit/tan
name = "Tan suit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/suit/tan
-/datum/gear/suitwhite
+/datum/gear/uniform/suit/white
name = "White suit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/suit/white
-/datum/gear/assistantformal
+/datum/gear/uniform/assistantformal
name = "Assistant's formal uniform"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/assistantformal
-/datum/gear/maidcostume
+/datum/gear/uniform/maidcostume
name = "Maid costume"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/maid
-/datum/gear/mailmanuniform
+/datum/gear/uniform/mailmanuniform
name = "Mailman's jumpsuit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/mailman
-/datum/gear/skirtblack
+/datum/gear/uniform/skirt
name = "Black skirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/skirt
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS
-/datum/gear/skirtblue
+/datum/gear/uniform/skirt/blue
name = "Blue skirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/skirt/blue
-/datum/gear/skirtred
+/datum/gear/uniform/skirt/red
name = "Red skirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/skirt/red
-/datum/gear/skirtpurple
+/datum/gear/uniform/skirt/purple
name = "Purple skirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/skirt/purple
-/datum/gear/skirtplaid
+/datum/gear/uniform/skirt/plaid
name = "Plaid skirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/skirt/plaid
-/datum/gear/schoolgirlblue
+/datum/gear/uniform/schoolgirlblue
name = "Blue Schoolgirl Uniform"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/schoolgirl
-/datum/gear/schoolgirlred
+/datum/gear/uniform/schoolgirlred
name = "Red Schoolgirl Uniform"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/schoolgirl/red
-/datum/gear/schoolgirlgreen
+/datum/gear/uniform/schoolgirlgreen
name = "Green Schoolgirl Uniform"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/schoolgirl/green
-/datum/gear/schoolgirlorange
+/datum/gear/uniform/schoolgirlorange
name = "Orange Schoolgirl Uniform"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/schoolgirl/orange
-/datum/gear/stripeddress
+/datum/gear/uniform/dress
name = "Striped Dress"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/striped
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES
-/datum/gear/sundresswhite
+/datum/gear/uniform/dress/sun/white
name = "White Sundress"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/sundress/white
-/datum/gear/sundress
+/datum/gear/uniform/dress/sun
name = "Sundress"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/sundress
-/datum/gear/greendress
+/datum/gear/uniform/dress/green
name = "Green Dress"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/green
-/datum/gear/pinkdress
+/datum/gear/uniform/dress/pink
name = "Pink Dress"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/pink
-/datum/gear/flowerdress
+
+/datum/gear/uniform/dress/orange
name = "Flower Dress"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/flower
-/datum/gear/sweptskirt
+/datum/gear/uniform/skirt/swept
name = "Swept skirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/skirt/swept
-/datum/gear/croptop
+/datum/gear/uniform/croptop
name = "Croptop"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/croptop
-/datum/gear/yoga
+/datum/gear/uniform/pants
name = "Yoga Pants"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/yoga
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_PANTS
-/datum/gear/kilt
+/datum/gear/uniform/kilt
name = "Kilt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/kilt
-/datum/gear/camoshorts
+/datum/gear/uniform/pants/camo
name = "Camo Pants"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/camo
-/datum/gear/athleticshorts
+/datum/gear/uniform/shorts
name = "Athletic Shorts"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/shorts/red
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SHORTS
-/datum/gear/bjeans
+/datum/gear/uniform/pants/bjeans
name = "Black Jeans"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/blackjeans
-/datum/gear/cjeans
+/datum/gear/uniform/pants/cjeans
name = "Classic Jeans"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/classicjeans
-/datum/gear/khaki
+/datum/gear/uniform/pants/khaki
name = "Khaki Pants"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/khaki
-/datum/gear/wpants
+/datum/gear/uniform/pants/white
name = "White Pants"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/white
-/datum/gear/rpants
+/datum/gear/uniform/pants/red
name = "Red Pants"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/red
-/datum/gear/tpants
+/datum/gear/uniform/pants/tan
name = "Tan Pants"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/tan
-/datum/gear/trpants
+/datum/gear/uniform/pants/track
name = "Track Pants"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/track
-/datum/gear/rippedjeans
+/datum/gear/uniform/pants/ripped
name = "Ripped Jeans"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/jeanripped
-/datum/gear/jeanshort
+/datum/gear/uniform/shorts/jean
name = "Jean Shorts"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/jeanshort
-/datum/gear/denimskirt
+/datum/gear/uniform/skirt/denim
name = "Denim Skirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/pants/denimskirt
-/datum/gear/yoga
- name = "Yoga Pants"
- category = SLOT_W_UNIFORM
- path = /obj/item/clothing/under/pants/yoga
-
// Pantsless Sweaters
-/datum/gear/turtleneck
+/datum/gear/uniform/turtleneck
name = "Tactitool Turtleneck"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/syndicate/cosmetic
-/datum/gear/creamsweater
+/datum/gear/uniform/sweater
name = "Cream Commando Sweater"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/sweater
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS
-/datum/gear/blacksweater
+/datum/gear/uniform/sweater/black
name = "Black Commando Sweater"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/sweater/black
-/datum/gear/purpsweater
+/datum/gear/uniform/sweater/purple
name = "Purple Commando Sweater"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/sweater/purple
-/datum/gear/greensweater
+/datum/gear/uniform/sweater/green
name = "Green Commando Sweater"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/sweater/green
-/datum/gear/redsweater
+/datum/gear/uniform/sweater/red
name = "Red Commando Sweater"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/sweater/red
-/datum/gear/bluesweater
+/datum/gear/uniform/sweater/blue
name = "Navy Commando Sweater"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/sweater/blue
-/datum/gear/keyholesweater
+/datum/gear/uniform/sweater/keyhole
name = "Keyhole Sweater"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/keyholesweater
-/datum/gear/polyjump
+/datum/gear/uniform/polyjump
name = "Polychromic Jumpsuit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/polyjumpsuit
cost = 2
-
-/datum/gear/polyskirt
+
+/datum/gear/uniform/skirt/poly
name = "Polychromic Jumpskirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/skirt/polychromic
cost = 2
-/datum/gear/polysuit
+/datum/gear/uniform/suit/poly
name = "Polychromic Button-up Shirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/poly_shirt
cost = 3
-
-/datum/gear/polypleated
+
+/datum/gear/uniform/skirt/poly/pleated
name = "Polychromic Pleated Sweaterskirt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/dress/skirt/polychromic/pleated
cost = 3
-/datum/gear/polykilt
+/datum/gear/uniform/polykilt
name = "Polychromic Kilt"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/kilt/polychromic
cost = 3
-/datum/gear/polyshorts
+/datum/gear/uniform/shorts/poly
name = "Polychromic Shorts"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/polyshorts
cost = 3
-/datum/gear/polyshortpants
+/datum/gear/uniform/shorts/poly/athletic
name = "Polychromic Athletic Shorts"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/shorts/polychromic
cost = 2
// Trekie things
//TOS
-/datum/gear/trekcmdtos
+/datum/gear/uniform/trekcmdtos
name = "TOS uniform, cmd"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/command
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Heads of Staff"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster")
-/datum/gear/trekmedscitos
+/datum/gear/uniform/trekmedscitos
name = "TOS uniform, med/sci"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/medsci
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist")
-/datum/gear/trekengtos
+/datum/gear/uniform/trekengtos
name = "TOS uniform, ops/sec"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/engsec
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Engineering, Security, and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
//TNG
-/datum/gear/trekcmdtng
+/datum/gear/uniform/trekcmdtng
name = "TNG uniform, cmd"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/command/next
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Heads of Staff"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster")
-/datum/gear/trekmedscitng
+/datum/gear/uniform/trekmedscitng
name = "TNG uniform, med/sci"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/medsci/next
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist")
-/datum/gear/trekengtng
+/datum/gear/uniform/trekengtng
name = "TNG uniform, ops/sec"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/engsec/next
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Engineering, Security, and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
//VOY
-/datum/gear/trekcmdvoy
+/datum/gear/uniform/trekcmdvoy
name = "VOY uniform, cmd"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/command/voy
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Heads of Staff"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster")
-/datum/gear/trekmedscivoy
+/datum/gear/uniform/trekmedscivoy
name = "VOY uniform, med/sci"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/medsci/voy
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist")
-/datum/gear/trekengvoy
+/datum/gear/uniform/trekengvoy
name = "VOY uniform, ops/sec"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/engsec/voy
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Engineering, Security, and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
//DS9
-/datum/gear/trekcmdds9
+/datum/gear/uniform/trekcmdds9
name = "DS9 uniform, cmd"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/command/ds9
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Heads of Staff"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster")
-/datum/gear/trekmedscids9
+/datum/gear/uniform/trekmedscids9
name = "DS9 uniform, med/sci"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/medsci/ds9
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist")
-/datum/gear/trekengds9
+/datum/gear/uniform/trekengds9
name = "DS9 uniform, ops/sec"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/engsec/ds9
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Engineering, Security, and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
//ENT
-/datum/gear/trekcmdent
+/datum/gear/uniform/trekcmdent
name = "ENT uniform, cmd"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/command/ent
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Heads of Staff"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster")
-/datum/gear/trekmedscient
+/datum/gear/uniform/trekmedscient
name = "ENT uniform, med/sci"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/medsci/ent
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist")
-/datum/gear/trekengent
+/datum/gear/uniform/trekengent
name = "ENT uniform, ops/sec"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/engsec/ent
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Engineering, Security, and Cargo"
restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster")
//TheMotionPicture
-/datum/gear/trekfedutil
+/datum/gear/uniform/trekfedutil
name = "TMP uniform"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/fedutil
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "All, barring Service and Civilian"
restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster",
"Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Scientist", "Roboticist",
"Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer",
"Cargo Technician", "Shaft Miner")
-/datum/gear/trekfedtrainee
+/datum/gear/uniform/trekfedtrainee
name = "TMP uniform, trainee"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/fedutil/trainee
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Assistant", "Janitor", "Cargo Technician")
-/datum/gear/trekfedservice
+/datum/gear/uniform/trekfedservice
name = "TMP uniform, service"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/fedutil/service
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer"
restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain")
//Orvilike
-/datum/gear/orvcmd
+/datum/gear/uniform/orvcmd
name = "ORV uniform, cmd"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/command/orv
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Heads of Staff"
restricted_roles = list("Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer", "Quartermaster")
-/datum/gear/orvcmd_capt
+/datum/gear/uniform/orvcmd_capt
name = "ORV uniform, capt"
- category = SLOT_W_UNIFORM
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
path = /obj/item/clothing/under/trek/command/orv/captain
restricted_roles = list("Captain")
-/datum/gear/orvmedsci
+/datum/gear/uniform/orvmedsci
name = "ORV uniform, med/sci"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/medsci/orv
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Medical and Science"
restricted_roles = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Paramedic", "Geneticist", "Research Director", "Scientist", "Roboticist")
-/datum/gear/orvcmd_medsci
+/datum/gear/uniform/orvcmd_medsci
name = "ORV uniform, med/sci, cmd"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/command/orv/medsci
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Chief Medical Officer", "Research Director")
-/datum/gear/orvops
+/datum/gear/uniform/orvops
name = "ORV uniform, ops/sec"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/engsec/orv
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_desc = "Engineering, Security and Cargo"
restricted_roles = list("Chief Engineer", "Atmospheric Technician", "Station Engineer", "Warden", "Detective", "Security Officer", "Head of Security", "Cargo Technician", "Shaft Miner", "Quartermaster")
-/datum/gear/orvcmd_ops
+/datum/gear/uniform/orvcmd_ops
name = "ORV uniform, ops/sec, cmd"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/command/orv/engsec
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Chief Engineer", "Head of Security")
-/datum/gear/orvass
+/datum/gear/uniform/orvass
name = "ORV uniform, assistant"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/orv
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Assistant")
-/datum/gear/orvsrv
+/datum/gear/uniform/orvsrv
name = "ORV uniform, service"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/trek/orv/service
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS
restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain")
restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer"
//Memes
-/datum/gear/gear_harnesses
+/datum/gear/uniform/gear_harnesses
name = "Gear Harness"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/gear_harness
//Christmas
/*Commenting out Until next Christmas or made automatic
-/datum/gear/christmasmaler
+/datum/gear/uniform/christmasmaler
name = "Red Masculine Christmas Suit"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/christmas
-/datum/gear/christmasmaleg
+/datum/gear/uniform/christmasmaleg
name = "Green Masculine Christmas Suit"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/christmas/green
-/datum/gear/christmasfemaler
+/datum/gear/uniform/christmasfemaler
name = "Red Feminine Christmas Suit"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/christmas/croptop
-/datum/gear/christmasfemaleg
+/datum/gear/uniform/christmasfemaleg
name = "Green Feminine Christmas Suit"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/christmas/croptop/green
-/datum/gear/pinkstripper
+/datum/gear/uniform/pinkstripper
name = "Pink stripper outfit"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/stripper
cost = 3
*/
-/datum/gear/greenstripper
+/datum/gear/uniform/greenstripper
name = "Green stripper outfit"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/misc/stripper/green
cost = 3
-/datum/gear/qipao
+/datum/gear/uniform/qipao
name = "Qipao, Black"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/qipao
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES
cost = 3
-/datum/gear/qipao/white
+/datum/gear/uniform/qipao/white
name = "Qipao, White"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/qipao/white
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES
cost = 3
-/datum/gear/qipao/red
+/datum/gear/uniform/qipao/red
name = "Qipao, Red"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/qipao/red
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES
cost = 3
-/datum/gear/cheongsam
+/datum/gear/uniform/cheongsam
name = "Cheongsam, Black"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/cheongsam
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES
cost = 3
-/datum/gear/cheongsam/white
+/datum/gear/uniform/cheongsam/white
name = "Cheongsam, White"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/cheongsam/white
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES
cost = 3
-/datum/gear/cheongsam/red
+/datum/gear/uniform/cheongsam/red
name = "Cheongsam, Red"
- category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/costume/cheongsam/red
+ subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES
cost = 3
+
+/datum/gear/uniform/dress/black
+ name = "Black dress"
+ path = /obj/item/clothing/under/misc/black_dress
+
+/datum/gear/uniform/skirt/pinktutu
+ name = "Pink tutu"
+ path = /obj/item/clothing/under/misc/pinktutu
+
+/datum/gear/uniform/bathrobe
+ name = "Bathrobe"
+ path = /obj/item/clothing/under/misc/bathrobe
+
+/datum/gear/uniform/kimono
+ name = "Kimono"
+ path = /obj/item/clothing/under/costume/kimono
+
+/datum/gear/uniform/kimono/black
+ name = "Black kimono"
+ path = /obj/item/clothing/under/costume/kimono/black
+
+/datum/gear/uniform/kimono/kamishimo
+ name = "Kamishimo"
+ path = /obj/item/clothing/under/costume/kimono/kamishimo
+
+/datum/gear/uniform/kimono/fancy
+ name = "Fancy kimono"
+ path = /obj/item/clothing/under/costume/kimono/fancy
+
+/datum/gear/uniform/kimono/sakura
+ name = "Sakura kimono"
+ path = /obj/item/clothing/under/costume/kimono/sakura
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
index 8ef302e904..f3059a480a 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
@@ -112,7 +112,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
M.visible_message("[M] suddenly shudders, and splits into two identical twins!")
SM.copy_languages(M, LANGUAGE_MIND)
playerClone = TRUE
- M.next_move_modifier = 1
+ M.action_cooldown_mod = 1
M.adjust_nutrition(-500)
//Damage the clone
@@ -154,7 +154,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
M.adjust_nutrition(M.nutrition/5)
if(50)
to_chat(M, "The synthetic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.")
- M.next_move_modifier += 4//If this makes you fast then please fix it, it should make you slow!!
+ M.action_cooldown_mod += 4//If this makes you fast then please fix it, it should make you slow!!
//candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies
if(51 to 79)
M.adjust_nutrition(M.nutrition/2)
@@ -164,7 +164,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
M.set_nutrition(20000) //https://www.youtube.com/watch?v=Bj_YLenOlZI
if(86)//Upon splitting, you get really hungry and are capable again. Deletes the chem after you're done.
M.set_nutrition(15)//YOU BEST BE EATTING AFTER THIS YOU CUTIE
- M.next_move_modifier -= 4
+ M.action_cooldown_mod -= 4
to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.")
//clone
@@ -195,14 +195,14 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
if (playerClone == TRUE)//If the player made a clone with it, then thats all they get.
playerClone = FALSE
return
- if (M.next_move_modifier == 4 && !M.has_status_effect(/datum/status_effect/chem/SGDF))//checks if they're ingested over 20u of the stuff, but fell short of the required 30u to make a clone.
+ if (M.action_cooldown_mod == 4 && !M.has_status_effect(/datum/status_effect/chem/SGDF))//checks if they're ingested over 20u of the stuff, but fell short of the required 30u to make a clone.
to_chat(M, "You feel the cells begin to merge with your body, unable to reach nucleation, they instead merge with your body, healing any wounds.")
M.adjustCloneLoss(-10, 0) //I don't want to make Rezadone obsolete.
M.adjustBruteLoss(-25, 0)// Note that this takes a long time to apply and makes you fat and useless when it's in you, I don't think this small burst of healing will be useful considering how long it takes to get there.
M.adjustFireLoss(-25, 0)
M.blood_volume += 250
M.heal_bodypart_damage(1,1)
- M.next_move_modifier = 1
+ M.action_cooldown_mod = 1
if (M.nutrition < 1500)
M.adjust_nutrition(250)
else if (unitCheck == TRUE && !M.has_status_effect(/datum/status_effect/chem/SGDF))// If they're ingested a little bit (10u minimum), then give them a little healing.
@@ -211,7 +211,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
M.adjustBruteLoss(-10, 0)
M.adjustFireLoss(-10, 0)
M.blood_volume += 100
- M.next_move_modifier = 1
+ M.action_cooldown_mod = 1
if (M.nutrition < 1500)
M.adjust_nutrition(500)
@@ -325,7 +325,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
M.adjust_nutrition(M.nutrition/5)
if(50)
to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.")
- M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!!
+ M.action_cooldown_mod = 4//If this makes you fast then please fix it, it should make you slow!!
if(51 to 73)
M.adjust_nutrition(M.nutrition/2)
if(74)
@@ -339,7 +339,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
if (!M.reagents.has_reagent(/datum/reagent/medicine/pen_acid))//Counterplay is pent.)
message_admins("(non-infectious) SDZF: Zombie spawned at [M] [COORD(M)]!")
M.set_nutrition(startHunger - 500) //YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE
- M.next_move_modifier = 1
+ M.action_cooldown_mod = 1
to_chat(M, "Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.")
M.visible_message("[M] suddenly shudders, and splits into a funky smelling copy of themselves!")
M.emote("scream")
diff --git a/modular_citadel/code/modules/reagents/objects/clothes.dm b/modular_citadel/code/modules/reagents/objects/clothes.dm
index d3c566ce70..ab4d49c56f 100644
--- a/modular_citadel/code/modules/reagents/objects/clothes.dm
+++ b/modular_citadel/code/modules/reagents/objects/clothes.dm
@@ -9,7 +9,7 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
//item_flags = NODROP //Tips their hat!
-/obj/item/clothing/head/hattip/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/clothing/head/hattip/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user))
var/mob/living/carbon/C = user
if(is_ninja(C))
diff --git a/modular_citadel/code/modules/reagents/objects/items.dm b/modular_citadel/code/modules/reagents/objects/items.dm
index 27b8961835..f4316b3c58 100644
--- a/modular_citadel/code/modules/reagents/objects/items.dm
+++ b/modular_citadel/code/modules/reagents/objects/items.dm
@@ -9,7 +9,7 @@
w_class = WEIGHT_CLASS_TINY
//A little janky with pockets
-/obj/item/fermichem/pHbooklet/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+/obj/item/fermichem/pHbooklet/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(user.get_held_index_of_item(src))//Does this check pockets too..?
if(numberOfPages == 50)
icon_state = "pHbookletOpen"
diff --git a/sound/effects/blood1.ogg b/sound/effects/wounds/blood1.ogg
similarity index 100%
rename from sound/effects/blood1.ogg
rename to sound/effects/wounds/blood1.ogg
diff --git a/sound/effects/blood2.ogg b/sound/effects/wounds/blood2.ogg
similarity index 100%
rename from sound/effects/blood2.ogg
rename to sound/effects/wounds/blood2.ogg
diff --git a/sound/effects/blood3.ogg b/sound/effects/wounds/blood3.ogg
similarity index 100%
rename from sound/effects/blood3.ogg
rename to sound/effects/wounds/blood3.ogg
diff --git a/sound/effects/crack1.ogg b/sound/effects/wounds/crack1.ogg
similarity index 100%
rename from sound/effects/crack1.ogg
rename to sound/effects/wounds/crack1.ogg
diff --git a/sound/effects/crack2.ogg b/sound/effects/wounds/crack2.ogg
similarity index 100%
rename from sound/effects/crack2.ogg
rename to sound/effects/wounds/crack2.ogg
diff --git a/sound/effects/wounds/crackandbleed.ogg b/sound/effects/wounds/crackandbleed.ogg
new file mode 100644
index 0000000000..ea07f13d48
Binary files /dev/null and b/sound/effects/wounds/crackandbleed.ogg differ
diff --git a/sound/effects/wounds/pierce1.ogg b/sound/effects/wounds/pierce1.ogg
new file mode 100644
index 0000000000..cd7b7c3961
Binary files /dev/null and b/sound/effects/wounds/pierce1.ogg differ
diff --git a/sound/effects/wounds/pierce2.ogg b/sound/effects/wounds/pierce2.ogg
new file mode 100644
index 0000000000..4977cab299
Binary files /dev/null and b/sound/effects/wounds/pierce2.ogg differ
diff --git a/sound/effects/wounds/pierce3.ogg b/sound/effects/wounds/pierce3.ogg
new file mode 100644
index 0000000000..e81700b134
Binary files /dev/null and b/sound/effects/wounds/pierce3.ogg differ
diff --git a/sound/effects/sizzle1.ogg b/sound/effects/wounds/sizzle1.ogg
similarity index 100%
rename from sound/effects/sizzle1.ogg
rename to sound/effects/wounds/sizzle1.ogg
diff --git a/sound/effects/sizzle2.ogg b/sound/effects/wounds/sizzle2.ogg
similarity index 100%
rename from sound/effects/sizzle2.ogg
rename to sound/effects/wounds/sizzle2.ogg
diff --git a/sound/machines/clockcult/ratvar_scream.ogg b/sound/machines/clockcult/ratvar_scream.ogg
new file mode 100644
index 0000000000..5c0c0a0d63
Binary files /dev/null and b/sound/machines/clockcult/ratvar_scream.ogg differ
diff --git a/sound/magic/abomscream.ogg b/sound/magic/abomscream.ogg
new file mode 100644
index 0000000000..4f450e05f7
Binary files /dev/null and b/sound/magic/abomscream.ogg differ
diff --git a/sound/mecha/neostep1.ogg b/sound/mecha/neostep1.ogg
new file mode 100644
index 0000000000..ce7f51ad23
Binary files /dev/null and b/sound/mecha/neostep1.ogg differ
diff --git a/sound/mecha/neostep2.ogg b/sound/mecha/neostep2.ogg
new file mode 100644
index 0000000000..e828d9eadd
Binary files /dev/null and b/sound/mecha/neostep2.ogg differ
diff --git a/sound/mecha/powerloader_step.ogg b/sound/mecha/powerloader_step.ogg
new file mode 100644
index 0000000000..af427df865
Binary files /dev/null and b/sound/mecha/powerloader_step.ogg differ
diff --git a/sound/roundend/CitadelStationHasSeenBetterDays.ogg b/sound/roundend/CitadelStationHasSeenBetterDays.ogg
new file mode 100644
index 0000000000..2fa0c5b33c
Binary files /dev/null and b/sound/roundend/CitadelStationHasSeenBetterDays.ogg differ
diff --git a/sound/voice/catpeople/distressed.ogg b/sound/voice/catpeople/distressed.ogg
new file mode 100644
index 0000000000..cebe73dffc
Binary files /dev/null and b/sound/voice/catpeople/distressed.ogg differ
diff --git a/sound/voice/catpeople/license.txt b/sound/voice/catpeople/license.txt
new file mode 100644
index 0000000000..7218480ddb
--- /dev/null
+++ b/sound/voice/catpeople/license.txt
@@ -0,0 +1,2 @@
+distressed_cat.ogg from Cat annoyed meow / wail by jbierfeldt at https://freesound.org/people/jbierfeldt/sounds/440735/, chopped up and ogged
+cat_puking.ogg from catpuking mp3 by NoiseCollector and Mocha the cat at https://freesound.org/people/NoiseCollector/sounds/80778/, chopped up, volume altered and ogged
\ No newline at end of file
diff --git a/sound/voice/catpeople/puking.ogg b/sound/voice/catpeople/puking.ogg
new file mode 100644
index 0000000000..e19c10858f
Binary files /dev/null and b/sound/voice/catpeople/puking.ogg differ
diff --git a/sound/weapons/shot.ogg b/sound/weapons/shot.ogg
new file mode 100644
index 0000000000..6c57482973
Binary files /dev/null and b/sound/weapons/shot.ogg differ
diff --git a/strings/abductee_objectives.txt b/strings/abductee_objectives.txt
index 93fd946818..135bb7673b 100644
--- a/strings/abductee_objectives.txt
+++ b/strings/abductee_objectives.txt
@@ -31,7 +31,7 @@ Flood the station's powernet with as much electricity as you can.
Replace all the floor tiles with wood, carpeting, grass or bling.
You must escape the station! Get the shuttle called!
Don't allow anyone to be cloned.
-The oxygen is killing them all and they don't even know it. Make sure no oxygen is on the station.
+Their cold, mindless gaze pierce your soul. They see your every movements, it's merely a question of time before they try to control us further. Deactivate all cameras!
Your body must be improved. Ingest as many drugs as you can.
You are hungry. Eat as much food as you can find.
You see you see what they cannot you see the open door you seeE you SEeEe you SEe yOU seEee SHOW THEM ALL
diff --git a/strings/wounds/bone_scar_desc.json b/strings/wounds/bone_scar_desc.json
new file mode 100644
index 0000000000..3540547c4a
--- /dev/null
+++ b/strings/wounds/bone_scar_desc.json
@@ -0,0 +1,26 @@
+{
+ "generic": ["general disfigurement"],
+
+ "bluntmoderate": [
+ "the bone equivalent of a faded bruise",
+ "a series of tiny chip marks"
+ ],
+
+ "bluntsevere": [
+ "a series of faded hairline cracks",
+ "a small bone dent"
+ ],
+
+ "bluntcritical": [
+ "large streaks of refilled cracks",
+ "a fractal of reformed stress marks",
+ "a cluster of calluses"
+ ],
+
+ "dismember": [
+ "is slightly misaligned",
+ "has clearly been dropped recently",
+ "has a damaged socket"
+ ]
+
+}
\ No newline at end of file
diff --git a/strings/wounds/flesh_scar_desc.json b/strings/wounds/flesh_scar_desc.json
new file mode 100644
index 0000000000..fb2b927a30
--- /dev/null
+++ b/strings/wounds/flesh_scar_desc.json
@@ -0,0 +1,86 @@
+{
+ "generic": ["general disfigurement"],
+
+ "bluntmoderate": [
+ "light discoloring",
+ "a slight blue tint"
+ ],
+
+ "bluntsevere": [
+ "a faded, fist-sized bruise",
+ "a vaguely triangular peel scar"
+ ],
+
+ "bluntcritical": [
+ "a section of janky skin lines and badly healed scars",
+ "a large patch of uneven skin tone",
+ "a cluster of calluses"
+ ],
+
+
+
+ "slashmoderate": [
+ "light, faded lines",
+ "minor cut marks",
+ "a small faded slit",
+ "a series of small scars"
+ ],
+
+ "slashsevere": [
+ "a twisted line of faded gashes",
+ "a gnarled sickle-shaped slice scar"
+ ],
+
+ "slashcritical": [
+ "a winding path of very badly healed scar tissue",
+ "a series of peaks and valleys along a gruesome line of cut scar tissue",
+ "a grotesque snake of indentations and stitching scars"
+ ],
+
+
+
+ "piercemoderate": [
+ "a small, faded bruise",
+ "a small twist of reformed skin",
+ "a thumb-sized puncture scar"
+ ],
+
+ "piercesevere": [
+ "an ink-splat shaped pocket of scar tissue",
+ "a long-faded puncture wound",
+ "a tumbling puncture hole with evidence of faded stitching"
+ ],
+
+ "piercecritical": [
+ "a rippling shockwave of scar tissue",
+ "a wide, scattered cloud of shrapnel marks",
+ "a gruesome multi-pronged puncture scar"
+ ],
+
+
+
+ "burnmoderate": [
+ "small amoeba-shaped skinmarks",
+ "a faded streak of depressed skin"
+ ],
+
+ "burnsevere": [
+ "a large, jagged patch of faded skin",
+ "random spots of shiny, smooth skin",
+ "spots of taut, leathery skin"
+ ],
+
+ "burncritical": [
+ "massive, disfiguring keloid scars",
+ "several long streaks of badly discolored and malformed skin",
+ "unmistakeable splotches of dead tissue from serious burns"
+ ],
+
+
+ "dismember": [
+ "is several skintone shades paler than the rest of the body",
+ "is a gruesome patchwork of artificial flesh",
+ "has a large series of attachment scars at the articulation points"
+ ]
+
+}
\ No newline at end of file
diff --git a/strings/wounds/scar_loc.json b/strings/wounds/scar_loc.json
new file mode 100644
index 0000000000..f721294925
--- /dev/null
+++ b/strings/wounds/scar_loc.json
@@ -0,0 +1,52 @@
+{
+ "": ["general area"],
+
+ "head": [
+ "left eyebrow",
+ "cheekbone",
+ "neck",
+ "throat",
+ "jawline",
+ "entire face"
+ ],
+
+ "chest": [
+ "upper chest",
+ "lower abdomen",
+ "midsection",
+ "collarbone",
+ "lower back"
+ ],
+
+ "l_arm": [
+ "outer left forearm",
+ "inner left wrist",
+ "left elbow",
+ "left bicep",
+ "left shoulder"
+ ],
+
+ "r_arm": [
+ "outer right forearm",
+ "inner right wrist",
+ "right elbow",
+ "right bicep",
+ "right shoulder"
+ ],
+
+ "l_leg": [
+ "inner left thigh",
+ "outer left calf",
+ "outer left hip",
+ "left kneecap",
+ "lower left shin"
+ ],
+
+ "r_leg": [
+ "inner right thigh",
+ "outer right calf",
+ "outer right hip",
+ "right kneecap",
+ "lower right shin"
+ ]
+}
\ No newline at end of file
diff --git a/tgstation.dme b/tgstation.dme
index 2a7156f043..faa1ce990c 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -61,6 +61,7 @@
#include "code\__DEFINES\language.dm"
#include "code\__DEFINES\layers_planes.dm"
#include "code\__DEFINES\lighting.dm"
+#include "code\__DEFINES\loadout.dm"
#include "code\__DEFINES\logging.dm"
#include "code\__DEFINES\machines.dm"
#include "code\__DEFINES\maps.dm"
@@ -124,6 +125,7 @@
#include "code\__DEFINES\_flags\do_after.dm"
#include "code\__DEFINES\_flags\item_flags.dm"
#include "code\__DEFINES\_flags\obj_flags.dm"
+#include "code\__DEFINES\_flags\return_values.dm"
#include "code\__DEFINES\_flags\shields.dm"
#include "code\__DEFINES\admin\keybindings.dm"
#include "code\__DEFINES\chemistry\reactions.dm"
@@ -135,7 +137,6 @@
#include "code\__DEFINES\dcs\signals.dm"
#include "code\__DEFINES\mapping\maploader.dm"
#include "code\__DEFINES\material\worth.dm"
-#include "code\__DEFINES\misc\return_values.dm"
#include "code\__DEFINES\mobs\slowdowns.dm"
#include "code\__DEFINES\research\stock_parts.dm"
#include "code\__DEFINES\skills\defines.dm"
@@ -200,6 +201,7 @@
#include "code\_globalvars\lists\client.dm"
#include "code\_globalvars\lists\flavor_misc.dm"
#include "code\_globalvars\lists\keybindings.dm"
+#include "code\_globalvars\lists\loadout_categories.dm"
#include "code\_globalvars\lists\maintenance_loot.dm"
#include "code\_globalvars\lists\mapping.dm"
#include "code\_globalvars\lists\medals.dm"
@@ -220,6 +222,9 @@
#include "code\_onclick\observer.dm"
#include "code\_onclick\other_mobs.dm"
#include "code\_onclick\overmind.dm"
+#include "code\_onclick\right_click.dm"
+#include "code\_onclick\right_item_attack.dm"
+#include "code\_onclick\right_other_mobs.dm"
#include "code\_onclick\telekinesis.dm"
#include "code\_onclick\hud\_defines.dm"
#include "code\_onclick\hud\action_button.dm"
@@ -229,6 +234,7 @@
#include "code\_onclick\hud\alien_larva.dm"
#include "code\_onclick\hud\blob_overmind.dm"
#include "code\_onclick\hud\blobbernauthud.dm"
+#include "code\_onclick\hud\clockwork_marauder.dm"
#include "code\_onclick\hud\constructs.dm"
#include "code\_onclick\hud\credits.dm"
#include "code\_onclick\hud\devil.dm"
@@ -252,7 +258,11 @@
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\screen_objects.dm"
#include "code\_onclick\hud\swarmer.dm"
+#include "code\_onclick\hud\screen_objects\clickdelay.dm"
+#include "code\_onclick\hud\screen_objects\sprint.dm"
+#include "code\_onclick\hud\screen_objects\stamina.dm"
#include "code\_onclick\hud\screen_objects\storage.dm"
+#include "code\_onclick\hud\screen_objects\vore.dm"
#include "code\controllers\admin.dm"
#include "code\controllers\configuration_citadel.dm"
#include "code\controllers\controller.dm"
@@ -339,6 +349,7 @@
#include "code\controllers\subsystem\processing\circuit.dm"
#include "code\controllers\subsystem\processing\fastprocess.dm"
#include "code\controllers\subsystem\processing\fields.dm"
+#include "code\controllers\subsystem\processing\huds.dm"
#include "code\controllers\subsystem\processing\instruments.dm"
#include "code\controllers\subsystem\processing\nanites.dm"
#include "code\controllers\subsystem\processing\networks.dm"
@@ -353,6 +364,7 @@
#include "code\datums\ai_laws.dm"
#include "code\datums\armor.dm"
#include "code\datums\beam.dm"
+#include "code\datums\beepsky_fashion.dm"
#include "code\datums\browser.dm"
#include "code\datums\callback.dm"
#include "code\datums\chatmessage.dm"
@@ -368,6 +380,7 @@
#include "code\datums\explosion.dm"
#include "code\datums\forced_movement.dm"
#include "code\datums\holocall.dm"
+#include "code\datums\http.dm"
#include "code\datums\hud.dm"
#include "code\datums\mind.dm"
#include "code\datums\mutable_appearance.dm"
@@ -421,6 +434,7 @@
#include "code\datums\components\igniter.dm"
#include "code\datums\components\infective.dm"
#include "code\datums\components\jousting.dm"
+#include "code\datums\components\killerqueen.dm"
#include "code\datums\components\knockback.dm"
#include "code\datums\components\knockoff.dm"
#include "code\datums\components\lifesteal.dm"
@@ -659,7 +673,9 @@
#include "code\datums\wounds\_wounds.dm"
#include "code\datums\wounds\bones.dm"
#include "code\datums\wounds\burns.dm"
-#include "code\datums\wounds\cuts.dm"
+#include "code\datums\wounds\loss.dm"
+#include "code\datums\wounds\pierce.dm"
+#include "code\datums\wounds\slash.dm"
#include "code\game\alternate_appearance.dm"
#include "code\game\atoms.dm"
#include "code\game\atoms_movable.dm"
@@ -961,6 +977,7 @@
#include "code\game\objects\items\AI_modules.dm"
#include "code\game\objects\items\airlock_painter.dm"
#include "code\game\objects\items\apc_frame.dm"
+#include "code\game\objects\items\armor_kits.dm"
#include "code\game\objects\items\balls.dm"
#include "code\game\objects\items\binoculars.dm"
#include "code\game\objects\items\blueprints.dm"
@@ -1507,6 +1524,7 @@
#include "code\modules\antagonists\clockcult\clock_effects\servant_blocker.dm"
#include "code\modules\antagonists\clockcult\clock_effects\spatial_gateway.dm"
#include "code\modules\antagonists\clockcult\clock_helpers\clock_powerdrain.dm"
+#include "code\modules\antagonists\clockcult\clock_helpers\clock_rites.dm"
#include "code\modules\antagonists\clockcult\clock_helpers\component_helpers.dm"
#include "code\modules\antagonists\clockcult\clock_helpers\fabrication_helpers.dm"
#include "code\modules\antagonists\clockcult\clock_helpers\hierophant_network.dm"
@@ -1514,6 +1532,7 @@
#include "code\modules\antagonists\clockcult\clock_helpers\ratvarian_language.dm"
#include "code\modules\antagonists\clockcult\clock_helpers\scripture_checks.dm"
#include "code\modules\antagonists\clockcult\clock_helpers\slab_abilities.dm"
+#include "code\modules\antagonists\clockcult\clock_items\clock_augments.dm"
#include "code\modules\antagonists\clockcult\clock_items\clock_components.dm"
#include "code\modules\antagonists\clockcult\clock_items\clockwork_armor.dm"
#include "code\modules\antagonists\clockcult\clock_items\clockwork_slab.dm"
@@ -1525,6 +1544,7 @@
#include "code\modules\antagonists\clockcult\clock_items\soul_vessel.dm"
#include "code\modules\antagonists\clockcult\clock_items\wraith_spectacles.dm"
#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\_call_weapon.dm"
+#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\brass_claw.dm"
#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\ratvarian_shield.dm"
#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\ratvarian_spear.dm"
#include "code\modules\antagonists\clockcult\clock_mobs\_eminence.dm"
@@ -1532,6 +1552,7 @@
#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_applications.dm"
#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_cyborg.dm"
#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_drivers.dm"
+#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_judgement.dm"
#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_scripts.dm"
#include "code\modules\antagonists\clockcult\clock_structures\_trap_object.dm"
#include "code\modules\antagonists\clockcult\clock_structures\ark_of_the_clockwork_justicar.dm"
@@ -1540,6 +1561,7 @@
#include "code\modules\antagonists\clockcult\clock_structures\heralds_beacon.dm"
#include "code\modules\antagonists\clockcult\clock_structures\mania_motor.dm"
#include "code\modules\antagonists\clockcult\clock_structures\ocular_warden.dm"
+#include "code\modules\antagonists\clockcult\clock_structures\prolonging_prism.dm"
#include "code\modules\antagonists\clockcult\clock_structures\ratvar_the_clockwork_justicar.dm"
#include "code\modules\antagonists\clockcult\clock_structures\reflector.dm"
#include "code\modules\antagonists\clockcult\clock_structures\stargazer.dm"
@@ -2317,6 +2339,7 @@
#include "code\modules\mining\lavaland\ash_flora.dm"
#include "code\modules\mining\lavaland\necropolis_chests.dm"
#include "code\modules\mining\lavaland\ruins\gym.dm"
+#include "code\modules\mob\clickdelay.dm"
#include "code\modules\mob\death.dm"
#include "code\modules\mob\emote.dm"
#include "code\modules\mob\inventory.dm"
@@ -2369,6 +2392,7 @@
#include "code\modules\mob\dead\observer\say.dm"
#include "code\modules\mob\living\blood.dm"
#include "code\modules\mob\living\bloodcrawl.dm"
+#include "code\modules\mob\living\clickdelay.dm"
#include "code\modules\mob\living\damage_procs.dm"
#include "code\modules\mob\living\death.dm"
#include "code\modules\mob\living\emote.dm"
@@ -2491,6 +2515,7 @@
#include "code\modules\mob\living\carbon\human\species_types\synthliz.dm"
#include "code\modules\mob\living\carbon\human\species_types\synths.dm"
#include "code\modules\mob\living\carbon\human\species_types\vampire.dm"
+#include "code\modules\mob\living\carbon\human\species_types\xeno.dm"
#include "code\modules\mob\living\carbon\human\species_types\zombies.dm"
#include "code\modules\mob\living\carbon\monkey\combat.dm"
#include "code\modules\mob\living\carbon\monkey\death.dm"
@@ -3290,6 +3315,7 @@
#include "code\modules\surgery\plastic_surgery.dm"
#include "code\modules\surgery\prosthetic_replacement.dm"
#include "code\modules\surgery\remove_embedded_object.dm"
+#include "code\modules\surgery\repair_puncture.dm"
#include "code\modules\surgery\surgery.dm"
#include "code\modules\surgery\surgery_step.dm"
#include "code\modules\surgery\tools.dm"
@@ -3434,12 +3460,6 @@
#include "interface\menu.dm"
#include "interface\stylesheet.dm"
#include "interface\skin.dmf"
-#include "modular_citadel\code\_onclick\click.dm"
-#include "modular_citadel\code\_onclick\item_attack.dm"
-#include "modular_citadel\code\_onclick\other_mobs.dm"
-#include "modular_citadel\code\_onclick\hud\screen_objects.dm"
-#include "modular_citadel\code\_onclick\hud\sprint.dm"
-#include "modular_citadel\code\_onclick\hud\stamina.dm"
#include "modular_citadel\code\datums\components\souldeath.dm"
#include "modular_citadel\code\datums\status_effects\chems.dm"
#include "modular_citadel\code\game\objects\cit_screenshake.dm"
diff --git a/tgui/yarn.lock b/tgui/yarn.lock
index a2a23a7998..c2fc3a185f 100644
--- a/tgui/yarn.lock
+++ b/tgui/yarn.lock
@@ -1241,9 +1241,9 @@ bluebird@^3.5.5:
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
- version "4.11.8"
- resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
- integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
+ version "4.11.9"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
+ integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
body-parser@1.19.0:
version "1.19.0"
@@ -2203,9 +2203,9 @@ electron-to-chromium@^1.3.390:
integrity sha512-DbCBdwtARI0l3e3m6ZIxVaTNahb6dSsmGjuag/twiVcWuM4MSpL5IfsJsJSyqLqxosE/m0CXlZaBmxegQW/dAg==
elliptic@^6.0.0:
- version "6.5.2"
- resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762"
- integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
+ integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==
dependencies:
bn.js "^4.4.0"
brorand "^1.0.1"