mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2025-12-09 22:53:43 +00:00
582 lines
18 KiB
Plaintext
582 lines
18 KiB
Plaintext
|
|
/*
|
|
run_armor_check(a,b)
|
|
args
|
|
a:def_zone - What part is getting hit, if null will check entire body
|
|
b:attack_flag - What type of attack, bullet, laser, energy, melee
|
|
c:armour_pen - How much armor to ignore.
|
|
d:absorb_text - Custom text to send to the player when the armor fully absorbs an attack.
|
|
e:soften_text - Similar to absorb_text, custom text to send to the player when some damage is reduced.
|
|
|
|
Returns
|
|
A number between 0 and 100, with higher numbers resulting in less damage taken.
|
|
*/
|
|
/mob/living/proc/run_armor_check(var/def_zone = null, var/attack_flag = "melee", var/armour_pen = 0, var/absorb_text = null, var/soften_text = null)
|
|
if(GLOB.Debug2)
|
|
log_world("## DEBUG: getarmor() was called.")
|
|
|
|
if(armour_pen >= 100)
|
|
return 0 //might as well just skip the processing
|
|
|
|
var/armor = getarmor(def_zone, attack_flag)
|
|
if(armor)
|
|
var/armor_variance_range = round(armor * 0.25) //Armor's effectiveness has a +25%/-25% variance.
|
|
var/armor_variance = rand(-armor_variance_range, armor_variance_range) //Get a random number between -25% and +25% of the armor's base value
|
|
if(GLOB.Debug2)
|
|
log_world("## DEBUG: The range of armor variance is [armor_variance_range]. The variance picked by RNG is [armor_variance].")
|
|
|
|
armor = min(armor + armor_variance, 100) //Now we calcuate damage using the new armor percentage.
|
|
armor = max(armor - armour_pen, 0) //Armor pen makes armor less effective.
|
|
if(armor >= 100)
|
|
if(absorb_text)
|
|
to_chat(src, "<span class='danger'>[absorb_text]</span>")
|
|
else
|
|
to_chat(src, "<span class='danger'>Your armor absorbs the blow!</span>")
|
|
|
|
else if(armor > 0)
|
|
if(soften_text)
|
|
to_chat(src, "<span class='danger'>[soften_text]</span>")
|
|
else
|
|
to_chat(src, "<span class='danger'>Your armor softens the blow!</span>")
|
|
if(GLOB.Debug2)
|
|
log_world("## DEBUG: Armor when [src] was attacked was [armor].")
|
|
return armor
|
|
|
|
/*
|
|
//Old armor code here.
|
|
if(armour_pen >= 100)
|
|
return 0 //might as well just skip the processing
|
|
|
|
var/armor = getarmor(def_zone, attack_flag)
|
|
var/absorb = 0
|
|
|
|
//Roll armour
|
|
if(prob(armor))
|
|
absorb += 1
|
|
if(prob(armor))
|
|
absorb += 1
|
|
|
|
//Roll penetration
|
|
if(prob(armour_pen))
|
|
absorb -= 1
|
|
if(prob(armour_pen))
|
|
absorb -= 1
|
|
|
|
if(absorb >= 2)
|
|
if(absorb_text)
|
|
show_message("[absorb_text]")
|
|
else
|
|
show_message("<span class='warning'>Your armor absorbs the blow!</span>")
|
|
return 2
|
|
if(absorb == 1)
|
|
if(absorb_text)
|
|
show_message("[soften_text]",4)
|
|
else
|
|
show_message("<span class='warning'>Your armor softens the blow!</span>")
|
|
return 1
|
|
return 0
|
|
*/
|
|
|
|
//Certain pieces of armor actually absorb flat amounts of damage from income attacks
|
|
/mob/living/proc/get_armor_soak(var/def_zone = null, var/attack_flag = "melee", var/armour_pen = 0)
|
|
var/soaked = getsoak(def_zone, attack_flag)
|
|
//5 points of armor pen negate one point of soak
|
|
if(armour_pen)
|
|
soaked = max(soaked - (armour_pen/5), 0)
|
|
return soaked
|
|
|
|
//if null is passed for def_zone, then this should return something appropriate for all zones (e.g. area effect damage)
|
|
/mob/living/proc/getarmor(var/def_zone, var/type)
|
|
return 0
|
|
|
|
/mob/living/proc/getsoak(var/def_zone, var/type)
|
|
return 0
|
|
|
|
// Clicking with an empty hand
|
|
/mob/living/attack_hand(mob/living/L)
|
|
..()
|
|
if(istype(L) && L.a_intent != INTENT_HELP)
|
|
if(ai_holder) // Using disarm, grab, or harm intent is considered a hostile action to the mob's AI.
|
|
ai_holder.react_to_attack(L)
|
|
|
|
/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone)
|
|
|
|
//Being hit while using a deadman switch
|
|
if(istype(get_active_hand(),/obj/item/assembly/signaler))
|
|
var/obj/item/assembly/signaler/signaler = get_active_hand()
|
|
if(signaler.deadman && prob(80))
|
|
log_and_message_admins("has triggered a signaler deadman's switch")
|
|
src.visible_message("<font color='red'>[src] triggers their deadman's switch!</font>")
|
|
signaler.signal()
|
|
|
|
if(ai_holder && P.firer)
|
|
ai_holder.react_to_attack(P.firer)
|
|
|
|
//Armor
|
|
var/soaked = get_armor_soak(def_zone, P.check_armour, P.armor_penetration)
|
|
var/absorb = run_armor_check(def_zone, P.check_armour, P.armor_penetration)
|
|
var/proj_sharp = is_sharp(P)
|
|
var/proj_edge = has_edge(P)
|
|
var/final_damage = P.get_final_damage(src)
|
|
|
|
if ((proj_sharp || proj_edge) && (soaked >= round(P.damage*0.8)))
|
|
proj_sharp = 0
|
|
proj_edge = 0
|
|
|
|
if ((proj_sharp || proj_edge) && prob(getarmor(def_zone, P.check_armour)))
|
|
proj_sharp = 0
|
|
proj_edge = 0
|
|
|
|
var/list/impact_sounds = LAZYACCESS(P.impact_sounds, get_bullet_impact_effect_type(def_zone))
|
|
if(length(impact_sounds))
|
|
playsound(src, pick(impact_sounds), 75)
|
|
|
|
//Stun Beams
|
|
if(P.taser_effect)
|
|
stun_effect_act(0, P.agony, def_zone, P)
|
|
to_chat(src, "<font color='red'>You have been hit by [P]!</font>")
|
|
if(!P.nodamage)
|
|
apply_damage(final_damage, P.damage_type, def_zone, absorb, soaked, 0, P, sharp=proj_sharp, edge=proj_edge)
|
|
qdel(P)
|
|
return
|
|
|
|
if(!P.nodamage)
|
|
apply_damage(final_damage, P.damage_type, def_zone, absorb, soaked, 0, P, sharp=proj_sharp, edge=proj_edge)
|
|
P.on_hit(src, absorb, soaked, def_zone)
|
|
|
|
if(absorb == 100)
|
|
return 2
|
|
else if (absorb >= 0)
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
// return absorb
|
|
|
|
/mob/living/get_bullet_impact_effect_type(var/def_zone)
|
|
return BULLET_IMPACT_MEAT
|
|
|
|
//Handles the effects of "stun" weapons
|
|
/mob/living/proc/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null)
|
|
flash_pain()
|
|
|
|
if (stun_amount)
|
|
Stun(stun_amount)
|
|
Weaken(stun_amount)
|
|
apply_effect(STUTTER, stun_amount)
|
|
apply_effect(EYE_BLUR, stun_amount)
|
|
|
|
if (agony_amount)
|
|
apply_damage(agony_amount, HALLOSS, def_zone, 0, used_weapon)
|
|
apply_effect(STUTTER, agony_amount/10)
|
|
apply_effect(EYE_BLUR, agony_amount/10)
|
|
|
|
/mob/living/proc/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null, var/stun = 1)
|
|
return 0 //only carbon liveforms have this proc
|
|
|
|
/mob/living/emp_act(severity)
|
|
var/list/L = src.get_contents()
|
|
for(var/obj/O in L)
|
|
O.emp_act(severity)
|
|
..()
|
|
|
|
/mob/living/blob_act(var/obj/structure/blob/B)
|
|
if(stat == DEAD || faction == "blob")
|
|
return
|
|
|
|
var/damage = rand(30, 40)
|
|
var/armor_pen = 0
|
|
var/armor_check = "melee"
|
|
var/damage_type = BRUTE
|
|
var/attack_message = "The blob attacks you!"
|
|
var/attack_verb = "attacks"
|
|
var/def_zone = pick(BP_HEAD, BP_TORSO, BP_GROIN, BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG)
|
|
|
|
if(B && B.overmind)
|
|
var/datum/blob_type/blob = B.overmind.blob_type
|
|
|
|
damage = rand(blob.damage_lower, blob.damage_upper)
|
|
armor_check = blob.armor_check
|
|
armor_pen = blob.armor_pen
|
|
damage_type = blob.damage_type
|
|
|
|
attack_message = "[blob.attack_message][isSynthetic() ? "[blob.attack_message_synth]":"[blob.attack_message_living]"]"
|
|
attack_verb = blob.attack_verb
|
|
B.overmind.blob_type.on_attack(B, src, def_zone)
|
|
|
|
if( (damage_type == TOX || damage_type == OXY) && isSynthetic()) // Borgs and FBPs don't really handle tox/oxy damage the same way other mobs do.
|
|
damage_type = BRUTE
|
|
damage *= 0.66 // Take 2/3s as much damage.
|
|
|
|
visible_message("<span class='danger'>\The [B] [attack_verb] \the [src]!</span>", "<span class='danger'>[attack_message]!</span>")
|
|
playsound(loc, 'sound/effects/attackblob.ogg', 50, 1)
|
|
|
|
//Armor
|
|
var/soaked = get_armor_soak(def_zone, armor_check, armor_pen)
|
|
var/absorb = run_armor_check(def_zone, armor_check, armor_pen)
|
|
|
|
apply_damage(damage, damage_type, def_zone, absorb, soaked)
|
|
|
|
/mob/living/proc/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
|
|
return target_zone
|
|
|
|
//Called when the mob is hit with an item in combat. Returns the blocked result
|
|
/mob/living/proc/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
|
|
visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] with [I.name] by [user]!</span>")
|
|
|
|
if(ai_holder)
|
|
ai_holder.react_to_attack(user)
|
|
|
|
var/soaked = get_armor_soak(hit_zone, "melee")
|
|
var/blocked = run_armor_check(hit_zone, "melee")
|
|
|
|
standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone)
|
|
|
|
if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too
|
|
var/turf/simulated/location = get_turf(src)
|
|
if(istype(location)) location.add_blood_floor(src)
|
|
|
|
return blocked
|
|
|
|
//returns 0 if the effects failed to apply for some reason, 1 otherwise.
|
|
/mob/living/proc/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/soaked, var/hit_zone)
|
|
if(!effective_force || blocked >= 100)
|
|
return 0
|
|
//Apply weapon damage
|
|
var/weapon_sharp = is_sharp(I)
|
|
var/weapon_edge = has_edge(I)
|
|
|
|
if(getsoak(hit_zone, "melee",) - (I.armor_penetration/5) > round(effective_force*0.8)) //soaking a hit turns sharp attacks into blunt ones
|
|
weapon_sharp = 0
|
|
weapon_edge = 0
|
|
|
|
if(prob(max(getarmor(hit_zone, "melee") - I.armor_penetration, 0))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
|
|
weapon_sharp = 0
|
|
weapon_edge = 0
|
|
|
|
apply_damage(effective_force, I.damtype, hit_zone, blocked, soaked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
|
|
|
|
return 1
|
|
|
|
//this proc handles being hit by a thrown atom
|
|
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve
|
|
if(istype(AM,/obj/))
|
|
var/obj/O = AM
|
|
var/dtype = O.damtype
|
|
var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR)
|
|
|
|
var/miss_chance = 15
|
|
if (O.throw_source)
|
|
var/distance = get_dist(O.throw_source, loc)
|
|
miss_chance = max(15*(distance-2), 0)
|
|
|
|
if (prob(miss_chance))
|
|
visible_message("<font color=#4F49AF>\The [O] misses [src] narrowly!</font>")
|
|
return
|
|
|
|
src.visible_message("<font color='red'>[src] has been hit by [O].</font>")
|
|
var/armor = run_armor_check(null, "melee")
|
|
var/soaked = get_armor_soak(null, "melee")
|
|
|
|
|
|
apply_damage(throw_damage, dtype, null, armor, soaked, is_sharp(O), has_edge(O), O)
|
|
|
|
O.throwing = 0 //it hit, so stop moving
|
|
|
|
if(ismob(O.thrower))
|
|
var/mob/M = O.thrower
|
|
var/client/assailant = M.client
|
|
if(assailant)
|
|
add_attack_logs(M,src,"Hit by thrown [O.name]")
|
|
if(ai_holder)
|
|
ai_holder.react_to_attack(O.thrower)
|
|
|
|
// Begin BS12 momentum-transfer code.
|
|
var/mass = 1.5
|
|
if(istype(O, /obj/item))
|
|
var/obj/item/I = O
|
|
mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR
|
|
var/momentum = speed*mass
|
|
|
|
if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED)
|
|
var/dir = get_dir(O.throw_source, src)
|
|
|
|
visible_message("<font color='red'>[src] staggers under the impact!</font>","<font color='red'>You stagger under the impact!</font>")
|
|
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
|
|
|
|
if(!O || !src) return
|
|
|
|
if(O.sharp) //Projectile is suitable for pinning.
|
|
if(soaked >= round(throw_damage*0.8))
|
|
return
|
|
|
|
//Handles embedding for non-humans and simple_mobs.
|
|
embed(O)
|
|
|
|
var/turf/T = near_wall(dir,2)
|
|
|
|
if(T)
|
|
src.loc = T
|
|
visible_message("<span class='warning'>[src] is pinned to the wall by [O]!</span>","<span class='warning'>You are pinned to the wall by [O]!</span>")
|
|
src.anchored = 1
|
|
src.pinned += O
|
|
|
|
/mob/living/proc/embed(var/obj/O, var/def_zone=null)
|
|
O.loc = src
|
|
src.embedded += O
|
|
src.verbs += /mob/proc/yank_out_object
|
|
|
|
//This is called when the mob is thrown into a dense turf
|
|
/mob/living/proc/turf_collision(var/turf/T, var/speed)
|
|
src.take_organ_damage(speed*5)
|
|
|
|
/mob/living/proc/near_wall(var/direction,var/distance=1)
|
|
var/turf/T = get_step(get_turf(src),direction)
|
|
var/turf/last_turf = src.loc
|
|
var/i = 1
|
|
|
|
while(i>0 && i<=distance)
|
|
if(T.density) //Turf is a wall!
|
|
return last_turf
|
|
i++
|
|
last_turf = T
|
|
T = get_step(T,direction)
|
|
|
|
return 0
|
|
|
|
// End BS12 momentum-transfer code.
|
|
|
|
/mob/living/attack_generic(var/mob/user, var/damage, var/attack_message)
|
|
if(!damage)
|
|
return
|
|
|
|
adjustBruteLoss(damage)
|
|
add_attack_logs(user,src,"Generic attack (probably animal)", admin_notify = FALSE) //Usually due to simple_mob attacks
|
|
if(ai_holder)
|
|
ai_holder.react_to_attack(user)
|
|
src.visible_message("<span class='danger'>[user] has [attack_message] [src]!</span>")
|
|
user.do_attack_animation(src)
|
|
spawn(1) updatehealth()
|
|
return 1
|
|
|
|
/mob/living/proc/IgniteMob()
|
|
if(fire_stacks > 0 && !on_fire)
|
|
on_fire = 1
|
|
handle_light()
|
|
update_fire()
|
|
|
|
/mob/living/proc/ExtinguishMob()
|
|
if(on_fire)
|
|
on_fire = 0
|
|
fire_stacks = 0
|
|
handle_light()
|
|
update_fire()
|
|
|
|
/mob/living/proc/update_fire()
|
|
return
|
|
|
|
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
|
|
fire_stacks = clamp(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS)
|
|
|
|
/mob/living/proc/handle_fire()
|
|
if(fire_stacks < 0)
|
|
fire_stacks = min(0, ++fire_stacks) //If we've doused ourselves in water to avoid fire, dry off slowly
|
|
|
|
if(fire_stacks > 0)
|
|
fire_stacks = max(0, (fire_stacks-0.1)) //Should slowly burn out
|
|
|
|
if(!on_fire)
|
|
return 1
|
|
else if(fire_stacks <= 0)
|
|
ExtinguishMob() //Fire's been put out.
|
|
return 1
|
|
|
|
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
|
|
if(G.gas[/datum/gas/oxygen] < 1)
|
|
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
|
|
return 1
|
|
|
|
var/turf/location = get_turf(src)
|
|
location.hotspot_expose(fire_burn_temperature(), 50, 1)
|
|
|
|
//altered this to cap at the temperature of the fire causing it, using the same 1:1500 value as /mob/living/carbon/human/handle_fire() in human/life.dm
|
|
/mob/living/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
|
if(exposed_temperature)
|
|
if(fire_stacks < exposed_temperature/1500) // Subject to balance
|
|
adjust_fire_stacks(2)
|
|
else
|
|
adjust_fire_stacks(2)
|
|
IgniteMob()
|
|
|
|
//Share fire evenly between the two mobs
|
|
//Called in MobCollide() and Crossed()
|
|
/mob/living/proc/spread_fire(mob/living/L)
|
|
return
|
|
// This is commented out pending discussion on Polaris. If you're a downsteam and you want people to spread fire by touching each other, feel free to uncomment this.
|
|
/*
|
|
if(!istype(L))
|
|
return
|
|
var/L_old_on_fire = L.on_fire
|
|
|
|
if(on_fire) //Only spread fire stacks if we're on fire
|
|
fire_stacks /= 2
|
|
L.fire_stacks += fire_stacks
|
|
if(L.IgniteMob())
|
|
message_admins("[key_name(src)] bumped into [key_name(L)] and set them on fire.")
|
|
|
|
if(L_old_on_fire) //Only ignite us and gain their stacks if they were onfire before we bumped them
|
|
L.fire_stacks /= 2
|
|
fire_stacks += L.fire_stacks
|
|
IgniteMob()
|
|
*/
|
|
|
|
/mob/living/proc/get_cold_protection()
|
|
return 0
|
|
|
|
/mob/living/proc/get_heat_protection()
|
|
return 0
|
|
|
|
/mob/living/proc/get_shock_protection()
|
|
return 0
|
|
|
|
/mob/living/proc/get_water_protection()
|
|
return 1 // Water won't hurt most things.
|
|
|
|
/mob/living/proc/get_poison_protection()
|
|
return 0
|
|
|
|
//Finds the effective temperature that the mob is burning at.
|
|
/mob/living/proc/fire_burn_temperature()
|
|
if (fire_stacks <= 0)
|
|
return 0
|
|
|
|
//Scale quadratically so that single digit numbers of fire stacks don't burn ridiculously hot.
|
|
//lower limit of 700 K, same as matches and roughly the temperature of a cool flame.
|
|
return max(2.25*round(FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE*(fire_stacks/FIRE_MAX_FIRESUIT_STACKS)**2), 700)
|
|
|
|
// Called when struck by lightning.
|
|
/mob/living/proc/lightning_act()
|
|
// The actual damage/electrocution is handled by the tesla_zap() that accompanies this.
|
|
Paralyse(5)
|
|
stuttering += 20
|
|
make_jittery(150)
|
|
emp_act(1)
|
|
to_chat(src, span("critical", "You've been struck by lightning!"))
|
|
|
|
// Called when touching a lava tile.
|
|
// Does roughly 100 damage to unprotected mobs, and 20 to fully protected mobs.
|
|
/mob/living/lava_act()
|
|
add_modifier(/datum/modifier/fire/intense, 3 SECONDS) // Around 40 total if left to burn and without fire protection per stack.
|
|
inflict_heat_damage(10) // Another 40, however this is instantly applied to unprotected mobs.
|
|
adjustFireLoss(10) // Lava cannot be 100% resisted with fire protection.
|
|
|
|
//Acid
|
|
/mob/living/acid_act(var/mob/living/H)
|
|
make_dizzy(1)
|
|
adjustHalLoss(1)
|
|
inflict_heat_damage(5) // This is instantly applied to unprotected mobs.
|
|
inflict_poison_damage(5)
|
|
adjustFireLoss(5) // Acid cannot be 100% resisted by protection.
|
|
adjustToxLoss(5)
|
|
confused = max(confused, 1)
|
|
|
|
//Blood
|
|
//Acid
|
|
/mob/living/blood_act(var/mob/living/H)
|
|
inflict_poison_damage(5)
|
|
adjustToxLoss(5)
|
|
|
|
|
|
/mob/living/proc/reagent_permeability()
|
|
return 1
|
|
|
|
/mob/living/proc/handle_actions()
|
|
//Pretty bad, i'd use picked/dropped instead but the parent calls in these are nonexistent
|
|
for(var/datum/action/A in actions)
|
|
if(A.CheckRemoval(src))
|
|
A.Remove(src)
|
|
for(var/obj/item/I in src)
|
|
if(I.action_button_name)
|
|
if(!I.action)
|
|
if(I.action_button_is_hands_free)
|
|
I.action = new/datum/action/item_action/hands_free
|
|
else
|
|
I.action = new/datum/action/item_action
|
|
I.action.name = I.action_button_name
|
|
I.action.target = I
|
|
I.action.Grant(src)
|
|
return
|
|
|
|
/mob/living/update_action_buttons()
|
|
if(!hud_used) return
|
|
if(!client) return
|
|
|
|
if(hud_used.hud_shown != 1) //Hud toggled to minimal
|
|
return
|
|
|
|
client.screen -= hud_used.hide_actions_toggle
|
|
for(var/datum/action/A in actions)
|
|
if(A.button)
|
|
client.screen -= A.button
|
|
|
|
if(hud_used.action_buttons_hidden)
|
|
if(!hud_used.hide_actions_toggle)
|
|
hud_used.hide_actions_toggle = new(hud_used)
|
|
hud_used.hide_actions_toggle.UpdateIcon()
|
|
|
|
if(!hud_used.hide_actions_toggle.moved)
|
|
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(1)
|
|
//hud_used.SetButtonCoords(hud_used.hide_actions_toggle,1)
|
|
|
|
client.screen += hud_used.hide_actions_toggle
|
|
return
|
|
|
|
var/button_number = 0
|
|
for(var/datum/action/A in actions)
|
|
button_number++
|
|
if(A.button == null)
|
|
var/atom/movable/screen/movable/action_button/N = new(hud_used)
|
|
N.owner = A
|
|
A.button = N
|
|
|
|
var/atom/movable/screen/movable/action_button/B = A.button
|
|
|
|
B.UpdateIcon()
|
|
|
|
B.name = A.UpdateName()
|
|
|
|
client.screen += B
|
|
|
|
if(!B.moved)
|
|
B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number)
|
|
//hud_used.SetButtonCoords(B,button_number)
|
|
|
|
if(button_number > 0)
|
|
if(!hud_used.hide_actions_toggle)
|
|
hud_used.hide_actions_toggle = new(hud_used)
|
|
hud_used.hide_actions_toggle.InitialiseIcon(src)
|
|
if(!hud_used.hide_actions_toggle.moved)
|
|
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
|
|
//hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1)
|
|
client.screen += hud_used.hide_actions_toggle
|
|
|
|
// Returns a number to determine if something is harder or easier to hit than normal.
|
|
/mob/living/proc/get_evasion()
|
|
var/result = evasion // First we get the 'base' evasion. Generally this is zero.
|
|
for(var/datum/modifier/M in modifiers)
|
|
if(!isnull(M.evasion))
|
|
result += M.evasion
|
|
return result
|
|
|
|
/mob/living/proc/get_accuracy_penalty()
|
|
// Certain statuses make it harder to score a hit.
|
|
var/accuracy_penalty = 0
|
|
if(eye_blind)
|
|
accuracy_penalty += 75
|
|
if(eye_blurry)
|
|
accuracy_penalty += 30
|
|
if(confused)
|
|
accuracy_penalty += 45
|
|
|
|
return accuracy_penalty
|