/mob/living/Initialize() . = ..() var/datum/atom_hud/data/human/medical/advanced/medhud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] medhud.add_to_hud(src) faction += "\ref[src]" determine_move_and_pull_forces() GLOB.mob_living_list += src // Used to determine the forces dependend on the mob size // Will only change the force if the force was not set in the mob type itself /mob/living/proc/determine_move_and_pull_forces() var/value switch(mob_size) if(MOB_SIZE_TINY) value = MOVE_FORCE_EXTREMELY_WEAK if(MOB_SIZE_SMALL) value = MOVE_FORCE_WEAK if(MOB_SIZE_HUMAN) value = MOVE_FORCE_NORMAL if(MOB_SIZE_LARGE) value = MOVE_FORCE_NORMAL // For now if(!move_force) move_force = value if(!pull_force) pull_force = value if(!move_resist) move_resist = value /mob/living/prepare_huds() ..() prepare_data_huds() /mob/living/proc/prepare_data_huds() med_hud_set_health() med_hud_set_status() /mob/living/Destroy() if(ranged_ability) ranged_ability.remove_ranged_ability(src) remove_from_all_data_huds() GLOB.mob_living_list -= src if(LAZYLEN(status_effects)) for(var/s in status_effects) var/datum/status_effect/S = s if(S.on_remove_on_mob_delete) //the status effect calls on_remove when its mob is deleted qdel(S) else S.be_replaced() return ..() /mob/living/ghostize(can_reenter_corpse = 1) var/prev_client = client . = ..() if(.) if(ranged_ability && prev_client) ranged_ability.remove_mousepointer(prev_client) /mob/living/proc/OpenCraftingMenu() return //Generic Bump(). Override MobBump() and ObjBump() instead of this. /mob/living/Bump(atom/A, yes) if(..()) //we are thrown onto something return if(buckled || !yes || now_pushing) return if(ismob(A)) if(MobBump(A)) return if(isobj(A)) if(ObjBump(A)) return if(istype(A, /atom/movable)) if(PushAM(A, move_force)) return //Called when we bump into a mob /mob/living/proc/MobBump(mob/M) //Even if we don't push/swap places, we "touched" them, so spread fire spreadFire(M) // No pushing if we're already pushing past something, or if the mob we're pushing into is anchored. if(now_pushing || M.anchored) return TRUE //Should stop you pushing a restrained person out of the way if(isliving(M)) var/mob/living/L = M if(L.pulledby && L.pulledby != src && L.restrained()) if(!(world.time % 5)) to_chat(src, "[L] is restrained, you cannot push past.") return TRUE if(L.pulling) if(ismob(L.pulling)) var/mob/P = L.pulling if(P.restrained()) if(!(world.time % 5)) to_chat(src, "[L] is restrained, you cannot push past.") return TRUE if(moving_diagonally) //no mob swap during diagonal moves. return TRUE if(a_intent == INTENT_HELP) // Help intent doesn't mob swap a mob pulling a structure if(isstructure(M.pulling) || isstructure(pulling)) return TRUE if(!M.buckled && !M.has_buckled_mobs()) var/mob_swap //the puller can always swap with it's victim if on grab intent if(M.pulledby == src && a_intent == INTENT_GRAB) mob_swap = TRUE //restrained people act if they were on 'help' intent to prevent a person being pulled from being seperated from their puller else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP)) mob_swap = TRUE if(mob_swap) //switch our position with M if(loc && !loc.Adjacent(M.loc)) return TRUE now_pushing = TRUE var/oldloc = loc var/oldMloc = M.loc var/M_passmob = (M.pass_flags & PASSMOB) // we give PASSMOB to both mobs to avoid bumping other mobs during swap. var/src_passmob = (pass_flags & PASSMOB) M.pass_flags |= PASSMOB pass_flags |= PASSMOB M.Move(oldloc) Move(oldMloc) if(!src_passmob) pass_flags &= ~PASSMOB if(!M_passmob) M.pass_flags &= ~PASSMOB now_pushing = FALSE return TRUE // okay, so we didn't switch. but should we push? // not if he's not CANPUSH of course if(!(M.status_flags & CANPUSH)) return TRUE //anti-riot equipment is also anti-push if(M.r_hand && (prob(M.r_hand.block_chance * 2)) && !istype(M.r_hand, /obj/item/clothing)) return TRUE if(M.l_hand && (prob(M.l_hand.block_chance * 2)) && !istype(M.l_hand, /obj/item/clothing)) return TRUE //Called when we bump into an obj /mob/living/proc/ObjBump(obj/O) return //Called when we want to push an atom/movable /mob/living/proc/PushAM(atom/movable/AM, force = move_force) if(isstructure(AM) && AM.pulledby) if(a_intent == INTENT_HELP && AM.pulledby != src) // Help intent doesn't push other peoples pulled structures return FALSE if(get_dist(get_step(AM, get_dir(src, AM)), AM.pulledby)>1)//Release pulled structures beyond 1 distance AM.pulledby.stop_pulling() if(now_pushing) return TRUE if(moving_diagonally) // no pushing during diagonal moves return TRUE if(!client && (mob_size < MOB_SIZE_SMALL)) return now_pushing = TRUE var/t = get_dir(src, AM) var/push_anchored = FALSE if((AM.move_resist * MOVE_FORCE_CRUSH_RATIO) <= force) if(move_crush(AM, move_force, t)) push_anchored = TRUE if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally if(force_push(AM, move_force, t, push_anchored)) push_anchored = TRUE if((AM.anchored && !push_anchored) || (force < (AM.move_resist * MOVE_FORCE_PUSH_RATIO))) now_pushing = FALSE return if(istype(AM, /obj/structure/window)) var/obj/structure/window/W = AM if(W.fulltile) for(var/obj/structure/window/win in get_step(W,t)) now_pushing = FALSE return if(pulling == AM) stop_pulling() var/current_dir if(isliving(AM)) current_dir = AM.dir if(step(AM, t)) step(src, t) if(current_dir) AM.setDir(current_dir) now_pushing = FALSE /mob/living/proc/can_track(mob/living/user) //basic fast checks go first. When overriding this proc, I recommend calling ..() at the end. var/turf/T = get_turf(src) if(!T) return 0 if(!is_level_reachable(T.z)) return 0 if(user != null && src == user) return 0 if(invisibility || alpha == 0)//cloaked return 0 if(digitalcamo) return 0 // Now, are they viewable by a camera? (This is last because it's the most intensive check) if(!near_camera(src)) return 0 return 1 //mob verbs are a lot faster than object verbs //for more info on why this is not atom/pull, see examinate() in mob.dm /mob/living/verb/pulled(atom/movable/AM as mob|obj in oview(1)) set name = "Pull" set category = "Object" if(istype(AM) && Adjacent(AM)) start_pulling(AM, show_message = TRUE) else stop_pulling() /mob/living/stop_pulling() ..() if(pullin) pullin.update_icon(src) /mob/living/verb/stop_pulling1() set name = "Stop Pulling" set category = "IC" stop_pulling() //same as above /mob/living/pointed(atom/A as mob|obj|turf in view()) if(incapacitated(ignore_lying = TRUE)) return FALSE if(status_flags & FAKEDEATH) return FALSE if(!..()) return FALSE var/obj/item/hand_item = get_active_hand() if(istype(hand_item, /obj/item/gun) && A != hand_item) if(a_intent == INTENT_HELP || !ismob(A)) visible_message("[src] points to [A] with [hand_item]") return TRUE A.visible_message("[src] points [hand_item] at [A]!", "[src] points [hand_item] at you!") A << 'sound/weapons/targeton.ogg' return TRUE visible_message("[src] points to [A]") return TRUE /mob/living/verb/succumb() set hidden = 1 if(InCritical()) create_attack_log("[src] has ["succumbed to death"] with [round(health, 0.1)] points of health!") create_log(MISC_LOG, "has succumbed to death with [round(health, 0.1)] points of health") adjustOxyLoss(health - HEALTH_THRESHOLD_DEAD) // super check for weird mobs, including ones that adjust hp // we don't want to go overboard and gib them, though for(var/i = 1 to 5) if(health < HEALTH_THRESHOLD_DEAD) break take_overall_damage(max(5, health - HEALTH_THRESHOLD_DEAD), 0) death() to_chat(src, "You have given up life and succumbed to death.") /mob/living/proc/InCritical() return (health < HEALTH_THRESHOLD_CRIT && health > HEALTH_THRESHOLD_DEAD && stat == UNCONSCIOUS) /mob/living/ex_act(severity) ..() flash_eyes() /mob/living/acid_act(acidpwr, acid_volume) take_organ_damage(acidpwr * min(1, acid_volume * 0.1)) return 1 /mob/living/welder_act(mob/user, obj/item/I) if(!I.tool_use_check(null, 0)) //Don't need the message, just if it succeeded return if(IgniteMob()) message_admins("[key_name_admin(user)] set [key_name_admin(src)] on fire with [I]") log_game("[key_name(user)] set [key_name(src)] on fire with [I]") /mob/living/proc/updatehealth(reason = "none given") if(status_flags & GODMODE) health = maxHealth stat = CONSCIOUS return health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() update_stat("updatehealth([reason])") med_hud_set_health() med_hud_set_status() update_health_hud() //This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually //affects them once clothing is factored in. ~Errorage /mob/living/proc/calculate_affecting_pressure(var/pressure) return 0 /mob/living/proc/adjustBodyTemp(actual, desired, incrementboost) var/temperature = actual var/difference = abs(actual-desired) //get difference var/increments = difference/10 //find how many increments apart they are var/change = increments*incrementboost // Get the amount to change by (x per increment) // Too cold if(actual < desired) temperature += change if(actual > desired) temperature = desired // Too hot if(actual > desired) temperature -= change if(actual < desired) temperature = desired // if(istype(src, /mob/living/carbon/human)) // to_chat(world, "[src] ~ [bodytemperature] ~ [temperature]") return temperature /mob/proc/get_contents() //Recursive function to find everything a mob is holding. /mob/living/get_contents(var/obj/item/storage/Storage = null) var/list/L = list() if(Storage) //If it called itself L += Storage.return_inv() //Leave this commented out, it will cause storage items to exponentially add duplicate to the list //for(var/obj/item/storage/S in Storage.return_inv()) //Check for storage items // L += get_contents(S) for(var/obj/item/gift/G in Storage.return_inv()) //Check for gift-wrapped items L += G.gift if(istype(G.gift, /obj/item/storage)) L += get_contents(G.gift) for(var/obj/item/smallDelivery/D in Storage.return_inv()) //Check for package wrapped items L += D.wrapped if(istype(D.wrapped, /obj/item/storage)) //this should never happen L += get_contents(D.wrapped) return L else L += contents for(var/obj/item/storage/S in contents) //Check for storage items L += get_contents(S) for(var/obj/item/clothing/suit/storage/S in contents)//Check for labcoats and jackets L += get_contents(S) for(var/obj/item/clothing/accessory/storage/S in contents)//Check for holsters L += get_contents(S) for(var/obj/item/implant/storage/I in contents) //Check for storage implants. L += I.get_contents() for(var/obj/item/gift/G in contents) //Check for gift-wrapped items L += G.gift if(istype(G.gift, /obj/item/storage)) L += get_contents(G.gift) for(var/obj/item/smallDelivery/D in contents) //Check for package wrapped items L += D.wrapped if(istype(D.wrapped, /obj/item/storage)) //this should never happen L += get_contents(D.wrapped) for(var/obj/item/folder/F in contents) L += F.contents //Folders can't store any storage items. return L /mob/living/proc/check_contents_for(A) var/list/L = get_contents() for(var/obj/B in L) if(B.type == A) return 1 return 0 // Living mobs use can_inject() to make sure that the mob is not syringe-proof in general. /mob/living/proc/can_inject(mob/user, error_msg, target_zone, penetrate_thick) return TRUE /mob/living/is_injectable(mob/user, allowmobs = TRUE) return (allowmobs && reagents && can_inject(user)) /mob/living/is_drawable(mob/user, allowmobs = TRUE) return (allowmobs && reagents && can_inject(user)) /mob/living/proc/restore_all_organs() return /mob/living/proc/revive() rejuvenate() if(iscarbon(src)) var/mob/living/carbon/C = src if(C.handcuffed && !initial(C.handcuffed)) C.unEquip(C.handcuffed) C.handcuffed = initial(C.handcuffed) C.update_handcuffed() if(C.legcuffed && !initial(C.legcuffed)) C.unEquip(C.legcuffed) C.legcuffed = initial(C.legcuffed) C.update_inv_legcuffed() if(C.reagents) C.reagents.clear_reagents() QDEL_LIST(C.reagents.addiction_list) C.reagents.addiction_threshold_accumulated.Cut() QDEL_LIST(C.processing_patches) // rejuvenate: Called by `revive` to get the mob into a revivable state // the admin "rejuvenate" command calls `revive`, not this proc. /mob/living/proc/rejuvenate() var/mob/living/carbon/human/human_mob = null //Get this declared for use later. // shut down various types of badness setToxLoss(0) setOxyLoss(0) setCloneLoss(0) setBrainLoss(0) setStaminaLoss(0) SetSleeping(0) SetParalysis(0, 1, 1) SetStunned(0, 1, 1) SetWeakened(0, 1, 1) SetSlowed(0) SetLoseBreath(0) SetDizzy(0) SetJitter(0) SetConfused(0) SetDrowsy(0) radiation = 0 SetDruggy(0) SetHallucinate(0) set_nutrition(NUTRITION_LEVEL_FED + 50) bodytemperature = 310 CureBlind() CureNearsighted() CureMute() CureDeaf() CureTourettes() CureEpilepsy() CureCoughing() CureNervous() SetEyeBlind(0) SetEyeBlurry(0) RestoreEars() heal_overall_damage(1000, 1000) ExtinguishMob() fire_stacks = 0 on_fire = 0 suiciding = 0 if(buckled) //Unbuckle the mob and clear the alerts. buckled.unbuckle_mob(src, force = TRUE) if(iscarbon(src)) var/mob/living/carbon/C = src C.handcuffed = initial(C.handcuffed) for(var/thing in C.viruses) var/datum/disease/D = thing D.cure(0) // restore all of the human's blood and reset their shock stage if(ishuman(src)) human_mob = src human_mob.set_heartattack(FALSE) human_mob.restore_blood() human_mob.decaylevel = 0 human_mob.remove_all_embedded_objects() restore_all_organs() surgeries.Cut() //End all surgeries. if(stat == DEAD) update_revive() else if(stat == UNCONSCIOUS) WakeUp() update_fire() regenerate_icons() restore_blood() if(human_mob) human_mob.update_eyes() human_mob.update_dna() return /mob/living/proc/remove_CC(should_update_canmove = TRUE) SetWeakened(0, FALSE) SetStunned(0, FALSE) SetParalysis(0, FALSE) SetSleeping(0, FALSE) setStaminaLoss(0) SetSlowed(0) if(should_update_canmove) update_canmove() /mob/living/proc/UpdateDamageIcon() return /mob/living/proc/Examine_OOC() set name = "Examine Meta-Info (OOC)" set category = "OOC" set src in view() if(config.allow_Metadata) if(client) to_chat(usr, "[src]'s Metainfo:
[client.prefs.metadata]") else to_chat(usr, "[src] does not have any stored infomation!") else to_chat(usr, "OOC Metadata is not supported by this server!") return /mob/living/Move(atom/newloc, direct, movetime) if(buckled && buckled.loc != newloc) //not updating position if(!buckled.anchored) return buckled.Move(newloc, direct) else return 0 var/atom/movable/pullee = pulling if(pullee && get_dist(src, pullee) > 1) stop_pulling() if(pullee && !isturf(pullee.loc) && pullee.loc != loc) log_game("DEBUG: [src]'s pull on [pullee] was broken despite [pullee] being in [pullee.loc]. Pull stopped manually.") stop_pulling() if(restrained()) stop_pulling() var/turf/T = loc . = ..() if(.) handle_footstep(loc) step_count++ if(pulling && pulling == pullee) // we were pulling a thing and didn't lose it during our move. if(pulling.anchored) stop_pulling() return var/pull_dir = get_dir(src, pulling) if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir))) // puller and pullee more than one tile away or in diagonal position if(isliving(pulling)) var/mob/living/M = pulling if(M.lying && !M.buckled && (prob(M.getBruteLoss() * 200 / M.maxHealth))) M.makeTrail(T) pulling.Move(T, get_dir(pulling, T), movetime) // the pullee tries to reach our previous position if(pulling && get_dist(src, pulling) > 1) // the pullee couldn't keep up stop_pulling() if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //seperated from our puller and not in the middle of a diagonal move pulledby.stop_pulling() if(s_active && !(s_active in contents) && get_turf(s_active) != get_turf(src)) //check !( s_active in contents ) first so we hopefully don't have to call get_turf() so much. s_active.close(src) /mob/living/proc/handle_footstep(turf/T) if(istype(T)) return 1 return 0 /mob/living/proc/makeTrail(turf/T) if(!has_gravity(src)) return var/blood_exists = 0 for(var/obj/effect/decal/cleanable/trail_holder/C in loc) //checks for blood splatter already on the floor blood_exists = 1 if(isturf(loc)) var/trail_type = getTrail() if(trail_type) var/brute_ratio = round(getBruteLoss()/maxHealth, 0.1) if(blood_volume && blood_volume > max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage. var/newdir = get_dir(T, loc) if(newdir != src.dir) newdir = newdir | dir if(newdir == 3) //N + S newdir = NORTH else if(newdir == 12) //E + W newdir = EAST if((newdir in GLOB.cardinal) && (prob(50))) newdir = turn(get_dir(T, loc), 180) if(!blood_exists) new /obj/effect/decal/cleanable/trail_holder(loc) for(var/obj/effect/decal/cleanable/trail_holder/TH in loc) if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) TH.existing_dirs += newdir TH.overlays.Add(image('icons/effects/blood.dmi', trail_type, dir = newdir)) TH.transfer_mob_blood_dna(src) if(ishuman(src)) var/mob/living/carbon/human/H = src if(H.dna.species.blood_color) TH.color = H.dna.species.blood_color else TH.color = "#A10808" /mob/living/carbon/human/makeTrail(turf/T) if((NO_BLOOD in dna.species.species_traits) || dna.species.exotic_blood || !bleed_rate || bleedsuppress) return ..() /mob/living/proc/getTrail() if(getBruteLoss() < 300) return pick("ltrails_1", "ltrails_2") else return pick("trails_1", "trails_2") /mob/living/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0) if(buckled) return if(client && client.move_delay >= world.time + world.tick_lag * 2) pressure_resistance_prob_delta -= 30 var/list/turfs_to_check = list() if(has_limbs) var/turf/T = get_step(src, angle2dir(dir2angle(direction) + 90)) if (T) turfs_to_check += T T = get_step(src, angle2dir(dir2angle(direction) - 90)) if(T) turfs_to_check += T for(var/t in turfs_to_check) T = t if(T.density) pressure_resistance_prob_delta -= 20 continue for(var/atom/movable/AM in T) if(AM.density && AM.anchored) pressure_resistance_prob_delta -= 20 break ..(pressure_difference, direction, pressure_resistance_prob_delta) /*////////////////////// START RESIST PROCS */////////////////////// /mob/living/can_resist() return !((next_move > world.time) || incapacitated(ignore_restraints = TRUE, ignore_lying = TRUE)) /mob/living/verb/resist() set name = "Resist" set category = "IC" if(!can_resist()) return changeNext_move(CLICK_CD_RESIST) SEND_SIGNAL(src, COMSIG_LIVING_RESIST, src) if(!restrained()) if(resist_grab()) return //unbuckling yourself if(buckled && last_special <= world.time) resist_buckle() //Breaking out of a container (Locker, sleeper, cryo...) else if(isobj(loc)) var/obj/C = loc C.container_resist(src) else if(canmove) if(on_fire) resist_fire() //stop, drop, and roll else if(last_special <= world.time) resist_restraints() //trying to remove cuffs. /*//////////////////// RESIST SUBPROCS *///////////////////// /mob/living/proc/resist_grab() var/resisting = 0 for(var/X in grabbed_by) var/obj/item/grab/G = X resisting++ switch(G.state) if(GRAB_PASSIVE) qdel(G) if(GRAB_AGGRESSIVE) if(prob(60)) visible_message("[src] has broken free of [G.assailant]'s grip!") qdel(G) if(GRAB_NECK) if(prob(5)) visible_message("[src] has broken free of [G.assailant]'s headlock!") qdel(G) if(resisting) visible_message("[src] resists!") return 1 /mob/living/proc/resist_buckle() spawn(0) resist_muzzle() buckled.user_unbuckle_mob(src,src) /mob/living/proc/resist_muzzle() return /mob/living/proc/resist_fire() return /mob/living/proc/resist_restraints() spawn(0) resist_muzzle() return /*////////////////////// END RESIST PROCS */////////////////////// /mob/living/proc/Exhaust() to_chat(src, "You're too exhausted to keep going...") Weaken(5) /mob/living/proc/get_visible_name() return name /mob/living/update_gravity(has_gravity) if(!SSticker) return if(has_gravity) clear_alert("weightless") else throw_alert("weightless", /obj/screen/alert/weightless) if(!flying) float(!has_gravity) /mob/living/proc/float(on) if(throwing) return var/fixed = FALSE if(anchored || (buckled && buckled.anchored)) fixed = TRUE if(on && !floating && !fixed) animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1) sleep(10) animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1) floating = TRUE else if(((!on || fixed) && floating)) animate(src, pixel_y = get_standard_pixel_y_offset(lying), time = 10) floating = FALSE /mob/living/proc/can_use_vents() return "You can't fit into that vent." //called when the mob receives a bright flash /mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash) if(check_eye_prot() < intensity && (override_blindness_check || !(BLINDNESS in mutations))) overlay_fullscreen("flash", type) addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25) return 1 /mob/living/proc/check_eye_prot() return 0 /mob/living/proc/check_ear_prot() // The src mob is trying to strip an item from someone // Override if a certain type of mob should be behave differently when stripping items (can't, for example) /mob/living/stripPanelUnequip(obj/item/what, mob/who, where, var/silent = 0) if(what.flags & NODROP) to_chat(src, "You can't remove \the [what.name], it appears to be stuck!") return if(!silent) who.visible_message("[src] tries to remove [who]'s [what.name].", \ "[src] tries to remove [who]'s [what.name].") what.add_fingerprint(src) if(do_mob(src, who, what.strip_delay)) if(what && what == who.get_item_by_slot(where) && Adjacent(who)) who.unEquip(what) if(silent) put_in_hands(what) add_attack_logs(src, who, "Stripped of [what]") // The src mob is trying to place an item on someone // Override if a certain mob should be behave differently when placing items (can't, for example) /mob/living/stripPanelEquip(obj/item/what, mob/who, where, var/silent = 0) what = get_active_hand() if(what && (what.flags & NODROP)) to_chat(src, "You can't put \the [what.name] on [who], it's stuck to your hand!") return if(what) if(!what.mob_can_equip(who, where, 1)) to_chat(src, "\The [what.name] doesn't fit in that place!") return if(!silent) visible_message("[src] tries to put [what] on [who].") if(do_mob(src, who, what.put_on_delay)) if(what && Adjacent(who) && !(what.flags & NODROP)) unEquip(what) who.equip_to_slot_if_possible(what, where, FALSE, TRUE) add_attack_logs(src, who, "Equipped [what]") /mob/living/singularity_act() investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up! gib() return 20 /mob/living/singularity_pull(S, current_size) ..() if(current_size >= STAGE_SIX) //your puny magboots/wings/whatever will not save you against supermatter singularity throw_at(S, 14, 3, src, TRUE) else if(!mob_negates_gravity()) step_towards(src,S) /mob/living/narsie_act() if(client) makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, src, null, 1) spawn_dust() gib() /mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!used_item) used_item = get_active_hand() ..() floating = FALSE // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. /mob/living/proc/do_jitter_animation(jitteriness, loop_amount = 6) var/amplitude = min(4, (jitteriness / 100) + 1) var/pixel_x_diff = rand(-amplitude, amplitude) var/pixel_y_diff = rand(-amplitude / 3, amplitude / 3) var/final_pixel_x = get_standard_pixel_x_offset(lying) var/final_pixel_y = get_standard_pixel_y_offset(lying) animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = loop_amount) animate(pixel_x = final_pixel_x , pixel_y = final_pixel_y , time = 2) floating = FALSE // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. /mob/living/proc/get_temperature(datum/gas_mixture/environment) var/loc_temp = T0C if(istype(loc, /obj/mecha)) var/obj/mecha/M = loc loc_temp = M.return_temperature() else if(istype(loc, /obj/spacepod)) var/obj/spacepod/S = loc loc_temp = S.return_temperature() else if(istype(loc, /obj/structure/transit_tube_pod)) loc_temp = environment.temperature else if(istype(get_turf(src), /turf/space)) var/turf/heat_turf = get_turf(src) loc_temp = heat_turf.temperature else if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) var/obj/machinery/atmospherics/unary/cryo_cell/C = loc if(C.air_contents.total_moles() < 10) loc_temp = environment.temperature else loc_temp = C.air_contents.temperature else loc_temp = environment.temperature return loc_temp /mob/living/proc/get_standard_pixel_x_offset(lying = 0) return initial(pixel_x) /mob/living/proc/get_standard_pixel_y_offset(lying = 0) return initial(pixel_y) /mob/living/proc/spawn_dust() new /obj/effect/decal/cleanable/ash(loc) //used in datum/reagents/reaction() proc /mob/living/proc/get_permeability_protection() return 0 /mob/living/proc/attempt_harvest(obj/item/I, mob/user) if(user.a_intent == INTENT_HARM && stat == DEAD && butcher_results) //can we butcher it? var/sharpness = is_sharp(I) if(sharpness) to_chat(user, "You begin to butcher [src]...") playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1) if(do_mob(user, src, 80 / sharpness) && Adjacent(I)) harvest(user) return 1 /mob/living/proc/harvest(mob/living/user) if(QDELETED(src)) return if(butcher_results) for(var/path in butcher_results) for(var/i = 1, i <= butcher_results[path], i++) new path(loc) butcher_results.Remove(path) //In case you want to have things like simple_animals drop their butcher results on gib, so it won't double up below. visible_message("[user] butchers [src].") gib() /mob/living/movement_delay(ignorewalk = 0) . = ..() if(isturf(loc)) var/turf/T = loc . += T.slowdown if(slowed) . += 10 if(forced_look) . += 3 if(ignorewalk) . += config.run_speed else switch(m_intent) if(MOVE_INTENT_RUN) if(drowsyness > 0) . += 6 . += config.run_speed if(MOVE_INTENT_WALK) . += config.walk_speed /mob/living/proc/can_use_guns(var/obj/item/gun/G) if(G.trigger_guard != TRIGGER_GUARD_ALLOW_ALL && !IsAdvancedToolUser() && !issmall(src)) to_chat(src, "You don't have the dexterity to do this!") return 0 return 1 /mob/living/start_pulling(atom/movable/AM, state, force = pull_force, show_message = FALSE) if(!AM || !src) return FALSE if(!(AM.can_be_pulled(src, state, force, show_message))) return FALSE if(incapacitated()) return // If we're pulling something then drop what we're currently pulling and pull this instead. AM.add_fingerprint(src) if(pulling) if(AM == pulling)// Are we trying to pull something we are already pulling? Then just stop here, no need to continue. return stop_pulling() if(AM.pulledby) visible_message("[src] has pulled [AM] from [AM.pulledby]'s grip.") AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. pulling = AM AM.pulledby = src if(pullin) pullin.update_icon(src) if(ismob(AM)) var/mob/M = AM if(!iscarbon(src)) M.LAssailant = null else M.LAssailant = usr /mob/living/proc/check_pull() if(pulling && !(pulling in orange(1))) stop_pulling() /mob/living/proc/update_z(new_z) // 1+ to register, null to unregister if(registered_z != new_z) if(registered_z) SSmobs.clients_by_zlevel[registered_z] -= src if(client) if(new_z) SSmobs.clients_by_zlevel[new_z] += src for (var/I in length(SSidlenpcpool.idle_mobs_by_zlevel[new_z]) to 1 step -1) //Backwards loop because we're removing (guarantees optimal rather than worst-case performance), it's fine to use .len here but doesn't compile on 511 var/mob/living/simple_animal/SA = SSidlenpcpool.idle_mobs_by_zlevel[new_z][I] if (SA) SA.toggle_ai(AI_ON) // Guarantees responsiveness for when appearing right next to mobs else SSidlenpcpool.idle_mobs_by_zlevel[new_z] -= SA registered_z = new_z else registered_z = null /mob/living/onTransitZ(old_z,new_z) ..() update_z(new_z) /mob/living/proc/owns_soul() if(mind) return mind.soulOwner == mind return 1 /mob/living/proc/return_soul() if(mind) if(mind.soulOwner.devilinfo)//Not sure how this could happen, but whatever. mind.soulOwner.devilinfo.remove_soul(mind) mind.soulOwner = mind mind.damnation_type = 0 /mob/living/proc/has_bane(banetype) if(mind) if(mind.devilinfo) return mind.devilinfo.bane == banetype return 0 /mob/living/proc/check_weakness(obj/item/weapon, mob/living/attacker) if(mind && mind.devilinfo) return check_devil_bane_multiplier(weapon, attacker) return 1 /mob/living/proc/check_acedia() if(src.mind && src.mind.objectives) for(var/datum/objective/sintouched/acedia/A in src.mind.objectives) return 1 return 0 /mob/living/proc/fakefireextinguish() return /mob/living/proc/fakefire() return /mob/living/extinguish_light() for(var/atom/A in src) if(A.light_range > 0) A.extinguish_light() /mob/living/vv_edit_var(var_name, var_value) switch(var_name) if("stat") if((stat == DEAD) && (var_value < DEAD))//Bringing the dead back to life GLOB.dead_mob_list -= src GLOB.alive_mob_list += src if((stat < DEAD) && (var_value == DEAD))//Kill he GLOB.alive_mob_list -= src GLOB.dead_mob_list += src . = ..() switch(var_name) if("weakened") SetWeakened(var_value) if("stunned") SetStunned(var_value) if("paralysis") SetParalysis(var_value) if("sleeping") SetSleeping(var_value) if("maxHealth") updatehealth() if("resize") update_transform() if("lighting_alpha") sync_lighting_plane_alpha()