diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1a852f8da12..3408492e8a9 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -9,8 +9,8 @@ var/last_bumped = 0 var/pass_flags = 0 var/throwpass = 0 - var/germ_level = 0 // The higher the germ level, the more germ on the atom. var/datum/crafting_holder/craft_holder = null + var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom. ///Chemistry. var/datum/reagents/reagents = null diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 88c6f072629..920b3455796 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1,570 +1,580 @@ -/mob/living/carbon/Login() - ..() - update_hud() - return - - -/mob/living/carbon/Move(NewLoc, direct) - . = ..() - if(.) - if(src.nutrition && src.stat != 2) - src.nutrition -= HUNGER_FACTOR/10 - if(src.m_intent == "run") - src.nutrition -= HUNGER_FACTOR/10 - if((M_FAT in src.mutations) && src.m_intent == "run" && src.bodytemperature <= 360) - src.bodytemperature += 2 - -/mob/living/carbon/relaymove(var/mob/user, direction) - if(user in src.stomach_contents) - if(prob(40)) - for(var/mob/M in hearers(4, src)) - if(M.client) - M.show_message(text("\red You hear something rumbling inside [src]'s stomach..."), 2) - var/obj/item/I = user.get_active_hand() - if(I && I.force) - var/d = rand(round(I.force / 4), I.force) - if(istype(src, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - var/organ = H.get_organ("chest") - if (istype(organ, /datum/organ/external)) - var/datum/organ/external/temp = organ - if(temp.take_damage(d, 0)) - H.UpdateDamageIcon() - H.updatehealth() - else - src.take_organ_damage(d) - for(var/mob/M in viewers(user, null)) - if(M.client) - M.show_message(text("\red [user] attacks [src]'s stomach wall with the [I.name]!"), 2) - playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1) - - if(prob(src.getBruteLoss() - 50)) - for(var/atom/movable/A in stomach_contents) - A.loc = loc - stomach_contents.Remove(A) - src.gib() - -/mob/living/carbon/gib() - for(var/mob/M in src) - if(M in src.stomach_contents) - src.stomach_contents.Remove(M) - M.loc = src.loc - for(var/mob/N in viewers(src, null)) - if(N.client) - N.show_message(text("\red [M] bursts out of [src]!"), 2) - . = ..() - -/mob/living/carbon/proc/share_contact_diseases(var/mob/M) - for(var/datum/disease/D in viruses) - if(D.spread_by_touch()) - M.contract_disease(D, 0, 1, CONTACT_HANDS) - for(var/datum/disease/D in M.viruses) - if(D.spread_by_touch()) - contract_disease(D, 0, 1, CONTACT_HANDS) - -/mob/living/carbon/attack_hand(mob/M as mob) - if(!istype(M, /mob/living/carbon)) return - if (hasorgans(M)) - var/datum/organ/external/temp = M:organs_by_name["r_hand"] - if (M.hand) - temp = M:organs_by_name["l_hand"] - if(temp && !temp.is_usable()) - M << "\red You can't use your [temp.display_name]" - return - share_contact_diseases(M) - return - - -/mob/living/carbon/attack_paw(mob/M as mob) - if(!istype(M, /mob/living/carbon)) return - share_contact_diseases(M) - return - -/mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0) - if(status_flags & GODMODE) return 0 //godmode - shock_damage *= siemens_coeff - if (shock_damage<1) - return 0 - src.take_overall_damage(0,shock_damage,used_weapon="Electrocution") - //src.burn_skin(shock_damage) - //src.adjustFireLoss(shock_damage) //burn_skin will do this for us - //src.updatehealth() - src.visible_message( - "\red [src] was shocked by the [source]!", \ - "\red You feel a powerful shock course through your body!", \ - "\red You hear a heavy electrical crack." \ - ) -// if(src.stunned < shock_damage) src.stunned = shock_damage - Stun(10)//This should work for now, more is really silly and makes you lay there forever -// if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff - Weaken(10) - return shock_damage - - -/mob/living/carbon/proc/swap_hand() - var/obj/item/item_in_hand = src.get_active_hand() - if(item_in_hand) //this segment checks if the item in your hand is twohanded. - if(istype(item_in_hand,/obj/item/weapon/twohanded)) - if(item_in_hand:wielded == 1) - usr << "Your other hand is too busy holding the [item_in_hand.name]" - return - src.hand = !( src.hand ) - if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object) - if(hand) //This being 1 means the left hand is in use - hud_used.l_hand_hud_object.icon_state = "hand_active" - hud_used.r_hand_hud_object.icon_state = "hand_inactive" - else - hud_used.l_hand_hud_object.icon_state = "hand_inactive" - hud_used.r_hand_hud_object.icon_state = "hand_active" - /*if (!( src.hand )) - src.hands.dir = NORTH - else - src.hands.dir = SOUTH*/ - return - -/mob/living/carbon/proc/activate_hand(var/selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand. - - if(istext(selhand)) - selhand = lowertext(selhand) - - if(selhand == "right" || selhand == "r") - selhand = 0 - if(selhand == "left" || selhand == "l") - selhand = 1 - - if(selhand != src.hand) - swap_hand() - -/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) - if (src.health >= config.health_threshold_crit) - if(src == M && istype(src, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - src.visible_message( \ - text("\blue [src] examines [].",src.gender==MALE?"himself":"herself"), \ - "\blue You check yourself for injuries." \ - ) - - for(var/datum/organ/external/org in H.organs) - var/status = "" - var/brutedamage = org.brute_dam - var/burndamage = org.burn_dam - if(halloss > 0) - if(prob(30)) - brutedamage += halloss - if(prob(30)) - burndamage += halloss - - if(brutedamage > 0) - status = "bruised" - if(brutedamage > 20) - status = "bleeding" - if(brutedamage > 40) - status = "mangled" - if(brutedamage > 0 && burndamage > 0) - status += " and " - if(burndamage > 40) - status += "peeling away" - - else if(burndamage > 10) - status += "blistered" - else if(burndamage > 0) - status += "numb" - if(org.status & ORGAN_DESTROYED) - status = "MISSING!" - if(org.status & ORGAN_MUTATED) - status = "weirdly shapen." - if(status == "") - status = "OK" - src.show_message(text("\t []My [] is [].",status=="OK"?"\blue ":"\red ",org.display_name,status),1) - if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit)) - H.play_xylophone() - else if(lying) // /vg/: For hugs. This is how update_icon figgers it out, anyway. - N3X15 - var/t_him = "it" - if (src.gender == MALE) - t_him = "him" - else if (src.gender == FEMALE) - t_him = "her" - if (istype(src,/mob/living/carbon/human) && src:w_uniform) - var/mob/living/carbon/human/H = src - H.w_uniform.add_fingerprint(M) - src.sleeping = max(0,src.sleeping-5) - if(src.sleeping == 0) - src.resting = 0 - AdjustParalysis(-3) - AdjustStunned(-3) - AdjustWeakened(-3) - playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - M.visible_message( \ - "\blue [M] shakes [src] trying to wake [t_him] up!", \ - "\blue You shake [src] trying to wake [t_him] up!", \ - ) - // BEGIN HUGCODE - N3X - else - if (istype(src,/mob/living/carbon/human) && src:w_uniform) - var/mob/living/carbon/human/H = src - H.w_uniform.add_fingerprint(M) - playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - M.visible_message( \ - "\blue [M] gives [src] a [pick("hug","warm embrace")].", \ - "\blue You hug [src].", \ - ) - if(prob(10)) - src.emote("fart") - reagents.add_reagent("paracetamol", 1) - share_contact_diseases(M) - - -/mob/living/carbon/proc/eyecheck() - return 0 - -// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching. -// Stop! ... Hammertime! ~Carn - -/mob/living/carbon/proc/getDNA() - return dna - -/mob/living/carbon/proc/setDNA(var/datum/dna/newDNA) - dna = newDNA - -// ++++ROCKDTBEN++++ MOB PROCS //END - - - -/mob/living/carbon/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null) // -- TLE -- Merged by Carn - if(stat) - src << "You must be conscious to do this!" - return - if(lying) - src << "You can't vent crawl while you're stunned!" - return - - if(vent_found) // one was passed in, probably from vent/AltClick() - if(vent_found.welded) - src << "That vent is welded shut." - return - if(!vent_found.Adjacent(src)) - return // don't even acknowledge that - else - for(var/obj/machinery/atmospherics/unary/vent_pump/v in range(1,src)) - if(!v.welded) - if(v.Adjacent(src)) - vent_found = v - if(!vent_found) - src << "You'll need a non-welded vent to crawl into!" - return - if(!vent_found.network || !vent_found.network.normal_members.len) - src << "This vent is not connected to anything." - return - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in vent_found.network.normal_members) - if(temp_vent.welded) - continue - if(temp_vent in loc) - continue - var/turf/T = get_turf(temp_vent) - - if(!T || T.z != loc.z) - continue - - var/i = 1 - var/index = "[T.loc.name]\[[i]\]" - while(index in vents) - i++ - index = "[T.loc.name]\[[i]\]" - vents[index] = temp_vent - if(!vents.len) - src << "\red There are no available vents to travel to, they could be welded." - return - - var/obj/selection = input("Select a destination.", "Duct System") as null|anything in sortAssoc(vents) - if(!selection) return - - if(!vent_found.Adjacent(src)) - src << "Never mind, you left." - return - - for(var/obj/item/carried_item in contents)//If the monkey got on objects. - if( !istype(carried_item, /obj/item/weapon/implant) && !istype(carried_item, /obj/item/clothing/mask/facehugger) )//If it's not an implant or a facehugger - src << "\red You can't be carrying items or have items equipped when vent crawling!" - return - if(isslime(src)) - var/mob/living/carbon/slime/S = src - if(S.Victim) - src << "\red You'll have to let [S.Victim] go or finish eating \him first." - return - - var/obj/machinery/atmospherics/unary/vent_pump/target_vent = vents[selection] - if(!target_vent) - return - - for(var/mob/O in viewers(src, null)) - O.show_message(text("[src] scrambles into the ventillation ducts!"), 1) - loc = target_vent - - var/travel_time = round(get_dist(loc, target_vent.loc) / 2) - - spawn(travel_time) - - if(!target_vent) return - for(var/mob/O in hearers(target_vent,null)) - O.show_message("You hear something squeezing through the ventilation ducts.",2) - - sleep(travel_time) - - if(!target_vent) return - if(target_vent.welded) //the vent can be welded while alien scrolled through the list or travelled. - target_vent = vent_found //travel back. No additional time required. - src << "\red The vent you were heading to appears to be welded." - loc = target_vent.loc - var/area/new_area = get_area(loc) - if(new_area) - new_area.Entered(src) - - - -/mob/living/carbon/clean_blood() - . = ..() - if(ishuman(src)) - var/mob/living/carbon/human/H = src - if(H.gloves) - if(H.gloves.clean_blood()) - H.update_inv_gloves(0,0) - H.gloves.germ_level = 0 - else - if(H.bloody_hands) - H.bloody_hands = 0 - H.update_inv_gloves(0,0) - H.germ_level = 0 - update_icons() //apply the now updated overlays to the mob - - -//Throwing stuff - -/mob/living/carbon/proc/toggle_throw_mode() - if (in_throw_mode) - throw_mode_off() - else - throw_mode_on() - -/mob/living/carbon/proc/throw_mode_off() - src.in_throw_mode = 0 - if(src.throw_icon) //in case we don't have the HUD and we use the hotkey - src.throw_icon.icon_state = "act_throw_off" - -/mob/living/carbon/proc/throw_mode_on() - src.in_throw_mode = 1 - if(src.throw_icon) - src.throw_icon.icon_state = "act_throw_on" - -/mob/proc/throw_item(atom/target) - return - -/mob/living/carbon/throw_item(atom/target) - throw_mode_off() - if(usr.stat || !target) - return - if(target.type == /obj/screen) return - - var/atom/movable/item = src.get_active_hand() - - if(!item) return - - if (istype(item, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = item - item = G.throw() //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]") - msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (JMP)") - - if(!iscarbon(usr)) - M.LAssailant = null - else - M.LAssailant = usr - - if(!item) return //Grab processing has a chance of returning null - - item.layer = initial(item.layer) - u_equip(item) - update_icons() - - if (istype(usr, /mob/living/carbon)) //Check if a carbon mob is throwing. Modify/remove this line as required. - item.loc = usr.loc - if(src.client) - src.client.screen -= item - if(istype(item, /obj/item)) - item:dropped(src) // let it know it's been dropped - - //actually throw it! - if (item) - src.visible_message("\red [src] has thrown [item].") - - if(!src.lastarea) - src.lastarea = get_area(src.loc) - if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0)) - src.inertia_dir = get_dir(target, src) - step(src, inertia_dir) - - -/* - 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) -*/ - - - item.throw_at(target, item.throw_range, item.throw_speed) - -/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - ..() - bodytemperature = max(bodytemperature, BODYTEMP_HEAT_DAMAGE_LIMIT+10) - -/mob/living/carbon/can_use_hands() - if(handcuffed) - return 0 - if(buckled && ! istype(buckled, /obj/structure/stool/bed/chair)) // buckling does not restrict hands - return 0 - return 1 - -/mob/living/carbon/restrained() - if (handcuffed) - return 1 - return - -/mob/living/carbon/u_equip(obj/item/W as obj) - if(!W) return 0 - - else if (W == handcuffed) - handcuffed = null - update_inv_handcuffed() - - else if (W == legcuffed) - legcuffed = null - update_inv_legcuffed() - else - ..() - - return - -/mob/living/carbon/show_inv(mob/living/carbon/user as mob) - user.set_machine(src) - var/dat = {" -
[name]
-

-
Head(Mask): [(wear_mask ? wear_mask : "Nothing")] -
Left Hand: [(l_hand ? l_hand : "Nothing")] -
Right Hand: [(r_hand ? r_hand : "Nothing")] -
Back: [(back ? back : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] -
[(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))] -
[(internal ? text("Remove Internal") : "")] -
Empty Pockets -
Refresh -
Close -
"} - user << browse(dat, text("window=mob\ref[src];size=325x500")) - onclose(user, "mob\ref[src]") - return - -//generates realistic-ish pulse output based on preset levels -/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate - var/temp = 0 //see setup.dm:694 - switch(src.pulse) - if(PULSE_NONE) - return "0" - if(PULSE_SLOW) - temp = rand(40, 60) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_NORM) - temp = rand(60, 90) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_FAST) - temp = rand(90, 120) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_2FAST) - temp = rand(120, 160) - return num2text(method ? temp : temp + rand(-10, 10)) - if(PULSE_THREADY) - return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread" -// output for machines^ ^^^^^^^output for people^^^^^^^^^ - - -//Brain slug proc for voluntary removal of control. -/mob/living/carbon/proc/release_control() - - set category = "Alien" - set name = "Release Control" - set desc = "Release control of your host's body." - - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(!B) - return - - if(B.controlling) - src << "\red You withdraw your probosci, releasing control of [B.host_brain]" - B.host_brain << "\red 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" - - verbs -= /mob/living/carbon/proc/release_control - verbs -= /mob/living/carbon/proc/punish_host - verbs -= /mob/living/carbon/proc/spawn_larvae - -//Brain slug proc for tormenting the host. -/mob/living/carbon/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) - src << "\red You send a punishing spike of psychic agony lancing into your host's brain." - B.host_brain << "\red Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!" - -//Check for brain worms in head. -/mob/proc/has_brain_worms() - - for(var/I in contents) - if(istype(I,/mob/living/simple_animal/borer)) - return I - - return 0 - -/mob/living/carbon/proc/spawn_larvae() - set category = "Alien" - set name = "Reproduce" - set desc = "Spawn several young." - - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(!B) - return - - if(B.chemicals >= 100) - src << "\red Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body." - visible_message("\red [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") - B.chemicals -= 100 - - new /obj/effect/decal/cleanable/vomit(get_turf(src)) - playsound(loc, 'sound/effects/splat.ogg', 50, 1) - new /mob/living/simple_animal/borer(get_turf(src)) - - else - src << "You do not have enough chemicals stored to reproduce." - return +/mob/living/carbon/Login() + ..() + update_hud() + return + +/mob/living/carbon/Life() + ..() + + // Increase germ_level regularly + if(germ_level < GERM_LEVEL_AMBIENT) //if you're just standing there, you shouldn't get more germs beyond an ambient level + germ_level++ //increase by 1 per second + +/mob/living/carbon/Move(NewLoc, direct) + . = ..() + if(.) + if(src.nutrition && src.stat != 2) + src.nutrition -= HUNGER_FACTOR/10 + if(src.m_intent == "run") + src.nutrition -= HUNGER_FACTOR/10 + if((M_FAT in src.mutations) && src.m_intent == "run" && src.bodytemperature <= 360) + src.bodytemperature += 2 + + // Moving around increases germ_level faster + if(germ_level < GERM_LEVEL_MOVE_CAP && prob(1)) + germ_level++ + +/mob/living/carbon/relaymove(var/mob/user, direction) + if(user in src.stomach_contents) + if(prob(40)) + for(var/mob/M in hearers(4, src)) + if(M.client) + M.show_message(text("\red You hear something rumbling inside [src]'s stomach..."), 2) + var/obj/item/I = user.get_active_hand() + if(I && I.force) + var/d = rand(round(I.force / 4), I.force) + if(istype(src, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + var/organ = H.get_organ("chest") + if (istype(organ, /datum/organ/external)) + var/datum/organ/external/temp = organ + if(temp.take_damage(d, 0)) + H.UpdateDamageIcon() + H.updatehealth() + else + src.take_organ_damage(d) + for(var/mob/M in viewers(user, null)) + if(M.client) + M.show_message(text("\red [user] attacks [src]'s stomach wall with the [I.name]!"), 2) + playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1) + + if(prob(src.getBruteLoss() - 50)) + for(var/atom/movable/A in stomach_contents) + A.loc = loc + stomach_contents.Remove(A) + src.gib() + +/mob/living/carbon/gib() + for(var/mob/M in src) + if(M in src.stomach_contents) + src.stomach_contents.Remove(M) + M.loc = src.loc + for(var/mob/N in viewers(src, null)) + if(N.client) + N.show_message(text("\red [M] bursts out of [src]!"), 2) + . = ..() + +/mob/living/carbon/proc/share_contact_diseases(var/mob/M) + for(var/datum/disease/D in viruses) + if(D.spread_by_touch()) + M.contract_disease(D, 0, 1, CONTACT_HANDS) + for(var/datum/disease/D in M.viruses) + if(D.spread_by_touch()) + contract_disease(D, 0, 1, CONTACT_HANDS) + +/mob/living/carbon/attack_hand(mob/M as mob) + if(!istype(M, /mob/living/carbon)) return + if (hasorgans(M)) + var/datum/organ/external/temp = M:organs_by_name["r_hand"] + if (M.hand) + temp = M:organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + M << "\red You can't use your [temp.display_name]" + return + share_contact_diseases(M) + return + + +/mob/living/carbon/attack_paw(mob/M as mob) + if(!istype(M, /mob/living/carbon)) return + share_contact_diseases(M) + return + +/mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0) + if(status_flags & GODMODE) return 0 //godmode + shock_damage *= siemens_coeff + if (shock_damage<1) + return 0 + src.take_overall_damage(0,shock_damage,used_weapon="Electrocution") + //src.burn_skin(shock_damage) + //src.adjustFireLoss(shock_damage) //burn_skin will do this for us + //src.updatehealth() + src.visible_message( + "\red [src] was shocked by the [source]!", \ + "\red You feel a powerful shock course through your body!", \ + "\red You hear a heavy electrical crack." \ + ) +// if(src.stunned < shock_damage) src.stunned = shock_damage + Stun(10)//This should work for now, more is really silly and makes you lay there forever +// if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff + Weaken(10) + return shock_damage + + +/mob/living/carbon/proc/swap_hand() + var/obj/item/item_in_hand = src.get_active_hand() + if(item_in_hand) //this segment checks if the item in your hand is twohanded. + if(istype(item_in_hand,/obj/item/weapon/twohanded)) + if(item_in_hand:wielded == 1) + usr << "Your other hand is too busy holding the [item_in_hand.name]" + return + src.hand = !( src.hand ) + if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object) + if(hand) //This being 1 means the left hand is in use + hud_used.l_hand_hud_object.icon_state = "hand_active" + hud_used.r_hand_hud_object.icon_state = "hand_inactive" + else + hud_used.l_hand_hud_object.icon_state = "hand_inactive" + hud_used.r_hand_hud_object.icon_state = "hand_active" + /*if (!( src.hand )) + src.hands.dir = NORTH + else + src.hands.dir = SOUTH*/ + return + +/mob/living/carbon/proc/activate_hand(var/selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand. + + if(istext(selhand)) + selhand = lowertext(selhand) + + if(selhand == "right" || selhand == "r") + selhand = 0 + if(selhand == "left" || selhand == "l") + selhand = 1 + + if(selhand != src.hand) + swap_hand() + +/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) + if (src.health >= config.health_threshold_crit) + if(src == M && istype(src, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + src.visible_message( \ + text("\blue [src] examines [].",src.gender==MALE?"himself":"herself"), \ + "\blue You check yourself for injuries." \ + ) + + for(var/datum/organ/external/org in H.organs) + var/status = "" + var/brutedamage = org.brute_dam + var/burndamage = org.burn_dam + if(halloss > 0) + if(prob(30)) + brutedamage += halloss + if(prob(30)) + burndamage += halloss + + if(brutedamage > 0) + status = "bruised" + if(brutedamage > 20) + status = "bleeding" + if(brutedamage > 40) + status = "mangled" + if(brutedamage > 0 && burndamage > 0) + status += " and " + if(burndamage > 40) + status += "peeling away" + + else if(burndamage > 10) + status += "blistered" + else if(burndamage > 0) + status += "numb" + if(org.status & ORGAN_DESTROYED) + status = "MISSING!" + if(org.status & ORGAN_MUTATED) + status = "weirdly shapen." + if(status == "") + status = "OK" + src.show_message(text("\t []My [] is [].",status=="OK"?"\blue ":"\red ",org.display_name,status),1) + if((SKELETON in H.mutations) && (!H.w_uniform) && (!H.wear_suit)) + H.play_xylophone() + else if(lying) // /vg/: For hugs. This is how update_icon figgers it out, anyway. - N3X15 + var/t_him = "it" + if (src.gender == MALE) + t_him = "him" + else if (src.gender == FEMALE) + t_him = "her" + if (istype(src,/mob/living/carbon/human) && src:w_uniform) + var/mob/living/carbon/human/H = src + H.w_uniform.add_fingerprint(M) + src.sleeping = max(0,src.sleeping-5) + if(src.sleeping == 0) + src.resting = 0 + AdjustParalysis(-3) + AdjustStunned(-3) + AdjustWeakened(-3) + playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + M.visible_message( \ + "\blue [M] shakes [src] trying to wake [t_him] up!", \ + "\blue You shake [src] trying to wake [t_him] up!", \ + ) + // BEGIN HUGCODE - N3X + else + if (istype(src,/mob/living/carbon/human) && src:w_uniform) + var/mob/living/carbon/human/H = src + H.w_uniform.add_fingerprint(M) + playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + M.visible_message( \ + "\blue [M] gives [src] a [pick("hug","warm embrace")].", \ + "\blue You hug [src].", \ + ) + if(prob(10)) + src.emote("fart") + reagents.add_reagent("paracetamol", 1) + share_contact_diseases(M) + + +/mob/living/carbon/proc/eyecheck() + return 0 + +// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching. +// Stop! ... Hammertime! ~Carn + +/mob/living/carbon/proc/getDNA() + return dna + +/mob/living/carbon/proc/setDNA(var/datum/dna/newDNA) + dna = newDNA + +// ++++ROCKDTBEN++++ MOB PROCS //END + + + +/mob/living/carbon/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null) // -- TLE -- Merged by Carn + if(stat) + src << "You must be conscious to do this!" + return + if(lying) + src << "You can't vent crawl while you're stunned!" + return + + if(vent_found) // one was passed in, probably from vent/AltClick() + if(vent_found.welded) + src << "That vent is welded shut." + return + if(!vent_found.Adjacent(src)) + return // don't even acknowledge that + else + for(var/obj/machinery/atmospherics/unary/vent_pump/v in range(1,src)) + if(!v.welded) + if(v.Adjacent(src)) + vent_found = v + if(!vent_found) + src << "You'll need a non-welded vent to crawl into!" + return + if(!vent_found.network || !vent_found.network.normal_members.len) + src << "This vent is not connected to anything." + return + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in vent_found.network.normal_members) + if(temp_vent.welded) + continue + if(temp_vent in loc) + continue + var/turf/T = get_turf(temp_vent) + + if(!T || T.z != loc.z) + continue + + var/i = 1 + var/index = "[T.loc.name]\[[i]\]" + while(index in vents) + i++ + index = "[T.loc.name]\[[i]\]" + vents[index] = temp_vent + if(!vents.len) + src << "\red There are no available vents to travel to, they could be welded." + return + + var/obj/selection = input("Select a destination.", "Duct System") as null|anything in sortAssoc(vents) + if(!selection) return + + if(!vent_found.Adjacent(src)) + src << "Never mind, you left." + return + + for(var/obj/item/carried_item in contents)//If the monkey got on objects. + if( !istype(carried_item, /obj/item/weapon/implant) && !istype(carried_item, /obj/item/clothing/mask/facehugger) )//If it's not an implant or a facehugger + src << "\red You can't be carrying items or have items equipped when vent crawling!" + return + if(isslime(src)) + var/mob/living/carbon/slime/S = src + if(S.Victim) + src << "\red You'll have to let [S.Victim] go or finish eating \him first." + return + + var/obj/machinery/atmospherics/unary/vent_pump/target_vent = vents[selection] + if(!target_vent) + return + + for(var/mob/O in viewers(src, null)) + O.show_message(text("[src] scrambles into the ventillation ducts!"), 1) + loc = target_vent + + var/travel_time = round(get_dist(loc, target_vent.loc) / 2) + + spawn(travel_time) + + if(!target_vent) return + for(var/mob/O in hearers(target_vent,null)) + O.show_message("You hear something squeezing through the ventilation ducts.",2) + + sleep(travel_time) + + if(!target_vent) return + if(target_vent.welded) //the vent can be welded while alien scrolled through the list or travelled. + target_vent = vent_found //travel back. No additional time required. + src << "\red The vent you were heading to appears to be welded." + loc = target_vent.loc + var/area/new_area = get_area(loc) + if(new_area) + new_area.Entered(src) + + + +/mob/living/carbon/clean_blood() + . = ..() + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(H.gloves) + if(H.gloves.clean_blood()) + H.update_inv_gloves(0,0) + H.gloves.germ_level = 0 + else + if(H.bloody_hands) + H.bloody_hands = 0 + H.update_inv_gloves(0,0) + H.germ_level = 0 + update_icons() //apply the now updated overlays to the mob + + +//Throwing stuff + +/mob/living/carbon/proc/toggle_throw_mode() + if (in_throw_mode) + throw_mode_off() + else + throw_mode_on() + +/mob/living/carbon/proc/throw_mode_off() + src.in_throw_mode = 0 + if(src.throw_icon) //in case we don't have the HUD and we use the hotkey + src.throw_icon.icon_state = "act_throw_off" + +/mob/living/carbon/proc/throw_mode_on() + src.in_throw_mode = 1 + if(src.throw_icon) + src.throw_icon.icon_state = "act_throw_on" + +/mob/proc/throw_item(atom/target) + return + +/mob/living/carbon/throw_item(atom/target) + throw_mode_off() + if(usr.stat || !target) + return + if(target.type == /obj/screen) return + + var/atom/movable/item = src.get_active_hand() + + if(!item) return + + if (istype(item, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = item + item = G.throw() //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]") + msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (JMP)") + + if(!iscarbon(usr)) + M.LAssailant = null + else + M.LAssailant = usr + + if(!item) return //Grab processing has a chance of returning null + + item.layer = initial(item.layer) + u_equip(item) + update_icons() + + if (istype(usr, /mob/living/carbon)) //Check if a carbon mob is throwing. Modify/remove this line as required. + item.loc = usr.loc + if(src.client) + src.client.screen -= item + if(istype(item, /obj/item)) + item:dropped(src) // let it know it's been dropped + + //actually throw it! + if (item) + src.visible_message("\red [src] has thrown [item].") + + if(!src.lastarea) + src.lastarea = get_area(src.loc) + if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0)) + src.inertia_dir = get_dir(target, src) + step(src, inertia_dir) + + +/* + 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) +*/ + + + item.throw_at(target, item.throw_range, item.throw_speed) + +/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + ..() + bodytemperature = max(bodytemperature, BODYTEMP_HEAT_DAMAGE_LIMIT+10) + +/mob/living/carbon/can_use_hands() + if(handcuffed) + return 0 + if(buckled && ! istype(buckled, /obj/structure/stool/bed/chair)) // buckling does not restrict hands + return 0 + return 1 + +/mob/living/carbon/restrained() + if (handcuffed) + return 1 + return + +/mob/living/carbon/u_equip(obj/item/W as obj) + if(!W) return 0 + + else if (W == handcuffed) + handcuffed = null + update_inv_handcuffed() + + else if (W == legcuffed) + legcuffed = null + update_inv_legcuffed() + else + ..() + + return + +/mob/living/carbon/show_inv(mob/living/carbon/user as mob) + user.set_machine(src) + var/dat = {" +
[name]
+

+
Head(Mask): [(wear_mask ? wear_mask : "Nothing")] +
Left Hand: [(l_hand ? l_hand : "Nothing")] +
Right Hand: [(r_hand ? r_hand : "Nothing")] +
Back: [(back ? back : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] +
[(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))] +
[(internal ? text("Remove Internal") : "")] +
Empty Pockets +
Refresh +
Close +
"} + user << browse(dat, text("window=mob\ref[src];size=325x500")) + onclose(user, "mob\ref[src]") + return + +//generates realistic-ish pulse output based on preset levels +/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate + var/temp = 0 //see setup.dm:694 + switch(src.pulse) + if(PULSE_NONE) + return "0" + if(PULSE_SLOW) + temp = rand(40, 60) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_NORM) + temp = rand(60, 90) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_FAST) + temp = rand(90, 120) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_2FAST) + temp = rand(120, 160) + return num2text(method ? temp : temp + rand(-10, 10)) + if(PULSE_THREADY) + return method ? ">250" : "extremely weak and fast, patient's artery feels like a thread" +// output for machines^ ^^^^^^^output for people^^^^^^^^^ + + +//Brain slug proc for voluntary removal of control. +/mob/living/carbon/proc/release_control() + + set category = "Alien" + set name = "Release Control" + set desc = "Release control of your host's body." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.controlling) + src << "\red You withdraw your probosci, releasing control of [B.host_brain]" + B.host_brain << "\red 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" + + verbs -= /mob/living/carbon/proc/release_control + verbs -= /mob/living/carbon/proc/punish_host + verbs -= /mob/living/carbon/proc/spawn_larvae + +//Brain slug proc for tormenting the host. +/mob/living/carbon/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) + src << "\red You send a punishing spike of psychic agony lancing into your host's brain." + B.host_brain << "\red Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!" + +//Check for brain worms in head. +/mob/proc/has_brain_worms() + + for(var/I in contents) + if(istype(I,/mob/living/simple_animal/borer)) + return I + + return 0 + +/mob/living/carbon/proc/spawn_larvae() + set category = "Alien" + set name = "Reproduce" + set desc = "Spawn several young." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.chemicals >= 100) + src << "\red Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body." + visible_message("\red [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") + B.chemicals -= 100 + + new /obj/effect/decal/cleanable/vomit(get_turf(src)) + playsound(loc, 'sound/effects/splat.ogg', 50, 1) + new /mob/living/simple_animal/borer(get_turf(src)) + + else + src << "You do not have enough chemicals stored to reproduce." + return diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index f682c708015..ac9b99cec6c 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -287,8 +287,8 @@ var/this_wound_desc = W.desc if(W.bleeding()) this_wound_desc = "bleeding [this_wound_desc]" else if(W.bandaged) this_wound_desc = "bandaged [this_wound_desc]" - if(W.germ_level > 1000) this_wound_desc = "badly infected [this_wound_desc]" - else if(W.germ_level > 100) this_wound_desc = "lightly infected [this_wound_desc]" + if(W.germ_level > GANGREN_LEVEL_TWO) this_wound_desc = "badly infected [this_wound_desc]" + else if(W.germ_level > 330) this_wound_desc = "lightly infected [this_wound_desc]" if(this_wound_desc in wound_descriptors) wound_descriptors[this_wound_desc] += W.amount continue diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 9c68a5baa50..b445466d1de 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1361,14 +1361,11 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc if(druggy) druggy = max(druggy-1, 0) -/* - // Increase germ_level regularly - if(prob(40)) - germ_level += 1 + // If you're dirty, your gloves will become dirty, too. if(gloves && germ_level > gloves.germ_level && prob(10)) gloves.germ_level += 1 -*/ + return 1 proc/handle_regular_hud_updates() diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 9f74d34ba84..146ec7be165 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -72,12 +72,18 @@ if(E.status & ORGAN_BROKEN && !(E.status & ORGAN_SPLINTED) ) broken = 1 + if (!lying && world.time - l_move_time < 15) //Moving around with fractured ribs won't do you any good - if (broken && E.internal_organs && prob(15)) - if (!lying && world.time - l_move_time < 15) + if (broken && E.internal_organs && prob(15)) var/datum/organ/internal/I = pick(E.internal_organs) custom_pain("You feel broken bones moving in your [E.display_name]!", 1) I.take_damage(rand(3,5)) + + //Moving makes open wounds get infected much faster + if (E.wounds.len) + for(var/datum/wound/W in E.wounds) + if (W.can_infect()) + W.germ_level += 1 //Special effects for limbs. if(E.name in list("l_hand","l_arm","r_hand","r_arm") && (broken||malfunction)) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 250be806cc9..570e3551099 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -300,7 +300,10 @@ This function completely restores a damaged organ to perfect condition. if(last_dam != brute_dam + burn_dam) // Process when we are fully healed up. last_dam = brute_dam + burn_dam return 1 - last_dam = brute_dam + burn_dam + else + last_dam = brute_dam + burn_dam + if(germ_level > GANGREN_LEVEL_ONE) + return 1 return 0 /datum/organ/external/process() @@ -336,31 +339,34 @@ This function completely restores a damaged organ to perfect condition. return //Updating germ levels. Handles organ germ levels and necrosis. -#define GANGREN_LEVEL_ONE 100 -#define GANGREN_LEVEL_TWO 1000 -#define GANGREN_LEVEL_TERMINAL 2500 -#define GERM_TRANSFER_AMOUNT germ_level/500 +//#define GERM_TRANSFER_AMOUNT germ_level/500 /datum/organ/external/proc/update_germs() - if(status & ORGAN_ROBOT|ORGAN_DESTROYED) //Robotic limbs shouldn't be infected, nor should nonexistant limbs. + if(status & (ORGAN_ROBOT|ORGAN_DESTROYED)) //Robotic limbs shouldn't be infected, nor should nonexistant limbs. germ_level = 0 return - if(germ_level > 0 && owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs + if(owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs //Syncing germ levels with external wounds for(var/datum/wound/W in wounds) - if(!W.bandaged && !W.salved) - W.germ_level = max(W.germ_level, germ_level) //Wounds get all the germs - if (W.germ_level > germ_level) //Badly infected wounds raise internal germ levels - germ_level++ - - if(germ_level > GANGREN_LEVEL_ONE && prob(round(germ_level/100))) - germ_level++ - owner.adjustToxLoss(1) + //Open wounds can become infected + if (owner.germ_level > W.germ_level && W.can_infect()) + W.germ_level++ + + //Infected wounds raise the organ's germ level + W.germ_level = max(W.germ_level, germ_level) //Wounds get all the germs + if (W.germ_level > germ_level) //Badly infected wounds raise internal germ levels + germ_level++ if(germ_level > GANGREN_LEVEL_TWO) germ_level++ owner.adjustToxLoss(1) + + else if(germ_level > GANGREN_LEVEL_ONE && prob(round(germ_level/10))) //aiming for a light infection to become serious after 40 minutes, standing still + germ_level += 1 + owner.adjustToxLoss(1) + + /* if(germ_level > GANGREN_LEVEL_TERMINAL) if (!(status & ORGAN_DEAD)) diff --git a/code/setup.dm b/code/setup.dm index 871306e0284..cb10e879be3 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -861,4 +861,12 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse //Shuttle moving status #define SHUTTLE_IDLE 0 #define SHUTTLE_WARMUP 1 -#define SHUTTLE_INTRANSIT 2 +#define SHUTTLE_INTRANSIT 2 + +//Germs and infection +//These numbers have been calculated so that an untreated cut will become a serious infection after 50 minutes. +#define GERM_LEVEL_AMBIENT 120 //maximum germ level you can reach by standing still +#define GERM_LEVEL_MOVE_CAP 300 //maximum germ level you can reach by running around +#define GANGREN_LEVEL_ONE 50 +#define GANGREN_LEVEL_TWO 1000 +#define GANGREN_LEVEL_TERMINAL 2500