/mob/living/New() ..() if(!species_type) species_type = src.type if(can_butcher && !meat_amount) meat_amount = size immune_system = new (src) oxy_damage_modifier *= (maxHealth / 100) //Scale oxy damage based on the max health of the mob. /mob/living/create_reagents(const/max_vol) ..(max_vol) addicted_chems = new /datum/reagents(max_vol) addicted_chems.my_atom = src tolerated_chems = list() /mob/living/Destroy() if(butchering_drops) for(var/datum/butchering_product/B in butchering_drops) butchering_drops -= B QDEL_NULL(B) if(immune_system) QDEL_NULL(immune_system) if(addicted_chems) QDEL_NULL(addicted_chems) . = ..() /mob/living/examine(var/mob/user, var/size = "", var/show_name = TRUE, var/show_icon = TRUE) //Show the mob's size and whether it's been butchered switch(src.size) if(SIZE_TINY) size = "tiny" if(SIZE_SMALL) size = "small" if(SIZE_NORMAL) size = "average in size" if(SIZE_BIG) size = "big" if(SIZE_HUGE) size = "huge" var/pronoun = "it is" switch(gender) if(FEMALE) pronoun = "she is" if(MALE) pronoun = "he is" if(PLURAL) pronoun = "they are" ..(user, " [capitalize(pronoun)] [size].", show_name, FALSE) if(meat_taken > 0) to_chat(user, "[capitalize(pronoun)] partially butchered.") var/butchery = "" //More information about butchering status, check out "code/datums/helper_datums/butchering.dm" if(butchering_drops && butchering_drops.len) for(var/datum/butchering_product/B in butchering_drops) butchery = "[butchery][B.desc_modifier(src)]" if(butchery) to_chat(user, "[butchery]") /mob/living/Life() if(timestopped) return 0 //under effects of time magick ..() if (flags & INVULNERABLE) bodytemperature = initial(bodytemperature) if (monkeyizing) return 0 if(!loc) return 0 // Fixing a null error that occurs when the mob isn't found in the world -- TLE // Why the fuck is this handled here? if(reagents && reagents.has_reagent(BUSTANUT)) if(!(M_HARDCORE in mutations)) mutations.Add(M_HARDCORE) to_chat(src, "You feel like you're the best around. Nothing's going to get you down.") else if(M_HARDCORE in mutations) mutations.Remove(M_HARDCORE) to_chat(src, "You feel like a pleb.") handle_beams() if(istype(get_turf(src),/turf/unsimulated/floor/brimstone)) FireBurn(11, 9001, ONE_ATMOSPHERE) // lag free weird way of doing it fire_stacks = 11 IgniteMob() // ffffFIRE!!!! FIRE!!! FIRE!! return 1 // Apply connect damage /mob/living/beam_connect(var/obj/effect/beam/B) ..() last_beamchecks["\ref[B]"]=world.time /mob/living/beam_disconnect(var/obj/effect/beam/B) ..() apply_beam_damage(B) last_beamchecks.Remove("\ref[B]") // RIP /mob/living/handle_beams() if(flags & INVULNERABLE) return // New beam damage code (per-tick) for(var/obj/effect/beam/B in beams) apply_beam_damage(B) /mob/living/cultify() if(islegacycultist(src) && client) var/mob/living/simple_animal/construct/harvester/C = new /mob/living/simple_animal/construct/harvester(get_turf(src)) mind.transfer_to(C) to_chat(C, "The Geometer of Blood is overjoyed to be reunited with its followers, and accepts your body in sacrifice. As reward, you have been gifted with the shell of an Harvester.
Your tendrils can use and draw runes without need for a tome, your eyes can see beings through walls, and your mind can open any door. Use these assets to serve Nar-Sie and bring him any remaining living human in the world.
You can teleport yourself back to Nar-Sie along with any being under yourself at any time using your \"Harvest\" spell.
") dust() else if(!iscultist(src)) if(client) var/datum/faction/cult/narsie/cult_fact = find_active_faction_by_type(/datum/faction/cult/narsie) if (cult_fact) cult_fact.harvested++ var/mob/dead/G = (ghostize()) G.icon = 'icons/mob/mob.dmi' G.icon_state = "ghost-narsie" G.overlays = 0 if(istype(G.mind.current, /mob/living/carbon/human/)) var/mob/living/carbon/human/H = G.mind.current G.overlays += H.obj_overlays[ID_LAYER] G.overlays += H.obj_overlays[EARS_LAYER] G.overlays += H.obj_overlays[SUIT_LAYER] G.overlays += H.obj_overlays[GLASSES_LAYER] G.overlays += H.obj_overlays[GLASSES_OVER_HAIR_LAYER] G.overlays += H.obj_overlays[BELT_LAYER] G.overlays += H.obj_overlays[BACK_LAYER] G.overlays += H.obj_overlays[HEAD_LAYER] G.overlays += H.obj_overlays[HANDCUFF_LAYER] G.invisibility = 0 to_chat(G, "You feel relieved as what's left of your soul finally escapes its prison of flesh.") spawn(1) dust() /mob/living/apply_beam_damage(var/obj/effect/beam/B) var/lastcheck=last_beamchecks["\ref[B]"] // Figure out how much damage to deal. // Formula: (deciseconds_since_connect/10 deciseconds)*B.get_damage() var/damage = ((world.time - lastcheck)/10) * B.get_damage() * beam_defense(B) // Actually apply damage apply_damage(damage, B.damage_type, B.def_zone) // Emitter attack logging. Only when source of emitter beam is /mob/living and there's a ckey in either if (B.sources.len >= 1 && (isliving(B.sources[1]))) var/mob/living/assailant = B.sources[1] if (assailant.ckey || src.ckey) log_attack("[assailant.name][assailant.ckey ? "([assailant.ckey])" : "(no key)"] attacked [src.name][src.ckey ? "([src.ckey])" : "(no key)"] with [B.name]") // Update check time. last_beamchecks["\ref[B]"]=world.time //Return multiplier for damage /mob/living/proc/beam_defense(var/obj/effect/beam/B) return 1 /mob/living/verb/succumb() set hidden = 1 succumb_proc(0) /mob/living/proc/succumb_proc(var/gibbed = 0, var/from_deathgasp = FALSE) if (src.health < 0 && stat != DEAD) src.attack_log += "[src] has succumbed to death with [health] points of health!" src.apply_damage(maxHealth + src.health, OXY) if (!from_deathgasp) emote("deathgasp", message = TRUE) death(gibbed) to_chat(src, "You have given up life and succumbed to death.") /mob/living/proc/updatehealth() if(status_flags & GODMODE) health = maxHealth stat = CONSCIOUS else if(!(flags & INVULNERABLE)) var/prevhealth = health health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - halloss critlog(health,prevhealth) //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 //sort of a legacy burn method for /electrocute, /shock, and the e_chair /mob/living/proc/burn_skin(burn_amount) if(istype(src, /mob/living/carbon/human)) // to_chat(world, "DEBUG: burn_skin(), mutations=[mutations]") if(M_NO_SHOCK in src.mutations) //shockproof return 0 if (M_RESIST_HEAT in src.mutations) //fireproof return 0 var/mob/living/carbon/human/H = src //make this damage method divide the damage to be done among all the body parts, then burn each body part for that much damage. will have better effect then just randomly picking a body part var/divided_damage = (burn_amount)/(H.organs.len) var/extradam = 0 //added to when organ is at max dam for(var/datum/organ/external/affecting in H.organs) if(!affecting) continue if(affecting.take_damage(0, divided_damage+extradam)) //TODO: fix the extradam stuff. Or, ebtter yet...rewrite this entire proc ~Carn H.UpdateDamageIcon() H.updatehealth() return 1 else if(istype(src, /mob/living/carbon/monkey)) if (M_RESIST_HEAT in src.mutations) //fireproof return 0 var/mob/living/carbon/monkey/M = src M.adjustFireLoss(burn_amount) M.updatehealth() return 1 else if(istype(src, /mob/living/silicon/ai)) 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] ~ [src.bodytemperature] ~ [temperature]") return temperature /mob/living/proc/getBruteLoss(var/ignore_inorganic) return bruteloss /mob/living/proc/adjustBruteLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode if(INVOKE_EVENT(src, /event/damaged, "kind" = BRUTE, "amount" = amount)) return 0 bruteloss = min(max(bruteloss + (amount * brute_damage_modifier), 0),(maxHealth*2)) /mob/living/proc/getOxyLoss() return oxyloss /mob/living/proc/adjustOxyLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode if(INVOKE_EVENT(src, /event/damaged, "kind" = OXY, "amount" = amount)) return 0 oxyloss = min(max(oxyloss + (amount * oxy_damage_modifier), 0),(maxHealth*2)) /mob/living/proc/setOxyLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode oxyloss = amount /mob/living/proc/getToxLoss() return toxloss /mob/living/proc/adjustToxLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode if(INVOKE_EVENT(src, /event/damaged, "kind" = TOX, "amount" = amount)) return 0 var/mult = 1 if(ishuman(src)) var/mob/living/carbon/human/H = src if(H.species.tox_mod) mult = H.species.tox_mod var/datum/organ/internal/heart/hivelord/HL = H.get_heart() if(istype(HL) && amount < 0) // hivelord hearts just heal better mult *= 2 toxloss = min(max(toxloss + (amount * tox_damage_modifier * mult), 0),(maxHealth*2)) /mob/living/proc/setToxLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode toxloss = amount /mob/living/proc/getFireLoss(var/ignore_inorganic) return fireloss /mob/living/proc/adjustFireLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode if(mutations.Find(M_RESIST_HEAT)) return 0 if(INVOKE_EVENT(src, /event/damaged, "kind" = BURN, "amount" = amount)) return 0 fireloss = min(max(fireloss + (amount * burn_damage_modifier), 0),(maxHealth*2)) /mob/living/proc/getCloneLoss() return cloneloss /mob/living/proc/adjustCloneLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode if(INVOKE_EVENT(src, /event/damaged, "kind" = CLONE, "amount" = amount)) return 0 if(ishuman(src)) var/mob/living/carbon/human/H = src if(isslimeperson(H)) amount = min(amount, 0) cloneloss = min(max(cloneloss + (amount * clone_damage_modifier), 0),(maxHealth*2)) /mob/living/proc/setCloneLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode cloneloss = amount /mob/living/proc/getBrainLoss() return brainloss /mob/living/proc/adjustBrainLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode if(INVOKE_EVENT(src, /event/damaged, "kind" = BRAIN, "amount" = amount)) return 0 brainloss = min(max(brainloss + (amount * brain_damage_modifier), 0),(maxHealth*2)) /mob/living/proc/setBrainLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode brainloss = amount /mob/living/proc/getHalLoss() return halloss /mob/living/proc/adjustHalLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode halloss = min(max(halloss + (amount * hal_damage_modifier), 0),(maxHealth*2)) /mob/living/proc/setHalLoss(var/amount) if(status_flags & GODMODE) return 0 //godmode halloss = amount /mob/living/proc/getMaxHealth() return maxHealth /mob/living/proc/setMaxHealth(var/newMaxHealth) maxHealth = newMaxHealth /mob/living/proc/get_butchering_products() return list() // ++++ROCKDTBEN++++ MOB PROCS //END /mob/proc/get_contents() //Recursive function to find everything a mob is holding. /mob/living/get_contents(var/obj/item/weapon/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/weapon/storage/S in Storage.return_inv()) //Check for storage items // L += get_contents(S) for(var/obj/item/weapon/gift/G in Storage.return_inv()) //Check for gift-wrapped items L += G.gift if(istype(G.gift, /obj/item/weapon/storage)) L += get_contents(G.gift) for(var/obj/item/delivery/D in Storage.return_inv()) //Check for package wrapped items for(var/atom/movable/wrapped in D) //Basically always only one thing, but could theoretically be more L += wrapped if(istype(wrapped, /obj/item/weapon/storage)) //this should never happen L += get_contents(wrapped) return L else L += src.contents for(var/obj/item/weapon/storage/S in src.contents) //Check for storage items L += get_contents(S) for(var/obj/item/clothing/suit/storage/S in src.contents)//Check for labcoats and jackets L += get_contents(S.hold) for(var/obj/item/clothing/accessory/storage/S in src.contents)//Check for holsters L += get_contents(S.hold) for(var/obj/item/weapon/gift/G in src.contents) //Check for gift-wrapped items L += G.gift if(istype(G.gift, /obj/item/weapon/storage)) L += get_contents(G.gift) for(var/obj/item/delivery/D in src.contents) //Check for package wrapped items for(var/atom/movable/wrapped in D) //Basically always only one thing, but could theoretically be more L += wrapped if(istype(wrapped, /obj/item/weapon/storage)) //this should never happen L += get_contents(wrapped) return L /mob/living/proc/electrocute_act(const/shock_damage, const/obj/source, const/siemens_coeff = 1.0) if(status_flags & GODMODE || (M_NO_SHOCK in src.mutations)) return 0 var/damage = shock_damage * siemens_coeff if(damage <= 0) damage = 0 adjustFireLoss(damage) return damage /mob/living/emp_act(severity) for(var/obj/item/stickybomb/B in src) if(B.stuck_to) visible_message("\the [B] stuck on \the [src] suddenly deactivates itself and falls to the ground.") B.deactivate() B.unstick() if(flags & INVULNERABLE) return var/list/L = src.get_contents() for(var/obj/O in L) O.emp_act(severity) ..() /mob/living/proc/get_organ(zone) RETURN_TYPE(/datum/organ/external) return //A proc that turns organ strings into a list of organ datums //The organ strings can be fed in as arguments, or as a list /mob/living/proc/get_organs(organs) return list() /mob/living/proc/get_organ_target() var/t = src.zone_sel.selecting if ((t in list( "eyes", "mouth" ))) t = LIMB_HEAD var/datum/organ/external/def_zone = ran_zone(t) return def_zone // heal ONE external organ, organ gets randomly selected from damaged ones. /mob/living/proc/heal_organ_damage(var/brute, var/burn) adjustBruteLoss(-brute) adjustFireLoss(-burn) src.updatehealth() // damage ONE external organ, organ gets randomly selected from damaged ones. /mob/living/proc/take_organ_damage(var/brute, var/burn, var/ignore_inorganics = FALSE) if(status_flags & GODMODE) return 0 //godmode if(flags & INVULNERABLE) return 0 adjustBruteLoss(brute) adjustFireLoss(burn) src.updatehealth() // heal MANY external organs, in random order /mob/living/proc/heal_overall_damage(var/brute, var/burn) adjustBruteLoss(-brute) adjustFireLoss(-burn) src.updatehealth() // damage MANY external organs, in random order /mob/living/proc/take_overall_damage(var/brute, var/burn, var/used_weapon = null) if(status_flags & GODMODE) return 0 //godmode if(flags & INVULNERABLE) return 0 adjustBruteLoss(brute) adjustFireLoss(burn) src.updatehealth() return brute + burn /mob/living/proc/restore_all_organs() return /* NOTE TO ANYONE MAKING A PROC THAT USES REVIVE/REJUVENATE: If the proc calling either of these is: -meant to be an admin/overpowered revival proc, make sure you set suiciding = 0 -meant to be something that a player uses to heal/revive themself or others, check if suiciding = 1 and prevent them from reviving if true. Thanks. */ /mob/living/proc/revive(animation = 0) rejuvenate(animation) /* locked_to = initial(src.locked_to) */ if(iscarbon(src)) var/mob/living/carbon/C = src if(C.handcuffed) C.drop_from_inventory(C.handcuffed) if (C.mutual_handcuffs) C.drop_from_inventory(C.mutual_handcuffs) if (C.legcuffed) C.drop_from_inventory(C.legcuffed) hud_updateflag |= 1 << HEALTH_HUD hud_updateflag |= 1 << STATUS_HUD /mob/living/proc/rejuvenate(animation = 0) var/turf/T = get_turf(src) if(animation) T.turf_animation('icons/effects/64x64.dmi',"rejuvenate",-16,0,MOB_LAYER+1,'sound/effects/rejuvenate.ogg',anim_plane = EFFECTS_PLANE) // shut down various types of badness toxloss = 0 oxyloss = 0 cloneloss = 0 bruteloss = 0 fireloss = 0 brainloss = 0 halloss = 0 paralysis = 0 stunned = 0 knockdown = 0 remove_jitter() germ_level = 0 next_pain_time = 0 radiation = 0 rad_tick = 0 nutrition = 400 bodytemperature = 310 sdisabilities = 0 disabilities = 0 blinded = 0 eye_blind = 0 eye_blurry = 0 ear_deaf = 0 ear_damage = 0 say_mute = 0 said_last_words = 0 mutations.Remove(M_HUSK) if(!reagents) create_reagents(1000) else reagents.clear_reagents() heal_overall_damage(1000, 1000) ExtinguishMob() fire_stacks = 0 /* if(locked_to) locked_to.unbuckle() locked_to = initial(src.locked_to) */ if(istype(src, /mob/living/carbon)) var/mob/living/carbon/C = src dead_mob_list -= C living_mob_list |= list(C) if(istype(src, /mob/living/carbon/human)) var/mob/living/carbon/human/H = src H.timeofdeath = 0 H.vessel.reagent_list = list() H.vessel.add_reagent(BLOOD,560) H.pain_shock_stage = 0 for(var/organ_name in H.organs_by_name) var/datum/organ/external/O = H.organs_by_name[organ_name] for(var/obj/item/weapon/shard/shrapnel/s in O.implants) if(istype(s)) O.implants -= s H.contents -= s QDEL_NULL(s) O.amputated = 0 O.brute_dam = 0 O.burn_dam = 0 O.damage_state = "00" O.germ_level = 0 O.hidden = null O.number_wounds = 0 O.open = 0 O.perma_injury = 0 O.stage = 0 O.status = 0 O.trace_chemicals = list() O.wounds = list() O.wound_update_accuracy = 1 for(var/organ_name in H.internal_organs_by_name) var/datum/organ/internal/IO = H.internal_organs_by_name[organ_name] IO.damage = 0 IO.trace_chemicals.len = 0 IO.germ_level = 0 IO.status = 0 IO.robotic = 0 H.updatehealth() H.op_stage.butt = SURGERY_HAS_A_BUTT H.op_stage.butt_replace = SURGERY_BEGIN_BUTT_REPLACE for(var/datum/disease/D in viruses) D.cure(0) for (var/ID in virus2) var/datum/disease2/disease/V = virus2[ID] V.cure(src) if(stat == DEAD) resurrect() tod = null // restore us to conciousness stat = CONSCIOUS //Snowflake fix for zombiepowder status_flags &= ~FAKEDEATH // make the icons look correct regenerate_icons() update_canmove() clear_fullscreens() hud_updateflag |= 1 << HEALTH_HUD hud_updateflag |= 1 << STATUS_HUD /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(NewLoc, Dir = 0, step_x = 0, step_y = 0, glide_size_override = 0) if (locked_to && locked_to.loc != NewLoc) var/datum/locking_category/category = locked_to.get_lock_cat_for(src) if (locked_to.anchored || category.flags & CANT_BE_MOVED_BY_LOCKED_MOBS) return 0 else return locked_to.Move(NewLoc, Dir) if (restrained()) stop_pulling() var/turf/T = loc var/t7 = 1 //What the FUCK is this variable? if (restrained()) for(var/mob/living/M in range(src, 1)) if ((M.pulling == src && M.stat == 0 && !( M.restrained()))) t7 = null if (t7 && pulling && (Adjacent(pulling) || pulling.loc == loc)) . = ..() if (pulling && pulling.loc) if(!isturf(pulling.loc)) stop_pulling() return else if(Debug) diary <<"pulling disappeared? at [__LINE__] in mob.dm - pulling = [pulling]" diary <<"REPORT THIS" ///// if(pulling && pulling.anchored) stop_pulling() return var/mob/living/M = pulling if (!restrained()) var/diag = get_dir(src, pulling) if ((diag - 1) & diag) else diag = null if ((get_dist(src, pulling) > 1 || diag)) if(!istype(pulling) || !pulling) if (iscarbon(src)) var/mob/living/carbon/carbon = src if (!carbon.mutual_handcuffed_to) WARNING("Pulling disappeared! pulling = [pulling] old pulling = [M]") else if(isturf(pulling.loc)) if (isliving(pulling)) M = pulling var/ok = 1 if (locate(/obj/item/weapon/grab, M.grabbed_by)) if (prob(75)) var/obj/item/weapon/grab/G = pick(M.grabbed_by) if (istype(G, /obj/item/weapon/grab)) visible_message("[src] has pulled [G.affecting] from [G.assailant]'s grip.", drugged_message="[src] has pulled [G.affecting] from [G.assailant]'s hug.") qdel(G) else ok = 0 if (locate(/obj/item/weapon/grab, M.grabbed_by.len)) ok = 0 if (ok) var/atom/movable/secondarypull = M.pulling M.stop_pulling() INVOKE_EVENT(src, /event/before_move) pulling.Move(T, get_dir(pulling, T), glide_size_override = src.glide_size) INVOKE_EVENT(src, /event/after_move) if(M && secondarypull) M.start_pulling(secondarypull) else if (pulling) pulling.Move(T, get_dir(pulling, T), glide_size_override = src.glide_size) else stop_pulling() else stop_pulling() . = ..() if ((s_active && !is_holder_of(src, s_active))) s_active.close(src) if(update_slimes) for(var/mob/living/carbon/slime/M in view(1,src)) M.UpdateFeed(src) if(T != loc) handle_hookchain(Dir) if(client && client.eye && istype(client.eye,/turf/simulated/wall)) var/turf/simulated/wall/W = client.eye if (!Adjacent(W)) client.eye = src client.perspective = MOB_PERSPECTIVE W.peeper = null if(.) for(var/obj/item/weapon/gun/G in targeted_by) //Handle moving out of the gunner's view. var/mob/living/M = G.loc if(!(M in view(src))) NotTargeted(G) for(var/obj/item/weapon/gun/G in src) //Handle the gunner losing sight of their target/s if(G.target) for(var/mob/living/M in G.target) if(M && !(M in view(src))) M.NotTargeted(G) /mob/living/proc/handle_hookchain(var/direct) for(var/obj/item/weapon/gun/hookshot/hookshot in src) if(hookshot.clockwerk) continue for(var/i = 1;i\The [inside_tunneler]'s storage bin shudders.","You wander through subspace, looking for a way out (this will take about [breakout_time * 60] seconds).") spawn(0) if(do_after(usr,src,breakout_time * 60 * 10)) //minutes * 60seconds * 10deciseconds var/obj/item/weapon/subspacetunneler/still_in = get_holder_of_type(L, /obj/item/weapon/subspacetunneler) if(!inside_tunneler || !L || L.stat != CONSCIOUS || !still_in) //tunneler/user destroyed OR user dead/unconcious OR user no longer in tunneler return //Well then break it! inside_tunneler.break_out(L) return //Getting out of someone's inventory. if(istype(src.loc,/obj/item/weapon/holder)) var/obj/item/weapon/holder/H = src.loc forceMove(T) if(istype(H.loc, /mob/living)) var/mob/living/Location = H.loc Location.drop_from_inventory(H) QDEL_NULL(H) return else if(istype(src.loc, /obj/structure/strange_present)) var/obj/structure/strange_present/present = src.loc to_chat(L, "You attempt to unwrap yourself, these wraps are tight and will take some time.") if(do_after(src, src, 2 MINUTES)) L.visible_message("[L] successfully breaks out of [present]!",\ "You successfully break out!") forceMove(T) qdel(present) playsound(src.loc, 'sound/items/poster_ripped.ogg', 100, 1) return else if(istype(src.loc, /obj/item/delivery/large)) //Syndie item var/obj/item/delivery/large/package = src.loc to_chat(L, "You attempt to unwrap yourself, this package is tight and will take some time.") if(do_after(src, src, 2 MINUTES)) L.visible_message("[L] successfully breaks out of [package]!",\ "You successfully break out!") forceMove(T) qdel(package) playsound(src.loc, 'sound/items/poster_ripped.ogg', 100, 1) return else if(istype(src.loc, /obj/effect/spider/cocoon)) var/obj/effect/spider/cocoon/cocoon = src.loc to_chat(L, "You attempt to untangle yourself, the webs are tight and will take some time.") if(do_after(src, src, 2 MINUTES)) L.visible_message("[L] successfully breaks out of [cocoon]!",\ "You successfully break out!") forceMove(T) qdel(cocoon) //Detaching yourself from a tether if(L.tether) var/mob/living/carbon/CM = L if(!istype(CM) || !CM.handcuffed) var/datum/chain/tether_datum = L.tether.chain_datum if(tether_datum.extremity_B == src) L.visible_message("\the [L] quickly grabs and removes \the [L.tether] tethered to his body!", "You quickly grab and remove \the [L.tether] tethered to your body.") L.tether = null tether_datum.extremity_B = null tether_datum.rewind_chain() //Trying to unstick a stickybomb for(var/obj/item/stickybomb/B in L) if(B.stuck_to) L.visible_message("\the [L] is trying to reach and pull off \the [B] stuck on his body!", "You reach for \the [B] stuck on your body and start pulling.") if(do_after(L, src, 30, 10, FALSE)) L.visible_message("After struggling for an instant, \the [L] manages unstick \the [B] from his body!", "It came off!") L.put_in_hands(B) B.unstick(0) else to_chat(L, "You need to stop moving around while you try to get a hold of \the [B]!") return else continue //Resisting control by an alien mind. if(istype(src.loc,/mob/living/simple_animal/borer)) var/mob/living/simple_animal/borer/B = src.loc var/mob/living/captive_brain/H = src H.simple_message("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).",\ "You attempt to remember who you are and how the heck did you get here (this will probably take a while).") to_chat(B.host, "You feel the captive mind of [src] begin to resist your control.") spawn(rand(350,450)+B.host.brainloss) if(!B || !B.controlling) return B.host.adjustBrainLoss(rand(5,10)) H.simple_message("With an immense exertion of will, you regain control of your body!") to_chat(B.host, "You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.") var/mob/living/carbon/C=B.host C.do_release_control(0) // Was detach(). return //resisting grabs (as if it helps anyone...) if ((!(L.stat) && L.canmove && !(L.restrained()))) var/resisting = 0 for(var/obj/O in L.requests) L.requests.Remove(O) QDEL_NULL(O) resisting++ for(var/obj/item/weapon/grab/G in usr.grabbed_by) resisting++ if (G.state == GRAB_PASSIVE) qdel(G) else if (G.state == GRAB_AGGRESSIVE) if (prob(25)) L.visible_message("[L] has broken free of [G.assailant]'s grip!", \ drugged_message="[L] has broken free of [G.assailant]'s hug!") qdel(G) else if (G.state == GRAB_NECK) if (prob(5)) L.visible_message("[L] has broken free of [G.assailant]'s headlock!", \ drugged_message="[L] has broken free of [G.assailant]'s passionate hug!") qdel(G) if(resisting) L.visible_message("[L] resists!") if(L.locked_to && !L.isUnconscious()) // unbeartrapping yourself if (istype(L.locked_to, /obj/item/weapon/beartrap/)) if (!iscarbon(L)) L.locked_to.attack_hand(L) return else var/mob/living/carbon/C = L if (!C.handcuffed) L.locked_to.attack_hand(L) return //unbuckling yourself if(istype(L.locked_to, /obj/structure/bed)) var/obj/structure/bed/B = L.locked_to if(istype(B, /obj/structure/bed/guillotine)) var/obj/structure/bed/guillotine/G = B if(G.open) G.manual_unbuckle(L, resisting = TRUE) else L.visible_message("\The [L] attempts to dislodge \the [G]'s stocks!", "You attempt to dislodge \the [G]'s stocks (this will take around thirty seconds).", self_drugged_message="You attempt to chew through the wooden stocks of \the [G] (this will take a while).") spawn(0) if(do_after(usr, usr, 30 SECONDS)) if(!L.locked_to) return L.visible_message("\The [L] dislodges \the [G]'s stocks and climbs out of \the [src]!",\ "You dislodge \the [G]'s stocks and climb out of \the [G].",\ self_drugged_message="You successfully chew through the wooden stocks.") G.open = TRUE G.manual_unbuckle(L, resisting = TRUE) G.update_icon() G.verbs -= /obj/structure/bed/guillotine/verb/open_stocks G.verbs += /obj/structure/bed/guillotine/verb/close_stocks else L.simple_message("Your escape attempt was interrupted.", \ "Your chewing was interrupted. Damn it!") else if(iscarbon(L)) var/mob/living/carbon/C = L if(C.restrained()) if(isalienadult(C) || (M_HULK in usr.mutations)) C.visible_message("[C] is trying to forcefully unbuckle!", "You attempt to forcefully unbuckle (This will take around five seconds).") spawn(0) // I have no idea what this is supposed to actually do but everything else has it so why not if(do_after(C, C, 5 SECONDS)) if(!C.handcuffed || !C.locked_to) return C.visible_message("[C] manages to forcefully unbuckle!", "You successfully forcefully unbuckle.") if(!isalien(C)) C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) B.manual_unbuckle(C, resisting = TRUE) else to_chat(C, "Your unbuckling attempt was interrupted.") else C.visible_message("[C] attempts to unbuckle themself!", "You attempt to unbuckle yourself (this will take around one minute, and you need to stay still).", self_drugged_message="You attempt to regain control of your legs (this will take a while).") spawn(0) if(do_after(usr, usr, 1 MINUTES)) if(!C.locked_to) return C.visible_message("[C] manages to unbuckle themself!",\ "You successfully unbuckle yourself.",\ self_drugged_message="You successfully regain control of your legs and stand up.") B.manual_unbuckle(C, resisting = TRUE) else C.simple_message("Your unbuckling attempt was interrupted.", \ "Your attempt to regain control of your legs was interrupted. Damn it!") else B.manual_unbuckle(L) //release from kudzu /*else if(istype(L.locked_to, /obj/effect/plantsegment)) var/obj/effect/plantsegment/K = L.locked_to K.manual_unbuckle(L)*/ //Breaking out of a locker? if(src.loc && (istype(src.loc, /obj/structure/closet))) var/breakout_time = 2 //2 minutes by default var/obj/structure/closet/C = L.loc if(C.opened) return //Door's open... wait, why are you in it's contents then? if(!istype(C.loc, /obj/item/delivery/large)) //Wouldn't want to interrupt escaping being wrapped over the next few trivial checks if(istype(C, /obj/structure/closet/secure_closet)) var/obj/structure/closet/secure_closet/SC = L.loc if(!SC.locked && !SC.welded) return //It's a secure closet, but isn't locked. Easily escapable from, no need to 'resist' else if(!C.welded) return //closed but not welded... //okay, so the closet is either welded or locked... resist!!! L.visible_message("The [C] begins to shake violenty!", "You lean on the back of [C] and start pushing the door open (this will take about [breakout_time] minutes).") spawn(0) if(do_after(usr, C, breakout_time * 60 * 10, 30, custom_checks = new /callback(C, /obj/structure/closet/proc/on_do_after))) //minutes * 60seconds * 10deciseconds if(!C || !L || L.stat != CONSCIOUS || L.loc != C || C.opened) //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened return if(!istype(C.loc, /obj/item/delivery/large)) //Wouldn't want to interrupt escaping being wrapped over the next few trivial checks //Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'... if(istype(L.loc, /obj/structure/closet/secure_closet)) var/obj/structure/closet/secure_closet/SC = L.loc if(!SC.locked && !SC.welded) return else if(!C.welded) return //Well then break it! if(istype(usr.loc, /obj/structure/closet/secure_closet)) var/obj/structure/closet/secure_closet/SC = L.loc SC.desc = "It appears to be broken." SC.icon_state = SC.icon_off flick(SC.icon_broken, SC) sleep(10) flick(SC.icon_broken, SC) sleep(10) SC.broken = SC.locked // If it's only welded just break the welding, dont break the lock. SC.locked = 0 SC.welded = 0 L.visible_message("[L] successfully breaks out of [SC]!", "You successfully break out!") if(istype(SC.loc, /obj/item/delivery/large)) //Do this to prevent contents from being opened into nullspace (read: bluespace) var/obj/item/delivery/large/BD = SC.loc BD.attack_hand(usr) SC.open() else C.welded = 0 L.visible_message("[L] successfully breaks out of [C]!", "You successfully break out!") if(istype(C.loc, /obj/item/delivery/large)) //nullspace ect.. read the comment above var/obj/item/delivery/large/BD = C.loc BD.attack_hand(usr) C.open() //Removing a headcrab if(ishuman(L)) var/on_head = L.get_item_by_slot(slot_head) if(istype(on_head, /obj/item/clothing/mask/facehugger/headcrab)) var/obj/item/clothing/mask/facehugger/headcrab/crab = on_head if(crab.is_being_resisted) return crab.is_being_resisted = 1 L.visible_message("[L.real_name] starts struggling to tear \the [crab] off of their head!") if(do_after(L, crab, 3 SECONDS)) var/rng = 50 if(crab.stat == DEAD) rng = 100 if(prob(rng)) if(L.get_item_by_slot(slot_head) == crab) L.drop_from_inventory(crab) crab.GoIdle(10 SECONDS) L.visible_message("[L.real_name] successfully tears \the [crab] off of their head!") crab.is_being_resisted = 0 crab.escaping = 1 crab.GoActive() else to_chat(L, "\The [crab] is latched on tight! Keep struggling!") crab.is_being_resisted = 0 return crab.is_being_resisted = 0 //If the do_after is cancelled. // Breaking out of a cage if (src.locked_to && istype(src.locked_to, /obj/structure/cage)) locked_to.attack_hand(src) return if(src.loc && istype(src.loc, /obj/item/mecha_parts/mecha_equipment/tool/jail)) var/breakout_time = 30 SECONDS var/obj/item/mecha_parts/mecha_equipment/tool/jail/jailcell = src.loc L.visible_message("One of \the [src.loc]'s cells rattles.","You press against the lid of \the [src.loc] and attempt to pop it open (this will take about [breakout_time/10] seconds).") spawn(0) if(do_after(usr,src,breakout_time)) //minutes * 60seconds * 10deciseconds if(src.loc != jailcell || !L || L.stat != CONSCIOUS) //if we're no longer in that mounted cell OR user dead/unconcious return //Well then break it! jailcell.break_out(L) return if((L.loc && istype(L.loc, /obj/structure/inflatable/shelter)) || (L.loc && istype(L.loc, /obj/structure/reagent_dispensers/cauldron/barrel))) var/obj/O = L.loc O.container_resist(L) else if(iscarbon(L)) var/mob/living/carbon/CM = L //putting out a fire if(CM.on_fire && CM.canmove && ((!locate(/obj/effect/fire) in loc) || !CM.handcuffed)) //No point in putting ourselves out if we'd just get set on fire again. Unless there's nothing more pressing to resist out of, in which case go nuts. CM.Knockdown(5) CM.Stun(5) playsound(CM.loc, 'sound/effects/bodyfall.ogg', 50, 1) CM.visible_message("[CM] rolls on the floor, trying to put themselves out!", "You stop, drop, and roll!") for(var/i = 1 to CM.fire_stacks + 7) CM.dir = turn(CM.dir, pick(-90, 90)) sleep(1 SECONDS) CM.fire_stacks = 0 CM.visible_message("[CM] has successfully extinguished themselves!","You extinguish yourself.") ExtinguishMob() return CM.resist_restraints() //unsticking from a rooting trap, such as a sticky web or a blood nail if (istype(L.locked_to, /obj/effect/rooting_trap/)) var/obj/effect/rooting_trap/RT = L.locked_to RT.unstick_attempt(L) /mob/living/carbon/proc/resist_restraints() if(!canmove) return var/is_hulk = isalienadult(src) || (M_HULK in mutations) var/obj/item/cuffs var/resist_time = 2 MINUTES var/var_to_check // TOOD: Improve this once Lummox releases pointers? var/do_after_callback if(handcuffed) cuffs = handcuffed resist_time = cuffs.restraint_resist_time var_to_check = "handcuffed" else if(legcuffed) cuffs = legcuffed var/obj/item/weapon/legcuffs/legcuffs = cuffs resist_time = legcuffs.breakouttime var_to_check = "legcuffed" else if(mutual_handcuffs) cuffs = mutual_handcuffs resist_time = cuffs.restraint_resist_time/2 //it's only one cuff var_to_check = "mutual_handcuffs" else if(is_wearing_item(/obj/item/clothing/suit/strait_jacket, slot_wear_suit)) cuffs = get_item_by_slot(slot_wear_suit) if(!is_hulk) do_after_callback = new /callback(GLOBAL_PROC, /proc/strait_jacket_resist_do_after) var/left_arm = get_organ(LIMB_LEFT_ARM) var/right_arm = get_organ(LIMB_RIGHT_ARM) for(var/datum/organ/external/arm in list(left_arm, right_arm)) if(!arm.is_existing() || arm.is_broken()) resist_time = max(0, resist_time - 30 SECONDS) var_to_check = "wear_suit" else return if(is_hulk) resist_time = 5 SECONDS visible_message("[src] attempts to [is_hulk ? "break" : "remove"] \the [cuffs]!", "You attempt to [is_hulk ? "break" : "remove"] \the [cuffs] (this will take around [resist_time / 10] seconds and you need to stand still).", self_drugged_message="You attempt to regain control of your hands (this will take a while).") spawn(0) if(do_after(src, src, resist_time, custom_checks = do_after_callback)) if(vars[var_to_check] != cuffs || locked_to) return drop_from_inventory(cuffs) if(is_hulk) visible_message("[src] manages to break \the [cuffs]!", "You successfully break \the [cuffs].") if(!isalien(src)) say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) qdel(cuffs) else visible_message("[src] manages to remove \the [cuffs]!", "You successfully remove \the [cuffs].", self_drugged_message="You successfully regain control of your hands.") else simple_message("Your attempt at [is_hulk ? "breaking" : "removing"] \the [cuffs] was interrupted.", "Your attempt to regain control of your hands was interrupted. Damn it!") /proc/strait_jacket_resist_do_after(mob/living/carbon/user) var/left_arm = user.get_organ(LIMB_LEFT_ARM) var/right_arm = user.get_organ(LIMB_RIGHT_ARM) for(var/datum/organ/external/arm in list(left_arm, right_arm)) if(!arm) // Not a humanoid or something continue if(!arm.is_existing() || arm.is_broken() || !arm.is_organic()) continue if(prob(5)) arm.fracture() return FALSE return TRUE /mob/living/verb/lay_down() set name = "Rest" set category = "IC" if(client.move_delayer.blocked()) return rest_action() /mob/living/proc/rest_action() delayNextMove(1) resting = !resting update_canmove() to_chat(src, "You are now [resting ? "resting" : "getting up"]") /mob/living/proc/has_brain() return 1 /mob/living/proc/has_eyes() return 1 /mob/living/singularity_act() if(!(src.flags & INVULNERABLE)) var/gain = 20 investigation_log(I_SINGULO,"has been consumed by a singularity") gib() return(gain) /mob/living/singularity_pull(S, current_size, repel = FALSE) if(!(src.flags & INVULNERABLE)) if(!repel) step_towards(src, S) else step_away(src, S) //shuttle_act is called when a shuttle collides with the mob /mob/living/shuttle_act(datum/shuttle/S) if(!(src.flags & INVULNERABLE)) src.attack_log += "\[[time_stamp()]\] was gibbed by a shuttle ([S.name], [S.type])!" gib() return //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(AM.Adjacent(src)) src.start_pulling(AM) return //same as above /mob/living/pointed(atom/A as mob|obj|turf in tview(src)) if(src.incapacitated()) return 0 if(!..()) return 0 var/turf/T = get_turf(src) T.visible_message("[pointToMessage(src, A)]") return 1 /mob/living/proc/pointToMessage(var/pointer, var/pointed_at) return "\The [pointer] points at \the [pointed_at]." /mob/living/to_bump(atom/movable/AM as mob|obj) spawn(0) INVOKE_EVENT(src, /event/to_bump, "bumper" = src, "bumped" = AM) if (now_pushing || !loc || size <= SIZE_TINY) return now_pushing = 1 if (istype(AM, /obj/structure/bed/roller)) //no pushing rollerbeds that have people on them var/obj/structure/bed/roller/R = AM for(var/mob/living/tmob in range(R, 1)) if(tmob.pulling == R && !(tmob.restrained()) && tmob.stat == 0 && R.density == 1) to_chat(src, "[tmob] is pulling [R], you can't push past.") now_pushing = 0 return if (istype(AM, /mob/living)) //no pushing people pushing rollerbeds that have people on them var/mob/living/tmob = AM for(var/obj/structure/bed/roller/R in range(tmob, 1)) if(tmob.pulling == R && !(tmob.restrained()) && tmob.stat == 0 && R.density == 1) to_chat(src, "[tmob] is pulling [R], you can't push past.") now_pushing = 0 return for(var/mob/living/M in range(tmob, 1)) //no pushing prisoners or people pulling prisoners if(tmob.pinned.len || ((M.pulling == tmob && (tmob.restrained() && !(M.restrained()) && M.stat == 0)) || locate(/obj/item/weapon/grab, tmob.grabbed_by.len))) to_chat(src, "[tmob] is restrained, you can't push past.") now_pushing = 0 return if(tmob.pulling == M && (M.restrained() && !(tmob.restrained()) && tmob.stat == 0)) to_chat(src, "[tmob] is restraining [M], you can't push past.") now_pushing = 0 return //BubbleWrap: people in handcuffs are always switched around as if they were on 'help' intent to prevent a person being pulled from being seperated from their puller var/dense = 0 if(loc.density) dense = 1 for(var/atom/movable/A in loc) if(A == src) continue if(A.density) if(A.flow_flags&ON_BORDER) dense = !A.Cross(src, src.loc) else dense = 1 if(dense) break if((tmob.a_intent == I_HELP || tmob.restrained()) && (a_intent == I_HELP || src.restrained()) && tmob.canmove && canmove && !dense && can_move_mob(tmob, 1, 0)) // mutual brohugs all around! var/turf/oldloc = loc forceMove(tmob.loc) tmob.forceMove(oldloc, glide_size_override = src.glide_size) now_pushing = 0 for(var/mob/living/carbon/slime/slime in view(1,tmob)) if(slime.Victim == tmob) slime.UpdateFeed() return if(!can_move_mob(tmob, 0, 0)) now_pushing = 0 return var/mob/living/carbon/human/H = null if(ishuman(tmob)) H = tmob if(H && ((M_FAT in H.mutations) || (H && H.species && H.species.anatomy_flags & IS_BULKY))) var/mob/living/carbon/human/U = null if(ishuman(src)) U = src if(prob(40) && !(U && ((M_FAT in U.mutations) || (U && U.species && U.species.anatomy_flags & IS_BULKY)))) to_chat(src, "You fail to push [tmob]'s fat ass out of the way.") now_pushing = 0 return for(var/obj/item/weapon/shield/riot/R in tmob.held_items) if(prob(99)) now_pushing = 0 return if(!(tmob.status_flags & CANPUSH)) now_pushing = 0 return tmob.LAssailant = src tmob.assaulted_by(src, TRUE) now_pushing = 0 spawn(0) ..() if (!istype(AM, /atom/movable)) return if (!now_pushing) now_pushing = 1 if (!AM.anchored && AM.can_be_pushed(src)) var/t = get_dir(src, AM) if(AM.flow_flags & ON_BORDER && !t) t = AM.dir if (istype(AM, /obj/structure/window/full)) for(var/obj/structure/window/win in get_step(AM,t)) now_pushing = 0 return AM.set_glide_size(src.glide_size) if (ismob(AM)) var/mob/M = AM INVOKE_EVENT(src, /event/before_move) step(M, t) INVOKE_EVENT(src, /event/after_move) else step(AM, t) now_pushing = 0 return return /mob/living/is_open_container() return 1 /mob/living/proc/scoop_up(mob/M) //M = mob who scoops us up! if(!holder_type) return 0 var/obj/item/weapon/holder/D = new holder_type(loc, src) if(M.put_in_active_hand(D)) to_chat(M, "You scoop up [src].") to_chat(src, "[M] scoops you up.") src.forceMove(D) //Only move the mob into the holder after we're sure he has been picked up! return 1 else qdel(D) return 0 /mob/living/nuke_act() //Called when caught in a nuclear blast return /mob/living/proc/turn_into_statue(forever = 0, force) if(!force) if(mob_property_flags & (MOB_UNDEAD|MOB_CONSTRUCT|MOB_ROBOTIC|MOB_HOLOGRAPHIC|MOB_SUPERNATURAL)) return 0 spawn() //we try to turn into marble mannequins, but if we're not compatible we'll use the old statue type if(forever) if (!turn_into_mannequin("marble",TRUE)) new /obj/structure/closet/statue/eternal(get_turf(src), src) else if (!turn_into_mannequin("marble")) new /obj/structure/closet/statue(get_turf(src), src) timestopped = 1 return 1 /* How this proc that I took from /tg/ works: intensity determines the damage done to humans with eyes visual determines whether the proc damages eyes (in the living/carbon/human proc). 1 for no damage override_blindness_check = 1 means that it'll display a flash even if the mob is blind affect_silicon = 0 means that the flash won't affect silicons at all. */ /mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/abstract/screen/fullscreen/flash) if(override_blindness_check || !(disabilities & BLIND)) // flick("e_flash", flash) overlay_fullscreen("flash", type) return 1 /mob/living/proc/advanced_mutate() color = list(rand(),rand(),rand(),0, rand(),rand(),rand(),0, rand(),rand(),rand(),0, 0,0,0,1, 0,0,0,0) if(prob(5)) eye_blind = rand(0,100) if(prob(10)) eye_blurry = rand(0,100) if(prob(5)) ear_deaf = rand(0,100) if(prob(5)) say_mute = rand(0,100) brute_damage_modifier += rand(-5,5)/10 burn_damage_modifier += rand(-5,5)/10 tox_damage_modifier += rand(-5,5)/10 oxy_damage_modifier += rand(-5,5)/10 clone_damage_modifier += rand(-5,5)/10 brain_damage_modifier += rand(-5,5)/10 hal_damage_modifier += rand(-5,5)/10 movement_speed_modifier += rand(-9,9)/10 if(prob(1)) universal_speak = !universal_speak if(prob(1)) universal_understand = !universal_understand maxHealth = rand(50,200) meat_type = pick(typesof(/obj/item/weapon/reagent_containers/food/snacks/meat)) if(prob(5)) cap_calorie_burning_bodytemp = !cap_calorie_burning_bodytemp if(prob(10)) calorie_burning_heat_multiplier += rand(-5,5)/10 if(prob(10)) thermal_loss_multiplier += rand(-5,5)/10 //Throwing stuff /mob/living/proc/toggle_throw_mode() if (in_throw_mode) throw_mode_off() else throw_mode_on() /mob/living/proc/throw_mode_off() in_throw_mode = 0 if(throw_icon) throw_icon.icon_state = "act_throw_off" /mob/living/proc/throw_mode_on() if(gcDestroyed) return if(!held_items.len) //need hands to throw to_chat(src, "You have no hands with which to throw.") return in_throw_mode = 1 if(throw_icon) throw_icon.icon_state = "act_throw_on" /mob/proc/throw_item(var/atom/target,var/atom/movable/what=null) return #define FAILED_THROW 0 #define THREW_SOMETHING 1 #define THREW_NOTHING -1 /mob/living/throw_item(var/atom/target,var/atom/movable/what=null) if (src.throw_delayer.blocked()) return FAILED_THROW src.delayNextThrow(3) src.throw_mode_off() if(src.stat || !target) return FAILED_THROW if(!istype(loc,/turf)) to_chat(src, "You can't do that now!") return FAILED_THROW if(runescape_pvp && is_pacified()) to_chat(src, "As such, throwing items is also forbidden outside of maintenance areas.") return FAILED_THROW if(target.type == /obj/abstract/screen) return FAILED_THROW var/atom/movable/item = src.get_active_hand() if(what) item=what if(!item) return THREW_NOTHING if (istype(item, /obj/item/offhand)) var/obj/item/offhand/offhand = item if(offhand.wielding) src.throw_item(target, offhand.wielding) return FAILED_THROW else if (istype(item, /obj/item/weapon/grab)) var/obj/item/weapon/grab/G = item item = G.toss() //throw the person instead of the grab if(ismob(item)) var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors var/turf/end_T = get_turf(target) if(start_T && end_T) var/mob/M = item var/start_T_descriptor = "tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]" var/end_T_descriptor = "tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]" M.attack_log += text("\[[time_stamp()]\] Has been thrown by [usr.name] ([usr.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") usr.attack_log += text("\[[time_stamp()]\] Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") log_attack("[usr.name] ([usr.ckey]) Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") if(!iscarbon(usr)) M.LAssailant = null else M.LAssailant = usr M.assaulted_by(usr) qdel(G) if(!item) return FAILED_THROW //Grab processing has a chance of returning null if(isitem(item)) var/obj/item/I = item if(I.cant_drop > 0) to_chat(usr, "It's stuck to your hand!") return FAILED_THROW if(I.pre_throw(target)) return FAILED_THROW remove_from_mob(item) //actually throw it! if (item) item.forceMove(get_turf(src)) if(!(item.flags & NO_THROW_MSG)) src.visible_message("[src] has thrown [item].", \ drugged_message = "[item] escapes from [src]'s grasp and flies away!") src.apply_inertia(get_dir(target, src)) /* if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction src.inertia_dir = get_dir(target, src) step(src, inertia_dir) */ var/throw_mult=1 if(istype(src,/mob/living/carbon/human)) var/mob/living/carbon/human/H=src throw_mult = H.species.throw_mult throw_mult += (H.get_strength()-1)/2 //For each level of strength above 1, add 0.5 item.throw_at(target, item.throw_range*throw_mult, item.throw_speed*throw_mult) return THREW_SOMETHING /mob/living/send_to_past(var/duration) ..() var/static/list/resettable_vars = list( "maxHealth", "health", "bruteloss", "oxyloss", "toxloss", "fireloss", "cloneloss", "brainloss", "halloss", "hallucination", "meat_taken", "on_fire", "fire_stacks", "specialsauce", "silent", "is_ventcrawling") reset_vars_after_duration(resettable_vars, duration) /mob/living/proc/handle_dizziness() //Dizziness if(dizziness || undergoing_hypothermia() == MODERATE_HYPOTHERMIA) var/wasdizzy = 1 if(undergoing_hypothermia() == MODERATE_HYPOTHERMIA && !dizziness && prob(50)) dizziness = 120 wasdizzy = 0 var/client/C = client var/pixel_x_diff = 0 var/pixel_y_diff = 0 var/temp var/saved_dizz = dizziness dizziness = max(dizziness - 1, 0) if(C) var/oldsrc = src var/amplitude = dizziness * (sin(dizziness * 0.044 * world.time) + 1) / 70 //This shit is annoying at high strength src = null spawn(0) if(C) temp = amplitude * sin(0.008 * saved_dizz * world.time) pixel_x_diff += temp C.pixel_x += temp * PIXEL_MULTIPLIER temp = amplitude * cos(0.008 * saved_dizz * world.time) pixel_y_diff += temp C.pixel_y += temp * PIXEL_MULTIPLIER sleep(3) if(C) temp = amplitude * sin(0.008 * saved_dizz * world.time) pixel_x_diff += temp C.pixel_x += temp * PIXEL_MULTIPLIER temp = amplitude * cos(0.008 * saved_dizz * world.time) pixel_y_diff += temp C.pixel_y += temp * PIXEL_MULTIPLIER sleep(3) if(C) C.pixel_x -= pixel_x_diff * PIXEL_MULTIPLIER C.pixel_y -= pixel_y_diff * PIXEL_MULTIPLIER src = oldsrc if(!wasdizzy) dizziness = 0 /mob/living/proc/handle_jitteriness() if(jitteriness) var/amplitude = min(8, (jitteriness/70) + 1) var/pixel_x_diff = rand(-amplitude, amplitude) * PIXEL_MULTIPLIER var/pixel_y_diff = rand(-amplitude, amplitude) * PIXEL_MULTIPLIER spawn() animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 1, loop = -1) animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, time = 1, loop = -1, easing = BOUNCE_EASING) pixel_x_diff = rand(-amplitude, amplitude) * PIXEL_MULTIPLIER pixel_y_diff = rand(-amplitude, amplitude) * PIXEL_MULTIPLIER animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 1, loop = -1) animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, time = 1, loop = -1, easing = BOUNCE_EASING) pixel_x_diff = rand(-amplitude, amplitude) * PIXEL_MULTIPLIER pixel_y_diff = rand(-amplitude, amplitude) * PIXEL_MULTIPLIER animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 1, loop = -1) animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, time = 1, loop = -1, easing = BOUNCE_EASING) /mob/living/proc/Silent(amount) silent = max(max(silent,amount),0) /mob/living/proc/SetSilent(amount) silent = max(amount,0) /mob/living/on_syringe_injection(var/mob/user, var/obj/item/weapon/reagent_containers/syringe/tool) if(src == user) return ..() // Attempting to inject someone else takes time if(tool.get_injection_action(src) == INJECTION_SUIT_PORT) user.visible_message("[user] begins hunting for an injection port for \the [tool] on [src]'s suit!", "You begin hunting for an injection port for \the [tool] on [src]'s suit!") else user.visible_message("[user] is trying to inject [src] with \the [tool]!", "You try to inject [src] with \the [tool]!") if(!do_mob(user, src, tool.get_injection_time(src))) return INJECTION_RESULT_FAIL user.visible_message("[user] injects [src] with the \the [tool]!", "You inject [src] with \the [tool]!") var/reagent_names = english_list(tool.get_reagent_names()) add_attacklogs(user, src, "injected", object = tool, addition = "Reagents: [reagent_names]", admin_warn = TRUE) // TODO Every reagent reacts with the full volume instead of being scaled accordingly // TODO which is pretty irrelevant now but should be fixed tool.reagents.reaction(src, INGEST) return ..() /mob/living/proc/ApplySlip(var/obj/effect/overlay/puddle/P) return on_foot() // Check if we have legs, gravity, etc. Checked by the children. /mob/living/proc/Slip(stun_amount, weaken_amount, slip_on_walking = 0, overlay_type, slip_with_magbooties = 0) stop_pulling() Stun(stun_amount) Knockdown(weaken_amount) score.slips++ return 1 ///////////////////////DISEASE STUFF/////////////////////////////////////////////////////////////////// //Blocked is whether clothing prevented the spread of contact/blood /mob/living/proc/assume_contact_diseases(var/list/disease_list,var/atom/source,var/blocked=0,var/bleeding=0) if (istype(disease_list) && disease_list.len > 0) for(var/ID in disease_list) var/datum/disease2/disease/V = disease_list[ID] if (!V) message_admins("[key_name(src)] is trying to assume contact diseases from touching \a [source], but the disease_list contains an ID ([ID]) that isn't associated to an actual disease datum! Ping Deity about it please.") return if(!blocked && V.spread & SPREAD_CONTACT) infect_disease2(V, notes="(Contact, from [source])") else if(suitable_colony() && V.spread & SPREAD_COLONY) infect_disease2(V, notes="(Colonized, from [source])") else if(!blocked && bleeding && (V.spread & SPREAD_BLOOD)) infect_disease2(V, notes="(Blood, from [source])") //Called in Life() by humans (in handle_virus_updates.dm), monkeys and mice /mob/living/proc/find_nearby_disease()//only tries to find Contact and Blood spread diseases. Airborne ones are handled by breath_airborne_diseases() if(locked_to)//Riding a vehicle? return if(flying)//Flying? return var/turf/T = get_turf(src) //Virus Dishes aren't toys, handle with care, especially when they're open. for(var/obj/effect/decal/cleanable/virusdish/dish in T) dish.infection_attempt(src) for(var/obj/item/weapon/virusdish/dish in T) if (dish.open && dish.contained_virus) dish.infection_attempt(src,dish.contained_virus) var/obj/item/weapon/virusdish/dish = locate() in held_items if (dish && dish.open && dish.contained_virus) dish.infection_attempt(src,dish.contained_virus) //Now to check for stuff that's on the floor var/block = 0 var/bleeding = 0 if (lying) block = check_contact_sterility(FULL_TORSO) bleeding = check_bodypart_bleeding(FULL_TORSO) else block = check_contact_sterility(FEET) bleeding = check_bodypart_bleeding(FEET) var/static/list/viral_cleanable_types = list( /obj/effect/decal/cleanable/blood, /obj/effect/decal/cleanable/mucus, /obj/effect/decal/cleanable/vomit, ) for(var/obj/effect/decal/cleanable/C in T) if (is_type_in_list(C,viral_cleanable_types)) assume_contact_diseases(C.virus2,C,block,bleeding) for(var/obj/effect/rune/R in T) assume_contact_diseases(R.virus2,R,block,bleeding) return 0 //This one is used for one-way infections, such as getting splashed with someone's blood due to clobbering them to death /mob/living/proc/oneway_contact_diseases(var/mob/living/L,var/block=0,var/bleeding=0) assume_contact_diseases(L.virus2,L,block,bleeding) //This one is used for two-ways infections, such as hand-shakes, hugs, punches, people bumping into each others, etc /mob/living/proc/share_contact_diseases(var/mob/living/L,var/block=0,var/bleeding=0) L.assume_contact_diseases(virus2,src,block,bleeding) assume_contact_diseases(L.virus2,L,block,bleeding) //Called in Life() by humans (in handle_breath.dm), monkeys and mice /mob/living/proc/breath_airborne_diseases()//only tries to find Airborne spread diseases. Blood and Contact ones are handled by find_nearby_disease() if (!check_airborne_sterility() && isturf(loc))//checking for sterile mouth protections breath_airborne_diseases_from_clouds() var/turf/T = get_turf(src) var/list/breathable_cleanable_types = list( /obj/effect/decal/cleanable/blood, /obj/effect/decal/cleanable/mucus, /obj/effect/decal/cleanable/vomit, ) for(var/obj/effect/decal/cleanable/C in T) if (is_type_in_list(C,breathable_cleanable_types)) if(istype(C.virus2,/list) && C.virus2.len > 0) for(var/ID in C.virus2) var/datum/disease2/disease/V = C.virus2[ID] if(V.spread & SPREAD_AIRBORNE) infect_disease2(V, notes="(Airborne, from [C])") for(var/obj/effect/rune/R in T) if(istype(R.virus2,/list) && R.virus2.len > 0) for(var/ID in R.virus2) var/datum/disease2/disease/V = R.virus2[ID] if(V.spread & SPREAD_AIRBORNE) infect_disease2(V, notes="(Airborne, from [R])") spawn (1) //we don't want the rest of the mobs to start breathing clouds before they've settled down //otherwise it can produce exponential amounts of lag if many mobs are in an enclosed space spread_airborne_diseases() /mob/living/proc/breath_airborne_diseases_from_clouds() for(var/turf/T in range(1, src)) for(var/obj/effect/pathogen_cloud/cloud in T.contents) if (!cloud.sourceIsCarrier || cloud.source != src || cloud.modified) if (Adjacent(cloud)) for (var/ID in cloud.viruses) var/datum/disease2/disease/V = cloud.viruses[ID] //if (V.spread & SPREAD_AIRBORNE) //Anima Syndrome allows for clouds of non-airborne viruses infect_disease2(V, notes="(Airborne, from a pathogenic cloud[cloud.source ? " created by [key_name(cloud.source)]" : ""])") /mob/living/proc/spread_airborne_diseases() //spreading our own airborne viruses if (virus2 && virus2.len > 0) var/list/airborne_viruses = filter_disease_by_spread(virus2,required = SPREAD_AIRBORNE) if (airborne_viruses && airborne_viruses.len > 0) var/strength = 0 for (var/ID in airborne_viruses) var/datum/disease2/disease/V = airborne_viruses[ID] strength += V.infectionchance strength = round(strength/airborne_viruses.len) while (strength > 0)//stronger viruses create more clouds at once new /obj/effect/pathogen_cloud/core(get_turf(src), src, virus_copylist(airborne_viruses)) strength -= 40 /mob/living/proc/handle_virus_updates() if(status_flags & GODMODE) return 0 src.find_nearby_disease()//getting diseases from blood/mucus/vomit splatters and open dishes activate_diseases() /mob/living/proc/activate_diseases() if (virus2.len) var/active_disease = pick(virus2)//only one disease will activate its effects at a time. for (var/ID in virus2) var/datum/disease2/disease/V = virus2[ID] if(istype(V)) V.activate(src,active_disease!=ID) if (prob(radiation))//radiation turns your body into an inefficient pathogenic incubator. V.incubate(src,rad_tick/10) //effect mutations won't occur unless the mob also has ingested mutagen //and even if they occur, the new effect will have a badness similar to the old one, so helpful pathogen won't instantly become deadly ones. /mob/living/blob_act(destroy = 0,var/obj/effect/blob/source = null) if(flags & INVULNERABLE) return if(!isDead(src) && source) if (!(source.looks in blob_diseases)) CreateBlobDisease(source.looks) var/datum/disease2/disease/D = blob_diseases[source.looks] if (!check_contact_sterility(FULL_TORSO))//For simplicity's sake (for once), let's just assume that the blob strikes the torso. infect_disease2(D, notes="(Blob, from [source])") ..() /mob/living/proc/handle_symptom_on_death() if(islist(virus2) && virus2.len > 0) for(var/I in virus2) var/datum/disease2/disease/D = virus2[I] if(D.effects.len) for(var/datum/disease2/effect/E in D.effects) E.on_death(src) //Brain slug proc for voluntary removal of control. /mob/living/proc/release_control() set category = "Alien" set name = "Release Control" set desc = "Release control of your host's body." do_release_control(0) /mob/living/proc/do_release_control(var/rptext=1) var/mob/living/simple_animal/borer/B = has_brain_worms() if(!B) return if(B.controlling) if(rptext) to_chat(src, "You withdraw your probosci, releasing control of [B.host_brain]") to_chat(B.host_brain, "Your vision swims as the alien parasite releases control of your body.") B.ckey = ckey B.controlling = 0 if(B.host_brain.ckey) ckey = B.host_brain.ckey B.host_brain.ckey = null B.host_brain.name = "host brain" B.host_brain.real_name = "host brain" //reset name if the borer changed it fully_replace_character_name(null, B.host_name) verbs -= /mob/living/proc/release_control verbs -= /mob/living/proc/punish_host //Brain slug proc for tormenting the host. /mob/living/proc/punish_host() set category = "Alien" set name = "Torment host" set desc = "Punish your host with agony." var/mob/living/simple_animal/borer/B = has_brain_worms() if(!B) return if(B.host_brain.ckey) to_chat(src, "You send a punishing spike of psychic agony lancing into your host's brain.") to_chat(B.host_brain, "Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")