Merge branch 'master' into species-are-dumb
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1548,7 +1548,7 @@
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/science/lab)
|
||||
"ayu" = (
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-16"
|
||||
},
|
||||
/obj/effect/turf_decal/tile/purple{
|
||||
@@ -7757,7 +7757,7 @@
|
||||
/obj/structure/cable{
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/turf/open/floor/carpet,
|
||||
@@ -9031,7 +9031,7 @@
|
||||
/obj/structure/cable{
|
||||
icon_state = "2-8"
|
||||
},
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
@@ -9409,7 +9409,7 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/hallway/primary/fore)
|
||||
"dij" = (
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/turf/open/floor/carpet,
|
||||
@@ -11361,7 +11361,7 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/janitor)
|
||||
"eue" = (
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-04"
|
||||
},
|
||||
/obj/effect/turf_decal/tile/blue{
|
||||
@@ -17394,7 +17394,7 @@
|
||||
/obj/machinery/light{
|
||||
dir = 4
|
||||
},
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
@@ -22642,7 +22642,7 @@
|
||||
/turf/open/floor/engine,
|
||||
/area/engine/engineering)
|
||||
"lfs" = (
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-08"
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
@@ -27858,7 +27858,7 @@
|
||||
/turf/open/floor/carpet,
|
||||
/area/quartermaster/miningoffice)
|
||||
"old" = (
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "applebush"
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
@@ -28531,7 +28531,7 @@
|
||||
/turf/open/floor/carpet,
|
||||
/area/crew_quarters/heads/hop)
|
||||
"oGU" = (
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
@@ -29602,7 +29602,7 @@
|
||||
c_tag = "Courtroom East";
|
||||
dir = 8
|
||||
},
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "applebush"
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
@@ -32153,7 +32153,7 @@
|
||||
/turf/open/floor/carpet,
|
||||
/area/crew_quarters/dorms)
|
||||
"qHO" = (
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-21"
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
@@ -32961,7 +32961,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/turf_decal/tile/neutral,
|
||||
/obj//obj/item/kirbyplants,
|
||||
/obj/item/kirbyplants,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/crew_quarters/fitness)
|
||||
"rhX" = (
|
||||
@@ -34346,7 +34346,7 @@
|
||||
/area/engine/engineering)
|
||||
"saN" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
@@ -34837,7 +34837,7 @@
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/turf_decal/tile/blue,
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
@@ -36237,7 +36237,7 @@
|
||||
/obj/effect/turf_decal/tile/red{
|
||||
dir = 4
|
||||
},
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
@@ -43182,7 +43182,7 @@
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-4"
|
||||
},
|
||||
/obj//obj/item/kirbyplants{
|
||||
/obj/item/kirbyplants{
|
||||
icon_state = "plant-10"
|
||||
},
|
||||
/obj/machinery/power/apc{
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
#define CUSTOM_SKINTONE 24 //adds a "_g" suffix to bodypart overlays icon states if a custom skintone is used.
|
||||
#define HORNCOLOR 25
|
||||
#define WINGCOLOR 26
|
||||
#define CAN_SCAR 27 // If this species can be scarred (fleshy)
|
||||
|
||||
//organ slots
|
||||
#define ORGAN_SLOT_BRAIN "brain"
|
||||
|
||||
@@ -12,4 +12,9 @@
|
||||
#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
|
||||
#define BLOCK_Z_FALL (1<<10)
|
||||
|
||||
/// Integrity defines for clothing (not flags but close enough)
|
||||
#define CLOTHING_PRISTINE 0 // We have no damage on the clothing
|
||||
#define CLOTHING_DAMAGED 1 // There's some damage on the clothing but it still has at least one functioning bodypart and can be equipped
|
||||
#define CLOTHING_SHREDDED 2 // The clothing is useless and cannot be equipped unless repaired first
|
||||
|
||||
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
|
||||
|
||||
@@ -74,6 +74,9 @@
|
||||
#define ADMIN_PUNISHMENT_MAZING "Puzzle"
|
||||
#define ADMIN_PUNISHMENT_PIE "Cream Pie"
|
||||
#define ADMIN_PUNISHMENT_CUSTOM_PIE "Custom Cream Pie"
|
||||
#define ADMIN_PUNISHMENT_CRACK ":B:oneless"
|
||||
#define ADMIN_PUNISHMENT_BLEED ":B:loodless"
|
||||
#define ADMIN_PUNISHMENT_SCARIFY "Scarify"
|
||||
#define ADMIN_PUNISHMENT_PICKLE "Pickle-ify"
|
||||
#define ADMIN_PUNISHMENT_FRY "Fry"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Defines for managed input/keybinding system.
|
||||
/// Max length of a keypress command before it's considered to be a forged packet/bogus command
|
||||
#define MAX_KEYPRESS_COMMANDLENGTH 16
|
||||
#define MAX_KEYPRESS_COMMANDLENGTH 32
|
||||
/// Maximum keys that can be bound to one button
|
||||
#define MAX_COMMANDS_PER_KEY 5
|
||||
/// Maximum keys per keybind
|
||||
|
||||
@@ -252,7 +252,14 @@
|
||||
#define COMPONENT_INTERRUPT_LIFE_BIOLOGICAL 1 // interrupt biological processes
|
||||
#define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling
|
||||
|
||||
// /mob/living/carbon signals
|
||||
// /mob/living/carbon physiology signals
|
||||
#define COMSIG_CARBON_GAIN_WOUND "carbon_gain_wound" //from /datum/wound/proc/apply_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L)
|
||||
#define COMSIG_CARBON_LOSE_WOUND "carbon_lose_wound" //from /datum/wound/proc/remove_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L)
|
||||
///from base of /obj/item/bodypart/proc/attach_limb(): (new_limb, special) allows you to fail limb attachment
|
||||
#define COMSIG_CARBON_ATTACH_LIMB "carbon_attach_limb"
|
||||
#define COMPONENT_NO_ATTACH (1<<0)
|
||||
#define COMSIG_CARBON_REMOVE_LIMB "carbon_remove_limb" //from base of /obj/item/bodypart/proc/drop_limb(special, dismembered)
|
||||
|
||||
#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity))
|
||||
#define COMSIG_CARBON_IDENTITY_TRANSFERRED_TO "carbon_id_transferred_to" //from datum/dna/transfer_identity(): (datum/dna, transfer_SE)
|
||||
#define COMSIG_CARBON_TACKLED "carbon_tackled" //sends from tackle.dm on tackle completion
|
||||
@@ -352,7 +359,7 @@
|
||||
#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
|
||||
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
|
||||
#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" // from base of /obj/item/projectile/proc/fire(): (obj/item/projectile, atom/original_target)
|
||||
#define COMSIG_PROJECTILE_FIRE "projectile_fire" ///from the base of /obj/projectile/proc/fire(): ()
|
||||
#define COMSIG_PROJECTILE_FIRE "projectile_fire" ///from the base of /obj/item/projectile/proc/fire(): ()
|
||||
#define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out" // sent to targets during the process_hit proc of projectiles
|
||||
#define COMSIG_EMBED_TRY_FORCE "item_try_embed" // sent when trying to force an embed (mainly for projectiles, only used in the embed element)
|
||||
#define COMSIG_PROJECTILE_PREHIT "com_proj_prehit" ///sent to targets during the process_hit proc of projectiles
|
||||
@@ -362,6 +369,7 @@
|
||||
// /mob/living/carbon/human signals
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
|
||||
#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack"
|
||||
#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted)
|
||||
#define COMSIG_HUMAN_PREFS_COPIED_TO "human_prefs_copied_to" //from datum/preferences/copy_to(): (datum/preferences, icon_updates, roundstart_checks)
|
||||
#define COMSIG_HUMAN_HARDSET_DNA "human_hardset_dna" //from mob/living/carbon/human/hardset_dna(): (ui, list/mutation_index, newreal_name, newblood_type, datum/species, newfeatures)
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
#define PULSE_CHANNEL "pulse channel"
|
||||
|
||||
// Methods of obtaining a circuit.
|
||||
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
|
||||
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and is able to be printed in the IC printer.
|
||||
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
|
||||
|
||||
// Categories that help differentiate circuits that can do different tipes of actions
|
||||
// Categories that help differentiate circuits that can do different types of actions
|
||||
#define IC_ACTION_MOVEMENT (1<<0) // If the circuit can move the assembly
|
||||
#define IC_ACTION_COMBAT (1<<1) // If the circuit can cause harm
|
||||
#define IC_ACTION_LONG_RANGE (1<<2) // If the circuit communicate with something outside of the assembly
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#define MOVE_INTENT_RUN "run"
|
||||
|
||||
//Blood levels
|
||||
#define BLOOD_VOLUME_MAX_LETHAL 2150
|
||||
#define BLOOD_VOLUME_EXCESS 2100
|
||||
#define BLOOD_VOLUME_MAXIMUM 2000
|
||||
#define BLOOD_VOLUME_SLIME_SPLIT 1120
|
||||
#define BLOOD_VOLUME_NORMAL 560
|
||||
@@ -57,6 +59,7 @@
|
||||
#define BODYPART_NOT_DISABLED 0
|
||||
#define BODYPART_DISABLED_DAMAGE 1
|
||||
#define BODYPART_DISABLED_PARALYSIS 2
|
||||
#define BODYPART_DISABLED_WOUND 3
|
||||
|
||||
#define DEFAULT_BODYPART_ICON 'icons/mob/human_parts.dmi'
|
||||
#define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi'
|
||||
@@ -103,12 +106,14 @@
|
||||
#define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems
|
||||
#define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery
|
||||
#define TRAUMA_RESILIENCE_LOBOTOMY 3 //Curable with lobotomy
|
||||
#define TRAUMA_RESILIENCE_MAGIC 4 //Curable only with magic
|
||||
#define TRAUMA_RESILIENCE_ABSOLUTE 5 //This is here to stay
|
||||
#define TRAUMA_RESILIENCE_WOUND 4 //Curable by healing the head wound
|
||||
#define TRAUMA_RESILIENCE_MAGIC 5 //Curable only with magic
|
||||
#define TRAUMA_RESILIENCE_ABSOLUTE 6 //This is here to stay
|
||||
|
||||
//Limit of traumas for each resilience tier
|
||||
#define TRAUMA_LIMIT_BASIC 3
|
||||
#define TRAUMA_LIMIT_SURGERY 2
|
||||
#define TRAUMA_LIMIT_WOUND 2
|
||||
#define TRAUMA_LIMIT_LOBOTOMY 3
|
||||
#define TRAUMA_LIMIT_MAGIC 3
|
||||
#define TRAUMA_LIMIT_ABSOLUTE INFINITY
|
||||
@@ -305,6 +310,7 @@
|
||||
#define GRAB_PIXEL_SHIFT_NECK 16
|
||||
|
||||
#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
|
||||
#define INTERACTING_WITH(X, Y) (Y in X.do_afters)
|
||||
|
||||
/// Field of vision defines.
|
||||
#define FOV_90_DEGREES 90
|
||||
@@ -315,4 +321,4 @@
|
||||
#define EYE_CONTACT_RANGE 5
|
||||
|
||||
/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
|
||||
#define EXAMINE_MORE_TIME 1 SECONDS
|
||||
#define EXAMINE_MORE_TIME 1 SECONDS
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#define STATUS_EFFECT_REGENERATIVE_CORE /datum/status_effect/regenerative_core //removes damage slowdown while giving a slow regenerating effect
|
||||
|
||||
#define STATUS_EFFECT_DETERMINED /datum/status_effect/determined //currently in a combat high from being seriously wounded
|
||||
|
||||
/////////////
|
||||
// DEBUFFS //
|
||||
/////////////
|
||||
@@ -107,6 +109,8 @@
|
||||
|
||||
#define STATUS_EFFECT_ELECTROSTAFF /datum/status_effect/electrostaff //slows down victim
|
||||
|
||||
#define STATUS_EFFECT_LIMP /datum/status_effect/limp //For when you have a busted leg (or two!) and want additional slowdown when walking on that leg
|
||||
|
||||
/////////////
|
||||
// NEUTRAL //
|
||||
/////////////
|
||||
|
||||
@@ -152,14 +152,17 @@
|
||||
var/list/po = A.priority_overlays;\
|
||||
if(LAZYLEN(rm)){\
|
||||
A.overlays -= rm;\
|
||||
rm.Cut();\
|
||||
A.remove_overlays = null;\
|
||||
}\
|
||||
if(LAZYLEN(ad)){\
|
||||
A.overlays |= ad;\
|
||||
ad.Cut();\
|
||||
A.add_overlays = null;\
|
||||
}\
|
||||
if(LAZYLEN(po)){\
|
||||
A.overlays |= po;\
|
||||
}\
|
||||
else{\
|
||||
A.priority_overlays = null;\
|
||||
}\
|
||||
A.flags_1 &= ~OVERLAY_QUEUED_1;\
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
//Glasswork Tools
|
||||
#define TOOL_BLOW "blowing_rod"
|
||||
#define TOOL_GLASS_CUT "glasskit"
|
||||
#define TOOL_BONESET "bonesetter"
|
||||
|
||||
// If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY,
|
||||
// tool sound is only played when op is started. If not, it's played twice.
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
#define TRAIT_SPRINT_LOCKED "sprint_locked"
|
||||
|
||||
//non-mob traits
|
||||
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
|
||||
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
|
||||
#define VEHICLE_TRAIT "vehicle" // inherited from riding vehicles
|
||||
#define INNATE_TRAIT "innate"
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#define WOUND_DAMAGE_EXPONENT 1.4
|
||||
|
||||
#define WOUND_SEVERITY_TRIVIAL 0 // for jokey/meme wounds like stubbed toe, no standard messages/sounds or second winds
|
||||
#define WOUND_SEVERITY_MODERATE 1
|
||||
#define WOUND_SEVERITY_SEVERE 2
|
||||
#define WOUND_SEVERITY_CRITICAL 3
|
||||
#define WOUND_SEVERITY_LOSS 4 // theoretical total limb loss, like dismemberment for cuts
|
||||
|
||||
#define WOUND_BRUTE 0
|
||||
#define WOUND_SHARP 1
|
||||
#define WOUND_BURN 2
|
||||
|
||||
// How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind()]
|
||||
#define WOUND_DETERMINATION_MODERATE 1
|
||||
#define WOUND_DETERMINATION_SEVERE 2.5
|
||||
#define WOUND_DETERMINATION_CRITICAL 5
|
||||
|
||||
#define WOUND_DETERMINATION_MAX 10
|
||||
|
||||
// set wound_bonus on an item or attack to this to disable checking wounding for the attack
|
||||
#define CANT_WOUND -100
|
||||
|
||||
// list in order of highest severity to lowest
|
||||
#define WOUND_LIST_BONE list(/datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/moderate)
|
||||
#define WOUND_LIST_CUT list(/datum/wound/brute/cut/loss, /datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate)
|
||||
#define WOUND_LIST_BURN list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate)
|
||||
|
||||
// Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse
|
||||
#define WOUND_INFECTION_MODERATE 4 // below this has no ill effects from infection
|
||||
#define WOUND_INFECTION_SEVERE 8 // then below here, you ooze some pus and suffer minor tox damage, but nothing serious
|
||||
#define WOUND_INFECTION_CRITICAL 12 // then below here, your limb occasionally locks up from damage and infection and briefly becomes disabled. Things are getting really bad
|
||||
#define WOUND_INFECTION_SEPTIC 20 // below here, your skin is almost entirely falling off and your limb locks up more frequently. You are within a stone's throw of septic paralysis and losing the limb
|
||||
// above WOUND_INFECTION_SEPTIC, your limb is completely putrid and you start rolling to lose the entire limb by way of paralyzation. After 3 failed rolls (~4-5% each probably), the limb is paralyzed
|
||||
|
||||
#define WOUND_BURN_SANITIZATION_RATE 0.15 // how quickly sanitization removes infestation and decays per tick
|
||||
#define WOUND_CUT_MAX_BLOODFLOW 8 // how much blood you can lose per tick per cut max. 8 is a LOT of blood for one cut so don't worry about hitting it easily
|
||||
#define WOUND_BONE_HEAD_TIME_VARIANCE 20 // if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100)
|
||||
|
||||
// The following are for persistent scar save formats
|
||||
#define SCAR_SAVE_ZONE 1 // The body_zone we're applying to on granting
|
||||
#define SCAR_SAVE_DESC 2 // The description we're loading
|
||||
#define SCAR_SAVE_PRECISE_LOCATION 3 // The precise location we're loading
|
||||
#define SCAR_SAVE_SEVERITY 4 // The severity the scar had
|
||||
@@ -81,6 +81,10 @@
|
||||
if (CONFIG_GET(flag/log_attack))
|
||||
WRITE_LOG(GLOB.world_attack_log, "ATTACK: [text]")
|
||||
|
||||
/proc/log_wounded(text)
|
||||
if (CONFIG_GET(flag/log_attack))
|
||||
WRITE_LOG(GLOB.world_attack_log, "WOUND: [text]")
|
||||
|
||||
/proc/log_manifest(ckey, datum/mind/mind,mob/body, latejoin = FALSE)
|
||||
if (CONFIG_GET(flag/log_manifest))
|
||||
WRITE_LOG(GLOB.world_manifest_log, "[ckey] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]")
|
||||
|
||||
@@ -166,6 +166,8 @@
|
||||
|
||||
var/target_loc = target.loc
|
||||
|
||||
LAZYADD(user.do_afters, target)
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
var/datum/progressbar/progbar
|
||||
if (progress)
|
||||
@@ -183,6 +185,9 @@
|
||||
break
|
||||
if(uninterruptible)
|
||||
continue
|
||||
if(!(target in user.do_afters))
|
||||
. = FALSE
|
||||
break
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
@@ -191,9 +196,10 @@
|
||||
if((!drifting && user.loc != user_loc) || target.loc != target_loc || (!ignorehelditem && user.get_active_held_item() != holding) || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
if(progress)
|
||||
qdel(progbar)
|
||||
|
||||
if(!QDELETED(target))
|
||||
LAZYREMOVE(user.do_afters, target)
|
||||
|
||||
//some additional checks as a callback for for do_afters that want to break on losing health or on the mob taking action
|
||||
/mob/proc/break_do_after_checks(list/checked_health, check_clicks)
|
||||
@@ -216,6 +222,9 @@
|
||||
if(target && !isturf(target))
|
||||
Tloc = target.loc
|
||||
|
||||
if(target)
|
||||
LAZYADD(user.do_afters, target)
|
||||
|
||||
var/atom/Uloc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
@@ -260,6 +269,10 @@
|
||||
. = 0
|
||||
break
|
||||
|
||||
if(target && !(target in user.do_afters))
|
||||
. = FALSE
|
||||
break
|
||||
|
||||
if(needhand)
|
||||
//This might seem like an odd check, but you can still need a hand even when it's empty
|
||||
//i.e the hand is used to pull some item/tool out of the construction
|
||||
@@ -270,8 +283,10 @@
|
||||
if(user.get_active_held_item() != holding)
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
if(progress)
|
||||
qdel(progbar)
|
||||
if(!QDELETED(target))
|
||||
LAZYREMOVE(user.do_afters, target)
|
||||
|
||||
/mob/proc/do_after_coefficent() // This gets added to the delay on a do_after, default 1
|
||||
. = 1
|
||||
@@ -291,6 +306,7 @@
|
||||
var/list/originalloc = list()
|
||||
for(var/atom/target in targets)
|
||||
originalloc[target] = target.loc
|
||||
LAZYADD(user.do_afters, target)
|
||||
|
||||
var/holding = user.get_active_held_item()
|
||||
var/datum/progressbar/progbar
|
||||
@@ -321,3 +337,7 @@
|
||||
break mainloop
|
||||
if(progbar)
|
||||
qdel(progbar)
|
||||
for(var/thing in targets)
|
||||
var/atom/target = thing
|
||||
if(!QDELETED(target))
|
||||
LAZYREMOVE(user.do_afters, target)
|
||||
|
||||
@@ -339,10 +339,24 @@
|
||||
/proc/isLeap(y)
|
||||
return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
|
||||
|
||||
|
||||
/// For finding out what body parts a body zone covers, the inverse of the below basically
|
||||
/proc/zone2body_parts_covered(def_zone)
|
||||
switch(def_zone)
|
||||
if(BODY_ZONE_CHEST)
|
||||
return list(CHEST, GROIN)
|
||||
if(BODY_ZONE_HEAD)
|
||||
return list(HEAD)
|
||||
if(BODY_ZONE_L_ARM)
|
||||
return list(ARM_LEFT, HAND_LEFT)
|
||||
if(BODY_ZONE_R_ARM)
|
||||
return list(ARM_RIGHT, HAND_RIGHT)
|
||||
if(BODY_ZONE_L_LEG)
|
||||
return list(LEG_LEFT, FOOT_LEFT)
|
||||
if(BODY_ZONE_R_LEG)
|
||||
return list(LEG_RIGHT, FOOT_RIGHT)
|
||||
|
||||
//Turns a Body_parts_covered bitfield into a list of organ/limb names.
|
||||
//(I challenge you to find a use for this)
|
||||
//(I challenge you to find a use for this) -I found a use for it!!
|
||||
/proc/body_parts_covered2organ_names(bpc)
|
||||
var/list/covered_parts = list()
|
||||
|
||||
|
||||
@@ -4,12 +4,18 @@
|
||||
|
||||
Otherwise pretty standard.
|
||||
*/
|
||||
|
||||
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
|
||||
if(!has_active_hand()) //can't attack without a hand.
|
||||
to_chat(src, "<span class='notice'>You look at your arm and sigh.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/bodypart/check_arm = get_active_hand()
|
||||
if(check_arm && check_arm.is_disabled() == BODYPART_DISABLED_WOUND)
|
||||
to_chat(src, "<span class='warning'>The damage in your [check_arm.name] is preventing you from using it! Get it fixed, or at least splinted!</span>")
|
||||
return
|
||||
|
||||
// Special glove functions:
|
||||
// If the gloves do anything, have them return 1 to stop
|
||||
// normal attack_hand() here.
|
||||
|
||||
@@ -268,6 +268,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
SaveRandomizedRecipes()
|
||||
SavePanicBunker()
|
||||
SavePaintings()
|
||||
SaveScars()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
|
||||
var/bunker_path = file("data/bunker_passthrough.json")
|
||||
@@ -547,3 +548,24 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/json_file = file("data/paintings.json")
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(paintings))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SaveScars()
|
||||
for(var/i in GLOB.joined_player_list)
|
||||
var/mob/living/carbon/human/ending_human = get_mob_by_ckey(i)
|
||||
if(!istype(ending_human) || !ending_human.mind || !ending_human.client || !ending_human.client.prefs || !ending_human.client.prefs.persistent_scars)
|
||||
continue
|
||||
|
||||
var/mob/living/carbon/human/original_human = ending_human.mind.original_character
|
||||
if(!original_human || original_human.stat == DEAD || !original_human.all_scars || !(original_human == ending_human))
|
||||
if(ending_human.client) // i was told if i don't check this every step of the way byond might decide a client ceases to exist mid proc so here we go
|
||||
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ""
|
||||
else
|
||||
for(var/k in ending_human.all_wounds)
|
||||
var/datum/wound/W = k
|
||||
W.remove_wound() // so we can get the scars for open wounds
|
||||
if(!ending_human.client)
|
||||
return
|
||||
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ending_human.format_scars()
|
||||
if(!ending_human.client)
|
||||
return
|
||||
ending_human.client.prefs.save_character()
|
||||
|
||||
+15
-12
@@ -1,9 +1,9 @@
|
||||
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]"
|
||||
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[wound]"
|
||||
|
||||
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
. = locate(ARMORID)
|
||||
if (!.)
|
||||
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
|
||||
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound)
|
||||
|
||||
/datum/armor
|
||||
datum_flags = DF_USE_TAG
|
||||
@@ -17,8 +17,9 @@
|
||||
var/fire
|
||||
var/acid
|
||||
var/magic
|
||||
var/wound
|
||||
|
||||
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
src.melee = melee
|
||||
src.bullet = bullet
|
||||
src.laser = laser
|
||||
@@ -29,15 +30,16 @@
|
||||
src.fire = fire
|
||||
src.acid = acid
|
||||
src.magic = magic
|
||||
src.wound = wound
|
||||
tag = ARMORID
|
||||
|
||||
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic)
|
||||
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.wound+wound)
|
||||
|
||||
/datum/armor/proc/modifyAllRatings(modifier = 0)
|
||||
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier)
|
||||
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, wound+modifier)
|
||||
|
||||
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
|
||||
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound)
|
||||
return getArmor((isnull(melee) ? src.melee : melee),\
|
||||
(isnull(bullet) ? src.bullet : bullet),\
|
||||
(isnull(laser) ? src.laser : laser),\
|
||||
@@ -47,19 +49,20 @@
|
||||
(isnull(rad) ? src.rad : rad),\
|
||||
(isnull(fire) ? src.fire : fire),\
|
||||
(isnull(acid) ? src.acid : acid),\
|
||||
(isnull(magic) ? src.magic : magic))
|
||||
(isnull(magic) ? src.magic : magic),\
|
||||
(isnull(wound) ? src.wound : wound))
|
||||
|
||||
/datum/armor/proc/getRating(rating)
|
||||
return vars[rating]
|
||||
|
||||
/datum/armor/proc/getList()
|
||||
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
|
||||
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic, "wound" = wound)
|
||||
|
||||
/datum/armor/proc/attachArmor(datum/armor/AA)
|
||||
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic)
|
||||
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, wound+AA.wound)
|
||||
|
||||
/datum/armor/proc/detachArmor(datum/armor/AA)
|
||||
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic)
|
||||
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, wound-AA.wound)
|
||||
|
||||
/datum/armor/vv_edit_var(var_name, var_value)
|
||||
if (var_name == NAMEOF(src, tag))
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
if(get_dist(owner, stalker) <= 1)
|
||||
playsound(owner, 'sound/magic/demon_attack1.ogg', 50)
|
||||
owner.visible_message("<span class='warning'>[owner] is torn apart by invisible claws!</span>", "<span class='userdanger'>Ghostly claws tear your body apart!</span>")
|
||||
owner.take_bodypart_damage(rand(20, 45))
|
||||
owner.take_bodypart_damage(rand(20, 45), wound_bonus=CANT_WOUND)
|
||||
else if(prob(50))
|
||||
stalker.forceMove(get_step_towards(stalker, owner))
|
||||
if(get_dist(owner, stalker) <= 8)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var/speed = 80 //time in deciseconds taken to butcher something
|
||||
var/effectiveness = 100 //percentage effectiveness; numbers above 100 yield extra drops
|
||||
var/bonus_modifier = 0 //percentage increase to bonus item chance
|
||||
var/butcher_sound = 'sound/weapons/slice.ogg' //sound played when butchering
|
||||
var/butcher_sound = 'sound/effects/butcher.ogg' //sound played when butchering
|
||||
var/butchering_enabled = TRUE
|
||||
var/can_be_blunt = FALSE
|
||||
|
||||
@@ -64,8 +64,11 @@
|
||||
H.visible_message("<span class='danger'>[user] slits [H]'s throat!</span>", \
|
||||
"<span class='userdanger'>[user] slits your throat...</span>")
|
||||
log_combat(user, H, "finishes slicing the throat of")
|
||||
H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD)
|
||||
H.bleed_rate = clamp(H.bleed_rate + 20, 0, 30)
|
||||
H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD, wound_bonus=CANT_WOUND) // easy tiger, we'll get to that in a sec
|
||||
var/obj/item/bodypart/slit_throat = H.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(slit_throat)
|
||||
var/datum/wound/brute/cut/critical/screaming_through_a_slit_throat = new
|
||||
screaming_through_a_slit_throat.apply_wound(slit_throat)
|
||||
H.apply_status_effect(/datum/status_effect/neck_slice)
|
||||
|
||||
/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
var/damage = rand(min_damage, max_damage)
|
||||
if(HAS_TRAIT(H, TRAIT_LIGHT_STEP))
|
||||
damage *= 0.75
|
||||
H.apply_damage(damage, BRUTE, picked_def_zone)
|
||||
H.apply_damage(damage, BRUTE, picked_def_zone, wound_bonus = CANT_WOUND)
|
||||
|
||||
if(cooldown < world.time - 10) //cooldown to avoid message spam.
|
||||
if(!H.incapacitated(ignore_restraints = TRUE))
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
playsound(victim,'sound/weapons/bladeslice.ogg', 40)
|
||||
weapon.add_mob_blood(victim)//it embedded itself in you, of course it's bloody!
|
||||
var/damage = weapon.w_class * impact_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus=-30, sharpness = TRUE)
|
||||
SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
else
|
||||
victim.visible_message("<span class='danger'>[weapon] sticks itself to [victim]'s [limb.name]!</span>",ignored_mobs=victim)
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
if(harmful && prob(chance))
|
||||
var/damage = weapon.w_class * jostle_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] embedded in your [limb.name] jostles and stings!</span>")
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
|
||||
if(harmful)
|
||||
var/damage = weapon.w_class * remove_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
|
||||
victim.visible_message("<span class='danger'>[weapon] falls out of [victim.name]'s [limb.name]!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] falls out of your [limb.name]!</span>")
|
||||
else
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
if(harmful)
|
||||
var/damage = weapon.w_class * remove_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage) //It hurts to rip it out, get surgery you dingus.
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, sharpness=TRUE) //It hurts to rip it out, get surgery you dingus.
|
||||
victim.emote("scream")
|
||||
victim.visible_message("<span class='notice'>[victim] successfully rips [weapon] out of [victim.p_their()] [limb.name]!</span>", "<span class='notice'>You successfully remove [weapon] from your [limb.name].</span>")
|
||||
else
|
||||
@@ -276,7 +276,7 @@
|
||||
damage *= 0.7
|
||||
|
||||
if(harmful && prob(chance))
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] embedded in your [limb.name] hurts!</span>")
|
||||
|
||||
if(prob(fall_chance))
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
///Store the thrownthing datum for later use
|
||||
/datum/component/tackler/proc/registerTackle(mob/living/carbon/user, datum/thrownthing/TT)
|
||||
tackle = TT
|
||||
tackle.thrower = user
|
||||
|
||||
///See if we can tackle or not. If we can, leap!
|
||||
/datum/component/tackler/proc/checkTackle(mob/living/carbon/user, atom/A, params)
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
|
||||
/datum/datacore/proc/manifest()
|
||||
for(var/mob/dead/new_player/N in GLOB.player_list)
|
||||
if(!N?.client)
|
||||
continue
|
||||
if(N.new_character)
|
||||
log_manifest(N.ckey,N.new_character.mind,N.new_character)
|
||||
if(ishuman(N.new_character))
|
||||
|
||||
@@ -64,7 +64,8 @@ Bonus
|
||||
if(bleed)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.bleed_rate += 5 * power
|
||||
var/obj/item/bodypart/random_part = pick(H.bodyparts)
|
||||
random_part.generic_bleedstacks += 5 * power
|
||||
return 1
|
||||
|
||||
/*
|
||||
|
||||
@@ -223,8 +223,8 @@
|
||||
/obj/item/clothing/gloves/krav_maga/combatglovesplus
|
||||
name = "combat gloves plus"
|
||||
desc = "These tactical gloves are fireproof and shock resistant, and using nanochip technology it teaches you the powers of krav maga."
|
||||
icon_state = "combat"
|
||||
item_state = "blackgloves"
|
||||
icon_state = "fightglovesblack"
|
||||
item_state = "fightglovesblack"
|
||||
siemens_coefficient = 0
|
||||
permeability_coefficient = 0.05
|
||||
strip_delay = 80
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
else
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1)
|
||||
log_combat(A, D, "strong punched (Sleeping Carp)")//so as to not double up on logging
|
||||
D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting)
|
||||
D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting, wound_bonus = CANT_WOUND)
|
||||
return TRUE
|
||||
|
||||
///Crashing Wave Kick: Harm Disarm combo, throws people seven tiles backwards
|
||||
@@ -56,7 +56,7 @@
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
|
||||
var/atom/throw_target = get_edge_target_turf(D, A.dir)
|
||||
D.throw_at(throw_target, 7, 14, A)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST, wound_bonus = CANT_WOUND, wound_bonus = CANT_WOUND)
|
||||
log_combat(A, D, "launchkicked (Sleeping Carp)")
|
||||
return TRUE
|
||||
|
||||
@@ -66,14 +66,14 @@
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
|
||||
if((D.mobility_flags & MOBILITY_STAND))
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
|
||||
D.DefaultCombatKnockdown(50, override_hardstun = 0.01, override_stamdmg = 0)
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD) //A cit specific change form the tg port to really punish anyone who tries to stand up
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND) //A cit specific change form the tg port to really punish anyone who tries to stand up
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the head, sending them face first into the floor!</span>", \
|
||||
"<span class='userdanger'>You are kicked in the head by [A], sending you crashing to the floor!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
else
|
||||
D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
|
||||
D.drop_all_held_items()
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the head!</span>", \
|
||||
"<span class='userdanger'>You are kicked in the head by [A]!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
@@ -99,7 +99,7 @@
|
||||
D.visible_message("<span class='danger'>[A] [atk_verb]s [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [atk_verb]s you!</span>", null, null, A)
|
||||
to_chat(A, "<span class='danger'>You [atk_verb] [D]!</span>")
|
||||
D.apply_damage(damage, BRUTE, affecting)
|
||||
D.apply_damage(damage, BRUTE, affecting, wound_bonus = CANT_WOUND)
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND) && damage >= stunthreshold)
|
||||
to_chat(D, "<span class='danger'>You stumble and fall!</span>")
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
/// Our skill holder.
|
||||
var/datum/skill_holder/skill_holder
|
||||
|
||||
///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not
|
||||
var/mob/original_character
|
||||
|
||||
/datum/mind/New(var/key)
|
||||
skill_holder = new(src)
|
||||
src.key = key
|
||||
|
||||
@@ -77,10 +77,14 @@
|
||||
description = "<span class='boldwarning'>Pull it out!</span>\n"
|
||||
mood_change = -7
|
||||
|
||||
/datum/mood_event/table
|
||||
description = "<span class='warning'>Someone threw me on a table!</span>\n"
|
||||
mood_change = -2
|
||||
timeout = 2 MINUTES
|
||||
/datum/mood_event/table_limbsmash
|
||||
description = "<span class='warning'>That fucking table, man that hurts...</span>\n"
|
||||
mood_change = -3
|
||||
timeout = 3 MINUTES
|
||||
|
||||
/datum/mood_event/table_limbsmash/add_effects(obj/item/bodypart/banged_limb)
|
||||
if(banged_limb)
|
||||
description = "<span class='warning'>My fucking [banged_limb.name], man that hurts...</span>\n"
|
||||
|
||||
/datum/mood_event/table/add_effects()
|
||||
if(ishuman(owner))
|
||||
|
||||
@@ -441,6 +441,10 @@
|
||||
owner.adjustBruteLoss(-10, FALSE)
|
||||
owner.adjustFireLoss(-5, FALSE)
|
||||
owner.adjustOxyLoss(-10)
|
||||
if(!iscarbon(owner))
|
||||
return
|
||||
var/mob/living/carbon/C = owner
|
||||
QDEL_LIST(C.all_scars)
|
||||
|
||||
/obj/screen/alert/status_effect/fleshmend
|
||||
name = "Fleshmend"
|
||||
|
||||
@@ -430,10 +430,19 @@
|
||||
|
||||
/datum/status_effect/neck_slice/tick()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.stat == DEAD || H.bleed_rate <= 8)
|
||||
var/obj/item/bodypart/throat = H.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(H.stat == DEAD || !throat)
|
||||
H.remove_status_effect(/datum/status_effect/neck_slice)
|
||||
if(prob(10))
|
||||
H.emote(pick("gasp", "gag", "choke"))
|
||||
var/still_bleeding = FALSE
|
||||
for(var/thing in throat.wounds)
|
||||
var/datum/wound/W = thing
|
||||
if(W.wound_type == WOUND_LIST_CUT && W.severity > WOUND_SEVERITY_MODERATE)
|
||||
still_bleeding = TRUE
|
||||
break
|
||||
if(!still_bleeding)
|
||||
H.remove_status_effect(/datum/status_effect/neck_slice)
|
||||
|
||||
/mob/living/proc/apply_necropolis_curse(set_curse, duration = 10 MINUTES)
|
||||
var/datum/status_effect/necropolis_curse/C = has_status_effect(STATUS_EFFECT_NECROPOLIS_CURSE)
|
||||
|
||||
@@ -279,3 +279,7 @@
|
||||
/datum/status_effect/grouped/before_remove(source)
|
||||
sources -= source
|
||||
return !length(sources)
|
||||
|
||||
//do_after modifier!
|
||||
/datum/status_effect/proc/interact_speed_modifier()
|
||||
return 1
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
|
||||
// The shattered remnants of your broken limbs fill you with determination!
|
||||
/obj/screen/alert/status_effect/determined
|
||||
name = "Determined"
|
||||
desc = "The serious wounds you've sustained have put your body into fight-or-flight mode! Now's the time to look for an exit!"
|
||||
icon_state = "regenerative_core"
|
||||
|
||||
/datum/status_effect/determined
|
||||
id = "determined"
|
||||
alert_type = /obj/screen/alert/status_effect/determined
|
||||
|
||||
/datum/status_effect/determined/on_apply()
|
||||
. = ..()
|
||||
owner.visible_message("<span class='danger'>[owner] grits [owner.p_their()] teeth in pain!</span>", "<span class='notice'><b>Your senses sharpen as your body tenses up from the wounds you've sustained!</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/datum/status_effect/determined/on_remove()
|
||||
owner.visible_message("<span class='danger'>[owner]'s body slackens noticeably!</span>", "<span class='warning'><b>Your adrenaline rush dies off, and the pain from your wounds come aching back in...</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/limp
|
||||
id = "limp"
|
||||
status_type = STATUS_EFFECT_REPLACE
|
||||
tick_interval = 10
|
||||
alert_type = /obj/screen/alert/status_effect/limp
|
||||
var/msg_stage = 0//so you dont get the most intense messages immediately
|
||||
/// The left leg of the limping person
|
||||
var/obj/item/bodypart/l_leg/left
|
||||
/// The right leg of the limping person
|
||||
var/obj/item/bodypart/r_leg/right
|
||||
/// Which leg we're limping with next
|
||||
var/obj/item/bodypart/next_leg
|
||||
/// How many deciseconds we limp for on the left leg
|
||||
var/slowdown_left = 0
|
||||
/// How many deciseconds we limp for on the right leg
|
||||
var/slowdown_right = 0
|
||||
|
||||
/datum/status_effect/limp/on_apply()
|
||||
if(!iscarbon(owner))
|
||||
return FALSE
|
||||
var/mob/living/carbon/C = owner
|
||||
left = C.get_bodypart(BODY_ZONE_L_LEG)
|
||||
right = C.get_bodypart(BODY_ZONE_R_LEG)
|
||||
update_limp()
|
||||
RegisterSignal(C, COMSIG_MOVABLE_MOVED, .proc/check_step)
|
||||
RegisterSignal(C, list(COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB), .proc/update_limp)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/limp/on_remove()
|
||||
UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB))
|
||||
return ..()
|
||||
|
||||
/obj/screen/alert/status_effect/limp
|
||||
name = "Limping"
|
||||
desc = "One or more of your legs has been wounded, slowing down steps with that leg! Get it fixed, or at least splinted!"
|
||||
|
||||
/datum/status_effect/limp/proc/check_step(mob/whocares, OldLoc, Dir, forced)
|
||||
if(!owner.client || !(owner.mobility_flags & MOBILITY_STAND) || !owner.has_gravity() || (owner.movement_type & FLYING) || forced)
|
||||
return
|
||||
var/determined_mod = 1
|
||||
if(owner.has_status_effect(STATUS_EFFECT_DETERMINED))
|
||||
determined_mod = 0.25
|
||||
if(next_leg == left)
|
||||
owner.client.move_delay += slowdown_left * determined_mod
|
||||
next_leg = right
|
||||
else
|
||||
owner.client.move_delay += slowdown_right * determined_mod
|
||||
next_leg = left
|
||||
|
||||
/datum/status_effect/limp/proc/update_limp()
|
||||
var/mob/living/carbon/C = owner
|
||||
left = C.get_bodypart(BODY_ZONE_L_LEG)
|
||||
right = C.get_bodypart(BODY_ZONE_R_LEG)
|
||||
|
||||
if(!left && !right)
|
||||
C.remove_status_effect(src)
|
||||
return
|
||||
|
||||
slowdown_left = 0
|
||||
slowdown_right = 0
|
||||
|
||||
if(left)
|
||||
for(var/thing in left.wounds)
|
||||
var/datum/wound/W = thing
|
||||
slowdown_left += W.limp_slowdown
|
||||
|
||||
if(right)
|
||||
for(var/thing in right.wounds)
|
||||
var/datum/wound/W = thing
|
||||
slowdown_right += W.limp_slowdown
|
||||
|
||||
// this handles losing your leg with the limp and the other one being in good shape as well
|
||||
if(!slowdown_left && !slowdown_right)
|
||||
C.remove_status_effect(src)
|
||||
return
|
||||
|
||||
|
||||
/////////////////////////
|
||||
//////// WOUNDS /////////
|
||||
/////////////////////////
|
||||
|
||||
// wound alert
|
||||
/obj/screen/alert/status_effect/wound
|
||||
name = "Wounded"
|
||||
desc = "Your body has sustained serious damage, click here to inspect yourself."
|
||||
|
||||
/obj/screen/alert/status_effect/wound/Click()
|
||||
var/mob/living/carbon/C = usr
|
||||
C.check_self_for_injuries()
|
||||
|
||||
// wound status effect base
|
||||
/datum/status_effect/wound
|
||||
id = "wound"
|
||||
status_type = STATUS_EFFECT_MULTIPLE
|
||||
var/obj/item/bodypart/linked_limb
|
||||
var/datum/wound/linked_wound
|
||||
alert_type = NONE
|
||||
|
||||
/datum/status_effect/wound/on_creation(mob/living/new_owner, incoming_wound)
|
||||
. = ..()
|
||||
var/datum/wound/W = incoming_wound
|
||||
linked_wound = W
|
||||
linked_limb = linked_wound.limb
|
||||
|
||||
/datum/status_effect/wound/on_remove()
|
||||
linked_wound = null
|
||||
linked_limb = null
|
||||
UnregisterSignal(owner, COMSIG_CARBON_LOSE_WOUND)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/wound/on_apply()
|
||||
if(!iscarbon(owner))
|
||||
return FALSE
|
||||
RegisterSignal(owner, COMSIG_CARBON_LOSE_WOUND, .proc/check_remove)
|
||||
return ..()
|
||||
|
||||
/// check if the wound getting removed is the wound we're tied to
|
||||
/datum/status_effect/wound/proc/check_remove(mob/living/L, datum/wound/W)
|
||||
if(W == linked_wound)
|
||||
qdel(src)
|
||||
|
||||
|
||||
// bones
|
||||
/datum/status_effect/wound/bone
|
||||
|
||||
/datum/status_effect/wound/bone/interact_speed_modifier()
|
||||
var/mob/living/carbon/C = owner
|
||||
|
||||
if(C.get_active_hand() == linked_limb)
|
||||
to_chat(C, "<span class='warning'>The [lowertext(linked_wound)] in your [linked_limb.name] slows your progress!</span>")
|
||||
return linked_wound.interaction_efficiency_penalty
|
||||
|
||||
return 1
|
||||
|
||||
/datum/status_effect/wound/bone/nextmove_modifier()
|
||||
var/mob/living/carbon/C = owner
|
||||
|
||||
if(C.get_active_hand() == linked_limb)
|
||||
return linked_wound.interaction_efficiency_penalty
|
||||
|
||||
return 1
|
||||
|
||||
/datum/status_effect/wound/bone/moderate
|
||||
id = "disjoint"
|
||||
/datum/status_effect/wound/bone/severe
|
||||
id = "hairline"
|
||||
|
||||
/datum/status_effect/wound/bone/critical
|
||||
id = "compound"
|
||||
|
||||
// cuts
|
||||
/datum/status_effect/wound/cut/moderate
|
||||
id = "abrasion"
|
||||
|
||||
/datum/status_effect/wound/cut/severe
|
||||
id = "laceration"
|
||||
|
||||
/datum/status_effect/wound/cut/critical
|
||||
id = "avulsion"
|
||||
|
||||
// burns
|
||||
/datum/status_effect/wound/burn/moderate
|
||||
id = "seconddeg"
|
||||
|
||||
/datum/status_effect/wound/burn/severe
|
||||
id = "thirddeg"
|
||||
|
||||
/datum/status_effect/wound/burn/critical
|
||||
id = "fourthdeg"
|
||||
@@ -122,3 +122,19 @@
|
||||
if(H)
|
||||
var/datum/species/species = H.dna.species
|
||||
species.disliked_food &= ~ALCOHOL
|
||||
|
||||
/datum/quirk/longtimer
|
||||
name = "Longtimer"
|
||||
desc = "You've been around for a long time and seen more than your fair share of action, suffering some pretty nasty scars along the way. For whatever reason, you've declined to get them removed or augmented."
|
||||
value = 0
|
||||
gain_text = "<span class='notice'>Your body has seen better days.</span>"
|
||||
lose_text = "<span class='notice'>Your sins may wash away, but those scars are here to stay...</span>"
|
||||
medical_record_text = "Patient has withstood significant physical trauma and declined plastic surgery procedures to heal scarring."
|
||||
/// the minimum amount of scars we can generate
|
||||
var/min_scars = 3
|
||||
/// the maximum amount of scars we can generate
|
||||
var/max_scars = 7
|
||||
|
||||
/datum/quirk/longtimer/on_spawn()
|
||||
var/mob/living/carbon/C = quirk_holder
|
||||
C.generate_fake_scars(rand(min_scars, max_scars))
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* scars are cosmetic datums that are assigned to bodyparts once they recover from wounds. Each wound type and severity have their own descriptions for what the scars
|
||||
* look like, and then each body part has a list of "specific locations" like your elbow or wrist or wherever the scar can appear, to make it more interesting than "right arm"
|
||||
*
|
||||
*
|
||||
* Arguments:
|
||||
* *
|
||||
*/
|
||||
/datum/scar
|
||||
var/obj/item/bodypart/limb
|
||||
var/mob/living/carbon/victim
|
||||
var/severity
|
||||
var/description
|
||||
var/precise_location
|
||||
|
||||
/// Scars from the longtimer quirk are "fake" and won't be saved with persistent scarring, since it makes you spawn with a lot by default
|
||||
var/fake=FALSE
|
||||
|
||||
/// How many tiles away someone can see this scar, goes up with severity. Clothes covering this limb will decrease visibility by 1 each, except for the head/face which is a binary "is mask obscuring face" check
|
||||
var/visibility = 2
|
||||
/// Whether this scar can actually be covered up by clothing
|
||||
var/coverable = TRUE
|
||||
/// What zones this scar can be applied to
|
||||
var/list/applicable_zones = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_ARM, BODY_ZONE_R_LEG)
|
||||
|
||||
/datum/scar/Destroy(force, ...)
|
||||
if(limb)
|
||||
LAZYREMOVE(limb.scars, src)
|
||||
if(victim)
|
||||
LAZYREMOVE(victim.all_scars, src)
|
||||
. = ..()
|
||||
|
||||
/**
|
||||
* generate() is used to actually fill out the info for a scar, according to the limb and wound it is provided.
|
||||
*
|
||||
* After creating a scar, call this on it while targeting the scarred bodypart with a given wound to apply the scar.
|
||||
*
|
||||
* Arguments:
|
||||
* * BP- The bodypart being targeted
|
||||
* * W- The wound being used to generate the severity and description info
|
||||
* * add_to_scars- Should always be TRUE unless you're just storing a scar for later usage, like how cuts want to store a scar for the highest severity of cut, rather than the severity when the wound is fully healed (probably demoted to moderate)
|
||||
*/
|
||||
/datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE)
|
||||
if(!(BP.body_zone in applicable_zones))
|
||||
qdel(src)
|
||||
return
|
||||
limb = BP
|
||||
severity = W.severity
|
||||
if(limb.owner)
|
||||
victim = limb.owner
|
||||
if(add_to_scars)
|
||||
LAZYADD(limb.scars, src)
|
||||
if(victim)
|
||||
LAZYADD(victim.all_scars, src)
|
||||
|
||||
description = pick(W.scarring_descriptions)
|
||||
precise_location = pick(limb.specific_locations)
|
||||
switch(W.severity)
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
visibility = 2
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
visibility = 3
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
visibility = 5
|
||||
|
||||
/// Used when we finalize a scar from a healing cut
|
||||
/datum/scar/proc/lazy_attach(obj/item/bodypart/BP, datum/wound/W)
|
||||
LAZYADD(BP.scars, src)
|
||||
if(BP.owner)
|
||||
victim = BP.owner
|
||||
LAZYADD(victim.all_scars, src)
|
||||
|
||||
/// Used to "load" a persistent scar
|
||||
/datum/scar/proc/load(obj/item/bodypart/BP, description, specific_location, severity=WOUND_SEVERITY_SEVERE)
|
||||
if(!(BP.body_zone in applicable_zones))
|
||||
qdel(src)
|
||||
return
|
||||
limb = BP
|
||||
src.severity = severity
|
||||
LAZYADD(limb.scars, src)
|
||||
if(BP.owner)
|
||||
victim = BP.owner
|
||||
LAZYADD(victim.all_scars, src)
|
||||
src.description = description
|
||||
precise_location = specific_location
|
||||
switch(severity)
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
visibility = 2
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
visibility = 3
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
visibility = 5
|
||||
return TRUE
|
||||
|
||||
/// What will show up in examine_more() if this scar is visible
|
||||
/datum/scar/proc/get_examine_description(mob/viewer)
|
||||
if(!victim || !is_visible(viewer))
|
||||
return
|
||||
|
||||
var/msg = "[victim.p_they(TRUE)] [victim.p_have()] [description] on [victim.p_their()] [precise_location]."
|
||||
switch(severity)
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
msg = "<span class='tinynotice'>[msg]</span>"
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
msg = "<span class='smallnotice'>[msg]</span>"
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
msg = "<span class='smallnotice'><b>[msg]</b></span>"
|
||||
return "\t[msg]"
|
||||
|
||||
/// Whether a scar can currently be seen by the viewer
|
||||
/datum/scar/proc/is_visible(mob/viewer)
|
||||
if(!victim || !viewer)
|
||||
return
|
||||
if(get_dist(viewer, victim) > visibility)
|
||||
return
|
||||
|
||||
if(!ishuman(victim) || isobserver(viewer) || victim == viewer)
|
||||
return TRUE
|
||||
|
||||
var/mob/living/carbon/human/H = victim
|
||||
if(istype(limb, /obj/item/bodypart/head))
|
||||
if((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) || (H.head && (H.head.flags_inv & HIDEFACE)))
|
||||
return FALSE
|
||||
else if(limb.scars_covered_by_clothes)
|
||||
var/num_covers = LAZYLEN(H.clothingonpart(limb))
|
||||
if(num_covers + get_dist(viewer, victim) >= visibility)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Used to format a scar to safe in preferences for persistent scars
|
||||
/datum/scar/proc/format()
|
||||
if(!fake)
|
||||
return "[limb.body_zone]|[description]|[precise_location]|[severity]"
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
Wounds are specific medical complications that can arise and be applied to (currently) carbons, with a focus on humans. All of the code for and related to this is heavily WIP,
|
||||
and the documentation will be slanted towards explaining what each part/piece is leading up to, until such a time as I finish the core implementations. The original design doc
|
||||
can be found at https://hackmd.io/@Ryll/r1lb4SOwU
|
||||
|
||||
Wounds are datums that operate like a mix of diseases, brain traumas, and components, and are applied to a /obj/item/bodypart (preferably attached to a carbon) when they take large spikes of damage
|
||||
or under other certain conditions (thrown hard against a wall, sustained exposure to plasma fire, etc). Wounds are categorized by the three following criteria:
|
||||
1. Severity: Either MODERATE, SEVERE, or CRITICAL. See the hackmd for more details
|
||||
2. Viable zones: What body parts the wound is applicable to. Generic wounds like broken bones and severe burns can apply to every zone, but you may want to add special wounds for certain limbs
|
||||
like a twisted ankle for legs only, or open air exposure of the organs for particularly gruesome chest wounds. Wounds should be able to function for every zone they are marked viable for.
|
||||
3. Damage type: Currently either BRUTE or BURN. Again, see the hackmd for a breakdown of my plans for each type.
|
||||
|
||||
When a body part suffers enough damage to get a wound, the severity (determined by a roll or something, worse damage leading to worse wounds), affected limb, and damage type sustained are factored into
|
||||
deciding what specific wound will be applied. I'd like to have a few different types of wounds for at least some of the choices, but I'm just doing rough generals for now. Expect polishing
|
||||
*/
|
||||
|
||||
/datum/wound
|
||||
/// What it's named
|
||||
var/name = "ouchie"
|
||||
/// The description shown on the scanners
|
||||
var/desc = ""
|
||||
/// The basic treatment suggested by health analyzers
|
||||
var/treat_text = ""
|
||||
/// What the limb looks like on a cursory examine
|
||||
var/examine_desc = "is badly hurt"
|
||||
|
||||
/// needed for "your arm has a compound fracture" vs "your arm has some third degree burns"
|
||||
var/a_or_from = "a"
|
||||
/// The visible message when this happens
|
||||
var/occur_text = ""
|
||||
/// This sound will be played upon the wound being applied
|
||||
var/sound_effect
|
||||
|
||||
/// Either WOUND_SEVERITY_TRIVIAL (meme wounds like stubbed toe), WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_SEVERE, or WOUND_SEVERITY_CRITICAL (or maybe WOUND_SEVERITY_LOSS)
|
||||
var/severity = WOUND_SEVERITY_MODERATE
|
||||
/// The list of wounds it belongs in, WOUND_LIST_BONE, WOUND_LIST_CUT, or WOUND_LIST_BURN
|
||||
var/wound_type
|
||||
|
||||
/// What body zones can we affect
|
||||
var/list/viable_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
/// Who owns the body part that we're wounding
|
||||
var/mob/living/carbon/victim = null
|
||||
/// If we only work on organics (everything right now)
|
||||
var/organic_only = TRUE
|
||||
/// The bodypart we're parented to
|
||||
var/obj/item/bodypart/limb = null
|
||||
|
||||
/// Specific items such as bandages or sutures that can try directly treating this wound
|
||||
var/list/treatable_by
|
||||
/// Specific items such as bandages or sutures that can try directly treating this wound only if the user has the victim in an aggressive grab or higher
|
||||
var/list/treatable_by_grabbed
|
||||
/// Tools with the specified tool flag will also be able to try directly treating this wound
|
||||
var/treatable_tool
|
||||
/// Set to TRUE if we don't give a shit about the patient's comfort and are allowed to just use any random sharp thing on this wound. Will require an aggressive grab or more to perform
|
||||
var/treatable_sharp
|
||||
/// How long it will take to treat this wound with a standard effective tool, assuming it doesn't need surgery
|
||||
var/base_treat_time = 5 SECONDS
|
||||
|
||||
/// Using this limb in a do_after interaction will multiply the length by this duration (arms)
|
||||
var/interaction_efficiency_penalty = 1
|
||||
/// Incoming damage on this limb will be multiplied by this, to simulate tenderness and vulnerability (mostly burns).
|
||||
var/damage_mulitplier_penalty = 1
|
||||
/// If set and this wound is applied to a leg, we take this many deciseconds extra per step on this leg
|
||||
var/limp_slowdown
|
||||
/// How much we're contributing to this limb's bleed_rate
|
||||
var/blood_flow
|
||||
|
||||
/// The minimum we need to roll on [/obj/item/bodypart/proc/check_wounding()] to begin suffering this wound, see check_wounding_mods() for more
|
||||
var/threshold_minimum
|
||||
/// How much having this wound will add to all future check_wounding() rolls on this limb, to allow progression to worse injuries with repeated damage
|
||||
var/threshold_penalty
|
||||
/// If we need to process each life tick
|
||||
var/processes = FALSE
|
||||
|
||||
/// If TRUE and an item that can treat multiple different types of coexisting wounds (gauze can be used to splint broken bones, staunch bleeding, and cover burns), we get first dibs if we come up first for it, then become nonpriority.
|
||||
/// Otherwise, if no untreated wound claims the item, we cycle through the non priority wounds and pick a random one who can use that item.
|
||||
var/treat_priority = FALSE
|
||||
|
||||
/// If having this wound makes currently makes the parent bodypart unusable
|
||||
var/disabling
|
||||
|
||||
/// What status effect we assign on application
|
||||
var/status_effect_type
|
||||
/// The status effect we're linked to
|
||||
var/datum/status_effect/linked_status_effect
|
||||
/// If we're operating on this wound and it gets healed, we'll nix the surgery too
|
||||
var/datum/surgery/attached_surgery
|
||||
/// if you're a lazy git and just throw them in cryo, the wound will go away after accumulating severity * 25 power
|
||||
var/cryo_progress
|
||||
|
||||
/// What kind of scars this wound will create description wise once healed
|
||||
var/list/scarring_descriptions = list("general disfigurement")
|
||||
/// If we've already tried scarring while removing (since remove_wound calls qdel, and qdel calls remove wound, .....) TODO: make this cleaner
|
||||
var/already_scarred = FALSE
|
||||
/// If we forced this wound through badmin smite, we won't count it towards the round totals
|
||||
var/from_smite
|
||||
|
||||
/datum/wound/Destroy()
|
||||
if(attached_surgery)
|
||||
QDEL_NULL(attached_surgery)
|
||||
if(limb?.wounds && (src in limb.wounds)) // destroy can call remove_wound() and remove_wound() calls qdel, so we check to make sure there's anything to remove first
|
||||
remove_wound()
|
||||
limb = null
|
||||
victim = null
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* apply_wound() is used once a wound type is instantiated to assign it to a bodypart, and actually come into play.
|
||||
*
|
||||
*
|
||||
* Arguments:
|
||||
* * L: The bodypart we're wounding, we don't care about the person, we can get them through the limb
|
||||
* * silent: Not actually necessary I don't think, was originally used for demoting wounds so they wouldn't make new messages, but I believe old_wound took over that, I may remove this shortly
|
||||
* * old_wound: If our new wound is a replacement for one of the same time (promotion or demotion), we can reference the old one just before it's removed to copy over necessary vars
|
||||
* * smited- If this is a smite, we don't care about this wound for stat tracking purposes (not yet implemented)
|
||||
*/
|
||||
/datum/wound/proc/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE)
|
||||
if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || isalien(L.owner))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(ishuman(L.owner))
|
||||
var/mob/living/carbon/human/H = L.owner
|
||||
if(organic_only && ((NOBLOOD in H.dna.species.species_traits) || !L.is_organic_limb()))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// we accept promotions and demotions, but no point in redundancy. This should have already been checked wherever the wound was rolled and applied for (see: bodypart damage code), but we do an extra check
|
||||
// in case we ever directly add wounds
|
||||
for(var/i in L.wounds)
|
||||
var/datum/wound/preexisting_wound = i
|
||||
if((preexisting_wound.type == type) && (preexisting_wound != old_wound))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
victim = L.owner
|
||||
limb = L
|
||||
LAZYADD(victim.all_wounds, src)
|
||||
LAZYADD(limb.wounds, src)
|
||||
limb.update_wounds()
|
||||
if(status_effect_type)
|
||||
linked_status_effect = victim.apply_status_effect(status_effect_type, src)
|
||||
SEND_SIGNAL(victim, COMSIG_CARBON_GAIN_WOUND, src, limb)
|
||||
if(!victim.alerts["wound"]) // only one alert is shared between all of the wounds
|
||||
victim.throw_alert("wound", /obj/screen/alert/status_effect/wound)
|
||||
|
||||
var/demoted
|
||||
if(old_wound)
|
||||
demoted = (severity <= old_wound.severity)
|
||||
|
||||
if(severity == WOUND_SEVERITY_TRIVIAL)
|
||||
return
|
||||
|
||||
if(!(silent || demoted))
|
||||
var/msg = "<span class='danger'>[victim]'s [limb.name] [occur_text]!</span>"
|
||||
var/vis_dist = COMBAT_MESSAGE_RANGE
|
||||
|
||||
if(severity != WOUND_SEVERITY_MODERATE)
|
||||
msg = "<b>[msg]</b>"
|
||||
vis_dist = DEFAULT_MESSAGE_RANGE
|
||||
|
||||
victim.visible_message(msg, "<span class='userdanger'>Your [limb.name] [occur_text]!</span>", vision_distance = vis_dist)
|
||||
if(sound_effect)
|
||||
playsound(L.owner, sound_effect, 60 + 20 * severity, TRUE)
|
||||
|
||||
if(!demoted)
|
||||
wound_injury(old_wound)
|
||||
second_wind()
|
||||
|
||||
/// Remove the wound from whatever it's afflicting, and cleans up whateverstatus effects it had or modifiers it had on interaction times. ignore_limb is used for detachments where we only want to forget the victim
|
||||
/datum/wound/proc/remove_wound(ignore_limb, replaced = FALSE)
|
||||
//TODO: have better way to tell if we're getting removed without replacement (full heal) scar stuff
|
||||
if(limb && !already_scarred && !replaced)
|
||||
already_scarred = TRUE
|
||||
var/datum/scar/new_scar = new
|
||||
new_scar.generate(limb, src)
|
||||
if(victim)
|
||||
LAZYREMOVE(victim.all_wounds, src)
|
||||
if(!victim.all_wounds)
|
||||
victim.clear_alert("wound")
|
||||
SEND_SIGNAL(victim, COMSIG_CARBON_LOSE_WOUND, src, limb)
|
||||
if(limb && !ignore_limb)
|
||||
LAZYREMOVE(limb.wounds, src)
|
||||
limb.update_wounds()
|
||||
|
||||
/**
|
||||
* replace_wound() is used when you want to replace the current wound with a new wound, presumably of the same category, just of a different severity (either up or down counts)
|
||||
*
|
||||
* This proc actually instantiates the new wound based off the specific type path passed, then returns the new instantiated wound datum.
|
||||
*
|
||||
* Arguments:
|
||||
* * new_type- The TYPE PATH of the wound you want to replace this, like /datum/wound/brute/cut/severe
|
||||
* * smited- If this is a smite, we don't care about this wound for stat tracking purposes (not yet implemented)
|
||||
*/
|
||||
/datum/wound/proc/replace_wound(new_type, smited = FALSE)
|
||||
var/datum/wound/new_wound = new new_type
|
||||
already_scarred = TRUE
|
||||
remove_wound(replaced=TRUE)
|
||||
new_wound.apply_wound(limb, old_wound = src, smited = smited)
|
||||
qdel(src)
|
||||
return new_wound
|
||||
|
||||
/// The immediate negative effects faced as a result of the wound
|
||||
/datum/wound/proc/wound_injury(datum/wound/old_wound = null)
|
||||
return
|
||||
|
||||
/// Additional beneficial effects when the wound is gained, in case you want to give a temporary boost to allow the victim to try an escape or last stand
|
||||
/datum/wound/proc/second_wind()
|
||||
|
||||
switch(severity)
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_MODERATE)
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_SEVERE)
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_CRITICAL)
|
||||
|
||||
/**
|
||||
* try_treating() is an intercept run from [/mob/living/carbon/attackby()] right after surgeries but before anything else. Return TRUE here if the item is something that is relevant to treatment to take over the interaction.
|
||||
*
|
||||
* This proc leads into [/datum/wound/proc/treat()] and probably shouldn't be added onto in children types. You can specify what items or tools you want to be intercepted
|
||||
* with var/list/treatable_by and var/treatable_tool, then if an item fulfills one of those requirements and our wound claims it first, it goes over to treat() and treat_self().
|
||||
*
|
||||
* Arguments:
|
||||
* * I: The item we're trying to use
|
||||
* * user: The mob trying to use it on us
|
||||
*/
|
||||
/datum/wound/proc/try_treating(obj/item/I, mob/user)
|
||||
// first we weed out if we're not dealing with our wound's bodypart, or if it might be an attack
|
||||
if(!I || limb.body_zone != user.zone_selected || (I.force && user.a_intent != INTENT_HELP))
|
||||
return FALSE
|
||||
|
||||
var/allowed = FALSE
|
||||
|
||||
// check if we have a valid treatable tool (or, if cauteries are allowed, if we have something hot)
|
||||
if((I.tool_behaviour == treatable_tool) || (treatable_tool == TOOL_CAUTERY && I.get_temperature()))
|
||||
allowed = TRUE
|
||||
// failing that, see if we're aggro grabbing them and if we have an item that works for aggro grabs only
|
||||
else if(user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE && check_grab_treatments(I, user))
|
||||
allowed = TRUE
|
||||
// failing THAT, we check if we have a generally allowed item
|
||||
else
|
||||
for(var/allowed_type in treatable_by)
|
||||
if(istype(I, allowed_type))
|
||||
allowed = TRUE
|
||||
break
|
||||
|
||||
// if none of those apply, we return false to avoid interrupting
|
||||
if(!allowed)
|
||||
return FALSE
|
||||
|
||||
// now that we've determined we have a valid attempt at treating, we can stomp on their dreams if we're already interacting with the patient
|
||||
if(INTERACTING_WITH(user, victim))
|
||||
to_chat(user, "<span class='warning'>You're already interacting with [victim]!</span>")
|
||||
return TRUE
|
||||
|
||||
// lastly, treat them
|
||||
treat(I, user)
|
||||
return TRUE
|
||||
|
||||
/// Return TRUE if we have an item that can only be used while aggro grabbed (unhanded aggro grab treatments go in [/datum/wound/proc/try_handling()]). Treatment is still is handled in [/datum/wound/proc/treat()]
|
||||
/datum/wound/proc/check_grab_treatments(obj/item/I, mob/user)
|
||||
return FALSE
|
||||
|
||||
/// Like try_treating() but for unhanded interactions from humans, used by joint dislocations for manual bodypart chiropractice for example.
|
||||
/datum/wound/proc/try_handling(mob/living/carbon/human/user)
|
||||
return FALSE
|
||||
|
||||
/// Someone is using something that might be used for treating the wound on this limb
|
||||
/datum/wound/proc/treat(obj/item/I, mob/user)
|
||||
return
|
||||
|
||||
/// If var/processing is TRUE, this is run on each life tick
|
||||
/datum/wound/proc/handle_process()
|
||||
return
|
||||
|
||||
/// For use in do_after callback checks
|
||||
/datum/wound/proc/still_exists()
|
||||
return (!QDELETED(src) && limb)
|
||||
|
||||
/// When our parent bodypart is hurt
|
||||
/datum/wound/proc/receive_damage(wounding_type, wounding_dmg, wound_bonus)
|
||||
return
|
||||
|
||||
/// Called from cryoxadone and pyroxadone when they're proc'ing. Wounds will slowly be fixed separately from other methods when these are in effect. crappy name but eh
|
||||
/datum/wound/proc/on_xadone(power)
|
||||
cryo_progress += power
|
||||
if(cryo_progress > 33 * severity)
|
||||
qdel(src)
|
||||
|
||||
/// Called when we're crushed in an airlock or firedoor, for one of the improvised joint dislocation fixes
|
||||
/datum/wound/proc/crush()
|
||||
return
|
||||
|
||||
/**
|
||||
* get_examine_description() is used in carbon/examine and human/examine to show the status of this wound. Useful if you need to show some status like the wound being splinted or bandaged.
|
||||
*
|
||||
* Return the full string line you want to show, note that we're already dealing with the 'warning' span at this point, and that \n is already appended for you in the place this is called from
|
||||
*
|
||||
* Arguments:
|
||||
* * mob/user: The user examining the wound's owner, if that matters
|
||||
*/
|
||||
/datum/wound/proc/get_examine_description(mob/user)
|
||||
return "<B>[victim.p_their(TRUE)] [limb.name] [examine_desc]!</B>"
|
||||
|
||||
/datum/wound/proc/get_scanner_description(mob/user)
|
||||
return "Type: [name]\nSeverity: [severity_text()]\nDescription: [desc]\nRecommended Treatment: [treat_text]"
|
||||
|
||||
/datum/wound/proc/severity_text()
|
||||
switch(severity)
|
||||
if(WOUND_SEVERITY_TRIVIAL)
|
||||
return "Trivial"
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
return "Moderate"
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
return "Severe"
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
return "Critical"
|
||||
@@ -0,0 +1,453 @@
|
||||
|
||||
/*
|
||||
Bones
|
||||
*/
|
||||
// TODO: well, a lot really, but i'd kill to get overlays and a bonebreaking effect like Blitz: The League, similar to electric shock skeletons
|
||||
|
||||
/*
|
||||
Base definition
|
||||
*/
|
||||
/datum/wound/brute/bone
|
||||
sound_effect = 'sound/effects/crack1.ogg'
|
||||
wound_type = WOUND_LIST_BONE
|
||||
|
||||
/// The item we're currently splinted with, if there is one
|
||||
var/obj/item/stack/splinted
|
||||
|
||||
/// Have we been taped?
|
||||
var/taped
|
||||
/// Have we been bone gel'd?
|
||||
var/gelled
|
||||
/// If we did the gel + surgical tape healing method for fractures, how many regen points we need
|
||||
var/regen_points_needed
|
||||
/// Our current counter for gel + surgical tape regeneration
|
||||
var/regen_points_current
|
||||
/// If we suffer severe head booboos, we can get brain traumas tied to them
|
||||
var/datum/brain_trauma/active_trauma
|
||||
/// What brain trauma group, if any, we can draw from for head wounds
|
||||
var/brain_trauma_group
|
||||
/// If we deal brain traumas, when is the next one due?
|
||||
var/next_trauma_cycle
|
||||
/// How long do we wait +/- 20% for the next trauma?
|
||||
var/trauma_cycle_cooldown
|
||||
/// If this is a chest wound and this is set, we have this chance to cough up blood when hit in the chest
|
||||
var/chance_internal_bleeding = 0
|
||||
|
||||
/*
|
||||
Overwriting of base procs
|
||||
*/
|
||||
/datum/wound/brute/bone/wound_injury(datum/wound/old_wound = null)
|
||||
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group)
|
||||
processes = TRUE
|
||||
active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND)
|
||||
next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown)
|
||||
|
||||
RegisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, .proc/attack_with_hurt_hand)
|
||||
if(limb.held_index && victim.get_item_for_held_index(limb.held_index) && (disabling || prob(30 * severity)))
|
||||
var/obj/item/I = victim.get_item_for_held_index(limb.held_index)
|
||||
if(istype(I, /obj/item/offhand))
|
||||
I = victim.get_inactive_held_item()
|
||||
|
||||
if(I && victim.dropItemToGround(I))
|
||||
victim.visible_message("<span class='danger'>[victim] drops [I] in shock!</span>", "<span class='warning'><b>The force on your [limb.name] causes you to drop [I]!</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
|
||||
update_inefficiencies()
|
||||
|
||||
/datum/wound/brute/bone/remove_wound(ignore_limb, replaced)
|
||||
limp_slowdown = 0
|
||||
QDEL_NULL(active_trauma)
|
||||
if(victim)
|
||||
UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK)
|
||||
return ..()
|
||||
|
||||
/datum/wound/brute/bone/handle_process()
|
||||
. = ..()
|
||||
if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle)
|
||||
if(active_trauma)
|
||||
QDEL_NULL(active_trauma)
|
||||
else
|
||||
active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND)
|
||||
next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown)
|
||||
|
||||
if(!regen_points_needed)
|
||||
return
|
||||
|
||||
regen_points_current++
|
||||
if(prob(severity * 2))
|
||||
victim.take_bodypart_damage(rand(2, severity * 2), stamina=rand(2, severity * 2.5), wound_bonus=CANT_WOUND)
|
||||
if(prob(33))
|
||||
to_chat(victim, "<span class='danger'>You feel a sharp pain in your body as your bones are reforming!</span>")
|
||||
|
||||
if(regen_points_current > regen_points_needed)
|
||||
if(!victim || !limb)
|
||||
qdel(src)
|
||||
return
|
||||
to_chat(victim, "<span class='green'>Your [limb.name] has recovered from your fracture!</span>")
|
||||
remove_wound()
|
||||
|
||||
/// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so
|
||||
/datum/wound/brute/bone/proc/attack_with_hurt_hand(mob/M, atom/target, proximity)
|
||||
if(victim.get_active_hand() != limb || victim.a_intent == INTENT_HELP || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE)
|
||||
return
|
||||
|
||||
// With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit
|
||||
if(prob((severity - 1) * 15))
|
||||
// And you have a 70% or 50% chance to actually land the blow, respectively
|
||||
if(prob(70 - 20 * (severity - 1)))
|
||||
to_chat(victim, "<span class='userdanger'>The fracture in your [limb.name] shoots with pain as you strike [target]!</span>")
|
||||
limb.receive_damage(brute=rand(1,5))
|
||||
else
|
||||
victim.visible_message("<span class='danger'>[victim] weakly strikes [target] with [victim.p_their()] broken [limb.name], recoiling from pain!</span>", \
|
||||
"<span class='userdanger'>You fail to strike [target] as the fracture in your [limb.name] lights up in unbearable pain!</span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
victim.emote("scream")
|
||||
victim.Stun(0.5 SECONDS)
|
||||
limb.receive_damage(brute=rand(3,7))
|
||||
return COMPONENT_NO_ATTACK_HAND
|
||||
|
||||
/datum/wound/brute/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus)
|
||||
if(!victim)
|
||||
return
|
||||
|
||||
if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(chance_internal_bleeding + wounding_dmg))
|
||||
var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound
|
||||
switch(blood_bled)
|
||||
if(1 to 6)
|
||||
victim.bleed(blood_bled, TRUE)
|
||||
if(7 to 13)
|
||||
victim.visible_message("<span class='danger'>[victim] coughs up a bit of blood from the blow to [victim.p_their()] chest.</span>", "<span class='danger'>You cough up a bit of blood from the blow to your chest.</span>")
|
||||
victim.bleed(blood_bled, TRUE)
|
||||
if(14 to 19)
|
||||
victim.visible_message("<span class='danger'>[victim] spits out a string of blood from the blow to [victim.p_their()] chest!</span>", "<span class='danger'>You spit out a string of blood from the blow to your chest!</span>")
|
||||
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
|
||||
victim.bleed(blood_bled)
|
||||
if(20 to INFINITY)
|
||||
victim.visible_message("<span class='danger'>[victim] chokes up a spray of blood from the blow to [victim.p_their()] chest!</span>", "<span class='danger'><b>You choke up on a spray of blood from the blow to your chest!</b></span>")
|
||||
victim.bleed(blood_bled)
|
||||
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
|
||||
victim.add_splatter_floor(get_step(victim.loc, victim.dir))
|
||||
|
||||
if(!(wounding_type in list(WOUND_SHARP, WOUND_BURN)) || !splinted || wound_bonus == CANT_WOUND)
|
||||
return
|
||||
|
||||
splinted.take_damage(wounding_dmg, damage_type = (wounding_type == WOUND_SHARP ? BRUTE : BURN), sound_effect = FALSE)
|
||||
if(QDELETED(splinted))
|
||||
var/destroyed_verb = (wounding_type == WOUND_SHARP ? "torn" : "burned")
|
||||
victim.visible_message("<span class='danger'>The splint securing [victim]'s [limb.name] is [destroyed_verb] away!</span>", "<span class='danger'><b>The splint securing your [limb.name] is [destroyed_verb] away!</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
splinted = null
|
||||
treat_priority = TRUE
|
||||
update_inefficiencies()
|
||||
|
||||
|
||||
/datum/wound/brute/bone/get_examine_description(mob/user)
|
||||
if(!splinted && !gelled && !taped)
|
||||
return ..()
|
||||
|
||||
var/msg = ""
|
||||
if(!splinted)
|
||||
msg = "<B>[victim.p_their(TRUE)] [limb.name] [examine_desc]"
|
||||
else
|
||||
var/splint_condition = ""
|
||||
// how much life we have left in these bandages
|
||||
switch(splinted.obj_integrity / splinted.max_integrity * 100)
|
||||
if(0 to 25)
|
||||
splint_condition = "just barely "
|
||||
if(25 to 50)
|
||||
splint_condition = "loosely "
|
||||
if(50 to 75)
|
||||
splint_condition = "mostly "
|
||||
if(75 to INFINITY)
|
||||
splint_condition = "tightly "
|
||||
|
||||
msg = "<B>[victim.p_their(TRUE)] [limb.name] is [splint_condition] fastened in a splint of [splinted.name]</B>"
|
||||
|
||||
if(taped)
|
||||
msg += ", <span class='notice'>and appears to be reforming itself under some surgical tape!</span>"
|
||||
else if(gelled)
|
||||
msg += ", <span class='notice'>with fizzing flecks of blue bone gel sparking off the bone!</span>"
|
||||
else
|
||||
msg += "!"
|
||||
return "[msg]</B>"
|
||||
|
||||
/*
|
||||
New common procs for /datum/wound/brute/bone/
|
||||
*/
|
||||
|
||||
/datum/wound/brute/bone/proc/update_inefficiencies()
|
||||
if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(splinted)
|
||||
limp_slowdown = initial(limp_slowdown) * splinted.splint_factor
|
||||
else
|
||||
limp_slowdown = initial(limp_slowdown)
|
||||
victim.apply_status_effect(STATUS_EFFECT_LIMP)
|
||||
else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
|
||||
if(splinted)
|
||||
interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * splinted.splint_factor)
|
||||
else
|
||||
interaction_efficiency_penalty = interaction_efficiency_penalty
|
||||
|
||||
if(initial(disabling) && splinted)
|
||||
disabling = FALSE
|
||||
else if(initial(disabling))
|
||||
disabling = TRUE
|
||||
|
||||
limb.update_wounds()
|
||||
|
||||
/*
|
||||
BEWARE OF REDUNDANCY AHEAD THAT I MUST PARE DOWN
|
||||
*/
|
||||
|
||||
/datum/wound/brute/bone/proc/splint(obj/item/stack/I, mob/user)
|
||||
if(splinted && splinted.splint_factor >= I.splint_factor)
|
||||
to_chat(user, "<span class='warning'>The splint already on [user == victim ? "your" : "[victim]'s"] [limb.name] is better than you can do with [I].</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='danger'>[user] begins splinting [victim]'s [limb.name] with [I].</span>", "<span class='warning'>You begin splinting [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
|
||||
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
user.visible_message("<span class='green'>[user] finishes splinting [victim]'s [limb.name]!</span>", "<span class='green'>You finish splinting [user == victim ? "your" : "[victim]'s"] [limb.name]!</span>")
|
||||
treat_priority = FALSE
|
||||
splinted = new I.type(limb)
|
||||
splinted.amount = 1
|
||||
I.use(1)
|
||||
update_inefficiencies()
|
||||
|
||||
/*
|
||||
Moderate (Joint Dislocation)
|
||||
*/
|
||||
|
||||
/datum/wound/brute/bone/moderate
|
||||
name = "Joint Dislocation"
|
||||
desc = "Patient's bone has been unset from socket, causing pain and reduced motor function."
|
||||
treat_text = "Recommended application of bonesetter to affected limb, though manual relocation by applying an aggressive grab to the patient and helpfully interacting with afflicted limb may suffice."
|
||||
examine_desc = "is awkwardly jammed out of place"
|
||||
occur_text = "jerks violently and becomes unseated"
|
||||
severity = WOUND_SEVERITY_MODERATE
|
||||
viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
interaction_efficiency_penalty = 1.5
|
||||
limp_slowdown = 3
|
||||
threshold_minimum = 35
|
||||
threshold_penalty = 15
|
||||
treatable_tool = TOOL_BONESET
|
||||
status_effect_type = /datum/status_effect/wound/bone/moderate
|
||||
scarring_descriptions = list("light discoloring", "a slight blue tint")
|
||||
|
||||
/datum/wound/brute/bone/moderate/crush()
|
||||
if(prob(33))
|
||||
victim.visible_message("<span class='danger'>[victim]'s dislocated [limb.name] pops back into place!</span>", "<span class='userdanger'>Your dislocated [limb.name] pops back into place! Ow!</span>")
|
||||
remove_wound()
|
||||
|
||||
/datum/wound/brute/bone/moderate/try_handling(mob/living/carbon/human/user)
|
||||
if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB)
|
||||
return FALSE
|
||||
|
||||
if(user.grab_state == GRAB_PASSIVE)
|
||||
to_chat(user, "<span class='warning'>You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!</span>")
|
||||
return TRUE
|
||||
|
||||
if(user.grab_state >= GRAB_AGGRESSIVE)
|
||||
user.visible_message("<span class='danger'>[user] begins twisting and straining [victim]'s dislocated [limb.name]!</span>", "<span class='notice'>You begin twisting and straining [victim]'s dislocated [limb.name]...</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[user] begins twisting and straining your dislocated [limb.name]!</span>")
|
||||
if(user.a_intent == INTENT_HELP)
|
||||
chiropractice(user)
|
||||
else
|
||||
malpractice(user)
|
||||
return TRUE
|
||||
|
||||
/// If someone is snapping our dislocated joint back into place by hand with an aggro grab and help intent
|
||||
/datum/wound/brute/bone/moderate/proc/chiropractice(mob/living/carbon/human/user)
|
||||
var/time = base_treat_time
|
||||
|
||||
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
if(prob(65))
|
||||
user.visible_message("<span class='danger'>[user] snaps [victim]'s dislocated [limb.name] back into place!</span>", "<span class='notice'>You snap [victim]'s dislocated [limb.name] back into place!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[user] snaps your dislocated [limb.name] back into place!</span>")
|
||||
victim.emote("scream")
|
||||
limb.receive_damage(brute=20, wound_bonus=CANT_WOUND)
|
||||
qdel(src)
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user] wrenches [victim]'s dislocated [limb.name] around painfully!</span>", "<span class='danger'>You wrench [victim]'s dislocated [limb.name] around painfully!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[user] wrenches your dislocated [limb.name] around painfully!</span>")
|
||||
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
|
||||
chiropractice(user)
|
||||
|
||||
/// If someone is snapping our dislocated joint into a fracture by hand with an aggro grab and harm or disarm intent
|
||||
/datum/wound/brute/bone/moderate/proc/malpractice(mob/living/carbon/human/user)
|
||||
var/time = base_treat_time
|
||||
|
||||
if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
if(prob(65))
|
||||
user.visible_message("<span class='danger'>[user] snaps [victim]'s dislocated [limb.name] with a sickening crack!</span>", "<span class='danger'>You snap [victim]'s dislocated [limb.name] with a sickening crack!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[user] snaps your dislocated [limb.name] with a sickening crack!</span>")
|
||||
victim.emote("scream")
|
||||
limb.receive_damage(brute=25, wound_bonus=30)
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user] wrenches [victim]'s dislocated [limb.name] around painfully!</span>", "<span class='danger'>You wrench [victim]'s dislocated [limb.name] around painfully!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[user] wrenches your dislocated [limb.name] around painfully!</span>")
|
||||
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
|
||||
malpractice(user)
|
||||
|
||||
|
||||
/datum/wound/brute/bone/moderate/treat(obj/item/I, mob/user)
|
||||
if(victim == user)
|
||||
victim.visible_message("<span class='danger'>[user] begins resetting [victim.p_their()] [limb.name] with [I].</span>", "<span class='warning'>You begin resetting your [limb.name] with [I]...</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user] begins resetting [victim]'s [limb.name] with [I].</span>", "<span class='notice'>You begin resetting [victim]'s [limb.name] with [I]...</span>")
|
||||
|
||||
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
if(victim == user)
|
||||
limb.receive_damage(brute=15, wound_bonus=CANT_WOUND)
|
||||
victim.visible_message("<span class='danger'>[user] finishes resetting [victim.p_their()] [limb.name]!</span>", "<span class='userdanger'>You reset your [limb.name]!</span>")
|
||||
else
|
||||
limb.receive_damage(brute=10, wound_bonus=CANT_WOUND)
|
||||
user.visible_message("<span class='danger'>[user] finishes resetting [victim]'s [limb.name]!</span>", "<span class='nicegreen'>You finish resetting [victim]'s [limb.name]!</span>", victim)
|
||||
to_chat(victim, "<span class='userdanger'>[user] resets your [limb.name]!</span>")
|
||||
|
||||
victim.emote("scream")
|
||||
qdel(src)
|
||||
|
||||
/*
|
||||
Severe (Hairline Fracture)
|
||||
*/
|
||||
|
||||
/datum/wound/brute/bone/severe
|
||||
name = "Hairline Fracture"
|
||||
desc = "Patient's bone has suffered a crack in the foundation, causing serious pain and reduced limb functionality."
|
||||
treat_text = "Recommended light surgical application of bone gel, though splinting will prevent worsening situation."
|
||||
examine_desc = "appears bruised and grotesquely swollen"
|
||||
|
||||
occur_text = "sprays chips of bone and develops a nasty looking bruise"
|
||||
severity = WOUND_SEVERITY_SEVERE
|
||||
interaction_efficiency_penalty = 2
|
||||
limp_slowdown = 6
|
||||
threshold_minimum = 60
|
||||
threshold_penalty = 30
|
||||
treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/gauze, /obj/item/stack/medical/bone_gel)
|
||||
status_effect_type = /datum/status_effect/wound/bone/severe
|
||||
treat_priority = TRUE
|
||||
scarring_descriptions = list("a faded, fist-sized bruise", "a vaguely triangular peel scar")
|
||||
brain_trauma_group = BRAIN_TRAUMA_MILD
|
||||
trauma_cycle_cooldown = 1.5 MINUTES
|
||||
chance_internal_bleeding = 40
|
||||
|
||||
/datum/wound/brute/bone/critical
|
||||
name = "Compound Fracture"
|
||||
desc = "Patient's bones have suffered multiple gruesome fractures, causing significant pain and near uselessness of limb."
|
||||
treat_text = "Immediate binding of affected limb, followed by surgical intervention ASAP."
|
||||
examine_desc = "has a cracked bone sticking out of it"
|
||||
occur_text = "cracks apart, exposing broken bones to open air"
|
||||
severity = WOUND_SEVERITY_CRITICAL
|
||||
interaction_efficiency_penalty = 4
|
||||
limp_slowdown = 9
|
||||
sound_effect = 'sound/effects/crack2.ogg'
|
||||
threshold_minimum = 115
|
||||
threshold_penalty = 50
|
||||
disabling = TRUE
|
||||
treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/gauze, /obj/item/stack/medical/bone_gel)
|
||||
status_effect_type = /datum/status_effect/wound/bone/critical
|
||||
treat_priority = TRUE
|
||||
scarring_descriptions = list("a section of janky skin lines and badly healed scars", "a large patch of uneven skin tone", "a cluster of calluses")
|
||||
brain_trauma_group = BRAIN_TRAUMA_SEVERE
|
||||
trauma_cycle_cooldown = 2.5 MINUTES
|
||||
chance_internal_bleeding = 60
|
||||
|
||||
// doesn't make much sense for "a" bone to stick out of your head
|
||||
/datum/wound/brute/bone/critical/apply_wound(obj/item/bodypart/L, silent, datum/wound/old_wound, smited)
|
||||
if(L.body_zone == BODY_ZONE_HEAD)
|
||||
occur_text = "splits open, exposing a bare, cracked skull through the flesh and blood"
|
||||
examine_desc = "has an unsettling indent, with bits of skull poking out"
|
||||
. = ..()
|
||||
|
||||
/// if someone is using bone gel on our wound
|
||||
/datum/wound/brute/bone/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user)
|
||||
if(gelled)
|
||||
to_chat(user, "<span class='warning'>[user == victim ? "Your" : "[victim]'s"] [limb.name] is already coated with bone gel!</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='danger'>[user] begins hastily applying [I] to [victim]'s' [limb.name]...</span>", "<span class='warning'>You begin hastily applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name], disregarding the warning label...</span>")
|
||||
|
||||
if(!do_after(user, base_treat_time * 1.5 * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
I.use(1)
|
||||
victim.emote("scream")
|
||||
if(user != victim)
|
||||
user.visible_message("<span class='notice'>[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!</span>", "<span class='notice'>You finish applying [I] to [victim]'s [limb.name]!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[user] finishes applying [I] to your [limb.name], and you can feel the bones exploding with pain as they begin melting and reforming!</span>")
|
||||
else
|
||||
var/painkiller_bonus = 0
|
||||
if(victim.drunkenness)
|
||||
painkiller_bonus += 5
|
||||
if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/medicine/morphine))
|
||||
painkiller_bonus += 10
|
||||
if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/determination))
|
||||
painkiller_bonus += 5
|
||||
|
||||
if(prob(25 + (20 * (severity - 2)) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers
|
||||
victim.visible_message("<span class='danger'>[victim] fails to finish applying [I] to [victim.p_their()] [limb.name], passing out from the pain!</span>", "<span class='notice'>You black out from the pain of applying [I] to your [limb.name] before you can finish!</span>")
|
||||
victim.AdjustUnconscious(5 SECONDS)
|
||||
return
|
||||
victim.visible_message("<span class='notice'>[victim] finishes applying [I] to [victim.p_their()] [limb.name], grimacing from the pain!</span>", "<span class='notice'>You finish applying [I] to your [limb.name], and your bones explode in pain!</span>")
|
||||
|
||||
limb.receive_damage(30, stamina=100, wound_bonus=CANT_WOUND)
|
||||
if(!gelled)
|
||||
gelled = TRUE
|
||||
|
||||
/// if someone is using surgical tape on our wound
|
||||
/datum/wound/brute/bone/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user)
|
||||
if(!gelled)
|
||||
to_chat(user, "<span class='warning'>[user == victim ? "Your" : "[victim]'s"] [limb.name] must be coated with bone gel to perform this emergency operation!</span>")
|
||||
return
|
||||
if(taped)
|
||||
to_chat(user, "<span class='warning'>[user == victim ? "Your" : "[victim]'s"] [limb.name] is already wrapped in [I.name] and reforming!</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='danger'>[user] begins applying [I] to [victim]'s' [limb.name]...</span>", "<span class='warning'>You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]...</span>")
|
||||
|
||||
if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
regen_points_current = 0
|
||||
regen_points_needed = 30 SECONDS * (user == victim ? 1.5 : 1) * (severity - 1)
|
||||
I.use(1)
|
||||
if(user != victim)
|
||||
user.visible_message("<span class='notice'>[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!</span>", "<span class='notice'>You finish applying [I] to [victim]'s [limb.name]!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='green'>[user] finishes applying [I] to your [limb.name], you immediately begin to feel your bones start to reform!</span>")
|
||||
else
|
||||
victim.visible_message("<span class='notice'>[victim] finishes applying [I] to [victim.p_their()] [limb.name], !</span>", "<span class='green'>You finish applying [I] to your [limb.name], and you immediately begin to feel your bones start to reform!</span>")
|
||||
|
||||
taped = TRUE
|
||||
processes = TRUE
|
||||
|
||||
/datum/wound/brute/bone/treat(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/stack/medical/bone_gel))
|
||||
gel(I, user)
|
||||
else if(istype(I, /obj/item/stack/sticky_tape/surgical))
|
||||
tape(I, user)
|
||||
else if(istype(I, /obj/item/stack/medical/gauze))
|
||||
splint(I, user)
|
||||
|
||||
/datum/wound/brute/bone/get_scanner_description(mob/user)
|
||||
. = ..()
|
||||
|
||||
. += "<div class='ml-3'>"
|
||||
|
||||
if(!gelled)
|
||||
. += "Alternative Treatment: Apply bone gel directly to injured limb, then apply surgical tape to begin bone regeneration. This is both excruciatingly painful and slow, and only recommended in dire circumstances.\n"
|
||||
else if(!taped)
|
||||
. += "<span class='notice'>Continue Alternative Treatment: Apply surgical tape directly to injured limb to begin bone regeneration. Note, this is both excruciatingly painful and slow.</span>\n"
|
||||
else
|
||||
. += "<span class='notice'>Note: Bone regeneration in effect. Bone is [round((regen_points_current*100)/regen_points_needed,0.1)]% regenerated.</span>\n"
|
||||
|
||||
if(limb.body_zone == BODY_ZONE_HEAD)
|
||||
. += "Cranial Trauma Detected: Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired."
|
||||
else if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume)
|
||||
. += "Ribcage Trauma Detected: Further trauma to chest is likely to worsen internal bleeding until bone is repaired."
|
||||
. += "</div>"
|
||||
@@ -0,0 +1,323 @@
|
||||
|
||||
|
||||
|
||||
// TODO: well, a lot really, but specifically I want to add potential fusing of clothing/equipment on the affected area, and limb infections, though those may go in body part code
|
||||
/datum/wound/burn
|
||||
a_or_from = "from"
|
||||
wound_type = WOUND_LIST_BURN
|
||||
processes = TRUE
|
||||
sound_effect = 'sound/effects/sizzle1.ogg'
|
||||
|
||||
treatable_by = list(/obj/item/stack/medical/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon
|
||||
|
||||
// Flesh damage vars
|
||||
/// How much damage to our flesh we currently have. Once both this and infestation reach 0, the wound is considered healed
|
||||
var/flesh_damage = 5
|
||||
/// Our current counter for how much flesh regeneration we have stacked from regenerative mesh/synthflesh/whatever, decrements each tick and lowers flesh_damage
|
||||
var/flesh_healing = 0
|
||||
|
||||
// Infestation vars (only for severe and critical)
|
||||
/// How quickly infection breeds on this burn if we don't have disinfectant
|
||||
var/infestation_rate = 0
|
||||
/// Our current level of infection
|
||||
var/infestation = 0
|
||||
/// Our current level of sanitization/anti-infection, from disinfectants/alcohol/UV lights. While positive, totally pauses and slowly reverses infestation effects each tick
|
||||
var/sanitization = 0
|
||||
|
||||
/// Once we reach infestation beyond WOUND_INFESTATION_SEPSIS, we get this many warnings before the limb is completely paralyzed (you'd have to ignore a really bad burn for a really long time for this to happen)
|
||||
var/strikes_to_lose_limb = 3
|
||||
|
||||
/// The current bandage we have for this wound (maybe move bandages to the limb?)
|
||||
var/obj/item/stack/current_bandage
|
||||
|
||||
/datum/wound/burn/handle_process()
|
||||
. = ..()
|
||||
if(strikes_to_lose_limb == 0)
|
||||
victim.adjustToxLoss(0.5)
|
||||
if(prob(1))
|
||||
victim.visible_message("<span class='danger'>The infection on the remnants of [victim]'s [limb.name] shift and bubble nauseatingly!</span>", "<span class='warning'>You can feel the infection on the remnants of your [limb.name] coursing through your veins!</span>")
|
||||
return
|
||||
|
||||
if(victim.reagents)
|
||||
if(victim.reagents.has_reagent(/datum/reagent/medicine/spaceacillin))
|
||||
sanitization += 0.9
|
||||
if(victim.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine/))
|
||||
sanitization += 0.9
|
||||
if(victim.reagents.has_reagent(/datum/reagent/medicine/mine_salve))
|
||||
sanitization += 0.3
|
||||
flesh_healing += 0.5
|
||||
|
||||
if(current_bandage)
|
||||
current_bandage.absorption_capacity -= WOUND_BURN_SANITIZATION_RATE
|
||||
if(current_bandage.absorption_capacity <= 0)
|
||||
victim.visible_message("<span class='danger'>Pus soaks through \the [current_bandage] on [victim]'s [limb.name].</span>", "<span class='warning'>Pus soaks through \the [current_bandage] on your [limb.name].</span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
QDEL_NULL(current_bandage)
|
||||
treat_priority = TRUE
|
||||
|
||||
if(flesh_healing > 0)
|
||||
var/bandage_factor = (current_bandage ? current_bandage.splint_factor : 1)
|
||||
flesh_damage = max(0, flesh_damage - 1)
|
||||
flesh_healing = max(0, flesh_healing - bandage_factor) // good bandages multiply the length of flesh healing
|
||||
|
||||
// here's the check to see if we're cleared up
|
||||
if((flesh_damage <= 0) && (infestation <= 1))
|
||||
to_chat(victim, "<span class='green'>The burns on your [limb.name] have cleared up!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// sanitization is checked after the clearing check but before the rest, because we freeze the effects of infection while we have sanitization
|
||||
if(sanitization > 0)
|
||||
var/bandage_factor = (current_bandage ? current_bandage.splint_factor : 1)
|
||||
infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE)
|
||||
sanitization = max(0, sanitization - (WOUND_BURN_SANITIZATION_RATE * bandage_factor))
|
||||
return
|
||||
|
||||
infestation += infestation_rate
|
||||
|
||||
switch(infestation)
|
||||
if(0 to WOUND_INFECTION_MODERATE)
|
||||
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
|
||||
if(prob(30))
|
||||
victim.adjustToxLoss(0.2)
|
||||
if(prob(6))
|
||||
to_chat(victim, "<span class='warning'>The blisters on your [limb.name] ooze a strange pus...</span>")
|
||||
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
|
||||
if(!disabling && prob(2))
|
||||
to_chat(victim, "<span class='warning'><b>Your [limb.name] completely locks up, as you struggle for control against the infection!</b></span>")
|
||||
disabling = TRUE
|
||||
else if(disabling && prob(8))
|
||||
to_chat(victim, "<span class='notice'>You regain sensation in your [limb.name], but it's still in terrible shape!</span>")
|
||||
disabling = FALSE
|
||||
else if(prob(20))
|
||||
victim.adjustToxLoss(0.5)
|
||||
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
|
||||
if(!disabling && prob(3))
|
||||
to_chat(victim, "<span class='warning'><b>You suddenly lose all sensation of the festering infection in your [limb.name]!</b></span>")
|
||||
disabling = TRUE
|
||||
else if(disabling && prob(3))
|
||||
to_chat(victim, "<span class='notice'>You can barely feel your [limb.name] again, and you have to strain to retain motor control!</span>")
|
||||
disabling = FALSE
|
||||
else if(prob(1))
|
||||
to_chat(victim, "<span class='warning'>You contemplate life without your [limb.name]...</span>")
|
||||
victim.adjustToxLoss(0.75)
|
||||
else if(prob(4))
|
||||
victim.adjustToxLoss(1)
|
||||
if(WOUND_INFECTION_SEPTIC to INFINITY)
|
||||
if(prob(infestation))
|
||||
switch(strikes_to_lose_limb)
|
||||
if(3 to INFINITY)
|
||||
to_chat(victim, "<span class='deadsay'>The skin on your [limb.name] is literally dripping off, you feel awful!</span>")
|
||||
if(2)
|
||||
to_chat(victim, "<span class='deadsay'><b>The infection in your [limb.name] is literally dripping off, you feel horrible!</b></span>")
|
||||
if(1)
|
||||
to_chat(victim, "<span class='deadsay'><b>Infection has just about completely claimed your [limb.name]!</b></span>")
|
||||
if(0)
|
||||
to_chat(victim, "<span class='deadsay'><b>The last of the nerve endings in your [limb.name] wither away, as the infection completely paralyzes your joint connector.</b></span>")
|
||||
threshold_penalty = 120 // piss easy to destroy
|
||||
var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone)
|
||||
victim.gain_trauma(sepsis)
|
||||
strikes_to_lose_limb--
|
||||
|
||||
/datum/wound/burn/get_examine_description(mob/user)
|
||||
if(strikes_to_lose_limb <= 0)
|
||||
return "<span class='deadsay'><B>[victim.p_their(TRUE)] [limb.name] is completely dead and unrecognizable as organic.</B></span>"
|
||||
|
||||
var/condition = ""
|
||||
if(current_bandage)
|
||||
var/bandage_condition
|
||||
switch(current_bandage.absorption_capacity)
|
||||
if(0 to 1.25)
|
||||
bandage_condition = "nearly ruined "
|
||||
if(1.25 to 2.75)
|
||||
bandage_condition = "badly worn "
|
||||
if(2.75 to 4)
|
||||
bandage_condition = "slightly pus-stained "
|
||||
if(4 to INFINITY)
|
||||
bandage_condition = "clean "
|
||||
|
||||
condition += " underneath a dressing of [bandage_condition] [current_bandage.name]"
|
||||
else
|
||||
switch(infestation)
|
||||
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
|
||||
condition += ", <span class='deadsay'>with small spots of discoloration along the nearby veins!</span>"
|
||||
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
|
||||
condition += ", <span class='deadsay'>with dark clouds spreading outwards under the skin!</span>"
|
||||
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
|
||||
condition += ", <span class='deadsay'>with streaks of rotten infection pulsating outward!</span>"
|
||||
if(WOUND_INFECTION_SEPTIC to INFINITY)
|
||||
return "<span class='deadsay'><B>[victim.p_their(TRUE)] [limb.name] is a mess of char and rot, skin literally dripping off the bone with infection!</B></span>"
|
||||
else
|
||||
condition += "!"
|
||||
|
||||
return "<B>[victim.p_their(TRUE)] [limb.name] [examine_desc][condition]</B>"
|
||||
|
||||
/datum/wound/burn/get_scanner_description(mob/user)
|
||||
if(strikes_to_lose_limb == 0)
|
||||
var/oopsie = "Type: [name]\nSeverity: [severity_text()]"
|
||||
oopsie += "<div class='ml-3'>Infection Level: <span class='deadsay'>The infection is total. The bodypart is lost. Amputate or augment limb immediately.</span></div>"
|
||||
return oopsie
|
||||
|
||||
. = ..()
|
||||
. += "<div class='ml-3'>"
|
||||
|
||||
if(infestation <= sanitization && flesh_damage <= flesh_healing)
|
||||
. += "No further treatment required: Burns will heal shortly."
|
||||
else
|
||||
switch(infestation)
|
||||
if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE)
|
||||
. += "Infection Level: Moderate\n"
|
||||
if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL)
|
||||
. += "Infection Level: Severe\n"
|
||||
if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC)
|
||||
. += "Infection Level: <span class='deadsay'>CRITICAL</span>\n"
|
||||
if(WOUND_INFECTION_SEPTIC to INFINITY)
|
||||
. += "Infection Level: <span class='deadsay'>LOSS IMMINENT</span>\n"
|
||||
if(infestation > sanitization)
|
||||
. += "\tSurgical debridement, antiobiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n"
|
||||
|
||||
if(flesh_damage > 0)
|
||||
. += "Flesh damage detected: Please apply ointment or regenerative mesh to allow recovery.\n"
|
||||
. += "</div>"
|
||||
|
||||
/*
|
||||
new burn common procs
|
||||
*/
|
||||
|
||||
/// if someone is using ointment on our burns
|
||||
/datum/wound/burn/proc/ointment(obj/item/stack/medical/ointment/I, mob/user)
|
||||
user.visible_message("<span class='notice'>[user] begins applying [I] to [victim]'s [limb.name]...</span>", "<span class='notice'>You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]...</span>")
|
||||
if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target = victim))
|
||||
return
|
||||
|
||||
limb.heal_damage(I.heal_brute, I.heal_burn)
|
||||
user.visible_message("<span class='green'>[user] applies [I] to [victim].</span>", "<span class='green'>You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].</span>")
|
||||
I.use(1)
|
||||
sanitization += I.sanitization
|
||||
flesh_healing += I.flesh_regeneration
|
||||
|
||||
if((infestation <= 0 || sanitization >= infestation) && (flesh_damage <= 0 || flesh_healing > flesh_damage))
|
||||
to_chat(user, "<span class='notice'>You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.name] to recover.</span>")
|
||||
else
|
||||
try_treating(I, user)
|
||||
|
||||
/// for use in the burn dressing surgery since we don't want to make them do another do_after obviously
|
||||
/datum/wound/burn/proc/force_bandage(obj/item/stack/medical/gauze/I, mob/user)
|
||||
QDEL_NULL(current_bandage)
|
||||
current_bandage = new I.type(limb)
|
||||
current_bandage.amount = 1
|
||||
treat_priority = FALSE
|
||||
sanitization += I.sanitization
|
||||
I.use(1)
|
||||
|
||||
/// if someone is wrapping gauze on our burns
|
||||
/datum/wound/burn/proc/bandage(obj/item/stack/medical/gauze/I, mob/user)
|
||||
if(current_bandage)
|
||||
if(current_bandage.absorption_capacity > I.absorption_capacity + 1)
|
||||
to_chat(user, "<span class='warning'>The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!</span>")
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] begins to redress the burns on [victim]'s [limb.name] with [I]...</span>", "<span class='warning'>You begin redressing the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
else
|
||||
user.visible_message("<span class='notice'>[user] begins to dress the burns on [victim]'s [limb.name] with [I]...</span>", "<span class='notice'>You begin dressing the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
|
||||
if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
user.visible_message("<span class='green'>[user] applies [I] to [victim].</span>", "<span class='green'>You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].</span>")
|
||||
QDEL_NULL(current_bandage)
|
||||
current_bandage = new I.type(limb)
|
||||
current_bandage.amount = 1
|
||||
treat_priority = FALSE
|
||||
sanitization += I.sanitization
|
||||
I.use(1)
|
||||
|
||||
/// if someone is using mesh on our burns
|
||||
/datum/wound/burn/proc/mesh(obj/item/stack/medical/mesh/I, mob/user)
|
||||
user.visible_message("<span class='notice'>[user] begins wrapping [victim]'s [limb.name] with [I]...</span>", "<span class='notice'>You begin wrapping [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
limb.heal_damage(I.heal_brute, I.heal_burn)
|
||||
user.visible_message("<span class='green'>[user] applies [I] to [victim].</span>", "<span class='green'>You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].</span>")
|
||||
I.use(1)
|
||||
sanitization += I.sanitization
|
||||
flesh_healing += I.flesh_regeneration
|
||||
|
||||
if(sanitization >= infestation && flesh_healing > flesh_damage)
|
||||
to_chat(user, "<span class='notice'>You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.name] to recover.</span>")
|
||||
else
|
||||
try_treating(I, user)
|
||||
|
||||
/// Paramedic UV penlights
|
||||
/datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user)
|
||||
if(I.uv_cooldown > world.time)
|
||||
to_chat(user, "<span class='notice'>[I] is still recharging!</span>")
|
||||
return
|
||||
if(infestation <= 0 || infestation < sanitization)
|
||||
to_chat(user, "<span class='notice'>There's no infection to treat on [victim]'s [limb.name]!</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='notice'>[user] flashes the burns on [victim]'s [limb] with [I].</span>", "<span class='notice'>You flash the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I].</span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
sanitization += I.uv_power
|
||||
I.uv_cooldown = world.time + I.uv_cooldown_length
|
||||
|
||||
/datum/wound/burn/treat(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/stack/medical/gauze))
|
||||
bandage(I, user)
|
||||
else if(istype(I, /obj/item/stack/medical/ointment))
|
||||
ointment(I, user)
|
||||
else if(istype(I, /obj/item/stack/medical/mesh))
|
||||
mesh(I, user)
|
||||
else if(istype(I, /obj/item/flashlight/pen/paramedic))
|
||||
uv(I, user)
|
||||
|
||||
/// basic support for instabitaluri/synthflesh healing flesh damage, more chem support in the future
|
||||
/datum/wound/burn/proc/regenerate_flesh(amount)
|
||||
flesh_healing += amount * 0.5 // 20u patch will heal 10 flesh standard
|
||||
|
||||
// we don't even care about first degree burns, straight to second
|
||||
/datum/wound/burn/moderate
|
||||
name = "Second Degree Burns"
|
||||
desc = "Patient is suffering considerable burns with mild skin penetration, weakening limb integrity and increased burning sensations."
|
||||
treat_text = "Recommended application of topical ointment or regenerative mesh to affected region."
|
||||
examine_desc = "is badly burned and breaking out in blisters"
|
||||
occur_text = "breaks out with violent red burns"
|
||||
severity = WOUND_SEVERITY_MODERATE
|
||||
damage_mulitplier_penalty = 1.1
|
||||
threshold_minimum = 40
|
||||
threshold_penalty = 30 // burns cause significant decrease in limb integrity compared to other wounds
|
||||
status_effect_type = /datum/status_effect/wound/burn/moderate
|
||||
flesh_damage = 5
|
||||
scarring_descriptions = list("small amoeba-shaped skinmarks", "a faded streak of depressed skin")
|
||||
|
||||
/datum/wound/burn/severe
|
||||
name = "Third Degree Burns"
|
||||
desc = "Patient is suffering extreme burns with full skin penetration, creating serious risk of infection and greatly reduced limb integrity."
|
||||
treat_text = "Recommended immediate disinfection and excision of any infected skin, followed by bandaging and ointment."
|
||||
examine_desc = "appears seriously charred, with aggressive red splotches"
|
||||
occur_text = "chars rapidly, exposing ruined tissue and spreading angry red burns"
|
||||
severity = WOUND_SEVERITY_SEVERE
|
||||
damage_mulitplier_penalty = 1.2
|
||||
threshold_minimum = 80
|
||||
threshold_penalty = 40
|
||||
status_effect_type = /datum/status_effect/wound/burn/severe
|
||||
treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
|
||||
infestation_rate = 0.05 // appx 13 minutes to reach sepsis without any treatment
|
||||
flesh_damage = 12.5
|
||||
scarring_descriptions = list("a large, jagged patch of faded skin", "random spots of shiny, smooth skin", "spots of taut, leathery skin")
|
||||
|
||||
/datum/wound/burn/critical
|
||||
name = "Catastrophic Burns"
|
||||
desc = "Patient is suffering near complete loss of tissue and significantly charred muscle and bone, creating life-threatening risk of infection and negligible limb integrity."
|
||||
treat_text = "Immediate surgical debriding of any infected skin, followed by potent tissue regeneration formula and bandaging."
|
||||
examine_desc = "is a ruined mess of blanched bone, melted fat, and charred tissue"
|
||||
occur_text = "vaporizes as flesh, bone, and fat melt together in a horrifying mess"
|
||||
severity = WOUND_SEVERITY_CRITICAL
|
||||
damage_mulitplier_penalty = 1.3
|
||||
sound_effect = 'sound/effects/sizzle2.ogg'
|
||||
threshold_minimum = 140
|
||||
threshold_penalty = 80
|
||||
status_effect_type = /datum/status_effect/wound/burn/critical
|
||||
treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh)
|
||||
infestation_rate = 0.15 // appx 4.33 minutes to reach sepsis without any treatment
|
||||
flesh_damage = 20
|
||||
scarring_descriptions = list("massive, disfiguring keloid scars", "several long streaks of badly discolored and malformed skin", "unmistakeable splotches of dead tissue from serious burns")
|
||||
@@ -0,0 +1,309 @@
|
||||
|
||||
/*
|
||||
Cuts
|
||||
*/
|
||||
|
||||
/datum/wound/brute/cut
|
||||
sound_effect = 'sound/weapons/slice.ogg'
|
||||
processes = TRUE
|
||||
wound_type = WOUND_LIST_CUT
|
||||
treatable_by = list(/obj/item/stack/medical/suture, /obj/item/stack/medical/gauze)
|
||||
treatable_by_grabbed = list(/obj/item/gun/energy/laser)
|
||||
treatable_tool = TOOL_CAUTERY
|
||||
treat_priority = TRUE
|
||||
base_treat_time = 3 SECONDS
|
||||
|
||||
/// How much blood we start losing when this wound is first applied
|
||||
var/initial_flow
|
||||
/// When we have less than this amount of flow, either from treatment or clotting, we demote to a lower cut or are healed of the wound
|
||||
var/minimum_flow
|
||||
/// How fast our blood flow will naturally decrease per tick, not only do larger cuts bleed more faster, they clot slower
|
||||
var/clot_rate
|
||||
|
||||
/// Once the blood flow drops below minimum_flow, we demote it to this type of wound. If there's none, we're all better
|
||||
var/demotes_to
|
||||
|
||||
/// How much staunching per type (cautery, suturing, bandaging) you can have before that type is no longer effective for this cut NOT IMPLEMENTED
|
||||
var/max_per_type
|
||||
/// The maximum flow we've had so far
|
||||
var/highest_flow
|
||||
/// How much flow we've already cauterized
|
||||
var/cauterized
|
||||
/// How much flow we've already sutured
|
||||
var/sutured
|
||||
|
||||
/// The current bandage we have for this wound (maybe move bandages to the limb?)
|
||||
var/obj/item/stack/current_bandage
|
||||
/// A bad system I'm using to track the worst scar we earned (since we can demote, we want the biggest our wound has been, not what it was when it was cured (probably moderate))
|
||||
var/datum/scar/highest_scar
|
||||
|
||||
/datum/wound/brute/cut/wound_injury(datum/wound/brute/cut/old_wound = null)
|
||||
blood_flow = initial_flow
|
||||
if(old_wound)
|
||||
blood_flow = max(old_wound.blood_flow, initial_flow)
|
||||
if(old_wound.severity > severity && old_wound.highest_scar)
|
||||
highest_scar = old_wound.highest_scar
|
||||
old_wound.highest_scar = null
|
||||
if(old_wound.current_bandage)
|
||||
current_bandage = old_wound.current_bandage
|
||||
old_wound.current_bandage = null
|
||||
|
||||
if(!highest_scar)
|
||||
highest_scar = new
|
||||
highest_scar.generate(limb, src, add_to_scars=FALSE)
|
||||
|
||||
/datum/wound/brute/cut/remove_wound(ignore_limb, replaced)
|
||||
if(!replaced && highest_scar)
|
||||
already_scarred = TRUE
|
||||
highest_scar.lazy_attach(limb)
|
||||
return ..()
|
||||
|
||||
/datum/wound/brute/cut/get_examine_description(mob/user)
|
||||
if(!current_bandage)
|
||||
return ..()
|
||||
|
||||
var/bandage_condition = ""
|
||||
// how much life we have left in these bandages
|
||||
switch(current_bandage.absorption_capacity)
|
||||
if(0 to 1.25)
|
||||
bandage_condition = "nearly ruined "
|
||||
if(1.25 to 2.75)
|
||||
bandage_condition = "badly worn "
|
||||
if(2.75 to 4)
|
||||
bandage_condition = "slightly bloodied "
|
||||
if(4 to INFINITY)
|
||||
bandage_condition = "clean "
|
||||
return "<B>The cuts on [victim.p_their()] [limb.name] are wrapped with [bandage_condition] [current_bandage.name]!</B>"
|
||||
|
||||
/datum/wound/brute/cut/receive_damage(wounding_type, wounding_dmg, wound_bonus)
|
||||
if(victim.stat != DEAD && wounding_type == WOUND_SHARP) // can't stab dead bodies to make it bleed faster this way
|
||||
blood_flow += 0.05 * wounding_dmg
|
||||
|
||||
/datum/wound/brute/cut/handle_process()
|
||||
blood_flow = min(blood_flow, WOUND_CUT_MAX_BLOODFLOW)
|
||||
|
||||
if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/toxin/heparin))
|
||||
blood_flow += 0.5 // old herapin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first
|
||||
else if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/medicine/coagulant))
|
||||
blood_flow -= 0.25
|
||||
|
||||
if(current_bandage)
|
||||
if(clot_rate > 0)
|
||||
blood_flow -= clot_rate
|
||||
blood_flow -= current_bandage.absorption_rate
|
||||
current_bandage.absorption_capacity -= current_bandage.absorption_rate
|
||||
if(current_bandage.absorption_capacity < 0)
|
||||
victim.visible_message("<span class='danger'>Blood soaks through \the [current_bandage] on [victim]'s [limb.name].</span>", "<span class='warning'>Blood soaks through \the [current_bandage] on your [limb.name].</span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
QDEL_NULL(current_bandage)
|
||||
treat_priority = TRUE
|
||||
else
|
||||
blood_flow -= clot_rate
|
||||
|
||||
if(blood_flow > highest_flow)
|
||||
highest_flow = blood_flow
|
||||
|
||||
if(blood_flow < minimum_flow)
|
||||
if(demotes_to)
|
||||
replace_wound(demotes_to)
|
||||
else
|
||||
to_chat(victim, "<span class='green'>The cut on your [limb.name] has stopped bleeding!</span>")
|
||||
qdel(src)
|
||||
|
||||
/* BEWARE, THE BELOW NONSENSE IS MADNESS. bones.dm looks more like what I have in mind and is sufficiently clean, don't pay attention to this messiness */
|
||||
|
||||
/datum/wound/brute/cut/check_grab_treatments(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/gun/energy/laser))
|
||||
return TRUE
|
||||
|
||||
/datum/wound/brute/cut/treat(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/gun/energy/laser))
|
||||
las_cauterize(I, user)
|
||||
else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature() > 300)
|
||||
tool_cauterize(I, user)
|
||||
else if(istype(I, /obj/item/stack/medical/gauze))
|
||||
bandage(I, user)
|
||||
else if(istype(I, /obj/item/stack/medical/suture))
|
||||
suture(I, user)
|
||||
|
||||
/datum/wound/brute/cut/try_handling(mob/living/carbon/human/user)
|
||||
if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB)
|
||||
return FALSE
|
||||
|
||||
if(!iscatperson(user))
|
||||
return FALSE
|
||||
|
||||
if(!(user.client?.prefs.vore_flags & LICKABLE))
|
||||
return FALSE
|
||||
|
||||
lick_wounds(user)
|
||||
return TRUE
|
||||
|
||||
/// if a felinid is licking this cut to reduce bleeding
|
||||
/datum/wound/brute/cut/proc/lick_wounds(mob/living/carbon/human/user)
|
||||
if(INTERACTING_WITH(user, victim))
|
||||
to_chat(user, "<span class='warning'>You're already interacting with [victim]!</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='notice'>[user] begins licking the wounds on [victim]'s [limb.name].</span>", "<span class='notice'>You begin licking the wounds on [victim]'s [limb.name]...</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='notice'>[user] begins to lick the wounds on your [limb.name].</span")
|
||||
if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
user.visible_message("<span class='notice'>[user] licks the wounds on [victim]'s [limb.name].</span>", "<span class='notice'>You lick some of the wounds on [victim]'s [limb.name]</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='green'>[user] licks the wounds on your [limb.name]!</span")
|
||||
blood_flow -= 0.5
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
try_handling(user)
|
||||
else if(demotes_to)
|
||||
to_chat(user, "<span class='green'>You successfully lower the severity of [victim]'s cuts.</span>")
|
||||
|
||||
/datum/wound/brute/cut/on_xadone(power)
|
||||
. = ..()
|
||||
blood_flow -= 0.03 * power // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort
|
||||
|
||||
/// If someone's putting a laser gun up to our cut to cauterize it
|
||||
/datum/wound/brute/cut/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user)
|
||||
var/self_penalty_mult = (user == victim ? 1.25 : 1)
|
||||
user.visible_message("<span class='warning'>[user] begins aiming [lasgun] directly at [victim]'s [limb.name]...</span>", "<span class='userdanger'>You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [limb.name]...</span>")
|
||||
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
var/damage = lasgun.chambered.BB.damage
|
||||
lasgun.chambered.BB.wound_bonus -= 30
|
||||
lasgun.chambered.BB.damage *= self_penalty_mult
|
||||
if(!lasgun.process_fire(victim, victim, TRUE, null, limb.body_zone))
|
||||
return
|
||||
victim.emote("scream")
|
||||
blood_flow -= damage / (5 * self_penalty_mult) // 20 / 5 = 4 bloodflow removed, p good
|
||||
cauterized += damage / (5 * self_penalty_mult)
|
||||
victim.visible_message("<span class='warning'>The cuts on [victim]'s [limb.name] scar over!</span>")
|
||||
|
||||
/// If someone is using either a cautery tool or something with heat to cauterize this cut
|
||||
/datum/wound/brute/cut/proc/tool_cauterize(obj/item/I, mob/user)
|
||||
var/self_penalty_mult = (user == victim ? 1.5 : 1)
|
||||
user.visible_message("<span class='danger'>[user] begins cauterizing [victim]'s [limb.name] with [I]...</span>", "<span class='danger'>You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
user.visible_message("<span class='green'>[user] cauterizes some of the bleeding on [victim].</span>", "<span class='green'>You cauterize some of the bleeding on [victim].</span>")
|
||||
limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND)
|
||||
if(prob(30))
|
||||
victim.emote("scream")
|
||||
var/blood_cauterized = (0.6 / self_penalty_mult)
|
||||
blood_flow -= blood_cauterized
|
||||
cauterized += blood_cauterized
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
try_treating(I, user)
|
||||
else if(demotes_to)
|
||||
to_chat(user, "<span class='green'>You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.</span>")
|
||||
|
||||
/// If someone is using a suture to close this cut
|
||||
/datum/wound/brute/cut/proc/suture(obj/item/stack/medical/suture/I, mob/user)
|
||||
var/self_penalty_mult = (user == victim ? 1.4 : 1)
|
||||
user.visible_message("<span class='notice'>[user] begins stitching [victim]'s [limb.name] with [I]...</span>", "<span class='notice'>You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
user.visible_message("<span class='green'>[user] stitches up some of the bleeding on [victim].</span>", "<span class='green'>You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].</span>")
|
||||
var/blood_sutured = I.stop_bleeding / self_penalty_mult
|
||||
blood_flow -= blood_sutured
|
||||
sutured += blood_sutured
|
||||
limb.heal_damage(I.heal_brute, I.heal_burn)
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
try_treating(I, user)
|
||||
else if(demotes_to)
|
||||
to_chat(user, "<span class='green'>You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.</span>")
|
||||
|
||||
/// If someone is using gauze on this cut
|
||||
/datum/wound/brute/cut/proc/bandage(obj/item/stack/I, mob/user)
|
||||
if(current_bandage)
|
||||
if(current_bandage.absorption_capacity > I.absorption_capacity + 1)
|
||||
to_chat(user, "<span class='warning'>The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!</span>")
|
||||
return
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins rewrapping the cuts on [victim]'s [limb.name] with [I]...</span>", "<span class='warning'>You begin rewrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins wrapping the cuts on [victim]'s [limb.name] with [I]...</span>", "<span class='warning'>You begin wrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
user.visible_message("<span class='green'>[user] applies [I] to [victim]'s [limb.name].</span>", "<span class='green'>You bandage some of the bleeding on [user == victim ? "yourself" : "[victim]"].</span>")
|
||||
QDEL_NULL(current_bandage)
|
||||
current_bandage = new I.type(limb)
|
||||
current_bandage.amount = 1
|
||||
treat_priority = FALSE
|
||||
I.use(1)
|
||||
|
||||
|
||||
/datum/wound/brute/cut/moderate
|
||||
name = "Rough Abrasion"
|
||||
desc = "Patient's skin has been badly scraped, generating moderate blood loss."
|
||||
treat_text = "Application of clean bandages or first-aid grade sutures, followed by food and rest."
|
||||
examine_desc = "has an open cut"
|
||||
occur_text = "is cut open, slowly leaking blood"
|
||||
sound_effect = 'sound/effects/blood1.ogg'
|
||||
severity = WOUND_SEVERITY_MODERATE
|
||||
initial_flow = 2
|
||||
minimum_flow = 0.5
|
||||
max_per_type = 3
|
||||
clot_rate = 0.15
|
||||
threshold_minimum = 20
|
||||
threshold_penalty = 10
|
||||
status_effect_type = /datum/status_effect/wound/cut/moderate
|
||||
scarring_descriptions = list("light, faded lines", "minor cut marks", "a small faded slit", "a series of small scars")
|
||||
|
||||
/datum/wound/brute/cut/severe
|
||||
name = "Open Laceration"
|
||||
desc = "Patient's skin is ripped clean open, allowing significant blood loss."
|
||||
treat_text = "Speedy application of first-aid grade sutures and clean bandages, followed by vitals monitoring to ensure recovery."
|
||||
examine_desc = "has a severe cut"
|
||||
occur_text = "is ripped open, veins spurting blood"
|
||||
sound_effect = 'sound/effects/blood2.ogg'
|
||||
severity = WOUND_SEVERITY_SEVERE
|
||||
initial_flow = 3.25
|
||||
minimum_flow = 2.75
|
||||
clot_rate = 0.07
|
||||
max_per_type = 4
|
||||
threshold_minimum = 50
|
||||
threshold_penalty = 25
|
||||
demotes_to = /datum/wound/brute/cut/moderate
|
||||
status_effect_type = /datum/status_effect/wound/cut/severe
|
||||
scarring_descriptions = list("a twisted line of faded gashes", "a gnarled sickle-shaped slice scar", "a long-faded puncture wound")
|
||||
|
||||
/datum/wound/brute/cut/critical
|
||||
name = "Weeping Avulsion"
|
||||
desc = "Patient's skin is completely torn open, along with significant loss of tissue. Extreme blood loss will lead to quick death without intervention."
|
||||
treat_text = "Immediate bandaging and either suturing or cauterization, followed by supervised resanguination."
|
||||
examine_desc = "is spurting blood at an alarming rate"
|
||||
occur_text = "is torn open, spraying blood wildly"
|
||||
sound_effect = 'sound/effects/blood3.ogg'
|
||||
severity = WOUND_SEVERITY_CRITICAL
|
||||
initial_flow = 4.25
|
||||
minimum_flow = 4
|
||||
clot_rate = -0.05 // critical cuts actively get worse instead of better
|
||||
max_per_type = 5
|
||||
threshold_minimum = 80
|
||||
threshold_penalty = 40
|
||||
demotes_to = /datum/wound/brute/cut/severe
|
||||
status_effect_type = /datum/status_effect/wound/cut/critical
|
||||
scarring_descriptions = list("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")
|
||||
|
||||
// TODO: see about moving dismemberment over to this, i'll have to add judging dismembering power/wound potential wrt item size i guess
|
||||
/datum/wound/brute/cut/loss
|
||||
name = "Dismembered"
|
||||
desc = "oof ouch!!"
|
||||
occur_text = "is violently dismembered!"
|
||||
sound_effect = 'sound/effects/dismember.ogg'
|
||||
viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
severity = WOUND_SEVERITY_LOSS
|
||||
threshold_minimum = 180
|
||||
status_effect_type = null
|
||||
|
||||
/datum/wound/brute/cut/loss/apply_wound(obj/item/bodypart/L, silent, datum/wound/brute/cut/old_wound, smited = FALSE)
|
||||
if(!L.dismemberable)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
L.dismember()
|
||||
qdel(src)
|
||||
@@ -986,6 +986,39 @@ Proc for attack log creation, because really why not
|
||||
var/reverse_message = "has been [what_done] by [ssource][postfix]"
|
||||
target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE)
|
||||
|
||||
/**
|
||||
* log_wound() is for when someone is *attacked* and suffers a wound. Note that this only captures wounds from damage, so smites/forced wounds aren't logged, as well as demotions like cuts scabbing over
|
||||
*
|
||||
* Note that this has no info on the attack that dealt the wound: information about where damage came from isn't passed to the bodypart's damaged proc. When in doubt, check the attack log for attacks at that same time
|
||||
* TODO later: Add logging for healed wounds, though that will require some rewriting of healing code to prevent admin heals from spamming the logs. Not high priority
|
||||
*
|
||||
* Arguments:
|
||||
* * victim- The guy who got wounded
|
||||
* * suffered_wound- The wound, already applied, that we're logging. It has to already be attached so we can get the limb from it
|
||||
* * dealt_damage- How much damage is associated with the attack that dealt with this wound.
|
||||
* * dealt_wound_bonus- The wound_bonus, if one was specified, of the wounding attack
|
||||
* * dealt_bare_wound_bonus- The bare_wound_bonus, if one was specified *and applied*, of the wounding attack. Not shown if armor was present
|
||||
* * base_roll- Base wounding ability of an attack is a random number from 1 to (dealt_damage ** WOUND_DAMAGE_EXPONENT). This is the number that was rolled in there, before mods
|
||||
*/
|
||||
/proc/log_wound(atom/victim, datum/wound/suffered_wound, dealt_damage, dealt_wound_bonus, dealt_bare_wound_bonus, base_roll)
|
||||
if(QDELETED(victim) || !suffered_wound)
|
||||
return
|
||||
var/message = "has suffered: [suffered_wound][suffered_wound.limb ? " to [suffered_wound.limb.name]" : null]"// maybe indicate if it's a promote/demote?
|
||||
|
||||
if(dealt_damage)
|
||||
message += " | Damage: [dealt_damage]"
|
||||
// The base roll is useful since it can show how lucky someone got with the given attack. For example, dealing a cut
|
||||
if(base_roll)
|
||||
message += " (rolled [base_roll]/[dealt_damage ** WOUND_DAMAGE_EXPONENT])"
|
||||
|
||||
if(dealt_wound_bonus)
|
||||
message += " | WB: [dealt_wound_bonus]"
|
||||
|
||||
if(dealt_bare_wound_bonus)
|
||||
message += " | BWB: [dealt_bare_wound_bonus]"
|
||||
|
||||
victim.log_message(message, LOG_ATTACK, color="blue")
|
||||
|
||||
// Filter stuff
|
||||
/atom/proc/add_filter(name,priority,list/params)
|
||||
LAZYINITLIST(filter_data)
|
||||
|
||||
@@ -343,6 +343,10 @@
|
||||
/obj/machinery/door/proc/crush()
|
||||
for(var/mob/living/L in get_turf(src))
|
||||
L.visible_message("<span class='warning'>[src] closes on [L], crushing [L.p_them()]!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
for(var/datum/wound/W in C.all_wounds)
|
||||
W.crush(DOOR_CRUSH_DAMAGE)
|
||||
if(isalien(L)) //For xenos
|
||||
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
|
||||
L.emote("roar")
|
||||
|
||||
@@ -162,8 +162,6 @@
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!ishuman(user))
|
||||
return
|
||||
if(attached)
|
||||
visible_message("[attached] is detached from [src]")
|
||||
attached = null
|
||||
@@ -174,7 +172,11 @@
|
||||
else
|
||||
toggle_mode()
|
||||
|
||||
/obj/machinery/iv_drip/verb/eject_beaker()
|
||||
/obj/machinery/iv_drip/attack_robot(mob/user)
|
||||
if(Adjacent(user))
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/iv_drip/verb/eject_beaker(mob/user)
|
||||
set category = "Object"
|
||||
set name = "Remove IV Container"
|
||||
set src in view(1)
|
||||
@@ -189,6 +191,8 @@
|
||||
if(usr && Adjacent(usr) && usr.can_hold_items())
|
||||
if(!usr.put_in_hands(beaker))
|
||||
beaker.forceMove(drop_location())
|
||||
if(iscyborg(user))
|
||||
beaker.forceMove(drop_location())
|
||||
beaker = null
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -183,9 +183,21 @@
|
||||
var/T = get_turf(target)
|
||||
if(locate(/mob/living) in T)
|
||||
new /obj/effect/temp_visual/medical_holosign(T,user) //produce a holographic glow
|
||||
holo_cooldown = world.time + 100
|
||||
holo_cooldown = world.time + 10 SECONDS
|
||||
return
|
||||
|
||||
// see: [/datum/wound/burn/proc/uv()]
|
||||
/obj/item/flashlight/pen/paramedic
|
||||
name = "paramedic penlight"
|
||||
desc = "A high-powered UV penlight intended to help stave off infection in the field on serious burned patients. Probably really bad to look into."
|
||||
icon_state = "penlight_surgical"
|
||||
/// Our current UV cooldown
|
||||
var/uv_cooldown = 0
|
||||
/// How long between UV fryings
|
||||
var/uv_cooldown_length = 1 MINUTES
|
||||
/// How much sanitization to apply to the burn wound
|
||||
var/uv_power = 1
|
||||
|
||||
/obj/effect/temp_visual/medical_holosign
|
||||
name = "medical holosign"
|
||||
desc = "A small holographic glow that indicates a medic is coming to treat a patient."
|
||||
|
||||
@@ -10,6 +10,14 @@ NANITE SCANNER
|
||||
GENETICS SCANNER
|
||||
|
||||
*/
|
||||
|
||||
// Describes the three modes of scanning available for health analyzers
|
||||
#define SCANMODE_HEALTH 0
|
||||
#define SCANMODE_CHEMICAL 1
|
||||
#define SCANMODE_WOUND 2
|
||||
#define SCANNER_CONDENSED 0
|
||||
#define SCANNER_VERBOSE 1
|
||||
|
||||
/obj/item/t_scanner
|
||||
name = "\improper T-ray scanner"
|
||||
desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
|
||||
@@ -80,7 +88,7 @@ GENETICS SCANNER
|
||||
throw_range = 7
|
||||
custom_materials = list(/datum/material/iron=200)
|
||||
var/mode = 1
|
||||
var/scanmode = 0
|
||||
var/scanmode = SCANMODE_HEALTH
|
||||
var/advanced = FALSE
|
||||
|
||||
/obj/item/healthanalyzer/suicide_act(mob/living/carbon/user)
|
||||
@@ -88,37 +96,40 @@ GENETICS SCANNER
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/healthanalyzer/attack_self(mob/user)
|
||||
if(!scanmode)
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to scan chemical contents.</span>")
|
||||
scanmode = 1
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to check physical health.</span>")
|
||||
scanmode = 0
|
||||
scanmode = (scanmode + 1) % 3
|
||||
switch(scanmode)
|
||||
if(SCANMODE_HEALTH)
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to check physical health.</span>")
|
||||
if(SCANMODE_CHEMICAL)
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to scan chemical contents.</span>")
|
||||
if(SCANMODE_WOUND)
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to report extra info on wounds.</span>")
|
||||
|
||||
/obj/item/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user)
|
||||
flick("[icon_state]-scan", src) //makes it so that it plays the scan animation upon scanning, including clumsy scanning
|
||||
|
||||
// Clumsiness/brain damage check
|
||||
if ((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50))
|
||||
to_chat(user, "<span class='notice'>You stupidly try to analyze the floor's vitals!</span>")
|
||||
user.visible_message("<span class='warning'>[user] has analyzed the floor's vitals!</span>")
|
||||
var/msg = "<span class='info'>*---------*\nAnalyzing results for The floor:\n\tOverall status: <b>Healthy</b>\n"
|
||||
msg += "Key: <font color='blue'>Suffocation</font>/<font color='green'>Toxin</font>/<font color='#FF8000'>Burn</font>/<font color='red'>Brute</font>\n"
|
||||
msg += "\tDamage specifics: <font color='blue'>0</font>-<font color='green'>0</font>-<font color='#FF8000'>0</font>-<font color='red'>0</font>\n"
|
||||
msg += "Body temperature: ???\n"
|
||||
msg += "*---------*</span>"
|
||||
to_chat(user, msg)
|
||||
user.visible_message("<span class='warning'>[user] analyzes the floor's vitals!</span>", \
|
||||
"<span class='notice'>You stupidly try to analyze the floor's vitals!</span>")
|
||||
to_chat(user, "<span class='info'>Analyzing results for The floor:\n\tOverall status: <b>Healthy</b></span>\
|
||||
\n<span class='info'>Key: <font color='blue'>Suffocation</font>/<font color='green'>Toxin</font>/<font color='#FF8000'>Burn</font>/<font color='red'>Brute</font></span>\
|
||||
\n<span class='info'>\tDamage specifics: <font color='blue'>0</font>-<font color='green'>0</font>-<font color='#FF8000'>0</font>-<font color='red'>0</font></span>\
|
||||
\n<span class='info'>Body temperature: ???</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='notice'>[user] has analyzed [M]'s vitals.</span>")
|
||||
user.visible_message("<span class='notice'>[user] analyzes [M]'s vitals.</span>", \
|
||||
"<span class='notice'>You analyze [M]'s vitals.</span>")
|
||||
|
||||
if(scanmode == 0)
|
||||
if(scanmode == SCANMODE_HEALTH)
|
||||
healthscan(user, M, mode, advanced)
|
||||
else if(scanmode == 1)
|
||||
else if(scanmode == SCANMODE_CHEMICAL)
|
||||
chemscan(user, M)
|
||||
else
|
||||
woundscan(user, M, src)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
// Used by the PDA medical scanner too
|
||||
/proc/healthscan(mob/user, mob/living/M, mode = 1, advanced = FALSE)
|
||||
if(isliving(user) && (user.incapacitated() || user.eye_blind))
|
||||
@@ -402,6 +413,17 @@ GENETICS SCANNER
|
||||
msg += "<span class='danger'> Intervention recommended.</span>\n"
|
||||
else
|
||||
msg += "\n"
|
||||
// Wounds
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
var/list/wounded_parts = C.get_wounded_bodyparts()
|
||||
for(var/i in wounded_parts)
|
||||
var/obj/item/bodypart/wounded_part = i
|
||||
msg += "<span class='alert ml-1'><b>Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]</b>"
|
||||
for(var/k in wounded_part.wounds)
|
||||
var/datum/wound/W = k
|
||||
msg += "<div class='ml-2'>Type: [W.name]\nSeverity: [W.severity_text()]\nRecommended Treatment: [W.treat_text]</div>\n" // less lines than in woundscan() so we don't overload people trying to get basic med info
|
||||
msg += "</span>\n"
|
||||
|
||||
for(var/thing in M.diseases)
|
||||
var/datum/disease/D = thing
|
||||
@@ -414,7 +436,7 @@ GENETICS SCANNER
|
||||
var/blood_typepath = C.get_blood_id()
|
||||
if(blood_typepath)
|
||||
if(ishuman(C))
|
||||
if(H.bleed_rate)
|
||||
if(H.is_bleeding())
|
||||
msg += "<span class='danger'>Subject is bleeding!</span>\n"
|
||||
var/blood_percent = round((C.scan_blood_volume() / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
|
||||
var/blood_type = C.dna.blood_type
|
||||
@@ -505,6 +527,67 @@ GENETICS SCANNER
|
||||
desc = "A hand-held body scanner able to distinguish vital signs of the subject with high accuracy."
|
||||
advanced = TRUE
|
||||
|
||||
/// Displays wounds with extended information on their status vs medscanners
|
||||
/proc/woundscan(mob/user, mob/living/carbon/patient, obj/item/healthanalyzer/wound/scanner)
|
||||
if(!istype(patient))
|
||||
return
|
||||
|
||||
var/render_list = ""
|
||||
for(var/i in patient.get_wounded_bodyparts())
|
||||
var/obj/item/bodypart/wounded_part = i
|
||||
render_list += "<span class='alert ml-1'><b>Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]</b>"
|
||||
for(var/k in wounded_part.wounds)
|
||||
var/datum/wound/W = k
|
||||
render_list += "<div class='ml-2'>[W.get_scanner_description()]</div>\n"
|
||||
render_list += "</span>"
|
||||
|
||||
if(render_list == "")
|
||||
if(istype(scanner))
|
||||
// Only emit the cheerful scanner message if this scan came from a scanner
|
||||
playsound(scanner, 'sound/machines/ping.ogg', 50, FALSE)
|
||||
to_chat(user, "<span class='notice'>\The [scanner] makes a happy ping and briefly displays a smiley face with several exclamation points! It's really excited to report that [patient] has no wounds!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice ml-1'>No wounds detected in subject.</span>")
|
||||
else
|
||||
to_chat(user, jointext(render_list, ""))
|
||||
|
||||
/obj/item/healthanalyzer/wound
|
||||
name = "first aid analyzer"
|
||||
icon_state = "adv_spectrometer"
|
||||
desc = "A prototype MeLo-Tech medical scanner used to diagnose injuries and recommend treatment for serious wounds, but offers no further insight into the patient's health. You hope the final version is less annoying to read!"
|
||||
var/next_encouragement
|
||||
var/greedy
|
||||
|
||||
/obj/item/healthanalyzer/wound/attack_self(mob/user)
|
||||
if(next_encouragement < world.time)
|
||||
playsound(src, 'sound/machines/ping.ogg', 50, FALSE)
|
||||
var/list/encouragements = list("briefly displays a happy face, gazing emptily at you", "briefly displays a spinning cartoon heart", "displays an encouraging message about eating healthy and exercising", \
|
||||
"reminds you that everyone is doing their best", "displays a message wishing you well", "displays a sincere thank-you for your interest in first-aid", "formally absolves you of all your sins")
|
||||
to_chat(user, "<span class='notice'>\The [src] makes a happy ping and [pick(encouragements)]!</span>")
|
||||
next_encouragement = world.time + 10 SECONDS
|
||||
greedy = FALSE
|
||||
else if(!greedy)
|
||||
to_chat(user, "<span class='warning'>\The [src] displays an eerily high-definition frowny face, chastizing you for asking it for too much encouragement.</span>")
|
||||
greedy = TRUE
|
||||
else
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
to_chat(L, "<span class='warning'>\The [src] makes a disappointed buzz and pricks your finger for being greedy. Ow!</span>")
|
||||
L.adjustBruteLoss(4)
|
||||
L.dropItemToGround(src)
|
||||
|
||||
/obj/item/healthanalyzer/wound/attack(mob/living/carbon/patient, mob/living/carbon/human/user)
|
||||
add_fingerprint(user)
|
||||
user.visible_message("<span class='notice'>[user] scans [patient] for serious injuries.</span>", "<span class='notice'>You scan [patient] for serious injuries.</span>")
|
||||
|
||||
if(!istype(patient))
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
|
||||
to_chat(user, "<span class='notice'>\The [src] makes a sad buzz and briefly displays a frowny face, indicating it can't scan [patient].</span>")
|
||||
return
|
||||
|
||||
woundscan(user, patient, src)
|
||||
|
||||
/obj/item/analyzer
|
||||
desc = "A hand-held environmental scanner which reports current gas levels. Alt-Click to use the built in barometer function."
|
||||
name = "analyzer"
|
||||
@@ -878,3 +961,9 @@ GENETICS SCANNER
|
||||
return "[HM.name] ([HM.alias])"
|
||||
else
|
||||
return HM.alias
|
||||
|
||||
#undef SCANMODE_HEALTH
|
||||
#undef SCANMODE_CHEMICAL
|
||||
#undef SCANMODE_WOUND
|
||||
#undef SCANNER_CONDENSED
|
||||
#undef SCANNER_VERBOSE
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
max_integrity = 200
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
wound_bonus = -110
|
||||
bare_wound_bonus = 20
|
||||
block_parry_data = /datum/block_parry_data/dual_esword
|
||||
var/hacked = FALSE
|
||||
/// Can this reflect all energy projectiles?
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
max_integrity = 200
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
|
||||
resistance_flags = FIRE_PROOF
|
||||
wound_bonus = -20
|
||||
var/wielded = FALSE // track wielded status on item
|
||||
|
||||
/obj/item/fireaxe/Initialize()
|
||||
|
||||
@@ -60,6 +60,14 @@
|
||||
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/mega
|
||||
shrapnel_radius = 12
|
||||
|
||||
/obj/item/grenade/stingbang/breaker
|
||||
name = "breakbang"
|
||||
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/breaker
|
||||
|
||||
/obj/item/grenade/stingbang/shred
|
||||
name = "shredbang"
|
||||
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/shred
|
||||
|
||||
/obj/item/grenade/stingbang/prime(mob/living/lanced_by)
|
||||
if(iscarbon(loc))
|
||||
var/mob/living/carbon/C = loc
|
||||
|
||||
@@ -225,6 +225,7 @@
|
||||
throwforce = 10
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
obj_flags = UNIQUE_RENAME
|
||||
wound_bonus = -10
|
||||
var/chaplain_spawnable = TRUE
|
||||
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
|
||||
|
||||
@@ -657,6 +658,8 @@
|
||||
item_flags = ABSTRACT
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
sharpness = IS_SHARP
|
||||
wound_bonus = -20
|
||||
bare_wound_bonus = 25
|
||||
total_mass = TOTAL_MASS_HAND_REPLACEMENT
|
||||
|
||||
/obj/item/nullrod/armblade/Initialize()
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
sharpness = IS_SHARP_ACCURATE
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
var/bayonet = FALSE //Can this be attached to a gun?
|
||||
wound_bonus = -5
|
||||
bare_wound_bonus = 10
|
||||
custom_price = PRICE_NORMAL
|
||||
|
||||
/obj/item/kitchen/knife/Initialize()
|
||||
|
||||
@@ -506,7 +506,9 @@
|
||||
if(prob(50))
|
||||
step(W, pick(GLOB.alldirs))
|
||||
ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC)
|
||||
H.bleed_rate = 5
|
||||
for(var/i in H.bodyparts)
|
||||
var/obj/item/bodypart/BP = i
|
||||
BP.generic_bleedstacks += 5
|
||||
H.gib_animation()
|
||||
sleep(3)
|
||||
H.adjustBruteLoss(1000) //to make the body super-bloody
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
force = 14
|
||||
throwforce = 10
|
||||
wound_bonus = 15
|
||||
bare_wound_bonus = 10
|
||||
reach = 2
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
attack_verb = list("flogged", "whipped", "lashed", "disciplined")
|
||||
@@ -268,6 +270,8 @@
|
||||
var/force_off // Damage when off - not stunning
|
||||
var/weight_class_on // What is the new size class when turned on
|
||||
|
||||
wound_bonus = 15
|
||||
|
||||
/obj/item/melee/classic_baton/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -393,6 +397,7 @@
|
||||
force_off = 0
|
||||
weight_class_on = WEIGHT_CLASS_BULKY
|
||||
total_mass = TOTAL_MASS_NORMAL_ITEM
|
||||
bare_wound_bonus = 5
|
||||
|
||||
/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
|
||||
return
|
||||
target.apply_damage(totalitemdamage * fisto_setting, BRUTE)
|
||||
target.apply_damage(totalitemdamage * fisto_setting, BRUTE, wound_bonus = -25*fisto_setting**2)
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
|
||||
new /obj/effect/temp_visual/kinetic_blast(target.loc)
|
||||
|
||||
@@ -747,7 +747,7 @@
|
||||
|
||||
/obj/item/weapon/gripper
|
||||
name = "engineering gripper"
|
||||
desc = "A simple grasping tool for interacting with various engineering related items, such as circuits, gas tanks and conveyer belts. Alt click to drop instead of use."
|
||||
desc = "A simple grasping tool for interacting with various engineering related items, such as circuits, gas tanks, conveyer belts and more. Alt click to drop instead of use."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "gripper"
|
||||
|
||||
@@ -784,7 +784,7 @@
|
||||
wrapped = null
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gripper/afterattack(var/atom/target, var/mob/living/silicon/robot/user, proximity, params)
|
||||
/obj/item/weapon/gripper/pre_attack(var/atom/target, var/mob/living/silicon/robot/user, proximity, params)
|
||||
|
||||
if(!proximity)
|
||||
return
|
||||
@@ -839,6 +839,19 @@
|
||||
/obj/item/survivalcapsule
|
||||
)
|
||||
|
||||
/obj/item/weapon/gripper/medical
|
||||
name = "medical gripper"
|
||||
desc = "A simple grasping tool for interacting with medical equipment, such as beakers, blood bags, chem bags and more. Alt click to drop instead of use."
|
||||
icon_state = "gripper_medical"
|
||||
can_hold = list(
|
||||
/obj/item/storage/bag/bio,
|
||||
/obj/item/storage/bag/chemistry,
|
||||
/obj/item/storage/pill_bottle,
|
||||
/obj/item/reagent_containers/glass,
|
||||
/obj/item/reagent_containers/pill,
|
||||
/obj/item/reagent_containers/blood
|
||||
)
|
||||
|
||||
/obj/item/gun/energy/plasmacutter/cyborg
|
||||
name = "cyborg plasma cutter"
|
||||
desc = "A basic variation of the plasma cutter, compressed into a cyborg chassis. Less effective than normal plasma cutters."
|
||||
@@ -921,6 +934,9 @@
|
||||
icon_state = "data_1"
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Dogborg stuff
|
||||
***********************************************************************/
|
||||
///Mere cosmetic dogborg items, remnants of what were once the most annoying cyborg modules.
|
||||
/obj/item/dogborg_tongue
|
||||
name = "synthetic tongue"
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
icon_state = "large"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
item_flags = DROPDEL
|
||||
sharpness = TRUE
|
||||
|
||||
/obj/item/shrapnel/stingball // stingbang grenades
|
||||
name = "stingball"
|
||||
embedding = list(embed_chance=90, fall_chance=3, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=5, jostle_pain_mult=6, rip_time=15, embed_chance_turf_mod=-100)
|
||||
icon_state = "tiny"
|
||||
sharpness = FALSE
|
||||
|
||||
/obj/item/shrapnel/bullet // bullets
|
||||
name = "bullet"
|
||||
@@ -28,7 +30,7 @@
|
||||
|
||||
/obj/item/projectile/bullet/shrapnel
|
||||
name = "flying shrapnel shard"
|
||||
damage = 9
|
||||
damage = 8
|
||||
range = 10
|
||||
armour_penetration = -30
|
||||
dismemberment = 5
|
||||
@@ -36,6 +38,8 @@
|
||||
ricochet_chance = 40
|
||||
shrapnel_type = /obj/item/shrapnel
|
||||
ricochet_incidence_leeway = 60
|
||||
sharpness = TRUE
|
||||
wound_bonus = 30
|
||||
|
||||
/obj/item/projectile/bullet/shrapnel/mega
|
||||
name = "flying shrapnel hunk"
|
||||
@@ -62,3 +66,15 @@
|
||||
name = "megastingball pellet"
|
||||
ricochets_max = 6
|
||||
ricochet_chance = 110
|
||||
|
||||
/obj/item/projectile/bullet/pellet/stingball/breaker
|
||||
name = "breakbang pellet"
|
||||
damage = 10
|
||||
wound_bonus = 40
|
||||
sharpness = FALSE
|
||||
|
||||
/obj/item/projectile/bullet/pellet/stingball/shred
|
||||
name = "shredbang pellet"
|
||||
damage = 10
|
||||
wound_bonus = 30
|
||||
sharpness = TRUE
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
var/war_cry = "AAAAARGH!!!"
|
||||
var/icon_prefix = "spearglass"
|
||||
var/wielded = FALSE // track wielded status on item
|
||||
wound_bonus = -25
|
||||
bare_wound_bonus = 15
|
||||
|
||||
/obj/item/spear/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -15,6 +15,16 @@
|
||||
var/self_delay = 50
|
||||
var/other_delay = 0
|
||||
var/repeating = FALSE
|
||||
/// How much brute we heal per application
|
||||
var/heal_brute
|
||||
/// How much burn we heal per application
|
||||
var/heal_burn
|
||||
/// How much we reduce bleeding per application on cut wounds
|
||||
var/stop_bleeding
|
||||
/// How much sanitization to apply to burns on application
|
||||
var/sanitization
|
||||
/// How much we add to flesh_healing for burn wounds on application
|
||||
var/flesh_regeneration
|
||||
|
||||
/obj/item/stack/medical/attack(mob/living/M, mob/user)
|
||||
. = ..()
|
||||
@@ -70,8 +80,9 @@
|
||||
icon_state = "brutepack"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
var/heal_brute = 20
|
||||
self_delay = 20
|
||||
heal_brute = 40
|
||||
self_delay = 40
|
||||
other_delay = 20
|
||||
grind_results = list(/datum/reagent/medicine/styptic_powder = 10)
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/one
|
||||
@@ -95,7 +106,8 @@
|
||||
M.heal_bodypart_damage((heal_brute/2))
|
||||
return TRUE
|
||||
if(iscarbon(M))
|
||||
return heal_carbon(M, user, heal_brute, 0)
|
||||
return heal_carbon(M, user, heal_brute, heal_burn)
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
|
||||
to_chat(user, "<span class='notice'>You can't heal [M] with the \the [src]!</span>")
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/suicide_act(mob/user)
|
||||
@@ -104,24 +116,27 @@
|
||||
|
||||
/obj/item/stack/medical/gauze
|
||||
name = "medical gauze"
|
||||
desc = "A roll of elastic cloth that is extremely effective at stopping bleeding, heals minor wounds."
|
||||
desc = "A roll of elastic cloth, perfect for stabilizing all kinds of wounds, from cuts and burns, to broken bones. "
|
||||
gender = PLURAL
|
||||
singular_name = "medical gauze"
|
||||
icon_state = "gauze"
|
||||
var/stop_bleeding = 1800
|
||||
var/heal_brute = 5
|
||||
self_delay = 10
|
||||
heal_brute = 5
|
||||
self_delay = 50
|
||||
other_delay = 20
|
||||
amount = 6
|
||||
absorption_rate = 0.25
|
||||
absorption_capacity = 5
|
||||
splint_factor = 0.35
|
||||
custom_price = PRICE_REALLY_CHEAP
|
||||
|
||||
/obj/item/stack/medical/gauze/heal(mob/living/M, mob/user)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(!H.bleedsuppress && H.bleed_rate) //so you can't stack bleed suppression
|
||||
H.suppress_bloodloss(stop_bleeding)
|
||||
to_chat(user, "<span class='notice'>You stop the bleeding of [M]!</span>")
|
||||
H.adjustBruteLoss(-(heal_brute))
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You can not use \the [src] on [M]!</span>")
|
||||
// gauze is only relevant for wounds, which are handled in the wounds themselves
|
||||
/obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent)
|
||||
var/obj/item/bodypart/limb = M.get_bodypart(check_zone(user.zone_selected))
|
||||
if(limb)
|
||||
if(limb.brute_dam > 40)
|
||||
to_chat(user, "<span class='warning'>The bleeding on [user==M ? "your" : "[M]'s"] [limb.name] is from bruising, and cannot be treated with [src]!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There's no bleeding on [user==M ? "your" : "[M]'s"] [limb.name]</span>")
|
||||
|
||||
/obj/item/stack/medical/gauze/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_WIRECUTTER || I.get_sharpness())
|
||||
@@ -143,9 +158,12 @@
|
||||
/obj/item/stack/medical/gauze/improvised
|
||||
name = "improvised gauze"
|
||||
singular_name = "improvised gauze"
|
||||
desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds."
|
||||
stop_bleeding = 900
|
||||
heal_brute = 0
|
||||
desc = "A roll of cloth roughly cut from something that does a decent job of stabilizing wounds, but less efficiently so than real medical gauze."
|
||||
self_delay = 60
|
||||
other_delay = 30
|
||||
absorption_rate = 0.15
|
||||
absorption_capacity = 4
|
||||
|
||||
/obj/item/stack/medical/gauze/adv
|
||||
name = "sterilized medical gauze"
|
||||
@@ -161,49 +179,28 @@
|
||||
is_cyborg = 1
|
||||
cost = 250
|
||||
|
||||
/obj/item/stack/medical/ointment
|
||||
name = "ointment"
|
||||
desc = "Used to treat those nasty burn wounds."
|
||||
gender = PLURAL
|
||||
singular_name = "ointment"
|
||||
icon_state = "ointment"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
var/heal_burn = 20
|
||||
self_delay = 20
|
||||
grind_results = list(/datum/reagent/medicine/silver_sulfadiazine = 10)
|
||||
|
||||
/obj/item/stack/medical/ointment/one
|
||||
amount = 1
|
||||
|
||||
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
|
||||
if(M.stat == DEAD)
|
||||
to_chat(user, "<span class='notice'> [M] is dead. You can not help [M.p_them()]!</span>")
|
||||
return
|
||||
if(iscarbon(M))
|
||||
return heal_carbon(M, user, 0, heal_burn)
|
||||
if(AmBloodsucker(M))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You can't heal [M] with the \the [src]!</span>")
|
||||
|
||||
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
|
||||
return TOXLOSS
|
||||
|
||||
/obj/item/stack/medical/suture
|
||||
name = "suture"
|
||||
desc = "Sterile sutures used to seal up cuts and lacerations."
|
||||
desc = "Basic sterile sutures used to seal up cuts and lacerations and stop bleeding."
|
||||
gender = PLURAL
|
||||
singular_name = "suture"
|
||||
icon_state = "suture"
|
||||
self_delay = 30
|
||||
other_delay = 10
|
||||
amount = 15
|
||||
max_amount = 15
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
repeating = TRUE
|
||||
var/heal_brute = 10
|
||||
heal_brute = 10
|
||||
stop_bleeding = 0.6
|
||||
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
|
||||
|
||||
/obj/item/stack/medical/suture/emergency
|
||||
name = "emergency suture"
|
||||
desc = "A value pack of cheap sutures, not very good at repairing damage, but still decent at stopping bleeding."
|
||||
heal_brute = 5
|
||||
amount = 5
|
||||
max_amount = 5
|
||||
|
||||
/obj/item/stack/medical/suture/one
|
||||
amount = 1
|
||||
|
||||
@@ -233,10 +230,39 @@
|
||||
to_chat(user, "<span class='notice'>[M] is at full health.</span>")
|
||||
return FALSE
|
||||
user.visible_message("<span class='green'>[user] applies \the [src] on [M].</span>", "<span class='green'>You apply \the [src] on [M].</span>")
|
||||
M.heal_bodypart_damage(heal_brute)
|
||||
return TRUE
|
||||
return heal_carbon(M, user, heal_brute, heal_burn)
|
||||
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
|
||||
|
||||
/obj/item/stack/medical/ointment
|
||||
name = "ointment"
|
||||
desc = "Basic burn ointment, rated effective for second degree burns with proper bandaging, though it's still an effective stabilizer for worse burns. Not terribly good at outright healing burns though."
|
||||
gender = PLURAL
|
||||
singular_name = "ointment"
|
||||
icon_state = "ointment"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
self_delay = 40
|
||||
other_delay = 20
|
||||
|
||||
heal_burn = 5
|
||||
flesh_regeneration = 2.5
|
||||
sanitization = 0.3
|
||||
grind_results = list(/datum/reagent/medicine/kelotane = 10)
|
||||
|
||||
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
|
||||
if(M.stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>[M] is dead! You can not help [M.p_them()].</span>")
|
||||
return
|
||||
if(iscarbon(M))
|
||||
return heal_carbon(M, user, heal_brute, heal_burn)
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
|
||||
|
||||
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
|
||||
return TOXLOSS
|
||||
|
||||
/obj/item/stack/medical/mesh
|
||||
name = "regenerative mesh"
|
||||
@@ -247,9 +273,11 @@
|
||||
self_delay = 30
|
||||
other_delay = 10
|
||||
amount = 15
|
||||
heal_burn = 10
|
||||
max_amount = 15
|
||||
repeating = TRUE
|
||||
var/heal_burn = 10
|
||||
sanitization = 0.75
|
||||
flesh_regeneration = 3
|
||||
var/is_open = TRUE ///This var determines if the sterile packaging of the mesh has been opened.
|
||||
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
|
||||
|
||||
@@ -292,8 +320,8 @@
|
||||
to_chat(user, "<span class='warning'>[M] is dead! You can not help [M.p_them()].</span>")
|
||||
return
|
||||
if(iscarbon(M))
|
||||
return heal_carbon(M, user, 0, heal_burn)
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
|
||||
return heal_carbon(M, user, heal_brute, heal_burn)
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
|
||||
|
||||
|
||||
/obj/item/stack/medical/mesh/try_heal(mob/living/M, mob/user, silent = FALSE)
|
||||
@@ -323,6 +351,52 @@
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/medical/bone_gel
|
||||
name = "bone gel"
|
||||
singular_name = "bone gel"
|
||||
desc = "A potent medical gel that, when applied to a damaged bone in a proper surgical setting, triggers an intense melding reaction to repair the wound. Can be directly applied alongside surgical sticky tape to a broken bone in dire circumstances, though this is very harmful to the patient and not recommended."
|
||||
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
icon_state = "bone-gel"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
|
||||
amount = 4
|
||||
self_delay = 20
|
||||
grind_results = list(/datum/reagent/medicine/bicaridine = 10)
|
||||
novariants = TRUE
|
||||
|
||||
/obj/item/stack/medical/bone_gel/attack(mob/living/M, mob/user)
|
||||
to_chat(user, "<span class='warning'>Bone gel can only be used on fractured limbs while aggressively holding someone!</span>")
|
||||
return
|
||||
|
||||
/obj/item/stack/medical/bone_gel/suicide_act(mob/user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.visible_message("<span class='suicide'>[C] is squirting all of \the [src] into [C.p_their()] mouth! That's not proper procedure! It looks like [C.p_theyre()] trying to commit suicide!</span>")
|
||||
if(do_after(C, 2 SECONDS))
|
||||
C.emote("scream")
|
||||
for(var/i in C.bodyparts)
|
||||
var/obj/item/bodypart/bone = i
|
||||
var/datum/wound/brute/bone/severe/oof_ouch = new
|
||||
oof_ouch.apply_wound(bone)
|
||||
var/datum/wound/brute/bone/critical/oof_OUCH = new
|
||||
oof_OUCH.apply_wound(bone)
|
||||
|
||||
for(var/i in C.bodyparts)
|
||||
var/obj/item/bodypart/bone = i
|
||||
bone.receive_damage(brute=60)
|
||||
use(1)
|
||||
return (BRUTELOSS)
|
||||
else
|
||||
C.visible_message("<span class='suicide'>[C] screws up like an idiot and still dies anyway!</span>")
|
||||
return (BRUTELOSS)
|
||||
|
||||
/obj/item/stack/medical/bone_gel/cyborg
|
||||
custom_materials = null
|
||||
is_cyborg = 1
|
||||
cost = 250
|
||||
|
||||
/obj/item/stack/medical/aloe
|
||||
name = "aloe cream"
|
||||
desc = "A healing paste you can apply on wounds."
|
||||
@@ -355,4 +429,4 @@
|
||||
M.heal_bodypart_damage(heal, heal)
|
||||
return TRUE
|
||||
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
|
||||
|
||||
@@ -25,9 +25,18 @@
|
||||
var/list/mats_per_unit //list that tells you how much is in a single unit.
|
||||
///Datum material type that this stack is made of
|
||||
var/material_type
|
||||
max_integrity = 100
|
||||
//NOTE: When adding grind_results, the amounts should be for an INDIVIDUAL ITEM - these amounts will be multiplied by the stack size in on_grind()
|
||||
var/obj/structure/table/tableVariant // we tables now (stores table variant to be built from this stack)
|
||||
|
||||
// The following are all for medical treatment, they're here instead of /stack/medical because sticky tape can be used as a makeshift bandage or splint
|
||||
/// If set and this used as a splint for a broken bone wound, this is used as a multiplier for applicable slowdowns (lower = better) (also for speeding up burn recoveries)
|
||||
var/splint_factor
|
||||
/// How much blood flow this stack can absorb if used as a bandage on a cut wound, note that absorption is how much we lower the flow rate, not the raw amount of blood we suck up
|
||||
var/absorption_capacity
|
||||
/// How quickly we lower the blood flow on a cut wound we're bandaging. Expected lifetime of this bandage in ticks is thus absorption_capacity/absorption_rate, or until the cut heals, whichever comes first
|
||||
var/absorption_rate
|
||||
|
||||
/obj/item/stack/on_grind()
|
||||
for(var/i in 1 to grind_results.len) //This should only call if it's ground, so no need to check if grind_results exists
|
||||
grind_results[grind_results[i]] *= get_amount() //Gets the key at position i, then the reagent amount of that key, then multiplies it by stack size
|
||||
|
||||
@@ -7,10 +7,13 @@
|
||||
icon = 'icons/obj/tapes.dmi'
|
||||
icon_state = "tape_w"
|
||||
var/prefix = "sticky"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
full_w_class = WEIGHT_CLASS_TINY
|
||||
item_flags = NOBLUDGEON
|
||||
amount = 5
|
||||
max_amount = 5
|
||||
resistance_flags = FLAMMABLE
|
||||
splint_factor = 0.8
|
||||
grind_results = list(/datum/reagent/cellulose = 5)
|
||||
|
||||
var/list/conferred_embed = EMBED_HARMLESS
|
||||
@@ -54,6 +57,7 @@
|
||||
icon_state = "tape_y"
|
||||
prefix = "super sticky"
|
||||
conferred_embed = EMBED_HARMLESS_SUPERIOR
|
||||
splint_factor = 0.6
|
||||
|
||||
/obj/item/stack/sticky_tape/pointy
|
||||
name = "pointy tape"
|
||||
@@ -69,4 +73,14 @@
|
||||
desc = "You didn't know tape could look so sinister. Welcome to Space Station 13."
|
||||
icon_state = "tape_spikes"
|
||||
prefix = "super pointy"
|
||||
conferred_embed = EMBED_POINTY_SUPERIOR
|
||||
conferred_embed = EMBED_POINTY_SUPERIOR
|
||||
|
||||
/obj/item/stack/sticky_tape/surgical
|
||||
name = "surgical tape"
|
||||
singular_name = "surgical tape"
|
||||
desc = "Made for patching broken bones back together alongside bone gel, not for playing pranks."
|
||||
//icon_state = "tape_spikes"
|
||||
prefix = "surgical"
|
||||
conferred_embed = list("embed_chance" = 30, "pain_mult" = 0, "jostle_pain_mult" = 0, "ignore_throwspeed_threshold" = TRUE)
|
||||
splint_factor = 0.4
|
||||
custom_price = 500
|
||||
|
||||
@@ -369,6 +369,7 @@
|
||||
new /obj/item/circular_saw(src)
|
||||
new /obj/item/surgicaldrill(src)
|
||||
new /obj/item/cautery(src)
|
||||
new /obj/item/bonesetter(src)
|
||||
new /obj/item/surgical_drapes(src)
|
||||
new /obj/item/clothing/mask/surgical(src)
|
||||
new /obj/item/reagent_containers/medspray/sterilizine(src)
|
||||
@@ -391,6 +392,7 @@
|
||||
new /obj/item/circular_saw(src)
|
||||
new /obj/item/surgicaldrill(src)
|
||||
new /obj/item/cautery(src)
|
||||
new /obj/item/bonesetter(src)
|
||||
new /obj/item/surgical_drapes(src)
|
||||
new /obj/item/clothing/mask/surgical(src)
|
||||
new /obj/item/reagent_containers/medspray/sterilizine(src)
|
||||
@@ -485,6 +487,7 @@
|
||||
new /obj/item/circular_saw(src)
|
||||
new /obj/item/surgicaldrill(src)
|
||||
new /obj/item/cautery(src)
|
||||
new /obj/item/bonesetter(src)
|
||||
new /obj/item/surgical_drapes(src)
|
||||
new /obj/item/clothing/suit/straight_jacket(src)
|
||||
new /obj/item/clothing/mask/muzzle(src)
|
||||
@@ -501,6 +504,7 @@
|
||||
new /obj/item/scalpel/advanced(src)
|
||||
new /obj/item/retractor/advanced(src)
|
||||
new /obj/item/surgicaldrill/advanced(src)
|
||||
new /obj/item/bonesetter(src)
|
||||
new /obj/item/surgical_drapes(src)
|
||||
new /obj/item/clothing/suit/straight_jacket(src)
|
||||
new /obj/item/clothing/mask/muzzle(src)
|
||||
|
||||
@@ -162,6 +162,7 @@
|
||||
/obj/item/surgical_drapes, //for true paramedics
|
||||
/obj/item/scalpel,
|
||||
/obj/item/circular_saw,
|
||||
/obj/item/bonesetter,
|
||||
/obj/item/surgicaldrill,
|
||||
/obj/item/retractor,
|
||||
/obj/item/cautery,
|
||||
@@ -181,7 +182,8 @@
|
||||
/obj/item/implant,
|
||||
/obj/item/implanter,
|
||||
/obj/item/pinpointer/crew,
|
||||
/obj/item/reagent_containers/chem_pack
|
||||
/obj/item/reagent_containers/chem_pack,
|
||||
/obj/item/stack/sticky_tape //surgical tape
|
||||
))
|
||||
|
||||
/obj/item/storage/belt/medical/surgery_belt_adv
|
||||
@@ -811,4 +813,3 @@
|
||||
attack_verb = list("bashed", "slashes", "prods", "pokes")
|
||||
fitting_swords = list(/obj/item/melee/rapier)
|
||||
starting_sword = /obj/item/melee/rapier
|
||||
|
||||
|
||||
@@ -398,6 +398,20 @@
|
||||
STR.max_items = 6
|
||||
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/nugget))
|
||||
|
||||
/obj/item/storage/fancy/cracker_pack
|
||||
name = "cracker pack"
|
||||
desc = "A pack of delicious crackers. Keep away from parrots!"
|
||||
icon = 'icons/obj/food/containers.dmi'
|
||||
icon_state = "crackerbox"
|
||||
icon_type = "cracker"
|
||||
spawn_type = /obj/item/reagent_containers/food/snacks/cracker
|
||||
|
||||
/obj/item/storage/fancy/cracker_pack/ComponentInitialize()
|
||||
. = ..()
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.max_items = 6
|
||||
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/cracker))
|
||||
|
||||
/*
|
||||
* Ring Box
|
||||
*/
|
||||
|
||||
@@ -41,9 +41,25 @@
|
||||
new /obj/item/stack/medical/suture(src)
|
||||
new /obj/item/stack/medical/mesh(src)
|
||||
new /obj/item/stack/medical/mesh(src)
|
||||
new /obj/item/reagent_containers/hypospray/medipen(src)
|
||||
new /obj/item/reagent_containers/hypospray/medipen/ekit(src)
|
||||
new /obj/item/healthanalyzer(src)
|
||||
|
||||
/obj/item/storage/firstaid/emergency
|
||||
icon_state = "medbriefcase"
|
||||
name = "emergency first-aid kit"
|
||||
desc = "A very simple first aid kit meant to secure and stabilize serious wounds for later treatment."
|
||||
|
||||
/obj/item/storage/firstaid/emergency/PopulateContents()
|
||||
if(empty)
|
||||
return
|
||||
var/static/items_inside = list(
|
||||
/obj/item/healthanalyzer/wound = 1,
|
||||
/obj/item/stack/medical/gauze = 1,
|
||||
/obj/item/stack/medical/suture/emergency = 1,
|
||||
/obj/item/stack/medical/ointment = 1,
|
||||
/obj/item/reagent_containers/hypospray/medipen/ekit = 2)
|
||||
generate_items_inside(items_inside,src)
|
||||
|
||||
/obj/item/storage/firstaid/ancient
|
||||
icon_state = "firstaid"
|
||||
desc = "A first aid kit with the ability to heal common types of injuries."
|
||||
@@ -435,6 +451,7 @@
|
||||
/obj/item/retractor,
|
||||
/obj/item/cautery,
|
||||
/obj/item/surgical_drapes,
|
||||
/obj/item/bonesetter,
|
||||
/obj/item/autosurgeon,
|
||||
/obj/item/organ,
|
||||
/obj/item/implant,
|
||||
|
||||
@@ -20,6 +20,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
|
||||
var/has_latches = TRUE
|
||||
var/can_rubberify = TRUE
|
||||
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //very protecc too
|
||||
wound_bonus = 5
|
||||
|
||||
/obj/item/storage/toolbox/greyscale
|
||||
icon_state = "toolbox_default"
|
||||
|
||||
@@ -143,7 +143,6 @@
|
||||
if(prob(50))
|
||||
step(W, pick(GLOB.alldirs))
|
||||
ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC)
|
||||
H.bleed_rate = 5
|
||||
H.gib_animation()
|
||||
sleep(3)
|
||||
H.adjustBruteLoss(1000) //to make the body super-bloody
|
||||
|
||||
@@ -574,6 +574,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
||||
force = 10
|
||||
wound_bonus = -10
|
||||
throwforce = 12
|
||||
attack_verb = list("beat", "smacked")
|
||||
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 3.5)
|
||||
@@ -626,7 +627,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
homerun_ready = 0
|
||||
return
|
||||
else if(!target.anchored)
|
||||
target.throw_at(throw_target, rand(1,2), 7, user)
|
||||
var/whack_speed = (prob(60) ? 1 : 4)
|
||||
target.throw_at(throw_target, rand(1, 2), whack_speed, user) // sorry friends, 7 speed batting caused wounds to absolutely delete whoever you knocked your target into (and said target)
|
||||
|
||||
/obj/item/melee/baseball_bat/ablative
|
||||
name = "metal baseball bat"
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
var/damtype = BRUTE
|
||||
var/force = 0
|
||||
|
||||
/// How good a given object is at causing wounds on carbons. Higher values equal better shots at creating serious wounds.
|
||||
var/wound_bonus = 0
|
||||
/// If this attacks a human with no wound armor on the affected body part, add this to the wound mod. Some attacks may be significantly worse at wounding if there's even a slight layer of armor to absorb some of it vs bare flesh
|
||||
var/bare_wound_bonus = 0
|
||||
|
||||
var/datum/armor/armor
|
||||
var/obj_integrity //defaults to max_integrity
|
||||
var/max_integrity = 500
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
switch(choice)
|
||||
if("Underwear")
|
||||
var/new_undies = input(H, "Select your underwear", "Changing") as null|anything in GLOB.underwear_list
|
||||
if(H.underwear)
|
||||
if(new_undies)
|
||||
H.underwear = new_undies
|
||||
H.saved_underwear = new_undies
|
||||
var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[new_undies]
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
if (QDELETED(head))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/weapons/bladeslice.ogg', 100, 1)
|
||||
playsound(src, 'sound/weapons/guillotine.ogg', 100, TRUE)
|
||||
if (blade_sharpness >= GUILLOTINE_DECAP_MIN_SHARP || head.brute_dam >= 100)
|
||||
head.dismember()
|
||||
log_combat(user, H, "beheaded", src)
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
/obj/structure/table/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/table/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
/obj/structure/table/attack_hand(mob/living/user)
|
||||
if(Adjacent(user) && user.pulling)
|
||||
if(isliving(user.pulling))
|
||||
var/mob/living/pushed_mob = user.pulling
|
||||
@@ -71,7 +71,10 @@
|
||||
if(user.grab_state < GRAB_AGGRESSIVE)
|
||||
to_chat(user, "<span class='warning'>You need a better grip to do that!</span>")
|
||||
return
|
||||
tablepush(user, pushed_mob)
|
||||
if(user.grab_state >= GRAB_NECK)
|
||||
tablelimbsmash(user, pushed_mob)
|
||||
else
|
||||
tablepush(user, pushed_mob)
|
||||
if(user.a_intent == INTENT_HELP)
|
||||
pushed_mob.visible_message("<span class='notice'>[user] begins to place [pushed_mob] onto [src]...</span>", \
|
||||
"<span class='userdanger'>[user] begins to place [pushed_mob] onto [src]...</span>")
|
||||
@@ -138,6 +141,22 @@
|
||||
H.emote("nya")
|
||||
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "table", /datum/mood_event/table)
|
||||
|
||||
/obj/structure/table/proc/tablelimbsmash(mob/living/user, mob/living/pushed_mob)
|
||||
pushed_mob.Knockdown(30)
|
||||
var/obj/item/bodypart/banged_limb = pushed_mob.get_bodypart(user.zone_selected) || pushed_mob.get_bodypart(BODY_ZONE_HEAD)
|
||||
var/extra_wound = 0
|
||||
if(HAS_TRAIT(user, TRAIT_HULK))
|
||||
extra_wound = 20
|
||||
banged_limb.receive_damage(30, wound_bonus = extra_wound)
|
||||
pushed_mob.apply_damage(60, STAMINA)
|
||||
take_damage(50)
|
||||
|
||||
playsound(pushed_mob, 'sound/effects/bang.ogg', 90, TRUE)
|
||||
pushed_mob.visible_message("<span class='danger'>[user] smashes [pushed_mob]'s [banged_limb.name] against \the [src]!</span>",
|
||||
"<span class='userdanger'>[user] smashes your [banged_limb.name] against \the [src]</span>")
|
||||
log_combat(user, pushed_mob, "head slammed", null, "against [src]")
|
||||
SEND_SIGNAL(pushed_mob, COMSIG_ADD_MOOD_EVENT, "table", /datum/mood_event/table_limbsmash, banged_limb)
|
||||
|
||||
/obj/structure/table/shove_act(mob/living/target, mob/living/user)
|
||||
if(CHECK_MOBILITY(target, MOBILITY_STAND))
|
||||
target.DefaultCombatKnockdown(SHOVE_KNOCKDOWN_TABLE)
|
||||
@@ -553,7 +572,7 @@
|
||||
change_construction_value(-2)
|
||||
return ..()
|
||||
|
||||
/obj/structure/table/reinforced/brass/tablepush(mob/living/user, mob/living/pushed_mob)
|
||||
/obj/structure/table/reinforced/brass/tablelimbsmash(mob/living/user, mob/living/pushed_mob)
|
||||
.= ..()
|
||||
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 50, TRUE)
|
||||
|
||||
@@ -577,7 +596,7 @@
|
||||
buildstack = /obj/item/stack/tile/bronze
|
||||
canSmoothWith = list(/obj/structure/table/reinforced/brass, /obj/structure/table/bronze)
|
||||
|
||||
/obj/structure/table/bronze/tablepush(mob/living/user, mob/living/pushed_mob)
|
||||
/obj/structure/table/bronze/tablelimbsmash(mob/living/user, mob/living/pushed_mob)
|
||||
..()
|
||||
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 50, TRUE)
|
||||
|
||||
@@ -606,7 +625,7 @@
|
||||
computer.table = src
|
||||
break
|
||||
|
||||
/obj/structure/table/optable/tablepush(mob/living/user, mob/living/pushed_mob)
|
||||
/obj/structure/table/optable/tablelimbsmash(mob/living/user, mob/living/pushed_mob)
|
||||
pushed_mob.forceMove(loc)
|
||||
pushed_mob.set_resting(TRUE, TRUE)
|
||||
visible_message("<span class='notice'>[user] has laid [pushed_mob] on [src].</span>")
|
||||
|
||||
@@ -863,7 +863,7 @@
|
||||
if(jobban_isbanned(M, ROLE_TRAITOR) || isbanned_dept)
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=traitor;jobban4=[REF(M)]'><font color=red>Traitor</font></a></td>"
|
||||
else
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];jobban3=traitor;jobban4=[REF(M)]'>Traitor</a></td>"
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=traitor;jobban4=[REF(M)]'>Traitor</a></td>"
|
||||
|
||||
//Changeling
|
||||
if(jobban_isbanned(M, ROLE_CHANGELING) || isbanned_dept)
|
||||
|
||||
@@ -1281,7 +1281,11 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
ADMIN_PUNISHMENT_MAZING,
|
||||
ADMIN_PUNISHMENT_ROD,
|
||||
ADMIN_PUNISHMENT_PICKLE,
|
||||
ADMIN_PUNISHMENT_FRY)
|
||||
ADMIN_PUNISHMENT_FRY,
|
||||
ADMIN_PUNISHMENT_CRACK,
|
||||
ADMIN_PUNISHMENT_BLEED,
|
||||
ADMIN_PUNISHMENT_SCARIFY)
|
||||
|
||||
|
||||
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
|
||||
|
||||
@@ -1359,6 +1363,33 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
if(amount)
|
||||
A.reagents.add_reagent(chosen_id, amount)
|
||||
A.splat(target)
|
||||
if(ADMIN_PUNISHMENT_CRACK)
|
||||
if(!iscarbon(target))
|
||||
to_chat(usr,"<span class='warning'>This must be used on a carbon mob.</span>", confidential = TRUE)
|
||||
return
|
||||
var/mob/living/carbon/C = target
|
||||
for(var/obj/item/bodypart/squish_part in C.bodyparts)
|
||||
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))
|
||||
squish_part.force_wound_upwards(type_wound, smited=TRUE)
|
||||
if(ADMIN_PUNISHMENT_BLEED)
|
||||
if(!iscarbon(target))
|
||||
to_chat(usr,"<span class='warning'>This must be used on a carbon mob.</span>", confidential = TRUE)
|
||||
return
|
||||
var/mob/living/carbon/C = target
|
||||
for(var/obj/item/bodypart/slice_part in C.bodyparts)
|
||||
var/type_wound = pick(list(/datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate))
|
||||
slice_part.force_wound_upwards(type_wound, smited=TRUE)
|
||||
type_wound = pick(list(/datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate))
|
||||
slice_part.force_wound_upwards(type_wound, smited=TRUE)
|
||||
type_wound = pick(list(/datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe))
|
||||
slice_part.force_wound_upwards(type_wound, smited=TRUE)
|
||||
if(ADMIN_PUNISHMENT_SCARIFY)
|
||||
if(!iscarbon(target))
|
||||
to_chat(usr,"<span class='warning'>This must be used on a carbon mob.</span>", confidential = TRUE)
|
||||
return
|
||||
var/mob/living/carbon/C = target
|
||||
C.generate_fake_scars(rand(1, 4))
|
||||
to_chat(C, "<span class='warning'>You feel your body grow jaded and torn...</span>")
|
||||
if(ADMIN_PUNISHMENT_PICKLE)
|
||||
target.turn_into_pickle()
|
||||
if(ADMIN_PUNISHMENT_FRY)
|
||||
|
||||
@@ -36,6 +36,6 @@
|
||||
M.adjust_fire_stacks(round(reac_volume/10))
|
||||
M.IgniteMob()
|
||||
if(M)
|
||||
M.apply_damage(0.8*reac_volume, BURN)
|
||||
M.apply_damage(0.8*reac_volume, BURN, wound_bonus=CANT_WOUND)
|
||||
if(iscarbon(M))
|
||||
M.emote("scream")
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
M.reagents.add_reagent("frostoil", 0.3*reac_volume)
|
||||
M.reagents.add_reagent("ice", 0.3*reac_volume)
|
||||
M.reagents.add_reagent("cryogenic_poison", 0.3*reac_volume)
|
||||
M.apply_damage(0.2*reac_volume, BRUTE)
|
||||
M.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
|
||||
/datum/reagent/blob/cryogenic_poison/on_mob_life(mob/living/carbon/M)
|
||||
M.adjustBruteLoss(0.3*REAGENTS_EFFECT_MULTIPLIER, 0)
|
||||
|
||||
@@ -30,4 +30,4 @@
|
||||
if(prob(reac_volume*2))
|
||||
M.emp_act(EMP_LIGHT)
|
||||
if(M)
|
||||
M.apply_damage(reac_volume, BURN)
|
||||
M.apply_damage(reac_volume, BURN, wound_bonus=CANT_WOUND)
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
if(ROLE_BLOB in L.faction) //no friendly fire
|
||||
continue
|
||||
var/aoe_volume = ..(L, TOUCH, initial_volume, 0, L.get_permeability_protection(), O)
|
||||
L.apply_damage(0.4*aoe_volume, BRUTE)
|
||||
L.apply_damage(0.4*aoe_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
if(M)
|
||||
M.apply_damage(0.6*reac_volume, BRUTE)
|
||||
M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
else
|
||||
M.apply_damage(0.6*reac_volume, BRUTE)
|
||||
M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
|
||||
@@ -33,6 +33,6 @@
|
||||
|
||||
/datum/reagent/blob/networked_fibers/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
|
||||
reac_volume = ..()
|
||||
M.apply_damage(0.6*reac_volume, BRUTE)
|
||||
M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
if(M)
|
||||
M.apply_damage(0.6*reac_volume, BURN)
|
||||
M.apply_damage(0.6*reac_volume, BURN, wound_bonus=CANT_WOUND)
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS)
|
||||
M.adjust_fire_stacks(-(reac_volume / 10))
|
||||
M.ExtinguishMob()
|
||||
M.apply_damage(0.4*reac_volume, BRUTE)
|
||||
M.apply_damage(0.4*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
if(M)
|
||||
M.apply_damage(0.4*reac_volume, OXY)
|
||||
if(M)
|
||||
|
||||
@@ -31,4 +31,4 @@
|
||||
|
||||
/datum/reagent/blob/replicating_foam/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
|
||||
reac_volume = ..()
|
||||
M.apply_damage(0.7*reac_volume, BRUTE)
|
||||
M.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
|
||||
@@ -32,4 +32,4 @@
|
||||
|
||||
/datum/reagent/blob/shifting_fragments/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
|
||||
reac_volume = ..()
|
||||
M.apply_damage(0.7*reac_volume, BRUTE)
|
||||
M.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
|
||||
/datum/reagent/blob/synchronous_mesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
|
||||
reac_volume = ..()
|
||||
M.apply_damage(0.2*reac_volume, BRUTE)
|
||||
M.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
if(M && reac_volume)
|
||||
for(var/obj/structure/blob/B in range(1, M)) //if the target is completely surrounded, this is 2.4*reac_volume bonus damage, total of 2.6*reac_volume
|
||||
if(M)
|
||||
B.blob_attack_animation(M) //show them they're getting a bad time
|
||||
M.apply_damage(0.3*reac_volume, BRUTE)
|
||||
M.apply_damage(0.3*reac_volume, BRUTE, wound_bonus=CANT_WOUND)
|
||||
|
||||
@@ -226,7 +226,9 @@
|
||||
playsound(get_turf(target), 'sound/effects/splat.ogg', 40, 1)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.bleed_rate += 5
|
||||
var/obj/item/bodypart/head_part = H.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(head_part)
|
||||
head_part.generic_bleedstacks += 5
|
||||
target.add_splatter_floor(get_turf(target))
|
||||
user.add_mob_blood(target) // Put target's blood on us. The donor goes in the ( )
|
||||
target.add_mob_blood(target)
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
C.blood_volume -= 0.2
|
||||
C.adjustStaminaLoss(-15)
|
||||
// Stop Bleeding
|
||||
if(istype(H) && H.bleed_rate > 0 && rand(20) == 0)
|
||||
H.bleed_rate --
|
||||
if(istype(H) && H.is_bleeding() && rand(20) == 0)
|
||||
for(var/obj/item/bodypart/part in H.bodyparts)
|
||||
part.generic_bleedstacks --
|
||||
C.Jitter(5)
|
||||
sleep(10)
|
||||
// DONE!
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
var/datum/changelingprofile/first_prof = null
|
||||
var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation.
|
||||
var/absorbedcount = 0
|
||||
/// did we get succed by another changeling
|
||||
var/hostile_absorbed = FALSE
|
||||
var/trueabsorbs = 0//dna gained using absorb, not dna sting
|
||||
var/chem_charges = 20
|
||||
var/chem_storage = 75
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
|
||||
|
||||
var/datum/antagonist/changeling/target_ling = target.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(target_ling)//If the target was a changeling, suck out their extra juice and objective points!
|
||||
if(target_ling && !target_ling.hostile_absorbed)//If the target was a changeling, suck out their extra juice and objective points!
|
||||
to_chat(user, "<span class='boldnotice'>[target] was one of us. We have absorbed their power.</span>")
|
||||
target_ling.remove_changeling_powers()
|
||||
changeling.geneticpoints += round(target_ling.geneticpoints/2)
|
||||
@@ -102,6 +102,7 @@
|
||||
changeling.chem_storage += round(target_ling.chem_storage/2)
|
||||
changeling.chem_charges += min(target_ling.chem_charges, changeling.chem_storage)
|
||||
target_ling.chem_charges = 0
|
||||
target_ling.hostile_absorbed = TRUE
|
||||
target_ling.chem_storage = 0
|
||||
changeling.absorbedcount += (target_ling.absorbedcount)
|
||||
target_ling.stored_profiles.len = 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/effect/proc_holder/changeling/fleshmend
|
||||
name = "Fleshmend"
|
||||
desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath. Functions while unconscious. This ability is loud, and might cause our blood to react violently to heat."
|
||||
desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath, as well as hiding all of our scars. Costs 20 chemicals."
|
||||
helptext = "If we are on fire, the healing effect will not function. Does not regrow limbs or restore lost blood."
|
||||
chemical_cost = 20
|
||||
loudness = 2
|
||||
|
||||
@@ -165,6 +165,8 @@
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
sharpness = IS_SHARP
|
||||
wound_bonus = -60
|
||||
bare_wound_bonus = 20
|
||||
var/can_drop = FALSE
|
||||
var/fake = FALSE
|
||||
total_mass = TOTAL_MASS_HAND_REPLACEMENT
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
C.emote("scream")
|
||||
C.regenerate_limbs(1)
|
||||
C.regenerate_organs()
|
||||
for(var/i in C.all_wounds)
|
||||
var/datum/wound/W = i
|
||||
W.remove_wound()
|
||||
if(!user.getorganslot(ORGAN_SLOT_BRAIN))
|
||||
var/obj/item/organ/brain/B
|
||||
if(C.has_dna() && C.dna.species.mutant_brain)
|
||||
|
||||
@@ -36,9 +36,10 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(user, CHANGELING_DRAIN) || ((user.stat != DEAD) && !(HAS_TRAIT(user, TRAIT_DEATHCOMA))))
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!changeling)
|
||||
return FALSE
|
||||
if(changeling.hostile_absorbed || ((user.stat != DEAD) && !(HAS_TRAIT(user, TRAIT_DEATHCOMA))))
|
||||
changeling.purchasedpowers -= src
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
force = 15
|
||||
throwforce = 25
|
||||
wound_bonus = -30
|
||||
bare_wound_bonus = 30
|
||||
armour_penetration = 35
|
||||
actions_types = list(/datum/action/item_action/cult_dagger)
|
||||
|
||||
@@ -53,8 +55,10 @@
|
||||
flags_1 = CONDUCT_1
|
||||
sharpness = IS_SHARP
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 30
|
||||
force = 30 // whoever balanced this got beat in the head by a bible too many times good lord
|
||||
throwforce = 10
|
||||
wound_bonus = -80
|
||||
bare_wound_bonus = 30
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "rended")
|
||||
|
||||
|
||||
@@ -34,8 +34,11 @@
|
||||
healable = 0
|
||||
environment_smash = ENVIRONMENT_SMASH_STRUCTURES
|
||||
obj_damage = 50
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
melee_damage_lower = 22.5 // reduced from 30 to 22.5 with wounds since they get big buffs to slicing wounds
|
||||
melee_damage_upper = 22.5
|
||||
wound_bonus = -10
|
||||
bare_wound_bonus = 0
|
||||
sharpness = TRUE
|
||||
see_in_dark = 8
|
||||
blood_volume = 0 //No bleeding on getting shot, for skeddadles
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
@@ -43,13 +46,25 @@
|
||||
var/playstyle_string = "<span class='big bold'>You are a slaughter demon,</span><B> a terrible creature from another realm. You have a single desire: To kill. \
|
||||
You may use the \"Blood Crawl\" ability near blood pools to travel through them, appearing and disappearing from the station at will. \
|
||||
Pulling a dead or unconscious mob while you enter a pool will pull them in with you, allowing you to feast and regain your health. \
|
||||
You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. </B>"
|
||||
You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. \
|
||||
You gain strength the more attacks you land on live humanoids, though this resets when you return to the blood zone. You can also \
|
||||
launch a devastating slam attack with ctrl+shift+click, capable of smashing bones in one strike.</B>"
|
||||
|
||||
loot = list(/obj/effect/decal/cleanable/blood, \
|
||||
/obj/effect/decal/cleanable/blood/innards, \
|
||||
/obj/item/organ/heart/demon)
|
||||
del_on_death = 1
|
||||
deathmessage = "screams in anger as it collapses into a puddle of viscera!"
|
||||
// How long it takes for the alt-click slam attack to come off cooldown
|
||||
var/slam_cooldown_time = 45 SECONDS
|
||||
// The actual instance var for the cooldown
|
||||
var/slam_cooldown = 0
|
||||
// How many times we have hit humanoid targets since we last bloodcrawled, scaling wounding power
|
||||
var/current_hitstreak = 0
|
||||
// How much both our wound_bonus and bare_wound_bonus go up per hitstreak hit
|
||||
var/wound_bonus_per_hit = 5
|
||||
// How much our wound_bonus hitstreak bonus caps at (peak demonry)
|
||||
var/wound_bonus_hitstreak_max = 12
|
||||
|
||||
/mob/living/simple_animal/slaughter/Initialize()
|
||||
..()
|
||||
@@ -58,6 +73,33 @@
|
||||
if(istype(loc, /obj/effect/dummy/phased_mob/slaughter))
|
||||
bloodspell.phased = TRUE
|
||||
|
||||
/mob/living/simple_animal/slaughter/CtrlShiftClickOn(atom/A)
|
||||
if(!isliving(A))
|
||||
return ..()
|
||||
if(slam_cooldown + slam_cooldown_time > world.time)
|
||||
to_chat(src, "<span class='warning'>Your slam ability is still on cooldown!</span>")
|
||||
return
|
||||
|
||||
face_atom(A)
|
||||
var/mob/living/victim = A
|
||||
victim.take_bodypart_damage(brute=20, wound_bonus=wound_bonus) // don't worry, there's more punishment when they hit something
|
||||
visible_message("<span class='danger'>[src] slams into [victim] with monstrous strength!</span>", "<span class='danger'>You slam into [victim] with monstrous strength!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[src] slams into you with monstrous strength, sending you flying like a ragdoll!</span>")
|
||||
var/turf/yeet_target = get_edge_target_turf(victim, dir)
|
||||
victim.throw_at(yeet_target, 10, 5, src)
|
||||
slam_cooldown = world.time
|
||||
log_combat(src, victim, "slaughter slammed")
|
||||
|
||||
/mob/living/simple_animal/slaughter/UnarmedAttack(atom/A, proximity)
|
||||
if(iscarbon(A))
|
||||
var/mob/living/carbon/target = A
|
||||
if(target.stat != DEAD && target.mind && current_hitstreak < wound_bonus_hitstreak_max)
|
||||
current_hitstreak++
|
||||
wound_bonus += wound_bonus_per_hit
|
||||
bare_wound_bonus += wound_bonus_per_hit
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/innards
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
name = "pile of viscera"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
/datum/antagonist/slaughter/greet()
|
||||
. = ..()
|
||||
owner.announce_objectives()
|
||||
to_chat(owner, "<span class='warning'>You have a powerful alt-attack that slams people backwards that you can activate by shift+ctrl+clicking your target!</span>")
|
||||
|
||||
/datum/antagonist/slaughter/proc/forge_objectives()
|
||||
if(summoner)
|
||||
|
||||
@@ -43,6 +43,12 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
|
||||
var/list/dummy = get_gases()
|
||||
for(var/gas in dummy)
|
||||
dummy[gas] = get_moles(gas)
|
||||
dummy["TEMP"] = return_temperature()
|
||||
dummy["PRESSURE"] = return_pressure()
|
||||
dummy["HEAT CAPACITY"] = heat_capacity()
|
||||
dummy["TOTAL MOLES"] = total_moles()
|
||||
dummy["VOLUME"] = return_volume()
|
||||
dummy["THERMAL ENERGY"] = thermal_energy()
|
||||
return debug_variable("gases (READ ONLY)", dummy, 0, src)
|
||||
|
||||
/datum/gas_mixture/vv_get_dropdown()
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
var/escape_in_progress = FALSE
|
||||
var/message_cooldown
|
||||
var/breakout_time = 300
|
||||
///Cryo will continue to treat people with 0 damage but existing wounds, but will sound off when damage healing is done in case doctors want to directly treat the wounds instead
|
||||
var/treating_wounds = FALSE
|
||||
|
||||
fair_market_price = 10
|
||||
payment_department = ACCOUNT_MED
|
||||
@@ -174,15 +176,27 @@
|
||||
return
|
||||
|
||||
if(mob_occupant.health >= mob_occupant.getMaxHealth()) // Don't bother with fully healed people.
|
||||
on = FALSE
|
||||
update_icon()
|
||||
playsound(src, 'sound/machines/cryo_warning.ogg', volume) // Bug the doctors.
|
||||
var/msg = "Patient fully restored."
|
||||
if(autoeject) // Eject if configured.
|
||||
msg += " Auto ejecting patient now."
|
||||
open_machine()
|
||||
radio.talk_into(src, msg, radio_channel)
|
||||
return
|
||||
if(iscarbon(mob_occupant))
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
if(C.all_wounds)
|
||||
if(!treating_wounds) // if we have wounds and haven't already alerted the doctors we're only dealing with the wounds, let them know
|
||||
treating_wounds = TRUE
|
||||
playsound(src, 'sound/machines/cryo_warning.ogg', volume) // Bug the doctors.
|
||||
var/msg = "Patient vitals fully recovered, continuing automated wound treatment."
|
||||
radio.talk_into(src, msg, radio_channel)
|
||||
else // otherwise if we were only treating wounds and now we don't have any, turn off treating_wounds so we can boot 'em out
|
||||
treating_wounds = FALSE
|
||||
|
||||
if(!treating_wounds)
|
||||
on = FALSE
|
||||
update_icon()
|
||||
playsound(src, 'sound/machines/cryo_warning.ogg', volume) // Bug the doctors.
|
||||
var/msg = "Patient fully restored."
|
||||
if(autoeject) // Eject if configured.
|
||||
msg += " Auto ejecting patient now."
|
||||
open_machine()
|
||||
radio.talk_into(src, msg, radio_channel)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/air1 = airs[1]
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
/datum/export/robotics/surgery_gear_basic
|
||||
cost = 10
|
||||
unit_name = "surgery tool"
|
||||
export_types = list(/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, /obj/item/surgical_drapes)
|
||||
export_types = list(/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, /obj/item/bonesetter, /obj/item/surgical_drapes)
|
||||
|
||||
/datum/export/robotics/mech_weapon_laser
|
||||
cost = 300 //Sadly just metal and glass
|
||||
|
||||
@@ -75,3 +75,9 @@
|
||||
desc = "The simple beach ball is one of Nanotrasen's most popular products. 'Why do we make beach balls? Because we can! (TM)' - Nanotrasen"
|
||||
cost = 200
|
||||
contains = list(/obj/item/toy/beach_ball)
|
||||
|
||||
/datum/supply_pack/goody/hell_single
|
||||
name = "Hellgun Single-Pack"
|
||||
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)
|
||||
|
||||
@@ -114,7 +114,9 @@
|
||||
/obj/item/storage/box/medsprays,
|
||||
/obj/item/storage/box/syringes,
|
||||
/obj/item/storage/box/bodybags,
|
||||
/obj/item/storage/pill_bottle/stimulant)
|
||||
/obj/item/storage/pill_bottle/stimulant,
|
||||
/obj/item/stack/medical/bone_gel,
|
||||
/obj/item/stack/medical/bone_gel)
|
||||
crate_name = "medical supplies crate"
|
||||
|
||||
/datum/supply_pack/medical/adv_surgery_tools
|
||||
|
||||
@@ -83,24 +83,24 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/gender = MALE //gender of character (well duh)
|
||||
var/age = 30 //age of character
|
||||
var/underwear = "Nude" //underwear type
|
||||
var/undie_color = "FFF"
|
||||
var/undie_color = "FFFFFF"
|
||||
var/undershirt = "Nude" //undershirt type
|
||||
var/shirt_color = "FFF"
|
||||
var/shirt_color = "FFFFFF"
|
||||
var/socks = "Nude" //socks type
|
||||
var/socks_color = "FFF"
|
||||
var/socks_color = "FFFFFF"
|
||||
var/backbag = DBACKPACK //backpack type
|
||||
var/jumpsuit_style = PREF_SUIT //suit/skirt
|
||||
var/hair_style = "Bald" //Hair type
|
||||
var/hair_color = "000" //Hair color
|
||||
var/hair_color = "000000" //Hair color
|
||||
var/facial_hair_style = "Shaved" //Face hair type
|
||||
var/facial_hair_color = "000" //Facial hair color
|
||||
var/facial_hair_color = "000000" //Facial hair color
|
||||
var/skin_tone = "caucasian1" //Skin color
|
||||
var/use_custom_skin_tone = FALSE
|
||||
var/eye_color = "000" //Eye color
|
||||
var/eye_color = "000000" //Eye color
|
||||
var/datum/species/pref_species = new /datum/species/human() //Mutant race
|
||||
var/list/features = list("mcolor" = "FFF",
|
||||
"mcolor2" = "FFF",
|
||||
"mcolor3" = "FFF",
|
||||
var/list/features = list("mcolor" = "FFFFFF",
|
||||
"mcolor2" = "FFFFFF",
|
||||
"mcolor3" = "FFFFFF",
|
||||
"tail_lizard" = "Smooth",
|
||||
"tail_human" = "None",
|
||||
"snout" = "Round",
|
||||
@@ -131,23 +131,23 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
"cock_shape" = DEF_COCK_SHAPE,
|
||||
"cock_length" = COCK_SIZE_DEF,
|
||||
"cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF,
|
||||
"cock_color" = "fff",
|
||||
"cock_color" = "ffffff",
|
||||
"cock_taur" = FALSE,
|
||||
"has_balls" = FALSE,
|
||||
"balls_color" = "fff",
|
||||
"balls_color" = "ffffff",
|
||||
"balls_shape" = DEF_BALLS_SHAPE,
|
||||
"balls_size" = BALLS_SIZE_DEF,
|
||||
"balls_cum_rate" = CUM_RATE,
|
||||
"balls_cum_mult" = CUM_RATE_MULT,
|
||||
"balls_efficiency" = CUM_EFFICIENCY,
|
||||
"has_breasts" = FALSE,
|
||||
"breasts_color" = "fff",
|
||||
"breasts_color" = "ffffff",
|
||||
"breasts_size" = BREASTS_SIZE_DEF,
|
||||
"breasts_shape" = DEF_BREASTS_SHAPE,
|
||||
"breasts_producing" = FALSE,
|
||||
"has_vag" = FALSE,
|
||||
"vag_shape" = DEF_VAGINA_SHAPE,
|
||||
"vag_color" = "fff",
|
||||
"vag_color" = "ffffff",
|
||||
"has_womb" = FALSE,
|
||||
"balls_visibility" = GEN_VISIBLE_NO_UNDIES,
|
||||
"breasts_visibility"= GEN_VISIBLE_NO_UNDIES,
|
||||
@@ -239,6 +239,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/autostand = TRUE
|
||||
var/auto_ooc = FALSE
|
||||
|
||||
/// If we have persistent scars enabled
|
||||
var/persistent_scars = TRUE
|
||||
/// We have 5 slots for persistent scars, if enabled we pick a random one to load (empty by default) and scars at the end of the shift if we survived as our original person
|
||||
var/list/scars_list = list("1" = "", "2" = "", "3" = "", "4" = "", "5" = "")
|
||||
/// Which of the 5 persistent scar slots we randomly roll to load for this round, if enabled. Actually rolled in [/datum/preferences/proc/load_character(slot)]
|
||||
var/scars_index = 1
|
||||
|
||||
/datum/preferences/New(client/C)
|
||||
parent = C
|
||||
|
||||
@@ -825,6 +832,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Socks Color:</b> <span style='border:1px solid #161616; background-color: #[socks_color];'> </span> <a href='?_src_=prefs;preference=socks_color;task=input'>Change</a><BR>"
|
||||
dat += "<b>Backpack:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=bag;task=input'>[backbag]</a>"
|
||||
dat += "<b>Jumpsuit:</b><BR><a href ='?_src_=prefs;preference=suit;task=input'>[jumpsuit_style]</a><BR>"
|
||||
if(CAN_SCAR in pref_species.species_traits)
|
||||
dat += "<BR><b>Temporal Scarring:</b><BR><a href='?_src_=prefs;preference=persistent_scars'>[(persistent_scars) ? "Enabled" : "Disabled"]</A>"
|
||||
dat += "<a href='?_src_=prefs;preference=clear_scars'>Clear scar slots</A>"
|
||||
dat += "<b>Uplink Location:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=uplink_loc;task=input'>[uplink_spawn_loc]</a>"
|
||||
dat += "</td>"
|
||||
|
||||
@@ -1697,7 +1707,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("hair")
|
||||
var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference","#"+hair_color) as color|null
|
||||
if(new_hair)
|
||||
hair_color = sanitize_hexcolor(new_hair)
|
||||
hair_color = sanitize_hexcolor(new_hair, 6)
|
||||
|
||||
if("hair_style")
|
||||
var/new_hair_style
|
||||
@@ -1714,7 +1724,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("facial")
|
||||
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference","#"+facial_hair_color) as color|null
|
||||
if(new_facial)
|
||||
facial_hair_color = sanitize_hexcolor(new_facial)
|
||||
facial_hair_color = sanitize_hexcolor(new_facial, 6)
|
||||
|
||||
if("facial_hair_style")
|
||||
var/new_facial_hair_style
|
||||
@@ -1739,7 +1749,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("undie_color")
|
||||
var/n_undie_color = input(user, "Choose your underwear's color.", "Character Preference", "#[undie_color]") as color|null
|
||||
if(n_undie_color)
|
||||
undie_color = sanitize_hexcolor(n_undie_color)
|
||||
undie_color = sanitize_hexcolor(n_undie_color, 6)
|
||||
|
||||
if("undershirt")
|
||||
var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_list
|
||||
@@ -1749,7 +1759,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("shirt_color")
|
||||
var/n_shirt_color = input(user, "Choose your undershirt's color.", "Character Preference", "#[shirt_color]") as color|null
|
||||
if(n_shirt_color)
|
||||
shirt_color = sanitize_hexcolor(n_shirt_color)
|
||||
shirt_color = sanitize_hexcolor(n_shirt_color, 6)
|
||||
|
||||
if("socks")
|
||||
var/new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in GLOB.socks_list
|
||||
@@ -1759,12 +1769,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("socks_color")
|
||||
var/n_socks_color = input(user, "Choose your socks' color.", "Character Preference", "#[socks_color]") as color|null
|
||||
if(n_socks_color)
|
||||
socks_color = sanitize_hexcolor(n_socks_color)
|
||||
socks_color = sanitize_hexcolor(n_socks_color, 6)
|
||||
|
||||
if("eyes")
|
||||
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+eye_color) as color|null
|
||||
if(new_eyes)
|
||||
eye_color = sanitize_hexcolor(new_eyes)
|
||||
eye_color = sanitize_hexcolor(new_eyes, 6)
|
||||
|
||||
if("species")
|
||||
var/result = input(user, "Select a species", "Species Selection") as null|anything in GLOB.roundstart_race_names
|
||||
@@ -1809,7 +1819,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_mutantcolor == "#000000")
|
||||
features["mcolor"] = pref_species.default_color
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin
|
||||
features["mcolor"] = sanitize_hexcolor(new_mutantcolor)
|
||||
features["mcolor"] = sanitize_hexcolor(new_mutantcolor, 6)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -1820,7 +1830,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_mutantcolor == "#000000")
|
||||
features["mcolor2"] = pref_species.default_color
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin
|
||||
features["mcolor2"] = sanitize_hexcolor(new_mutantcolor)
|
||||
features["mcolor2"] = sanitize_hexcolor(new_mutantcolor, 6)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -1831,7 +1841,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_mutantcolor == "#000000")
|
||||
features["mcolor3"] = pref_species.default_color
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin
|
||||
features["mcolor3"] = sanitize_hexcolor(new_mutantcolor)
|
||||
features["mcolor3"] = sanitize_hexcolor(new_mutantcolor, 6)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -1959,7 +1969,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if (new_horn_color == "#000000")
|
||||
features["horns_color"] = "85615A"
|
||||
else
|
||||
features["horns_color"] = sanitize_hexcolor(new_horn_color)
|
||||
features["horns_color"] = sanitize_hexcolor(new_horn_color, 6)
|
||||
|
||||
if("wings")
|
||||
var/new_wings
|
||||
@@ -1973,7 +1983,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if (new_wing_color == "#000000")
|
||||
features["wings_color"] = "#FFFFFF"
|
||||
else
|
||||
features["wings_color"] = sanitize_hexcolor(new_wing_color)
|
||||
features["wings_color"] = sanitize_hexcolor(new_wing_color, 6)
|
||||
|
||||
if("frills")
|
||||
var/new_frills
|
||||
@@ -2147,7 +2157,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_cockcolor == "#000000")
|
||||
features["cock_color"] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["cock_color"] = sanitize_hexcolor(new_cockcolor)
|
||||
features["cock_color"] = sanitize_hexcolor(new_cockcolor, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -2187,7 +2197,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_ballscolor == "#000000")
|
||||
features["balls_color"] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["balls_color"] = sanitize_hexcolor(new_ballscolor)
|
||||
features["balls_color"] = sanitize_hexcolor(new_ballscolor, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -2214,7 +2224,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_breasts_color == "#000000")
|
||||
features["breasts_color"] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["breasts_color"] = sanitize_hexcolor(new_breasts_color)
|
||||
features["breasts_color"] = sanitize_hexcolor(new_breasts_color, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -2236,7 +2246,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_vagcolor == "#000000")
|
||||
features["vag_color"] = pref_species.default_color
|
||||
else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["vag_color"] = sanitize_hexcolor(new_vagcolor)
|
||||
features["vag_color"] = sanitize_hexcolor(new_vagcolor, 6)
|
||||
else
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -2545,6 +2555,17 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("hear_midis")
|
||||
toggles ^= SOUND_MIDI
|
||||
|
||||
if("persistent_scars")
|
||||
persistent_scars = !persistent_scars
|
||||
|
||||
if("clear_scars")
|
||||
to_chat(user, "<span class='notice'>All scar slots cleared. Please save character to confirm.</span>")
|
||||
scars_list["1"] = ""
|
||||
scars_list["2"] = ""
|
||||
scars_list["3"] = ""
|
||||
scars_list["4"] = ""
|
||||
scars_list["5"] = ""
|
||||
|
||||
if("lobby_music")
|
||||
toggles ^= SOUND_LOBBY
|
||||
if((toggles & SOUND_LOBBY) && user.client && isnewplayer(user))
|
||||
|
||||
@@ -224,6 +224,8 @@ 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
|
||||
S["ooccolor"] >> ooccolor
|
||||
@@ -440,6 +442,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
if(needs_update == -2) //fatal, can't load any data
|
||||
return 0
|
||||
|
||||
. = TRUE
|
||||
|
||||
//Species
|
||||
var/species_id
|
||||
S["species"] >> species_id
|
||||
@@ -453,6 +457,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
if(newtype)
|
||||
pref_species = new newtype
|
||||
|
||||
|
||||
scars_index = rand(1,5)
|
||||
|
||||
//Character
|
||||
S["real_name"] >> real_name
|
||||
S["nameless"] >> nameless
|
||||
@@ -497,6 +504,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["feature_insect_markings"] >> features["insect_markings"]
|
||||
S["feature_horns_color"] >> features["horns_color"]
|
||||
S["feature_wings_color"] >> features["wings_color"]
|
||||
S["persistent_scars"] >> persistent_scars
|
||||
S["scars1"] >> scars_list["1"]
|
||||
S["scars2"] >> scars_list["2"]
|
||||
S["scars3"] >> scars_list["3"]
|
||||
S["scars4"] >> scars_list["4"]
|
||||
S["scars5"] >> scars_list["5"]
|
||||
|
||||
|
||||
//Custom names
|
||||
@@ -623,14 +636,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_list)
|
||||
underwear = sanitize_inlist(underwear, GLOB.underwear_list)
|
||||
undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list)
|
||||
undie_color = sanitize_hexcolor(undie_color, 3, FALSE, initial(undie_color))
|
||||
shirt_color = sanitize_hexcolor(shirt_color, 3, FALSE, initial(shirt_color))
|
||||
undie_color = sanitize_hexcolor(undie_color, 6, FALSE, initial(undie_color))
|
||||
shirt_color = sanitize_hexcolor(shirt_color, 6, FALSE, initial(shirt_color))
|
||||
socks = sanitize_inlist(socks, GLOB.socks_list)
|
||||
socks_color = sanitize_hexcolor(socks_color, 3, FALSE, initial(socks_color))
|
||||
socks_color = sanitize_hexcolor(socks_color, 6, FALSE, initial(socks_color))
|
||||
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
|
||||
hair_color = sanitize_hexcolor(hair_color, 3, 0)
|
||||
facial_hair_color = sanitize_hexcolor(facial_hair_color, 3, 0)
|
||||
eye_color = sanitize_hexcolor(eye_color, 3, 0)
|
||||
hair_color = sanitize_hexcolor(hair_color, 6, FALSE)
|
||||
facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE)
|
||||
eye_color = sanitize_hexcolor(eye_color, 6, FALSE)
|
||||
|
||||
var/static/allow_custom_skintones
|
||||
if(isnull(allow_custom_skintones))
|
||||
@@ -641,12 +654,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
else
|
||||
skin_tone = sanitize_inlist(skin_tone, GLOB.skin_tones - GLOB.nonstandard_skin_tones, initial(skin_tone))
|
||||
|
||||
features["horns_color"] = sanitize_hexcolor(features["horns_color"], 3, FALSE, "85615a")
|
||||
features["wings_color"] = sanitize_hexcolor(features["wings_color"], 3, FALSE, "FFFFFF")
|
||||
features["horns_color"] = sanitize_hexcolor(features["horns_color"], 6, FALSE, "85615a")
|
||||
features["wings_color"] = sanitize_hexcolor(features["wings_color"], 6, FALSE, "FFFFFF")
|
||||
backbag = sanitize_inlist(backbag, GLOB.backbaglist, initial(backbag))
|
||||
jumpsuit_style = sanitize_inlist(jumpsuit_style, GLOB.jumpsuitlist, initial(jumpsuit_style))
|
||||
uplink_spawn_loc = sanitize_inlist(uplink_spawn_loc, GLOB.uplink_spawn_loc_list, initial(uplink_spawn_loc))
|
||||
features["mcolor"] = sanitize_hexcolor(features["mcolor"], 3, 0)
|
||||
features["mcolor"] = sanitize_hexcolor(features["mcolor"], 6, FALSE)
|
||||
features["tail_lizard"] = sanitize_inlist(features["tail_lizard"], GLOB.tails_list_lizard)
|
||||
features["tail_human"] = sanitize_inlist(features["tail_human"], GLOB.tails_list_human)
|
||||
features["snout"] = sanitize_inlist(features["snout"], GLOB.snouts_list)
|
||||
@@ -690,10 +703,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
features["cock_shape"] = sanitize_inlist(features["cock_shape"], GLOB.cock_shapes_list, DEF_COCK_SHAPE)
|
||||
features["balls_shape"] = sanitize_inlist(features["balls_shape"], GLOB.balls_shapes_list, DEF_BALLS_SHAPE)
|
||||
features["vag_shape"] = sanitize_inlist(features["vag_shape"], GLOB.vagina_shapes_list, DEF_VAGINA_SHAPE)
|
||||
features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 3, FALSE, "FFF")
|
||||
features["cock_color"] = sanitize_hexcolor(features["cock_color"], 3, FALSE, "FFF")
|
||||
features["balls_color"] = sanitize_hexcolor(features["balls_color"], 3, FALSE, "FFF")
|
||||
features["vag_color"] = sanitize_hexcolor(features["vag_color"], 3, FALSE, "FFF")
|
||||
features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 6, FALSE, "FFFFFF")
|
||||
features["cock_color"] = sanitize_hexcolor(features["cock_color"], 6, FALSE, "FFFFFF")
|
||||
features["balls_color"] = sanitize_hexcolor(features["balls_color"], 6, FALSE, "FFFFFF")
|
||||
features["vag_color"] = sanitize_hexcolor(features["vag_color"], 6, FALSE, "FFFFFF")
|
||||
features["breasts_visibility"] = sanitize_inlist(features["breasts_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["cock_visibility"] = sanitize_inlist(features["cock_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["balls_visibility"] = sanitize_inlist(features["balls_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
@@ -709,6 +722,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN)
|
||||
features["ooc_notes"] = copytext(features["ooc_notes"], 1, MAX_FLAVOR_LEN)
|
||||
|
||||
persistent_scars = sanitize_integer(persistent_scars)
|
||||
scars_list["1"] = sanitize_text(scars_list["1"])
|
||||
scars_list["2"] = sanitize_text(scars_list["2"])
|
||||
scars_list["3"] = sanitize_text(scars_list["3"])
|
||||
scars_list["4"] = sanitize_text(scars_list["4"])
|
||||
scars_list["5"] = sanitize_text(scars_list["5"])
|
||||
|
||||
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
|
||||
//Validate job prefs
|
||||
for(var/j in job_preferences)
|
||||
@@ -840,6 +860,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["vore_taste"] , vore_taste)
|
||||
WRITE_FILE(S["belly_prefs"] , belly_prefs)
|
||||
|
||||
WRITE_FILE(S["persistent_scars"] , persistent_scars)
|
||||
WRITE_FILE(S["scars1"] , scars_list["1"])
|
||||
WRITE_FILE(S["scars2"] , scars_list["2"])
|
||||
WRITE_FILE(S["scars3"] , scars_list["3"])
|
||||
WRITE_FILE(S["scars4"] , scars_list["4"])
|
||||
WRITE_FILE(S["scars5"] , scars_list["5"])
|
||||
|
||||
//gear loadout
|
||||
if(chosen_gear.len)
|
||||
var/text_to_save = chosen_gear.Join("|")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user