mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-26 01:52:29 +00:00
Merge branch 'dev' of https://github.com/Baystation12/Baystation12 into 11/6/2015_neerti_breaks_everything_bay_merge
Conflicts: .travis.yml code/_helpers/lists.dm code/game/objects/structures/crates_lockers/closets/secure/engineering.dm code/global.dm code/modules/client/preferences.dm code/modules/client/preferences_savefile.dm code/modules/reagents/dispenser/dispenser2.dm polaris.dme
This commit is contained in:
@@ -91,11 +91,14 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
|
||||
|
||||
/mob/dead/observer/Topic(href, href_list)
|
||||
if (href_list["track"])
|
||||
var/mob/target = locate(href_list["track"]) in mob_list
|
||||
if(target)
|
||||
ManualFollow(target)
|
||||
|
||||
|
||||
if(istype(href_list["track"],/mob))
|
||||
var/mob/target = locate(href_list["track"]) in mob_list
|
||||
if(target)
|
||||
ManualFollow(target)
|
||||
else
|
||||
var/atom/target = locate(href_list["track"])
|
||||
if(istype(target))
|
||||
ManualFollow(target)
|
||||
|
||||
/mob/dead/attackby(obj/item/W, mob/user)
|
||||
if(istype(W,/obj/item/weapon/book/tome))
|
||||
@@ -149,7 +152,7 @@ Works together with spawning an observer, noted above.
|
||||
if(key)
|
||||
var/mob/dead/observer/ghost = new(src) //Transfer safety to observer spawning proc.
|
||||
ghost.can_reenter_corpse = can_reenter_corpse
|
||||
ghost.timeofdeath = src.timeofdeath //BS12 EDIT
|
||||
ghost.timeofdeath = src.stat == DEAD ? src.timeofdeath : world.time
|
||||
ghost.key = key
|
||||
if(ghost.client && !ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
|
||||
ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
|
||||
@@ -320,7 +323,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(following && following == target)
|
||||
return
|
||||
following = target
|
||||
src << "<span class='notice'>Now following [target]</span>"
|
||||
src << "<span class='notice'>Now following \the [target]</span>"
|
||||
if(ismob(target))
|
||||
forceMove(get_turf(target))
|
||||
var/mob/M = target
|
||||
|
||||
@@ -212,4 +212,10 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/proc/transfer_languages(var/mob/source, var/mob/target, var/except_flags)
|
||||
for(var/datum/language/L in source.languages)
|
||||
if(L.flags & except_flags)
|
||||
continue
|
||||
target.add_language(L.name)
|
||||
|
||||
#undef SCRAMBLE_CACHE_LEN
|
||||
|
||||
@@ -123,5 +123,3 @@
|
||||
/mob/living/bot/proc/explode()
|
||||
qdel(src)
|
||||
|
||||
/mob/living/bot/attack_throat()
|
||||
return
|
||||
|
||||
@@ -11,4 +11,5 @@
|
||||
/mob/living/carbon/alien/larva/New()
|
||||
..()
|
||||
add_language("Xenomorph") //Bonus language.
|
||||
internal_organs |= new /obj/item/organ/xenos/hivenode(src)
|
||||
internal_organs |= new /obj/item/organ/xenos/hivenode(src)
|
||||
create_reagents(100)
|
||||
@@ -1,12 +1,34 @@
|
||||
#define MIN_LARVA_BLOOD_DRINK 0.5
|
||||
|
||||
//Larvae regenerate health and nutrition from plasma and alien weeds.
|
||||
/mob/living/carbon/alien/larva/handle_environment(var/datum/gas_mixture/environment)
|
||||
|
||||
if(!environment) return
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(environment.gas["phoron"] > 0 || (T && locate(/obj/effect/alien/weeds) in T.contents))
|
||||
var/obj/effect/plant/plant = locate() in T
|
||||
if(environment.gas["phoron"] > 0 || (plant && plant.seed.type == /datum/seed/xenomorph))
|
||||
update_progression()
|
||||
adjustBruteLoss(-1)
|
||||
adjustFireLoss(-1)
|
||||
adjustToxLoss(-1)
|
||||
adjustOxyLoss(-1)
|
||||
adjustOxyLoss(-1)
|
||||
|
||||
// Maybe not the -best- place but it's semiappropriate and fitting.
|
||||
// Drink the blood of your host!
|
||||
/mob/living/carbon/alien/larva/handle_chemicals_in_body()
|
||||
if(!loc)
|
||||
return
|
||||
if(!istype(loc, /obj/item/weapon/holder))
|
||||
return
|
||||
var/mob/living/carbon/human/M = loc.loc //ergh, replace with a flag sometime
|
||||
if(!istype(M))
|
||||
return
|
||||
if(M.vessel.total_volume > 0)
|
||||
M.vessel.trans_to(src,min(M.vessel.total_volume,MIN_LARVA_BLOOD_DRINK))
|
||||
update_progression()
|
||||
else
|
||||
src << "<span class='danger'>This host is depleted of blood...</span>"
|
||||
leave_host()
|
||||
|
||||
#undef MIN_LARVA_BLOOD_DRINK
|
||||
|
||||
111
code/modules/mob/living/carbon/alien/larva/powers.dm
Normal file
111
code/modules/mob/living/carbon/alien/larva/powers.dm
Normal file
@@ -0,0 +1,111 @@
|
||||
/mob/living/carbon/alien/larva/proc/check_can_infest(var/mob/living/M)
|
||||
if(!src)
|
||||
return 0
|
||||
if(!istype(loc, /turf))
|
||||
src << "<span class='danger'>You cannot infest a target in your current position.</span>"
|
||||
return 0
|
||||
if(incapacitated())
|
||||
src << "<span class='danger'>You cannot infest a target in your current state.</span>"
|
||||
return 0
|
||||
if(!M)
|
||||
return 1
|
||||
if(!M.lying)
|
||||
src << "<span class='danger'>\The [M] is not prone.</span>"
|
||||
return 0
|
||||
if(!(src.Adjacent(M)))
|
||||
src << "<span class='danger'>\The [M] is not in range.</span>"
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/alien/larva/verb/attach_host()
|
||||
|
||||
set name = "Attach to host"
|
||||
set desc = "Burrow into a prone victim and begin drinking their blood."
|
||||
set category = "Abilities"
|
||||
|
||||
if(!check_can_infest())
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/carbon/human/H in view(1,src))
|
||||
if(isxenomorph(H))
|
||||
continue
|
||||
if(src.Adjacent(H) && H.lying)
|
||||
choices += H
|
||||
|
||||
if(!choices.len)
|
||||
src << "<span class='danger'>There are no viable hosts within range.</span>"
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = input(src,"Who do you wish to infest?") as null|anything in choices
|
||||
|
||||
if(!H || !src || !H.lying) return
|
||||
|
||||
visible_message("<span class='danger'>\The [src] begins questing blindly towards \the [H]'s warm flesh...</span>")
|
||||
|
||||
if(!do_after(src,30))
|
||||
return
|
||||
|
||||
if(!check_can_infest(H))
|
||||
return
|
||||
|
||||
var/obj/item/organ/external/E = pick(H.organs)
|
||||
src << "<span class='danger'>You burrow deeply into \the [H]'s [E.name]!</span>"
|
||||
var/obj/item/weapon/holder/holder = new (loc)
|
||||
src.loc = holder
|
||||
holder.name = src.name
|
||||
E.embed(holder,0,"\The [src] burrows deeply into \the [H]'s [E.name]!")
|
||||
|
||||
/mob/living/carbon/alien/larva/verb/release_host()
|
||||
set category = "Abilities"
|
||||
set name = "Release Host"
|
||||
set desc = "Release your host."
|
||||
|
||||
if(incapacitated())
|
||||
src << "You cannot leave your host in your current state."
|
||||
return
|
||||
|
||||
if(!loc || !loc.loc)
|
||||
src << "You are not inside a host."
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = loc.loc
|
||||
|
||||
if(!istype(H))
|
||||
src << "You are not inside a host."
|
||||
return
|
||||
|
||||
src << "<span class='danger'>You begin writhing your way free of \the [H]'s flesh...</span>"
|
||||
|
||||
if(!do_after(src, 30))
|
||||
return
|
||||
|
||||
if(!H || !src)
|
||||
return
|
||||
|
||||
leave_host()
|
||||
|
||||
/mob/living/carbon/alien/larva/proc/leave_host()
|
||||
if(!loc || !loc.loc)
|
||||
src << "You are not inside a host."
|
||||
return
|
||||
var/mob/living/carbon/human/H = loc.loc
|
||||
if(!istype(H))
|
||||
src << "You are not inside a host."
|
||||
return
|
||||
var/obj/item/weapon/holder/holder = loc
|
||||
var/obj/item/organ/external/affected
|
||||
if(istype(holder))
|
||||
for(var/obj/item/organ/external/organ in H.organs) //Grab the organ holding the implant.
|
||||
for(var/obj/item/O in organ.implants)
|
||||
if(O == holder)
|
||||
affected = organ
|
||||
break
|
||||
affected.implants -= holder
|
||||
holder.loc = get_turf(holder)
|
||||
else
|
||||
src.loc = get_turf(src)
|
||||
if(affected)
|
||||
src << "<span class='danger'>You crawl out of \the [H]'s [affected.name] and plop to the ground.</span>"
|
||||
else
|
||||
src << "<span class='danger'>You plop to the ground.</span>"
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
..()
|
||||
|
||||
if (stat != DEAD) //still breathing
|
||||
// GROW!
|
||||
if (stat != DEAD && can_progress())
|
||||
update_progression()
|
||||
|
||||
blinded = null
|
||||
@@ -18,6 +17,10 @@
|
||||
//Status updates, death etc.
|
||||
update_icons()
|
||||
|
||||
/mob/living/carbon/alien/proc/can_progress()
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/carbon/alien/handle_mutations_and_radiation()
|
||||
|
||||
// Currently both Dionaea and larvae like to eat radiation, so I'm defining the
|
||||
@@ -158,7 +161,7 @@
|
||||
adjustFireLoss((environment.temperature - (T0C+66))/5) // Might be too high, check in testing.
|
||||
if (fire) fire.icon_state = "fire2"
|
||||
if(prob(20))
|
||||
src << "\red You feel a searing heat!"
|
||||
src << "<span class='danger'>You feel a searing heat!</span>"
|
||||
else
|
||||
if (fire) fire.icon_state = "fire0"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/mob/living/carbon/alien/verb/evolve()
|
||||
|
||||
set name = "Evolve"
|
||||
set desc = "Evolve into your adult form."
|
||||
set name = "Moult"
|
||||
set desc = "Moult your skin and become an adult."
|
||||
set category = "Abilities"
|
||||
|
||||
if(stat != CONSCIOUS)
|
||||
@@ -12,11 +12,11 @@
|
||||
return
|
||||
|
||||
if(handcuffed || legcuffed)
|
||||
src << "\red You cannot evolve when you are cuffed."
|
||||
src << "<span class='warning'>You cannot evolve when you are cuffed.</span>"
|
||||
return
|
||||
|
||||
if(amount_grown < max_grown)
|
||||
src << "\red You are not fully grown."
|
||||
src << "<span class='warning'>You are not fully grown.</span>"
|
||||
return
|
||||
|
||||
// confirm_evolution() handles choices and other specific requirements.
|
||||
@@ -27,6 +27,7 @@
|
||||
var/mob/living/carbon/human/adult = new adult_form(get_turf(src))
|
||||
adult.set_species(new_species)
|
||||
show_evolution_blurb()
|
||||
// TODO: drop a moulted skin. Ew.
|
||||
|
||||
if(mind)
|
||||
mind.transfer_to(adult)
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
breath = environment.remove_volume(volume_needed)
|
||||
handle_chemical_smoke(environment) //handle chemical smoke while we're at it
|
||||
|
||||
if(breath)
|
||||
if(breath && breath.total_moles)
|
||||
//handle mask filtering
|
||||
if(istype(wear_mask, /obj/item/clothing/mask) && breath)
|
||||
var/obj/item/clothing/mask/M = wear_mask
|
||||
@@ -65,13 +65,15 @@
|
||||
|
||||
//Handle possble chem smoke effect
|
||||
/mob/living/carbon/proc/handle_chemical_smoke(var/datum/gas_mixture/environment)
|
||||
if(wear_mask && (wear_mask.item_flags & BLOCK_GAS_SMOKE_EFFECT))
|
||||
if(species && environment.return_pressure() < species.breath_pressure/5)
|
||||
return //pressure is too low to even breathe in.
|
||||
if(wear_mask && (wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT))
|
||||
return
|
||||
|
||||
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
|
||||
if(smoke.reagents.total_volume)
|
||||
smoke.reagents.trans_to_mob(src, 10, CHEM_INGEST, copy = 1)
|
||||
//maybe check air pressure here or something to see if breathing in smoke is even possible.
|
||||
smoke.reagents.trans_to_mob(src, 5, CHEM_INGEST, copy = 1)
|
||||
smoke.reagents.trans_to_mob(src, 5, CHEM_BLOOD, copy = 1)
|
||||
// I dunno, maybe the reagents enter the blood stream through the lungs?
|
||||
break // If they breathe in the nasty stuff once, no need to continue checking
|
||||
|
||||
|
||||
98
code/modules/mob/living/carbon/carbon_defense.dm
Normal file
98
code/modules/mob/living/carbon/carbon_defense.dm
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
//Called when the mob is hit with an item in combat.
|
||||
/mob/living/carbon/resolve_item_attack(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
|
||||
if(check_attack_throat(I, user))
|
||||
return null
|
||||
..()
|
||||
|
||||
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
|
||||
if(!effective_force || blocked >= 2)
|
||||
return 0
|
||||
|
||||
//Hulk modifier
|
||||
if(HULK in user.mutations)
|
||||
effective_force *= 2
|
||||
|
||||
//Apply weapon damage
|
||||
var/weapon_sharp = is_sharp(I)
|
||||
var/weapon_edge = has_edge(I)
|
||||
if(prob(getarmor(hit_zone, "melee"))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
|
||||
weapon_sharp = 0
|
||||
weapon_edge = 0
|
||||
|
||||
apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
|
||||
|
||||
//Melee weapon embedded object code.
|
||||
if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I))
|
||||
var/damage = effective_force
|
||||
if (blocked)
|
||||
damage /= blocked+1
|
||||
|
||||
//blunt objects should really not be embedding in things unless a huge amount of force is involved
|
||||
var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
|
||||
var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
|
||||
|
||||
//Sharp objects will always embed if they do enough damage.
|
||||
if((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance)))
|
||||
src.embed(I, hit_zone)
|
||||
|
||||
return 1
|
||||
|
||||
// Attacking someone with a weapon while they are neck-grabbed
|
||||
/mob/living/carbon/proc/check_attack_throat(obj/item/W, mob/user)
|
||||
if(user.a_intent == I_HURT)
|
||||
for(var/obj/item/weapon/grab/G in src.grabbed_by)
|
||||
if(G.assailant == user && G.state >= GRAB_NECK)
|
||||
if(attack_throat(W, G, user))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
// Knifing
|
||||
/mob/living/carbon/proc/attack_throat(obj/item/W, obj/item/weapon/grab/G, mob/user)
|
||||
|
||||
if(!W.edge || !W.force || W.damtype != BRUTE)
|
||||
return 0 //unsuitable weapon
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] begins to slit [src]'s throat with \the [W]!</span>")
|
||||
|
||||
user.next_move = world.time + 20 //also should prevent user from triggering this repeatedly
|
||||
if(!do_after(user, 20))
|
||||
return 0
|
||||
if(!(G && G.assailant == user && G.affecting == src)) //check that we still have a grab
|
||||
return 0
|
||||
|
||||
var/damage_mod = 1
|
||||
//presumably, if they are wearing a helmet that stops pressure effects, then it probably covers the throat as well
|
||||
var/obj/item/clothing/head/helmet = get_equipped_item(slot_head)
|
||||
if(istype(helmet) && (helmet.body_parts_covered & HEAD) && (helmet.flags & STOPPRESSUREDAMAGE))
|
||||
//we don't do an armor_check here because this is not an impact effect like a weapon swung with momentum, that either penetrates or glances off.
|
||||
damage_mod = 1.0 - (helmet.armor["melee"]/100)
|
||||
|
||||
var/total_damage = 0
|
||||
for(var/i in 1 to 3)
|
||||
var/damage = min(W.force*1.5, 20)*damage_mod
|
||||
apply_damage(damage, W.damtype, "head", 0, sharp=W.sharp, edge=W.edge)
|
||||
total_damage += damage
|
||||
|
||||
var/oxyloss = total_damage
|
||||
if(total_damage >= 40) //threshold to make someone pass out
|
||||
oxyloss = 60 // Brain lacks oxygen immediately, pass out
|
||||
|
||||
adjustOxyLoss(min(oxyloss, 100 - getOxyLoss())) //don't put them over 100 oxyloss
|
||||
|
||||
if(total_damage)
|
||||
if(oxyloss >= 40)
|
||||
user.visible_message("<span class='danger'>\The [user] slit [src]'s throat open with \the [W]!</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>\The [user] cut [src]'s neck with \the [W]!</span>")
|
||||
|
||||
if(W.hitsound)
|
||||
playsound(loc, W.hitsound, 50, 1, -1)
|
||||
|
||||
G.last_action = world.time
|
||||
flick(G.hud.icon_state, G.hud)
|
||||
|
||||
user.attack_log += "\[[time_stamp()]\]<font color='red'> Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
|
||||
src.attack_log += "\[[time_stamp()]\]<font color='orange'> Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
|
||||
msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" )
|
||||
return 1
|
||||
@@ -654,38 +654,17 @@
|
||||
///eyecheck()
|
||||
///Returns a number between -1 to 2
|
||||
/mob/living/carbon/human/eyecheck()
|
||||
var/number = 0
|
||||
|
||||
if(!species.has_organ["eyes"]) //No eyes, can't hurt them.
|
||||
return 2
|
||||
return FLASH_PROTECTION_MAJOR
|
||||
|
||||
if(internal_organs_by_name["eyes"]) // Eyes are fucked, not a 'weak point'.
|
||||
var/obj/item/organ/I = internal_organs_by_name["eyes"]
|
||||
if(I.status & ORGAN_CUT_AWAY)
|
||||
return 2
|
||||
return FLASH_PROTECTION_MAJOR
|
||||
else
|
||||
return 2
|
||||
return
|
||||
|
||||
if(istype(src.head, /obj/item/clothing/head/welding))
|
||||
if(!src.head:up)
|
||||
number += 2
|
||||
if(istype(back, /obj/item/weapon/rig))
|
||||
var/obj/item/weapon/rig/O = back
|
||||
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
|
||||
number += 2
|
||||
if(istype(src.head, /obj/item/clothing/head/helmet/space))
|
||||
number += 2
|
||||
if(istype(src.head, /obj/item/clothing/head/helmet/space/emergency))
|
||||
number -= 2
|
||||
if(istype(src.glasses, /obj/item/clothing/glasses/thermal))
|
||||
number -= 1
|
||||
if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses))
|
||||
number += 1
|
||||
if(istype(src.glasses, /obj/item/clothing/glasses/welding))
|
||||
var/obj/item/clothing/glasses/welding/W = src.glasses
|
||||
if(!W.up)
|
||||
number += 2
|
||||
return number
|
||||
return flash_protection
|
||||
|
||||
//Used by various things that knock people out by applying blunt trauma to the head.
|
||||
//Checks that the species has a "head" (brain containing organ) and that hit_zone refers to it.
|
||||
@@ -972,7 +951,7 @@
|
||||
|
||||
if(L && !L.is_bruised())
|
||||
src.custom_pain("You feel a stabbing pain in your chest!", 1)
|
||||
L.damage = L.min_bruised_damage
|
||||
L.bruise()
|
||||
|
||||
/*
|
||||
/mob/living/carbon/human/verb/simulate()
|
||||
@@ -1282,11 +1261,10 @@
|
||||
if(C.body_parts_covered & FEET)
|
||||
feet_exposed = 0
|
||||
|
||||
flavor_text = flavor_texts["general"]
|
||||
flavor_text += "\n\n"
|
||||
flavor_text = ""
|
||||
for (var/T in flavor_texts)
|
||||
if(flavor_texts[T] && flavor_texts[T] != "")
|
||||
if((T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed))
|
||||
if((T == "general") || (T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed))
|
||||
flavor_text += flavor_texts[T]
|
||||
flavor_text += "\n\n"
|
||||
if(!shrink)
|
||||
|
||||
@@ -296,23 +296,6 @@
|
||||
updatehealth()
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/proc/attack_joint(var/obj/item/W, var/mob/living/user, var/def_zone)
|
||||
if(!def_zone) def_zone = user.zone_sel.selecting
|
||||
var/target_zone = get_zone_with_miss_chance(check_zone(def_zone), src)
|
||||
|
||||
if(user == src) // Attacking yourself can't miss
|
||||
target_zone = user.zone_sel.selecting
|
||||
if(!target_zone)
|
||||
return null
|
||||
var/obj/item/organ/external/organ = get_organ(check_zone(target_zone))
|
||||
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1))
|
||||
return null
|
||||
var/dislocation_str
|
||||
if(prob(W.force))
|
||||
dislocation_str = "[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!"
|
||||
organ.dislocate(1)
|
||||
return dislocation_str
|
||||
|
||||
//Used to attack a joint through grabbing
|
||||
/mob/living/carbon/human/proc/grab_joint(var/mob/living/user, var/def_zone)
|
||||
var/has_grab = 0
|
||||
|
||||
@@ -16,14 +16,14 @@ emp_act
|
||||
|
||||
var/obj/item/organ/external/organ = get_organ()
|
||||
|
||||
//Shields
|
||||
//Shields
|
||||
var/shield_check = check_shields(P.damage, P, null, def_zone, "the [P.name]")
|
||||
if(shield_check)
|
||||
if(shield_check < 0)
|
||||
return shield_check
|
||||
else
|
||||
P.on_hit(src, 2, def_zone)
|
||||
return 2
|
||||
return 2
|
||||
|
||||
//Shrapnel
|
||||
if(P.can_embed())
|
||||
@@ -145,70 +145,77 @@ emp_act
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
|
||||
//Returns 1 if the attack hit, 0 if it missed.
|
||||
/mob/living/carbon/human/proc/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone)
|
||||
if(!I || !user) return 0
|
||||
|
||||
var/target_zone = def_zone? check_zone(def_zone) : get_zone_with_miss_chance(user.zone_sel.selecting, src)
|
||||
/mob/living/carbon/human/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
|
||||
if(check_attack_throat(I, user))
|
||||
return null
|
||||
|
||||
if(user == src) // Attacking yourself can't miss
|
||||
target_zone = user.zone_sel.selecting
|
||||
if(!target_zone)
|
||||
visible_message("<span class='danger'>[user] misses [src] with \the [I]!</span>")
|
||||
return 1
|
||||
return target_zone
|
||||
|
||||
var/obj/item/organ/external/affecting = get_organ(target_zone)
|
||||
var/hit_zone = get_zone_with_miss_chance(target_zone, src)
|
||||
|
||||
if(!hit_zone)
|
||||
visible_message("<span class='danger'>\The [user] misses [src] with \the [I]!</span>")
|
||||
return null
|
||||
|
||||
if(check_shields(I.force, I, user, target_zone, "the [I.name]"))
|
||||
return null
|
||||
|
||||
var/obj/item/organ/external/affecting = get_organ(hit_zone)
|
||||
if (!affecting || (affecting.status & ORGAN_DESTROYED) || affecting.is_stump())
|
||||
user << "<span class='danger'>They are missing that limb!</span>"
|
||||
return
|
||||
return null
|
||||
|
||||
var/effective_force = I.force
|
||||
if(user.a_intent == "disarm") effective_force = round(I.force/2)
|
||||
var/hit_area = affecting.name
|
||||
return hit_zone
|
||||
|
||||
if((user != src) && check_shields(effective_force, I, user, target_zone, "the [I.name]"))
|
||||
/mob/living/carbon/human/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
|
||||
var/obj/item/organ/external/affecting = get_organ(hit_zone)
|
||||
if(!affecting)
|
||||
return //should be prevented by attacked_with_item() but for sanity.
|
||||
|
||||
visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] in the [affecting.name] with [I.name] by [user]!</span>")
|
||||
|
||||
var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")
|
||||
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
|
||||
|
||||
return blocked
|
||||
|
||||
/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
|
||||
var/obj/item/organ/external/affecting = get_organ(hit_zone)
|
||||
if(!affecting)
|
||||
return 0
|
||||
|
||||
if(istype(I,/obj/item/weapon/card/emag))
|
||||
if(!(affecting.status & ORGAN_ROBOT))
|
||||
user << "\red That limb isn't robotic."
|
||||
return
|
||||
if(affecting.sabotaged)
|
||||
user << "\red [src]'s [affecting.name] is already sabotaged!"
|
||||
else
|
||||
user << "\red You sneakily slide [I] into the dataport on [src]'s [affecting.name] and short out the safeties."
|
||||
var/obj/item/weapon/card/emag/emag = I
|
||||
emag.uses--
|
||||
affecting.sabotaged = 1
|
||||
return 1
|
||||
// Handle striking to cripple.
|
||||
if(user.a_intent == I_DISARM)
|
||||
effective_force /= 2 //half the effective force
|
||||
if(!..(I, effective_force, blocked, hit_zone))
|
||||
return 0
|
||||
|
||||
attack_joint(affecting, I, blocked) //but can dislocate joints
|
||||
else if(!..())
|
||||
return 0
|
||||
|
||||
if(I.attack_verb.len)
|
||||
visible_message("\red <B>[src] has been [pick(I.attack_verb)] in the [hit_area] with [I.name] by [user]!</B>")
|
||||
else
|
||||
visible_message("\red <B>[src] has been attacked in the [hit_area] with [I.name] by [user]!</B>")
|
||||
if(effective_force > 10 || effective_force >= 5 && prob(33))
|
||||
forcesay(hit_appends) //forcesay checks stat already
|
||||
|
||||
var/armor = run_armor_check(affecting, "melee", I.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].")
|
||||
var/weapon_sharp = is_sharp(I)
|
||||
var/weapon_edge = has_edge(I)
|
||||
if ((weapon_sharp || weapon_edge) && prob(getarmor(target_zone, "melee")))
|
||||
weapon_sharp = 0
|
||||
weapon_edge = 0
|
||||
|
||||
if(armor >= 2) return 0
|
||||
if(!effective_force) return 0
|
||||
var/Iforce = effective_force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
|
||||
|
||||
apply_damage(effective_force, I.damtype, affecting, armor, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
|
||||
|
||||
var/bloody = 0
|
||||
if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (effective_force * 2)))
|
||||
I.add_blood(src) //Make the weapon bloody, not the person.
|
||||
// if(user.hand) user.update_inv_l_hand() //updates the attacker's overlay for the (now bloodied) weapon
|
||||
// else user.update_inv_r_hand() //removed because weapons don't have on-mob blood overlays
|
||||
if((I.damtype == BRUTE || I.damtype == HALLOSS) && prob(25 + (effective_force * 2)))
|
||||
if(!stat)
|
||||
if(headcheck(hit_zone))
|
||||
//Harder to score a stun but if you do it lasts a bit longer
|
||||
if(prob(effective_force))
|
||||
visible_message("<span class='danger'>[src] [species.knockout_message]</span>")
|
||||
apply_effect(20, PARALYZE, blocked)
|
||||
else
|
||||
//Easier to score a stun but lasts less time
|
||||
if(prob(effective_force + 10))
|
||||
visible_message("<span class='danger'>[src] has been knocked down!</span>")
|
||||
apply_effect(6, WEAKEN, blocked)
|
||||
|
||||
//Apply blood
|
||||
if(!(I.flags & NOBLOODY))
|
||||
I.add_blood(src)
|
||||
|
||||
if(prob(33))
|
||||
bloody = 1
|
||||
var/turf/location = loc
|
||||
if(istype(location, /turf/simulated))
|
||||
location.add_blood(src)
|
||||
@@ -218,21 +225,7 @@ emp_act
|
||||
H.bloody_body(src)
|
||||
H.bloody_hands(src)
|
||||
|
||||
if(!stat)
|
||||
if(headcheck(hit_area))
|
||||
//Harder to score a stun but if you do it lasts a bit longer
|
||||
if(prob(effective_force))
|
||||
apply_effect(20, PARALYZE, armor)
|
||||
visible_message("<span class='danger'>[src] [species.knockout_message]</span>")
|
||||
else
|
||||
//Easier to score a stun but lasts less time
|
||||
if(prob(effective_force + 10))
|
||||
apply_effect(6, WEAKEN, armor)
|
||||
visible_message("<span class='danger'>[src] has been knocked down!</span>")
|
||||
|
||||
//Apply blood
|
||||
if(bloody)
|
||||
switch(hit_area)
|
||||
switch(hit_zone)
|
||||
if("head")
|
||||
if(wear_mask)
|
||||
wear_mask.add_blood(src)
|
||||
@@ -246,22 +239,27 @@ emp_act
|
||||
if("chest")
|
||||
bloody_body(src)
|
||||
|
||||
if(Iforce > 10 || Iforce >= 5 && prob(33))
|
||||
forcesay(hit_appends) //forcesay checks stat already
|
||||
return 1
|
||||
|
||||
//Melee weapon embedded object code.
|
||||
if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I))
|
||||
var/damage = effective_force
|
||||
if (armor)
|
||||
damage /= armor+1
|
||||
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/blocked)
|
||||
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 2)
|
||||
return 0
|
||||
if(prob(W.force / (blocked+1)))
|
||||
visible_message("<span class='danger'>[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!</span>")
|
||||
organ.dislocate(1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//blunt objects should really not be embedding in things unless a huge amount of force is involved
|
||||
var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
|
||||
var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
|
||||
|
||||
//Sharp objects will always embed if they do enough damage.
|
||||
if((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance)))
|
||||
affecting.embed(I)
|
||||
/mob/living/carbon/human/emag_act(var/remaining_charges, mob/user, var/emag_source)
|
||||
var/obj/item/organ/external/affecting = get_organ(user.zone_sel.selecting)
|
||||
if(!affecting || !(affecting.status & ORGAN_ROBOT))
|
||||
user << "<span class='warning'>That limb isn't robotic.</span>"
|
||||
return -1
|
||||
if(affecting.sabotaged)
|
||||
user << "<span class='warning'>[src]'s [affecting.name] is already sabotaged!</span>"
|
||||
return -1
|
||||
user << "<span class='notice'>You sneakily slide [emag_source] into the dataport on [src]'s [affecting.name] and short out the safeties.</span>"
|
||||
affecting.sabotaged = 1
|
||||
return 1
|
||||
|
||||
//this proc handles being hit by a thrown atom
|
||||
@@ -446,4 +444,3 @@ emp_act
|
||||
perm += perm_by_part[part]
|
||||
|
||||
return perm
|
||||
|
||||
|
||||
@@ -85,3 +85,11 @@
|
||||
mob_bump_flag = HUMAN
|
||||
mob_push_flags = ~HEAVY
|
||||
mob_swap_flags = ~HEAVY
|
||||
|
||||
var/flash_protection = 0 // Total level of flash protection
|
||||
var/equipment_tint_total = 0 // Total level of visualy impairing items
|
||||
var/equipment_darkness_modifier // Darkvision modifier from equipped items
|
||||
var/equipment_vision_flags // Extra vision flags from equipped items
|
||||
var/equipment_see_invis // Max see invibility level granted by equipped items
|
||||
var/equipment_prescription // Eye prescription granted by equipped items
|
||||
var/list/equipment_overlays = list() // Extra overlays from equipped items
|
||||
|
||||
83
code/modules/mob/living/carbon/human/human_helpers.dm
Normal file
83
code/modules/mob/living/carbon/human/human_helpers.dm
Normal file
@@ -0,0 +1,83 @@
|
||||
#define HUMAN_EATING_NO_ISSUE 0
|
||||
#define HUMAN_EATING_NO_MOUTH 1
|
||||
#define HUMAN_EATING_BLOCKED_MOUTH 2
|
||||
|
||||
#define add_clothing_protection(A) \
|
||||
var/obj/item/clothing/C = A; \
|
||||
flash_protection += C.flash_protection; \
|
||||
equipment_tint_total += C.tint;
|
||||
|
||||
/mob/living/carbon/human/can_eat(var/food, var/feedback = 1)
|
||||
var/list/status = can_eat_status()
|
||||
if(status[0] == HUMAN_EATING_NO_ISSUE)
|
||||
return 1
|
||||
if(feedback)
|
||||
if(status[0] == HUMAN_EATING_NO_MOUTH)
|
||||
src << "Where do you intend to put \the [food]? You don't have a mouth!"
|
||||
else if(status[0] == HUMAN_EATING_BLOCKED_MOUTH)
|
||||
src << "<span class='warning'>\The [status[1]] is in the way!</span>"
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/can_force_feed(var/feeder, var/food, var/feedback = 1)
|
||||
var/list/status = can_eat_status()
|
||||
if(status[0] == HUMAN_EATING_NO_ISSUE)
|
||||
return 1
|
||||
if(feedback)
|
||||
if(status[0] == HUMAN_EATING_NO_MOUTH)
|
||||
feeder << "Where do you intend to put \the [food]? \The [src] doesn't have a mouth!"
|
||||
else if(status[0] == HUMAN_EATING_BLOCKED_MOUTH)
|
||||
feeder << "<span class='warning'>\The [status[1]] is in the way!</span>"
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/can_eat_status()
|
||||
if(!check_has_mouth())
|
||||
return list(HUMAN_EATING_NO_MOUTH)
|
||||
var/obj/item/blocked = check_mouth_coverage()
|
||||
if(blocked)
|
||||
return list(HUMAN_EATING_BLOCKED_MOUTH, blocked)
|
||||
return list(HUMAN_EATING_NO_ISSUE)
|
||||
|
||||
#undef HUMAN_EATING_NO_ISSUE
|
||||
#undef HUMAN_EATING_NO_MOUTH
|
||||
#undef HUMAN_EATING_BLOCKED_MOUTH
|
||||
|
||||
/mob/living/carbon/human/proc/update_equipment_vision()
|
||||
flash_protection = 0
|
||||
equipment_tint_total = 0
|
||||
equipment_see_invis = 0
|
||||
equipment_vision_flags = 0
|
||||
equipment_prescription = 0
|
||||
equipment_darkness_modifier = 0
|
||||
equipment_overlays.Cut()
|
||||
|
||||
if(istype(src.head, /obj/item/clothing/head))
|
||||
add_clothing_protection(head)
|
||||
if(istype(src.glasses, /obj/item/clothing/glasses))
|
||||
process_glasses(glasses)
|
||||
if(istype(src.wear_mask, /obj/item/clothing/mask))
|
||||
add_clothing_protection(wear_mask)
|
||||
if(istype(back,/obj/item/weapon/rig))
|
||||
process_rig(back)
|
||||
|
||||
/mob/living/carbon/human/proc/process_glasses(var/obj/item/clothing/glasses/G)
|
||||
if(G && G.active)
|
||||
equipment_darkness_modifier += G.darkness_view
|
||||
equipment_vision_flags |= G.vision_flags
|
||||
equipment_prescription = equipment_prescription || G.prescription
|
||||
if(G.overlay)
|
||||
equipment_overlays |= G.overlay
|
||||
if(G.see_invisible >= 0)
|
||||
if(equipment_see_invis)
|
||||
equipment_see_invis = min(equipment_see_invis, G.see_invisible)
|
||||
else
|
||||
equipment_see_invis = G.see_invisible
|
||||
|
||||
add_clothing_protection(G)
|
||||
G.process_hud(src)
|
||||
|
||||
/mob/living/carbon/human/proc/process_rig(var/obj/item/weapon/rig/O)
|
||||
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
|
||||
if((O.offline && O.offline_vision_restriction == 2) || (!O.offline && O.vision_restriction == 2))
|
||||
equipment_tint_total += TINT_BLIND
|
||||
if(O.visor && O.visor.active && O.visor.vision && O.visor.vision.glasses && (!O.helmet || (head && O.helmet == head)))
|
||||
process_glasses(O.visor.vision.glasses)
|
||||
@@ -224,11 +224,14 @@
|
||||
set name = "Split"
|
||||
set desc = "Split your humanoid form into its constituent nymphs."
|
||||
set category = "Abilities"
|
||||
diona_split_into_nymphs(5) // Separate proc to void argments being supplied when used as a verb
|
||||
|
||||
/mob/living/carbon/human/proc/diona_split_into_nymphs(var/number_of_resulting_nymphs)
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
var/mob/living/carbon/alien/diona/S = new(T)
|
||||
S.set_dir(dir)
|
||||
transfer_languages(src, S)
|
||||
if(mind)
|
||||
mind.transfer_to(S)
|
||||
|
||||
@@ -239,20 +242,18 @@
|
||||
|
||||
for(var/mob/living/carbon/alien/diona/D in src)
|
||||
nymphs++
|
||||
D.loc = T
|
||||
D.forceMove(T)
|
||||
transfer_languages(src, D, WHITELISTED|RESTRICTED)
|
||||
D.set_dir(pick(NORTH, SOUTH, EAST, WEST))
|
||||
|
||||
if(nymphs < 5)
|
||||
for(var/i in nymphs to 4)
|
||||
if(nymphs < number_of_resulting_nymphs)
|
||||
for(var/i in nymphs to (number_of_resulting_nymphs - 1))
|
||||
var/mob/M = new /mob/living/carbon/alien/diona(T)
|
||||
transfer_languages(src, M, WHITELISTED|RESTRICTED)
|
||||
M.set_dir(pick(NORTH, SOUTH, EAST, WEST))
|
||||
|
||||
|
||||
for(var/obj/item/W in src)
|
||||
drop_from_inventory(W)
|
||||
|
||||
visible_message("<span class='warning'>\The [src] quivers slightly, then splits apart with a wet slithering noise.</span>")
|
||||
|
||||
qdel(src)
|
||||
|
||||
|
||||
|
||||
@@ -41,11 +41,6 @@
|
||||
if (transforming)
|
||||
return
|
||||
|
||||
//Apparently, the person who wrote this code designed it so that
|
||||
//blinded get reset each cycle and then get activated later in the
|
||||
//code. Very ugly. I dont care. Moving this stuff here so its easy
|
||||
//to find it.
|
||||
blinded = null
|
||||
fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it.
|
||||
|
||||
//TODO: seperate this out
|
||||
@@ -153,6 +148,26 @@
|
||||
return ONE_ATMOSPHERE + pressure_difference
|
||||
|
||||
/mob/living/carbon/human/handle_disabilities()
|
||||
..()
|
||||
//Vision
|
||||
var/obj/item/organ/vision
|
||||
if(species.vision_organ)
|
||||
vision = internal_organs_by_name[species.vision_organ]
|
||||
|
||||
if(!vision) // Presumably if a species has no vision organs, they see via some other means.
|
||||
eye_blind = 0
|
||||
blinded = 0
|
||||
eye_blurry = 0
|
||||
else if(vision.is_broken()) // Vision organs cut out or broken? Permablind.
|
||||
eye_blind = 1
|
||||
blinded = 1
|
||||
eye_blurry = 1
|
||||
else
|
||||
//blindness
|
||||
if(!(sdisabilities & BLIND))
|
||||
if(equipment_tint_total >= TINT_BLIND) // Covered eyes, heal faster
|
||||
eye_blurry = max(eye_blurry-2, 0)
|
||||
|
||||
if (disabilities & EPILEPSY)
|
||||
if ((prob(1) && paralysis < 1))
|
||||
src << "\red You have a seizure!"
|
||||
@@ -202,7 +217,7 @@
|
||||
emote("drool")
|
||||
*/
|
||||
|
||||
if(stat != 2)
|
||||
if(stat != DEAD)
|
||||
var/rn = rand(0, 200)
|
||||
if(getBrainLoss() >= 5)
|
||||
if(0 <= rn && rn <= 3)
|
||||
@@ -342,11 +357,28 @@
|
||||
internals.icon_state = "internal0"
|
||||
return null
|
||||
|
||||
/mob/living/carbon/human/get_breath_from_environment(var/volume_needed=BREATH_VOLUME)
|
||||
var/datum/gas_mixture/breath = ..()
|
||||
|
||||
if(breath)
|
||||
//exposure to extreme pressures can rupture lungs
|
||||
var/check_pressure = breath.return_pressure()
|
||||
if(check_pressure < ONE_ATMOSPHERE / 5 || check_pressure > ONE_ATMOSPHERE * 5)
|
||||
if(!is_lung_ruptured() && prob(5))
|
||||
rupture_lung()
|
||||
|
||||
return breath
|
||||
|
||||
/mob/living/carbon/human/handle_breath(datum/gas_mixture/breath)
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
//exposure to extreme pressures can rupture lungs
|
||||
if(breath && (breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5))
|
||||
if(!is_lung_ruptured() && prob(5))
|
||||
rupture_lung()
|
||||
|
||||
//check if we actually need to process breath
|
||||
if(!breath || (breath.total_moles == 0) || suiciding)
|
||||
failed_last_breath = 1
|
||||
if(suiciding)
|
||||
@@ -359,10 +391,9 @@
|
||||
adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
|
||||
|
||||
oxygen_alert = max(oxygen_alert, 1)
|
||||
|
||||
return 0
|
||||
|
||||
var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa
|
||||
var/safe_pressure_min = species.breath_pressure // Minimum safe partial pressure of breathable gas in kPa
|
||||
|
||||
// Lung damage increases the minimum safe pressure.
|
||||
if(species.has_organ["lungs"])
|
||||
@@ -954,11 +985,11 @@
|
||||
for(var/atom/a in hallucinations)
|
||||
qdel(a)
|
||||
|
||||
if(halloss > 100)
|
||||
src << "<span class='notice'>You're in too much pain to keep going...</span>"
|
||||
src.visible_message("<B>[src]</B> slumps to the ground, too weak to continue fighting.")
|
||||
Paralyse(10)
|
||||
setHalLoss(99)
|
||||
if(halloss > 100)
|
||||
src << "<span class='warning'>[species.halloss_message_self]</span>"
|
||||
src.visible_message("<B>[src]</B> [species.halloss_message].")
|
||||
Paralyse(10)
|
||||
setHalLoss(99)
|
||||
|
||||
if(paralysis || sleeping)
|
||||
blinded = 1
|
||||
@@ -990,49 +1021,12 @@
|
||||
if(!E.len)
|
||||
embedded_flag = 0
|
||||
|
||||
//Eyes
|
||||
//Check rig first because it's two-check and other checks will override it.
|
||||
if(istype(back,/obj/item/weapon/rig))
|
||||
var/obj/item/weapon/rig/O = back
|
||||
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
|
||||
if((O.offline && O.offline_vision_restriction == 2) || (!O.offline && O.vision_restriction == 2))
|
||||
blinded = 1
|
||||
|
||||
// Check everything else.
|
||||
|
||||
//Periodically double-check embedded_flag
|
||||
if(embedded_flag && !(life_tick % 10))
|
||||
if(!embedded_needs_process())
|
||||
embedded_flag = 0
|
||||
//Vision
|
||||
var/obj/item/organ/vision
|
||||
if(species.vision_organ)
|
||||
vision = internal_organs_by_name[species.vision_organ]
|
||||
|
||||
if(!vision) // Presumably if a species has no vision organs, they see via some other means.
|
||||
eye_blind = 0
|
||||
blinded = 0
|
||||
eye_blurry = 0
|
||||
else if(vision.is_broken()) // Vision organs cut out or broken? Permablind.
|
||||
eye_blind = 1
|
||||
blinded = 1
|
||||
eye_blurry = 1
|
||||
else
|
||||
//blindness
|
||||
if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
|
||||
blinded = 1
|
||||
else if(eye_blind) // Blindness, heals slowly over time
|
||||
eye_blind = max(eye_blind-1,0)
|
||||
blinded = 1
|
||||
else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster
|
||||
eye_blurry = max(eye_blurry-3, 0)
|
||||
blinded = 1
|
||||
|
||||
//blurry sight
|
||||
if(vision.is_bruised()) // Vision organs impaired? Permablurry.
|
||||
eye_blurry = 1
|
||||
if(eye_blurry) // Blurry eyes heal slowly
|
||||
eye_blurry = max(eye_blurry-1, 0)
|
||||
|
||||
//Ears
|
||||
if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own
|
||||
@@ -1106,14 +1100,8 @@
|
||||
|
||||
// now handle what we see on our screen
|
||||
|
||||
if(!client)
|
||||
return 0
|
||||
|
||||
for(var/image/hud in client.images)
|
||||
if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe
|
||||
client.images.Remove(hud)
|
||||
|
||||
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
if(damageoverlay.overlays)
|
||||
damageoverlay.overlays = list()
|
||||
@@ -1185,60 +1173,6 @@
|
||||
I = overlays_cache[23]
|
||||
damageoverlay.overlays += I
|
||||
|
||||
if( stat == DEAD )
|
||||
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF
|
||||
see_in_dark = 8
|
||||
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
if(healths) healths.icon_state = "health7" //DEAD healthmeter
|
||||
if(client)
|
||||
if(client.view != world.view) // If mob dies while zoomed in with device, unzoom them.
|
||||
for(var/obj/item/item in contents)
|
||||
if(item.zoom)
|
||||
item.zoom()
|
||||
break
|
||||
|
||||
else
|
||||
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
||||
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING
|
||||
|
||||
if(XRAY in mutations)
|
||||
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
|
||||
see_in_dark = 8
|
||||
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
|
||||
if(seer==1)
|
||||
var/obj/effect/rune/R = locate() in loc
|
||||
if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"])
|
||||
see_invisible = SEE_INVISIBLE_CULT
|
||||
else
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
seer = 0
|
||||
|
||||
else
|
||||
sight = species.get_vision_flags(src)
|
||||
see_in_dark = species.darksight
|
||||
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING
|
||||
var/tmp/glasses_processed = 0
|
||||
var/obj/item/weapon/rig/rig = back
|
||||
if(istype(rig) && rig.visor)
|
||||
if(!rig.helmet || (head && rig.helmet == head))
|
||||
if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses)
|
||||
glasses_processed = 1
|
||||
process_glasses(rig.visor.vision.glasses)
|
||||
|
||||
if(glasses && !glasses_processed)
|
||||
glasses_processed = 1
|
||||
process_glasses(glasses)
|
||||
if(XRAY in mutations)
|
||||
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
|
||||
see_in_dark = 8
|
||||
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
|
||||
if(!glasses_processed && (species.get_vision_flags(src) > 0))
|
||||
sight |= species.get_vision_flags(src)
|
||||
if(!seer && !glasses_processed)
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
|
||||
if(healths)
|
||||
if (analgesic > 100)
|
||||
healths.icon_state = "health_health_numb"
|
||||
@@ -1257,8 +1191,6 @@
|
||||
if(0 to 20) healths.icon_state = "health5"
|
||||
else healths.icon_state = "health6"
|
||||
|
||||
if(!seer)
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
if(nutrition_icon)
|
||||
switch(nutrition)
|
||||
if(450 to INFINITY) nutrition_icon.icon_state = "nutrition0"
|
||||
@@ -1324,85 +1256,8 @@
|
||||
bodytemp.icon_state = "temp-1"
|
||||
else
|
||||
bodytemp.icon_state = "temp0"
|
||||
if(blind)
|
||||
if(blinded) blind.layer = 18
|
||||
else blind.layer = 0
|
||||
|
||||
if(disabilities & NEARSIGHTED) //this looks meh but saves a lot of memory by not requiring to add var/prescription
|
||||
if(glasses) //to every /obj/item
|
||||
var/obj/item/clothing/glasses/G = glasses
|
||||
if(!G.prescription)
|
||||
client.screen += global_hud.vimpaired
|
||||
else
|
||||
client.screen += global_hud.vimpaired
|
||||
|
||||
if(eye_blurry) client.screen += global_hud.blurry
|
||||
if(druggy) client.screen += global_hud.druggy
|
||||
|
||||
if(config.welder_vision)
|
||||
var/found_welder
|
||||
if(species.short_sighted)
|
||||
found_welder = 1
|
||||
else
|
||||
if(istype(glasses, /obj/item/clothing/glasses/welding))
|
||||
var/obj/item/clothing/glasses/welding/O = glasses
|
||||
if(!O.up)
|
||||
found_welder = 1
|
||||
if(!found_welder && istype(head, /obj/item/clothing/head/welding))
|
||||
var/obj/item/clothing/head/welding/O = head
|
||||
if(!O.up)
|
||||
found_welder = 1
|
||||
if(!found_welder && istype(back, /obj/item/weapon/rig))
|
||||
var/obj/item/weapon/rig/O = back
|
||||
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
|
||||
if((O.offline && O.offline_vision_restriction == 1) || (!O.offline && O.vision_restriction == 1))
|
||||
found_welder = 1
|
||||
if(found_welder)
|
||||
client.screen |= global_hud.darkMask
|
||||
|
||||
if(machine)
|
||||
var/viewflags = machine.check_eye(src)
|
||||
if(viewflags < 0)
|
||||
reset_view(null, 0)
|
||||
else if(viewflags)
|
||||
sight |= viewflags
|
||||
else if(eyeobj)
|
||||
if(eyeobj.owner != src)
|
||||
|
||||
reset_view(null)
|
||||
else
|
||||
var/isRemoteObserve = 0
|
||||
if((mRemote in mutations) && remoteview_target)
|
||||
if(remoteview_target.stat==CONSCIOUS)
|
||||
isRemoteObserve = 1
|
||||
if(!isRemoteObserve && client && !client.adminobs)
|
||||
remoteview_target = null
|
||||
reset_view(null, 0)
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/proc/process_glasses(var/obj/item/clothing/glasses/G)
|
||||
if(G && G.active)
|
||||
see_in_dark += G.darkness_view
|
||||
if(G.overlay)
|
||||
client.screen |= G.overlay
|
||||
if(G.vision_flags)
|
||||
sight |= G.vision_flags
|
||||
if(!druggy && !seer)
|
||||
see_invisible = SEE_INVISIBLE_MINIMUM
|
||||
if(G.see_invisible >= 0)
|
||||
see_invisible = G.see_invisible
|
||||
if(istype(G,/obj/item/clothing/glasses/night) && !seer)
|
||||
see_invisible = SEE_INVISIBLE_MINIMUM
|
||||
/* HUD shit goes here, as long as it doesn't modify sight flags */
|
||||
// The purpose of this is to stop xray and w/e from preventing you from using huds -- Love, Doohl
|
||||
var/obj/item/clothing/glasses/hud/O = G
|
||||
if(istype(G, /obj/item/clothing/glasses/sunglasses/sechud))
|
||||
var/obj/item/clothing/glasses/sunglasses/sechud/S = G
|
||||
O = S.hud
|
||||
if(istype(O))
|
||||
O.process_hud(src)
|
||||
if(!druggy && !seer) see_invisible = SEE_INVISIBLE_LIVING
|
||||
|
||||
/mob/living/carbon/human/handle_random_events()
|
||||
if(in_stasis)
|
||||
return
|
||||
@@ -1725,5 +1580,37 @@
|
||||
restore_blood()
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/handle_vision()
|
||||
if(client)
|
||||
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science)
|
||||
if(machine)
|
||||
var/viewflags = machine.check_eye(src)
|
||||
if(viewflags < 0)
|
||||
reset_view(null, 0)
|
||||
else if(viewflags)
|
||||
sight |= viewflags
|
||||
else if(eyeobj)
|
||||
if(eyeobj.owner != src)
|
||||
|
||||
reset_view(null)
|
||||
else
|
||||
var/isRemoteObserve = 0
|
||||
if((mRemote in mutations) && remoteview_target)
|
||||
if(remoteview_target.stat==CONSCIOUS)
|
||||
isRemoteObserve = 1
|
||||
if(!isRemoteObserve && client && !client.adminobs)
|
||||
remoteview_target = null
|
||||
reset_view(null, 0)
|
||||
|
||||
update_equipment_vision()
|
||||
species.handle_vision(src)
|
||||
|
||||
/mob/living/carbon/human/update_sight()
|
||||
..()
|
||||
if(stat == DEAD)
|
||||
return
|
||||
if(XRAY in mutations)
|
||||
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
|
||||
|
||||
#undef HUMAN_MAX_OXYLOSS
|
||||
#undef HUMAN_CRIT_MAX_OXYLOSS
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
var/prone_icon // If set, draws this from icobase when mob is prone.
|
||||
var/eyes = "eyes_s" // Icon for eyes.
|
||||
var/has_floating_eyes // Eyes will overlay over darkness (glow)
|
||||
var/blood_color = "#A10808" // Red.
|
||||
var/flesh_color = "#FFC896" // Pink.
|
||||
var/base_color // Used by changelings. Should also be used for icon previes..
|
||||
@@ -67,9 +68,12 @@
|
||||
var/death_sound
|
||||
var/death_message = "seizes up and falls limp, their eyes dead and lifeless..."
|
||||
var/knockout_message = "has been knocked unconscious!"
|
||||
var/halloss_message = "slumps to the ground, too weak to continue fighting."
|
||||
var/halloss_message_self = "You're in too much pain to keep going..."
|
||||
|
||||
// Environment tolerance/life processes vars.
|
||||
var/reagent_tag //Used for metabolizing reagents.
|
||||
var/breath_pressure = 16 // Minimum partial pressure safe for breathing, kPa
|
||||
var/breath_type = "oxygen" // Non-oxygen gas breathed, if any.
|
||||
var/poison_type = "phoron" // Poisonous air.
|
||||
var/exhale_type = "carbon_dioxide" // Exhaled gas type.
|
||||
@@ -152,6 +156,9 @@
|
||||
|
||||
var/pass_flags = 0
|
||||
|
||||
/datum/species/proc/get_eyes(var/mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
/datum/species/New()
|
||||
if(hud_type)
|
||||
hud = new hud_type()
|
||||
@@ -330,3 +337,42 @@
|
||||
|
||||
/datum/species/proc/get_vision_flags(var/mob/living/carbon/human/H)
|
||||
return vision_flags
|
||||
|
||||
/datum/species/proc/handle_vision(var/mob/living/carbon/human/H)
|
||||
H.update_sight()
|
||||
H.sight |= get_vision_flags(H)
|
||||
H.sight |= H.equipment_vision_flags
|
||||
|
||||
if(H.stat == DEAD)
|
||||
return 1
|
||||
|
||||
if(!H.druggy)
|
||||
H.see_in_dark = (H.sight == SEE_TURFS|SEE_MOBS|SEE_OBJS) ? 8 : min(darksight + H.equipment_darkness_modifier, 8)
|
||||
if(H.seer)
|
||||
var/obj/effect/rune/R = locate() in H.loc
|
||||
if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"])
|
||||
H.see_invisible = SEE_INVISIBLE_CULT
|
||||
if(H.see_invisible != SEE_INVISIBLE_CULT && H.equipment_see_invis)
|
||||
H.see_invisible = min(H.see_invisible, H.equipment_see_invis)
|
||||
|
||||
if(H.equipment_tint_total >= TINT_BLIND)
|
||||
H.eye_blind = max(H.eye_blind, 1)
|
||||
|
||||
if(H.blind)
|
||||
H.blind.layer = (H.eye_blind ? 18 : 0)
|
||||
|
||||
if(!H.client)//no client, no screen to update
|
||||
return 1
|
||||
|
||||
if(config.welder_vision)
|
||||
if(short_sighted || (H.equipment_tint_total >= TINT_HEAVY))
|
||||
H.client.screen += global_hud.darkMask
|
||||
else if((!H.equipment_prescription && (H.disabilities & NEARSIGHTED)) || H.equipment_tint_total == TINT_MODERATE)
|
||||
H.client.screen += global_hud.vimpaired
|
||||
if(H.eye_blurry) H.client.screen += global_hud.blurry
|
||||
if(H.druggy) H.client.screen += global_hud.druggy
|
||||
|
||||
for(var/overlay in H.equipment_overlays)
|
||||
H.client.screen |= overlay
|
||||
|
||||
return 1
|
||||
|
||||
@@ -242,19 +242,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/species/diona/handle_death(var/mob/living/carbon/human/H)
|
||||
|
||||
var/mob/living/carbon/alien/diona/S = new(get_turf(H))
|
||||
|
||||
if(H.mind)
|
||||
H.mind.transfer_to(S)
|
||||
|
||||
for(var/mob/living/carbon/alien/diona/D in H.contents)
|
||||
if(D.client)
|
||||
D.loc = H.loc
|
||||
else
|
||||
qdel(D)
|
||||
|
||||
H.visible_message("<span class='danger'>[H] splits apart with a wet slithering noise!</span>")
|
||||
H.diona_split_into_nymphs(0)
|
||||
|
||||
/datum/species/machine
|
||||
name = "Machine"
|
||||
@@ -281,6 +269,8 @@
|
||||
show_ssd = "flashing a 'system offline' glyph on their monitor"
|
||||
death_message = "gives one shrill beep before falling lifeless."
|
||||
knockout_message = "encounters a hardware fault and suddenly reboots!"
|
||||
halloss_message = "encounters a hardware fault and suddenly reboots."
|
||||
halloss_message_self = "ERROR: Unrecoverable machine check exception.<BR>System halted, rebooting..."
|
||||
|
||||
warning_low_pressure = 50
|
||||
hazard_low_pressure = 0
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability
|
||||
// It functions almost identically (see code/datums/diseases/alien_embryo.dm)
|
||||
|
||||
/obj/item/alien_embryo
|
||||
name = "alien embryo"
|
||||
desc = "All slimy and yuck."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "larva0_dead"
|
||||
var/mob/living/affected_mob
|
||||
var/stage = 0
|
||||
|
||||
/obj/item/alien_embryo/New()
|
||||
if(istype(loc, /mob/living))
|
||||
affected_mob = loc
|
||||
processing_objects.Add(src)
|
||||
spawn(0)
|
||||
AddInfectionImages(affected_mob)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/item/alien_embryo/Destroy()
|
||||
if(affected_mob)
|
||||
affected_mob.status_flags &= ~(XENO_HOST)
|
||||
spawn(0)
|
||||
RemoveInfectionImages(affected_mob)
|
||||
..()
|
||||
|
||||
/obj/item/alien_embryo/process()
|
||||
if(!affected_mob) return
|
||||
if(loc != affected_mob)
|
||||
affected_mob.status_flags &= ~(XENO_HOST)
|
||||
processing_objects.Remove(src)
|
||||
spawn(0)
|
||||
RemoveInfectionImages(affected_mob)
|
||||
affected_mob = null
|
||||
return
|
||||
|
||||
if(stage < 5 && prob(3))
|
||||
stage++
|
||||
spawn(0)
|
||||
RefreshInfectionImage(affected_mob)
|
||||
|
||||
switch(stage)
|
||||
if(2, 3)
|
||||
if(prob(1))
|
||||
affected_mob.emote("sneeze")
|
||||
if(prob(1))
|
||||
affected_mob.emote("cough")
|
||||
if(prob(1))
|
||||
affected_mob << "\red Your throat feels sore."
|
||||
if(prob(1))
|
||||
affected_mob << "\red Mucous runs down the back of your throat."
|
||||
if(4)
|
||||
if(prob(1))
|
||||
affected_mob.emote("sneeze")
|
||||
if(prob(1))
|
||||
affected_mob.emote("cough")
|
||||
if(prob(2))
|
||||
affected_mob << "\red Your muscles ache."
|
||||
if(prob(20))
|
||||
affected_mob.take_organ_damage(1)
|
||||
if(prob(2))
|
||||
affected_mob << "\red Your stomach hurts."
|
||||
if(prob(20))
|
||||
affected_mob.adjustToxLoss(1)
|
||||
affected_mob.updatehealth()
|
||||
if(5)
|
||||
affected_mob << "\red You feel something tearing its way out of your stomach..."
|
||||
affected_mob.adjustToxLoss(10)
|
||||
affected_mob.updatehealth()
|
||||
if(prob(50))
|
||||
AttemptGrow()
|
||||
|
||||
/obj/item/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1)
|
||||
var/list/candidates = get_alien_candidates()
|
||||
var/picked = null
|
||||
|
||||
// To stop clientless larva, we will check that our host has a client
|
||||
// if we find no ghosts to become the alien. If the host has a client
|
||||
// he will become the alien but if he doesn't then we will set the stage
|
||||
// to 2, so we don't do a process heavy check everytime.
|
||||
|
||||
if(candidates.len)
|
||||
picked = pick(candidates)
|
||||
else if(affected_mob.client)
|
||||
picked = affected_mob.key
|
||||
else
|
||||
stage = 4 // Let's try again later.
|
||||
return
|
||||
|
||||
if(affected_mob.lying)
|
||||
affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_lie")
|
||||
else
|
||||
affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_stand")
|
||||
spawn(6)
|
||||
var/mob/living/carbon/alien/larva/new_xeno = new(affected_mob.loc)
|
||||
new_xeno.key = picked
|
||||
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention
|
||||
if(gib_on_success)
|
||||
affected_mob.gib()
|
||||
qdel(src)
|
||||
|
||||
/*----------------------------------------
|
||||
Proc: RefreshInfectionImage()
|
||||
Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens.
|
||||
----------------------------------------*/
|
||||
/obj/item/alien_embryo/proc/RefreshInfectionImage()
|
||||
|
||||
for(var/mob/living/carbon/alien in player_list)
|
||||
|
||||
if(!locate(/obj/item/organ/xenos/hivenode) in alien.internal_organs)
|
||||
continue
|
||||
|
||||
if(alien.client)
|
||||
for(var/image/I in alien.client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected"))
|
||||
qdel(I)
|
||||
for(var/mob/living/L in mob_list)
|
||||
if(iscorgi(L) || iscarbon(L))
|
||||
if(L.status_flags & XENO_HOST)
|
||||
var/I = image('icons/mob/alien.dmi', loc = L, icon_state = "infected[stage]")
|
||||
alien.client.images += I
|
||||
|
||||
/*----------------------------------------
|
||||
Proc: AddInfectionImages(C)
|
||||
Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C.
|
||||
----------------------------------------*/
|
||||
/obj/item/alien_embryo/proc/AddInfectionImages(var/mob/living/C)
|
||||
if(C)
|
||||
|
||||
for(var/mob/living/carbon/alien in player_list)
|
||||
|
||||
if(!locate(/obj/item/organ/xenos/hivenode) in alien.internal_organs)
|
||||
continue
|
||||
|
||||
if(alien.client)
|
||||
if(C.status_flags & XENO_HOST)
|
||||
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]")
|
||||
alien.client.images += I
|
||||
|
||||
/*----------------------------------------
|
||||
Proc: RemoveInfectionImage(C)
|
||||
Des: Removes the alien infection image from all aliens in the world located in passed mob (C).
|
||||
----------------------------------------*/
|
||||
|
||||
/obj/item/alien_embryo/proc/RemoveInfectionImages(var/mob/living/C)
|
||||
|
||||
if(C)
|
||||
|
||||
for(var/mob/living/carbon/alien in player_list)
|
||||
|
||||
if(!locate(/obj/item/organ/xenos/hivenode) in alien.internal_organs)
|
||||
continue
|
||||
|
||||
if(alien.client)
|
||||
for(var/image/I in alien.client.images)
|
||||
if(I.loc == C)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected"))
|
||||
qdel(I)
|
||||
@@ -32,10 +32,11 @@ var/const/MAX_ACTIVE_TIME = 400
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob)
|
||||
..()
|
||||
/obj/item/clothing/mask/facehugger/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
|
||||
. = ..()
|
||||
user.drop_from_inventory(src)
|
||||
Attach(M)
|
||||
if(hit_zone == "head")
|
||||
Attach(target)
|
||||
|
||||
/obj/item/clothing/mask/facehugger/New()
|
||||
if(config.aliens_allowed)
|
||||
|
||||
@@ -88,13 +88,13 @@
|
||||
verbs -= /mob/living/carbon/human/proc/lay_egg
|
||||
return
|
||||
|
||||
if(locate(/obj/effect/alien/egg) in get_turf(src))
|
||||
if(locate(/obj/structure/alien/egg) in get_turf(src))
|
||||
src << "There's already an egg here."
|
||||
return
|
||||
|
||||
if(check_alien_ability(75,1,"egg sac"))
|
||||
visible_message("<span class='alium'><B>[src] has laid an egg!</B></span>")
|
||||
new /obj/effect/alien/egg(loc)
|
||||
new /obj/structure/alien/egg(loc)
|
||||
|
||||
return
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
|
||||
if(check_alien_ability(50,1,"resin spinner"))
|
||||
visible_message("<span class='alium'><B>[src] has planted some alien weeds!</B></span>")
|
||||
new /obj/effect/alien/weeds/node(loc)
|
||||
new /obj/structure/alien/node(loc)
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/corrosive_acid(O as obj|turf in oview(1)) //If they right click to corrode, an error will flash if its an invalid target./N
|
||||
@@ -154,7 +154,7 @@
|
||||
return
|
||||
|
||||
if(check_alien_ability(200,0,"acid gland"))
|
||||
new /obj/effect/alien/acid(get_turf(O), O)
|
||||
new /obj/effect/acid(get_turf(O), O)
|
||||
visible_message("<span class='alium'><B>[src] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!</B></span>")
|
||||
|
||||
return
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
/mob/living/carbon/human/proc/resin() // -- TLE
|
||||
set name = "Secrete Resin (75)"
|
||||
set desc = "Secrete tough malleable resin."
|
||||
set desc = "Secrete tough, malleable resin."
|
||||
set category = "Abilities"
|
||||
|
||||
var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin door","resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist
|
||||
@@ -214,9 +214,51 @@
|
||||
if("resin door")
|
||||
new /obj/structure/simple_door/resin(loc)
|
||||
if("resin wall")
|
||||
new /obj/effect/alien/resin/wall(loc)
|
||||
new /obj/structure/alien/resin/wall(loc)
|
||||
if("resin membrane")
|
||||
new /obj/effect/alien/resin/membrane(loc)
|
||||
new /obj/structure/alien/resin/membrane(loc)
|
||||
if("resin nest")
|
||||
new /obj/structure/bed/nest(loc)
|
||||
return
|
||||
return
|
||||
|
||||
mob/living/carbon/human/proc/xeno_infest(mob/living/carbon/human/M as mob in oview())
|
||||
set name = "Infest (500)"
|
||||
set desc = "Link a victim to the hivemind."
|
||||
set category = "Abilities"
|
||||
|
||||
if(!M.Adjacent(src))
|
||||
src << "<span class='warning'>They are too far away.</span>"
|
||||
return
|
||||
|
||||
if(!M.mind)
|
||||
src << "<span class='warning'>This mindless flesh adds nothing to the hive.</span>"
|
||||
return
|
||||
|
||||
if(M.species.get_bodytype() == "Xenomorph" || !isnull(M.internal_organs_by_name["hive node"]))
|
||||
src << "<span class='warning'>They are already part of the hive.</span>"
|
||||
return
|
||||
|
||||
var/obj/item/organ/affecting = M.get_organ("chest")
|
||||
if(!affecting || (affecting.status & ORGAN_ROBOT))
|
||||
src << "<span class='warning'>This form is not compatible with our physiology.</span>"
|
||||
return
|
||||
|
||||
src.visible_message("<span class='danger'>\The [src] crouches over \the [M], extending a hideous protuberance from its head!</span>")
|
||||
|
||||
if(!do_after(src, 150))
|
||||
return
|
||||
|
||||
if(!M || !M.Adjacent(src))
|
||||
src << "<span class='warning'>They are too far away.</span>"
|
||||
return
|
||||
|
||||
if(M.species.get_bodytype() == "Xenomorph" || !isnull(M.internal_organs_by_name["hive node"]) || !affecting || (affecting.status & ORGAN_ROBOT))
|
||||
return
|
||||
|
||||
if(!check_alien_ability(500,1,"egg sac"))
|
||||
return
|
||||
|
||||
src.visible_message("<span class='danger'>\The [src] regurgitates something into \the [M]'s torso!</span>")
|
||||
M << "<span class='danger'>A hideous lump of alien mass strains your ribcage as it settles within!</span>"
|
||||
var/obj/item/organ/xenos/hivenode/node = new(affecting)
|
||||
node.replaced(M,affecting)
|
||||
@@ -15,8 +15,8 @@
|
||||
|
||||
eyes = "blank_eyes"
|
||||
|
||||
brute_mod = 0.5 // Hardened carapace.
|
||||
burn_mod = 2 // Weak to fire.
|
||||
brute_mod = 0.25 // Hardened carapace.
|
||||
burn_mod = 1.1 // Weak to fire.
|
||||
|
||||
warning_low_pressure = 50
|
||||
hazard_low_pressure = -1
|
||||
@@ -98,11 +98,11 @@
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
if(!environment) return
|
||||
|
||||
if(environment.gas["phoron"] > 0 || locate(/obj/effect/alien/weeds) in T)
|
||||
if(!regenerate(H))
|
||||
var/obj/item/organ/xenos/plasmavessel/P = H.internal_organs_by_name["plasma vessel"]
|
||||
P.stored_plasma += weeds_plasma_rate
|
||||
P.stored_plasma = min(max(P.stored_plasma,0),P.max_plasma)
|
||||
var/obj/effect/plant/plant = locate() in T
|
||||
if((environment.gas["phoron"] > 0 || (plant && plant.seed && plant.seed.name == "xenomorph")) && !regenerate(H))
|
||||
var/obj/item/organ/xenos/plasmavessel/P = H.internal_organs_by_name["plasma vessel"]
|
||||
P.stored_plasma += weeds_plasma_rate
|
||||
P.stored_plasma = min(max(P.stored_plasma,0),P.max_plasma)
|
||||
..()
|
||||
|
||||
/datum/species/xenos/proc/regenerate(var/mob/living/carbon/human/H)
|
||||
@@ -140,14 +140,6 @@
|
||||
|
||||
return 0
|
||||
|
||||
/datum/species/xenos/handle_login_special(var/mob/living/carbon/human/H)
|
||||
H.AddInfectionImages()
|
||||
..()
|
||||
|
||||
/datum/species/xenos/handle_logout_special(var/mob/living/carbon/human/H)
|
||||
H.RemoveInfectionImages()
|
||||
..()
|
||||
|
||||
/datum/species/xenos/drone
|
||||
name = "Xenomorph Drone"
|
||||
caste_name = "drone"
|
||||
@@ -278,7 +270,8 @@
|
||||
/mob/living/carbon/human/proc/transfer_plasma,
|
||||
/mob/living/carbon/human/proc/corrosive_acid,
|
||||
/mob/living/carbon/human/proc/neurotoxin,
|
||||
/mob/living/carbon/human/proc/resin
|
||||
/mob/living/carbon/human/proc/resin,
|
||||
/mob/living/carbon/human/proc/xeno_infest
|
||||
)
|
||||
|
||||
/datum/species/xenos/queen/handle_login_special(var/mob/living/carbon/human/H)
|
||||
|
||||
@@ -22,28 +22,3 @@ proc/create_new_xenomorph(var/alien_caste,var/target)
|
||||
/mob/living/carbon/human/xqueen/New(var/new_loc)
|
||||
h_style = "Bald"
|
||||
..(new_loc, "Xenomorph Queen")
|
||||
|
||||
// I feel like we should generalize/condense down all the various icon-rendering antag procs.
|
||||
/*----------------------------------------
|
||||
Proc: AddInfectionImages()
|
||||
Des: Gives the client of the alien an image on each infected mob.
|
||||
----------------------------------------*/
|
||||
/mob/living/carbon/human/proc/AddInfectionImages()
|
||||
if (client)
|
||||
for (var/mob/living/C in mob_list)
|
||||
if(C.status_flags & XENO_HOST)
|
||||
var/obj/item/alien_embryo/A = locate() in C
|
||||
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]")
|
||||
client.images += I
|
||||
return
|
||||
|
||||
/*----------------------------------------
|
||||
Proc: RemoveInfectionImages()
|
||||
Des: Removes all infected images from the alien.
|
||||
----------------------------------------*/
|
||||
/mob/living/carbon/human/proc/RemoveInfectionImages()
|
||||
if (client)
|
||||
for(var/image/I in client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected"))
|
||||
qdel(I)
|
||||
return
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
|
||||
/datum/unarmed_attack/proc/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armour,var/attack_damage,var/zone)
|
||||
|
||||
if(target.stat == DEAD)
|
||||
return
|
||||
|
||||
var/stun_chance = rand(0, 100)
|
||||
|
||||
if(attack_damage >= 5 && armour < 2 && !(target == user) && stun_chance <= attack_damage * 5) // 25% standard chance
|
||||
@@ -233,4 +236,4 @@
|
||||
|
||||
switch(attack_damage)
|
||||
if(1 to 4) user.visible_message("<span class='danger'>[pick("[user] stomped on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!</span>")
|
||||
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/
|
||||
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/
|
||||
|
||||
@@ -163,6 +163,8 @@ Please contact me on #coderbus IRC. ~Carn x
|
||||
icon = stand_icon
|
||||
for(var/image/I in overlays_standing)
|
||||
overlays += I
|
||||
if(species.has_floating_eyes)
|
||||
overlays |= species.get_eyes(src)
|
||||
|
||||
if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone.
|
||||
var/matrix/M = matrix()
|
||||
|
||||
@@ -281,87 +281,3 @@
|
||||
/mob/living/carbon/slime/has_eyes()
|
||||
return 0
|
||||
|
||||
//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them////////////////////////
|
||||
|
||||
/*
|
||||
// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere
|
||||
/obj/item/slime_core
|
||||
name = "slime extract"
|
||||
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
|
||||
icon = 'icons/mob/slimes.dmi'
|
||||
icon_state = "slime extract"
|
||||
force = 1.0
|
||||
w_class = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 2
|
||||
throw_range = 6
|
||||
origin_tech = list(TECH_BIO = 4)
|
||||
var/POWERFLAG = 0 // sshhhhhhh
|
||||
var/Flush = 30
|
||||
var/Uses = 5 // uses before it goes inert
|
||||
|
||||
/obj/item/slime_core/New()
|
||||
..()
|
||||
create_reagents(100)
|
||||
POWERFLAG = rand(1,10)
|
||||
Uses = rand(7, 25)
|
||||
//flags |= NOREACT
|
||||
/*
|
||||
spawn()
|
||||
Life()
|
||||
|
||||
proc/Life()
|
||||
while(src)
|
||||
sleep(25)
|
||||
Flush--
|
||||
if(Flush <= 0)
|
||||
reagents.clear_reagents()
|
||||
Flush = 30
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime
|
||||
name = "slime egg"
|
||||
desc = "A small, gelatinous egg."
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "slime egg-growing"
|
||||
bitesize = 12
|
||||
origin_tech = list(TECH_BIO = 4)
|
||||
var/grown = 0
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/New()
|
||||
..()
|
||||
reagents.add_reagent("nutriment", 4)
|
||||
reagents.add_reagent("slimejelly", 1)
|
||||
spawn(rand(1200,1500))//the egg takes a while to "ripen"
|
||||
Grow()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow()
|
||||
grown = 1
|
||||
icon_state = "slime egg-grown"
|
||||
processing_objects.Add(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch()
|
||||
processing_objects.Remove(src)
|
||||
var/turf/T = get_turf(src)
|
||||
src.visible_message("<span class='warning'> The [name] pulsates and quivers!</span>")
|
||||
spawn(rand(50,100))
|
||||
src.visible_message("<span class='warning'> The [name] bursts open!</span>")
|
||||
new/mob/living/carbon/slime(T)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process()
|
||||
var/turf/location = get_turf(src)
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
if (environment.phoron > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch
|
||||
src.Hatch()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype( W, /obj/item/weapon/pen/crayon ))
|
||||
return
|
||||
else
|
||||
..()
|
||||
*/
|
||||
|
||||
@@ -126,24 +126,60 @@
|
||||
adjustEarDamage(-0.05,-1)
|
||||
|
||||
//this handles hud updates. Calls update_vision() and handle_hud_icons()
|
||||
/mob/living/handle_regular_hud_updates()
|
||||
if(!client)
|
||||
return 0
|
||||
..()
|
||||
/mob/living/proc/handle_regular_hud_updates()
|
||||
if(!client) return 0
|
||||
|
||||
handle_vision()
|
||||
handle_hud_icons()
|
||||
handle_vision()
|
||||
|
||||
return 1
|
||||
|
||||
/mob/living/proc/handle_vision()
|
||||
return
|
||||
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science)
|
||||
|
||||
update_sight()
|
||||
|
||||
if(stat == DEAD)
|
||||
return
|
||||
|
||||
if(blind)
|
||||
if(eye_blind)
|
||||
blind.layer = 18
|
||||
else
|
||||
blind.layer = 0
|
||||
if (disabilities & NEARSIGHTED)
|
||||
client.screen += global_hud.vimpaired
|
||||
if (eye_blurry)
|
||||
client.screen += global_hud.blurry
|
||||
if (druggy)
|
||||
client.screen += global_hud.druggy
|
||||
if(machine)
|
||||
var/viewflags = machine.check_eye(src)
|
||||
if(viewflags < 0)
|
||||
reset_view(null, 0)
|
||||
else if(viewflags)
|
||||
sight |= viewflags
|
||||
else if(eyeobj && eyeobj.owner != src)
|
||||
reset_view(null)
|
||||
else
|
||||
if(!client.adminobs)
|
||||
reset_view(null)
|
||||
|
||||
/mob/living/proc/update_sight()
|
||||
return
|
||||
if(stat == DEAD)
|
||||
sight |= SEE_TURFS
|
||||
sight |= SEE_MOBS
|
||||
sight |= SEE_OBJS
|
||||
see_in_dark = 8
|
||||
see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
else
|
||||
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
||||
see_in_dark = 2
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
|
||||
/mob/living/proc/handle_hud_icons()
|
||||
handle_hud_icons_health()
|
||||
handle_hud_glasses()
|
||||
return
|
||||
|
||||
/mob/living/proc/handle_hud_icons_health()
|
||||
|
||||
@@ -111,6 +111,42 @@
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
/mob/living/proc/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
|
||||
return target_zone
|
||||
|
||||
//Called when the mob is hit with an item in combat. Returns the blocked result
|
||||
/mob/living/proc/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone)
|
||||
visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] with [I.name] by [user]!</span>")
|
||||
|
||||
var/blocked = run_armor_check(hit_zone, "melee")
|
||||
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
|
||||
|
||||
if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too
|
||||
var/turf/simulated/location = get_turf(src)
|
||||
if(istype(location)) location.add_blood_floor(src)
|
||||
|
||||
return blocked
|
||||
|
||||
//returns 0 if the effects failed to apply for some reason, 1 otherwise.
|
||||
/mob/living/proc/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
|
||||
if(!effective_force || blocked >= 2)
|
||||
return 0
|
||||
|
||||
//Hulk modifier
|
||||
if(HULK in user.mutations)
|
||||
effective_force *= 2
|
||||
|
||||
//Apply weapon damage
|
||||
var/weapon_sharp = is_sharp(I)
|
||||
var/weapon_edge = has_edge(I)
|
||||
if(prob(max(getarmor(hit_zone, "melee") - I.armor_penetration, 0))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
|
||||
weapon_sharp = 0
|
||||
weapon_edge = 0
|
||||
|
||||
apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
|
||||
|
||||
return 1
|
||||
|
||||
//this proc handles being hit by a thrown atom
|
||||
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve
|
||||
if(istype(AM,/obj/))
|
||||
@@ -338,54 +374,3 @@
|
||||
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
|
||||
//hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1)
|
||||
client.screen += hud_used.hide_actions_toggle
|
||||
|
||||
|
||||
//If simple_animals are ever moved under carbon, then this can probably be moved to carbon as well
|
||||
/mob/living/proc/attack_throat(obj/item/W, obj/item/weapon/grab/G, mob/user)
|
||||
|
||||
// Knifing
|
||||
if(!W.edge || !W.force || W.damtype != BRUTE) return //unsuitable weapon
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] begins to slit [src]'s throat with \the [W]!</span>")
|
||||
|
||||
user.next_move = world.time + 20 //also should prevent user from triggering this repeatedly
|
||||
if(!do_after(user, 20))
|
||||
return
|
||||
if(!(G && G.assailant == user && G.affecting == src)) //check that we still have a grab
|
||||
return
|
||||
|
||||
var/damage_mod = 1
|
||||
//presumably, if they are wearing a helmet that stops pressure effects, then it probably covers the throat as well
|
||||
var/obj/item/clothing/head/helmet = get_equipped_item(slot_head)
|
||||
if(istype(helmet) && (helmet.body_parts_covered & HEAD) && (helmet.item_flags & STOPPRESSUREDAMAGE))
|
||||
//we don't do an armor_check here because this is not an impact effect like a weapon swung with momentum, that either penetrates or glances off.
|
||||
damage_mod = 1.0 - (helmet.armor["melee"]/100)
|
||||
|
||||
var/total_damage = 0
|
||||
for(var/i in 1 to 3)
|
||||
var/damage = min(W.force*1.5, 20)*damage_mod
|
||||
apply_damage(damage, W.damtype, "head", 0, sharp=W.sharp, edge=W.edge)
|
||||
total_damage += damage
|
||||
|
||||
var/oxyloss = total_damage
|
||||
if(total_damage >= 40) //threshold to make someone pass out
|
||||
oxyloss = 60 // Brain lacks oxygen immediately, pass out
|
||||
|
||||
adjustOxyLoss(min(oxyloss, 100 - getOxyLoss())) //don't put them over 100 oxyloss
|
||||
|
||||
if(total_damage)
|
||||
if(oxyloss >= 40)
|
||||
user.visible_message("<span class='danger'>\The [user] slit [src]'s throat open with \the [W]!</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>\The [user] cut [src]'s neck with \the [W]!</span>")
|
||||
|
||||
if(W.hitsound)
|
||||
playsound(loc, W.hitsound, 50, 1, -1)
|
||||
|
||||
G.last_action = world.time
|
||||
flick(G.hud.icon_state, G.hud)
|
||||
|
||||
user.attack_log += "\[[time_stamp()]\]<font color='red'> Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
|
||||
src.attack_log += "\[[time_stamp()]\]<font color='orange'> Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])</font>"
|
||||
msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" )
|
||||
return
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
/mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg)
|
||||
laws_sanity_check()
|
||||
laws.set_zeroth_law(law, law_borg)
|
||||
log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]")
|
||||
log_law("has given [src] the zeroth law: '[law]'[law_borg ? " / '[law_borg]'" : ""]")
|
||||
|
||||
/mob/living/silicon/robot/set_zeroth_law(var/law, var/law_borg)
|
||||
..()
|
||||
@@ -22,40 +22,40 @@
|
||||
/mob/living/silicon/proc/add_ion_law(var/law)
|
||||
laws_sanity_check()
|
||||
laws.add_ion_law(law)
|
||||
log_and_message_admins("has given [src] the ion law: [law]")
|
||||
log_law("has given [src] the ion law: [law]")
|
||||
|
||||
/mob/living/silicon/proc/add_inherent_law(var/law)
|
||||
laws_sanity_check()
|
||||
laws.add_inherent_law(law)
|
||||
log_and_message_admins("has given [src] the inherent law: [law]")
|
||||
log_law("has given [src] the inherent law: [law]")
|
||||
|
||||
/mob/living/silicon/proc/add_supplied_law(var/number, var/law)
|
||||
laws_sanity_check()
|
||||
laws.add_supplied_law(number, law)
|
||||
log_and_message_admins("has given [src] the supplied law: [law]")
|
||||
log_law("has given [src] the supplied law: [law]")
|
||||
|
||||
/mob/living/silicon/proc/delete_law(var/datum/ai_law/law)
|
||||
laws_sanity_check()
|
||||
laws.delete_law(law)
|
||||
log_and_message_admins("has deleted a law belonging to [src]: [law.law]")
|
||||
log_law("has deleted a law belonging to [src]: [law.law]")
|
||||
|
||||
/mob/living/silicon/proc/clear_inherent_laws(var/silent = 0)
|
||||
laws_sanity_check()
|
||||
laws.clear_inherent_laws()
|
||||
if(!silent)
|
||||
log_and_message_admins("cleared the inherent laws of [src]")
|
||||
log_law("cleared the inherent laws of [src]")
|
||||
|
||||
/mob/living/silicon/proc/clear_ion_laws(var/silent = 0)
|
||||
laws_sanity_check()
|
||||
laws.clear_ion_laws()
|
||||
if(!silent)
|
||||
log_and_message_admins("cleared the ion laws of [src]")
|
||||
log_law("cleared the ion laws of [src]")
|
||||
|
||||
/mob/living/silicon/proc/clear_supplied_laws(var/silent = 0)
|
||||
laws_sanity_check()
|
||||
laws.clear_supplied_laws()
|
||||
if(!silent)
|
||||
log_and_message_admins("cleared the supplied laws of [src]")
|
||||
log_law("cleared the supplied laws of [src]")
|
||||
|
||||
/mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws)
|
||||
var/prefix = ""
|
||||
@@ -103,3 +103,7 @@
|
||||
/mob/living/silicon/proc/lawsync()
|
||||
laws_sanity_check()
|
||||
laws.sort_laws()
|
||||
|
||||
/mob/living/silicon/proc/log_law(var/law_message)
|
||||
log_and_message_admins(law_message)
|
||||
lawchanges += "[worldtime2text()] - [usr ? "[key_name(usr)]" : "EVENT"] [law_message]"
|
||||
|
||||
@@ -91,6 +91,15 @@ var/global/list/robot_modules = list(
|
||||
return
|
||||
|
||||
/obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R, var/rate)
|
||||
var/obj/item/device/flash/F = locate() in src.modules
|
||||
if(F)
|
||||
if(F.broken)
|
||||
F.broken = 0
|
||||
F.times_used = 0
|
||||
F.icon_state = "flash"
|
||||
else if(F.times_used)
|
||||
F.times_used--
|
||||
|
||||
if(!synths || !synths.len)
|
||||
return
|
||||
|
||||
@@ -271,7 +280,6 @@ var/global/list/robot_modules = list(
|
||||
..()
|
||||
|
||||
/obj/item/weapon/robot_module/medical/crisis/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
|
||||
|
||||
var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules
|
||||
if(S.mode == 2)
|
||||
S.reagents.clear_reagents()
|
||||
@@ -423,13 +431,7 @@ var/global/list/robot_modules = list(
|
||||
..()
|
||||
|
||||
/obj/item/weapon/robot_module/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
|
||||
var/obj/item/device/flash/F = locate() in src.modules
|
||||
if(F.broken)
|
||||
F.broken = 0
|
||||
F.times_used = 0
|
||||
F.icon_state = "flash"
|
||||
else if(F.times_used)
|
||||
F.times_used--
|
||||
..()
|
||||
var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in src.modules
|
||||
if(T.power_supply.charge < T.power_supply.maxcharge)
|
||||
T.power_supply.give(T.charge_cost * amount)
|
||||
@@ -462,6 +464,7 @@ var/global/list/robot_modules = list(
|
||||
..()
|
||||
|
||||
/obj/item/weapon/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
|
||||
..()
|
||||
var/obj/item/device/lightreplacer/LR = locate() in src.modules
|
||||
LR.Charge(R, amount)
|
||||
if(src.emag)
|
||||
@@ -544,6 +547,7 @@ var/global/list/robot_modules = list(
|
||||
..()
|
||||
|
||||
/obj/item/weapon/robot_module/general/butler/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
|
||||
..()
|
||||
var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules
|
||||
E.reagents.add_reagent("enzyme", 2 * amount)
|
||||
if(src.emag)
|
||||
|
||||
@@ -68,31 +68,46 @@
|
||||
if (!message)
|
||||
return
|
||||
|
||||
var/obj/machinery/hologram/holopad/T = src.holo
|
||||
if(T && T.masters[src])//If there is a hologram and its master is the user.
|
||||
|
||||
//Human-like, sorta, heard by those who understand humans.
|
||||
var/rendered_a
|
||||
//Speach distorted, heard by those who do not understand AIs.
|
||||
var/message_stars = stars(message)
|
||||
var/rendered_b
|
||||
var/obj/machinery/hologram/holopad/H = src.holo
|
||||
if(H && H.masters[src])//If there is a hologram and its master is the user.
|
||||
|
||||
// AI can hear their own message, this formats it for them.
|
||||
if(speaking)
|
||||
rendered_a = "<span class='game say'><span class='name'>[name]</span> [speaking.format_message(message, verb)]</span>"
|
||||
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [speaking.format_message(message_stars, verb)]</span>"
|
||||
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [speaking.format_message(message, verb)]</span></i>"//The AI can "hear" its own message.
|
||||
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [speaking.format_message(message, verb)]</span></i>"
|
||||
else
|
||||
rendered_a = "<span class='game say'><span class='name'>[name]</span> [verb], <span class='message'>\"[message]\"</span></span>"
|
||||
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [verb], <span class='message'>\"[message_stars]\"</span></span>"
|
||||
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [verb], <span class='message'><span class='body'>\"[message]\"</span></span></span></i>"//The AI can "hear" its own message.
|
||||
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [verb], <span class='message'><span class='body'>\"[message]\"</span></span></span></i>"
|
||||
|
||||
//This is so pAI's and people inside lockers/boxes,etc can hear the AI Holopad, the alternative being recursion through contents.
|
||||
//This is much faster.
|
||||
var/list/listening = list()
|
||||
var/list/listening_obj = list()
|
||||
var/turf/T = get_turf(H)
|
||||
|
||||
if(T)
|
||||
var/list/hear = hear(7, T)
|
||||
var/list/hearturfs = list()
|
||||
|
||||
for(var/I in hear)
|
||||
if(istype(I, /mob/))
|
||||
var/mob/M = I
|
||||
listening += M
|
||||
hearturfs += M.locs[1]
|
||||
for(var/obj/O in M.contents)
|
||||
listening_obj |= O
|
||||
else if(istype(I, /obj/))
|
||||
var/obj/O = I
|
||||
hearturfs += O.locs[1]
|
||||
listening_obj |= O
|
||||
|
||||
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
|
||||
M.hear_say(message,verb,speaking,null,null, src)
|
||||
continue
|
||||
if(M.loc && M.locs[1] in hearturfs)
|
||||
M.hear_say(message,verb,speaking,null,null, src)
|
||||
|
||||
|
||||
for(var/mob/M in hearers(T.loc))//The location is the object, default distance.
|
||||
if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to.
|
||||
M.show_message(rendered_a, 2)
|
||||
else//If they do not.
|
||||
M.show_message(rendered_b, 2)
|
||||
/*Radios "filter out" this conversation channel so we don't need to account for them.
|
||||
This is another way of saying that we won't bother dealing with them.*/
|
||||
else
|
||||
src << "No holopad connected."
|
||||
return 0
|
||||
|
||||
@@ -132,9 +132,6 @@
|
||||
updatehealth()
|
||||
return 1*/
|
||||
|
||||
/mob/living/silicon/attack_throat()
|
||||
return
|
||||
|
||||
/proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai)
|
||||
if(!istype(bot) || !istype(ai))
|
||||
return 0
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
var/obj/item/inventory_head
|
||||
var/obj/item/inventory_back
|
||||
var/facehugger
|
||||
|
||||
//IAN! SQUEEEEEEEEE~
|
||||
/mob/living/simple_animal/corgi/Ian
|
||||
@@ -123,13 +122,6 @@
|
||||
var/icon/back_icon = image('icons/mob/corgi_back.dmi',back_icon_state)
|
||||
if(back_icon)
|
||||
overlays += back_icon
|
||||
|
||||
if(facehugger)
|
||||
if(istype(src, /mob/living/simple_animal/corgi/puppy))
|
||||
overlays += image('icons/mob/mask.dmi',"facehugger_corgipuppy")
|
||||
else
|
||||
overlays += image('icons/mob/mask.dmi',"facehugger_corgi")
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
emote_see = list("jiggles", "bounces in place")
|
||||
var/colour = "grey"
|
||||
|
||||
/mob/living/simple_animal/slime/can_force_feed(var/feeder, var/food, var/feedback)
|
||||
if(feedback)
|
||||
feeder << "Where do you intend to put \the [food]? \The [src] doesn't have a mouth!"
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/adultslime
|
||||
name = "pet slime"
|
||||
desc = "A lovable, domesticated slime."
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
return 0
|
||||
|
||||
else
|
||||
attacked_with_item(O, user)
|
||||
O.attack(src, user, user.zone_sel.selecting)
|
||||
|
||||
/mob/living/simple_animal/spiderbot/emag_act(var/remaining_charges, var/mob/user)
|
||||
if (emagged)
|
||||
|
||||
@@ -286,28 +286,28 @@
|
||||
if(istype(O, /obj/item/weapon/material/knife) || istype(O, /obj/item/weapon/material/knife/butch))
|
||||
harvest(user)
|
||||
else
|
||||
attacked_with_item(O, user)
|
||||
if(!O.force)
|
||||
visible_message("<span class='notice'>[user] gently taps [src] with \the [O].</span>")
|
||||
else
|
||||
O.attack(src, user, user.zone_sel.selecting)
|
||||
|
||||
//TODO: refactor mob attackby(), attacked_by(), and friends.
|
||||
/mob/living/simple_animal/proc/attacked_with_item(var/obj/item/O, var/mob/user)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
if(!O.force)
|
||||
visible_message("<span class='notice'>[user] gently taps [src] with \the [O].</span>")
|
||||
return
|
||||
|
||||
if(O.force > resistance)
|
||||
var/damage = O.force
|
||||
if (O.damtype == HALLOSS)
|
||||
damage = 0
|
||||
if(supernatural && istype(O,/obj/item/weapon/nullrod))
|
||||
damage *= 2
|
||||
purge = 3
|
||||
adjustBruteLoss(damage)
|
||||
else
|
||||
usr << "<span class='danger'>This weapon is ineffective, it does no damage.</span>"
|
||||
/mob/living/simple_animal/hit_with_weapon(obj/item/O, mob/living/user, var/effective_force, var/hit_zone)
|
||||
|
||||
visible_message("<span class='danger'>\The [src] has been attacked with \the [O] by [user].</span>")
|
||||
user.do_attack_animation(src)
|
||||
|
||||
if(O.force <= resistance)
|
||||
user << "<span class='danger'>This weapon is ineffective, it does no damage.</span>"
|
||||
return 2
|
||||
|
||||
var/damage = O.force
|
||||
if (O.damtype == HALLOSS)
|
||||
damage = 0
|
||||
if(supernatural && istype(O,/obj/item/weapon/nullrod))
|
||||
damage *= 2
|
||||
purge = 3
|
||||
adjustBruteLoss(damage)
|
||||
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/movement_delay()
|
||||
var/tally = 0 //Incase I need to add stuff other than "speed" later
|
||||
|
||||
@@ -498,6 +498,12 @@ proc/is_blind(A)
|
||||
/mob/proc/is_client_active(var/active = 1)
|
||||
return client && client.inactivity < active MINUTES
|
||||
|
||||
/mob/proc/can_eat()
|
||||
return 1
|
||||
|
||||
/mob/proc/can_force_feed()
|
||||
return 1
|
||||
|
||||
#define SAFE_PERP -50
|
||||
/mob/living/proc/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
|
||||
if(stat == DEAD)
|
||||
|
||||
@@ -289,7 +289,7 @@
|
||||
|
||||
|
||||
proc/AttemptLateSpawn(rank,var/spawning_at)
|
||||
if (src != usr)
|
||||
if(src != usr)
|
||||
return 0
|
||||
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
|
||||
usr << "\red The round is either not ready, or has already finished..."
|
||||
@@ -323,7 +323,7 @@
|
||||
character.loc = C.loc
|
||||
|
||||
AnnounceCyborg(character, rank, "has been downloaded to the empty core in \the [character.loc.loc]")
|
||||
ticker.mode.latespawn(character)
|
||||
ticker.mode.handle_latejoin(character)
|
||||
|
||||
qdel(C)
|
||||
qdel(src)
|
||||
@@ -338,7 +338,7 @@
|
||||
character.buckled.loc = character.loc
|
||||
character.buckled.set_dir(character.dir)
|
||||
|
||||
ticker.mode.latespawn(character)
|
||||
ticker.mode.handle_latejoin(character)
|
||||
|
||||
if(character.mind.assigned_role != "Cyborg")
|
||||
data_core.manifest_inject(character)
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
datum/preferences
|
||||
//The mob should have a gender you want before running this proc. Will run fine without H
|
||||
proc/randomize_appearance_for(var/mob/living/carbon/human/H)
|
||||
if(H)
|
||||
if(H.gender == MALE)
|
||||
gender = MALE
|
||||
else
|
||||
gender = FEMALE
|
||||
gender = pick(MALE, FEMALE)
|
||||
s_tone = random_skin_tone()
|
||||
h_style = random_hair_style(gender, species)
|
||||
f_style = random_facial_hair_style(gender, species)
|
||||
|
||||
@@ -161,30 +161,6 @@
|
||||
qdel(src)
|
||||
return O
|
||||
|
||||
//human -> alien
|
||||
/mob/living/carbon/human/proc/Alienize()
|
||||
if (transforming)
|
||||
return
|
||||
for(var/obj/item/W in src)
|
||||
drop_from_inventory(W)
|
||||
regenerate_icons()
|
||||
transforming = 1
|
||||
canmove = 0
|
||||
icon = null
|
||||
invisibility = 101
|
||||
for(var/t in organs)
|
||||
qdel(t)
|
||||
|
||||
var/alien_caste = pick("Hunter","Sentinel","Drone")
|
||||
var/mob/living/carbon/human/new_xeno = create_new_xenomorph(alien_caste,loc)
|
||||
|
||||
new_xeno.a_intent = I_HURT
|
||||
new_xeno.key = key
|
||||
|
||||
new_xeno << "<B>You are now an alien.</B>"
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/slimeize(adult as num, reproduce as num)
|
||||
if (transforming)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user