/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null, armour_penetration, penetrated_text) var/armor = getarmor(def_zone, attack_flag) //the if "armor" check is because this is used for everything on /living, including humans if(armor && armour_penetration) armor = max(0, armor - armour_penetration) if(penetrated_text) to_chat(src, "[penetrated_text]") else to_chat(src, "Your armor was penetrated!") else if(armor >= 100) if(absorb_text) to_chat(src, "[absorb_text]") else to_chat(src, "Your armor absorbs the blow!") else if(armor > 0) if(soften_text) to_chat(src, "[soften_text]") else to_chat(src, "Your armor softens the blow!") return armor /mob/living/proc/getarmor(def_zone, type) return 0 //this returns the mob's protection against eye damage (number between -1 and 2) from bright lights /mob/living/proc/get_eye_protection() return 0 //this returns the mob's protection against ear damage (0:no protection; 1: some ear protection; 2: has no ears) /mob/living/proc/get_ear_protection() return 0 /mob/living/proc/is_mouth_covered(head_only = 0, mask_only = 0) return FALSE /mob/living/proc/is_eyes_covered(check_glasses = 1, check_head = 1, check_mask = 1) return FALSE /mob/living/proc/on_hit(obj/item/projectile/P) return /mob/living/bullet_act(obj/item/projectile/P, def_zone) var/armor = run_armor_check(def_zone, P.flag, "","",P.armour_penetration) if(!P.nodamage) apply_damage(P.damage, P.damage_type, def_zone, armor) if(P.dismemberment) check_projectile_dismemberment(P, def_zone) return P.on_hit(src, armor) /mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone) return 0 /obj/item/proc/get_volume_by_throwforce_and_or_w_class() if(throwforce && w_class) return CLAMP((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100 else if(w_class) return CLAMP(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100 else return 0 /mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE) if(istype(AM, /obj/item)) var/obj/item/I = AM var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest var/dtype = BRUTE var/volume = I.get_volume_by_throwforce_and_or_w_class() SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, zone) dtype = I.damtype if (I.throwforce > 0) //If the weapon's throwforce is greater than zero... if (I.throwhitsound) //...and throwhitsound is defined... playsound(loc, I.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound. else if(I.hitsound) //Otherwise, if the weapon's hitsound is defined... playsound(loc, I.hitsound, volume, 1, -1) //...play the weapon's hitsound. else if(!I.throwhitsound) //Otherwise, if throwhitsound isn't defined... playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg. else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero... playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg if(!I.throwforce)// Otherwise, if the item's throwforce is 0... playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg. if(!blocked) visible_message("[src] has been hit by [I].", \ "[src] has been hit by [I].") var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration) apply_damage(I.throwforce, dtype, zone, armor) if(I.thrownby) log_combat(I.thrownby, src, "threw and hit", I) else return 1 else playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) ..() /mob/living/mech_melee_attack(obj/mecha/M) if(M.occupant.a_intent == INTENT_HARM) M.do_attack_animation(src) if(M.damtype == "brute") step_away(src,M,15) switch(M.damtype) if(BRUTE) Unconscious(20) take_overall_damage(rand(M.force/2, M.force)) playsound(src, 'sound/weapons/punch4.ogg', 50, 1) if(BURN) take_overall_damage(0, rand(M.force/2, M.force)) playsound(src, 'sound/items/welder.ogg', 50, 1) if(TOX) M.mech_toxin_damage(src) else return updatehealth() visible_message("[M.name] has hit [src]!", \ "[M.name] has hit [src]!", null, COMBAT_MESSAGE_RANGE) log_combat(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") else step_away(src,M) log_combat(M.occupant, src, "pushed", M) visible_message("[M] pushes [src] out of the way.", null, null, 5) /mob/living/fire_act() adjust_fire_stacks(3) IgniteMob() /mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0) if(user == anchored || !isturf(user.loc)) return FALSE if(user.pulling && user.grab_state == GRAB_AGGRESSIVE && user.voremode) if(ismob(user.pulling)) var/mob/P = user.pulling user.vore_attack(user, P, src) // User, Pulled, Predator target (which can be user, pulling, or src) return if(user == src) //we want to be able to self click if we're voracious return FALSE if(!user.pulling || user.pulling != src) user.start_pulling(src, supress_message) return if(!(status_flags & CANPUSH) || has_trait(TRAIT_PUSHIMMUNE)) to_chat(user, "[src] can't be grabbed more aggressively!") return FALSE if(user.has_trait(TRAIT_PACIFISM)) to_chat(user, "You don't want to risk hurting [src]!") return FALSE grippedby(user) //proc to upgrade a simple pull into a more aggressive grab. /mob/living/proc/grippedby(mob/living/carbon/user, instant = FALSE) if(user.grab_state < GRAB_KILL) user.changeNext_move(CLICK_CD_GRABBING) playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) if(user.grab_state) //only the first upgrade is instantaneous var/old_grab_state = user.grab_state var/grab_upgrade_time = instant ? 0 : 30 visible_message("[user] starts to tighten [user.p_their()] grip on [src]!", \ "[user] starts to tighten [user.p_their()] grip on you!") switch(user.grab_state) if(GRAB_AGGRESSIVE) log_combat(user, src, "attempted to neck grab", addition="neck grab") if(GRAB_NECK) log_combat(user, src, "attempted to strangle", addition="kill grab") if(!do_mob(user, src, grab_upgrade_time)) return 0 if(!user.pulling || user.pulling != src || user.grab_state != old_grab_state || user.a_intent != INTENT_GRAB) return 0 if(user.voremode && user.grab_state == GRAB_AGGRESSIVE) return 0 user.grab_state++ switch(user.grab_state) if(GRAB_AGGRESSIVE) log_combat(user, src, "grabbed", addition="aggressive grab") visible_message("[user] has grabbed [src] aggressively!", \ "[user] has grabbed [src] aggressively!") drop_all_held_items() stop_pulling() if(GRAB_NECK) log_combat(user, src, "grabbed", addition="neck grab") visible_message("[user] has grabbed [src] by the neck!",\ "[user] has grabbed you by the neck!") update_canmove() //we fall down if(!buckled && !density) Move(user.loc) if(GRAB_KILL) log_combat(user, src, "strangled", addition="kill grab") visible_message("[user] is strangling [src]!", \ "[user] is strangling you!") update_canmove() //we fall down if(!buckled && !density) Move(user.loc) return 1 /mob/living/attack_slime(mob/living/simple_animal/slime/M) if(!SSticker.HasRoundStarted()) to_chat(M, "You cannot attack people before the game has started.") return if(M.buckled) if(M in buckled_mobs) M.Feedstop() return // can't attack while eating! if(has_trait(TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE if (stat != DEAD) log_combat(M, src, "attacked") M.do_attack_animation(src) visible_message("The [M.name] glomps [src]!", \ "The [M.name] glomps [src]!", null, COMBAT_MESSAGE_RANGE) return TRUE /mob/living/attack_animal(mob/living/simple_animal/M) M.face_atom(src) if(M.melee_damage_upper == 0) M.visible_message("\The [M] [M.friendly] [src]!") return FALSE else if(M.has_trait(TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) M.do_attack_animation(src) visible_message("\The [M] [M.attacktext] [src]!", \ "\The [M] [M.attacktext] [src]!", null, COMBAT_MESSAGE_RANGE) log_combat(M, src, "attacked") return TRUE /mob/living/attack_paw(mob/living/carbon/monkey/M) if(isturf(loc) && istype(loc.loc, /area/start)) to_chat(M, "No attacking people at spawn, you jackass.") return FALSE if (M.a_intent == INTENT_HARM) if(M.has_trait(TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH)) to_chat(M, "You can't bite with your mouth covered!") return FALSE M.do_attack_animation(src, ATTACK_EFFECT_BITE) if (prob(75)) log_combat(M, src, "attacked") playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) visible_message("[M.name] bites [src]!", \ "[M.name] bites [src]!", null, COMBAT_MESSAGE_RANGE) return TRUE else visible_message("[M.name] has attempted to bite [src]!", \ "[M.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE) return FALSE /mob/living/attack_larva(mob/living/carbon/alien/larva/L) switch(L.a_intent) if("help") visible_message("[L.name] rubs its head against [src].") return FALSE else if(L.has_trait(TRAIT_PACIFISM)) to_chat(L, "You don't want to hurt anyone!") return L.do_attack_animation(src) if(prob(90)) log_combat(L, src, "attacked") visible_message("[L.name] bites [src]!", \ "[L.name] bites [src]!", null, COMBAT_MESSAGE_RANGE) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) return TRUE else visible_message("[L.name] has attempted to bite [src]!", \ "[L.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE) return FALSE /mob/living/attack_alien(mob/living/carbon/alien/humanoid/M) switch(M.a_intent) if ("help") visible_message("[M] caresses [src] with its scythe like arm.") return FALSE if ("grab") grabbedby(M) return FALSE if("harm") if(M.has_trait(TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE M.do_attack_animation(src) return TRUE if("disarm") M.do_attack_animation(src, ATTACK_EFFECT_DISARM) return TRUE /mob/living/ex_act(severity, target, origin) if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src)) return ..() //Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs. /mob/living/acid_act(acidpwr, acid_volume) take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1)) return 1 /mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE) SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage) if(tesla_shock && (flags_1 & TESLA_IGNORE_1)) return FALSE if(has_trait(TRAIT_SHOCKIMMUNE)) return FALSE if(shock_damage > 0) if(!illusion) adjustFireLoss(shock_damage) visible_message( "[src] was shocked by \the [source]!", \ "You feel a powerful shock coursing through your body!", \ "You hear a heavy electrical crack." \ ) return shock_damage /mob/living/emp_act(severity) . = ..() if(. & EMP_PROTECT_CONTENTS) return for(var/obj/O in contents) O.emp_act(severity) /mob/living/singularity_act() var/gain = 20 investigate_log("([key_name(src)]) has been consumed by the singularity.", INVESTIGATE_SINGULO) //Oh that's where the clown ended up! gib() return(gain) /mob/living/narsie_act() if(status_flags & GODMODE || QDELETED(src)) return if(is_servant_of_ratvar(src) && !stat) to_chat(src, "You resist Nar'Sie's influence... but not all of it. Run!") adjustBruteLoss(35) if(src && reagents) reagents.add_reagent("heparin", 5) return FALSE if(GLOB.cult_narsie && GLOB.cult_narsie.souls_needed[src]) GLOB.cult_narsie.souls_needed -= src GLOB.cult_narsie.souls += 1 if((GLOB.cult_narsie.souls == GLOB.cult_narsie.soul_goal) && (GLOB.cult_narsie.resolved == FALSE)) GLOB.cult_narsie.resolved = TRUE sound_to_playing_players('sound/machines/alarm.ogg') addtimer(CALLBACK(GLOBAL_PROC, .proc/cult_ending_helper, 1), 120) addtimer(CALLBACK(GLOBAL_PROC, .proc/ending_helper), 270) if(client) makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, src, cultoverride = TRUE) else switch(rand(1, 6)) if(1) new /mob/living/simple_animal/hostile/construct/armored/hostile(get_turf(src)) if(2) new /mob/living/simple_animal/hostile/construct/wraith/hostile(get_turf(src)) if(3 to 6) new /mob/living/simple_animal/hostile/construct/builder/hostile(get_turf(src)) spawn_dust() gib() return TRUE /mob/living/ratvar_act() if(status_flags & GODMODE) return if(stat != DEAD && !is_servant_of_ratvar(src)) to_chat(src, "A blinding light boils you alive! Run!") adjust_fire_stacks(20) IgniteMob() return FALSE //called when the mob receives a bright flash /mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash) if(get_eye_protection() < intensity && (override_blindness_check || !(has_trait(TRAIT_BLIND)))) overlay_fullscreen("flash", type) addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25) return TRUE return FALSE //called when the mob receives a loud bang /mob/living/proc/soundbang_act() return 0 //to damage the clothes worn by a mob /mob/living/proc/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone) return /mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!used_item) used_item = get_active_held_item() ..() floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.