Merge remote-tracking branch 'citadel/master' into shoelaces
This commit is contained in:
@@ -558,12 +558,25 @@
|
||||
client.prefs.random_character()
|
||||
client.prefs.real_name = client.prefs.pref_species.random_name(gender,1)
|
||||
client.prefs.copy_to(H)
|
||||
var/cur_scar_index = client.prefs.scars_index
|
||||
if(client.prefs.persistent_scars && client.prefs.scars_list["[cur_scar_index]"])
|
||||
var/scar_string = client.prefs.scars_list["[cur_scar_index]"]
|
||||
var/valid_scars = ""
|
||||
for(var/scar_line in splittext(scar_string, ";"))
|
||||
if(H.load_scar(scar_line))
|
||||
valid_scars += "[scar_line];"
|
||||
|
||||
client.prefs.scars_list["[cur_scar_index]"] = valid_scars
|
||||
client.prefs.save_character()
|
||||
|
||||
client.prefs.copy_to(H)
|
||||
H.dna.update_dna_identity()
|
||||
if(mind)
|
||||
if(transfer_after)
|
||||
mind.late_joiner = TRUE
|
||||
mind.active = 0 //we wish to transfer the key manually
|
||||
mind.transfer_to(H) //won't transfer key since the mind is not active
|
||||
mind.original_character = H
|
||||
|
||||
H.name = real_name
|
||||
|
||||
|
||||
@@ -5,16 +5,26 @@
|
||||
#define EXOTIC_BLEED_MULTIPLIER 4 //Multiplies the actually bled amount by this number for the purposes of turf reaction calculations.
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/suppress_bloodloss(amount)
|
||||
if(bleedsuppress)
|
||||
/mob/living/carbon/monkey/handle_blood()
|
||||
if(bodytemperature <= TCRYO || (HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood.
|
||||
return
|
||||
else
|
||||
bleedsuppress = TRUE
|
||||
addtimer(CALLBACK(src, .proc/resume_bleeding), amount)
|
||||
|
||||
var/temp_bleed = 0
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
temp_bleed += BP.get_bleed_rate()
|
||||
BP.generic_bleedstacks = max(0, BP.generic_bleedstacks - 1)
|
||||
bleed(temp_bleed)
|
||||
|
||||
//Blood regeneration if there is some space
|
||||
if(blood_volume < BLOOD_VOLUME_NORMAL)
|
||||
blood_volume += 0.1 // regenerate blood VERY slowly
|
||||
if(blood_volume < BLOOD_VOLUME_OKAY)
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
|
||||
|
||||
/mob/living/carbon/human/proc/resume_bleeding()
|
||||
bleedsuppress = 0
|
||||
if(stat != DEAD && bleed_rate)
|
||||
if(stat != DEAD && is_bleeding())
|
||||
to_chat(src, "<span class='warning'>The blood soaks through your bandage.</span>")
|
||||
|
||||
|
||||
@@ -29,20 +39,13 @@
|
||||
// Takes care blood loss and regeneration
|
||||
/mob/living/carbon/human/handle_blood()
|
||||
|
||||
if(NOBLOOD in dna.species.species_traits)
|
||||
bleed_rate = 0
|
||||
if(NOBLOOD in dna.species.species_traits || bleedsuppress || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
return
|
||||
|
||||
if(bleed_rate < 0)
|
||||
bleed_rate = 0
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_NOMARROW)) //Bloodsuckers don't need to be here.
|
||||
return
|
||||
|
||||
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE))) //cryosleep or husked people do not pump the blood.
|
||||
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood.
|
||||
|
||||
//Blood regeneration if there is some space
|
||||
if(blood_volume < (BLOOD_VOLUME_NORMAL * blood_ratio) && !HAS_TRAIT(src, TRAIT_NOHUNGER))
|
||||
if(blood_volume < BLOOD_VOLUME_NORMAL && !HAS_TRAIT(src, TRAIT_NOHUNGER))
|
||||
var/nutrition_ratio = 0
|
||||
switch(nutrition)
|
||||
if(0 to NUTRITION_LEVEL_STARVING)
|
||||
@@ -55,22 +58,27 @@
|
||||
nutrition_ratio = 0.8
|
||||
else
|
||||
nutrition_ratio = 1
|
||||
if(HAS_TRAIT(src, TRAIT_HIGH_BLOOD))
|
||||
nutrition_ratio *= 1.2
|
||||
if(satiety > 80)
|
||||
nutrition_ratio *= 1.25
|
||||
adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR)
|
||||
blood_volume = min((BLOOD_VOLUME_NORMAL * blood_ratio), blood_volume + 0.5 * nutrition_ratio)
|
||||
blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio)
|
||||
|
||||
//Effects of bloodloss
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
switch(blood_volume * INVERSE(blood_ratio))
|
||||
switch(blood_volume)
|
||||
if(BLOOD_VOLUME_EXCESS to BLOOD_VOLUME_MAX_LETHAL)
|
||||
if(prob(15))
|
||||
to_chat(src, "<span class='userdanger'>Blood starts to tear your skin apart. You're going to burst!</span>")
|
||||
gib()
|
||||
if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS)
|
||||
if(prob(10))
|
||||
to_chat(src, "<span class='warning'>You feel terribly bloated.</span>")
|
||||
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
|
||||
if(prob(5))
|
||||
to_chat(src, "<span class='warning'>You feel [word].</span>")
|
||||
adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.01, 1))
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.02, 1))
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
|
||||
if(prob(5))
|
||||
blur_eyes(6)
|
||||
to_chat(src, "<span class='warning'>You feel very [word].</span>")
|
||||
@@ -87,24 +95,11 @@
|
||||
//Bleeding out
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
var/brutedamage = BP.brute_dam
|
||||
temp_bleed += BP.get_bleed_rate()
|
||||
BP.generic_bleedstacks = max(0, BP.generic_bleedstacks - 1)
|
||||
|
||||
if(BP.status == BODYPART_ROBOTIC) //for the moment, synth limbs won't bleed, but soon, my pretty.
|
||||
continue
|
||||
|
||||
//We want an accurate reading of .len
|
||||
listclearnulls(BP.embedded_objects)
|
||||
for(var/obj/item/embeddies in BP.embedded_objects)
|
||||
if(!embeddies.isEmbedHarmless())
|
||||
temp_bleed += 0.5
|
||||
|
||||
if(brutedamage >= 20)
|
||||
temp_bleed += (brutedamage * 0.013)
|
||||
|
||||
bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
|
||||
|
||||
if(bleed_rate && !bleedsuppress && !(HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
bleed(bleed_rate)
|
||||
if(temp_bleed)
|
||||
bleed(temp_bleed)
|
||||
|
||||
//Makes a blood drop, leaking amt units of blood from the mob
|
||||
/mob/living/carbon/proc/bleed(amt)
|
||||
@@ -128,9 +123,11 @@
|
||||
/mob/living/proc/restore_blood()
|
||||
blood_volume = initial(blood_volume)
|
||||
|
||||
/mob/living/carbon/human/restore_blood()
|
||||
/mob/living/carbon/restore_blood()
|
||||
blood_volume = (BLOOD_VOLUME_NORMAL * blood_ratio)
|
||||
bleed_rate = 0
|
||||
for(var/i in bodyparts)
|
||||
var/obj/item/bodypart/BP = i
|
||||
BP.generic_bleedstacks = 0
|
||||
|
||||
/****************************************************
|
||||
BLOOD TRANSFERS
|
||||
|
||||
@@ -331,6 +331,8 @@
|
||||
max_traumas = TRAUMA_LIMIT_BASIC
|
||||
if(TRAUMA_RESILIENCE_SURGERY)
|
||||
max_traumas = TRAUMA_LIMIT_SURGERY
|
||||
if(TRAUMA_RESILIENCE_WOUND)
|
||||
max_traumas = TRAUMA_LIMIT_WOUND
|
||||
if(TRAUMA_RESILIENCE_LOBOTOMY)
|
||||
max_traumas = TRAUMA_LIMIT_LOBOTOMY
|
||||
if(TRAUMA_RESILIENCE_MAGIC)
|
||||
@@ -389,7 +391,7 @@
|
||||
return
|
||||
|
||||
var/trauma_type = pick(possible_traumas)
|
||||
gain_trauma(trauma_type, resilience)
|
||||
return gain_trauma(trauma_type, resilience)
|
||||
|
||||
//Cure a random trauma of a certain resilience level
|
||||
/obj/item/organ/brain/proc/cure_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_BASIC)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
return attack_hand(user)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/mask/facehugger/attack_hand(mob/user)
|
||||
/obj/item/clothing/mask/facehugger/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if((stat == CONSCIOUS && !sterile) && !isalien(user))
|
||||
if(Leap(user))
|
||||
return
|
||||
|
||||
@@ -88,11 +88,32 @@
|
||||
for(var/datum/surgery/S in surgeries)
|
||||
if(S.next_step(user,user.a_intent))
|
||||
return 1
|
||||
|
||||
if(!all_wounds || !(user.a_intent == INTENT_HELP || user == src))
|
||||
return ..()
|
||||
|
||||
// The following priority/nonpriority searching is so that if we have two wounds on a limb that use the same item for treatment (gauze can bandage cuts AND splint broken bones),
|
||||
// we prefer whichever wound is not already treated (ignore the splinted broken bone for the open cut). If there's no priority wounds that this can treat, go through the
|
||||
// non-priority ones randomly.
|
||||
var/list/nonpriority_wounds = list()
|
||||
for(var/datum/wound/W in shuffle(all_wounds))
|
||||
if(!W.treat_priority)
|
||||
nonpriority_wounds += W
|
||||
else if(W.treat_priority && W.try_treating(I, user))
|
||||
return 1
|
||||
|
||||
for(var/datum/wound/W in shuffle(nonpriority_wounds))
|
||||
if(W.try_treating(I, user))
|
||||
return 1
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
. = ..()
|
||||
var/hurt = TRUE
|
||||
var/extra_speed = 0
|
||||
if(throwingdatum.thrower != src)
|
||||
extra_speed = min(max(0, throwingdatum.speed - initial(throw_speed)), 3)
|
||||
if(GetComponent(/datum/component/tackler))
|
||||
return
|
||||
if(throwingdatum?.thrower && iscyborg(throwingdatum.thrower))
|
||||
@@ -102,18 +123,18 @@
|
||||
if(hit_atom.density && isturf(hit_atom))
|
||||
if(hurt)
|
||||
DefaultCombatKnockdown(20)
|
||||
take_bodypart_damage(10)
|
||||
take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5)
|
||||
if(iscarbon(hit_atom) && hit_atom != src)
|
||||
var/mob/living/carbon/victim = hit_atom
|
||||
if(victim.movement_type & FLYING)
|
||||
return
|
||||
if(hurt)
|
||||
victim.take_bodypart_damage(10)
|
||||
take_bodypart_damage(10)
|
||||
victim.take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5)
|
||||
take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5)
|
||||
victim.DefaultCombatKnockdown(20)
|
||||
DefaultCombatKnockdown(20)
|
||||
visible_message("<span class='danger'>[src] crashes into [victim], knocking them both over!</span>",\
|
||||
"<span class='userdanger'>You violently crash into [victim]!</span>")
|
||||
visible_message("<span class='danger'>[src] crashes into [victim] [extra_speed ? "really hard" : ""], knocking them both over!</span>",\
|
||||
"<span class='userdanger'>You violently crash into [victim] [extra_speed ? "extra hard" : ""]!</span>")
|
||||
playsound(src,'sound/weapons/punch1.ogg',50,1)
|
||||
|
||||
|
||||
@@ -153,6 +174,7 @@
|
||||
if(IS_STAMCRIT(src))
|
||||
to_chat(src, "<span class='warning'>You're too exhausted.</span>")
|
||||
return
|
||||
|
||||
var/random_turn = a_intent == INTENT_HARM
|
||||
//END OF CIT CHANGES
|
||||
|
||||
@@ -196,12 +218,18 @@
|
||||
adjustStaminaLossBuffered(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST))
|
||||
|
||||
if(thrown_thing)
|
||||
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
|
||||
log_message("has thrown [thrown_thing]", LOG_ATTACK)
|
||||
var/power_throw = 0
|
||||
if(HAS_TRAIT(src, TRAIT_HULK))
|
||||
power_throw++
|
||||
if(pulling && grab_state >= GRAB_NECK)
|
||||
power_throw++
|
||||
visible_message("<span class='danger'>[src] throws [thrown_thing][power_throw ? " really hard!" : "."]</span>", \
|
||||
"<span class='danger'>You throw [thrown_thing][power_throw ? " really hard!" : "."]</span>")
|
||||
log_message("has thrown [thrown_thing] [power_throw ? "really hard" : ""]", LOG_ATTACK)
|
||||
do_attack_animation(target, no_effect = 1)
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1)
|
||||
newtonian_move(get_dir(target, src))
|
||||
thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, move_force, random_turn)
|
||||
thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed + power_throw, src, null, null, null, move_force, random_turn)
|
||||
|
||||
/mob/living/carbon/restrained(ignore_grab)
|
||||
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
|
||||
@@ -892,6 +920,9 @@
|
||||
var/datum/disease/D = thing
|
||||
if(D.severity != DISEASE_SEVERITY_POSITIVE)
|
||||
D.cure(FALSE)
|
||||
for(var/thing in all_wounds)
|
||||
var/datum/wound/W = thing
|
||||
W.remove_wound()
|
||||
if(admin_revive)
|
||||
regenerate_limbs()
|
||||
regenerate_organs()
|
||||
@@ -982,6 +1013,10 @@
|
||||
if(SANITY_NEUTRAL to SANITY_GREAT)
|
||||
. *= 0.90
|
||||
|
||||
for(var/i in status_effects)
|
||||
var/datum/status_effect/S = i
|
||||
. *= S.interact_speed_modifier()
|
||||
|
||||
|
||||
/mob/living/carbon/proc/create_internal_organs()
|
||||
for(var/X in internal_organs)
|
||||
@@ -1170,3 +1205,47 @@
|
||||
if(wear_mask)
|
||||
if(wear_mask.flags_inv & HIDEEYES)
|
||||
LAZYOR(., SLOT_GLASSES)
|
||||
|
||||
// if any of our bodyparts are bleeding
|
||||
/mob/living/carbon/proc/is_bleeding()
|
||||
for(var/i in bodyparts)
|
||||
var/obj/item/bodypart/BP = i
|
||||
if(BP.get_bleed_rate())
|
||||
return TRUE
|
||||
|
||||
// get our total bleedrate
|
||||
/mob/living/carbon/proc/get_total_bleed_rate()
|
||||
var/total_bleed_rate = 0
|
||||
for(var/i in bodyparts)
|
||||
var/obj/item/bodypart/BP = i
|
||||
total_bleed_rate += BP.get_bleed_rate()
|
||||
|
||||
return total_bleed_rate
|
||||
|
||||
/**
|
||||
* generate_fake_scars()- for when you want to scar someone, but you don't want to hurt them first. These scars don't count for temporal scarring (hence, fake)
|
||||
*
|
||||
* If you want a specific wound scar, pass that wound type as the second arg, otherwise you can pass a list like WOUND_LIST_CUT to generate a random cut scar.
|
||||
*
|
||||
* Arguments:
|
||||
* * num_scars- A number for how many scars you want to add
|
||||
* * forced_type- Which wound or category of wounds you want to choose from, WOUND_LIST_BONE, WOUND_LIST_CUT, or WOUND_LIST_BURN (or some combination). If passed a list, picks randomly from the listed wounds. Defaults to all 3 types
|
||||
*/
|
||||
/mob/living/carbon/proc/generate_fake_scars(num_scars, forced_type)
|
||||
for(var/i in 1 to num_scars)
|
||||
var/datum/scar/S = new
|
||||
var/obj/item/bodypart/BP = pick(bodyparts)
|
||||
|
||||
var/wound_type
|
||||
if(forced_type)
|
||||
if(islist(forced_type))
|
||||
wound_type = pick(forced_type)
|
||||
else
|
||||
wound_type = forced_type
|
||||
else
|
||||
wound_type = pick(WOUND_LIST_BONE + WOUND_LIST_CUT + WOUND_LIST_BURN)
|
||||
|
||||
var/datum/wound/W = new wound_type
|
||||
S.generate(BP, W)
|
||||
S.fake = TRUE
|
||||
QDEL_NULL(W)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/mob/living/carbon/check_unarmed_parry_activation_special()
|
||||
return ..() && length(get_empty_held_indexes())
|
||||
@@ -79,7 +79,7 @@
|
||||
send_item_attack_message(I, user, affecting.name, totitemdamage)
|
||||
I.do_stagger_action(src, user, totitemdamage)
|
||||
if(I.force)
|
||||
apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage
|
||||
apply_damage(totitemdamage, I.damtype, affecting, wound_bonus = I.wound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness()) //CIT CHANGE - replaces I.force with totitemdamage
|
||||
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
|
||||
var/basebloodychance = affecting.brute_dam + totitemdamage
|
||||
if(prob(basebloodychance))
|
||||
@@ -112,7 +112,7 @@
|
||||
return //so we don't call the carbon's attack_hand().
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/carbon/attack_hand(mob/living/carbon/human/user)
|
||||
/mob/living/carbon/attack_hand(mob/living/carbon/human/user, act_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.) //was the attack blocked?
|
||||
return
|
||||
@@ -127,11 +127,14 @@
|
||||
ContactContractDisease(D)
|
||||
|
||||
if(lying && surgeries.len)
|
||||
if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)
|
||||
if(act_intent == INTENT_HELP || act_intent == INTENT_DISARM)
|
||||
for(var/datum/surgery/S in surgeries)
|
||||
if(S.next_step(user, user.a_intent))
|
||||
if(S.next_step(user, act_intent))
|
||||
return TRUE
|
||||
|
||||
for(var/datum/wound/W in all_wounds)
|
||||
if(W.try_handling(user))
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
|
||||
|
||||
@@ -467,3 +470,8 @@
|
||||
if (BP.status < 2)
|
||||
amount += BP.burn_dam
|
||||
return amount
|
||||
|
||||
/mob/living/carbon/proc/get_interaction_efficiency(zone)
|
||||
var/obj/item/bodypart/limb = get_bodypart(zone)
|
||||
if(!limb)
|
||||
return
|
||||
|
||||
@@ -65,6 +65,11 @@
|
||||
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
|
||||
var/tackling = FALSE //Whether or not we are tackling, this will prevent the knock into effects for carbons
|
||||
|
||||
/// All of the wounds a carbon has afflicted throughout their limbs
|
||||
var/list/all_wounds
|
||||
/// All of the scars a carbon has afflicted throughout their limbs
|
||||
var/list/all_scars
|
||||
|
||||
/// Protection (insulation) from the heat, Value 0-1 corresponding to the percentage of protection
|
||||
var/heat_protection = 0 // No heat protection
|
||||
/// Protection (insulation) from the cold, Value 0-1 corresponding to the percentage of protection
|
||||
@@ -72,3 +77,4 @@
|
||||
|
||||
/// Timer id of any transformation
|
||||
var/transformation_timer
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
|
||||
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
|
||||
var/hit_percent = (100-blocked)/100
|
||||
if(!forced && hit_percent <= 0)
|
||||
@@ -21,13 +21,13 @@
|
||||
switch(damagetype)
|
||||
if(BRUTE)
|
||||
if(BP)
|
||||
if(damage > 0 ? BP.receive_damage(damage_amount) : BP.heal_damage(abs(damage_amount), 0))
|
||||
if(BP.receive_damage(damage_amount, 0, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
|
||||
update_damage_overlays()
|
||||
else //no bodypart, we deal damage with a more general method.
|
||||
adjustBruteLoss(damage_amount, forced = forced)
|
||||
if(BURN)
|
||||
if(BP)
|
||||
if(damage > 0 ? BP.receive_damage(0, damage_amount) : BP.heal_damage(0, abs(damage_amount)))
|
||||
if(BP.receive_damage(0, damage_amount, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
|
||||
update_damage_overlays()
|
||||
else
|
||||
adjustFireLoss(damage_amount, forced = forced)
|
||||
@@ -202,12 +202,12 @@
|
||||
//Damages ONE bodypart randomly selected from damagable ones.
|
||||
//It automatically updates damage overlays if necessary
|
||||
//It automatically updates health status
|
||||
/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0)
|
||||
/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
|
||||
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
|
||||
if(!parts.len)
|
||||
return
|
||||
var/obj/item/bodypart/picked = pick(parts)
|
||||
if(picked.receive_damage(brute, burn, stamina))
|
||||
if(picked.receive_damage(brute, burn, stamina,check_armor ? run_armor_check(picked, (brute ? "melee" : burn ? "fire" : stamina ? "bullet" : null)) : FALSE, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
|
||||
update_damage_overlays()
|
||||
|
||||
//Heal MANY bodyparts, in random order
|
||||
@@ -235,12 +235,12 @@
|
||||
update_damage_overlays()
|
||||
update_stamina() //CIT CHANGE - makes sure update_stamina() always gets called after a health update
|
||||
|
||||
// damage MANY bodyparts, in random order
|
||||
/mob/living/carbon/take_overall_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE)
|
||||
/// damage MANY bodyparts, in random order
|
||||
/mob/living/carbon/take_overall_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status)
|
||||
if(status_flags & GODMODE)
|
||||
return //godmode
|
||||
|
||||
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
|
||||
var/list/obj/item/bodypart/parts = get_damageable_bodyparts(required_status)
|
||||
var/update = 0
|
||||
while(parts.len && (brute > 0 || burn > 0 || stamina > 0))
|
||||
var/obj/item/bodypart/picked = pick(parts)
|
||||
@@ -253,7 +253,7 @@
|
||||
var/stamina_was = picked.stamina_dam
|
||||
|
||||
|
||||
update |= picked.receive_damage(brute_per_part, burn_per_part, stamina_per_part, FALSE)
|
||||
update |= picked.receive_damage(brute_per_part, burn_per_part, stamina_per_part, FALSE, required_status, wound_bonus = CANT_WOUND) // disabling wounds from these for now cuz your entire body snapping cause your heart stopped would suck
|
||||
|
||||
brute = round(brute - (picked.brute_dam - brute_was), DAMAGE_PRECISION)
|
||||
burn = round(burn - (picked.burn_dam - burn_was), DAMAGE_PRECISION)
|
||||
@@ -265,3 +265,12 @@
|
||||
if(update)
|
||||
update_damage_overlays()
|
||||
update_stamina()
|
||||
|
||||
///Returns a list of bodyparts with wounds (in case someone has a wound on an otherwise fully healed limb)
|
||||
/mob/living/carbon/proc/get_wounded_bodyparts(brute = FALSE, burn = FALSE, stamina = FALSE, status)
|
||||
var/list/obj/item/bodypart/parts = list()
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
if(LAZYLEN(BP.wounds))
|
||||
parts += BP
|
||||
return parts
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!</B>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
for(var/datum/wound/W in BP.wounds)
|
||||
msg += "[W.get_examine_description(user)]\n"
|
||||
|
||||
for(var/X in disabled)
|
||||
var/obj/item/bodypart/BP = X
|
||||
@@ -99,6 +101,22 @@
|
||||
if(pulledby && pulledby.grab_state)
|
||||
msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n"
|
||||
|
||||
var/scar_severity = 0
|
||||
for(var/i in all_scars)
|
||||
var/datum/scar/S = i
|
||||
if(S.is_visible(user))
|
||||
scar_severity += S.severity
|
||||
|
||||
switch(scar_severity)
|
||||
if(1 to 2)
|
||||
msg += "<span class='smallnotice'>[t_He] [t_has] visible scarring, you can look again to take a closer look...</span>\n"
|
||||
if(3 to 4)
|
||||
msg += "<span class='notice'><i>[t_He] [t_has] several bad scars, you can look again to take a closer look...</i></span>\n"
|
||||
if(5 to 6)
|
||||
msg += "<span class='notice'><b><i>[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...</i></b></span>\n"
|
||||
if(7 to INFINITY)
|
||||
msg += "<span class='notice'><b><i>[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...</i></b></span>\n"
|
||||
|
||||
if(msg.len)
|
||||
. += "<span class='warning'>[msg.Join("")]</span>"
|
||||
|
||||
@@ -135,3 +153,25 @@
|
||||
. += "[t_He] look[p_s()] ecstatic."
|
||||
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
|
||||
. += "*---------*</span>"
|
||||
|
||||
/mob/living/carbon/examine_more(mob/user)
|
||||
if(!all_scars)
|
||||
return ..()
|
||||
|
||||
var/list/visible_scars
|
||||
for(var/i in all_scars)
|
||||
var/datum/scar/S = i
|
||||
if(S.is_visible(user))
|
||||
LAZYADD(visible_scars, S)
|
||||
|
||||
if(!visible_scars)
|
||||
return ..()
|
||||
|
||||
var/msg = list("<span class='notice'><i>You examine [src] closer, and note the following...</i></span>")
|
||||
for(var/i in visible_scars)
|
||||
var/datum/scar/S = i
|
||||
var/scar_text = S.get_examine_description(user)
|
||||
if(scar_text)
|
||||
msg += "[scar_text]"
|
||||
|
||||
return msg
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
// depending on the species, it will run the corresponding apply_damage code there
|
||||
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
|
||||
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness)
|
||||
|
||||
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage)
|
||||
// depending on the species, it will run the corresponding apply_damage code there
|
||||
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage)
|
||||
|
||||
@@ -163,16 +163,18 @@
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!</B>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
for(var/datum/wound/W in BP.wounds)
|
||||
msg += "[W.get_examine_description(user)]\n"
|
||||
|
||||
for(var/X in disabled)
|
||||
var/obj/item/bodypart/BP = X
|
||||
var/damage_text
|
||||
if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //Stamina is disabling the limb
|
||||
damage_text = "limp and lifeless"
|
||||
else
|
||||
damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg
|
||||
msg += "<B>[capitalize(t_his)] [BP.name] is [damage_text]!</B>\n"
|
||||
|
||||
if(BP.is_disabled() != BODYPART_DISABLED_WOUND) // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!)
|
||||
if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //we don't care if it's stamcritted
|
||||
damage_text = "limp and lifeless"
|
||||
else
|
||||
damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg
|
||||
msg += "<B>[capitalize(t_his)] [BP.name] is [damage_text]!</B>\n"
|
||||
//stores missing limbs
|
||||
var/l_limbs_missing = 0
|
||||
var/r_limbs_missing = 0
|
||||
@@ -246,16 +248,40 @@
|
||||
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
|
||||
msg += "[t_He] look[p_s()] extremely disgusted.\n"
|
||||
|
||||
if(ShowAsPaleExamine())
|
||||
msg += "[t_He] [t_has] pale skin.\n"
|
||||
var/apparent_blood_volume = blood_volume
|
||||
if(skin_tone == "albino")
|
||||
apparent_blood_volume -= 150 // enough to knock you down one tier
|
||||
switch(apparent_blood_volume)
|
||||
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
|
||||
msg += "[t_He] [t_has] pale skin.\n"
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
msg += "<b>[t_He] look[p_s()] like pale death.</b>\n"
|
||||
if(-INFINITY to BLOOD_VOLUME_BAD)
|
||||
msg += "<span class='deadsay'><b>[t_He] resemble[p_s()] a crushed, empty juice pouch.</b></span>\n"
|
||||
|
||||
if(bleedsuppress)
|
||||
msg += "[t_He] [t_is] bandaged with something.\n"
|
||||
else if(bleed_rate)
|
||||
if(bleed_rate >= 8) //8 is the rate at which heparin causes you to bleed
|
||||
msg += "<b>[t_He] [t_is] bleeding uncontrollably!</b>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_is] bleeding!</B>\n"
|
||||
msg += "[t_He] [t_is] embued with a power that defies bleeding.\n" // only statues and highlander sword can cause this so whatever
|
||||
else if(is_bleeding())
|
||||
var/list/obj/item/bodypart/bleeding_limbs = list()
|
||||
|
||||
for(var/i in bodyparts)
|
||||
var/obj/item/bodypart/BP = i
|
||||
if(BP.get_bleed_rate())
|
||||
bleeding_limbs += BP
|
||||
|
||||
var/num_bleeds = LAZYLEN(bleeding_limbs)
|
||||
var/bleed_text = "<B>[t_He] [t_is] bleeding from [t_his]"
|
||||
switch(num_bleeds)
|
||||
if(1 to 2)
|
||||
bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]"
|
||||
if(3 to INFINITY)
|
||||
for(var/i in 1 to (num_bleeds - 1))
|
||||
var/obj/item/bodypart/BP = bleeding_limbs[i]
|
||||
bleed_text += " [BP.name],"
|
||||
bleed_text += " and [bleeding_limbs[num_bleeds].name]"
|
||||
|
||||
bleed_text += "!</B>\n"
|
||||
msg += bleed_text
|
||||
|
||||
if(reagents.has_reagent(/datum/reagent/teslium))
|
||||
msg += "[t_He] [t_is] emitting a gentle blue glow!\n"
|
||||
@@ -331,6 +357,21 @@
|
||||
if(digitalcamo)
|
||||
msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n"
|
||||
|
||||
var/scar_severity = 0
|
||||
for(var/i in all_scars)
|
||||
var/datum/scar/S = i
|
||||
if(S.is_visible(user))
|
||||
scar_severity += S.severity
|
||||
|
||||
switch(scar_severity)
|
||||
if(1 to 2)
|
||||
msg += "<span class='smallnotice'>[t_He] [t_has] visible scarring, you can look again to take a closer look...</span>\n"
|
||||
if(3 to 4)
|
||||
msg += "<span class='notice'><i>[t_He] [t_has] several bad scars, you can look again to take a closer look...</i></span>\n"
|
||||
if(5 to 6)
|
||||
msg += "<span class='notice'><b><i>[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...</i></b></span>\n"
|
||||
if(7 to INFINITY)
|
||||
msg += "<span class='notice'><b><i>[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...</i></b></span>\n"
|
||||
|
||||
if (length(msg))
|
||||
. += "<span class='warning'>[msg.Join("")]</span>"
|
||||
|
||||
@@ -1067,10 +1067,21 @@
|
||||
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
|
||||
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
|
||||
|
||||
|
||||
/mob/living/carbon/human/do_after_coefficent()
|
||||
. = ..()
|
||||
. *= physiology.do_after_speed
|
||||
|
||||
/mob/living/carbon/human/is_bleeding()
|
||||
if(NOBLOOD in dna.species.species_traits || bleedsuppress)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/get_total_bleed_rate()
|
||||
if(NOBLOOD in dna.species.species_traits)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/species
|
||||
var/race = null
|
||||
|
||||
|
||||
@@ -34,6 +34,19 @@
|
||||
protection += physiology.armor.getRating(d_type)
|
||||
return protection
|
||||
|
||||
///Get all the clothing on a specific body part
|
||||
/mob/living/carbon/human/proc/clothingonpart(obj/item/bodypart/def_zone)
|
||||
var/list/covering_part = list()
|
||||
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
|
||||
for(var/bp in body_parts)
|
||||
if(!bp)
|
||||
continue
|
||||
if(bp && istype(bp , /obj/item/clothing))
|
||||
var/obj/item/clothing/C = bp
|
||||
if(C.body_parts_covered & def_zone.body_part)
|
||||
covering_part += C
|
||||
return covering_part
|
||||
|
||||
/mob/living/carbon/human/on_hit(obj/item/projectile/P)
|
||||
if(dna && dna.species)
|
||||
dna.species.on_hit(P, src)
|
||||
@@ -106,16 +119,16 @@
|
||||
visible_message("<span class='danger'>[user] [hulk_verb_continous] [src]!</span>", \
|
||||
"<span class='userdanger'>[user] [hulk_verb_continous] you!</span>", null, COMBAT_MESSAGE_RANGE, null, user,
|
||||
"<span class='danger'>You [hulk_verb_simple] [src]!</span>")
|
||||
adjustBruteLoss(15)
|
||||
apply_damage(15, BRUTE, wound_bonus=10)
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/attack_hand(mob/user)
|
||||
/mob/living/carbon/human/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
dna.species.spec_attack_hand(H, src)
|
||||
dna.species.spec_attack_hand(H, src, null, act_intent, unarmed_attack_flags)
|
||||
|
||||
/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M)
|
||||
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
@@ -217,16 +230,17 @@
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration)
|
||||
apply_damage(damage, M.melee_damage_type, affecting, armor)
|
||||
|
||||
apply_damage(damage, M.melee_damage_type, affecting, armor, wound_bonus = M.wound_bonus, bare_wound_bonus = M.bare_wound_bonus, sharpness = M.sharpness)
|
||||
|
||||
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime attack
|
||||
return
|
||||
var/damage = rand(5, 25)
|
||||
var/wound_mod = -45 // 25^1.4=90, 90-45=45
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 35)
|
||||
wound_mod = -90 // 35^1.4=145, 145-90=55
|
||||
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
@@ -236,7 +250,7 @@
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
apply_damage(damage, BRUTE, affecting, armor_block, wound_bonus=wound_mod)
|
||||
|
||||
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
|
||||
if(M.occupant.a_intent == INTENT_HARM)
|
||||
@@ -614,6 +628,20 @@
|
||||
no_damage = TRUE
|
||||
to_send += "\t <span class='[no_damage ? "notice" : "warning"]'>Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].</span>\n"
|
||||
|
||||
for(var/thing in LB.wounds)
|
||||
var/datum/wound/W = thing
|
||||
var/msg
|
||||
switch(W.severity)
|
||||
if(WOUND_SEVERITY_TRIVIAL)
|
||||
msg = "\t <span class='danger'>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)].</span>"
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
msg = "\t <span class='warning'>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!</span>"
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!</b></span>"
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!!</b></span>"
|
||||
to_chat(src, msg)
|
||||
|
||||
for(var/obj/item/I in LB.embedded_objects)
|
||||
if(I.isEmbedHarmless())
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>")
|
||||
@@ -623,8 +651,25 @@
|
||||
for(var/t in missing)
|
||||
to_send += "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>\n"
|
||||
|
||||
if(bleed_rate)
|
||||
to_send += "<span class='danger'>You are bleeding!</span>\n"
|
||||
if(is_bleeding())
|
||||
var/list/obj/item/bodypart/bleeding_limbs = list()
|
||||
for(var/i in bodyparts)
|
||||
var/obj/item/bodypart/BP = i
|
||||
if(BP.get_bleed_rate())
|
||||
bleeding_limbs += BP
|
||||
|
||||
var/num_bleeds = LAZYLEN(bleeding_limbs)
|
||||
var/bleed_text = "<span class='danger'>You are bleeding from your"
|
||||
switch(num_bleeds)
|
||||
if(1 to 2)
|
||||
bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]"
|
||||
if(3 to INFINITY)
|
||||
for(var/i in 1 to (num_bleeds - 1))
|
||||
var/obj/item/bodypart/BP = bleeding_limbs[i]
|
||||
bleed_text += " [BP.name],"
|
||||
bleed_text += " and [bleeding_limbs[num_bleeds].name]"
|
||||
bleed_text += "!</span>"
|
||||
to_chat(src, bleed_text)
|
||||
if(getStaminaLoss())
|
||||
if(getStaminaLoss() > 30)
|
||||
to_send += "<span class='info'>You're completely exhausted.</span>\n"
|
||||
@@ -717,6 +762,89 @@
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/check_self_for_injuries()
|
||||
if(stat == DEAD || stat == UNCONSCIOUS)
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>[src] examines [p_them()]self.</span>", \
|
||||
"<span class='notice'>You check yourself for injuries.</span>")
|
||||
|
||||
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/LB = X
|
||||
missing -= LB.body_zone
|
||||
if(LB.is_pseudopart) //don't show injury text for fake bodyparts; ie chainsaw arms or synthetic armblades
|
||||
continue
|
||||
var/self_aware = FALSE
|
||||
if(HAS_TRAIT(src, TRAIT_SELF_AWARE))
|
||||
self_aware = TRUE
|
||||
var/limb_max_damage = LB.max_damage
|
||||
var/status = ""
|
||||
var/brutedamage = LB.brute_dam
|
||||
var/burndamage = LB.burn_dam
|
||||
if(hallucination)
|
||||
if(prob(30))
|
||||
brutedamage += rand(30,40)
|
||||
if(prob(30))
|
||||
burndamage += rand(30,40)
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_SELF_AWARE))
|
||||
status = "[brutedamage] brute damage and [burndamage] burn damage"
|
||||
if(!brutedamage && !burndamage)
|
||||
status = "no damage"
|
||||
|
||||
else
|
||||
if(brutedamage > 0)
|
||||
status = LB.light_brute_msg
|
||||
if(brutedamage > (limb_max_damage*0.4))
|
||||
status = LB.medium_brute_msg
|
||||
if(brutedamage > (limb_max_damage*0.8))
|
||||
status = LB.heavy_brute_msg
|
||||
if(brutedamage > 0 && burndamage > 0)
|
||||
status += " and "
|
||||
|
||||
if(burndamage > (limb_max_damage*0.8))
|
||||
status += LB.heavy_burn_msg
|
||||
else if(burndamage > (limb_max_damage*0.2))
|
||||
status += LB.medium_burn_msg
|
||||
else if(burndamage > 0)
|
||||
status += LB.light_burn_msg
|
||||
|
||||
if(status == "")
|
||||
status = "OK"
|
||||
var/no_damage
|
||||
if(status == "OK" || status == "no damage")
|
||||
no_damage = TRUE
|
||||
var/isdisabled = " "
|
||||
if(LB.is_disabled())
|
||||
isdisabled = " is disabled "
|
||||
if(no_damage)
|
||||
isdisabled += " but otherwise "
|
||||
else
|
||||
isdisabled += " and "
|
||||
to_chat(src, "\t <span class='[no_damage ? "notice" : "warning"]'>Your [LB.name][isdisabled][self_aware ? " has " : " is "][status].</span>")
|
||||
|
||||
for(var/thing in LB.wounds)
|
||||
var/datum/wound/W = thing
|
||||
var/msg
|
||||
switch(W.severity)
|
||||
if(WOUND_SEVERITY_TRIVIAL)
|
||||
msg = "\t <span class='danger'>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)].</span>"
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
msg = "\t <span class='warning'>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!</span>"
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!</b></span>"
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
msg = "\t <span class='warning'><b>Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!!</b></span>"
|
||||
to_chat(src, msg)
|
||||
|
||||
for(var/obj/item/I in LB.embedded_objects)
|
||||
if(I.isEmbedHarmless())
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>")
|
||||
else
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
|
||||
|
||||
/mob/living/carbon/human/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
|
||||
if(damage_type != BRUTE && damage_type != BURN)
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
buckle_lying = FALSE
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
/// Enable stamina combat
|
||||
combat_flags = COMBAT_FLAGS_DEFAULT
|
||||
combat_flags = COMBAT_FLAGS_DEFAULT | COMBAT_FLAG_UNARMED_PARRY
|
||||
status_flags = CANSTUN|CANKNOCKDOWN|CANUNCONSCIOUS|CANPUSH|CANSTAGGER
|
||||
has_field_of_vision = FALSE //Handled by species.
|
||||
|
||||
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
|
||||
|
||||
block_parry_data = /datum/block_parry_data/unarmed/human
|
||||
|
||||
//Hair colour and style
|
||||
var/hair_color = "000"
|
||||
var/hair_style = "Bald"
|
||||
@@ -49,7 +51,6 @@
|
||||
|
||||
var/special_voice = "" // For changing our voice. Used by a symptom.
|
||||
|
||||
var/bleed_rate = 0 //how much are we bleeding
|
||||
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
|
||||
|
||||
var/blood_state = BLOOD_STATE_NOT_BLOODY
|
||||
@@ -71,3 +72,45 @@
|
||||
var/lastpuke = 0
|
||||
var/account_id
|
||||
var/last_fire_update
|
||||
|
||||
/// Unarmed parry data for human
|
||||
/datum/block_parry_data/unarmed/human
|
||||
parry_respect_clickdelay = TRUE
|
||||
parry_stamina_cost = 4
|
||||
parry_attack_types = ATTACK_TYPE_UNARMED
|
||||
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
|
||||
|
||||
parry_time_windup = 0
|
||||
parry_time_spindown = 1
|
||||
parry_time_active = 5
|
||||
|
||||
parry_time_perfect = 1
|
||||
parry_time_perfect_leeway = 1
|
||||
parry_imperfect_falloff_percent = 20
|
||||
parry_efficiency_perfect = 100
|
||||
|
||||
parry_efficiency_considered_successful = 0.01
|
||||
parry_efficiency_to_counterattack = 0.01
|
||||
parry_max_attacks = 3
|
||||
parry_cooldown = 30
|
||||
parry_failed_stagger_duration = 0
|
||||
parry_failed_clickcd_duration = 0.4
|
||||
|
||||
parry_data = list( // yeah it's snowflake
|
||||
"HUMAN_PARRY_STAGGER" = 3 SECONDS,
|
||||
"HUMAN_PARRY_PUNCH" = TRUE,
|
||||
"HUMAN_PARRY_MININUM_EFFICIENCY" = 0.9
|
||||
)
|
||||
|
||||
/mob/living/carbon/human/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time)
|
||||
var/datum/block_parry_data/D = return_block_parry_datum(block_parry_data)
|
||||
if(!owner.Adjacent(attacker))
|
||||
return ..()
|
||||
if(parry_efficiency < D.parry_data["HUMAN_PARRY_MINIMUM_EFFICIENCY"])
|
||||
return ..()
|
||||
visible_message("<span class='warning'>[src] strikes back perfectly at [attacker], staggering them!</span>")
|
||||
if(D.parry_data["HUMAN_PARRY_PUNCH"])
|
||||
UnarmedAttack(attacker, TRUE, INTENT_HARM, UNARMED_ATTACK_PARRY)
|
||||
var/mob/living/L = attacker
|
||||
if(istype(L))
|
||||
L.Stagger(D.parry_data["HUMAN_PARRY_STAGGER"])
|
||||
|
||||
@@ -151,3 +151,22 @@
|
||||
if(blood_dna.len)
|
||||
last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works
|
||||
last_blood_DNA = blood_dna[blood_dna.len]*/
|
||||
|
||||
/// For use formatting all of the scars this human has for saving for persistent scarring
|
||||
/mob/living/carbon/human/proc/format_scars()
|
||||
if(!all_scars)
|
||||
return
|
||||
var/scars = ""
|
||||
for(var/i in all_scars)
|
||||
var/datum/scar/S = i
|
||||
scars += "[S.format()];"
|
||||
return scars
|
||||
|
||||
/// Takes a single scar from the persistent scar loader and recreates it from the saved data
|
||||
/mob/living/carbon/human/proc/load_scar(scar_line)
|
||||
var/list/scar_data = splittext(scar_line, "|")
|
||||
if(LAZYLEN(scar_data) != 4)
|
||||
return // invalid, should delete
|
||||
var/obj/item/bodypart/BP = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]")
|
||||
var/datum/scar/S = new
|
||||
return S.load(BP, scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]))
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
. = ..()
|
||||
for(var/datum/mutation/human/HM in dna.mutations)
|
||||
HM.on_move(NewLoc)
|
||||
if(. && (combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) && !(movement_type & FLYING) && CHECK_ALL_MOBILITY(src, MOBILITY_MOVE|MOBILITY_STAND) && m_intent == MOVE_INTENT_RUN && has_gravity(loc) && !pulledby)
|
||||
if(. && (combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) && !(movement_type & FLYING) && CHECK_ALL_MOBILITY(src, MOBILITY_MOVE|MOBILITY_STAND) && m_intent == MOVE_INTENT_RUN && has_gravity(loc) && (!pulledby || (pulledby.pulledby == src)))
|
||||
if(!HAS_TRAIT(src, TRAIT_FREESPRINT))
|
||||
doSprintLossTiles(1)
|
||||
if((oldpseudoheight - pseudo_z_axis) >= 8)
|
||||
|
||||
@@ -7,7 +7,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this
|
||||
var/limbs_id //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans.
|
||||
var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
|
||||
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
|
||||
var/default_color = "#FFFFFF" // if alien colors are disabled, this is the color that will be used by that race
|
||||
|
||||
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
|
||||
var/has_field_of_vision = TRUE
|
||||
@@ -73,7 +73,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/datum/outfit/outfit_important_for_life // A path to an outfit that is important for species life e.g. plasmaman outfit
|
||||
|
||||
// species-only traits. Can be found in DNA.dm
|
||||
var/list/species_traits = list()
|
||||
var/list/species_traits = list(CAN_SCAR) //by default they can scar unless set to something else
|
||||
// generic traits tied to having the species
|
||||
var/list/inherent_traits = list()
|
||||
var/inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
@@ -854,10 +854,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m"
|
||||
var/list/colorlist = list()
|
||||
var/husk = HAS_TRAIT(H, TRAIT_HUSK)
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor"]]0")
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor2"]]0")
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]0")
|
||||
colorlist += list(0,0,0, hair_alpha)
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor"]]00")
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor2"]]00")
|
||||
colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]00")
|
||||
colorlist += husk ? list(0, 0, 0) : list(0, 0, 0, hair_alpha)
|
||||
for(var/index in 1 to colorlist.len)
|
||||
colorlist[index] /= 255
|
||||
|
||||
@@ -1031,7 +1031,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
H.apply_overlay(BODY_FRONT_LAYER)
|
||||
H.apply_overlay(HORNS_LAYER)
|
||||
|
||||
|
||||
/*
|
||||
* Equip the outfit required for life. Replaces items currently worn.
|
||||
*/
|
||||
@@ -1446,7 +1445,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
target.grabbedby(user)
|
||||
return 1
|
||||
|
||||
/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
|
||||
/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style, unarmed_attack_flags = NONE)
|
||||
if(!attacker_style && HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm [target]!</span>")
|
||||
return FALSE
|
||||
@@ -1458,10 +1457,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
target_message = "<span class='warning'>[target] blocks your attack!</span>")
|
||||
return FALSE
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount
|
||||
user.adjustStaminaLossBuffered(1.5)
|
||||
else
|
||||
user.adjustStaminaLossBuffered(3.5)
|
||||
if(!(unarmed_attack_flags & UNARMED_ATTACK_PARRY))
|
||||
if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount
|
||||
user.adjustStaminaLossBuffered(1.5)
|
||||
else
|
||||
user.adjustStaminaLossBuffered(3.5)
|
||||
|
||||
if(attacker_style && attacker_style.harm_act(user,target))
|
||||
return TRUE
|
||||
@@ -1499,13 +1499,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected))
|
||||
|
||||
var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases
|
||||
if(user.dna.species.punchdamagelow)
|
||||
if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage)
|
||||
miss_chance = 0
|
||||
else if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists have a flat 10% miss chance
|
||||
miss_chance = 10
|
||||
else
|
||||
miss_chance = min(10 + max(puncherstam * 0.5, puncherbrute * 0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob()
|
||||
if(unarmed_attack_flags & UNARMED_ATTACK_PARRY)
|
||||
miss_chance = 0
|
||||
else
|
||||
if(user.dna.species.punchdamagelow)
|
||||
if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage)
|
||||
miss_chance = 0
|
||||
else if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists have a flat 10% miss chance
|
||||
miss_chance = 10
|
||||
else
|
||||
miss_chance = min(10 + max(puncherstam * 0.5, puncherbrute * 0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob()
|
||||
|
||||
if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted
|
||||
playsound(target.loc, user.dna.species.miss_sound, 25, TRUE, -1)
|
||||
@@ -1683,7 +1686,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
/datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
|
||||
/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags)
|
||||
if(!istype(M))
|
||||
return
|
||||
CHECK_DNA_AND_SPECIES(M)
|
||||
@@ -1695,7 +1698,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
attacker_style = M.mind.martial_art
|
||||
if(attacker_style?.pacifism_check && HAS_TRAIT(M, TRAIT_PACIFISM)) // most martial arts are quite harmful, alas.
|
||||
attacker_style = null
|
||||
switch(M.a_intent)
|
||||
switch(act_intent)
|
||||
if("help")
|
||||
help(M, H, attacker_style)
|
||||
|
||||
@@ -1703,7 +1706,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
grab(M, H, attacker_style)
|
||||
|
||||
if("harm")
|
||||
harm(M, H, attacker_style)
|
||||
harm(M, H, attacker_style, unarmed_attack_flags)
|
||||
|
||||
if("disarm")
|
||||
disarm(M, H, attacker_style)
|
||||
@@ -1730,9 +1733,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/armor_block = H.run_armor_check(affecting, "melee", "<span class='notice'>Your armor has protected your [hit_area].</span>", "<span class='notice'>Your armor has softened a hit to your [hit_area].</span>",I.armour_penetration)
|
||||
armor_block = min(90,armor_block) //cap damage reduction at 90%
|
||||
var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
|
||||
var/Iwound_bonus = I.wound_bonus
|
||||
|
||||
// this way, you can't wound with a surgical tool on help intent if they have a surgery active and are laying down, so a misclick with a circular saw on the wrong limb doesn't bleed them dry (they still get hit tho)
|
||||
if((I.item_flags & SURGICAL_TOOL) && user.a_intent == INTENT_HELP && (H.mobility_flags & ~MOBILITY_STAND) && (LAZYLEN(H.surgeries) > 0))
|
||||
Iwound_bonus = CANT_WOUND
|
||||
|
||||
var/weakness = H.check_weakness(I, user)
|
||||
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H) //CIT CHANGE - replaces I.force with totitemdamage
|
||||
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H, wound_bonus = Iwound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness())
|
||||
|
||||
|
||||
H.send_item_attack_message(I, user, hit_area, totitemdamage)
|
||||
|
||||
@@ -1947,8 +1956,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
append_message += ", causing them to drop [target_held_item]"
|
||||
log_combat(user, target, "shoved", append_message)
|
||||
|
||||
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
|
||||
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
|
||||
SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness) // make sure putting wound_bonus here doesn't screw up other signals or uses for this signal
|
||||
var/hit_percent = (100-(blocked+armor))/100
|
||||
hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100
|
||||
if(!forced && hit_percent <= 0)
|
||||
@@ -1975,7 +1984,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
H.damageoverlaytemp = 20
|
||||
var/damage_amount = forced ? damage : damage * hit_percent * brutemod * H.physiology.brute_mod
|
||||
if(BP)
|
||||
if(damage > 0 ? BP.receive_damage(damage_amount, 0) : BP.heal_damage(abs(damage_amount), 0))
|
||||
if(BP.receive_damage(damage_amount, 0, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
|
||||
H.update_damage_overlays()
|
||||
if(HAS_TRAIT(H, TRAIT_MASO) && prob(damage_amount))
|
||||
H.mob_climax(forced_climax=TRUE)
|
||||
@@ -1986,7 +1995,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
H.damageoverlaytemp = 20
|
||||
var/damage_amount = forced ? damage : damage * hit_percent * burnmod * H.physiology.burn_mod
|
||||
if(BP)
|
||||
if(damage > 0 ? BP.receive_damage(0, damage_amount) : BP.heal_damage(0, abs(damage_amount)))
|
||||
if(BP.receive_damage(0, damage_amount, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness))
|
||||
H.update_damage_overlays()
|
||||
else
|
||||
H.adjustFireLoss(damage_amount)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
id = "abductor"
|
||||
say_mod = "gibbers"
|
||||
sexes = FALSE
|
||||
species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL)
|
||||
species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL,CAN_SCAR)
|
||||
inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_CHUNKYFINGERS,TRAIT_NOHUNGER,TRAIT_NOBREATH)
|
||||
mutanttongue = /obj/item/organ/tongue/abductor
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "Angel"
|
||||
id = "angel"
|
||||
default_color = "FFFFFF"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,CAN_SCAR)
|
||||
mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "wings" = "Angel")
|
||||
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
|
||||
no_equip = list(SLOT_BACK)
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
id = "insect"
|
||||
say_mod = "chitters"
|
||||
default_color = "00FF00"
|
||||
species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR)
|
||||
species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,CAN_SCAR)
|
||||
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
|
||||
mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None",
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None",
|
||||
"insect_wings" = "None", "insect_fluff" = "None", "mam_snouts" = "None", "taur" = "None", "insect_markings" = "None")
|
||||
attack_verb = "slash"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
id = "dullahan"
|
||||
default_color = "FFFFFF"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
|
||||
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
|
||||
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH,CAN_SCAR)
|
||||
mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "deco_wings" = "None")
|
||||
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
|
||||
mutant_brain = /obj/item/organ/brain/dullahan
|
||||
|
||||
@@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
name = "Dwarf"
|
||||
id = "dwarf" //Also called Homo sapiens pumilionis
|
||||
default_color = "FFFFFF"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,CAN_SCAR)
|
||||
inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB)
|
||||
limbs_id = "human"
|
||||
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "Anthromorphic Fly"
|
||||
id = "fly"
|
||||
say_mod = "buzzes"
|
||||
species_traits = list(NOEYES)
|
||||
species_traits = list(NOEYES,CAN_SCAR)
|
||||
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
|
||||
mutanttongue = /obj/item/organ/tongue/fly
|
||||
mutantliver = /obj/item/organ/liver/fly
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
id = "mammal"
|
||||
default_color = "4B4B4B"
|
||||
icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR)
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,CAN_SCAR)
|
||||
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST
|
||||
mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None",
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None",
|
||||
"mam_body_markings" = "Husky", "taur" = "None", "horns" = "None", "legs" = "Plantigrade", "meat_type" = "Mammalian")
|
||||
attack_verb = "claw"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
@@ -55,7 +55,7 @@
|
||||
say_mod = "hisses"
|
||||
default_color = "00FF00"
|
||||
icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,LIPS)
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
|
||||
mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade")
|
||||
attack_verb = "slash"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
|
||||
@@ -422,9 +422,9 @@
|
||||
else
|
||||
reactive_teleport(H)
|
||||
|
||||
/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
|
||||
/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags)
|
||||
..()
|
||||
if(world.time > last_teleport + teleport_cooldown && M != H && M.a_intent != INTENT_HELP)
|
||||
if(world.time > last_teleport + teleport_cooldown && M != H && act_intent != INTENT_HELP)
|
||||
reactive_teleport(H)
|
||||
|
||||
/datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
|
||||
@@ -519,9 +519,9 @@
|
||||
var/golem_name = "[uppertext(clown_name)]"
|
||||
return golem_name
|
||||
|
||||
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
|
||||
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags)
|
||||
..()
|
||||
if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP)
|
||||
if(world.time > last_banana + banana_cooldown && M != H && act_intent != INTENT_HELP)
|
||||
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
|
||||
last_banana = world.time
|
||||
|
||||
@@ -830,9 +830,9 @@
|
||||
if(world.time > last_gong_time + gong_cooldown)
|
||||
gong(H)
|
||||
|
||||
/datum/species/golem/bronze/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
|
||||
/datum/species/golem/bronze/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags)
|
||||
..()
|
||||
if(world.time > last_gong_time + gong_cooldown && M.a_intent != INTENT_HELP)
|
||||
if(world.time > last_gong_time + gong_cooldown && act_intent != INTENT_HELP)
|
||||
gong(H)
|
||||
|
||||
/datum/species/golem/bronze/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
id = "human"
|
||||
default_color = "FFFFFF"
|
||||
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR)
|
||||
mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None")
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,CAN_SCAR)
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None")
|
||||
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
|
||||
skinned_type = /obj/item/stack/sheet/animalhide/human
|
||||
disliked_food = GROSS | RAW
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR)
|
||||
mutantlungs = /obj/item/organ/lungs/slime
|
||||
mutant_heart = /obj/item/organ/heart/slime
|
||||
mutant_bodyparts = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None")
|
||||
inherent_traits = list(TRAIT_TOXINLOVER)
|
||||
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
|
||||
gib_types = list(/obj/effect/gibspawner/slime, /obj/effect/gibspawner/slime/bodypartless)
|
||||
@@ -443,7 +443,7 @@
|
||||
default_color = "00FFFF"
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
|
||||
inherent_traits = list(TRAIT_TOXINLOVER)
|
||||
mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
|
||||
say_mod = "says"
|
||||
hair_color = "mutcolor"
|
||||
hair_alpha = 160 //a notch brighter so it blends better.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
id = "lizard"
|
||||
say_mod = "hisses"
|
||||
default_color = "00FF00"
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR)
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,CAN_SCAR)
|
||||
mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur", "deco_wings")
|
||||
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
|
||||
mutanttongue = /obj/item/organ/tongue/lizard
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
nojumpsuit = TRUE
|
||||
|
||||
say_mod = "poofs" //what does a mushroom sound like
|
||||
species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL)
|
||||
species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL,CAN_SCAR)
|
||||
inherent_traits = list(TRAIT_NOBREATH)
|
||||
speedmod = 1.5 //faster than golems but not by much
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
name = "Anthromorphic Plant"
|
||||
id = "pod"
|
||||
default_color = "59CE00"
|
||||
species_traits = list(MUTCOLORS,EYECOLOR)
|
||||
species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR)
|
||||
attack_verb = "slash"
|
||||
attack_sound = 'sound/weapons/slice.ogg'
|
||||
miss_sound = 'sound/weapons/slashmiss.ogg'
|
||||
@@ -64,7 +64,7 @@
|
||||
name = "Anthromorphic Plant"
|
||||
id = "podweak"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
|
||||
mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
|
||||
limbs_id = "pod"
|
||||
light_nutrition_gain_factor = 3
|
||||
light_bruteheal = -0.2
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
blacklisted = 1
|
||||
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
|
||||
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
|
||||
species_traits = list(NOBLOOD,NOEYES)
|
||||
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH)
|
||||
species_traits = list(NOBLOOD,NOEYES,CAN_SCAR)
|
||||
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH,CAN_SCAR)
|
||||
|
||||
dangerous_existence = 1
|
||||
mutanteyes = /obj/item/organ/eyes/night_vision
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD)
|
||||
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
|
||||
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
|
||||
mutant_bodyparts = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
|
||||
mutant_bodyparts = list("mcolor" = "FFFFFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None")
|
||||
exotic_bloodtype = "U"
|
||||
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
|
||||
mutant_heart = /obj/item/organ/heart/vampire
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
sexes = 0
|
||||
blacklisted = 1
|
||||
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
|
||||
species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING)
|
||||
species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING,CAN_SCAR)
|
||||
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH)
|
||||
inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID
|
||||
mutanttongue = /obj/item/organ/tongue/zombie
|
||||
@@ -33,7 +33,7 @@
|
||||
limbs_id = "zombie"
|
||||
mutanthands = /obj/item/zombie_hand
|
||||
armor = 20 // 120 damage to KO a zombie, which kills it
|
||||
speedmod = 1.6
|
||||
speedmod = 1.6 // they're very slow
|
||||
mutanteyes = /obj/item/organ/eyes/night_vision/zombie
|
||||
var/heal_rate = 1
|
||||
var/regen_cooldown = 0
|
||||
@@ -41,11 +41,10 @@
|
||||
/datum/species/zombie/infectious/check_roundstart_eligible()
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount)
|
||||
. = min(20, amount)
|
||||
|
||||
/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE)
|
||||
/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
|
||||
. = ..()
|
||||
if(.)
|
||||
regen_cooldown = world.time + REGENERATION_DELAY
|
||||
@@ -62,6 +61,10 @@
|
||||
heal_amt *= 2
|
||||
C.heal_overall_damage(heal_amt,heal_amt)
|
||||
C.adjustToxLoss(-heal_amt)
|
||||
for(var/i in C.all_wounds)
|
||||
var/datum/wound/W = i
|
||||
if(prob(4-W.severity))
|
||||
W.remove_wound()
|
||||
if(!C.InCritical() && prob(4))
|
||||
playsound(C, pick(spooks), 50, TRUE, 10)
|
||||
|
||||
@@ -85,6 +88,11 @@
|
||||
infection = new()
|
||||
infection.Insert(C)
|
||||
|
||||
//make their bodyparts stamina-resistant
|
||||
var/incoming_stam_mult = 0.7
|
||||
for(var/obj/item/bodypart/part in C.bodyparts)
|
||||
part.incoming_stam_mult = incoming_stam_mult
|
||||
//todo: add negative wound resistance to all parts when wounds is merged (zombies are physically weak in terms of limbs)
|
||||
|
||||
// Your skin falls off
|
||||
/datum/species/krokodil_addict
|
||||
|
||||
@@ -404,6 +404,12 @@
|
||||
if(stat != DEAD || D.process_dead)
|
||||
D.stage_act()
|
||||
|
||||
/mob/living/carbon/handle_wounds()
|
||||
for(var/thing in all_wounds)
|
||||
var/datum/wound/W = thing
|
||||
if(W.processes) // meh
|
||||
W.handle_process()
|
||||
|
||||
//todo generalize this and move hud out
|
||||
/mob/living/carbon/proc/handle_changeling()
|
||||
if(mind && hud_used && hud_used.lingchemdisplay)
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
//These have to be after the parent new to ensure that the monkey
|
||||
//bodyparts are actually created before we try to equip things to
|
||||
//those slots
|
||||
if(ancestor_chain > 1)
|
||||
generate_fake_scars(rand(ancestor_chain, ancestor_chain * 4))
|
||||
if(relic_hat)
|
||||
equip_to_slot_or_del(new relic_hat, SLOT_HEAD)
|
||||
if(relic_mask)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* Returns TRUE if damage applied
|
||||
*/
|
||||
/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
|
||||
/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
|
||||
var/hit_percent = (100-blocked)/100
|
||||
if(!damage || (hit_percent <= 0))
|
||||
return 0
|
||||
@@ -245,7 +245,7 @@
|
||||
update_stamina()
|
||||
|
||||
// damage ONE external organ, organ gets randomly selected from damaged ones.
|
||||
/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE)
|
||||
/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
|
||||
adjustBruteLoss(brute, FALSE) //zero as argument for no instant health update
|
||||
adjustFireLoss(burn, FALSE)
|
||||
adjustStaminaLoss(stamina, FALSE)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this.
|
||||
*/
|
||||
/mob/living/proc/Life(seconds, times_fired)
|
||||
set waitfor = FALSE // yeah hey we're kind of on a subsystem, no sleeping will be tolerated here!
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
if(mob_transforming)
|
||||
return
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
/mob/living/proc/BiologicalLife(seconds, times_fired)
|
||||
handle_diseases()// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not.
|
||||
|
||||
handle_wounds()
|
||||
|
||||
// Everything after this shouldn't process while dead (as of the time of writing)
|
||||
if(stat == DEAD)
|
||||
return FALSE
|
||||
@@ -80,7 +82,7 @@
|
||||
handle_diginvis() //AI becomes unable to see mob
|
||||
|
||||
if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
|
||||
float(on = TRUE)
|
||||
INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE)
|
||||
|
||||
if(!loc)
|
||||
return FALSE
|
||||
@@ -109,6 +111,9 @@
|
||||
/mob/living/proc/handle_diseases()
|
||||
return
|
||||
|
||||
/mob/living/proc/handle_wounds()
|
||||
return
|
||||
|
||||
/mob/living/proc/handle_diginvis()
|
||||
if(!digitaldisguise)
|
||||
src.digitaldisguise = image(loc = src)
|
||||
|
||||
@@ -636,7 +636,7 @@
|
||||
TH.transfer_mob_blood_dna(src)
|
||||
|
||||
/mob/living/carbon/human/makeTrail(turf/T)
|
||||
if((NOBLOOD in dna.species.species_traits) || !bleed_rate || bleedsuppress)
|
||||
if((NOBLOOD in dna.species.species_traits) || !is_bleeding() || bleedsuppress)
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -802,7 +802,7 @@
|
||||
else
|
||||
throw_alert("gravity", /obj/screen/alert/weightless)
|
||||
if(!override && !is_flying())
|
||||
float(!has_gravity)
|
||||
INVOKE_ASYNC(src, /atom/movable.proc/float, !has_gravity)
|
||||
|
||||
/mob/living/float(on)
|
||||
if(throwing)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
data = mind.martial_art.block_parry_data
|
||||
method = MARTIAL_PARRY
|
||||
tool = mind.martial_art
|
||||
else if(combat_flags & COMBAT_FLAG_UNARMED_PARRY)
|
||||
else if((combat_flags & COMBAT_FLAG_UNARMED_PARRY) && check_unarmed_parry_activation_special())
|
||||
data = block_parry_data
|
||||
method = UNARMED_PARRY
|
||||
tool = src
|
||||
@@ -93,6 +93,12 @@
|
||||
if(I.can_active_parry())
|
||||
return I
|
||||
|
||||
/**
|
||||
* Check if we can unarmed parry
|
||||
*/
|
||||
/mob/living/proc/check_unarmed_parry_activation_special()
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Called via timer when the parry sequence ends.
|
||||
*/
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
totaldamage = block_calculate_resultant_damage(totaldamage, returnlist)
|
||||
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
|
||||
if(!P.nodamage)
|
||||
apply_damage(totaldamage, P.damage_type, def_zone, armor)
|
||||
apply_damage(totaldamage, P.damage_type, def_zone, armor, wound_bonus=P.wound_bonus, bare_wound_bonus=P.bare_wound_bonus, sharpness=P.sharpness)
|
||||
if(P.dismemberment)
|
||||
check_projectile_dismemberment(P, def_zone)
|
||||
var/missing = 100 - final_percent
|
||||
@@ -138,7 +138,7 @@
|
||||
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
|
||||
"<span class='userdanger'>You have been hit by [I].</span>")
|
||||
var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration)
|
||||
apply_damage(total_damage, dtype, impacting_zone, armor)
|
||||
apply_damage(total_damage, dtype, impacting_zone, armor, sharpness=I.sharpness)
|
||||
if(I.thrownby)
|
||||
log_combat(I.thrownby, src, "threw and hit", I)
|
||||
else
|
||||
@@ -270,10 +270,10 @@
|
||||
user.set_pull_offsets(src, grab_state)
|
||||
return 1
|
||||
|
||||
/mob/living/attack_hand(mob/user)
|
||||
/mob/living/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
..() //Ignoring parent return value here.
|
||||
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user)
|
||||
if((user != src) && user.a_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
|
||||
if((user != src) && act_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE | ((unarmed_attack_flags & UNARMED_ATTACK_PARRY)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE), null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS))
|
||||
log_combat(user, src, "attempted to touch")
|
||||
visible_message("<span class='warning'>[user] attempted to touch [src]!</span>",
|
||||
"<span class='warning'>[user] attempted to touch you!</span>", target = user,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
|
||||
/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE)
|
||||
var/hit_percent = (100-blocked)/100
|
||||
if(!damage || (!forced && hit_percent <= 0))
|
||||
return 0
|
||||
|
||||
@@ -2,7 +2,18 @@
|
||||
//as they handle all relevant stuff like adding it to the player's screen and such
|
||||
|
||||
//Returns the thing in our active hand (whatever is in our active module-slot, in this case)
|
||||
//This proc has been butchered into a proc that overrides borg item holding for the sake of making grippers work.
|
||||
//I'd be immensely thankful if anyone can figure out a less obtuse way of making grippers work without breaking functionality.
|
||||
/mob/living/silicon/robot/get_active_held_item()
|
||||
var/item = module_active
|
||||
if(istype(item, /obj/item/weapon/gripper))
|
||||
var/obj/item/weapon/gripper/G = item
|
||||
if(G.wrapped)
|
||||
if(G.wrapped.loc != G)
|
||||
G.wrapped = null
|
||||
return module_active
|
||||
item = G.wrapped
|
||||
return item
|
||||
return module_active
|
||||
|
||||
|
||||
|
||||
@@ -324,7 +324,7 @@
|
||||
/obj/item/crowbar/cyborg,
|
||||
/obj/item/healthanalyzer,
|
||||
/obj/item/reagent_containers/borghypo,
|
||||
/obj/item/reagent_containers/glass/beaker/large,
|
||||
/obj/item/weapon/gripper/medical,
|
||||
/obj/item/reagent_containers/dropper,
|
||||
/obj/item/reagent_containers/syringe,
|
||||
/obj/item/surgical_drapes,
|
||||
@@ -334,9 +334,11 @@
|
||||
/obj/item/surgicaldrill,
|
||||
/obj/item/scalpel,
|
||||
/obj/item/circular_saw,
|
||||
/obj/item/bonesetter,
|
||||
/obj/item/roller/robo,
|
||||
/obj/item/borg/cyborghug/medical,
|
||||
/obj/item/stack/medical/gauze/cyborg,
|
||||
/obj/item/stack/medical/bone_gel/cyborg,
|
||||
/obj/item/organ_storage,
|
||||
/obj/item/borg/lollipop,
|
||||
/obj/item/sensor_device,
|
||||
@@ -444,7 +446,7 @@
|
||||
/obj/item/t_scanner,
|
||||
/obj/item/analyzer,
|
||||
/obj/item/storage/part_replacer/cyborg,
|
||||
/obj/item/holosign_creator/atmos,
|
||||
/obj/item/holosign_creator/combifan,
|
||||
/obj/item/weapon/gripper,
|
||||
/obj/item/lightreplacer/cyborg,
|
||||
/obj/item/geiger_counter/cyborg,
|
||||
@@ -779,9 +781,8 @@
|
||||
/obj/item/toy/crayon/spraycan/borg,
|
||||
/obj/item/hand_labeler/borg,
|
||||
/obj/item/razor,
|
||||
/obj/item/rsf,
|
||||
/obj/item/instrument/violin,
|
||||
/obj/item/instrument/guitar,
|
||||
/obj/item/rsf/cyborg,
|
||||
/obj/item/instrument/piano_synth,
|
||||
/obj/item/reagent_containers/dropper,
|
||||
/obj/item/lighter,
|
||||
/obj/item/storage/bag/tray,
|
||||
@@ -1051,6 +1052,8 @@
|
||||
/obj/item/cautery,
|
||||
/obj/item/surgicaldrill,
|
||||
/obj/item/scalpel,
|
||||
/obj/item/bonesetter,
|
||||
/obj/item/stack/medical/bone_gel,
|
||||
/obj/item/melee/transforming/energy/sword/cyborg/saw,
|
||||
/obj/item/roller/robo,
|
||||
/obj/item/card/emag,
|
||||
|
||||
@@ -102,6 +102,10 @@
|
||||
var/can_salute = TRUE
|
||||
var/salute_delay = 60 SECONDS
|
||||
|
||||
//emotes/speech stuff
|
||||
var/patrol_emote = "Engaging patrol mode."
|
||||
var/patrol_fail_emote = "Unable to start patrol."
|
||||
|
||||
/mob/living/simple_animal/bot/proc/get_mode()
|
||||
if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
|
||||
if(paicard)
|
||||
@@ -612,7 +616,7 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
if(tries >= BOT_STEP_MAX_RETRIES) //Bot is trapped, so stop trying to patrol.
|
||||
auto_patrol = 0
|
||||
tries = 0
|
||||
speak("Unable to start patrol.")
|
||||
speak(patrol_fail_emote)
|
||||
|
||||
return
|
||||
|
||||
@@ -628,7 +632,7 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
return
|
||||
mode = BOT_PATROL
|
||||
else // no patrol target, so need a new one
|
||||
speak("Engaging patrol mode.")
|
||||
speak(patrol_emote)
|
||||
find_patrol_target()
|
||||
tries++
|
||||
return
|
||||
|
||||
@@ -341,7 +341,7 @@
|
||||
|
||||
target_types = typecacheof(target_types)
|
||||
|
||||
/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(istype(A, /obj/effect/decal/cleanable))
|
||||
anchored = TRUE
|
||||
icon_state = "cleanbot-c"
|
||||
|
||||
@@ -518,7 +518,7 @@ Auto Patrol[]"},
|
||||
/mob/living/simple_animal/bot/ed209/redtag
|
||||
lasercolor = "r"
|
||||
|
||||
/mob/living/simple_animal/bot/ed209/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/bot/ed209/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(!on)
|
||||
return
|
||||
if(iscarbon(A))
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
internal_ext.max_water = INFINITY
|
||||
internal_ext.refill()
|
||||
|
||||
/mob/living/simple_animal/bot/firebot/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/bot/firebot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(!on)
|
||||
return
|
||||
if(internal_ext)
|
||||
|
||||
@@ -413,7 +413,7 @@
|
||||
/obj/machinery/bot_core/floorbot
|
||||
req_one_access = list(ACCESS_CONSTRUCTION, ACCESS_ROBOTICS)
|
||||
|
||||
/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(isturf(A))
|
||||
repair(A)
|
||||
else
|
||||
|
||||
@@ -141,7 +141,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
retaliate(Proj.firer)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/bot/honkbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(!on)
|
||||
return
|
||||
if(iscarbon(A))
|
||||
@@ -367,4 +367,4 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
..()
|
||||
|
||||
/obj/machinery/bot_core/honkbot
|
||||
req_one_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
req_one_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
|
||||
@@ -625,7 +625,7 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/bot/medbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
patient = C
|
||||
@@ -790,4 +790,4 @@
|
||||
#undef MEDBOT_PANIC_HIGH
|
||||
#undef MEDBOT_PANIC_FUCK
|
||||
#undef MEDBOT_PANIC_ENDING
|
||||
#undef MEDBOT_PANIC_END
|
||||
#undef MEDBOT_PANIC_END
|
||||
|
||||
@@ -752,7 +752,7 @@
|
||||
if(load)
|
||||
unload()
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/bot/mulebot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(isturf(A) && isturf(loc) && loc.Adjacent(A) && load)
|
||||
unload(get_dir(loc, A))
|
||||
else
|
||||
|
||||
@@ -33,6 +33,20 @@
|
||||
var/check_records = TRUE //Does it check security records?
|
||||
var/arrest_type = FALSE //If true, don't handcuff
|
||||
|
||||
var/obj/item/clothing/head/bot_accessory
|
||||
var/datum/beepsky_fashion/stored_fashion
|
||||
|
||||
//emotes (BOT is replaced with bot name, CRIMINAL with criminal name, THREAT_LEVEL with threat level)
|
||||
var/death_emote = "BOT blows apart!"
|
||||
var/capture_one = "BOT is trying to put zipties on CRIMINAL!"
|
||||
var/capture_two = "BOT is trying to put zipties on you!"
|
||||
var/infraction = "Level THREAT_LEVEL infraction alert!"
|
||||
var/taunt = "<b>BOT</b> points at CRIMINAL!"
|
||||
var/attack_one = "BOT has stunned CRIMINAL!"
|
||||
var/attack_two = "BOT has stunned you!"
|
||||
var/list/arrest_texts = list("Detaining", "Arresting")
|
||||
var/arrest_emote = "ARREST_TYPE level THREAT_LEVEL scumbag CRIMINAL in LOCATION."
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky
|
||||
name = "Officer Beep O'sky"
|
||||
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
|
||||
@@ -49,6 +63,103 @@
|
||||
resize = 0.8
|
||||
update_transform()
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/process_emote(var/emote_type, var/atom/criminal, var/threat, var/arrest = -1, var/location)
|
||||
var/emote = "The continuity of space itself collapses around [src]. You should probably report that to someone higher up."
|
||||
switch(emote_type)
|
||||
if("DEATH")
|
||||
emote = death_emote
|
||||
if("CAPTURE_ONE")
|
||||
emote = capture_one
|
||||
if("CAPTURE_TWO")
|
||||
emote = capture_two
|
||||
if("INFRACTION")
|
||||
emote = infraction
|
||||
if("TAUNT")
|
||||
emote = taunt
|
||||
if("ATTACK_ONE")
|
||||
emote = attack_one
|
||||
if("ATTACK_TWO")
|
||||
emote = attack_two
|
||||
if("ARREST")
|
||||
emote = arrest_emote
|
||||
|
||||
//now replace pieces of the text with the information we have
|
||||
if(emote_type != "TAUNT" && emote_type != "ARREST")
|
||||
emote = replacetext(emote, "BOT", name)
|
||||
else
|
||||
emote = replacetext(emote, "BOT", "<b>[name]</b>") //needs to be bold if its a taunt or an arrest text
|
||||
if(criminal)
|
||||
emote = replacetext(emote, "CRIMINAL", criminal.name)
|
||||
if(threat)
|
||||
emote = replacetext(emote, "THREAT_LEVEL", threat)
|
||||
if(arrest > -1)
|
||||
emote = replacetext(emote, "ARREST_TYPE", arrest_texts[arrest + 1])
|
||||
if(location)
|
||||
emote = replacetext(emote, "LOCATION", location)
|
||||
return emote
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/apply_fashion(var/datum/beepsky_fashion/fashion)
|
||||
stored_fashion = new fashion
|
||||
if(stored_fashion.name)
|
||||
name = stored_fashion.name
|
||||
|
||||
if(stored_fashion.desc)
|
||||
desc = stored_fashion.desc
|
||||
|
||||
if(stored_fashion.death_emote)
|
||||
death_emote = stored_fashion.death_emote
|
||||
|
||||
if(stored_fashion.capture_one)
|
||||
capture_one = stored_fashion.capture_one
|
||||
|
||||
if(stored_fashion.capture_two)
|
||||
capture_two = stored_fashion.capture_two
|
||||
|
||||
if(stored_fashion.infraction)
|
||||
infraction = stored_fashion.infraction
|
||||
|
||||
if(stored_fashion.taunt)
|
||||
taunt = stored_fashion.taunt
|
||||
|
||||
if(stored_fashion.attack_one)
|
||||
attack_one = stored_fashion.attack_one
|
||||
|
||||
if(stored_fashion.attack_two)
|
||||
attack_two = stored_fashion.attack_two
|
||||
|
||||
if(stored_fashion.patrol_emote)
|
||||
patrol_emote = stored_fashion.patrol_emote
|
||||
|
||||
if(stored_fashion.patrol_fail_emote)
|
||||
patrol_fail_emote = stored_fashion.patrol_fail_emote
|
||||
|
||||
if(stored_fashion.arrest_texts)
|
||||
arrest_texts = stored_fashion.arrest_texts
|
||||
|
||||
if(stored_fashion.arrest_emote)
|
||||
arrest_emote = stored_fashion.arrest_emote
|
||||
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/reset_fashion()
|
||||
bot_accessory.forceMove(get_turf(src))
|
||||
//reset all emotes/sounds and name/desc
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
death_emote = initial(death_emote)
|
||||
capture_one = initial(capture_one)
|
||||
capture_two = initial(capture_two)
|
||||
infraction = initial(infraction)
|
||||
taunt = initial(taunt)
|
||||
attack_one = initial(attack_one)
|
||||
attack_two = initial(attack_two)
|
||||
arrest_texts = initial(arrest_texts)
|
||||
arrest_emote = initial(arrest_emote)
|
||||
patrol_emote = initial(patrol_emote)
|
||||
arrest_texts = initial(arrest_texts)
|
||||
arrest_emote = initial(arrest_emote)
|
||||
bot_accessory = null
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky/explode()
|
||||
var/atom/Tsec = drop_location()
|
||||
@@ -178,6 +289,11 @@ Auto Patrol: []"},
|
||||
retaliate(H)
|
||||
if(special_retaliate_after_attack(H))
|
||||
return
|
||||
if(H.a_intent == INTENT_HELP && bot_accessory)
|
||||
|
||||
to_chat(H, "<span class='warning'>You knock [bot_accessory] off of [src]'s head!</span>")
|
||||
reset_fashion()
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -185,11 +301,48 @@ Auto Patrol: []"},
|
||||
..()
|
||||
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry.
|
||||
return
|
||||
if(istype(W, /obj/item/clothing/head))
|
||||
attempt_place_on_head(user, W)
|
||||
return
|
||||
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
|
||||
retaliate(user)
|
||||
if(special_retaliate_after_attack(user))
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/attempt_place_on_head(mob/user, obj/item/clothing/head/H)
|
||||
if(user && !user.temporarilyRemoveItemFromInventory(H))
|
||||
to_chat(user, "<span class='warning'>\The [H] is stuck to your hand, you cannot put it on [src]'s head!</span>")
|
||||
return
|
||||
if(bot_accessory)
|
||||
to_chat("<span class='warning'>\[src] already has an accessory, and the laws of physics disallow him from wearing a second!</span>")
|
||||
return
|
||||
|
||||
if(H.beepsky_fashion)
|
||||
to_chat(user, "<span class='warning'>You set [H] on [src].</span>")
|
||||
bot_accessory = H
|
||||
H.forceMove(src)
|
||||
apply_fashion(H.beepsky_fashion)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You set [H] on [src]'s head, but it falls off!</span>")
|
||||
H.forceMove(drop_location())
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/regenerate_icons()
|
||||
..()
|
||||
if(bot_accessory)
|
||||
if(!stored_fashion)
|
||||
stored_fashion = new bot_accessory.beepsky_fashion
|
||||
if(!stored_fashion.obj_icon_state)
|
||||
stored_fashion.obj_icon_state = bot_accessory.icon_state
|
||||
if(!stored_fashion.obj_alpha)
|
||||
stored_fashion.obj_alpha = bot_accessory.alpha
|
||||
if(!stored_fashion.obj_color)
|
||||
stored_fashion.obj_color = bot_accessory.color
|
||||
add_overlay(stored_fashion.get_overlay())
|
||||
else
|
||||
if(stored_fashion)
|
||||
cut_overlay(stored_fashion.get_overlay())
|
||||
stored_fashion = null
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(emagged == 2)
|
||||
@@ -208,7 +361,7 @@ Auto Patrol: []"},
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/UnarmedAttack(atom/A)
|
||||
/mob/living/simple_animal/bot/secbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE)
|
||||
if(!on)
|
||||
return
|
||||
if(iscarbon(A))
|
||||
@@ -233,8 +386,8 @@ Auto Patrol: []"},
|
||||
/mob/living/simple_animal/bot/secbot/proc/cuff(mob/living/carbon/C)
|
||||
mode = BOT_ARREST
|
||||
playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2)
|
||||
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
|
||||
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
|
||||
C.visible_message("<span class='danger'>[process_emote("CAPTURE_ONE", C)]</span>",\
|
||||
"<span class='userdanger'>[process_emote("CAPTURE_TWO", C)]</span>")
|
||||
if(do_after(src, 60, FALSE, C))
|
||||
attempt_handcuff(C)
|
||||
|
||||
@@ -249,16 +402,22 @@ Auto Patrol: []"},
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C)
|
||||
var/judgement_criteria = judgement_criteria()
|
||||
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
|
||||
icon_state = "secbot-c"
|
||||
addtimer(CALLBACK(src, /atom/.proc/update_icon), 2)
|
||||
var/threat = 5
|
||||
if(ishuman(C))
|
||||
if(stored_fashion)
|
||||
stored_fashion.stun_attack(C)
|
||||
if(stored_fashion.stun_sounds && !stored_fashion.ignore_sound)
|
||||
playsound(src, pick(stored_fashion.stun_sounds), 50, TRUE, -1)
|
||||
else
|
||||
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
|
||||
C.stuttering = 5
|
||||
C.DefaultCombatKnockdown(100)
|
||||
var/mob/living/carbon/human/H = C
|
||||
threat = H.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
|
||||
else
|
||||
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
|
||||
C.DefaultCombatKnockdown(100)
|
||||
C.stuttering = 5
|
||||
threat = C.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
|
||||
@@ -266,9 +425,9 @@ Auto Patrol: []"},
|
||||
log_combat(src,C,"stunned")
|
||||
if(declare_arrests)
|
||||
var/area/location = get_area(src)
|
||||
speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag <b>[C]</b> in [location].", radio_channel)
|
||||
C.visible_message("<span class='danger'>[src] has stunned [C]!</span>",\
|
||||
"<span class='userdanger'>[src] has stunned you!</span>")
|
||||
speak(process_emote("ARREST", C, threat, arrest_type, location), radio_channel)
|
||||
C.visible_message("<span class='danger'>[process_emote("ATTACK_ONE", C)]</span>",\
|
||||
"<span class='userdanger'>[process_emote("ATTACK_TWO", C)]</span>")
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/handle_automated_action()
|
||||
if(!..())
|
||||
@@ -355,7 +514,6 @@ Auto Patrol: []"},
|
||||
look_for_perp()
|
||||
bot_patrol()
|
||||
|
||||
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/proc/back_to_idle()
|
||||
@@ -391,9 +549,9 @@ Auto Patrol: []"},
|
||||
else if(threatlevel >= 4)
|
||||
target = C
|
||||
oldtarget_name = C.name
|
||||
speak("Level [threatlevel] infraction alert!")
|
||||
speak(process_emote("INFRACTION", target, threatlevel))
|
||||
playsound(loc, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE)
|
||||
visible_message("<b>[src]</b> points at [C.name]!")
|
||||
visible_message(process_emote("TAUNT", target, threatlevel))
|
||||
mode = BOT_HUNT
|
||||
INVOKE_ASYNC(src, .proc/handle_automated_action)
|
||||
break
|
||||
@@ -408,7 +566,7 @@ Auto Patrol: []"},
|
||||
/mob/living/simple_animal/bot/secbot/explode()
|
||||
|
||||
walk_to(src,0)
|
||||
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
|
||||
visible_message("<span class='boldannounce'>[process_emote("DEATH")]</span>")
|
||||
var/atom/Tsec = drop_location()
|
||||
|
||||
var/obj/item/bot_assembly/secbot/Sa = new (Tsec)
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
detonate(user)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/guardian_bomb/attack_hand(mob/living/user)
|
||||
/obj/guardian_bomb/attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
detonate(user)
|
||||
|
||||
/obj/guardian_bomb/examine(mob/user)
|
||||
|
||||
@@ -29,8 +29,11 @@
|
||||
var/armored = FALSE
|
||||
|
||||
obj_damage = 60
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 30
|
||||
melee_damage_lower = 15 // i know it's like half what it used to be, but bears cause bleeding like crazy now so it works out
|
||||
melee_damage_upper = 15
|
||||
wound_bonus = -5
|
||||
bare_wound_bonus = 10 // BEAR wound bonus am i right
|
||||
sharpness = TRUE
|
||||
attack_verb_continuous = "claws"
|
||||
attack_verb_simple = "claw"
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
@@ -69,8 +72,9 @@
|
||||
icon_dead = "combatbear_dead"
|
||||
faction = list("russian")
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1, /obj/item/bear_armor = 1)
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 35
|
||||
melee_damage_lower = 18
|
||||
melee_damage_upper = 20
|
||||
wound_bonus = 0
|
||||
armour_penetration = 20
|
||||
health = 120
|
||||
maxHealth = 120
|
||||
@@ -99,8 +103,9 @@
|
||||
A.maxHealth += 60
|
||||
A.health += 60
|
||||
A.armour_penetration += 20
|
||||
A.melee_damage_lower += 5
|
||||
A.melee_damage_lower += 3
|
||||
A.melee_damage_upper += 5
|
||||
A.wound_bonus += 5
|
||||
A.update_icons()
|
||||
to_chat(user, "<span class='info'>You strap the armor plating to [A] and sharpen [A.p_their()] claws with the nail filer. This was a great idea.</span>")
|
||||
qdel(src)
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
/obj/structure/leaper_bubble/Initialize()
|
||||
. = ..()
|
||||
float(on = TRUE)
|
||||
INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE)
|
||||
QDEL_IN(src, 100)
|
||||
|
||||
/obj/structure/leaper_bubble/Destroy()
|
||||
|
||||
@@ -385,7 +385,7 @@ Difficulty: Very Hard
|
||||
if(isliving(speaker))
|
||||
ActivationReaction(speaker, ACTIVATE_SPEECH)
|
||||
|
||||
/obj/machinery/anomalous_crystal/attack_hand(mob/user)
|
||||
/obj/machinery/anomalous_crystal/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
#define SWOOP_DAMAGEABLE 1
|
||||
#define SWOOP_INVULNERABLE 2
|
||||
|
||||
///used whenever the drake generates a hotspot
|
||||
#define DRAKE_FIRE_TEMP 500
|
||||
///used whenever the drake generates a hotspot
|
||||
#define DRAKE_FIRE_EXPOSURE 50
|
||||
|
||||
/*
|
||||
|
||||
ASH DRAKE
|
||||
@@ -148,7 +153,7 @@ Difficulty: Medium
|
||||
break
|
||||
range--
|
||||
new /obj/effect/hotspot(J)
|
||||
J.hotspot_expose(700,50,1)
|
||||
J.hotspot_expose(DRAKE_FIRE_TEMP, DRAKE_FIRE_EXPOSURE, 1)
|
||||
for(var/mob/living/L in J.contents - hit_things)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon))
|
||||
continue
|
||||
@@ -404,7 +409,7 @@ Difficulty: Medium
|
||||
if(istype(T, /turf/closed))
|
||||
break
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
T.hotspot_expose(DRAKE_FIRE_TEMP,DRAKE_FIRE_EXPOSURE,1)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L in hit_list || L == source)
|
||||
continue
|
||||
|
||||
@@ -643,7 +643,7 @@ Difficulty: Normal
|
||||
to_chat(L, "<span class='userdanger'>You're struck by a [name]!</span>")
|
||||
var/limb_to_hit = L.get_bodypart(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
|
||||
var/armor = L.run_armor_check(limb_to_hit, "melee", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!")
|
||||
L.apply_damage(damage, BURN, limb_to_hit, armor)
|
||||
L.apply_damage(damage, BURN, limb_to_hit, armor, wound_bonus=CANT_WOUND)
|
||||
if(ishostile(L))
|
||||
var/mob/living/simple_animal/hostile/H = L //mobs find and damage you...
|
||||
if(H.stat == CONSCIOUS && !H.target && H.AIStatus != AI_OFF && !H.client)
|
||||
|
||||
@@ -52,6 +52,8 @@ Difficulty: Medium
|
||||
elimination = 1
|
||||
appearance_flags = 0
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
wound_bonus = -40
|
||||
bare_wound_bonus = 20
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -129,7 +129,7 @@ Difficulty: Hard
|
||||
to_chat(L, "<span class='userdanger'>[src]'s ground slam shockwave sends you flying!</span>")
|
||||
var/turf/thrownat = get_ranged_target_turf_direct(src, L, 8, rand(-10, 10))
|
||||
L.throw_at(thrownat, 8, 2, src, TRUE) //, force = MOVE_FORCE_OVERPOWERING, gentle = TRUE)
|
||||
L.apply_damage(20, BRUTE)
|
||||
L.apply_damage(20, BRUTE, wound_bonus=CANT_WOUND)
|
||||
shake_camera(L, 2, 1)
|
||||
all_turfs -= T
|
||||
sleep(delay)
|
||||
|
||||
@@ -148,7 +148,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
desc = "You're not quite sure how a signal can be menacing."
|
||||
invisibility = 100
|
||||
|
||||
/obj/structure/elite_tumor/attack_hand(mob/user)
|
||||
/obj/structure/elite_tumor/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
. = ..()
|
||||
if(ishuman(user))
|
||||
switch(activity)
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
.=..()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
/obj/structure/spawner/nether/attack_hand(mob/user)
|
||||
/obj/structure/spawner/nether/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
user.visible_message("<span class='warning'>[user] is violently pulled into the link!</span>", \
|
||||
"<span class='userdanger'>Touching the portal, you are quickly pulled through into a world of unimaginable horror!</span>")
|
||||
contents.Add(user)
|
||||
|
||||
@@ -77,6 +77,9 @@
|
||||
/mob/living/simple_animal/hostile/syndicate/melee
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
wound_bonus = -10
|
||||
bare_wound_bonus = 20
|
||||
sharpness = TRUE
|
||||
icon_state = "syndicate_knife"
|
||||
icon_living = "syndicate_knife"
|
||||
loot = list(/obj/effect/gibspawner/human)
|
||||
|
||||
@@ -140,6 +140,13 @@
|
||||
///What kind of footstep this mob should have. Null if it shouldn't have any.
|
||||
var/footstep_type
|
||||
|
||||
//How much wounding power it has
|
||||
var/wound_bonus = CANT_WOUND
|
||||
//How much bare wounding power it has
|
||||
var/bare_wound_bonus = 0
|
||||
//If the attacks from this are sharp
|
||||
var/sharpness = FALSE
|
||||
|
||||
/mob/living/simple_animal/Initialize()
|
||||
. = ..()
|
||||
GLOB.simple_animals[AIStatus] += src
|
||||
|
||||
@@ -589,6 +589,8 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
|
||||
/mob/Stat()
|
||||
..()
|
||||
|
||||
SSvote?.render_statpanel(src)
|
||||
|
||||
//This is only called from client/Stat(), let's assume client exists.
|
||||
|
||||
if(statpanel("Status"))
|
||||
|
||||
@@ -123,6 +123,9 @@
|
||||
|
||||
var/list/progressbars = null //for stacking do_after bars
|
||||
|
||||
///For storing what do_after's someone has, in case we want to restrict them to only one of a certain do_after at a time
|
||||
var/list/do_afters
|
||||
|
||||
var/list/mousemove_intercept_objects
|
||||
|
||||
var/datum/click_intercept
|
||||
|
||||
Reference in New Issue
Block a user