Files
Cody BrittainandGitHub 3f62424312 [MDB Ignore] [IDB Ignore] Kills off /obj/item/device (#21774)
This has zero reason to exist in our code base. We have no procs or
variables tied to this. I removed it to make future modifications
cleaner.

---------

Signed-off-by: Cody Brittain <1779662+Generalcamo@users.noreply.github.com>
2026-02-01 05:14:26 +00:00

571 lines
20 KiB
Plaintext

/mob/living/proc/modify_damage_by_armor(def_zone, damage, damage_type, damage_flags, mob/living/victim, armor_pen, silent = FALSE)
var/list/armors = get_armors_by_zone(def_zone, damage_type, damage_flags)
. = args.Copy(2)
for(var/armor in armors)
var/datum/component/armor/armor_datum = armor
. = armor_datum.apply_damage_modifications(arglist(.))
/mob/living/check_projectile_armor(def_zone, obj/projectile/impacting_projectile, is_silent)
if(impacting_projectile.damage > 0) // Run the block computation if we did damage or if we only use armor for effects (nodamage)
//Since we get a ratio from this and we need a percentage, we multiply by 100 to get the percentage
return (get_blocked_ratio(def_zone, impacting_projectile.damage_type, impacting_projectile.damage_flags(), impacting_projectile.armor_penetration, impacting_projectile.damage) * 100)
return 0
/mob/living/proc/get_blocked_ratio(def_zone, damage_type, damage_flags, armor_pen, damage)
var/list/armors = get_armors_by_zone(def_zone, damage_type, damage_flags)
. = 0
for(var/armor in armors)
var/datum/component/armor/armor_datum = armor
. = 1 - (1 - .) * (1 - armor_datum.get_blocked(damage_type, damage_flags, armor_pen, damage)) // multiply the amount we let through
. = min(1, .)
/mob/living/proc/get_armors_by_zone(def_zone, damage_type, damage_flags)
. = list()
var/natural_armor = GetComponent(/datum/component/armor)
if(natural_armor)
. += natural_armor
if(psi)
var/armor = psi.GetComponent(/datum/component/armor/psionic)
if(armor)
. += armor
/**
* Determines if the mob has a shield, and what to do with it
*
* Returns one of the `BULLET_ACT_*` defines
*
* `BULLET_ACT_HIT` if the shield didn't block the hit,
* `BULLET_ACT_BLOCK` if the shield blocked the hit,
* `BULLET_ACT_FORCE_PIERCE` if the shield avoided the mob from being hit, but whatever hit it wasn't stopped (eg. a bullet that doesn't hit the mob, but gets deflected)
*/
/mob/living/proc/check_shields(damage, atom/damage_source, mob/attacker, def_zone, attack_text)
return BULLET_ACT_HIT
/mob/living/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
. = ..()
if(. != BULLET_ACT_HIT)
return .
/*#############################################
THINGS THAT CAN AVOID THE MOB BEING HIT
OR ALTER THE DAMAGE WE TAKE
#############################################*/
var/blocked
//Auras, essentially magic and encompassing around us, gets checked first
if(!src.aura_check(AURA_TYPE_BULLET, hitting_projectile, def_zone, piercing_hit))
blocked = 100
return BULLET_ACT_FORCE_PIERCE
//Shields, in front of us (hopefully), check the bullet before it reaches us
var/shield_check = check_shields(hitting_projectile.damage, hitting_projectile, hitting_projectile.firer, def_zone, "the [hitting_projectile.name]")
if(shield_check != BULLET_ACT_HIT)
hitting_projectile.on_hit(src, 100, def_zone)
return shield_check
//Armor, right above our skin, can soften the hit
// we need a second, silent armor check to actually know how much to reduce damage taken, as opposed to
// on [/atom/proc/bullet_act] where it's just to pass it to the projectile's on_hit().
blocked = check_projectile_armor(def_zone, hitting_projectile, is_silent = TRUE)
var/damage = hitting_projectile.damage //We use a supporting variable to store the damage, since we can alter it below
//If it's anti material vulnerable, apply the anti-material potential factor
if(is_anti_materiel_vulnerable())
damage = hitting_projectile.damage * hitting_projectile.anti_materiel_potential
/*##################################
OK WE ARE BEING HIT NOW IF
WE HAVE REACHED THIS POINT
##################################*/
//If the projectile has damage and it's not completely blocked, apply it
if(damage > 0 && blocked < 100)
//Apply the damage to the living mob
apply_damage(damage, hitting_projectile.damage_type, def_zone, blocked, used_weapon = hitting_projectile, damage_flags = hitting_projectile.damage_flags(), used_weapon = hitting_projectile, armor_pen = hitting_projectile.armor_penetration)
/*### START Other effects of being hit and damaged ###*/
//Being hit while using a cloaking device
var/obj/item/cloaking_device/C = locate(/obj/item/cloaking_device) in src
if(C && C.active)
C.attack_self(src)//Should shut it off
update_icon()
to_chat(src, SPAN_NOTICE("Your [C.name] was disrupted!"))
Stun(2)
//Being hit while using a deadman switch
var/obj/item/assembly/signaler/signaler = get_active_hand()
if(istype(signaler))
if(signaler.deadman && prob(80))
log_and_message_admins("has triggered a signaler deadman's switch")
src.visible_message(SPAN_WARNING("[src] triggers their deadman's switch!"))
signaler.signal()
/*### END Other effects of being hit and damaged ###*/
bullet_impact_visuals(hitting_projectile, def_zone, damage, blocked)
//Messages related to being hit (not necessarily damaged)
if(!hitting_projectile.do_not_log)
var/impacted_organ = get_organ_name_from_zone(def_zone)
//If the projectile was blocked and it's not at point blank range, then it missed
if(blocked >= 100 && !hitting_projectile.point_blank)
src.visible_message(SPAN_NOTICE("\The [hitting_projectile] misses [src] narrowly!"))
playsound(src, SFX_BULLET_MISS, 50, 1)
//Otherwise it hit
else
//If the projectile is suppressed, give a message only to the mob, and a smaller one
if(hitting_projectile.suppressed)
to_chat(src, SPAN_DANGER("You've been hit in the [impacted_organ] by \a [hitting_projectile]!"))
//Otherwise announce it as a visible message, and make it larger
else
//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter
src.visible_message(SPAN_DANGER("\The [src] is hit by \a [hitting_projectile] in the [impacted_organ]!"),
SPAN_DANGER(FONT_LARGE("You are hit by \a [hitting_projectile] in the [impacted_organ]!")))
if(blocked < 100)
return BULLET_ACT_HIT
else
return BULLET_ACT_BLOCK
/mob/living/proc/get_flash_protection(ignore_inherent = FALSE)
return FLASH_PROTECTION_NONE
/mob/living/proc/get_hearing_protection()
return FALSE
/mob/living/proc/get_hearing_sensitivity()
return FALSE
/mob/living/proc/aura_check(var/type)
if(!auras)
return TRUE
. = TRUE
var/list/newargs = args - args[1]
for(var/obj/aura/aura as anything in auras)
var/result = 0
switch(type)
if(AURA_TYPE_WEAPON)
result = aura.attackby(arglist(newargs))
if(AURA_TYPE_BULLET)
result = aura.bullet_act(arglist(newargs))
if(AURA_TYPE_THROWN)
result = aura.hitby(arglist(newargs))
if(AURA_TYPE_LIFE)
result = aura.life_tick()
if(result & AURA_FALSE)
. = FALSE
if(result & AURA_CANCEL)
break
/**
* For visuals, blood splatters and so on
*
* * impacting_projectile - The `/obj/projectile` that hit the mob
* * def_zone - The zone that the projectile hit the mob in, use the defines
* * damage - The amount of damage the projectile did
* * blocked - The **percentage** of damage that was blocked, eg. by armor, a number
*/
/mob/living/proc/bullet_impact_visuals(obj/projectile/impacting_projectile, def_zone, damage, blocked)
SHOULD_NOT_SLEEP(TRUE)
var/list/impact_sounds = LAZYACCESS(impacting_projectile.impact_sounds, get_bullet_impact_effect_type(def_zone))
if(length(impact_sounds))
playsound(src, pick(impact_sounds), 75)
/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, var/damage_flags)
flash_pain(stun_amount)
if(stun_amount)
Stun(stun_amount)
Weaken(stun_amount)
apply_effect(stun_amount, STUTTER)
apply_effect(stun_amount, EYE_BLUR)
if(agony_amount)
apply_damage(agony_amount, DAMAGE_PAIN, def_zone, used_weapon)
apply_effect(agony_amount / 10, STUTTER)
apply_effect(agony_amount / 10, EYE_BLUR)
/mob/living/proc/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null, var/tesla_shock = 0, var/ground_zero)
return 0 //only carbon liveforms have this proc
/mob/living/emp_act(severity)
. = ..()
//If no protection of the contents, apply the EMP effect to the contents
if(!(. & EMP_PROTECT_CONTENTS))
for(var/obj/O in get_contents())
O.emp_act(severity)
/mob/living/flash_act(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, ignore_inherent = FALSE, type = /atom/movable/screen/fullscreen/flash, length = 2.5 SECONDS)
if(is_blind() && !(override_blindness_check || affect_silicon))
return FALSE
if(get_flash_protection(ignore_inherent) >= intensity)
return FALSE
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, /mob/proc/clear_fullscreen, "flash", length), length)
return TRUE
/// Called when the mob hears a very loud noise!
/// Intensity can be an EAR_PROTECTION_X define or an arbitrary/computed value between -1 and 2 (or more if you're insane)
/mob/living/proc/noise_act(intensity = EAR_PROTECTION_MODERATE, stun_pwr = 0, damage_pwr = 0, deafen_pwr = 0)
return FALSE
/mob/living/proc/get_attack_victim(obj/item/I, mob/living/user, var/target_zone)
return src
/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, var/ground_zero)
visible_message(SPAN_DANGER("[src] has been [LAZYPICK(I.attack_verb,"attacked")] with [I] by [user]!"))
. = standard_weapon_hit_effects(I, user, effective_force, hit_zone)
if(I.damtype == DAMAGE_BRUTE && prob(33) && I.force) // Added blood for whacking non-humans too
var/turf/simulated/location = get_turf(src)
if(istype(location)) location.add_blood_floor(src)
//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/hit_zone)
if(!effective_force)
return FALSE
//Hulk modifier
if((user.mutations & HULK))
effective_force *= 2
//Apply weapon damage
var/damage_flags = I.damage_flags()
return apply_damage(effective_force, I.damtype, hit_zone, I, damage_flags, I.armor_penetration)
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(!aura_check(AURA_TYPE_THROWN, hitting_atom, throwingdatum.speed))
return
if(isobj(hitting_atom))
var/obj/O = hitting_atom
var/dtype = O.damtype
var/throw_damage = O.throwforce*(throwingdatum.speed/THROWFORCE_SPEED_DIVISOR)
var/miss_chance = 15
if (O.throwing?.thrower?.resolve())
var/distance = get_dist(O.throwing?.thrower?.resolve(), loc)
miss_chance = max(15*(distance-2), 0)
if (prob(miss_chance))
visible_message(SPAN_NOTICE("\The [O] misses [src] narrowly!"))
playsound(src, 'sound/effects/throw_miss.ogg', 50, 1)
return
src.visible_message(SPAN_WARNING("[src] has been hit by [O]."))
apply_damage(throw_damage, dtype, null, damage_flags = O.damage_flags(), used_weapon = O)
O.throwing?.finalize(hit = TRUE, target = src) //it hit, so stop moving
if(ismob(O.throwing?.thrower?.resolve()))
var/mob/M = O.throwing?.thrower?.resolve()
var/client/assailant = M.client
if(assailant)
src.attack_log += "\[[time_stamp()]\] <font color='orange'>Has been hit with a [O], thrown by [M.name] ([assailant.ckey])</font>"
M.attack_log += "\[[time_stamp()]\] <span class='warning'>Hit [src.name] ([src.ckey]) with a thrown [O]</span>"
if(!istype(src,/mob/living/simple_animal/rat))
msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [M.name] ([assailant.ckey]) (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)",ckey=key_name(M),ckey_target=key_name(src))
// 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 = throwingdatum.speed*mass
if(O.throwing?.thrower?.resolve() && momentum >= THROWNOBJ_KNOCKBACK_SPEED)
var/dir = get_dir(O.throwing?.thrower?.resolve(), src)
visible_message(SPAN_WARNING("[src] staggers under the impact!"),
SPAN_WARNING("You stagger under the impact!"))
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
if(!O || !src)
return
if(O.sharp) //Projectile is suitable for pinning.
//Handles embedding for non-humans and simple_animals.
embed(O)
var/turf/T = near_wall(dir,2)
if(T)
src.forceMove(T)
visible_message(SPAN_WARNING("[src] is pinned to the wall by [O]!"),
SPAN_WARNING("You are pinned to the wall by [O]!"))
src.anchored = 1
src.pinned += O
/mob/living/proc/embed(obj/O, def_zone=null, datum/wound/supplied_wound)
O.forceMove(src)
src.embedded += O
add_verb(src, /mob/proc/yank_out_object)
///This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/atom/T, var/speed = THROWFORCE_SPEED_DIVISOR, var/sound_to_play = 'sound/effects/bangtaper.ogg')
visible_message(SPAN_DANGER("[src] slams into \the [T]!"))
playsound(T, sound_to_play, 50, 1, 1)//so it plays sounds on the turf instead, makes for awesome carps to hull collision and such
apply_damage(speed*5, DAMAGE_BRUTE)
/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(mob/user, damage, attack_message, environment_smash, armor_penetration, attack_flags, damage_type)
if(!damage)
return
user.attack_log += "\[[time_stamp()]\] <span class='warning'>attacked [src.name] ([src.ckey])</span>"
src.attack_log += "\[[time_stamp()]\] <font color='orange'>was attacked by [user.name] ([user.ckey])</font>"
if (attack_message)
src.visible_message(SPAN_DANGER("[user] has [attack_message] [src]!"))
user.do_attack_animation(src)
apply_damage(damage, damage_type, user.zone_sel?.selecting, armor_pen = armor_penetration, damage_flags = attack_flags)
updatehealth()
return TRUE
/**
* Adds fire_stacks to a mob. See handle_fire() for details about how fire works.
*/
/mob/living/proc/IgniteMob(var/fire_stacks_to_add = 0)
if(fire_stacks_to_add)
adjust_fire_stacks(fire_stacks_to_add)
if(fire_stacks > 0 && !on_fire)
// Sanity check
fire_stacks_temperature = 0
set_on_fire()
update_fire()
return TRUE
return FALSE
/mob/living/proc/set_on_fire()
on_fire = TRUE
fire_stacks++
to_chat(src, SPAN_DANGER(FONT_LARGE("You are set on fire!")))
set_light(3, 2, LIGHT_COLOR_FIRE)
/mob/living/proc/extinguish_fire()
on_fire = FALSE
to_chat(src, SPAN_GOOD(FONT_LARGE("You are no longer on fire.")))
set_light(0)
/mob/living/proc/ExtinguishMob(var/fire_stacks_to_remove = 0)
if(fire_stacks_to_remove)
adjust_fire_stacks(-fire_stacks_to_remove)
if(fire_stacks <= 0 && on_fire)
// Cleanup
fire_stacks_temperature = 0
extinguish_fire()
update_fire()
return TRUE
return FALSE
/mob/living/proc/ExtinguishMobCompletely()
return ExtinguishMob(fire_stacks)
/mob/living/proc/update_fire()
return
/mob/living/proc/adjust_fire_stacks(var/add_fire_stacks)
fire_stacks = clamp(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS)
return fire_stacks
/**
* Handles whether or not a fire is currently active or is extinguished this tick.
* If there's no location, fire stacks are exhausted, !on_fire, or we run out of oxygen in our tile, fire goes out.
*
* Being 'on fire' means this:
* * You ignite things nearby, at the temperature on which you're on fire.
* * Your body temperature increases if you're not fully thermally protected.
*
* Normally, being exposed to high-temperature air means that body temperature increases, as moderated by the level
* and coverage of the mob's thermal protection. Being on fire adds an additional tick check- it takes the temperature
* of the air (the highest you're exposed to at any point) and uses fire_stacks as a loose multiplier to effective temp.
* Your max thermal protection temp and coverage level is compared against this modified (higher) value.
*
* This means that even if the air temp is below your protection level, being on fire and STAYING on fire can still raise your body temp.
*
* Returns boolean TRUE if fire is extinguished for any reason.
*/
/mob/living/proc/handle_fire(var/seconds_per_tick, var/datum/gas_mixture/environment)
if(!loc)
ExtinguishMobCompletely()
return TRUE
if(fire_stacks < 0)
fire_stacks = min(0, ++fire_stacks) //If we've doused ourselves in water to avoid fire, dry off slowly
if(!on_fire)
return 1
else if(fire_stacks <= 0)
ExtinguishMobCompletely() //Fire's been put out.
return 1
if(environment.gas[GAS_OXYGEN] < 1)
ExtinguishMobCompletely() //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(environment), 50, 1)
/mob/living/fire_act(exposed_temperature, exposed_volume)
. = ..()
IgniteMob(2)
/mob/living/proc/get_cold_protection()
return 0
/mob/living/proc/get_heat_protection()
return 0
/**
* Finds the effective temperature that the mob is burning at.
*
* The temperature of the environment in which the fire is currently located should moderate the temperature of the fire_stacks. Our
* lower limit is ~700 K (roughly your average cool match flame).
*
* Parameters:
* * environment - mob's loc's gas_mixture, inherited from /mob/living/proc/handle_fire(), which is inherited from /mob/living/life()
*
* Fun bonus fact: The original baystation code used the below formula:
* * max(2.25*round(FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE*(fire_stacks/FIRE_MAX_FIRESUIT_STACKS)**2), 700)
* Which resulted in crazy things like fires burning at 100000+ Kelvin, if the user just stood around long enough.
*/
/mob/living/proc/fire_burn_temperature(var/datum/gas_mixture/environment)
if (fire_stacks <= 0)
return 0
var/temperature = T0C + 20
// Sanity checking...
if(environment)
temperature = environment.temperature
// Air temp raised to a exponent between 1.002 and 1.05, or 700 + (75 * fire_stacks), whichever is higher.
return max(temperature ** (1 * (1 + (fire_stacks / 500))), 700 + (75 * fire_stacks))
/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 the item_action object does not exist, try to create it
if(!I.action)
//Try to use the default action type, if there is none, skip this implant
if(I.default_action_type)
I.action = new I.default_action_type
else
continue
I.action.name = I.action_button_name
I.action.SetTarget(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.update_icon()
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)
if(QDELETED(A))
continue
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.update_icon()
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