Merge branch 'master' into upstream-merge-31176
This commit is contained in:
@@ -24,6 +24,9 @@
|
||||
loc = pick(GLOB.newplayer_start)
|
||||
else
|
||||
loc = locate(1,1,1)
|
||||
|
||||
ComponentInitialize()
|
||||
|
||||
. = ..()
|
||||
|
||||
/mob/dead/new_player/prepare_huds()
|
||||
@@ -375,7 +378,7 @@
|
||||
if(GLOB.highlander)
|
||||
to_chat(humanc, "<span class='userdanger'><i>THERE CAN BE ONLY ONE!!!</i></span>")
|
||||
humanc.make_scottish()
|
||||
if(prob(2) && !issilicon(humanc) && !jobban_isbanned(humanc.mind, "Syndicate") && GLOB.miscreants_allowed && ROLE_MISCREANT in humanc.client.prefs.be_special)
|
||||
if(prob(5) && !issilicon(humanc) && !jobban_isbanned(humanc.mind, "Syndicate") && GLOB.miscreants_allowed && ROLE_MISCREANT in humanc.client.prefs.be_special)
|
||||
SSticker.generate_miscreant_objectives(humanc.mind)
|
||||
else
|
||||
if(CONFIG_GET(flag/allow_crew_objectives))
|
||||
@@ -393,6 +396,8 @@
|
||||
if(SSshuttle.emergency.timeLeft(1) > initial(SSshuttle.emergencyCallTime)*0.5)
|
||||
SSticker.mode.make_antag_chance(humanc)
|
||||
|
||||
log_manifest(character.mind.key,character.mind,character,latejoin = TRUE)
|
||||
|
||||
/mob/dead/new_player/proc/AddEmploymentContract(mob/living/carbon/human/employee)
|
||||
//TODO: figure out a way to exclude wizards/nukeops/demons from this.
|
||||
for(var/C in GLOB.employmentCabinets)
|
||||
@@ -447,7 +452,8 @@
|
||||
dat += "<a class='[position_class]' href='byond://?src=\ref[src];SelectedJob=[job.title]'>[job.title] ([job.current_positions])</a><br>"
|
||||
if(!job_count) //if there's nowhere to go, assistant opens up.
|
||||
for(var/datum/job/job in SSjob.occupations)
|
||||
if(job.title != "Assistant") continue
|
||||
if(job.title != "Assistant")
|
||||
continue
|
||||
dat += "<a class='otherPosition' href='byond://?src=\ref[src];SelectedJob=[job.title]'>[job.title] ([job.current_positions])</a><br>"
|
||||
break
|
||||
dat += "</div></div>"
|
||||
@@ -474,6 +480,8 @@
|
||||
client.prefs.copy_to(H)
|
||||
H.dna.update_dna_identity()
|
||||
if(mind)
|
||||
if(transfer_after)
|
||||
mind.late_joiner = TRUE
|
||||
mind.active = 0 //we wish to transfer the key manually
|
||||
mind.transfer_to(H) //won't transfer key since the mind is not active
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
facial_hair_color = hair_color
|
||||
eye_color = random_eye_color()
|
||||
if(!pref_species)
|
||||
var/rando_race = pick(CONFIG_GET(keyed_flag_list/roundstart_races))
|
||||
var/rando_race = pick(GLOB.roundstart_races)
|
||||
pref_species = new rando_race()
|
||||
features = random_features()
|
||||
age = rand(AGE_MIN,AGE_MAX)
|
||||
@@ -59,7 +59,7 @@
|
||||
if(previewJob && !nude)
|
||||
mannequin.job = previewJob.title
|
||||
previewJob.equip(mannequin, TRUE)
|
||||
mannequin.compile_overlays()
|
||||
COMPILE_OVERLAYS(mannequin)
|
||||
CHECK_TICK
|
||||
preview_icon = icon('icons/effects/effects.dmi', "nothing")
|
||||
preview_icon.Scale(48+32, 16+32)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@
|
||||
name = "Bear"
|
||||
icon_state = "bear"
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
|
||||
|
||||
/datum/sprite_accessory/tails/human/bear
|
||||
name = "Bear"
|
||||
icon_state = "bear"
|
||||
@@ -65,7 +65,7 @@
|
||||
icon_state = "cow"
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
gender_specific = 1
|
||||
|
||||
|
||||
/datum/sprite_accessory/tails/human/cow
|
||||
name = "Cow"
|
||||
icon_state = "cow"
|
||||
@@ -175,21 +175,24 @@
|
||||
name = "Otusian"
|
||||
icon_state = "otie"
|
||||
hasinner= 1
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
|
||||
/datum/sprite_accessory/tails/human/otie
|
||||
name = "Otusian"
|
||||
icon_state = "otie"
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
|
||||
/datum/sprite_accessory/tails_animated/human/otie
|
||||
name = "Otusian"
|
||||
icon_state = "otie"
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
|
||||
/datum/sprite_accessory/ears/human/rabbit
|
||||
name = "Rabbit"
|
||||
icon_state = "rabbit"
|
||||
hasinner= 1
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
|
||||
|
||||
/datum/sprite_accessory/tails/human/rabbit
|
||||
name = "Rabbit"
|
||||
icon_state = "rabbit"
|
||||
@@ -201,10 +204,11 @@
|
||||
icon_state = "rabbit"
|
||||
color_src = 0
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
|
||||
|
||||
/datum/sprite_accessory/ears/human/skunk
|
||||
name = "skunk"
|
||||
icon_state = "skunk"
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
|
||||
/datum/sprite_accessory/tails/human/skunk
|
||||
name = "skunk"
|
||||
@@ -248,6 +252,7 @@
|
||||
name = "Wolf"
|
||||
icon_state = "wolf"
|
||||
hasinner = 1
|
||||
icon = 'icons/mob/mam_bodyparts.dmi'
|
||||
|
||||
/datum/sprite_accessory/tails/human/wolf
|
||||
name = "Wolf"
|
||||
@@ -341,7 +346,7 @@
|
||||
/datum/sprite_accessory/mam_ears/bear
|
||||
name = "Bear"
|
||||
icon_state = "bear"
|
||||
|
||||
|
||||
/datum/sprite_accessory/mam_tails/bear
|
||||
name = "Bear"
|
||||
icon_state = "bear"
|
||||
@@ -352,9 +357,9 @@
|
||||
|
||||
/datum/sprite_accessory/mam_ears/catbig
|
||||
name = "Cat, Big"
|
||||
icon_state = "cat"
|
||||
icon_state = "catbig"
|
||||
hasinner = 1
|
||||
|
||||
|
||||
/datum/sprite_accessory/mam_tails/catbig
|
||||
name = "Cat, Big"
|
||||
icon_state = "catbig"
|
||||
@@ -367,7 +372,7 @@
|
||||
name = "Cow"
|
||||
icon_state = "cow"
|
||||
gender_specific = 1
|
||||
|
||||
|
||||
/datum/sprite_accessory/mam_tail/cow
|
||||
name = "Cow"
|
||||
icon_state = "cow"
|
||||
@@ -522,7 +527,7 @@
|
||||
name = "Rabbit"
|
||||
icon_state = "rabbit"
|
||||
hasinner= 1
|
||||
|
||||
|
||||
/datum/sprite_accessory/mam_tails/rabbit
|
||||
name = "Rabbit"
|
||||
icon_state = "rabbit"
|
||||
|
||||
@@ -31,6 +31,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
var/mob/observetarget = null //The target mob that the ghost is observing. Used as a reference in logout()
|
||||
var/ghost_hud_enabled = 1 //did this ghost disable the on-screen HUD?
|
||||
var/data_huds_on = 0 //Are data HUDs currently enabled?
|
||||
var/health_scan = FALSE //Are health scans currently enabled?
|
||||
var/list/datahuds = list(DATA_HUD_SECURITY_ADVANCED, DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC) //list of data HUDs shown to ghosts.
|
||||
var/ghost_orbit = GHOST_ORBIT_CIRCLE
|
||||
|
||||
@@ -305,15 +306,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
/mob/dead/observer/is_active()
|
||||
return 0
|
||||
|
||||
/mob/dead/observer/Stat()
|
||||
..()
|
||||
if(statpanel("Status"))
|
||||
if(SSticker.HasRoundStarted())
|
||||
if(istype(SSticker.mode, /datum/game_mode/blob))
|
||||
var/datum/game_mode/blob/B = SSticker.mode
|
||||
if(B.message_sent)
|
||||
stat(null, "Blobs to Blob Win: [GLOB.blobs_legit.len]/[B.blobwincount]")
|
||||
|
||||
/mob/dead/observer/verb/reenter_corpse()
|
||||
set category = "Ghost"
|
||||
set name = "Re-enter Corpse"
|
||||
@@ -486,7 +478,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
set name = "Boo!"
|
||||
set desc= "Scare your crew members because of boredom!"
|
||||
|
||||
if(bootime > world.time) return
|
||||
if(bootime > world.time)
|
||||
return
|
||||
var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src)
|
||||
if(L)
|
||||
L.flicker()
|
||||
@@ -586,6 +579,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(src, "<span class='warning'>This creature is too powerful for you to possess!</span>")
|
||||
return 0
|
||||
|
||||
if(istype (target, /mob/living/simple_animal/hostile/spawner))
|
||||
to_chat(src, "<span class='warning'>This isn't really a creature, now is it!</span>")
|
||||
return 0
|
||||
|
||||
if(can_reenter_corpse && mind && mind.current)
|
||||
if(alert(src, "Your soul is still tied to your former life as [mind.current.name], if you go forward there is no going back to that life. Are you sure you wish to continue?", "Move On", "Yes", "No") == "No")
|
||||
return 0
|
||||
@@ -597,14 +594,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
target.faction = list("neutral")
|
||||
return 1
|
||||
|
||||
/proc/show_server_hop_transfer_screen(expected_key)
|
||||
//only show it to incoming ghosts
|
||||
for(var/mob/dead/observer/O in GLOB.player_list)
|
||||
if(O.key == expected_key)
|
||||
if(O.client)
|
||||
new /obj/screen/splash(O.client, TRUE)
|
||||
break
|
||||
|
||||
//this is a mob verb instead of atom for performance reasons
|
||||
//see /mob/verb/examinate() in mob.dm for more info
|
||||
//overriden here and in /mob/living for different point span classes and sanity checks
|
||||
@@ -626,7 +615,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
|
||||
//this is called when a ghost is drag clicked to something.
|
||||
/mob/dead/observer/MouseDrop(atom/over)
|
||||
if(!usr || !over) return
|
||||
if(!usr || !over)
|
||||
return
|
||||
if (isobserver(usr) && usr.client.holder && isliving(over))
|
||||
if (usr.client.holder.cmd_ghost_drag(src,over))
|
||||
return
|
||||
@@ -682,6 +672,18 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(src, "<span class='notice'>Data HUDs enabled.</span>")
|
||||
data_huds_on = 1
|
||||
|
||||
/mob/dead/observer/verb/toggle_health_scan()
|
||||
set name = "Toggle Health Scan"
|
||||
set desc = "Toggles whether you health-scan living beings on click"
|
||||
set category = "Ghost"
|
||||
|
||||
if(health_scan) //remove old huds
|
||||
to_chat(src, "<span class='notice'>Health scan disabled.</span>")
|
||||
health_scan = FALSE
|
||||
else
|
||||
to_chat(src, "<span class='notice'>Health scan enabled.</span>")
|
||||
health_scan = TRUE
|
||||
|
||||
/mob/dead/observer/verb/restore_ghost_appearance()
|
||||
set name = "Restore Ghost Character"
|
||||
set desc = "Sets your deadchat name and ghost appearance to your \
|
||||
|
||||
@@ -216,25 +216,23 @@
|
||||
. = list()
|
||||
if(!bloodtype)
|
||||
return
|
||||
switch(bloodtype)
|
||||
if("A-")
|
||||
return list("A-", "O-")
|
||||
if("A+")
|
||||
return list("A-", "A+", "O-", "O+")
|
||||
if("B-")
|
||||
return list("B-", "O-")
|
||||
if("B+")
|
||||
return list("B-", "B+", "O-", "O+")
|
||||
if("AB-")
|
||||
return list("A-", "B-", "O-", "AB-")
|
||||
if("AB+")
|
||||
return list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+")
|
||||
if("O-")
|
||||
return list("O-")
|
||||
if("O+")
|
||||
return list("O-", "O+")
|
||||
if("L")
|
||||
return list("L")
|
||||
|
||||
var/static/list/bloodtypes_safe = list(
|
||||
"A-" = list("A-", "O-"),
|
||||
"A+" = list("A-", "A+", "O-", "O+"),
|
||||
"B-" = list("B-", "O-"),
|
||||
"B+" = list("B-", "B+", "O-", "O+"),
|
||||
"AB-" = list("A-", "B-", "O-", "AB-"),
|
||||
"AB+" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+"),
|
||||
"O-" = list("O-"),
|
||||
"O+" = list("O-", "O+"),
|
||||
"L" = list("L"),
|
||||
"U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U")
|
||||
)
|
||||
|
||||
var/safe = bloodtypes_safe[bloodtype]
|
||||
if(safe)
|
||||
. = safe
|
||||
|
||||
//to add a splatter of blood or other mob liquid.
|
||||
/mob/living/proc/add_splatter_floor(turf/T, small_drip)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
/mob/living/brain/proc/create_dna()
|
||||
stored_dna = new /datum/dna/stored(src)
|
||||
if(!stored_dna.species)
|
||||
var/rando_race = pick(CONFIG_GET(keyed_flag_list/roundstart_races))
|
||||
var/rando_race = pick(GLOB.roundstart_races)
|
||||
stored_dna.species = new rando_race()
|
||||
|
||||
/mob/living/brain/Destroy()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
throw_range = 5
|
||||
layer = ABOVE_MOB_LAYER
|
||||
zone = "head"
|
||||
slot = "brain"
|
||||
slot = ORGAN_SLOT_BRAIN
|
||||
vital = TRUE
|
||||
origin_tech = "biotech=5"
|
||||
attack_verb = list("attacked", "slapped", "whacked")
|
||||
@@ -70,7 +70,7 @@
|
||||
C.dna.copy_dna(brainmob.stored_dna)
|
||||
if(L.disabilities & NOCLONE)
|
||||
brainmob.disabilities |= NOCLONE //This is so you can't just decapitate a husked guy and clone them without needing to get a new body
|
||||
var/obj/item/organ/zombie_infection/ZI = L.getorganslot("zombie_infection")
|
||||
var/obj/item/organ/zombie_infection/ZI = L.getorganslot(ORGAN_SLOT_ZOMBIE)
|
||||
if(ZI)
|
||||
brainmob.set_species(ZI.old_species) //For if the brain is cloned
|
||||
if(L.mind && L.mind.current)
|
||||
|
||||
@@ -61,7 +61,7 @@ Doesn't work on other aliens/AI.*/
|
||||
|
||||
/obj/effect/proc_holder/alien/plant
|
||||
name = "Plant Weeds"
|
||||
desc = "Plants some alien weeds"
|
||||
desc = "Plants some alien weeds."
|
||||
plasma_cost = 50
|
||||
check_turf = 1
|
||||
action_icon_state = "alien_plant"
|
||||
@@ -76,7 +76,7 @@ Doesn't work on other aliens/AI.*/
|
||||
|
||||
/obj/effect/proc_holder/alien/whisper
|
||||
name = "Whisper"
|
||||
desc = "Whisper to someone"
|
||||
desc = "Whisper to someone."
|
||||
plasma_cost = 10
|
||||
action_icon_state = "alien_whisper"
|
||||
|
||||
@@ -104,7 +104,7 @@ Doesn't work on other aliens/AI.*/
|
||||
|
||||
/obj/effect/proc_holder/alien/transfer
|
||||
name = "Transfer Plasma"
|
||||
desc = "Transfer Plasma to another alien"
|
||||
desc = "Transfer Plasma to another alien."
|
||||
plasma_cost = 0
|
||||
action_icon_state = "alien_transfer"
|
||||
|
||||
@@ -169,7 +169,8 @@ Doesn't work on other aliens/AI.*/
|
||||
return
|
||||
var/mob/living/carbon/user = usr
|
||||
var/obj/effect/proc_holder/alien/acid/A = locate() in user.abilities
|
||||
if(!A) return
|
||||
if(!A)
|
||||
return
|
||||
if(user.getPlasma() > A.plasma_cost && A.corrode(O))
|
||||
user.adjustPlasma(-A.plasma_cost)
|
||||
|
||||
@@ -214,8 +215,7 @@ Doesn't work on other aliens/AI.*/
|
||||
|
||||
user.visible_message("<span class='danger'>[user] spits neurotoxin!", "<span class='alertalien'>You spit neurotoxin.</span>")
|
||||
var/obj/item/projectile/bullet/neurotoxin/A = new /obj/item/projectile/bullet/neurotoxin(user.loc)
|
||||
A.current = U
|
||||
A.preparePixelProjectile(target, get_turf(target), user, params)
|
||||
A.preparePixelProjectile(target, user, params)
|
||||
A.fire()
|
||||
user.newtonian_move(get_dir(U, T))
|
||||
user.adjustPlasma(-p_cost)
|
||||
@@ -269,7 +269,7 @@ Doesn't work on other aliens/AI.*/
|
||||
|
||||
/obj/effect/proc_holder/alien/regurgitate
|
||||
name = "Regurgitate"
|
||||
desc = "Empties the contents of your stomach"
|
||||
desc = "Empties the contents of your stomach."
|
||||
plasma_cost = 0
|
||||
action_icon_state = "alien_barf"
|
||||
|
||||
@@ -306,13 +306,15 @@ Doesn't work on other aliens/AI.*/
|
||||
|
||||
/mob/living/carbon/proc/getPlasma()
|
||||
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
|
||||
if(!vessel) return 0
|
||||
if(!vessel)
|
||||
return 0
|
||||
return vessel.storedPlasma
|
||||
|
||||
|
||||
/mob/living/carbon/proc/adjustPlasma(amount)
|
||||
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
|
||||
if(!vessel) return 0
|
||||
if(!vessel)
|
||||
return 0
|
||||
vessel.storedPlasma = max(vessel.storedPlasma + amount,0)
|
||||
vessel.storedPlasma = min(vessel.storedPlasma, vessel.max_plasma) //upper limit of max_plasma, lower limit of 0
|
||||
for(var/X in abilities)
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
/mob/living/carbon/alien/Life()
|
||||
findQueen()
|
||||
return..()
|
||||
|
||||
/mob/living/carbon/alien/check_breath(datum/gas_mixture/breath)
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
if(!breath || (breath.total_moles() == 0))
|
||||
//Aliens breathe in vaccuum
|
||||
return 0
|
||||
|
||||
var/toxins_used = 0
|
||||
var/tox_detect_threshold = 0.02
|
||||
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
|
||||
var/list/breath_gases = breath.gases
|
||||
|
||||
breath.assert_gases("plasma", "o2")
|
||||
|
||||
//Partial pressure of the toxins in our breath
|
||||
var/Toxins_pp = (breath_gases["plasma"][MOLES]/breath.total_moles())*breath_pressure
|
||||
|
||||
if(Toxins_pp > tox_detect_threshold) // Detect toxins in air
|
||||
adjustPlasma(breath_gases["plasma"][MOLES]*250)
|
||||
throw_alert("alien_tox", /obj/screen/alert/alien_tox)
|
||||
|
||||
toxins_used = breath_gases["plasma"][MOLES]
|
||||
|
||||
else
|
||||
clear_alert("alien_tox")
|
||||
|
||||
//Breathe in toxins and out oxygen
|
||||
breath_gases["plasma"][MOLES] -= toxins_used
|
||||
breath_gases["o2"][MOLES] += toxins_used
|
||||
|
||||
breath.garbage_collect()
|
||||
|
||||
//BREATH TEMPERATURE
|
||||
handle_breath_temperature(breath)
|
||||
|
||||
/mob/living/carbon/alien/handle_status_effects()
|
||||
..()
|
||||
//natural reduction of movement delay due to stun.
|
||||
if(move_delay_add > 0)
|
||||
move_delay_add = max(0, move_delay_add - rand(1, 2))
|
||||
|
||||
/mob/living/carbon/alien/handle_changeling()
|
||||
return
|
||||
|
||||
/mob/living/carbon/alien/handle_fire()//Aliens on fire code
|
||||
if(..())
|
||||
return
|
||||
bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up!
|
||||
return
|
||||
/mob/living/carbon/alien/Life()
|
||||
findQueen()
|
||||
return..()
|
||||
|
||||
/mob/living/carbon/alien/check_breath(datum/gas_mixture/breath)
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
if(!breath || (breath.total_moles() == 0))
|
||||
//Aliens breathe in vaccuum
|
||||
return 0
|
||||
|
||||
var/toxins_used = 0
|
||||
var/tox_detect_threshold = 0.02
|
||||
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
|
||||
var/list/breath_gases = breath.gases
|
||||
|
||||
breath.assert_gases(/datum/gas/plasma, /datum/gas/oxygen)
|
||||
|
||||
//Partial pressure of the toxins in our breath
|
||||
var/Toxins_pp = (breath_gases[/datum/gas/plasma][MOLES]/breath.total_moles())*breath_pressure
|
||||
|
||||
if(Toxins_pp > tox_detect_threshold) // Detect toxins in air
|
||||
adjustPlasma(breath_gases[/datum/gas/plasma][MOLES]*250)
|
||||
throw_alert("alien_tox", /obj/screen/alert/alien_tox)
|
||||
|
||||
toxins_used = breath_gases[/datum/gas/plasma][MOLES]
|
||||
|
||||
else
|
||||
clear_alert("alien_tox")
|
||||
|
||||
//Breathe in toxins and out oxygen
|
||||
breath_gases[/datum/gas/plasma][MOLES] -= toxins_used
|
||||
breath_gases[/datum/gas/oxygen][MOLES] += toxins_used
|
||||
|
||||
breath.garbage_collect()
|
||||
|
||||
//BREATH TEMPERATURE
|
||||
handle_breath_temperature(breath)
|
||||
|
||||
/mob/living/carbon/alien/handle_status_effects()
|
||||
..()
|
||||
//natural reduction of movement delay due to stun.
|
||||
if(move_delay_add > 0)
|
||||
move_delay_add = max(0, move_delay_add - rand(1, 2))
|
||||
|
||||
/mob/living/carbon/alien/handle_changeling()
|
||||
return
|
||||
|
||||
/mob/living/carbon/alien/handle_fire()//Aliens on fire code
|
||||
if(..())
|
||||
return
|
||||
bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up!
|
||||
return
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/mob/living/proc/alien_talk(message, shown_name = real_name)
|
||||
log_talk(src,"[key_name(src)] : [message]",LOGSAY)
|
||||
message = trim(message)
|
||||
if(!message) return
|
||||
if(!message)
|
||||
return
|
||||
|
||||
var/message_a = say_quote(message, get_spans())
|
||||
var/rendered = "<i><span class='alien'>Hivemind, <span class='name'>[shown_name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
|
||||
@@ -7,19 +7,15 @@
|
||||
..()
|
||||
|
||||
/mob/living/carbon/Destroy()
|
||||
for(var/guts in internal_organs)
|
||||
qdel(guts)
|
||||
for(var/atom/movable/food in stomach_contents)
|
||||
qdel(food)
|
||||
for(var/BP in bodyparts)
|
||||
qdel(BP)
|
||||
for(var/imp in implants)
|
||||
qdel(imp)
|
||||
bodyparts = list()
|
||||
//This must be done first, so the mob ghosts correctly before DNA etc is nulled
|
||||
. = ..()
|
||||
|
||||
QDEL_LIST(internal_organs)
|
||||
QDEL_LIST(stomach_contents)
|
||||
QDEL_LIST(bodyparts)
|
||||
QDEL_LIST(implants)
|
||||
remove_from_all_data_huds()
|
||||
if(dna)
|
||||
qdel(dna)
|
||||
return ..()
|
||||
QDEL_NULL(dna)
|
||||
|
||||
/mob/living/carbon/relaymove(mob/user, direction)
|
||||
if(user in src.stomach_contents)
|
||||
@@ -228,7 +224,7 @@
|
||||
internal = null
|
||||
update_internals_hud_icon(0)
|
||||
else if(ITEM && istype(ITEM, /obj/item/tank))
|
||||
if((wear_mask && (wear_mask.flags_1 & MASKINTERNALS_1)) || getorganslot("breathing_tube"))
|
||||
if((wear_mask && (wear_mask.flags_1 & MASKINTERNALS_1)) || getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
internal = ITEM
|
||||
update_internals_hud_icon(1)
|
||||
|
||||
@@ -527,7 +523,7 @@
|
||||
|
||||
sight = initial(sight)
|
||||
lighting_alpha = initial(lighting_alpha)
|
||||
var/obj/item/organ/eyes/E = getorganslot("eye_sight")
|
||||
var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES)
|
||||
if(!E)
|
||||
update_tint()
|
||||
else
|
||||
@@ -584,7 +580,7 @@
|
||||
if(wear_mask)
|
||||
. += wear_mask.tint
|
||||
|
||||
var/obj/item/organ/eyes/E = getorganslot("eye_sight")
|
||||
var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES)
|
||||
if(E)
|
||||
. += E.tint
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
var/obj/item/clothing/mask/MFP = src.wear_mask
|
||||
number += MFP.flash_protect
|
||||
|
||||
var/obj/item/organ/eyes/E = getorganslot("eye_sight")
|
||||
var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES)
|
||||
if(!E)
|
||||
number = INFINITY //Can't get flashed without eyes
|
||||
else
|
||||
@@ -28,7 +28,7 @@
|
||||
number += 1
|
||||
if(head && (head.flags_2 & BANG_PROTECT_2))
|
||||
number += 1
|
||||
var/obj/item/organ/ears/E = getorganslot("ears")
|
||||
var/obj/item/organ/ears/E = getorganslot(ORGAN_SLOT_EARS)
|
||||
if(!E)
|
||||
number = INFINITY
|
||||
else
|
||||
@@ -130,10 +130,12 @@
|
||||
|
||||
|
||||
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
|
||||
for(var/thing in viruses)
|
||||
var/datum/disease/D = thing
|
||||
if(D.spread_flags & VIRUS_SPREAD_CONTACT_SKIN)
|
||||
M.ContactContractDisease(D)
|
||||
|
||||
if(can_inject(M, TRUE))
|
||||
for(var/thing in viruses)
|
||||
var/datum/disease/D = thing
|
||||
if((D.spread_flags & VIRUS_SPREAD_CONTACT_SKIN) && prob(85))
|
||||
M.ContactContractDisease(D)
|
||||
|
||||
for(var/thing in M.viruses)
|
||||
var/datum/disease/D = thing
|
||||
@@ -279,7 +281,7 @@
|
||||
|
||||
var/damage = intensity - get_eye_protection()
|
||||
if(.) // we've been flashed
|
||||
var/obj/item/organ/eyes/eyes = getorganslot("eye_sight")
|
||||
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
|
||||
if (!eyes)
|
||||
return
|
||||
if(visual)
|
||||
@@ -323,7 +325,7 @@
|
||||
|
||||
/mob/living/carbon/soundbang_act(intensity = 1, stun_pwr = 20, damage_pwr = 5, deafen_pwr = 15)
|
||||
var/ear_safety = get_ear_protection()
|
||||
var/obj/item/organ/ears/ears = getorganslot("ears")
|
||||
var/obj/item/organ/ears/ears = getorganslot(ORGAN_SLOT_EARS)
|
||||
var/effect_amount = intensity - ear_safety
|
||||
if(effect_amount > 0)
|
||||
if(stun_pwr)
|
||||
@@ -363,6 +365,6 @@
|
||||
|
||||
/mob/living/carbon/can_hear()
|
||||
. = FALSE
|
||||
var/obj/item/organ/ears/ears = getorganslot("ears")
|
||||
var/obj/item/organ/ears/ears = getorganslot(ORGAN_SLOT_EARS)
|
||||
if(istype(ears) && !ears.deaf)
|
||||
. = TRUE
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
return 1
|
||||
|
||||
// Do we have a jetpack implant (and is it on)?
|
||||
var/obj/item/organ/cyberimp/chest/thrusters/T = getorganslot("thrusters")
|
||||
var/obj/item/organ/cyberimp/chest/thrusters/T = getorganslot(ORGAN_SLOT_THRUSTERS)
|
||||
if(istype(T) && movement_dir && T.allow_thrust(0.01))
|
||||
return 1
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
if(getorgan(/obj/item/organ/brain))
|
||||
msg += "<span class='deadsay'>[t_He] [t_is] limp and unresponsive, with no signs of life.</span>\n"
|
||||
else if(get_bodypart("head"))
|
||||
msg += "<span class='deadsay'>[t_He] appears that [t_his] brain is missing...</span>\n"
|
||||
msg += "<span class='deadsay'>It appears that [t_his] brain is missing...</span>\n"
|
||||
|
||||
var/list/missing = get_missing_limbs()
|
||||
for(var/t in missing)
|
||||
@@ -64,12 +64,12 @@
|
||||
msg += "<b>[t_He] [t_is] severely deformed.</b>\n"
|
||||
|
||||
if(getBrainLoss() > 60)
|
||||
msg += "[t_He] seems to be clumsy and unable to think.\n"
|
||||
msg += "[t_He] seem[p_s()] to be clumsy and unable to think.\n"
|
||||
|
||||
if(fire_stacks > 0)
|
||||
msg += "[t_He] [t_is] covered in something flammable.\n"
|
||||
if(fire_stacks < 0)
|
||||
msg += "[t_He] [t_is] looks a little soaked.\n"
|
||||
msg += "[t_He] look[p_s()] a little soaked.\n"
|
||||
|
||||
if(pulledby && pulledby.grab_state)
|
||||
msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
if(stat == DEAD)
|
||||
return
|
||||
stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
var/obj/item/organ/heart/H = getorganslot("heart")
|
||||
var/obj/item/organ/heart/H = getorganslot(ORGAN_SLOT_HEART)
|
||||
if(H)
|
||||
H.beat = BEAT_NONE
|
||||
|
||||
|
||||
@@ -75,24 +75,54 @@
|
||||
/datum/emote/living/carbon/human/wag/run_emote(mob/user, params)
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(.)
|
||||
if(!H.is_wagging_tail())
|
||||
H.startTailWag()
|
||||
else
|
||||
H.endTailWag()
|
||||
|
||||
/mob/living/carbon/human/proc/is_wagging_tail()
|
||||
return (dna && dna.species && ("waggingtail_lizard" in dna.species.mutant_bodyparts || "waggingtail_human" in dna.species.mutant_bodyparts))
|
||||
|
||||
/datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE)
|
||||
if(!..())
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.dna && H.dna.species && ((H.dna.features["tail_lizard"] != "None") || (H.dna.features["tail_human"] != "None") || ("mam_tail" in H.dna.species.mutant_bodyparts)))
|
||||
if(H.dna && H.dna.species && (("tail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || (H.dna.features["tail_human"] != "None")))
|
||||
return TRUE
|
||||
|
||||
/datum/emote/living/carbon/human/wag/select_message_type(mob/user)
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_human" in H.dna.species.mutant_bodyparts) || ("mam_waggingtail" in H.dna.species.mutant_bodyparts))
|
||||
if(("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_human" in H.dna.species.mutant_bodyparts))
|
||||
. = null
|
||||
|
||||
//Don't know where else to put this, it's basically an emote
|
||||
/mob/living/carbon/human/proc/startTailWag()
|
||||
if(!dna || !dna.species)
|
||||
return
|
||||
if("tail_lizard" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "tail_lizard"
|
||||
dna.species.mutant_bodyparts -= "spines"
|
||||
dna.species.mutant_bodyparts |= "waggingtail_lizard"
|
||||
dna.species.mutant_bodyparts |= "waggingspines"
|
||||
if("tail_human" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "tail_human"
|
||||
dna.species.mutant_bodyparts |= "waggingtail_human"
|
||||
update_body()
|
||||
|
||||
/mob/living/carbon/human/proc/endTailWag()
|
||||
if(!dna || !dna.species)
|
||||
return
|
||||
if("waggingtail_lizard" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "waggingtail_lizard"
|
||||
dna.species.mutant_bodyparts -= "waggingspines"
|
||||
dna.species.mutant_bodyparts |= "tail_lizard"
|
||||
dna.species.mutant_bodyparts |= "spines"
|
||||
if("waggingtail_human" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "waggingtail_human"
|
||||
dna.species.mutant_bodyparts |= "tail_human"
|
||||
update_body()
|
||||
|
||||
/datum/emote/living/carbon/human/wing
|
||||
key = "wing"
|
||||
key_third_person = "wings"
|
||||
@@ -121,41 +151,7 @@
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.dna && H.dna.species && (H.dna.features["wings"] != "None"))
|
||||
return TRUE
|
||||
|
||||
//Don't know where else to put this, it's basically an emote
|
||||
/mob/living/carbon/human/proc/startTailWag()
|
||||
if(!dna || !dna.species)
|
||||
return
|
||||
if("tail_lizard" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "tail_lizard"
|
||||
dna.species.mutant_bodyparts -= "spines"
|
||||
dna.species.mutant_bodyparts |= "waggingtail_lizard"
|
||||
dna.species.mutant_bodyparts |= "waggingspines"
|
||||
if("tail_human" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "tail_human"
|
||||
dna.species.mutant_bodyparts |= "waggingtail_human"
|
||||
if("mam_tail" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "mam_tail"
|
||||
dna.species.mutant_bodyparts |= "mam_waggingtail"
|
||||
update_body()
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/endTailWag()
|
||||
if(!dna || !dna.species)
|
||||
return
|
||||
if("waggingtail_lizard" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "waggingtail_lizard"
|
||||
dna.species.mutant_bodyparts -= "waggingspines"
|
||||
dna.species.mutant_bodyparts |= "tail_lizard"
|
||||
dna.species.mutant_bodyparts |= "spines"
|
||||
if("waggingtail_human" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "waggingtail_human"
|
||||
dna.species.mutant_bodyparts |= "tail_human"
|
||||
if("mam_waggingtail" in dna.species.mutant_bodyparts)
|
||||
dna.species.mutant_bodyparts -= "mam_waggingtail"
|
||||
dna.species.mutant_bodyparts |= "mam_tail"
|
||||
update_body()
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/OpenWings()
|
||||
if(!dna || !dna.species)
|
||||
return
|
||||
|
||||
@@ -181,11 +181,11 @@
|
||||
msg += "<B>[capitalize(t_his)] [parse_zone(t)] is missing!</B>\n"
|
||||
|
||||
if(l_limbs_missing >= 2 && r_limbs_missing == 0)
|
||||
msg += "[t_He] looks all right now.\n"
|
||||
msg += "[t_He] look[p_s()] all right now.\n"
|
||||
else if(l_limbs_missing == 0 && r_limbs_missing >= 2)
|
||||
msg += "[t_He] really keeps to the left.\n"
|
||||
else if(l_limbs_missing >= 2 && r_limbs_missing >= 2)
|
||||
msg += "[t_He] doesn't seem all there.\n"
|
||||
msg += "[t_He] [p_do()]n't seem all there.\n"
|
||||
|
||||
if(temp)
|
||||
if(temp < 30)
|
||||
@@ -211,7 +211,7 @@
|
||||
if(fire_stacks > 0)
|
||||
msg += "[t_He] [t_is] covered in something flammable.\n"
|
||||
if(fire_stacks < 0)
|
||||
msg += "[t_He] looks a little soaked.\n"
|
||||
msg += "[t_He] look[p_s()] a little soaked.\n"
|
||||
|
||||
|
||||
if(pulledby && pulledby.grab_state)
|
||||
@@ -245,7 +245,7 @@
|
||||
msg += "<B>[t_He] [t_is] bleeding!</B>\n"
|
||||
|
||||
if(reagents.has_reagent("teslium"))
|
||||
msg += "[t_He] is emitting a gentle blue glow!\n"
|
||||
msg += "[t_He] [t_is] emitting a gentle blue glow!\n"
|
||||
|
||||
if(islist(stun_absorption))
|
||||
for(var/i in stun_absorption)
|
||||
@@ -261,9 +261,9 @@
|
||||
if(41.01 to 51)
|
||||
msg += "[t_He] [t_is] quite flushed and [t_his] breath smells of alcohol.\n"
|
||||
if(51.01 to 61)
|
||||
msg += "[t_He] is very flushed and [t_his] movements jerky, with breath reeking of alcohol.\n"
|
||||
msg += "[t_He] [t_is] very flushed and [t_his] movements jerky, with breath reeking of alcohol.\n"
|
||||
if(61.01 to 91)
|
||||
msg += "[t_He] looks like a drunken mess.\n"
|
||||
msg += "[t_He] look[p_s()] like a drunken mess.\n"
|
||||
if(91.01 to INFINITY)
|
||||
msg += "[t_He] [t_is] a shitfaced, slobbering wreck.\n"
|
||||
|
||||
@@ -276,17 +276,17 @@
|
||||
|
||||
if(!appears_dead)
|
||||
if(stat == UNCONSCIOUS)
|
||||
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n"
|
||||
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.\n"
|
||||
else
|
||||
if(getBrainLoss() >= 60)
|
||||
msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n"
|
||||
if(InCritical())
|
||||
msg += "[t_He] is barely conscious.\n"
|
||||
msg += "[t_He] [t_is] barely conscious.\n"
|
||||
if(getorgan(/obj/item/organ/brain))
|
||||
if(istype(src, /mob/living/carbon/human/interactive))
|
||||
var/mob/living/carbon/human/interactive/auto = src
|
||||
if(auto.showexaminetext)
|
||||
msg += "<span class='deadsay'>[t_He] [t_is] appears to be some sort of sick automaton, [t_his] eyes are glazed over and [t_his] mouth is slightly agape.</span>\n"
|
||||
msg += "<span class='deadsay'>[t_He] appear[p_s()] to be some sort of sick automaton, [t_his] eyes are glazed over and [t_his] mouth is slightly agape.</span>\n"
|
||||
if(auto.debugexamine)
|
||||
var/dodebug = auto.doing2string(auto.doing)
|
||||
var/interestdebug = auto.interest2string(auto.interest)
|
||||
|
||||
@@ -270,13 +270,13 @@
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/perpname = get_face_name(get_id_name(""))
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud))
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud))
|
||||
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general)
|
||||
if(href_list["photo_front"] || href_list["photo_side"])
|
||||
if(R)
|
||||
if(!H.canUseHUD())
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/medical))
|
||||
return
|
||||
var/obj/item/photo/P = null
|
||||
if(href_list["photo_front"])
|
||||
@@ -287,13 +287,13 @@
|
||||
P.show(H)
|
||||
|
||||
if(href_list["hud"] == "m")
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/medical))
|
||||
if(href_list["p_stat"])
|
||||
var/health_status = input(usr, "Specify a new physical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel")
|
||||
if(R)
|
||||
if(!H.canUseHUD())
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/medical))
|
||||
return
|
||||
if(health_status && health_status != "Cancel")
|
||||
R.fields["p_stat"] = health_status
|
||||
@@ -303,7 +303,7 @@
|
||||
if(R)
|
||||
if(!H.canUseHUD())
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/medical))
|
||||
return
|
||||
if(health_status && health_status != "Cancel")
|
||||
R.fields["m_stat"] = health_status
|
||||
@@ -352,7 +352,7 @@
|
||||
to_chat(usr, "<span class='danger'>Gathered data is inconsistent with the analysis, possible cause: poisoning.</span>")
|
||||
|
||||
if(href_list["hud"] == "s")
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
if(usr.stat || usr == src) //|| !usr.canmove || usr.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
|
||||
return //Non-fluff: This allows sec to set people to arrest as they get disarmed or beaten
|
||||
// Checks the user has security clearence before allowing them to change arrest status via hud, comment out to enable all access
|
||||
@@ -379,7 +379,7 @@
|
||||
if(setcriminal != "Cancel")
|
||||
if(R)
|
||||
if(H.canUseHUD())
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
investigate_log("[src.key] has been set from [R.fields["criminal"]] to [setcriminal] by [usr.name] ([usr.key]).", INVESTIGATE_RECORDS)
|
||||
R.fields["criminal"] = setcriminal
|
||||
sec_hud_set_security_status()
|
||||
@@ -389,7 +389,7 @@
|
||||
if(R)
|
||||
if(!H.canUseHUD())
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
to_chat(usr, "<b>Name:</b> [R.fields["name"]] <b>Criminal Status:</b> [R.fields["criminal"]]")
|
||||
to_chat(usr, "<b>Minor Crimes:</b>")
|
||||
@@ -418,7 +418,7 @@
|
||||
return
|
||||
else if(!H.canUseHUD())
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
|
||||
GLOB.data_core.addMinorCrime(R.fields["id"], crime)
|
||||
@@ -433,7 +433,7 @@
|
||||
return
|
||||
else if (!H.canUseHUD())
|
||||
return
|
||||
else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
|
||||
GLOB.data_core.addMajorCrime(R.fields["id"], crime)
|
||||
@@ -444,7 +444,7 @@
|
||||
if(R)
|
||||
if(!H.canUseHUD())
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
to_chat(usr, "<b>Comments/Log:</b>")
|
||||
var/counter = 1
|
||||
@@ -462,7 +462,7 @@
|
||||
return
|
||||
else if(!H.canUseHUD())
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
var/counter = 1
|
||||
while(R.fields[text("com_[]", counter)])
|
||||
@@ -637,7 +637,7 @@
|
||||
return 0
|
||||
|
||||
var/they_breathe = (!(NOBREATH in C.dna.species.species_traits))
|
||||
var/they_lung = C.getorganslot("lungs")
|
||||
var/they_lung = C.getorganslot(ORGAN_SLOT_LUNGS)
|
||||
|
||||
if(C.health > HEALTH_THRESHOLD_CRIT)
|
||||
return
|
||||
@@ -696,10 +696,10 @@
|
||||
|
||||
|
||||
/mob/living/carbon/human/wash_cream()
|
||||
//clean both to prevent a rare bug
|
||||
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_lizard"))
|
||||
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_human"))
|
||||
|
||||
if(creamed) //clean both to prevent a rare bug
|
||||
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_lizard"))
|
||||
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_human"))
|
||||
creamed = FALSE
|
||||
|
||||
//Turns a mob black, flashes a skeleton overlay
|
||||
//Just like a cartoon!
|
||||
@@ -710,7 +710,7 @@
|
||||
var/static/mutable_appearance/electrocution_skeleton_anim
|
||||
if(!electrocution_skeleton_anim)
|
||||
electrocution_skeleton_anim = mutable_appearance(icon, "electrocuted_base")
|
||||
electrocution_skeleton_anim.appearance_flags |= RESET_COLOR
|
||||
electrocution_skeleton_anim.appearance_flags |= RESET_COLOR|KEEP_APART
|
||||
add_overlay(electrocution_skeleton_anim)
|
||||
addtimer(CALLBACK(src, .proc/end_electrocution_animation, electrocution_skeleton_anim), anim_duration)
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.current = curloc
|
||||
P.firer = src
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
@@ -452,7 +451,7 @@
|
||||
siemens_coeff = gloves_siemens_coeff
|
||||
if(undergoing_cardiac_arrest() && !illusion)
|
||||
if(shock_damage * siemens_coeff >= 1 && prob(25))
|
||||
var/obj/item/organ/heart/heart = getorganslot("heart")
|
||||
var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART)
|
||||
heart.beating = TRUE
|
||||
if(stat == CONSCIOUS)
|
||||
to_chat(src, "<span class='notice'>You feel your heart beating again!</span>")
|
||||
|
||||
@@ -1,48 +1,50 @@
|
||||
/mob/living/carbon/human
|
||||
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
|
||||
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
|
||||
pressure_resistance = 25
|
||||
//Hair colour and style
|
||||
var/hair_color = "000"
|
||||
var/hair_style = "Bald"
|
||||
|
||||
//Facial hair colour and style
|
||||
var/facial_hair_color = "000"
|
||||
var/facial_hair_style = "Shaved"
|
||||
|
||||
//Eye colour
|
||||
var/eye_color = "000"
|
||||
|
||||
var/skin_tone = "caucasian1" //Skin tone
|
||||
|
||||
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
|
||||
var/lip_color = "white"
|
||||
|
||||
var/age = 30 //Player's age (pure fluff)
|
||||
|
||||
var/underwear = "Nude" //Which underwear the player wants
|
||||
var/undershirt = "Nude" //Which undershirt the player wants
|
||||
var/socks = "Nude" //Which socks the player wants
|
||||
var/backbag = DBACKPACK //Which backpack type the player has chosen.
|
||||
|
||||
//Equipment slots
|
||||
var/obj/item/wear_suit = null
|
||||
var/obj/item/w_uniform = null
|
||||
var/obj/item/belt = null
|
||||
var/obj/item/wear_id = null
|
||||
var/obj/item/r_store = null
|
||||
var/obj/item/l_store = null
|
||||
var/obj/item/s_store = null
|
||||
|
||||
var/special_voice = "" // For changing our voice. Used by a symptom.
|
||||
|
||||
var/bleed_rate = 0 //how much are we bleeding
|
||||
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
|
||||
|
||||
var/name_override //For temporary visible name changes
|
||||
|
||||
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
|
||||
var/datum/personal_crafting/handcrafting
|
||||
can_buckle = TRUE
|
||||
buckle_lying = FALSE
|
||||
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)
|
||||
/mob/living/carbon/human
|
||||
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
|
||||
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
|
||||
pressure_resistance = 25
|
||||
//Hair colour and style
|
||||
var/hair_color = "000"
|
||||
var/hair_style = "Bald"
|
||||
|
||||
//Facial hair colour and style
|
||||
var/facial_hair_color = "000"
|
||||
var/facial_hair_style = "Shaved"
|
||||
|
||||
//Eye colour
|
||||
var/eye_color = "000"
|
||||
|
||||
var/skin_tone = "caucasian1" //Skin tone
|
||||
|
||||
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
|
||||
var/lip_color = "white"
|
||||
|
||||
var/age = 30 //Player's age (pure fluff)
|
||||
|
||||
var/underwear = "Nude" //Which underwear the player wants
|
||||
var/undershirt = "Nude" //Which undershirt the player wants
|
||||
var/socks = "Nude" //Which socks the player wants
|
||||
var/backbag = DBACKPACK //Which backpack type the player has chosen.
|
||||
|
||||
//Equipment slots
|
||||
var/obj/item/wear_suit = null
|
||||
var/obj/item/w_uniform = null
|
||||
var/obj/item/belt = null
|
||||
var/obj/item/wear_id = null
|
||||
var/obj/item/r_store = null
|
||||
var/obj/item/l_store = null
|
||||
var/obj/item/s_store = null
|
||||
|
||||
var/special_voice = "" // For changing our voice. Used by a symptom.
|
||||
|
||||
var/bleed_rate = 0 //how much are we bleeding
|
||||
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
|
||||
|
||||
var/name_override //For temporary visible name changes
|
||||
|
||||
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
|
||||
var/datum/personal_crafting/handcrafting
|
||||
can_buckle = TRUE
|
||||
buckle_lying = FALSE
|
||||
|
||||
var/creamed = FALSE //to use with creampie overlays
|
||||
var/static/list/can_ride_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot))
|
||||
|
||||
@@ -45,14 +45,15 @@
|
||||
return
|
||||
else
|
||||
//No oldFP or it's a different kind of blood
|
||||
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP)
|
||||
var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
|
||||
FP.blood_state = S.blood_state
|
||||
FP.entered_dirs |= dir
|
||||
FP.bloodiness = S.bloody_shoes[S.blood_state]
|
||||
if(S.blood_DNA && S.blood_DNA.len)
|
||||
FP.transfer_blood_dna(S.blood_DNA)
|
||||
FP.update_icon()
|
||||
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP)
|
||||
if (S.bloody_shoes[S.blood_state] > BLOOD_LOSS_IN_SPREAD)
|
||||
var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
|
||||
FP.blood_state = S.blood_state
|
||||
FP.entered_dirs |= dir
|
||||
FP.bloodiness = S.bloody_shoes[S.blood_state] - BLOOD_LOSS_IN_SPREAD
|
||||
if(S.blood_DNA && S.blood_DNA.len)
|
||||
FP.transfer_blood_dna(S.blood_DNA)
|
||||
FP.update_icon()
|
||||
update_inv_shoes()
|
||||
//End bloody footprints
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
/mob/living/carbon/human/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
|
||||
if((C.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || (initial(C.flags_inv) & (HIDEHAIR|HIDEFACIALHAIR)))
|
||||
update_hair()
|
||||
if(toggle_off && internal && !getorganslot("breathing_tube"))
|
||||
if(toggle_off && internal && !getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
update_internals_hud_icon(0)
|
||||
internal = null
|
||||
if(C.flags_inv & HIDEEYES)
|
||||
@@ -265,7 +265,6 @@
|
||||
//delete all equipment without dropping anything
|
||||
/mob/living/carbon/human/proc/delete_equipment()
|
||||
for(var/slot in get_all_slots())//order matters, dependant slots go first
|
||||
var/obj/item/I = get_item_by_slot(slot)
|
||||
qdel(I)
|
||||
qdel(slot)
|
||||
for(var/obj/item/I in held_items)
|
||||
qdel(I)
|
||||
qdel(I)
|
||||
|
||||
@@ -59,6 +59,8 @@
|
||||
return ONE_ATMOSPHERE
|
||||
if(ismob(loc))
|
||||
return ONE_ATMOSPHERE
|
||||
if(istype(loc, /obj/item/device/dogborg/sleeper))
|
||||
return ONE_ATMOSPHERE
|
||||
else
|
||||
return pressure
|
||||
|
||||
@@ -91,7 +93,7 @@
|
||||
#define HUMAN_CRIT_MAX_OXYLOSS (SSmobs.wait/30)
|
||||
/mob/living/carbon/human/check_breath(datum/gas_mixture/breath)
|
||||
|
||||
var/L = getorganslot("lungs")
|
||||
var/L = getorganslot(ORGAN_SLOT_LUNGS)
|
||||
|
||||
if(!L)
|
||||
if(health >= HEALTH_THRESHOLD_CRIT)
|
||||
@@ -133,6 +135,12 @@
|
||||
|
||||
/mob/living/carbon/human/proc/get_thermal_protection()
|
||||
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
|
||||
|
||||
if(istype(loc, /obj/item/device/dogborg/sleeper))
|
||||
return FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
|
||||
if(ismob(loc))
|
||||
return FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
|
||||
|
||||
if(wear_suit)
|
||||
if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT)
|
||||
thermal_protection += (wear_suit.max_heat_protection_temperature*0.7)
|
||||
@@ -244,7 +252,9 @@
|
||||
|
||||
if(dna && (RESISTCOLD in dna.species.species_traits))
|
||||
return 1
|
||||
|
||||
|
||||
if(istype(loc, /obj/item/device/dogborg/sleeper))
|
||||
return 1 //freezing to death in sleepers ruins fun.
|
||||
if(ismob(loc))
|
||||
return 1 //because lazy and being inside somemone insulates you from space
|
||||
|
||||
@@ -328,7 +338,7 @@
|
||||
/mob/living/carbon/human/proc/undergoing_cardiac_arrest()
|
||||
if(!can_heartattack())
|
||||
return FALSE
|
||||
var/obj/item/organ/heart/heart = getorganslot("heart")
|
||||
var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART)
|
||||
if(istype(heart) && heart.beating)
|
||||
return FALSE
|
||||
return TRUE
|
||||
@@ -337,7 +347,7 @@
|
||||
if(!can_heartattack())
|
||||
return FALSE
|
||||
|
||||
var/obj/item/organ/heart/heart = getorganslot("heart")
|
||||
var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART)
|
||||
if(!istype(heart))
|
||||
return
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
for(var/i=1, ((i <= D.stage) && (i <= temp_message.len)), i++) //Loop for each stage of the disease or until we run out of words
|
||||
if(prob(3 * D.stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12%
|
||||
var/H = pick(pick_list)
|
||||
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue
|
||||
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":"))
|
||||
continue
|
||||
temp_message[H] = "HONK"
|
||||
pick_list -= H //Make sure that you dont HONK the same word twice
|
||||
message = jointext(temp_message, " ")
|
||||
@@ -48,7 +49,7 @@
|
||||
CHECK_DNA_AND_SPECIES(src)
|
||||
|
||||
// how do species that don't breathe talk? magic, that's what.
|
||||
if(!(NOBREATH in dna.species.species_traits) && !getorganslot("lungs"))
|
||||
if(!(NOBREATH in dna.species.species_traits) && !getorganslot(ORGAN_SLOT_LUNGS))
|
||||
return 0
|
||||
if(mind)
|
||||
return !mind.miming
|
||||
@@ -69,8 +70,10 @@
|
||||
/mob/living/carbon/human/binarycheck()
|
||||
if(ears)
|
||||
var/obj/item/device/radio/headset/dongle = ears
|
||||
if(!istype(dongle)) return 0
|
||||
if(dongle.translate_binary) return 1
|
||||
if(!istype(dongle))
|
||||
return 0
|
||||
if(dongle.translate_binary)
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/radio(message, message_mode, list/spans, language)
|
||||
. = ..()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// This code handles different species in the game.
|
||||
|
||||
GLOBAL_LIST_EMPTY(roundstart_races)
|
||||
|
||||
#define HEAT_DAMAGE_LEVEL_1 2
|
||||
#define HEAT_DAMAGE_LEVEL_2 3
|
||||
#define HEAT_DAMAGE_LEVEL_3 8
|
||||
@@ -8,18 +10,15 @@
|
||||
#define COLD_DAMAGE_LEVEL_2 1.5
|
||||
#define COLD_DAMAGE_LEVEL_3 3
|
||||
|
||||
|
||||
/datum/species
|
||||
var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this
|
||||
var/limbs_id //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans.
|
||||
var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
|
||||
var/roundstart = 0 // can this mob be chosen at roundstart? (assuming the config option is checked?)
|
||||
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
|
||||
|
||||
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
|
||||
|
||||
var/face_y_offset = 0
|
||||
var/hair_y_offset = 0
|
||||
var/list/offset_features = list(OFFSET_UNIFORM = list(0,0), OFFSET_ID = list(0,0), OFFSET_GLOVES = list(0,0), OFFSET_GLASSES = list(0,0), OFFSET_EARS = list(0,0), OFFSET_SHOES = list(0,0), OFFSET_S_STORE = list(0,0), OFFSET_FACEMASK = list(0,0), OFFSET_HEAD = list(0,0), OFFSET_FACE = list(0,0), OFFSET_BELT = list(0,0), OFFSET_BACK = list(0,0), OFFSET_SUIT = list(0,0), OFFSET_NECK = list(0,0))
|
||||
|
||||
var/hair_color // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
|
||||
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
|
||||
@@ -66,10 +65,8 @@
|
||||
var/obj/item/organ/lungs/mutantlungs = null
|
||||
var/breathid = "o2"
|
||||
|
||||
//Flight and floating
|
||||
var/override_float = 0
|
||||
|
||||
var/obj/item/organ/brain/mutant_brain = /obj/item/organ/brain
|
||||
var/obj/item/organ/heart/mutant_heart = /obj/item/organ/heart
|
||||
var/obj/item/organ/eyes/mutanteyes = /obj/item/organ/eyes
|
||||
var/obj/item/organ/ears/mutantears = /obj/item/organ/ears
|
||||
var/obj/item/mutanthands
|
||||
@@ -77,6 +74,7 @@
|
||||
|
||||
var/obj/item/organ/liver/mutantliver
|
||||
var/obj/item/organ/stomach/mutantstomach
|
||||
var/override_float = FALSE
|
||||
|
||||
//Citadel snowflake
|
||||
var/fixed_mut_color2 = ""
|
||||
@@ -96,6 +94,20 @@
|
||||
..()
|
||||
|
||||
|
||||
/proc/generate_selectable_species()
|
||||
for(var/I in subtypesof(/datum/species))
|
||||
var/datum/species/S = new I
|
||||
if(S.check_roundstart_eligible())
|
||||
GLOB.roundstart_races += S.id
|
||||
qdel(S)
|
||||
if(!GLOB.roundstart_races.len)
|
||||
GLOB.roundstart_races += "human"
|
||||
|
||||
/datum/species/proc/check_roundstart_eligible()
|
||||
if(id in (CONFIG_GET(keyed_flag_list/roundstart_races)))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/species/proc/random_name(gender,unique,lastname)
|
||||
if(unique)
|
||||
return random_unique_name(gender)
|
||||
@@ -126,15 +138,15 @@
|
||||
|
||||
//Will regenerate missing organs
|
||||
/datum/species/proc/regenerate_organs(mob/living/carbon/C,datum/species/old_species,replace_current=TRUE)
|
||||
var/obj/item/organ/brain/brain = C.getorganslot("brain")
|
||||
var/obj/item/organ/heart/heart = C.getorganslot("heart")
|
||||
var/obj/item/organ/lungs/lungs = C.getorganslot("lungs")
|
||||
var/obj/item/organ/appendix/appendix = C.getorganslot("appendix")
|
||||
var/obj/item/organ/eyes/eyes = C.getorganslot("eye_sight")
|
||||
var/obj/item/organ/ears/ears = C.getorganslot("ears")
|
||||
var/obj/item/organ/tongue/tongue = C.getorganslot("tongue")
|
||||
var/obj/item/organ/liver/liver = C.getorganslot("liver")
|
||||
var/obj/item/organ/stomach/stomach = C.getorganslot("stomach")
|
||||
var/obj/item/organ/brain/brain = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
var/obj/item/organ/heart/heart = C.getorganslot(ORGAN_SLOT_HEART)
|
||||
var/obj/item/organ/lungs/lungs = C.getorganslot(ORGAN_SLOT_LUNGS)
|
||||
var/obj/item/organ/appendix/appendix = C.getorganslot(ORGAN_SLOT_APPENDIX)
|
||||
var/obj/item/organ/eyes/eyes = C.getorganslot(ORGAN_SLOT_EYES)
|
||||
var/obj/item/organ/ears/ears = C.getorganslot(ORGAN_SLOT_EARS)
|
||||
var/obj/item/organ/tongue/tongue = C.getorganslot(ORGAN_SLOT_TONGUE)
|
||||
var/obj/item/organ/liver/liver = C.getorganslot(ORGAN_SLOT_LIVER)
|
||||
var/obj/item/organ/stomach/stomach = C.getorganslot(ORGAN_SLOT_STOMACH)
|
||||
|
||||
var/should_have_brain = TRUE
|
||||
var/should_have_heart = !(NOBLOOD in species_traits)
|
||||
@@ -158,7 +170,7 @@
|
||||
heart.Remove(C,1)
|
||||
QDEL_NULL(heart)
|
||||
if(should_have_heart && !heart)
|
||||
heart = new()
|
||||
heart = new mutant_heart()
|
||||
heart.Insert(C)
|
||||
|
||||
if(lungs && (replace_current || !should_have_lungs))
|
||||
@@ -265,11 +277,11 @@
|
||||
C.dropItemToGround(I)
|
||||
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
|
||||
C.put_in_hands(new mutanthands())
|
||||
|
||||
|
||||
if(VIRUSIMMUNE in species_traits)
|
||||
for(var/datum/disease/A in C.viruses)
|
||||
A.cure(FALSE)
|
||||
|
||||
|
||||
|
||||
if(NOAROUSAL in species_traits)
|
||||
C.canbearoused = FALSE
|
||||
@@ -413,7 +425,9 @@
|
||||
else
|
||||
hair_overlay.color = forced_colour
|
||||
hair_overlay.alpha = hair_alpha
|
||||
hair_overlay.pixel_y += hair_y_offset
|
||||
if(OFFSET_FACE in H.dna.species.offset_features)
|
||||
hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
|
||||
hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
|
||||
if(hair_overlay.icon)
|
||||
standing += hair_overlay
|
||||
|
||||
@@ -434,14 +448,18 @@
|
||||
if(H.lip_style && (LIPS in species_traits) && HD)
|
||||
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER)
|
||||
lip_overlay.color = H.lip_color
|
||||
lip_overlay.pixel_y += face_y_offset
|
||||
if(OFFSET_FACE in H.dna.species.offset_features)
|
||||
lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
|
||||
lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
|
||||
standing += lip_overlay
|
||||
|
||||
// eyes
|
||||
if((EYECOLOR in species_traits) && HD)
|
||||
var/mutable_appearance/eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
|
||||
eye_overlay.color = "#" + H.eye_color
|
||||
eye_overlay.pixel_y += face_y_offset
|
||||
if(OFFSET_FACE in H.dna.species.offset_features)
|
||||
eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
|
||||
eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
|
||||
standing += eye_overlay
|
||||
|
||||
//Underwear, Undershirts & Socks
|
||||
@@ -1135,36 +1153,33 @@
|
||||
return 0
|
||||
|
||||
/datum/species/proc/handle_mutations_and_radiation(mob/living/carbon/human/H)
|
||||
. = FALSE
|
||||
var/radiation = H.radiation
|
||||
|
||||
if(!(RADIMMUNE in species_traits))
|
||||
if(H.radiation)
|
||||
if (H.radiation > 100)
|
||||
if(!H.IsKnockdown())
|
||||
H.emote("collapse")
|
||||
H.Knockdown(200)
|
||||
to_chat(H, "<span class='danger'>You feel weak.</span>")
|
||||
switch(H.radiation)
|
||||
if(50 to 75)
|
||||
if(prob(5))
|
||||
if(!H.IsKnockdown())
|
||||
H.emote("collapse")
|
||||
H.Knockdown(60)
|
||||
to_chat(H, "<span class='danger'>You feel weak.</span>")
|
||||
if(RADIMMUNE in species_traits)
|
||||
radiation = 0
|
||||
return TRUE
|
||||
|
||||
if(prob(15))
|
||||
if(!( H.hair_style == "Shaved") || !(H.hair_style == "Bald") || (HAIR in species_traits))
|
||||
to_chat(H, "<span class='danger'>Your hair starts to fall out in clumps...</span>")
|
||||
addtimer(CALLBACK(src, .proc/go_bald, H), 50)
|
||||
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
|
||||
if(!H.IsKnockdown())
|
||||
H.emote("collapse")
|
||||
H.Knockdown(RAD_MOB_KNOCKDOWN_AMOUNT)
|
||||
to_chat(H, "<span class='danger'>You feel weak.</span>")
|
||||
|
||||
if(75 to 100)
|
||||
if(prob(1))
|
||||
to_chat(H, "<span class='danger'>You mutate!</span>")
|
||||
H.randmutb()
|
||||
H.emote("gasp")
|
||||
H.domutcheck()
|
||||
return 0
|
||||
H.radiation = 0
|
||||
return 1
|
||||
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
|
||||
H.vomit(10, TRUE)
|
||||
|
||||
if(radiation > RAD_MOB_MUTATE)
|
||||
if(prob(1))
|
||||
to_chat(H, "<span class='danger'>You mutate!</span>")
|
||||
H.randmutb()
|
||||
H.emote("gasp")
|
||||
H.domutcheck()
|
||||
|
||||
if(radiation > RAD_MOB_HAIRLOSS)
|
||||
if(prob(15) && !(H.hair_style == "Bald") && (HAIR in species_traits))
|
||||
to_chat(H, "<span class='danger'>Your hair starts to fall out in clumps...</span>")
|
||||
addtimer(CALLBACK(src, .proc/go_bald, H), 50)
|
||||
|
||||
/datum/species/proc/go_bald(mob/living/carbon/human/H)
|
||||
if(QDELETED(H)) //may be called from a timer
|
||||
@@ -1205,7 +1220,7 @@
|
||||
if(!gravity)
|
||||
var/obj/item/tank/jetpack/J = H.back
|
||||
var/obj/item/clothing/suit/space/hardsuit/C = H.wear_suit
|
||||
var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot("thrusters")
|
||||
var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot(ORGAN_SLOT_THRUSTERS)
|
||||
if(!istype(J) && istype(C))
|
||||
J = C.jetpack
|
||||
if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking
|
||||
@@ -1261,7 +1276,7 @@
|
||||
return 1
|
||||
else
|
||||
var/we_breathe = (!(NOBREATH in user.dna.species.species_traits))
|
||||
var/we_lung = user.getorganslot("lungs")
|
||||
var/we_lung = user.getorganslot(ORGAN_SLOT_LUNGS)
|
||||
|
||||
if(we_breathe && we_lung)
|
||||
user.do_cpr(target)
|
||||
@@ -1482,7 +1497,9 @@
|
||||
H.adjust_blurriness(10)
|
||||
|
||||
if(prob(I.force + ((100 - H.health)/2)) && H != user)
|
||||
SSticker.mode.remove_revolutionary(H.mind, FALSE, user)
|
||||
var/datum/antagonist/rev/rev = H.mind.has_antag_datum(/datum/antagonist/rev)
|
||||
if(rev)
|
||||
rev.remove_revolutionary(FALSE, user)
|
||||
|
||||
if(bloody) //Apply blood
|
||||
if(H.wear_mask)
|
||||
@@ -1763,4 +1780,4 @@
|
||||
|
||||
#undef COLD_DAMAGE_LEVEL_1
|
||||
#undef COLD_DAMAGE_LEVEL_2
|
||||
#undef COLD_DAMAGE_LEVEL_3
|
||||
#undef COLD_DAMAGE_LEVEL_3
|
||||
|
||||
@@ -1,139 +1,139 @@
|
||||
/datum/species/angel
|
||||
name = "Angel"
|
||||
id = "angel"
|
||||
default_color = "FFFFFF"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
|
||||
mutant_bodyparts = list("tail_human", "ears", "wings")
|
||||
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "Angel")
|
||||
use_skintones = 1
|
||||
no_equip = list(slot_back)
|
||||
blacklisted = 1
|
||||
limbs_id = "human"
|
||||
skinned_type = /obj/item/stack/sheet/animalhide/human
|
||||
|
||||
var/datum/action/innate/flight/fly
|
||||
|
||||
/datum/species/angel/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
|
||||
..()
|
||||
if(H.dna && H.dna.species &&((H.dna.features["wings"] != "Angel") && ("wings" in H.dna.species.mutant_bodyparts)))
|
||||
H.dna.features["wings"] = "Angel"
|
||||
H.update_body()
|
||||
if(ishuman(H) && !fly)
|
||||
fly = new
|
||||
fly.Grant(H)
|
||||
|
||||
/datum/species/angel/on_species_loss(mob/living/carbon/human/H)
|
||||
if(fly)
|
||||
fly.Remove(H)
|
||||
if(H.movement_type & FLYING)
|
||||
H.movement_type &= ~FLYING
|
||||
ToggleFlight(H,0)
|
||||
if(H.dna && H.dna.species &&((H.dna.features["wings"] != "None") && ("wings" in H.dna.species.mutant_bodyparts)))
|
||||
H.dna.features["wings"] = "None"
|
||||
H.update_body()
|
||||
..()
|
||||
|
||||
/datum/species/angel/spec_life(mob/living/carbon/human/H)
|
||||
HandleFlight(H)
|
||||
|
||||
/datum/species/angel/proc/HandleFlight(mob/living/carbon/human/H)
|
||||
if(H.movement_type & FLYING)
|
||||
if(!CanFly(H))
|
||||
ToggleFlight(H,0)
|
||||
return 0
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/datum/species/angel/proc/CanFly(mob/living/carbon/human/H)
|
||||
if(H.stat || H.IsStun() || H.IsKnockdown())
|
||||
return 0
|
||||
if(H.wear_suit && ((H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) //Jumpsuits have tail holes, so it makes sense they have wing holes too
|
||||
to_chat(H, "Your suit blocks your wings from extending!")
|
||||
return 0
|
||||
var/turf/T = get_turf(H)
|
||||
if(!T)
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
if(environment && !(environment.return_pressure() > 30))
|
||||
to_chat(H, "<span class='warning'>The atmosphere is too thin for you to fly!</span>")
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
|
||||
/datum/action/innate/flight
|
||||
name = "Toggle Flight"
|
||||
check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUN
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "flight"
|
||||
|
||||
/datum/action/innate/flight/Activate()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/datum/species/angel/A = H.dna.species
|
||||
if(A.CanFly(H))
|
||||
if(H.movement_type & FLYING)
|
||||
to_chat(H, "<span class='notice'>You settle gently back onto the ground...</span>")
|
||||
A.ToggleFlight(H,0)
|
||||
H.update_canmove()
|
||||
else
|
||||
to_chat(H, "<span class='notice'>You beat your wings and begin to hover gently above the ground...</span>")
|
||||
H.resting = 0
|
||||
A.ToggleFlight(H,1)
|
||||
H.update_canmove()
|
||||
|
||||
/datum/species/angel/proc/flyslip(mob/living/carbon/human/H)
|
||||
var/obj/buckled_obj
|
||||
if(H.buckled)
|
||||
buckled_obj = H.buckled
|
||||
|
||||
to_chat(H, "<span class='notice'>Your wings spazz out and launch you!</span>")
|
||||
|
||||
playsound(H.loc, 'sound/misc/slip.ogg', 50, 1, -3)
|
||||
|
||||
for(var/obj/item/I in H.held_items)
|
||||
H.accident(I)
|
||||
|
||||
var/olddir = H.dir
|
||||
|
||||
H.stop_pulling()
|
||||
if(buckled_obj)
|
||||
buckled_obj.unbuckle_mob(H)
|
||||
step(buckled_obj, olddir)
|
||||
else
|
||||
for(var/i=1, i<5, i++)
|
||||
spawn (i)
|
||||
step(H, olddir)
|
||||
H.spin(1,1)
|
||||
return 1
|
||||
|
||||
|
||||
/datum/species/angel/spec_stun(mob/living/carbon/human/H,amount)
|
||||
if(H.movement_type & FLYING)
|
||||
ToggleFlight(H,0)
|
||||
flyslip(H)
|
||||
. = ..()
|
||||
|
||||
/datum/species/angel/negates_gravity(mob/living/carbon/human/H)
|
||||
if(H.movement_type & FLYING)
|
||||
return 1
|
||||
|
||||
/datum/species/angel/space_move(mob/living/carbon/human/H)
|
||||
if(H.movement_type & FLYING)
|
||||
return 1
|
||||
|
||||
/datum/species/angel/proc/ToggleFlight(mob/living/carbon/human/H,flight)
|
||||
if(flight && CanFly(H))
|
||||
stunmod = 2
|
||||
speedmod = -1
|
||||
H.movement_type |= FLYING
|
||||
override_float = 1
|
||||
H.pass_flags |= PASSTABLE
|
||||
H.OpenWings()
|
||||
else
|
||||
stunmod = 1
|
||||
speedmod = 0
|
||||
H.movement_type &= ~FLYING
|
||||
override_float = 0
|
||||
H.pass_flags &= ~PASSTABLE
|
||||
H.CloseWings()
|
||||
/datum/species/angel
|
||||
name = "Angel"
|
||||
id = "angel"
|
||||
default_color = "FFFFFF"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
|
||||
mutant_bodyparts = list("tail_human", "ears", "wings")
|
||||
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "Angel")
|
||||
use_skintones = 1
|
||||
no_equip = list(slot_back)
|
||||
blacklisted = 1
|
||||
limbs_id = "human"
|
||||
skinned_type = /obj/item/stack/sheet/animalhide/human
|
||||
|
||||
var/datum/action/innate/flight/fly
|
||||
|
||||
/datum/species/angel/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
|
||||
..()
|
||||
if(H.dna && H.dna.species &&((H.dna.features["wings"] != "Angel") && ("wings" in H.dna.species.mutant_bodyparts)))
|
||||
H.dna.features["wings"] = "Angel"
|
||||
H.update_body()
|
||||
if(ishuman(H) && !fly)
|
||||
fly = new
|
||||
fly.Grant(H)
|
||||
|
||||
/datum/species/angel/on_species_loss(mob/living/carbon/human/H)
|
||||
if(fly)
|
||||
fly.Remove(H)
|
||||
if(H.movement_type & FLYING)
|
||||
H.movement_type &= ~FLYING
|
||||
ToggleFlight(H,0)
|
||||
if(H.dna && H.dna.species &&((H.dna.features["wings"] != "None") && ("wings" in H.dna.species.mutant_bodyparts)))
|
||||
H.dna.features["wings"] = "None"
|
||||
H.update_body()
|
||||
..()
|
||||
|
||||
/datum/species/angel/spec_life(mob/living/carbon/human/H)
|
||||
HandleFlight(H)
|
||||
|
||||
/datum/species/angel/proc/HandleFlight(mob/living/carbon/human/H)
|
||||
if(H.movement_type & FLYING)
|
||||
if(!CanFly(H))
|
||||
ToggleFlight(H,0)
|
||||
return 0
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/datum/species/angel/proc/CanFly(mob/living/carbon/human/H)
|
||||
if(H.stat || H.IsStun() || H.IsKnockdown())
|
||||
return 0
|
||||
if(H.wear_suit && ((H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) //Jumpsuits have tail holes, so it makes sense they have wing holes too
|
||||
to_chat(H, "Your suit blocks your wings from extending!")
|
||||
return 0
|
||||
var/turf/T = get_turf(H)
|
||||
if(!T)
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
if(environment && !(environment.return_pressure() > 30))
|
||||
to_chat(H, "<span class='warning'>The atmosphere is too thin for you to fly!</span>")
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
|
||||
/datum/action/innate/flight
|
||||
name = "Toggle Flight"
|
||||
check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUN
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "flight"
|
||||
|
||||
/datum/action/innate/flight/Activate()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/datum/species/angel/A = H.dna.species
|
||||
if(A.CanFly(H))
|
||||
if(H.movement_type & FLYING)
|
||||
to_chat(H, "<span class='notice'>You settle gently back onto the ground...</span>")
|
||||
A.ToggleFlight(H,0)
|
||||
H.update_canmove()
|
||||
else
|
||||
to_chat(H, "<span class='notice'>You beat your wings and begin to hover gently above the ground...</span>")
|
||||
H.resting = 0
|
||||
A.ToggleFlight(H,1)
|
||||
H.update_canmove()
|
||||
|
||||
/datum/species/angel/proc/flyslip(mob/living/carbon/human/H)
|
||||
var/obj/buckled_obj
|
||||
if(H.buckled)
|
||||
buckled_obj = H.buckled
|
||||
|
||||
to_chat(H, "<span class='notice'>Your wings spazz out and launch you!</span>")
|
||||
|
||||
playsound(H.loc, 'sound/misc/slip.ogg', 50, 1, -3)
|
||||
|
||||
for(var/obj/item/I in H.held_items)
|
||||
H.accident(I)
|
||||
|
||||
var/olddir = H.dir
|
||||
|
||||
H.stop_pulling()
|
||||
if(buckled_obj)
|
||||
buckled_obj.unbuckle_mob(H)
|
||||
step(buckled_obj, olddir)
|
||||
else
|
||||
for(var/i=1, i<5, i++)
|
||||
spawn (i)
|
||||
step(H, olddir)
|
||||
H.spin(1,1)
|
||||
return 1
|
||||
|
||||
|
||||
/datum/species/angel/spec_stun(mob/living/carbon/human/H,amount)
|
||||
if(H.movement_type & FLYING)
|
||||
ToggleFlight(H,0)
|
||||
flyslip(H)
|
||||
. = ..()
|
||||
|
||||
/datum/species/angel/negates_gravity(mob/living/carbon/human/H)
|
||||
if(H.movement_type & FLYING)
|
||||
return 1
|
||||
|
||||
/datum/species/angel/space_move(mob/living/carbon/human/H)
|
||||
if(H.movement_type & FLYING)
|
||||
return 1
|
||||
|
||||
/datum/species/angel/proc/ToggleFlight(mob/living/carbon/human/H,flight)
|
||||
if(flight && CanFly(H))
|
||||
stunmod = 2
|
||||
speedmod = -0.35
|
||||
H.movement_type |= FLYING
|
||||
override_float = TRUE
|
||||
H.pass_flags |= PASSTABLE
|
||||
H.OpenWings()
|
||||
else
|
||||
stunmod = 1
|
||||
speedmod = 0
|
||||
H.movement_type &= ~FLYING
|
||||
override_float = FALSE
|
||||
H.pass_flags &= ~PASSTABLE
|
||||
H.CloseWings()
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/datum/species/dullahan
|
||||
name = "dullahan"
|
||||
id = "dullahan"
|
||||
default_color = "FFFFFF"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NOBREATH,NOHUNGER)
|
||||
mutant_bodyparts = list("tail_human", "ears", "wings")
|
||||
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None")
|
||||
use_skintones = TRUE
|
||||
mutant_brain = /obj/item/organ/brain/dullahan
|
||||
mutanteyes = /obj/item/organ/eyes/dullahan
|
||||
mutanttongue = /obj/item/organ/tongue/dullahan
|
||||
mutantears = /obj/item/organ/ears/dullahan
|
||||
blacklisted = TRUE
|
||||
limbs_id = "human"
|
||||
skinned_type = /obj/item/stack/sheet/animalhide/human
|
||||
|
||||
var/obj/item/dullahan_relay/myhead
|
||||
|
||||
|
||||
/datum/species/dullahan/check_roundstart_eligible()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
|
||||
. = ..()
|
||||
H.flags_1 &= ~HEAR_1
|
||||
var/obj/item/bodypart/head/head = H.get_bodypart("head")
|
||||
if(head)
|
||||
head.drop_limb()
|
||||
head.flags_1 = HEAR_1
|
||||
head.throwforce = 25
|
||||
myhead = new /obj/item/dullahan_relay (head, H)
|
||||
H.put_in_hands(head)
|
||||
|
||||
/datum/species/dullahan/on_species_loss(mob/living/carbon/human/H)
|
||||
H.flags_1 |= ~HEAR_1
|
||||
H.reset_perspective(H)
|
||||
if(myhead)
|
||||
var/obj/item/dullahan_relay/DR = myhead
|
||||
myhead = null
|
||||
DR.owner = null
|
||||
qdel(DR)
|
||||
H.regenerate_limb("head",FALSE)
|
||||
..()
|
||||
|
||||
/datum/species/dullahan/spec_life(mob/living/carbon/human/H)
|
||||
if(QDELETED(myhead))
|
||||
myhead = null
|
||||
H.gib()
|
||||
var/obj/item/bodypart/head/head2 = H.get_bodypart("head")
|
||||
if(head2)
|
||||
myhead = null
|
||||
H.gib()
|
||||
|
||||
/datum/species/dullahan/proc/update_vision_perspective(mob/living/carbon/human/H)
|
||||
var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
|
||||
if(eyes)
|
||||
H.update_tint()
|
||||
if(eyes.tint)
|
||||
H.reset_perspective(H)
|
||||
else
|
||||
H.reset_perspective(myhead)
|
||||
|
||||
/obj/item/organ/brain/dullahan
|
||||
decoy_override = TRUE
|
||||
vital = FALSE
|
||||
|
||||
/obj/item/organ/tongue/dullahan
|
||||
zone = "abstract"
|
||||
|
||||
/obj/item/organ/tongue/dullahan/TongueSpeech(var/message)
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.dna.species.id == "dullahan")
|
||||
var/datum/species/dullahan/D = H.dna.species
|
||||
if(isobj(D.myhead.loc))
|
||||
var/obj/O = D.myhead.loc
|
||||
O.say(message)
|
||||
message = ""
|
||||
return message
|
||||
|
||||
/obj/item/organ/ears/dullahan
|
||||
zone = "abstract"
|
||||
|
||||
/obj/item/organ/eyes/dullahan
|
||||
name = "head vision"
|
||||
desc = "An abstraction."
|
||||
actions_types = list(/datum/action/item_action/organ_action/dullahan)
|
||||
zone = "abstract"
|
||||
|
||||
/datum/action/item_action/organ_action/dullahan
|
||||
name = "Toggle Perspective"
|
||||
desc = "Switch between seeing normally from your head, or blindly from your body."
|
||||
|
||||
/datum/action/item_action/organ_action/dullahan/Trigger()
|
||||
. = ..()
|
||||
var/obj/item/organ/eyes/dullahan/DE = target
|
||||
if(DE.tint)
|
||||
DE.tint = 0
|
||||
else
|
||||
DE.tint = INFINITY
|
||||
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.dna.species.id == "dullahan")
|
||||
var/datum/species/dullahan/D = H.dna.species
|
||||
D.update_vision_perspective(H)
|
||||
|
||||
/obj/item/dullahan_relay
|
||||
var/mob/living/owner
|
||||
flags_1 = HEAR_1
|
||||
|
||||
/obj/item/dullahan_relay/Initialize(mapload,new_owner)
|
||||
. = ..()
|
||||
owner = new_owner
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/dullahan_relay/process()
|
||||
if(!istype(loc, /obj/item/bodypart/head) || QDELETED(owner))
|
||||
. = PROCESS_KILL
|
||||
qdel(src)
|
||||
|
||||
/obj/item/dullahan_relay/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
if(!QDELETED(owner))
|
||||
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
to_chat(owner,message)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/dullahan_relay/Destroy()
|
||||
if(!QDELETED(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.dna.species.id == "dullahan")
|
||||
var/datum/species/dullahan/D = H.dna.species
|
||||
D.myhead = null
|
||||
owner.gib()
|
||||
owner = null
|
||||
..()
|
||||
@@ -8,7 +8,6 @@
|
||||
attack_verb = "claw"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
miss_sound = 'sound/weapons/slashmiss.ogg'
|
||||
roundstart = 1
|
||||
liked_food = MEAT | FRIED
|
||||
disliked_food = TOXIC
|
||||
|
||||
@@ -31,7 +30,6 @@
|
||||
attack_verb = "peck"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
miss_sound = 'sound/weapons/slashmiss.ogg'
|
||||
roundstart = 1
|
||||
liked_food = MEAT | FRUIT
|
||||
disliked_food = TOXIC
|
||||
|
||||
@@ -53,7 +51,6 @@
|
||||
attack_verb = "bite"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
miss_sound = 'sound/weapons/slashmiss.ogg'
|
||||
roundstart = 1
|
||||
liked_food = MEAT
|
||||
disliked_food = TOXIC
|
||||
|
||||
@@ -75,7 +72,6 @@
|
||||
attack_verb = "flutter" //wat?
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
miss_sound = 'sound/weapons/slashmiss.ogg'
|
||||
roundstart = 1
|
||||
liked_food = MEAT | FRUIT
|
||||
disliked_food = TOXIC
|
||||
|
||||
@@ -105,7 +101,6 @@
|
||||
skinned_type = /obj/item/stack/sheet/animalhide/xeno
|
||||
exotic_bloodtype = "L"
|
||||
damage_overlay_type = "xeno"
|
||||
roundstart = 1
|
||||
liked_food = MEAT
|
||||
|
||||
//Praise the Omnissiah, A challange worthy of my skills - HS
|
||||
@@ -138,7 +133,6 @@
|
||||
meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
|
||||
skinned_type = /obj/item/stack/sheet/animalhide/xeno
|
||||
// safe_toxins_max = 32 //Too much of anything is bad.
|
||||
roundstart = 0
|
||||
// whitelisted = 1
|
||||
// whitelist = list("talkingcactus") //testing whitelisting
|
||||
|
||||
@@ -182,7 +176,6 @@
|
||||
punchdamagehigh = 14
|
||||
punchstunthreshold = 13
|
||||
blacklisted = 1
|
||||
roundstart = 0
|
||||
whitelist = 1
|
||||
whitelist = list("talkingcactus")
|
||||
|
||||
@@ -233,7 +226,6 @@
|
||||
attack_verb = "bite"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
miss_sound = 'sound/weapons/slashmiss.ogg'
|
||||
// roundstart = 1
|
||||
whitelisted = 1
|
||||
whitelist = list("rubyflamewing")
|
||||
blacklisted = 0
|
||||
@@ -248,4 +240,3 @@
|
||||
attack_verb = "claw"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
miss_sound = 'sound/weapons/slashmiss.ogg'
|
||||
roundstart = 1
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
limbs_id = "golem"
|
||||
fixed_mut_color = "aaa"
|
||||
var/info_text = "As an <span class='danger'>Iron Golem</span>, you don't have any special traits."
|
||||
var/random_eligible = TRUE //If false, the golem subtype can't be made through golem mutation toxin
|
||||
|
||||
var/prefix = "Iron"
|
||||
var/list/special_names
|
||||
@@ -44,11 +45,20 @@
|
||||
name = "Random Golem"
|
||||
blacklisted = FALSE
|
||||
dangerous_existence = FALSE
|
||||
var/static/list/random_golem_types
|
||||
|
||||
/datum/species/golem/random/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
..()
|
||||
var/list/golem_types = typesof(/datum/species/golem) - src.type
|
||||
var/datum/species/golem/golem_type = pick(golem_types)
|
||||
if(!random_golem_types)
|
||||
random_golem_types = subtypesof(/datum/species/golem) - type
|
||||
for(var/V in random_golem_types)
|
||||
var/datum/species/golem/G = V
|
||||
if(!initial(G.random_eligible))
|
||||
random_golem_types -= G
|
||||
to_chat(world, "Excluding golem type [initial(G.id)]")
|
||||
else
|
||||
to_chat(world, "Allowing golem type [initial(G.id)]")
|
||||
var/datum/species/golem/golem_type = pick(random_golem_types)
|
||||
var/mob/living/carbon/human/H = C
|
||||
H.set_species(golem_type)
|
||||
to_chat(H, "[initial(golem_type.info_text)]")
|
||||
@@ -241,7 +251,7 @@
|
||||
heatmod = 1.5
|
||||
info_text = "As a <span class='danger'>Wooden Golem</span>, you have plant-like traits: you take damage from extreme temperatures, can be set on fire, and have lower armor than a normal golem. You regenerate when in the light and wither in the darkness."
|
||||
prefix = "Wooden"
|
||||
special_names = list("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", "Venus", "Sprout","Cocoa", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
|
||||
special_names = list("Bark", "Willow", "Catalpa", "Woody", "Oak", "Sap", "Twig", "Branch", "Maple", "Birch", "Elm", "Basswood", "Cottonwood", "Larch", "Aspen", "Ash", "Beech", "Buckeye", "Cedar", "Chestnut", "Cypress", "Fir", "Hawthorn", "Hazel", "Hickory", "Ironwood", "Juniper", "Leaf", "Mangrove", "Palm", "Pawpaw", "Pine", "Poplar", "Redwood", "Redbud", "Sassafras", "Spruce", "Sumac", "Trunk", "Walnut", "Yew")
|
||||
human_surname_chance = 0
|
||||
special_name_chance = 100
|
||||
|
||||
@@ -295,7 +305,7 @@
|
||||
if(!active)
|
||||
if(world.time > last_event+30)
|
||||
active = 1
|
||||
radiation_pulse(get_turf(H), 3, 3, 5, 0)
|
||||
radiation_pulse(H, 50)
|
||||
last_event = world.time
|
||||
active = null
|
||||
..()
|
||||
@@ -360,16 +370,9 @@
|
||||
if(P.starting)
|
||||
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/turf/curloc = get_turf(H)
|
||||
|
||||
var/turf/target = get_turf(P.starting)
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.current = curloc
|
||||
P.firer = H
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
P.Angle = null
|
||||
P.preparePixelProjectile(locate(Clamp(target.x + new_x, 1, world.maxx), Clamp(target.y + new_y, 1, world.maxy), H.z), H)
|
||||
return -1
|
||||
return 0
|
||||
|
||||
@@ -426,6 +429,7 @@
|
||||
if(ishuman(C))
|
||||
unstable_teleport = new
|
||||
unstable_teleport.Grant(C)
|
||||
last_teleport = world.time
|
||||
|
||||
/datum/species/golem/bluespace/on_species_loss(mob/living/carbon/C)
|
||||
if(unstable_teleport)
|
||||
@@ -486,6 +490,11 @@
|
||||
var/banana_cooldown = 100
|
||||
var/active = null
|
||||
|
||||
/datum/species/golem/bananium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
..()
|
||||
last_banana = world.time
|
||||
last_honk = world.time
|
||||
|
||||
/datum/species/golem/bananium/random_name(gender,unique,lastname)
|
||||
var/clown_name = pick(GLOB.clown_names)
|
||||
var/golem_name = "[uppertext(clown_name)]"
|
||||
@@ -560,10 +569,13 @@
|
||||
. = ..()
|
||||
C.faction |= "cult"
|
||||
phase_shift = new
|
||||
phase_shift.charge_counter = 0
|
||||
C.AddSpell(phase_shift)
|
||||
abyssal_gaze = new
|
||||
abyssal_gaze.charge_counter = 0
|
||||
C.AddSpell(abyssal_gaze)
|
||||
dominate = new
|
||||
dominate.charge_counter = 0
|
||||
C.AddSpell(dominate)
|
||||
|
||||
/datum/species/golem/runic/on_species_loss(mob/living/carbon/C)
|
||||
@@ -594,7 +606,7 @@
|
||||
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>clockwork golem</span><span class='bold alloy'>, you are faster than \
|
||||
other types of golem (being a machine), and are immune to electric shocks.</span>"
|
||||
species_traits = list(NO_UNDERWEAR, NOTRANSSTING, NOBREATH, NOZOMBIE, VIRUSIMMUNE, RADIMMUNE, NOBLOOD, RESISTCOLD, RESISTPRESSURE, PIERCEIMMUNE)
|
||||
armor = 40 //Reinforced, but also slim to allow for fast movement
|
||||
armor = 20 //Reinforced, but much less so to allow for fast movement
|
||||
attack_verb = "smash"
|
||||
attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg'
|
||||
sexes = FALSE
|
||||
@@ -636,7 +648,8 @@
|
||||
has_corpse = TRUE
|
||||
blacklisted = TRUE
|
||||
dangerous_existence = TRUE
|
||||
|
||||
random_eligible = FALSE
|
||||
|
||||
/datum/species/golem/cloth
|
||||
name = "Cloth Golem"
|
||||
id = "cloth golem"
|
||||
@@ -652,6 +665,11 @@
|
||||
punchdamagehigh = 8 // not as heavy as stone
|
||||
prefix = "Cloth"
|
||||
|
||||
/datum/species/golem/cloth/check_roundstart_eligible()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/datum/species/golem/cloth/random_name(gender,unique,lastname)
|
||||
var/pharaoh_name = pick("Neferkare", "Hudjefa", "Khufu", "Mentuhotep", "Ahmose", "Amenhotep", "Thutmose", "Hatshepsut", "Tutankhamun", "Ramses", "Seti", \
|
||||
"Merenptah", "Djer", "Semerkhet", "Nynetjer", "Khafre", "Pepi", "Intef", "Ay") //yes, Ay was an actual pharaoh
|
||||
|
||||
@@ -145,10 +145,10 @@
|
||||
bodies = old_species.bodies
|
||||
|
||||
/datum/species/jelly/slime/spec_life(mob/living/carbon/human/H)
|
||||
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
|
||||
/*if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
|
||||
if(prob(5))
|
||||
to_chat(H, "<span class='notice'>You feel very bloated!</span>")
|
||||
else if(H.nutrition >= NUTRITION_LEVEL_WELL_FED)
|
||||
to_chat(H, "<span class='notice'>You feel very bloated!</span>")*/
|
||||
if(H.nutrition >= NUTRITION_LEVEL_WELL_FED)
|
||||
H.blood_volume += 3
|
||||
H.nutrition -= 2.5
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
if((!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman)) && !atmos_sealed)
|
||||
if(environment)
|
||||
if(environment.total_moles())
|
||||
if(environment.gases["o2"] && (environment.gases["o2"][MOLES]) >= 1) //Same threshhold that extinguishes fire
|
||||
if(environment.gases[/datum/gas/oxygen] && (environment.gases[/datum/gas/oxygen][MOLES]) >= 1) //Same threshhold that extinguishes fire
|
||||
H.adjust_fire_stacks(0.5)
|
||||
if(!H.on_fire && H.fire_stacks > 0)
|
||||
H.visible_message("<span class='danger'>[H]'s body reacts with the atmosphere and bursts into flames!</span>","<span class='userdanger'>Your body reacts with the atmosphere and bursts into flame!</span>")
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
disliked_food = NONE
|
||||
liked_food = NONE
|
||||
toxic_food = NONE
|
||||
roundstart = TRUE
|
||||
|
||||
|
||||
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#define HEART_RESPAWN_THRESHHOLD 40
|
||||
#define HEART_SPECIAL_SHADOWIFY 2
|
||||
|
||||
/datum/species/shadow
|
||||
// Humans cursed to stay in the darkness, lest their life forces drain. They regain health in shadow and die in light.
|
||||
@@ -24,6 +25,10 @@
|
||||
else if (light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) //heal in the dark
|
||||
H.heal_overall_damage(1,1)
|
||||
|
||||
/datum/species/shadow/check_roundstart_eligible()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/datum/species/shadow/nightmare
|
||||
name = "Nightmare"
|
||||
@@ -60,7 +65,8 @@
|
||||
return -1
|
||||
return 0
|
||||
|
||||
|
||||
/datum/species/shadow/nightmare/check_roundstart_eligible()
|
||||
return FALSE
|
||||
|
||||
//Organs
|
||||
|
||||
@@ -111,14 +117,15 @@
|
||||
|
||||
/obj/item/organ/heart/nightmare/Insert(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
blade = new/obj/item/light_eater
|
||||
M.put_in_hands(blade)
|
||||
if(special != HEART_SPECIAL_SHADOWIFY)
|
||||
blade = new/obj/item/light_eater
|
||||
M.put_in_hands(blade)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
respawn_progress = 0
|
||||
if(blade)
|
||||
if(blade && special != HEART_SPECIAL_SHADOWIFY)
|
||||
QDEL_NULL(blade)
|
||||
M.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
|
||||
..()
|
||||
@@ -141,6 +148,13 @@
|
||||
playsound(owner,'sound/effects/singlebeat.ogg',40,1)
|
||||
if(respawn_progress >= HEART_RESPAWN_THRESHHOLD)
|
||||
owner.revive(full_heal = TRUE)
|
||||
if(!(owner.dna.species.id == "shadow" || owner.dna.species.id == "nightmare"))
|
||||
var/mob/living/carbon/old_owner = owner
|
||||
Remove(owner, HEART_SPECIAL_SHADOWIFY)
|
||||
old_owner.set_species(/datum/species/shadow)
|
||||
Insert(old_owner, HEART_SPECIAL_SHADOWIFY)
|
||||
to_chat(owner, "<span class='userdanger'>You feel the shadows invade your skin, leaping into the center of your chest! You're alive!</span>")
|
||||
SEND_SOUND(owner, sound('sound/effects/ghost.ogg'))
|
||||
owner.visible_message("<span class='warning'>[owner] staggers to their feet!</span>")
|
||||
playsound(owner, 'sound/hallucinations/far_noise.ogg', 50, 1)
|
||||
respawn_progress = 0
|
||||
@@ -193,4 +207,5 @@
|
||||
O.burn()
|
||||
playsound(src, 'sound/items/welder.ogg', 50, 1)
|
||||
|
||||
#undef HEART_SPECIAL_SHADOWIFY
|
||||
#undef HEART_RESPAWN_THRESHHOLD
|
||||
@@ -11,3 +11,8 @@
|
||||
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
|
||||
disliked_food = NONE
|
||||
liked_food = NONE
|
||||
|
||||
/datum/species/skeleton/check_roundstart_eligible()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
@@ -118,4 +118,4 @@
|
||||
else
|
||||
return ..()
|
||||
else
|
||||
return ..()
|
||||
return ..()
|
||||
@@ -0,0 +1,125 @@
|
||||
/datum/species/vampire
|
||||
name = "vampire"
|
||||
id = "vampire"
|
||||
default_color = "FFFFFF"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NOHUNGER,NOBREATH,DRINKSBLOOD)
|
||||
mutant_bodyparts = list("tail_human", "ears", "wings")
|
||||
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "None")
|
||||
exotic_bloodtype = "U"
|
||||
use_skintones = TRUE
|
||||
mutant_heart = /obj/item/organ/heart/vampire
|
||||
mutanttongue = /obj/item/organ/tongue/vampire
|
||||
blacklisted = TRUE
|
||||
limbs_id = "human"
|
||||
skinned_type = /obj/item/stack/sheet/animalhide/human
|
||||
var/info_text = "You are a <span class='danger'>Vampire</span>. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
|
||||
|
||||
/datum/species/vampire/check_roundstart_eligible()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/species/vampire/on_species_gain(mob/living/carbon/human/C, datum/species/old_species)
|
||||
. = ..()
|
||||
to_chat(C, "[info_text]")
|
||||
C.skin_tone = "albino"
|
||||
C.update_body(0)
|
||||
var/obj/effect/proc_holder/spell/targeted/shapeshift/bat/B = new
|
||||
C.AddSpell(B)
|
||||
|
||||
/datum/species/vampire/on_species_loss(mob/living/carbon/C)
|
||||
. = ..()
|
||||
if(C.mind)
|
||||
for(var/S in C.mind.spell_list)
|
||||
var/obj/effect/proc_holder/spell/S2 = S
|
||||
if(S2.type == /obj/effect/proc_holder/spell/targeted/shapeshift/bat)
|
||||
C.mind.spell_list.Remove(S2)
|
||||
qdel(S2)
|
||||
|
||||
/datum/species/vampire/spec_life(mob/living/carbon/human/C)
|
||||
. = ..()
|
||||
if(istype(C.loc, /obj/structure/closet/coffin))
|
||||
C.heal_overall_damage(4,4)
|
||||
C.adjustToxLoss(-4)
|
||||
C.adjustOxyLoss(-4)
|
||||
C.adjustCloneLoss(-4)
|
||||
return
|
||||
C.blood_volume -= 0.75
|
||||
if(C.blood_volume <= BLOOD_VOLUME_SURVIVE)
|
||||
to_chat(C, "<span class='danger'>You ran out of blood!</span>")
|
||||
C.dust()
|
||||
var/area/A = get_area(C)
|
||||
if(istype(A, /area/chapel))
|
||||
to_chat(C, "<span class='danger'>You don't belong here!</span>")
|
||||
C.adjustFireLoss(20)
|
||||
C.adjust_fire_stacks(6)
|
||||
C.IgniteMob()
|
||||
|
||||
/obj/item/organ/tongue/vampire
|
||||
name = "vampire tongue"
|
||||
actions_types = list(/datum/action/item_action/organ_action/vampire)
|
||||
color = "#1C1C1C"
|
||||
var/drain_cooldown = 0
|
||||
|
||||
#define VAMP_DRAIN_AMOUNT 50
|
||||
|
||||
/datum/action/item_action/organ_action/vampire
|
||||
name = "Drain Victim"
|
||||
desc = "Leech blood from any carbon victim you are passively grabbing."
|
||||
|
||||
/datum/action/item_action/organ_action/vampire/Trigger()
|
||||
. = ..()
|
||||
if(iscarbon(owner))
|
||||
var/mob/living/carbon/H = owner
|
||||
var/obj/item/organ/tongue/vampire/V = target
|
||||
if(V.drain_cooldown >= world.time)
|
||||
to_chat(H, "<span class='notice'>You just drained blood, wait a few seconds.</span>")
|
||||
return
|
||||
if(H.pulling && iscarbon(H.pulling))
|
||||
var/mob/living/carbon/victim = H.pulling
|
||||
if(H.blood_volume >= BLOOD_VOLUME_MAXIMUM)
|
||||
to_chat(H, "<span class='notice'>You're already full!</span>")
|
||||
return
|
||||
if(victim.stat == DEAD)
|
||||
to_chat(H, "<span class='notice'>You need a living victim!</span>")
|
||||
return
|
||||
if(!victim.blood_volume || (victim.dna && ((NOBLOOD in victim.dna.species.species_traits) || victim.dna.species.exotic_blood)))
|
||||
to_chat(H, "<span class='notice'>[victim] doesn't have blood!</span>")
|
||||
return
|
||||
V.drain_cooldown = world.time + 30
|
||||
if(!do_after(H, 30, target = victim))
|
||||
return
|
||||
var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood
|
||||
var/drained_blood = min(victim.blood_volume, VAMP_DRAIN_AMOUNT, blood_volume_difference)
|
||||
to_chat(victim, "<span class='danger'>[H] is draining your blood!</span>")
|
||||
to_chat(H, "<span class='notice'>You drain some blood!</span>")
|
||||
playsound(H, 'sound/items/drink.ogg', 30, 1, -2)
|
||||
victim.blood_volume = Clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
|
||||
H.blood_volume = Clamp(H.blood_volume + drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
|
||||
if(!victim.blood_volume)
|
||||
to_chat(H, "<span class='warning'>You finish off [victim]'s blood supply!</span>")
|
||||
|
||||
#undef VAMP_DRAIN_AMOUNT
|
||||
|
||||
/obj/item/organ/heart/vampire
|
||||
name = "vampire heart"
|
||||
actions_types = list(/datum/action/item_action/organ_action/vampire_heart)
|
||||
color = "#1C1C1C"
|
||||
|
||||
/datum/action/item_action/organ_action/vampire_heart
|
||||
name = "Check Blood Level"
|
||||
desc = "Check how much blood you have remaining."
|
||||
|
||||
/datum/action/item_action/organ_action/vampire_heart/Trigger()
|
||||
. = ..()
|
||||
if(iscarbon(owner))
|
||||
var/mob/living/carbon/H = owner
|
||||
to_chat(H, "<span class='notice'>Current blood level: [H.blood_volume]/[BLOOD_VOLUME_MAXIMUM].</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shapeshift/bat
|
||||
name = "Bat Form"
|
||||
desc = "Take on the shape a space bat."
|
||||
invocation = "Squeak!"
|
||||
charge_max = 50
|
||||
cooldown_min = 50
|
||||
shapeshift_type = /mob/living/simple_animal/hostile/retaliate/bat
|
||||
@@ -14,6 +14,11 @@
|
||||
disliked_food = NONE
|
||||
liked_food = NONE
|
||||
|
||||
/datum/species/zombie/check_roundstart_eligible()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/datum/species/zombie/infectious
|
||||
name = "Infectious Zombie"
|
||||
id = "memezombies"
|
||||
@@ -24,6 +29,10 @@
|
||||
mutanteyes = /obj/item/organ/eyes/night_vision/zombie
|
||||
var/regen_cooldown = 0
|
||||
|
||||
/datum/species/zombie/infectious/check_roundstart_eligible()
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount)
|
||||
. = min(2, amount)
|
||||
|
||||
@@ -52,7 +61,7 @@
|
||||
// Infection organ needs to be handled separately from mutant_organs
|
||||
// because it persists through species transitions
|
||||
var/obj/item/organ/zombie_infection/infection
|
||||
infection = C.getorganslot("zombie_infection")
|
||||
infection = C.getorganslot(ORGAN_SLOT_ZOMBIE)
|
||||
if(!infection)
|
||||
infection = new()
|
||||
infection.Insert(C)
|
||||
|
||||
@@ -63,7 +63,7 @@ There are several things that need to be remembered:
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/update_fire()
|
||||
..("Standing")
|
||||
..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning")
|
||||
|
||||
|
||||
/* --------------------------------------- */
|
||||
@@ -134,6 +134,10 @@ There are several things that need to be remembered:
|
||||
if(!uniform_overlay)
|
||||
uniform_overlay = U.build_worn_icon(state = "[t_color]", default_layer = UNIFORM_LAYER, default_icon_file = ((w_uniform.icon_override) ? w_uniform.icon_override : 'icons/mob/uniform.dmi'), isinhands = FALSE)
|
||||
|
||||
|
||||
if(OFFSET_UNIFORM in dna.species.offset_features)
|
||||
uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
|
||||
uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
|
||||
overlays_standing[UNIFORM_LAYER] = uniform_overlay
|
||||
|
||||
apply_overlay(UNIFORM_LAYER)
|
||||
@@ -147,6 +151,8 @@ There are several things that need to be remembered:
|
||||
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_id]
|
||||
inv.update_icon()
|
||||
|
||||
var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
|
||||
|
||||
if(wear_id)
|
||||
wear_id.screen_loc = ui_id
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
@@ -154,8 +160,11 @@ There are several things that need to be remembered:
|
||||
update_observer_view(wear_id)
|
||||
|
||||
//TODO: add an icon file for ID slot stuff, so it's less snowflakey
|
||||
overlays_standing[ID_LAYER] = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = ((wear_id.icon_override) ? wear_id.icon_override : 'icons/mob/mob.dmi'))
|
||||
|
||||
id_overlay = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi')
|
||||
if(OFFSET_ID in dna.species.offset_features)
|
||||
id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
|
||||
id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
|
||||
overlays_standing[ID_LAYER] = id_overlay
|
||||
apply_overlay(ID_LAYER)
|
||||
|
||||
|
||||
@@ -176,6 +185,7 @@ There are several things that need to be remembered:
|
||||
|
||||
overlays_standing[GLOVES_LAYER] = bloody_overlay
|
||||
|
||||
var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER]
|
||||
if(gloves)
|
||||
gloves.screen_loc = ui_gloves
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
@@ -185,8 +195,12 @@ There are several things that need to be remembered:
|
||||
var/t_state = gloves.item_state
|
||||
if(!t_state)
|
||||
t_state = gloves.icon_state
|
||||
overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = ((gloves.icon_override) ? gloves.icon_override : 'icons/mob/hands.dmi'))
|
||||
|
||||
overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/hands.dmi')
|
||||
gloves_overlay = overlays_standing[GLOVES_LAYER]
|
||||
if(OFFSET_GLOVES in dna.species.offset_features)
|
||||
gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1]
|
||||
gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2]
|
||||
overlays_standing[GLOVES_LAYER] = gloves_overlay
|
||||
apply_overlay(GLOVES_LAYER)
|
||||
|
||||
|
||||
@@ -207,9 +221,13 @@ There are several things that need to be remembered:
|
||||
client.screen += glasses //Either way, add the item to the HUD
|
||||
update_observer_view(glasses,1)
|
||||
if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
|
||||
|
||||
overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = ((glasses.icon_override) ? glasses.icon_override : 'icons/mob/eyes.dmi'))
|
||||
|
||||
overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/eyes.dmi')
|
||||
var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER]
|
||||
if(glasses_overlay)
|
||||
if(OFFSET_GLASSES in dna.species.offset_features)
|
||||
glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1]
|
||||
glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2]
|
||||
overlays_standing[GLASSES_LAYER] = glasses_overlay
|
||||
apply_overlay(GLASSES_LAYER)
|
||||
|
||||
|
||||
@@ -230,8 +248,12 @@ There are several things that need to be remembered:
|
||||
client.screen += ears //add it to the client's screen
|
||||
update_observer_view(ears,1)
|
||||
|
||||
overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = ((ears.icon_override) ? ears.icon_override : 'icons/mob/ears.dmi'))
|
||||
|
||||
overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
|
||||
var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
|
||||
if(OFFSET_EARS in dna.species.offset_features)
|
||||
ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
|
||||
ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
|
||||
overlays_standing[EARS_LAYER] = ears_overlay
|
||||
apply_overlay(EARS_LAYER)
|
||||
|
||||
|
||||
@@ -251,8 +273,12 @@ There are several things that need to be remembered:
|
||||
if(hud_used.inventory_shown) //if the inventory is open
|
||||
client.screen += shoes //add it to client's screen
|
||||
update_observer_view(shoes,1)
|
||||
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = ((shoes.icon_override) ? shoes.icon_override : 'icons/mob/feet.dmi'))
|
||||
|
||||
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/feet.dmi')
|
||||
var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
|
||||
if(OFFSET_SHOES in dna.species.offset_features)
|
||||
shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
|
||||
shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2]
|
||||
overlays_standing[SHOES_LAYER] = shoes_overlay
|
||||
apply_overlay(SHOES_LAYER)
|
||||
|
||||
|
||||
@@ -272,13 +298,25 @@ There are several things that need to be remembered:
|
||||
if(!t_state)
|
||||
t_state = s_store.icon_state
|
||||
overlays_standing[SUIT_STORE_LAYER] = mutable_appearance('icons/mob/belt_mirror.dmi', t_state, -SUIT_STORE_LAYER)
|
||||
|
||||
var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_LAYER]
|
||||
if(OFFSET_S_STORE in dna.species.offset_features)
|
||||
s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
|
||||
s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2]
|
||||
overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
|
||||
apply_overlay(SUIT_STORE_LAYER)
|
||||
|
||||
|
||||
/mob/living/carbon/human/update_inv_head()
|
||||
..()
|
||||
update_mutant_bodyparts()
|
||||
var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER]
|
||||
if(head_overlay)
|
||||
remove_overlay(HEAD_LAYER)
|
||||
if(OFFSET_HEAD in dna.species.offset_features)
|
||||
head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1]
|
||||
head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
|
||||
overlays_standing[HEAD_LAYER] = head_overlay
|
||||
apply_overlay(HEAD_LAYER)
|
||||
|
||||
/mob/living/carbon/human/update_inv_belt()
|
||||
remove_overlay(BELT_LAYER)
|
||||
@@ -297,9 +335,12 @@ There are several things that need to be remembered:
|
||||
if(!t_state)
|
||||
t_state = belt.icon_state
|
||||
|
||||
overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = ((belt.icon_override) ? belt.icon_override : 'icons/mob/belt.dmi'))
|
||||
|
||||
|
||||
overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = 'icons/mob/belt.dmi')
|
||||
var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
|
||||
if(OFFSET_BELT in dna.species.offset_features)
|
||||
belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1]
|
||||
belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2]
|
||||
overlays_standing[BELT_LAYER] = belt_overlay
|
||||
apply_overlay(BELT_LAYER)
|
||||
|
||||
|
||||
@@ -318,8 +359,12 @@ There are several things that need to be remembered:
|
||||
client.screen += wear_suit
|
||||
update_observer_view(wear_suit,1)
|
||||
|
||||
overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = ((wear_suit.icon_override) ? wear_suit.icon_override : 'icons/mob/suit.dmi'))
|
||||
|
||||
overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = 'icons/mob/suit.dmi')
|
||||
var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
|
||||
if(OFFSET_SUIT in dna.species.offset_features)
|
||||
suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
|
||||
suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
|
||||
overlays_standing[SUIT_LAYER] = suit_overlay
|
||||
update_hair()
|
||||
update_mutant_bodyparts()
|
||||
|
||||
@@ -351,8 +396,26 @@ There are several things that need to be remembered:
|
||||
|
||||
/mob/living/carbon/human/update_inv_wear_mask()
|
||||
..()
|
||||
var/mutable_appearance/mask_overlay = overlays_standing[FACEMASK_LAYER]
|
||||
if(mask_overlay)
|
||||
remove_overlay(FACEMASK_LAYER)
|
||||
if(OFFSET_FACEMASK in dna.species.offset_features)
|
||||
mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1]
|
||||
mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2]
|
||||
overlays_standing[FACEMASK_LAYER] = mask_overlay
|
||||
apply_overlay(FACEMASK_LAYER)
|
||||
update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
|
||||
|
||||
/mob/living/carbon/human/update_inv_back()
|
||||
..()
|
||||
var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
|
||||
if(back_overlay)
|
||||
remove_overlay(BACK_LAYER)
|
||||
if(OFFSET_BACK in dna.species.offset_features)
|
||||
back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1]
|
||||
back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2]
|
||||
overlays_standing[BACK_LAYER] = back_overlay
|
||||
apply_overlay(BACK_LAYER)
|
||||
|
||||
/mob/living/carbon/human/update_inv_legcuffed()
|
||||
remove_overlay(LEGCUFF_LAYER)
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
var/datum/gas_mixture/breath
|
||||
|
||||
if(!getorganslot("breathing_tube"))
|
||||
if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL))
|
||||
losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
if((status_flags & GODMODE))
|
||||
return
|
||||
|
||||
var/lungs = getorganslot("lungs")
|
||||
var/lungs = getorganslot(ORGAN_SLOT_LUNGS)
|
||||
if(!lungs)
|
||||
adjustOxyLoss(2)
|
||||
|
||||
@@ -132,11 +132,10 @@
|
||||
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
|
||||
|
||||
var/list/breath_gases = breath.gases
|
||||
breath.assert_gases("o2","plasma","co2","n2o", "bz")
|
||||
|
||||
var/O2_partialpressure = (breath_gases["o2"][MOLES]/breath.total_moles())*breath_pressure
|
||||
var/Toxins_partialpressure = (breath_gases["plasma"][MOLES]/breath.total_moles())*breath_pressure
|
||||
var/CO2_partialpressure = (breath_gases["co2"][MOLES]/breath.total_moles())*breath_pressure
|
||||
breath.assert_gases(/datum/gas/oxygen, /datum/gas/plasma, /datum/gas/carbon_dioxide, /datum/gas/nitrous_oxide, /datum/gas/bz)
|
||||
var/O2_partialpressure = (breath_gases[/datum/gas/oxygen][MOLES]/breath.total_moles())*breath_pressure
|
||||
var/Toxins_partialpressure = (breath_gases[/datum/gas/plasma][MOLES]/breath.total_moles())*breath_pressure
|
||||
var/CO2_partialpressure = (breath_gases[/datum/gas/carbon_dioxide][MOLES]/breath.total_moles())*breath_pressure
|
||||
|
||||
|
||||
//OXYGEN
|
||||
@@ -147,7 +146,7 @@
|
||||
var/ratio = 1 - O2_partialpressure/safe_oxy_min
|
||||
adjustOxyLoss(min(5*ratio, 3))
|
||||
failed_last_breath = 1
|
||||
oxygen_used = breath_gases["o2"][MOLES]*ratio
|
||||
oxygen_used = breath_gases[/datum/gas/oxygen][MOLES]*ratio
|
||||
else
|
||||
adjustOxyLoss(3)
|
||||
failed_last_breath = 1
|
||||
@@ -157,11 +156,11 @@
|
||||
failed_last_breath = 0
|
||||
if(health >= HEALTH_THRESHOLD_CRIT)
|
||||
adjustOxyLoss(-5)
|
||||
oxygen_used = breath_gases["o2"][MOLES]
|
||||
oxygen_used = breath_gases[/datum/gas/oxygen][MOLES]
|
||||
clear_alert("not_enough_oxy")
|
||||
|
||||
breath_gases["o2"][MOLES] -= oxygen_used
|
||||
breath_gases["co2"][MOLES] += oxygen_used
|
||||
breath_gases[/datum/gas/oxygen][MOLES] -= oxygen_used
|
||||
breath_gases[/datum/gas/carbon_dioxide][MOLES] += oxygen_used
|
||||
|
||||
//CARBON DIOXIDE
|
||||
if(CO2_partialpressure > safe_co2_max)
|
||||
@@ -180,15 +179,15 @@
|
||||
|
||||
//TOXINS/PLASMA
|
||||
if(Toxins_partialpressure > safe_tox_max)
|
||||
var/ratio = (breath_gases["plasma"][MOLES]/safe_tox_max) * 10
|
||||
var/ratio = (breath_gases[/datum/gas/plasma][MOLES]/safe_tox_max) * 10
|
||||
adjustToxLoss(Clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
|
||||
throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
|
||||
else
|
||||
clear_alert("too_much_tox")
|
||||
|
||||
//NITROUS OXIDE
|
||||
if(breath_gases["n2o"])
|
||||
var/SA_partialpressure = (breath_gases["n2o"][MOLES]/breath.total_moles())*breath_pressure
|
||||
if(breath_gases[/datum/gas/nitrous_oxide])
|
||||
var/SA_partialpressure = (breath_gases[/datum/gas/nitrous_oxide][MOLES]/breath.total_moles())*breath_pressure
|
||||
if(SA_partialpressure > SA_para_min)
|
||||
Unconscious(60)
|
||||
if(SA_partialpressure > SA_sleep_min)
|
||||
@@ -198,12 +197,22 @@
|
||||
emote(pick("giggle","laugh"))
|
||||
|
||||
//BZ (Facepunch port of their Agent B)
|
||||
if(breath_gases["bz"])
|
||||
var/bz_partialpressure = (breath_gases["bz"][MOLES]/breath.total_moles())*breath_pressure
|
||||
if(breath_gases[/datum/gas/bz])
|
||||
var/bz_partialpressure = (breath_gases[/datum/gas/bz][MOLES]/breath.total_moles())*breath_pressure
|
||||
if(bz_partialpressure > 1)
|
||||
hallucination += 20
|
||||
else if(bz_partialpressure > 0.01)
|
||||
hallucination += 5//Removed at 2 per tick so this will slowly build up
|
||||
//TRITIUM
|
||||
if(breath_gases[/datum/gas/tritium])
|
||||
var/tritium_partialpressure = (breath_gases[/datum/gas/tritium][MOLES]/breath.total_moles())*breath_pressure
|
||||
radiation += tritium_partialpressure/10
|
||||
//NITRYL
|
||||
if (breath_gases[/datum/gas/nitryl])
|
||||
var/nitryl_partialpressure = (breath_gases[/datum/gas/nitryl][MOLES]/breath.total_moles())*breath_pressure
|
||||
adjustFireLoss(nitryl_partialpressure/4)
|
||||
|
||||
|
||||
|
||||
breath.garbage_collect()
|
||||
|
||||
@@ -221,7 +230,7 @@
|
||||
if(internal.loc != src)
|
||||
internal = null
|
||||
update_internals_hud_icon(0)
|
||||
else if ((!wear_mask || !(wear_mask.flags_1 & MASKINTERNALS_1)) && !getorganslot("breathing_tube"))
|
||||
else if ((!wear_mask || !(wear_mask.flags_1 & MASKINTERNALS_1)) && !getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
internal = null
|
||||
update_internals_hud_icon(0)
|
||||
else
|
||||
@@ -281,24 +290,9 @@
|
||||
HM.force_lose(src)
|
||||
dna.temporary_mutations.Remove(mut)
|
||||
|
||||
if(radiation)
|
||||
radiation = Clamp(radiation, 0, 100)
|
||||
switch(radiation)
|
||||
if(0 to 50)
|
||||
radiation = max(radiation-1,0)
|
||||
if(prob(25))
|
||||
adjustToxLoss(1)
|
||||
|
||||
if(50 to 75)
|
||||
radiation = max(radiation-2,0)
|
||||
adjustToxLoss(1)
|
||||
if(prob(5))
|
||||
radiation = max(radiation-5,0)
|
||||
|
||||
if(75 to 100)
|
||||
radiation = max(radiation-3,0)
|
||||
adjustToxLoss(3)
|
||||
|
||||
radiation -= min(radiation, RAD_LOSS_PER_TICK)
|
||||
if(radiation > RAD_MOB_SAFE)
|
||||
adjustToxLoss(log(radiation-RAD_MOB_SAFE)*RAD_TOX_COEFFICIENT)
|
||||
|
||||
/mob/living/carbon/handle_stomach()
|
||||
set waitfor = 0
|
||||
@@ -407,7 +401,7 @@
|
||||
/////////
|
||||
|
||||
/mob/living/carbon/proc/handle_liver()
|
||||
var/obj/item/organ/liver/liver = getorganslot("liver")
|
||||
var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER)
|
||||
if((!dna && !liver) || (NOLIVER in dna.species.species_traits))
|
||||
return
|
||||
if(liver)
|
||||
@@ -420,17 +414,17 @@
|
||||
liver_failure()
|
||||
|
||||
/mob/living/carbon/proc/undergoing_liver_failure()
|
||||
var/obj/item/organ/liver/liver = getorganslot("liver")
|
||||
var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER)
|
||||
if(liver && liver.failing)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/proc/return_liver_damage()
|
||||
var/obj/item/organ/liver/liver = getorganslot("liver")
|
||||
var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER)
|
||||
if(liver)
|
||||
return liver.damage
|
||||
|
||||
/mob/living/carbon/proc/applyLiverDamage(var/d)
|
||||
var/obj/item/organ/liver/L = getorganslot("liver")
|
||||
var/obj/item/organ/liver/L = getorganslot(ORGAN_SLOT_LIVER)
|
||||
if(L)
|
||||
L.damage += d
|
||||
|
||||
|
||||
@@ -23,32 +23,25 @@
|
||||
walk_to(src,0)
|
||||
|
||||
/mob/living/carbon/monkey/handle_mutations_and_radiation()
|
||||
|
||||
if (radiation)
|
||||
if (radiation > 100)
|
||||
if(radiation)
|
||||
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
|
||||
if(!IsKnockdown())
|
||||
emote("collapse")
|
||||
Knockdown(200)
|
||||
Knockdown(RAD_MOB_KNOCKDOWN_AMOUNT)
|
||||
to_chat(src, "<span class='danger'>You feel weak.</span>")
|
||||
if(radiation > 30 && prob((radiation - 30) * (radiation - 30) * 0.0002))
|
||||
gorillize()
|
||||
return
|
||||
switch(radiation)
|
||||
if(radiation > RAD_MOB_MUTATE)
|
||||
if(prob(1))
|
||||
to_chat(src, "<span class='danger'>You mutate!</span>")
|
||||
randmutb()
|
||||
emote("gasp")
|
||||
domutcheck()
|
||||
|
||||
if(50 to 75)
|
||||
if(prob(5))
|
||||
if(!IsKnockdown())
|
||||
emote("collapse")
|
||||
Knockdown(60)
|
||||
to_chat(src, "<span class='danger'>You feel weak.</span>")
|
||||
|
||||
if(75 to 100)
|
||||
if(prob(1))
|
||||
to_chat(src, "<span class='danger'>You mutate!</span>")
|
||||
randmutb()
|
||||
emote("gasp")
|
||||
domutcheck()
|
||||
..()
|
||||
if(radiation > RAD_MOB_MUTATE * 2 && prob(50))
|
||||
gorillize()
|
||||
return
|
||||
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
|
||||
vomit(10, TRUE)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath)
|
||||
if(abs(310.15 - breath.temperature) > 50)
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
return protection
|
||||
|
||||
/mob/living/carbon/monkey/IsVocal()
|
||||
if(!getorganslot("lungs"))
|
||||
if(!getorganslot(ORGAN_SLOT_LUNGS))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/carbon/treat_message(message)
|
||||
message = ..(message)
|
||||
var/obj/item/organ/tongue/T = getorganslot("tongue")
|
||||
var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE)
|
||||
if(!T) //hoooooouaah!
|
||||
var/regex/tongueless_lower = new("\[gdntke]+", "g")
|
||||
var/regex/tongueless_upper = new("\[GDNTKE]+", "g")
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
/mob/living/carbon/get_spans()
|
||||
. = ..()
|
||||
var/obj/item/organ/tongue/T = getorganslot("tongue")
|
||||
var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE)
|
||||
if(T)
|
||||
. |= T.get_spans()
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
. |= I.get_held_item_speechspans(src)
|
||||
|
||||
/mob/living/carbon/could_speak_in_language(datum/language/dt)
|
||||
var/obj/item/organ/tongue/T = getorganslot("tongue")
|
||||
var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE)
|
||||
if(T)
|
||||
. = T.could_speak_in_language(dt)
|
||||
else
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// eye damage, eye_blind, eye_blurry, druggy, BLIND disability, NEARSIGHT disability, and HUSK disability.
|
||||
|
||||
/mob/living/carbon/damage_eyes(amount)
|
||||
var/obj/item/organ/eyes/eyes = getorganslot("eye_sight")
|
||||
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
|
||||
if (!eyes)
|
||||
return
|
||||
if(amount>0)
|
||||
@@ -15,7 +15,7 @@
|
||||
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
|
||||
|
||||
/mob/living/carbon/set_eye_damage(amount)
|
||||
var/obj/item/organ/eyes/eyes = getorganslot("eye_sight")
|
||||
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
|
||||
if (!eyes)
|
||||
return
|
||||
eyes.eye_damage = max(amount,0)
|
||||
@@ -28,7 +28,7 @@
|
||||
clear_fullscreen("eye_damage")
|
||||
|
||||
/mob/living/carbon/adjust_eye_damage(amount)
|
||||
var/obj/item/organ/eyes/eyes = getorganslot("eye_sight")
|
||||
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
|
||||
if (!eyes)
|
||||
return
|
||||
eyes.eye_damage = max(eyes.eye_damage+amount, 0)
|
||||
@@ -41,39 +41,28 @@
|
||||
clear_fullscreen("eye_damage")
|
||||
|
||||
/mob/living/carbon/adjust_drugginess(amount)
|
||||
var/old_druggy = druggy
|
||||
if(amount>0)
|
||||
druggy += amount
|
||||
if(!old_druggy)
|
||||
overlay_fullscreen("high", /obj/screen/fullscreen/high)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else if(old_druggy)
|
||||
druggy = max(druggy+amount, 0)
|
||||
if(!druggy)
|
||||
clear_fullscreen("high")
|
||||
clear_alert("high")
|
||||
druggy = max(druggy+amount, 0)
|
||||
if(druggy)
|
||||
overlay_fullscreen("high", /obj/screen/fullscreen/high)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else
|
||||
clear_fullscreen("high")
|
||||
clear_alert("high")
|
||||
|
||||
/mob/living/carbon/set_drugginess(amount)
|
||||
var/old_druggy = druggy
|
||||
druggy = amount
|
||||
if(amount>0)
|
||||
if(!old_druggy)
|
||||
overlay_fullscreen("high", /obj/screen/fullscreen/high)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else if(old_druggy)
|
||||
druggy = max(amount, 0)
|
||||
if(druggy)
|
||||
overlay_fullscreen("high", /obj/screen/fullscreen/high)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else
|
||||
clear_fullscreen("high")
|
||||
clear_alert("high")
|
||||
|
||||
/mob/living/carbon/adjust_disgust(amount)
|
||||
var/old_disgust = disgust
|
||||
if(amount>0)
|
||||
disgust = min(disgust+amount, DISGUST_LEVEL_MAXEDOUT)
|
||||
|
||||
else if(old_disgust)
|
||||
disgust = max(disgust+amount, 0)
|
||||
disgust = Clamp(disgust+amount, 0, DISGUST_LEVEL_MAXEDOUT)
|
||||
|
||||
/mob/living/carbon/set_disgust(amount)
|
||||
if(amount >= 0)
|
||||
disgust = amount
|
||||
disgust = Clamp(amount, 0, DISGUST_LEVEL_MAXEDOUT)
|
||||
|
||||
/mob/living/carbon/cure_blind()
|
||||
if(disabilities & BLIND)
|
||||
|
||||
@@ -153,6 +153,7 @@
|
||||
if(back)
|
||||
overlays_standing[BACK_LAYER] = back.build_worn_icon(state = back.icon_state, default_layer = BACK_LAYER, default_icon_file = 'icons/mob/back.dmi')
|
||||
update_hud_back(back)
|
||||
|
||||
apply_overlay(BACK_LAYER)
|
||||
|
||||
/mob/living/carbon/update_inv_head()
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
dust_animation()
|
||||
spawn_dust(just_ash)
|
||||
qdel(src)
|
||||
QDEL_IN(src,5) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes.
|
||||
|
||||
/mob/living/proc/dust_animation()
|
||||
return
|
||||
@@ -73,6 +73,9 @@
|
||||
med_hud_set_health()
|
||||
med_hud_set_status()
|
||||
|
||||
if (client)
|
||||
client.move_delay = initial(client.move_delay)
|
||||
|
||||
for(var/s in ownedSoullinks)
|
||||
var/datum/soullink/S = s
|
||||
S.ownerDies(gibbed)
|
||||
|
||||
@@ -325,6 +325,7 @@
|
||||
message = "snores."
|
||||
message_mime = "sleeps soundly."
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
stat_allowed = UNCONSCIOUS
|
||||
|
||||
/datum/emote/living/stare
|
||||
key = "stare"
|
||||
@@ -521,6 +522,8 @@
|
||||
|
||||
/datum/emote/living/slap/run_emote(mob/user, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/obj/item/slapper/N = new(user)
|
||||
if(user.put_in_hands(N))
|
||||
to_chat(user, "<span class='notice'>You ready your slapping hand.</span>")
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
if(digitalinvis)
|
||||
handle_diginvis() //AI becomes unable to see mob
|
||||
|
||||
if((movement_type & FLYING) && !floating) //TODO: Better floating
|
||||
float(on = TRUE)
|
||||
|
||||
if (notransform)
|
||||
return
|
||||
if(!loc)
|
||||
@@ -92,7 +95,7 @@
|
||||
ExtinguishMob()
|
||||
return
|
||||
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
|
||||
if(!G.gases["o2"] || G.gases["o2"][MOLES] < 1)
|
||||
if(!G.gases[/datum/gas/oxygen] || G.gases[/datum/gas/oxygen][MOLES] < 1)
|
||||
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
|
||||
return
|
||||
var/turf/location = get_turf(src)
|
||||
@@ -123,5 +126,3 @@
|
||||
|
||||
/mob/living/proc/update_damage_hud()
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -107,7 +107,6 @@
|
||||
/mob/living/proc/MobCollide(mob/M)
|
||||
//Even if we don't push/swap places, we "touched" them, so spread fire
|
||||
spreadFire(M)
|
||||
|
||||
//Also diseases
|
||||
for(var/thing in viruses)
|
||||
var/datum/disease/D = thing
|
||||
@@ -120,7 +119,8 @@
|
||||
ContactContractDisease(D)
|
||||
|
||||
if(now_pushing)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
|
||||
//Should stop you pushing a restrained person out of the way
|
||||
if(isliving(M))
|
||||
@@ -174,7 +174,7 @@
|
||||
M.pass_flags &= ~PASSMOB
|
||||
|
||||
now_pushing = 0
|
||||
|
||||
|
||||
if(!move_failed)
|
||||
return 1
|
||||
|
||||
@@ -564,7 +564,7 @@
|
||||
if(!force_moving)
|
||||
..(pressure_difference, direction, pressure_resistance_prob_delta)
|
||||
|
||||
/mob/living/proc/can_resist()
|
||||
/mob/living/can_resist()
|
||||
return !((next_move > world.time) || incapacitated(ignore_restraints = TRUE))
|
||||
|
||||
/mob/living/verb/resist()
|
||||
@@ -758,16 +758,6 @@
|
||||
/mob/living/proc/get_standard_pixel_y_offset(lying = 0)
|
||||
return initial(pixel_y)
|
||||
|
||||
/mob/living/Stat()
|
||||
..()
|
||||
|
||||
if(statpanel("Status"))
|
||||
if(SSticker && SSticker.mode)
|
||||
if(istype(SSticker.mode, /datum/game_mode/blob))
|
||||
var/datum/game_mode/blob/B = SSticker.mode
|
||||
if(B.message_sent)
|
||||
stat(null, "Blobs to Blob Win: [GLOB.blobs_legit.len]/[B.blobwincount]")
|
||||
|
||||
/mob/living/cancel_camera()
|
||||
..()
|
||||
cameraFollow = null
|
||||
@@ -885,6 +875,19 @@
|
||||
G.Recall()
|
||||
to_chat(G, "<span class='holoparasite'>Your summoner has changed form!</span>")
|
||||
|
||||
/mob/living/rad_act(amount)
|
||||
if(!amount || amount < RAD_MOB_SKIN_PROTECTION)
|
||||
return
|
||||
|
||||
amount -= RAD_BACKGROUND_RADIATION // This will always be at least 1 because of how skin protection is calculated
|
||||
|
||||
var/blocked = getarmor(null, "rad")
|
||||
|
||||
if(amount > RAD_BURN_THRESHOLD)
|
||||
apply_damage((amount-RAD_BURN_THRESHOLD)/RAD_BURN_THRESHOLD, BURN, null, blocked)
|
||||
|
||||
apply_effect((amount*RAD_MOB_COEFFICIENT)/max(1, (radiation**2)*RAD_OVERDOSE_REDUCTION), IRRADIATE, blocked)
|
||||
|
||||
/mob/living/proc/fakefireextinguish()
|
||||
return
|
||||
|
||||
@@ -1018,4 +1021,4 @@
|
||||
|
||||
/mob/living/proc/add_abilities_to_panel()
|
||||
for(var/obj/effect/proc_holder/A in abilities)
|
||||
statpanel("[A.panel]",A.get_panel_text(),A)
|
||||
statpanel("[A.panel]",A.get_panel_text(),A)
|
||||
|
||||
@@ -338,18 +338,11 @@
|
||||
/mob/living/ratvar_act()
|
||||
if(status_flags & GODMODE)
|
||||
return
|
||||
|
||||
if(stat != DEAD && !is_servant_of_ratvar(src))
|
||||
for(var/obj/item/implant/mindshield/M in implants)
|
||||
qdel(M)
|
||||
if(!add_servant_of_ratvar(src))
|
||||
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
|
||||
adjustFireLoss(35)
|
||||
if(src)
|
||||
adjust_fire_stacks(1)
|
||||
IgniteMob()
|
||||
return FALSE
|
||||
return TRUE
|
||||
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
|
||||
adjust_fire_stacks(20)
|
||||
IgniteMob()
|
||||
return FALSE
|
||||
|
||||
|
||||
//called when the mob receives a bright flash
|
||||
|
||||
@@ -69,7 +69,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
"÷" = "cords"
|
||||
))
|
||||
|
||||
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null)
|
||||
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE)
|
||||
var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
|
||||
var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
|
||||
|
||||
@@ -105,7 +105,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
say_dead(original_message)
|
||||
return
|
||||
|
||||
if(check_emote(original_message) || !can_speak_basic(original_message))
|
||||
if(check_emote(original_message) || !can_speak_basic(original_message, ignore_spam))
|
||||
return
|
||||
|
||||
if(in_critical)
|
||||
@@ -270,12 +270,12 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
if(can_speak_basic(message) && can_speak_vocal(message))
|
||||
return 1
|
||||
|
||||
/mob/living/proc/can_speak_basic(message) //Check BEFORE handling of xeno and ling channels
|
||||
/mob/living/proc/can_speak_basic(message, ignore_spam = FALSE) //Check BEFORE handling of xeno and ling channels
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "<span class='danger'>You cannot speak in IC (muted).</span>")
|
||||
return 0
|
||||
if(client.handle_spam_prevention(message,MUTE_IC))
|
||||
if(!ignore_spam && client.handle_spam_prevention(message,MUTE_IC))
|
||||
return 0
|
||||
|
||||
return 1
|
||||
@@ -362,7 +362,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
if(message_mode == MODE_VOCALCORDS)
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C = src
|
||||
var/obj/item/organ/vocal_cords/V = C.getorganslot("vocal_cords")
|
||||
var/obj/item/organ/vocal_cords/V = C.getorganslot(ORGAN_SLOT_VOICE)
|
||||
if(V && V.can_speak_with())
|
||||
V.handle_speech(message) //message
|
||||
V.speak_with(message) //action
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
var/chnotify = 0
|
||||
|
||||
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
|
||||
..()
|
||||
. = ..()
|
||||
if(!target_ai) //If there is no player/brain inside.
|
||||
new/obj/structure/AIcore/deactivated(loc) //New empty terminal.
|
||||
qdel(src)//Delete AI.
|
||||
@@ -143,8 +143,8 @@
|
||||
if(isturf(loc))
|
||||
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
|
||||
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall,\
|
||||
/mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/set_automatic_say_channel)
|
||||
/mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, \
|
||||
/mob/living/silicon/ai/proc/set_automatic_say_channel)
|
||||
|
||||
GLOB.ai_list += src
|
||||
GLOB.shuttle_caller_list += src
|
||||
@@ -813,12 +813,16 @@
|
||||
return FALSE
|
||||
if(be_close && !in_range(M, src))
|
||||
return FALSE
|
||||
//stop AIs from leaving windows open and using then after they lose vision
|
||||
//apc_override is needed here because AIs use their own APC when powerless
|
||||
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
|
||||
if(M && GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
|
||||
return FALSE
|
||||
return TRUE
|
||||
return can_see(M) //stop AIs from leaving windows open and using then after they lose vision
|
||||
|
||||
/mob/living/silicon/ai/proc/can_see(atom/A)
|
||||
if(isturf(loc)) //AI in core, check if on cameras
|
||||
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
|
||||
//apc_override is needed here because AIs use their own APC when depowered
|
||||
return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(get_turf_pixel(A))) || apc_override
|
||||
//AI is carded/shunted
|
||||
//view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist
|
||||
return get_dist(src, A) <= client.view
|
||||
|
||||
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
|
||||
@@ -988,6 +992,6 @@
|
||||
return
|
||||
|
||||
/mob/living/silicon/ai/spawned/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
|
||||
. = ..()
|
||||
if(!target_ai)
|
||||
target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct
|
||||
..()
|
||||
|
||||
@@ -110,6 +110,8 @@
|
||||
if(obscuredTurfs[t])
|
||||
if(!t.obscured)
|
||||
t.obscured = image('icons/effects/cameravis.dmi', t, null, LIGHTING_LAYER+1)
|
||||
t.obscured.pixel_x = -t.pixel_x
|
||||
t.obscured.pixel_y = -t.pixel_y
|
||||
t.obscured.plane = LIGHTING_PLANE+1
|
||||
obscured += t.obscured
|
||||
for(var/eye in seenby)
|
||||
@@ -165,6 +167,8 @@
|
||||
var/turf/t = turf
|
||||
if(!t.obscured)
|
||||
t.obscured = image('icons/effects/cameravis.dmi', t, null, LIGHTING_LAYER+1)
|
||||
t.obscured.pixel_x = -t.pixel_x
|
||||
t.obscured.pixel_y = -t.pixel_y
|
||||
t.obscured.plane = LIGHTING_PLANE+1
|
||||
obscured += t.obscured
|
||||
|
||||
|
||||
@@ -139,9 +139,12 @@
|
||||
ai_restore_power()
|
||||
return
|
||||
switch(PRP)
|
||||
if (1) to_chat(src, "APC located. Optimizing route to APC to avoid needless power waste.")
|
||||
if (2) to_chat(src, "Best route identified. Hacking offline APC power port.")
|
||||
if (3) to_chat(src, "Power port upload access confirmed. Loading control program into APC power port software.")
|
||||
if (1)
|
||||
to_chat(src, "APC located. Optimizing route to APC to avoid needless power waste.")
|
||||
if (2)
|
||||
to_chat(src, "Best route identified. Hacking offline APC power port.")
|
||||
if (3)
|
||||
to_chat(src, "Power port upload access confirmed. Loading control program into APC power port software.")
|
||||
if (4)
|
||||
to_chat(src, "Transfer complete. Forcing APC to execute program.")
|
||||
sleep(50)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/mob/living/silicon/Login()
|
||||
if(mind && SSticker.mode)
|
||||
SSticker.mode.remove_cultist(mind, 0, 0)
|
||||
SSticker.mode.remove_revolutionary(mind, TRUE)
|
||||
var/datum/antagonist/rev/rev = mind.has_antag_datum(/datum/antagonist/rev)
|
||||
if(rev)
|
||||
rev.remove_revolutionary(TRUE)
|
||||
..()
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
var/list/software = list()
|
||||
var/userDNA // The DNA string of our assigned user
|
||||
var/obj/item/device/paicard/card // The card we inhabit
|
||||
var/hacking = FALSE //Are we hacking a door?
|
||||
|
||||
var/speakStatement = "states"
|
||||
var/speakExclamation = "declares"
|
||||
@@ -121,6 +122,29 @@
|
||||
emittersemicd = TRUE
|
||||
addtimer(CALLBACK(src, .proc/emittercool), 600)
|
||||
|
||||
/mob/living/silicon/pai/Life()
|
||||
if(hacking)
|
||||
process_hack()
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/pai/proc/process_hack()
|
||||
|
||||
if(cable && cable.machine && istype(cable.machine, /obj/machinery/door) && cable.machine == hackdoor && get_dist(src, hackdoor) <= 1)
|
||||
hackprogress = Clamp(hackprogress + 4, 0, 100)
|
||||
else
|
||||
temp = "Door Jack: Connection to airlock has been lost. Hack aborted."
|
||||
hackprogress = 0
|
||||
hacking = FALSE
|
||||
hackdoor = null
|
||||
return
|
||||
if(screen == "doorjack" && subscreen == 0) // Update our view, if appropriate
|
||||
paiInterface()
|
||||
if(hackprogress >= 100)
|
||||
hackprogress = 0
|
||||
var/obj/machinery/door/D = cable.machine
|
||||
D.open()
|
||||
hacking = FALSE
|
||||
|
||||
/mob/living/silicon/pai/make_laws()
|
||||
laws = new /datum/ai_laws/pai()
|
||||
return TRUE
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
var/savefile/F = new /savefile(src.savefile_path(user))
|
||||
|
||||
|
||||
WRITE_FILE(F["name"], name)
|
||||
WRITE_FILE(F["description"], description)
|
||||
WRITE_FILE(F["role"], role)
|
||||
WRITE_FILE(F["comments"], comments)
|
||||
WRITE_FILE(F["name"], name)
|
||||
WRITE_FILE(F["description"], description)
|
||||
WRITE_FILE(F["role"], role)
|
||||
WRITE_FILE(F["comments"], comments)
|
||||
|
||||
WRITE_FILE(F["version"], 1)
|
||||
WRITE_FILE(F["version"], 1)
|
||||
|
||||
return 1
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
|
||||
var/savefile/F = new /savefile(path)
|
||||
|
||||
if(!F) return //Not everyone has a pai savefile.
|
||||
if(!F)
|
||||
return //Not everyone has a pai savefile.
|
||||
|
||||
var/version = null
|
||||
F["version"] >> version
|
||||
|
||||
@@ -28,44 +28,44 @@
|
||||
var/dat = ""
|
||||
var/left_part = ""
|
||||
var/right_part = softwareMenu()
|
||||
src.set_machine(src)
|
||||
set_machine(src)
|
||||
|
||||
if(temp)
|
||||
left_part = temp
|
||||
else if(src.stat == DEAD) // Show some flavor text if the pAI is dead
|
||||
else if(stat == DEAD) // Show some flavor text if the pAI is dead
|
||||
left_part = "<b><font color=red>�Rr�R �a�� ��Rr����o�</font></b>"
|
||||
right_part = "<pre>Program index hash not found</pre>"
|
||||
|
||||
else
|
||||
switch(src.screen) // Determine which interface to show here
|
||||
switch(screen) // Determine which interface to show here
|
||||
if("main")
|
||||
left_part = ""
|
||||
if("directives")
|
||||
left_part = src.directives()
|
||||
left_part = directives()
|
||||
if("pdamessage")
|
||||
left_part = src.pdamessage()
|
||||
left_part = pdamessage()
|
||||
if("buy")
|
||||
left_part = downloadSoftware()
|
||||
if("manifest")
|
||||
left_part = src.softwareManifest()
|
||||
left_part = softwareManifest()
|
||||
if("medicalrecord")
|
||||
left_part = src.softwareMedicalRecord()
|
||||
left_part = softwareMedicalRecord()
|
||||
if("securityrecord")
|
||||
left_part = src.softwareSecurityRecord()
|
||||
left_part = softwareSecurityRecord()
|
||||
if("translator")
|
||||
left_part = src.softwareTranslator()
|
||||
left_part = softwareTranslator()
|
||||
if("atmosensor")
|
||||
left_part = src.softwareAtmo()
|
||||
left_part = softwareAtmo()
|
||||
if("securityhud")
|
||||
left_part = src.facialRecognition()
|
||||
left_part = facialRecognition()
|
||||
if("medicalhud")
|
||||
left_part = src.medicalAnalysis()
|
||||
left_part = medicalAnalysis()
|
||||
if("doorjack")
|
||||
left_part = src.softwareDoor()
|
||||
left_part = softwareDoor()
|
||||
if("camerajack")
|
||||
left_part = src.softwareCamera()
|
||||
left_part = softwareCamera()
|
||||
if("signaller")
|
||||
left_part = src.softwareSignal()
|
||||
left_part = softwareSignal()
|
||||
|
||||
//usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc
|
||||
|
||||
@@ -119,16 +119,16 @@
|
||||
var/soft = href_list["software"]
|
||||
var/sub = href_list["sub"]
|
||||
if(soft)
|
||||
src.screen = soft
|
||||
screen = soft
|
||||
if(sub)
|
||||
src.subscreen = text2num(sub)
|
||||
subscreen = text2num(sub)
|
||||
switch(soft)
|
||||
// Purchasing new software
|
||||
if("buy")
|
||||
if(subscreen == 1)
|
||||
var/target = href_list["buy"]
|
||||
if(available_software.Find(target) && !software.Find(target))
|
||||
var/cost = src.available_software[target]
|
||||
var/cost = available_software[target]
|
||||
if(ram >= cost)
|
||||
software.Add(target)
|
||||
ram -= cost
|
||||
@@ -196,7 +196,8 @@
|
||||
var/mob/living/M = card.loc
|
||||
var/count = 0
|
||||
while(!isliving(M))
|
||||
if(!M || !M.loc) return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
|
||||
if(!M || !M.loc)
|
||||
return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
|
||||
M = M.loc
|
||||
count++
|
||||
if(count >= 6)
|
||||
@@ -248,7 +249,7 @@
|
||||
medHUD = !medHUD
|
||||
if(medHUD)
|
||||
add_med_hud()
|
||||
|
||||
|
||||
else
|
||||
var/datum/atom_hud/med = GLOB.huds[med_hud]
|
||||
med.remove_hud_from(src)
|
||||
@@ -259,17 +260,17 @@
|
||||
// this is PERMAMENT.
|
||||
if("doorjack")
|
||||
if(href_list["jack"])
|
||||
if(src.cable && src.cable.machine)
|
||||
src.hackdoor = src.cable.machine
|
||||
src.hackloop()
|
||||
if(cable && cable.machine)
|
||||
hackdoor = cable.machine
|
||||
hackloop()
|
||||
if(href_list["cancel"])
|
||||
src.hackdoor = null
|
||||
hackdoor = null
|
||||
if(href_list["cable"])
|
||||
var/turf/T = get_turf(src.loc)
|
||||
var/turf/T = get_turf(loc)
|
||||
cable = new /obj/item/pai_cable(T)
|
||||
T.visible_message("<span class='warning'>A port on [src] opens to reveal [src.cable], which promptly falls to the floor.</span>", "<span class='italics'>You hear the soft click of something light and hard falling to the ground.</span>")
|
||||
//src.updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window
|
||||
src.paiInterface() // So we'll just call the update directly rather than doing some default checks
|
||||
T.visible_message("<span class='warning'>A port on [src] opens to reveal [cable], which promptly falls to the floor.</span>", "<span class='italics'>You hear the soft click of something light and hard falling to the ground.</span>")
|
||||
//updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window
|
||||
paiInterface() // So we'll just call the update directly rather than doing some default checks
|
||||
return
|
||||
|
||||
// MENUS
|
||||
@@ -287,7 +288,7 @@
|
||||
|
||||
// Basic
|
||||
dat += "<b>Basic</b> <br>"
|
||||
for(var/s in src.software)
|
||||
for(var/s in software)
|
||||
if(s == "digital messenger")
|
||||
dat += "<a href='byond://?src=\ref[src];software=pdamessage;sub=0'>Digital Messenger</a> <br>"
|
||||
if(s == "crew manifest")
|
||||
@@ -304,15 +305,15 @@
|
||||
|
||||
// Advanced
|
||||
dat += "<b>Advanced</b> <br>"
|
||||
for(var/s in src.software)
|
||||
for(var/s in software)
|
||||
if(s == "atmosphere sensor")
|
||||
dat += "<a href='byond://?src=\ref[src];software=atmosensor;sub=0'>Atmospheric Sensor</a> <br>"
|
||||
if(s == "heartbeat sensor")
|
||||
dat += "<a href='byond://?src=\ref[src];software=[s]'>Heartbeat Sensor</a> <br>"
|
||||
if(s == "security HUD")
|
||||
dat += "<a href='byond://?src=\ref[src];software=securityhud;sub=0'>Facial Recognition Suite</a>[(src.secHUD) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=securityhud;sub=0'>Facial Recognition Suite</a>[(secHUD) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
if(s == "medical HUD")
|
||||
dat += "<a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Medical Analysis Suite</a>[(src.medHUD) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Medical Analysis Suite</a>[(medHUD) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
if(s == "universal translator")
|
||||
var/translator_on = (flags_2 & OMNITONGUE_2)
|
||||
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a>[translator_on ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
@@ -333,12 +334,12 @@
|
||||
var/dat = ""
|
||||
|
||||
dat += "<h2>CentCom pAI Module Subversion Network</h2><br>"
|
||||
dat += "<pre>Remaining Available Memory: [src.ram]</pre><br>"
|
||||
dat += "<pre>Remaining Available Memory: [ram]</pre><br>"
|
||||
dat += "<p style=\"text-align:center\"><b>Trunks available for checkout</b><br>"
|
||||
|
||||
for(var/s in available_software)
|
||||
if(!software.Find(s))
|
||||
var/cost = src.available_software[s]
|
||||
var/cost = available_software[s]
|
||||
var/displayName = uppertext(s)
|
||||
dat += "<a href='byond://?src=\ref[src];software=buy;sub=1;buy=[s]'>[displayName]</a> ([cost]) <br>"
|
||||
else
|
||||
@@ -351,12 +352,12 @@
|
||||
/mob/living/silicon/pai/proc/directives()
|
||||
var/dat = ""
|
||||
|
||||
dat += "[(src.master) ? "Your master: [src.master] ([src.master_dna])" : "You are bound to no one."]"
|
||||
dat += "[(master) ? "Your master: [master] ([master_dna])" : "You are bound to no one."]"
|
||||
dat += "<br><br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=directive;getdna=1'>Request carrier DNA sample</a><br>"
|
||||
dat += "<h2>Directives</h2><br>"
|
||||
dat += "<b>Prime Directive</b><br>"
|
||||
dat += " [src.laws.zeroth]<br>"
|
||||
dat += " [laws.zeroth]<br>"
|
||||
dat += "<b>Supplemental Directives</b><br>"
|
||||
for(var/slaws in laws.supplied)
|
||||
dat += " [slaws]<br>"
|
||||
@@ -398,14 +399,14 @@
|
||||
Frequency:
|
||||
<A href='byond://?src=\ref[src];software=signaller;freq=-10;'>-</A>
|
||||
<A href='byond://?src=\ref[src];software=signaller;freq=-2'>-</A>
|
||||
[format_frequency(src.sradio.frequency)]
|
||||
[format_frequency(sradio.frequency)]
|
||||
<A href='byond://?src=\ref[src];software=signaller;freq=2'>+</A>
|
||||
<A href='byond://?src=\ref[src];software=signaller;freq=10'>+</A><BR>
|
||||
|
||||
Code:
|
||||
<A href='byond://?src=\ref[src];software=signaller;code=-5'>-</A>
|
||||
<A href='byond://?src=\ref[src];software=signaller;code=-1'>-</A>
|
||||
[src.sradio.code]
|
||||
[sradio.code]
|
||||
<A href='byond://?src=\ref[src];software=signaller;code=1'>+</A>
|
||||
<A href='byond://?src=\ref[src];software=signaller;code=5'>+</A><BR>
|
||||
|
||||
@@ -476,7 +477,7 @@
|
||||
/mob/living/silicon/pai/proc/facialRecognition()
|
||||
var/dat = {"<h3>Facial Recognition Suite</h3><br>
|
||||
When enabled, this package will scan all viewable faces and compare them against the known criminal database, providing real-time graphical data about any detected persons of interest.<br><br>
|
||||
The package is currently [ (src.secHUD) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>
|
||||
The package is currently [ (secHUD) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>
|
||||
<a href='byond://?src=\ref[src];software=securityhud;sub=0;toggle=1'>Toggle Package</a><br>
|
||||
"}
|
||||
return dat
|
||||
@@ -484,16 +485,16 @@
|
||||
// Medical HUD
|
||||
/mob/living/silicon/pai/proc/medicalAnalysis()
|
||||
var/dat = ""
|
||||
if(src.subscreen == 0)
|
||||
if(subscreen == 0)
|
||||
dat += {"<h3>Medical Analysis Suite</h3><br>
|
||||
<h4>Visual Status Overlay</h4><br>
|
||||
When enabled, this package will scan all nearby crewmembers' vitals and provide real-time graphical data about their state of health.<br><br>
|
||||
The suite is currently [ (src.medHUD) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>
|
||||
The suite is currently [ (medHUD) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>
|
||||
<a href='byond://?src=\ref[src];software=medicalhud;sub=0;toggle=1'>Toggle Suite</a><br>
|
||||
<br>
|
||||
<a href='byond://?src=\ref[src];software=medicalhud;sub=1'>Host Bioscan</a><br>
|
||||
"}
|
||||
if(src.subscreen == 1)
|
||||
if(subscreen == 1)
|
||||
dat += {"<h3>Medical Analysis Suite</h3><br>
|
||||
<h4>Host Bioscan</h4><br>
|
||||
"}
|
||||
@@ -501,8 +502,8 @@
|
||||
if(!isliving(M))
|
||||
while(!isliving(M))
|
||||
if(isturf(M))
|
||||
src.temp = "Error: No biological host found. <br>"
|
||||
src.subscreen = 0
|
||||
temp = "Error: No biological host found. <br>"
|
||||
subscreen = 0
|
||||
return dat
|
||||
M = M.loc
|
||||
dat += {"Bioscan Results for [M]: <br>"
|
||||
@@ -529,7 +530,7 @@
|
||||
/mob/living/silicon/pai/proc/softwareAtmo()
|
||||
var/dat = "<h3>Atmospheric Sensor</h4>"
|
||||
|
||||
var/turf/T = get_turf(src.loc)
|
||||
var/turf/T = get_turf(loc)
|
||||
if (isnull(T))
|
||||
dat += "Unable to obtain a reading.<br>"
|
||||
else
|
||||
@@ -556,14 +557,14 @@
|
||||
var/dat = "<h3>Camera Jack</h3>"
|
||||
dat += "Cable status : "
|
||||
|
||||
if(!src.cable)
|
||||
if(!cable)
|
||||
dat += "<font color=#FF5555>Retracted</font> <br>"
|
||||
return dat
|
||||
if(!src.cable.machine)
|
||||
if(!cable.machine)
|
||||
dat += "<font color=#FFFF55>Extended</font> <br>"
|
||||
return dat
|
||||
|
||||
var/obj/machinery/machine = src.cable.machine
|
||||
var/obj/machinery/machine = cable.machine
|
||||
dat += "<font color=#55FF55>Connected</font> <br>"
|
||||
|
||||
if(!istype(machine, /obj/machinery/camera))
|
||||
@@ -574,55 +575,37 @@
|
||||
/mob/living/silicon/pai/proc/softwareDoor()
|
||||
var/dat = "<h3>Airlock Jack</h3>"
|
||||
dat += "Cable status : "
|
||||
if(!src.cable)
|
||||
if(!cable)
|
||||
dat += "<font color=#FF5555>Retracted</font> <br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=doorjack;cable=1;sub=0'>Extend Cable</a> <br>"
|
||||
return dat
|
||||
if(!src.cable.machine)
|
||||
if(!cable.machine)
|
||||
dat += "<font color=#FFFF55>Extended</font> <br>"
|
||||
return dat
|
||||
|
||||
var/obj/machinery/machine = src.cable.machine
|
||||
var/obj/machinery/machine = cable.machine
|
||||
dat += "<font color=#55FF55>Connected</font> <br>"
|
||||
if(!istype(machine, /obj/machinery/door))
|
||||
dat += "Connected device's firmware does not appear to be compatible with Airlock Jack protocols.<br>"
|
||||
return dat
|
||||
// var/obj/machinery/airlock/door = machine
|
||||
|
||||
if(!src.hackdoor)
|
||||
if(!hackdoor)
|
||||
dat += "<a href='byond://?src=\ref[src];software=doorjack;jack=1;sub=0'>Begin Airlock Jacking</a> <br>"
|
||||
else
|
||||
dat += "Jack in progress... [src.hackprogress]% complete.<br>"
|
||||
dat += "Jack in progress... [hackprogress]% complete.<br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=doorjack;cancel=1;sub=0'>Cancel Airlock Jack</a> <br>"
|
||||
//src.hackdoor = machine
|
||||
//src.hackloop()
|
||||
return dat
|
||||
|
||||
// Door Jack - supporting proc
|
||||
/mob/living/silicon/pai/proc/hackloop()
|
||||
var/turf/T = get_turf(src.loc)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
|
||||
if(T.loc)
|
||||
to_chat(AI, "<font color = red><b>Network Alert: Brute-force encryption crack in progress in [T.loc].</b></font>")
|
||||
else
|
||||
to_chat(AI, "<font color = red><b>Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.</b></font>")
|
||||
while(src.hackprogress < 100)
|
||||
if(src.cable && src.cable.machine && istype(src.cable.machine, /obj/machinery/door) && src.cable.machine == src.hackdoor && get_dist(src, src.hackdoor) <= 1)
|
||||
hackprogress += rand(1, 10)
|
||||
else
|
||||
src.temp = "Door Jack: Connection to airlock has been lost. Hack aborted."
|
||||
hackprogress = 0
|
||||
src.hackdoor = null
|
||||
return
|
||||
if(hackprogress >= 100) // This is clunky, but works. We need to make sure we don't ever display a progress greater than 100,
|
||||
hackprogress = 100 // but we also need to reset the progress AFTER it's been displayed
|
||||
if(src.screen == "doorjack" && src.subscreen == 0) // Update our view, if appropriate
|
||||
src.paiInterface()
|
||||
if(hackprogress >= 100)
|
||||
src.hackprogress = 0
|
||||
var/obj/machinery/door/D = cable.machine
|
||||
D.open()
|
||||
sleep(50) // Update every 5 seconds
|
||||
hacking = TRUE
|
||||
|
||||
// Digital Messenger
|
||||
/mob/living/silicon/pai/proc/pdamessage()
|
||||
@@ -635,7 +618,7 @@
|
||||
dat += "<ul>"
|
||||
if(!pda.toff)
|
||||
for (var/obj/item/device/pda/P in sortNames(get_viewable_pdas()))
|
||||
if (P == src.pda)
|
||||
if (P == pda)
|
||||
continue
|
||||
dat += "<li><a href='byond://?src=\ref[src];software=pdamessage;target=\ref[P]'>[P]</a>"
|
||||
dat += "</li>"
|
||||
|
||||
@@ -11,33 +11,21 @@
|
||||
/mob/living/silicon/robot/proc/uneq_module(obj/item/O)
|
||||
if(!O)
|
||||
return 0
|
||||
O.mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
if(istype(O, /obj/item/borg/sight))
|
||||
O.mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
if(istype(O, /obj/item/borg/sight))
|
||||
var/obj/item/borg/sight/S = O
|
||||
sight_mode &= ~S.sight_mode
|
||||
update_sight()
|
||||
else if(istype(O, /obj/item/storage/bag/tray/))
|
||||
var/obj/item/storage/bag/tray/T = O
|
||||
T.do_quick_empty()
|
||||
else if(istype(O,/obj/item/gun/energy/laser/cyborg))
|
||||
laser = 0
|
||||
update_icons()
|
||||
else if(istype(O,/obj/item/gun/energy/disabler/cyborg))
|
||||
disabler = 0
|
||||
update_icons()
|
||||
else if(istype(O,/obj/item/device/dogborg/sleeper))
|
||||
sleeper_g = 0
|
||||
sleeper_r = 0
|
||||
update_icons()
|
||||
var/obj/item/device/dogborg/sleeper/S = O
|
||||
S.go_out()
|
||||
if(client)
|
||||
client.screen -= O
|
||||
observer_screen_update(O,FALSE)
|
||||
O.forceMove(module) //Return item to module so it appears in its contents, so it can be taken out again.
|
||||
|
||||
if(O.flags_1 & DROPDEL_1)
|
||||
O.flags_1 &= ~DROPDEL_1 //we shouldn't HAVE things with DROPDEL_1 in our modules, but better safe than runtiming horribly
|
||||
if(O.flags_1 & DROPDEL_1)
|
||||
O.flags_1 &= ~DROPDEL_1 //we shouldn't HAVE things with DROPDEL_1 in our modules, but better safe than runtiming horribly
|
||||
|
||||
O.dropped(src)
|
||||
|
||||
@@ -62,12 +50,6 @@
|
||||
if(activated(O))
|
||||
to_chat(src, "<span class='warning'>That module is already activated.</span>")
|
||||
return
|
||||
if(istype(O,/obj/item/gun/energy/laser/cyborg))
|
||||
laser = 1
|
||||
update_icons()
|
||||
if(istype(O,/obj/item/gun/energy/disabler/cyborg))
|
||||
disabler = 1
|
||||
update_icons()
|
||||
if(!held_items[1])
|
||||
held_items[1] = O
|
||||
O.screen_loc = inv1.screen_loc
|
||||
@@ -194,7 +176,8 @@
|
||||
|
||||
//toggle_module(module) - Toggles the selection of the module slot specified by "module".
|
||||
/mob/living/silicon/robot/proc/toggle_module(module) //Module is 1-3
|
||||
if(module < 1 || module > 3) return
|
||||
if(module < 1 || module > 3)
|
||||
return
|
||||
|
||||
if(module_selected(module))
|
||||
deselect_module(module)
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
can_buckle = TRUE
|
||||
buckle_lying = FALSE
|
||||
can_ride_typecache = list(/mob/living/carbon/human)
|
||||
var/static/list/can_ride_typecache = typecacheof(/mob/living/carbon/human)
|
||||
|
||||
/mob/living/silicon/robot/get_cell()
|
||||
return cell
|
||||
@@ -1149,7 +1149,7 @@
|
||||
|
||||
/mob/living/silicon/robot/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
|
||||
if(!is_type_in_typecache(M, can_ride_typecache))
|
||||
M.visible_message("<span class='warning'>[M] really can't seem to mount the [src]...</span>")
|
||||
M.visible_message("<span class='warning'>[M] really can't seem to mount [src]...</span>")
|
||||
return
|
||||
if(!riding_datum)
|
||||
riding_datum = new /datum/riding/cyborg(src)
|
||||
|
||||
@@ -305,6 +305,7 @@
|
||||
/obj/item/device/multitool/cyborg,
|
||||
/obj/item/device/t_scanner,
|
||||
/obj/item/device/analyzer,
|
||||
/obj/item/device/geiger_counter,
|
||||
/obj/item/device/assembly/signaler/cyborg,
|
||||
/obj/item/areaeditor/blueprints/cyborg,
|
||||
/obj/item/device/electroadaptive_pseudocircuit,
|
||||
@@ -351,7 +352,8 @@
|
||||
/obj/item/soap/tongue,
|
||||
/obj/item/device/analyzer/nose,
|
||||
/obj/item/device/dogborg/sleeper/K9,
|
||||
/obj/item/gun/energy/disabler/cyborg)
|
||||
/obj/item/gun/energy/disabler/cyborg,
|
||||
/obj/item/pinpointer/crew)
|
||||
emag_modules = list(/obj/item/gun/energy/laser/cyborg)
|
||||
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security,
|
||||
/obj/item/clockwork/weapon/ratvarian_spear)
|
||||
@@ -384,8 +386,9 @@
|
||||
/obj/item/device/analyzer/nose,
|
||||
/obj/item/soap/tongue,
|
||||
/obj/item/device/healthanalyzer,
|
||||
/obj/item/device/dogborg/sleeper,
|
||||
/obj/item/device/dogborg/sleeper/medihound,
|
||||
/obj/item/twohanded/shockpaddles/hound,
|
||||
/obj/item/stack/medical/gauze/cyborg,
|
||||
/obj/item/device/sensor_device)
|
||||
emag_modules = list(/obj/item/dogborg/pounce)
|
||||
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/medical,
|
||||
@@ -404,10 +407,9 @@
|
||||
/obj/item/robot_module/scrubpup
|
||||
name = "Janitor"
|
||||
basic_modules = list(
|
||||
/obj/item/device/assembly/flash/cyborg,
|
||||
/obj/item/dogborg/jaws/small,
|
||||
/obj/item/device/analyzer/nose,
|
||||
/obj/item/soap/tongue,
|
||||
/obj/item/soap/tongue/scrubpup,
|
||||
/obj/item/device/lightreplacer/cyborg,
|
||||
/obj/item/device/dogborg/sleeper/compactor)
|
||||
emag_modules = list(/obj/item/dogborg/pounce)
|
||||
@@ -419,7 +421,7 @@
|
||||
feedback_key = "cyborg_scrubpup"
|
||||
hat_offset = INFINITY
|
||||
clean_on_move = TRUE
|
||||
|
||||
|
||||
/obj/item/robot_module/scrubpup/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
|
||||
..()
|
||||
var/obj/item/device/lightreplacer/LR = locate(/obj/item/device/lightreplacer) in basic_modules
|
||||
@@ -632,14 +634,17 @@
|
||||
/obj/item/retractor,
|
||||
/obj/item/hemostat,
|
||||
/obj/item/cautery,
|
||||
/obj/item/surgicaldrill,
|
||||
/obj/item/scalpel,
|
||||
/obj/item/melee/transforming/energy/sword/cyborg/saw,
|
||||
/obj/item/roller/robo,
|
||||
/obj/item/card/emag,
|
||||
/obj/item/crowbar/cyborg,
|
||||
/obj/item/extinguisher/mini,
|
||||
/obj/item/pinpointer/syndicate_cyborg,
|
||||
/obj/item/stack/medical/gauze/cyborg,
|
||||
/obj/item/gun/medbeam)
|
||||
/obj/item/gun/medbeam,
|
||||
/obj/item/organ_storage)
|
||||
ratvar_modules = list(
|
||||
/obj/item/clockwork/slab/cyborg/medical,
|
||||
/obj/item/clockwork/weapon/ratvarian_spear)
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
diag_hud_set_status()
|
||||
diag_hud_set_health()
|
||||
|
||||
/mob/living/silicon/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/rad_insulation, RAD_NO_INSULATION, TRUE, TRUE)
|
||||
|
||||
/mob/living/silicon/med_hud_set_health()
|
||||
return //we use a different hud
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
icon = 'icons/mob/aibots.dmi'
|
||||
layer = MOB_LAYER
|
||||
gender = NEUTER
|
||||
luminosity = 3
|
||||
light_range = 3
|
||||
stop_automated_movement = 1
|
||||
wander = 0
|
||||
healable = 0
|
||||
|
||||
@@ -124,6 +124,9 @@
|
||||
|
||||
if(!target) //Search for decals then.
|
||||
target = scan(/obj/effect/decal/cleanable)
|
||||
|
||||
if(!target) //Checks for remains
|
||||
target = scan(/obj/effect/decal/remains)
|
||||
|
||||
if(!target && trash) //Then for trash.
|
||||
target = scan(/obj/item/trash)
|
||||
@@ -178,7 +181,8 @@
|
||||
/obj/effect/decal/cleanable/ash,
|
||||
/obj/effect/decal/cleanable/greenglow,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/deadcockroach
|
||||
/obj/effect/decal/cleanable/deadcockroach,
|
||||
/obj/effect/decal/remains
|
||||
)
|
||||
|
||||
if(blood)
|
||||
@@ -206,15 +210,16 @@
|
||||
if(A && isturf(A.loc))
|
||||
var/atom/movable/AM = A
|
||||
if(istype(AM, /obj/effect/decal/cleanable))
|
||||
qdel(AM)
|
||||
for(var/obj/effect/decal/cleanable/C in A.loc)
|
||||
qdel(C)
|
||||
|
||||
anchored = FALSE
|
||||
target = null
|
||||
mode = BOT_IDLE
|
||||
icon_state = "cleanbot[on]"
|
||||
else if(istype(A, /obj/item))
|
||||
else if(istype(A, /obj/item) || istype(A, /obj/effect/decal/remains))
|
||||
visible_message("<span class='danger'>[src] sprays hydrofluoric acid at [A]!</span>")
|
||||
playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6)
|
||||
playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6)
|
||||
A.acid_act(75, 10)
|
||||
else if(istype(A, /mob/living/simple_animal/cockroach) || istype(A, /mob/living/simple_animal/mouse))
|
||||
var/mob/living/simple_animal/M = target
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
|
||||
//Floorbot assemblies
|
||||
/obj/item/toolbox_tiles
|
||||
desc = "It's a toolbox with tiles sticking out the top"
|
||||
desc = "It's a toolbox with tiles sticking out the top."
|
||||
name = "tiles and toolbox"
|
||||
icon = 'icons/mob/aibots.dmi'
|
||||
icon_state = "toolbox_tiles"
|
||||
@@ -205,7 +205,7 @@
|
||||
var/created_name = "Floorbot"
|
||||
|
||||
/obj/item/toolbox_tiles_sensor
|
||||
desc = "It's a toolbox with tiles sticking out the top and a sensor attached"
|
||||
desc = "It's a toolbox with tiles sticking out the top and a sensor attached."
|
||||
name = "tiles, toolbox and sensor arrangement"
|
||||
icon = 'icons/mob/aibots.dmi'
|
||||
icon_state = "toolbox_tiles_sensor"
|
||||
@@ -282,11 +282,11 @@
|
||||
var/skin = null //Same as medbot, set to tox or ointment for the respective kits.
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/firstaid_arm_assembly/New()
|
||||
..()
|
||||
spawn(5)
|
||||
if(skin)
|
||||
add_overlay("kit_skin_[skin]")
|
||||
/obj/item/firstaid_arm_assembly/New()
|
||||
..()
|
||||
spawn(5)
|
||||
if(skin)
|
||||
add_overlay("kit_skin_[skin]")
|
||||
|
||||
/obj/item/storage/firstaid/attackby(obj/item/bodypart/S, mob/user, params)
|
||||
|
||||
@@ -347,6 +347,51 @@
|
||||
S.name = created_name
|
||||
qdel(src)
|
||||
|
||||
|
||||
//Honkbot Assembly
|
||||
/obj/item/honkbot_assembly
|
||||
name = "incomplete honkbot assembly"
|
||||
desc = "The clown's up to no good once more"
|
||||
icon = 'icons/mob/aibots.dmi'
|
||||
icon_state = "honkbot_arm"
|
||||
var/build_step = ASSEMBLY_FIRST_STEP
|
||||
var/created_name = "Honkbot"
|
||||
|
||||
/obj/item/honkbot_assembly/attackby(obj/item/I, mob/user, params)
|
||||
|
||||
if(isprox(I) && (build_step == ASSEMBLY_FIRST_STEP))
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
return
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You add the [I] to [src]!</span>")
|
||||
icon_state = "honkbot_proxy"
|
||||
name = "incomplete Honkbot assembly"
|
||||
qdel(I)
|
||||
|
||||
else if(istype(I, /obj/item/bikehorn) && (build_step == ASSEMBLY_SECOND_STEP))
|
||||
if(istype(loc, /obj/item/storage/backpack)) //don't build them in your backpacks!
|
||||
return
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You add the [I] to [src]! Honk!</span>")
|
||||
var/T = get_turf(loc) //important to spawn on turf.
|
||||
var/mob/living/simple_animal/bot/honkbot/S = new(drop_location(T))
|
||||
S.name = created_name
|
||||
S.spam_flag = TRUE // only long enough to hear the first ping.
|
||||
addtimer(CALLBACK (S, .mob/living/simple_animal/bot/honkbot/proc/react_ping), 5)
|
||||
qdel(I)
|
||||
qdel(src)
|
||||
|
||||
else if(istype(I, /obj/item/pen))
|
||||
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
|
||||
if(!t)
|
||||
return
|
||||
if(!in_range(src, usr) && loc != usr)
|
||||
return
|
||||
created_name = t
|
||||
|
||||
else return ..()
|
||||
|
||||
//Secbot Assembly
|
||||
/obj/item/secbot_assembly
|
||||
name = "incomplete securitron assembly"
|
||||
|
||||
@@ -444,9 +444,7 @@ Auto Patrol[]"},
|
||||
|
||||
var/obj/item/projectile/A = new projectile (loc)
|
||||
playsound(loc, shoot_sound, 50, 1)
|
||||
A.current = U
|
||||
A.yo = U.y - T.y
|
||||
A.xo = U.x - T.x
|
||||
A.preparePixelProjectile(target, src)
|
||||
A.fire()
|
||||
|
||||
/mob/living/simple_animal/bot/ed209/attack_alien(mob/living/carbon/alien/user)
|
||||
|
||||
@@ -287,11 +287,11 @@
|
||||
anchored = TRUE
|
||||
if(PLACE_TILE)
|
||||
F = scan_target
|
||||
if(istype(F, /turf/open/floor/plating)) //The floor must not already have a tile.
|
||||
if(isplatingturf(F)) //The floor must not already have a tile.
|
||||
result = F
|
||||
if(REPLACE_TILE)
|
||||
F = scan_target
|
||||
if(isfloorturf(F) && !istype(F, /turf/open/floor/plating)) //The floor must already have a tile.
|
||||
if(isfloorturf(F) && !isplatingturf(F)) //The floor must already have a tile.
|
||||
result = F
|
||||
if(FIX_TILE) //Selects only damaged floors.
|
||||
F = scan_target
|
||||
@@ -299,7 +299,7 @@
|
||||
result = F
|
||||
if(TILE_EMAG) //Emag mode! Rip up the floor and cause breaches to space!
|
||||
F = scan_target
|
||||
if(!istype(F, /turf/open/floor/plating))
|
||||
if(!isplatingturf(F))
|
||||
result = F
|
||||
else //If no special processing is needed, simply return the result.
|
||||
result = scan_target
|
||||
@@ -329,7 +329,7 @@
|
||||
else
|
||||
var/turf/open/floor/F = target_turf
|
||||
|
||||
if(F.type != initial(tiletype.turf_type) && (F.broken || F.burnt || istype(F, /turf/open/floor/plating)) || F.type == (initial(tiletype.turf_type) && (F.broken || F.burnt)))
|
||||
if(F.type != initial(tiletype.turf_type) && (F.broken || F.burnt || isplatingturf(F)) || F.type == (initial(tiletype.turf_type) && (F.broken || F.burnt)))
|
||||
anchored = TRUE
|
||||
icon_state = "floorbot-c"
|
||||
mode = BOT_REPAIRING
|
||||
@@ -340,7 +340,7 @@
|
||||
F.burnt = 0
|
||||
F.ChangeTurf(/turf/open/floor/plasteel)
|
||||
|
||||
if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !istype(F, /turf/open/floor/plating))
|
||||
if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !isplatingturf(F))
|
||||
anchored = TRUE
|
||||
icon_state = "floorbot-c"
|
||||
mode = BOT_REPAIRING
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
/mob/living/simple_animal/bot/honkbot
|
||||
name = "\improper honkbot"
|
||||
desc = "A little robot. It looks happy with its bike horn."
|
||||
icon = 'icons/mob/aibots.dmi'
|
||||
icon_state = "honkbot"
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
health = 25
|
||||
maxHealth = 25
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
|
||||
pass_flags = PASSMOB
|
||||
|
||||
radio_key = /obj/item/device/encryptionkey/headset_service //doesn't have security key
|
||||
radio_channel = "Service" //Doesn't even use the radio anyway.
|
||||
bot_type = HONK_BOT
|
||||
model = "Honkbot"
|
||||
bot_core_type = /obj/machinery/bot_core/honkbot
|
||||
window_id = "autohonk"
|
||||
window_name = "Honkomatic Bike Horn Unit v1.0.7"
|
||||
data_hud_type = DATA_HUD_SECURITY_BASIC // show jobs
|
||||
|
||||
var/honksound = 'sound/items/bikehorn.ogg' //customizable sound
|
||||
var/spam_flag = FALSE
|
||||
var/cooldowntime = 30
|
||||
var/cooldowntimehorn = 10
|
||||
var/mob/living/carbon/target
|
||||
var/oldtarget_name
|
||||
var/target_lastloc = FALSE //Loc of target when arrested.
|
||||
var/last_found = FALSE //There's a delay
|
||||
var/threatlevel = FALSE
|
||||
var/declare_arrests = FALSE // speak, you shall not, unless to Honk
|
||||
var/idcheck = TRUE
|
||||
var/fcheck = TRUE
|
||||
var/check_records = TRUE
|
||||
var/arrest_type = FALSE
|
||||
var/weaponscheck = TRUE
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/Initialize()
|
||||
. = ..()
|
||||
icon_state = "honkbot[on]"
|
||||
auto_patrol = TRUE
|
||||
var/datum/job/clown/J = new/datum/job/clown
|
||||
access_card.access += J.get_access()
|
||||
prev_access = access_card.access
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/spam_flag_false() //used for addtimer
|
||||
spam_flag = FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/blink_end() //used for addtimer
|
||||
icon_state = "honkbot[on]"
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/sensor_blink()
|
||||
icon_state = "honkbot-c"
|
||||
addtimer(CALLBACK(src, .proc/blink_end), 5)
|
||||
|
||||
//honkbots react with sounds.
|
||||
/mob/living/simple_animal/bot/honkbot/proc/react_ping()
|
||||
playsound(src, 'sound/machines/ping.ogg', 50, 1, -1) //the first sound upon creation!
|
||||
spam_flag = TRUE
|
||||
sensor_blink()
|
||||
addtimer(CALLBACK(src, .proc/spam_flag_false), 18) // calibrates before starting the honk
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/react_buzz()
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1, -1)
|
||||
sensor_blink()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/bot_reset()
|
||||
..()
|
||||
target = null
|
||||
oldtarget_name = null
|
||||
anchored = FALSE
|
||||
walk_to(src,0)
|
||||
last_found = world.time
|
||||
spam_flag = FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/set_custom_texts()
|
||||
|
||||
text_hack = "You overload [name]'s sound control system"
|
||||
text_dehack = "You reboot [name] and restore the sound control system."
|
||||
text_dehack_fail = "[name] refuses to accept your authority!"
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/get_controls(mob/user)
|
||||
var/dat
|
||||
dat += hack(user)
|
||||
dat += showpai(user)
|
||||
dat += text({"
|
||||
<TT><B>Honkomatic Bike Horn Unit v1.0.7 controls</B></TT><BR><BR>
|
||||
Status: []<BR>
|
||||
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
|
||||
Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
|
||||
"<A href='?src=\ref[src];power=[TRUE]'>[on ? "On" : "Off"]</A>" )
|
||||
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
dat += text({"<BR> Auto Patrol: []"},
|
||||
|
||||
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
|
||||
return dat
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/judgement_criteria()
|
||||
var/final = NONE
|
||||
if(check_records)
|
||||
final = final|JUDGE_RECORDCHECK
|
||||
if(emagged)
|
||||
final = final|JUDGE_EMAGGED
|
||||
return final
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/retaliate(mob/living/carbon/human/H)
|
||||
var/judgement_criteria = judgement_criteria()
|
||||
threatlevel = H.assess_threat(judgement_criteria)
|
||||
threatlevel += 6
|
||||
if(threatlevel >= 4)
|
||||
target = H
|
||||
mode = BOT_HUNT
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H)
|
||||
if(H.a_intent == "harm")
|
||||
retaliate(H)
|
||||
addtimer(CALLBACK(src, .proc/react_buzz), 5)
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM).
|
||||
return
|
||||
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Check for welding tool to fix #2432.
|
||||
retaliate(user)
|
||||
addtimer(CALLBACK(src, .proc/react_buzz), 5)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/emag_act(mob/user)
|
||||
..()
|
||||
if(emagged == 2)
|
||||
if(user)
|
||||
user << "<span class='danger'>You short out [src]'s sound control system. It gives out an evil laugh!!</span>"
|
||||
oldtarget_name = user.name
|
||||
audible_message("<span class='danger'>[src] gives out an evil laugh!</span>")
|
||||
playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 75, 1, -1) // evil laughter
|
||||
icon_state = "honkbot[on]"
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/bullet_act(obj/item/projectile/Proj)
|
||||
if((istype(Proj,/obj/item/projectile/beam)) || (istype(Proj,/obj/item/projectile/bullet) && (Proj.damage_type == BURN))||(Proj.damage_type == BRUTE) && (!Proj.nodamage && Proj.damage < health))
|
||||
retaliate(Proj.firer)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/UnarmedAttack(atom/A)
|
||||
if(!on)
|
||||
return
|
||||
if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
if (emagged <= 1)
|
||||
honk_attack(A)
|
||||
else
|
||||
if(!C.IsStun() || arrest_type)
|
||||
stun_attack(A)
|
||||
..()
|
||||
else if (!spam_flag) //honking at the ground
|
||||
bike_horn(A)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
|
||||
if(istype(AM, /obj/item))
|
||||
playsound(src, honksound, 50, 1, -1)
|
||||
var/obj/item/I = AM
|
||||
if(I.throwforce < health && I.thrownby && (istype(I.thrownby, /mob/living/carbon/human)))
|
||||
var/mob/living/carbon/human/H = I.thrownby
|
||||
retaliate(H)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/bike_horn() //use bike_horn
|
||||
if (emagged <= 1)
|
||||
if (!spam_flag)
|
||||
playsound(src, honksound, 50, 1, -1)
|
||||
spam_flag = TRUE //prevent spam
|
||||
sensor_blink()
|
||||
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
|
||||
else if (emagged == 2) //emagged honkbots will spam short and memorable sounds.
|
||||
if (!spam_flag)
|
||||
playsound(src, "honkbot_e", 50, 0)
|
||||
spam_flag = TRUE // prevent spam
|
||||
icon_state = "honkbot-e"
|
||||
addtimer(CALLBACK(src, .proc/blink_end), 30)
|
||||
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/honk_attack(mob/living/carbon/C) // horn attack
|
||||
if(!spam_flag)
|
||||
playsound(loc, honksound, 50, 1, -1)
|
||||
spam_flag = TRUE // prevent spam
|
||||
sensor_blink()
|
||||
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/stun_attack(mob/living/carbon/C) // airhorn stun
|
||||
if(!spam_flag)
|
||||
playsound(loc, 'sound/items/AirHorn.ogg', 100, 1, -1) //HEEEEEEEEEEEENK!!
|
||||
sensor_blink()
|
||||
if(spam_flag == 0)
|
||||
if(ishuman(C))
|
||||
C.stuttering = 20
|
||||
C.adjustEarDamage(0, 5) //far less damage than the H.O.N.K.
|
||||
C.Jitter(50)
|
||||
C.Knockdown(60)
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(client) //prevent spam from players..
|
||||
spam_flag = TRUE
|
||||
if (emagged <= 1) //HONK once, then leave
|
||||
var/judgement_criteria = judgement_criteria()
|
||||
threatlevel = H.assess_threat(judgement_criteria)
|
||||
threatlevel -= 6
|
||||
target = oldtarget_name
|
||||
else // you really don't want to hit an emagged honkbot
|
||||
threatlevel = 6 // will never let you go
|
||||
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntime)
|
||||
|
||||
add_logs(src,C,"honked")
|
||||
|
||||
C.visible_message("<span class='danger'>[src] has honked [C]!</span>",\
|
||||
"<span class='userdanger'>[src] has honked you!</span>")
|
||||
else
|
||||
C.stuttering = 20
|
||||
C.Knockdown(80)
|
||||
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntime)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/handle_automated_action()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
switch(mode)
|
||||
|
||||
if(BOT_IDLE) // idle
|
||||
|
||||
walk_to(src,0)
|
||||
look_for_perp()
|
||||
if(!mode && auto_patrol)
|
||||
mode = BOT_START_PATROL
|
||||
|
||||
if(BOT_HUNT)
|
||||
|
||||
// if can't reach perp for long enough, go idle
|
||||
if(frustration >= 5) //gives up easier than beepsky
|
||||
walk_to(src,0)
|
||||
back_to_idle()
|
||||
return
|
||||
|
||||
if(target) // make sure target exists
|
||||
if(Adjacent(target) && isturf(target.loc))
|
||||
|
||||
if(threatlevel <= 4)
|
||||
honk_attack(target)
|
||||
else
|
||||
if(threatlevel >= 6)
|
||||
set waitfor = 0
|
||||
stun_attack(target)
|
||||
anchored = FALSE
|
||||
target_lastloc = target.loc
|
||||
return
|
||||
|
||||
else // not next to perp
|
||||
var/turf/olddist = get_dist(src, target)
|
||||
walk_to(src, target,1,4)
|
||||
if((get_dist(src, target)) >= (olddist))
|
||||
frustration++
|
||||
else
|
||||
frustration = 0
|
||||
else
|
||||
back_to_idle()
|
||||
|
||||
|
||||
if(BOT_START_PATROL)
|
||||
look_for_perp()
|
||||
start_patrol()
|
||||
|
||||
if(BOT_PATROL)
|
||||
look_for_perp()
|
||||
bot_patrol()
|
||||
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/back_to_idle()
|
||||
anchored = FALSE
|
||||
mode = BOT_IDLE
|
||||
target = null
|
||||
last_found = world.time
|
||||
frustration = 0
|
||||
INVOKE_ASYNC(src, .proc/handle_automated_action) //responds quickly
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/back_to_hunt()
|
||||
anchored = FALSE
|
||||
frustration = 0
|
||||
mode = BOT_HUNT
|
||||
INVOKE_ASYNC(src, .proc/handle_automated_action) // responds quickly
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/look_for_perp()
|
||||
anchored = FALSE
|
||||
for (var/mob/living/carbon/C in view(7,src))
|
||||
if((C.stat) || (C.handcuffed))
|
||||
continue
|
||||
|
||||
if((C.name == oldtarget_name) && (world.time < last_found + 100))
|
||||
continue
|
||||
|
||||
var/judgement_criteria = judgement_criteria()
|
||||
threatlevel = C.assess_threat(judgement_criteria)
|
||||
|
||||
if(threatlevel <= 3)
|
||||
if(C in view(4,src)) //keep the range short for patrolling
|
||||
if(!spam_flag)
|
||||
bike_horn()
|
||||
|
||||
else if(threatlevel >= 10)
|
||||
bike_horn() //just spam the shit outta this
|
||||
|
||||
else if(threatlevel >= 4)
|
||||
if(!spam_flag)
|
||||
target = C
|
||||
oldtarget_name = C.name
|
||||
bike_horn()
|
||||
speak("Honk!")
|
||||
visible_message("<b>[src]</b> starts chasing [C.name]!")
|
||||
mode = BOT_HUNT
|
||||
INVOKE_ASYNC(src, .proc/handle_automated_action)
|
||||
break
|
||||
else
|
||||
continue
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/explode()
|
||||
|
||||
walk_to(src,0)
|
||||
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
|
||||
var/turf/Tsec = get_turf(src)
|
||||
//doesn't drop cardboard nor its assembly, since its a very frail material.
|
||||
if(prob(50))
|
||||
new /obj/item/bodypart/l_arm/robot/(Tsec)
|
||||
new /obj/item/bikehorn(Tsec)
|
||||
new /obj/item/device/assembly/prox_sensor(Tsec)
|
||||
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
new /obj/effect/decal/cleanable/oil(loc)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/attack_alien(var/mob/living/carbon/alien/user as mob)
|
||||
..()
|
||||
if(!isalien(target))
|
||||
target = user
|
||||
mode = BOT_HUNT
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/Crossed(atom/movable/AM)
|
||||
if(ismob(AM) && (on)) //only if its online
|
||||
if(prob(30)) //you're far more likely to trip on a honkbot
|
||||
var/mob/living/carbon/C = AM
|
||||
if(!istype(C) || !C || in_range(src, target))
|
||||
return
|
||||
C.visible_message("<span class='warning'>[pick( \
|
||||
"[C] dives out of [src]'s way!", \
|
||||
"[C] stumbles over [src]!", \
|
||||
"[C] jumps out of [src]'s path!", \
|
||||
"[C] trips over [src] and falls!", \
|
||||
"[C] topples over [src]!", \
|
||||
"[C] leaps out of [src]'s way!")]</span>")
|
||||
C.Knockdown(10)
|
||||
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 1, -1)
|
||||
if(!client)
|
||||
speak("Honk!")
|
||||
sensor_blink()
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/bot_core/honkbot
|
||||
req_one_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
@@ -341,13 +341,16 @@
|
||||
/mob/living/simple_animal/bot/medbot/proc/assess_patient(mob/living/carbon/C)
|
||||
//Time to see if they need medical help!
|
||||
if(C.stat == DEAD || (C.status_flags & FAKEDEATH))
|
||||
return 0 //welp too late for them!
|
||||
return FALSE //welp too late for them!
|
||||
|
||||
if(!(loc == C.loc) || !(isturf(C.loc) && isturf(loc)))
|
||||
return FALSE
|
||||
|
||||
if(C.suiciding)
|
||||
return 0 //Kevorkian school of robotic medical assistants.
|
||||
return FALSE //Kevorkian school of robotic medical assistants.
|
||||
|
||||
if(emagged == 2) //Everyone needs our medicine. (Our medicine is toxins)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if(declare_crit && C.health <= 0) //Critical condition! Call for help!
|
||||
declare(C)
|
||||
@@ -356,20 +359,20 @@
|
||||
if((reagent_glass) && (use_beaker) && ((C.getBruteLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getOxyLoss() >= (heal_threshold + 15))))
|
||||
for(var/datum/reagent/R in reagent_glass.reagents.reagent_list)
|
||||
if(!C.reagents.has_reagent(R.id))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
//They're injured enough for it!
|
||||
if((!C.reagents.has_reagent(treatment_brute_avoid)) && (C.getBruteLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_brute)))
|
||||
return 1 //If they're already medicated don't bother!
|
||||
return TRUE //If they're already medicated don't bother!
|
||||
|
||||
if((!C.reagents.has_reagent(treatment_oxy_avoid)) && (C.getOxyLoss() >= (15 + heal_threshold)) && (!C.reagents.has_reagent(treatment_oxy)))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if((!C.reagents.has_reagent(treatment_fire_avoid)) && (C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_fire)))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if((!C.reagents.has_reagent(treatment_tox_avoid)) && (C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_tox)))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if(treat_virus && !C.reagents.has_reagent(treatment_virus_avoid) && !C.reagents.has_reagent(treatment_virus))
|
||||
for(var/thing in C.viruses)
|
||||
@@ -378,9 +381,9 @@
|
||||
if(!(D.visibility_flags & HIDDEN_SCANNER || D.visibility_flags & HIDDEN_PANDEMIC) \
|
||||
&& D.severity != VIRUS_SEVERITY_POSITIVE \
|
||||
&& (D.stage > 1 || (D.spread_flags & VIRUS_SPREAD_AIRBORNE))) // medibot can't detect a virus in its initial stage unless it spreads airborne.
|
||||
return 1 //STOP DISEASE FOREVER
|
||||
return TRUE //STOP DISEASE FOREVER
|
||||
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/UnarmedAttack(atom/A)
|
||||
if(iscarbon(A))
|
||||
@@ -504,11 +507,11 @@
|
||||
/mob/living/simple_animal/bot/medbot/proc/check_overdose(mob/living/carbon/patient,reagent_id,injection_amount)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[reagent_id]
|
||||
if(!R.overdose_threshold) //Some chems do not have an OD threshold
|
||||
return 0
|
||||
return FALSE
|
||||
var/current_volume = patient.reagents.get_reagent_amount(reagent_id)
|
||||
if(current_volume + injection_amount > R.overdose_threshold)
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/explode()
|
||||
on = FALSE
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
emagged = TRUE
|
||||
if(!open)
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] the [src]'s controls!</span>")
|
||||
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>")
|
||||
flick("mulebot-emagged", src)
|
||||
playsound(src, "sparks", 100, 0)
|
||||
|
||||
@@ -490,7 +490,8 @@
|
||||
|
||||
var/oldloc = loc
|
||||
var/moved = step_towards(src, next) // attempt to move
|
||||
if(cell) cell.use(1)
|
||||
if(cell)
|
||||
cell.use(1)
|
||||
if(moved && oldloc!=loc) // successful move
|
||||
blockcount = 0
|
||||
path -= loc
|
||||
|
||||
@@ -145,7 +145,6 @@
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.current = curloc
|
||||
P.firer = src
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
name = "Syndicate Operative"
|
||||
id_job = "Operative"
|
||||
id_access_list = list(ACCESS_SYNDICATE)
|
||||
hair_style = "Bald"
|
||||
facial_hair_style = "Shaved"
|
||||
outfit = /datum/outfit/syndicatesoldiercorpse
|
||||
|
||||
/datum/outfit/syndicatesoldiercorpse
|
||||
@@ -31,6 +33,8 @@
|
||||
name = "Syndicate Commando"
|
||||
id_job = "Operative"
|
||||
id_access_list = list(ACCESS_SYNDICATE)
|
||||
hair_style = "Bald"
|
||||
facial_hair_style = "Shaved"
|
||||
outfit = /datum/outfit/syndicatecommandocorpse
|
||||
|
||||
/datum/outfit/syndicatecommandocorpse
|
||||
@@ -50,6 +54,8 @@
|
||||
name = "Syndicate Stormtrooper"
|
||||
id_job = "Operative"
|
||||
id_access_list = list(ACCESS_SYNDICATE)
|
||||
hair_style = "Bald"
|
||||
facial_hair_style = "Shaved"
|
||||
outfit = /datum/outfit/syndicatestormtroopercorpse
|
||||
|
||||
/datum/outfit/syndicatestormtroopercorpse
|
||||
@@ -67,11 +73,16 @@
|
||||
/obj/effect/mob_spawn/human/clown/corpse
|
||||
roundstart = FALSE
|
||||
instant = TRUE
|
||||
|
||||
skin_tone = "caucasian1"
|
||||
hair_style = "Bald"
|
||||
facial_hair_style = "Shaved"
|
||||
|
||||
/obj/effect/mob_spawn/human/corpse/pirate
|
||||
name = "Pirate"
|
||||
skin_tone = "Caucasian1" //all pirates are white because it's easier that way
|
||||
outfit = /datum/outfit/piratecorpse
|
||||
hair_style = "Bald"
|
||||
facial_hair_style = "Shaved"
|
||||
|
||||
/datum/outfit/piratecorpse
|
||||
name = "Pirate Corpse"
|
||||
@@ -94,12 +105,17 @@
|
||||
/obj/effect/mob_spawn/human/corpse/russian
|
||||
name = "Russian"
|
||||
outfit = /datum/outfit/russiancorpse
|
||||
hair_style = "Bald"
|
||||
facial_hair_style = "Shaved"
|
||||
|
||||
/datum/outfit/russiancorpse
|
||||
name = "Russian Corpse"
|
||||
uniform = /obj/item/clothing/under/soviet
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
head = /obj/item/clothing/head/bearpelt
|
||||
gloves = /obj/item/clothing/gloves/color/black
|
||||
mask = /obj/item/clothing/mask/gas
|
||||
|
||||
|
||||
|
||||
/obj/effect/mob_spawn/human/corpse/russian/ranged
|
||||
@@ -109,6 +125,7 @@
|
||||
name = "Ranged Russian Corpse"
|
||||
head = /obj/item/clothing/head/ushanka
|
||||
|
||||
|
||||
/obj/effect/mob_spawn/human/corpse/russian/ranged/trooper
|
||||
outfit = /datum/outfit/russiancorpse/ranged/trooper
|
||||
|
||||
@@ -119,8 +136,8 @@
|
||||
shoes = /obj/item/clothing/shoes/combat
|
||||
gloves = /obj/item/clothing/gloves/combat
|
||||
ears = /obj/item/device/radio/headset
|
||||
mask = /obj/item/clothing/mask/balaclava
|
||||
head = /obj/item/clothing/head/helmet/alt
|
||||
mask = /obj/item/clothing/mask/balaclava
|
||||
|
||||
|
||||
/obj/effect/mob_spawn/human/corpse/russian/ranged/officer
|
||||
@@ -131,7 +148,7 @@
|
||||
name = "Russian Officer Corpse"
|
||||
uniform = /obj/item/clothing/under/rank/security/navyblue/russian
|
||||
suit = /obj/item/clothing/suit/security/officer/russian
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
shoes = /obj/item/clothing/shoes/combat
|
||||
ears = /obj/item/device/radio/headset
|
||||
head = /obj/item/clothing/head/ushanka
|
||||
|
||||
@@ -139,6 +156,9 @@
|
||||
/obj/effect/mob_spawn/human/corpse/wizard
|
||||
name = "Space Wizard Corpse"
|
||||
outfit = /datum/outfit/wizardcorpse
|
||||
hair_style = "Bald"
|
||||
facial_hair_style = "Long Beard"
|
||||
skin_tone = "Caucasian1"
|
||||
|
||||
/datum/outfit/wizardcorpse
|
||||
name = "Space Wizard Corpse"
|
||||
@@ -153,6 +173,8 @@
|
||||
id_job = "Private Security Force"
|
||||
id_access = "Security Officer"
|
||||
outfit = /datum/outfit/nanotrasensoldiercorpse2
|
||||
hair_style = "Bald"
|
||||
facial_hair_style = "Shaved"
|
||||
|
||||
/datum/outfit/nanotrasensoldiercorpse2
|
||||
name = "NT Private Security Officer Corpse"
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
/mob/living/simple_animal/pet/cat/update_canmove()
|
||||
..()
|
||||
if(client)
|
||||
if(client && stat != DEAD)
|
||||
if (resting)
|
||||
icon_state = "[icon_living]_rest"
|
||||
else
|
||||
|
||||
@@ -63,7 +63,8 @@
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/show_inv(mob/user)
|
||||
user.set_machine(src)
|
||||
if(user.stat) return
|
||||
if(user.stat)
|
||||
return
|
||||
|
||||
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
|
||||
if(inventory_head)
|
||||
@@ -123,7 +124,8 @@
|
||||
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
|
||||
if(usr.stat) return
|
||||
if(usr.stat)
|
||||
return
|
||||
|
||||
//Removing from inventory
|
||||
if(href_list["remove_inv"])
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
gold_core_spawnable = 2
|
||||
|
||||
/mob/living/simple_animal/pet/penguin/emperor/shamebrero
|
||||
name = "Shamebrero penguin."
|
||||
name = "Shamebrero penguin"
|
||||
desc = "Shameful of all he surveys."
|
||||
icon_state = "penguin_shamebrero"
|
||||
icon_living = "penguin_shamebrero"
|
||||
|
||||
@@ -143,7 +143,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(src, "<span class='danger'>Your summoner has died!</span>")
|
||||
visible_message("<span class='danger'><B>The [src] dies along with its user!</B></span>")
|
||||
visible_message("<span class='danger'><B>[src] dies along with its user!</B></span>")
|
||||
death(TRUE)
|
||||
qdel(src)
|
||||
snapback()
|
||||
@@ -320,6 +320,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
forceMove(summoner.loc)
|
||||
new /obj/effect/temp_visual/guardian/phase(loc)
|
||||
cooldown = world.time + 10
|
||||
reset_perspective()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -460,7 +461,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
|
||||
/obj/item/guardiancreator
|
||||
name = "deck of tarot cards"
|
||||
desc = "An enchanted deck of tarot cards, rumored to be a source of unimaginable power. "
|
||||
desc = "An enchanted deck of tarot cards, rumored to be a source of unimaginable power."
|
||||
icon = 'icons/obj/toy.dmi'
|
||||
icon_state = "deck_syndicate_full"
|
||||
var/used = FALSE
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
/obj/guardian_bomb/proc/detonate(mob/living/user)
|
||||
if(isliving(user))
|
||||
if(user != spawner && user != spawner.summoner && !spawner.hasmatchingsummoner(user))
|
||||
to_chat(user, "<span class='danger'><B>The [src] was boobytrapped!</span></B>")
|
||||
to_chat(user, "<span class='danger'><B>[src] was boobytrapped!</span></B>")
|
||||
to_chat(spawner, "<span class='danger'><B>Success! Your trap caught [user]</span></B>")
|
||||
var/turf/T = get_turf(src)
|
||||
stored_obj.forceMove(T)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/mob/living/simple_animal/hostile/guardian/punch/AttackingTarget()
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
src.say("[src.battlecry][src.battlecry][src.battlecry][src.battlecry][src.battlecry][src.battlecry][src.battlecry][src.battlecry][src.battlecry][src.battlecry]!!")
|
||||
say("[battlecry][battlecry][battlecry][battlecry][battlecry][battlecry][battlecry][battlecry][battlecry][battlecry]!!", ignore_spam = TRUE)
|
||||
playsound(loc, src.attack_sound, 50, 1, 1)
|
||||
playsound(loc, src.attack_sound, 50, 1, 1)
|
||||
playsound(loc, src.attack_sound, 50, 1, 1)
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
var/idle = 0
|
||||
var/isqueen = FALSE
|
||||
var/icon_base = "bee"
|
||||
var/static/beehometypecache = typecacheof(/obj/structure/beebox)
|
||||
var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0)
|
||||
@@ -118,7 +120,7 @@
|
||||
if(istype(A, /obj/machinery/hydroponics))
|
||||
var/obj/machinery/hydroponics/Hydro = A
|
||||
if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit)
|
||||
wanted_objects |= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted
|
||||
wanted_objects |= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -132,8 +134,9 @@
|
||||
if(target == beehome)
|
||||
var/obj/structure/beebox/BB = target
|
||||
forceMove(BB)
|
||||
toggle_ai(AI_IDLE)
|
||||
target = null
|
||||
wanted_objects -= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
|
||||
wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home
|
||||
return //no don't attack the goddamm box
|
||||
else
|
||||
. = ..()
|
||||
@@ -157,7 +160,7 @@
|
||||
return
|
||||
|
||||
target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity
|
||||
wanted_objects -= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted
|
||||
wanted_objects -= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
|
||||
Hydro.recent_bee_visit = TRUE
|
||||
spawn(BEE_TRAY_RECENT_VISIT)
|
||||
if(Hydro)
|
||||
@@ -187,12 +190,13 @@
|
||||
if(loc == beehome)
|
||||
idle = min(100, ++idle)
|
||||
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
|
||||
toggle_ai(AI_ON)
|
||||
forceMove(beehome.drop_location())
|
||||
else
|
||||
idle = max(0, --idle)
|
||||
if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
|
||||
if(!FindTarget())
|
||||
wanted_objects |= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
|
||||
wanted_objects |= beehometypecache //so we don't attack beeboxes when not going home
|
||||
target = beehome
|
||||
if(!beehome) //add outselves to a beebox (of the same reagent) if we have no home
|
||||
for(var/obj/structure/beebox/BB in view(vision_range, src))
|
||||
@@ -285,3 +289,11 @@
|
||||
QDEL_NULL(queen)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/bees/consider_wakeup()
|
||||
if (beehome && loc == beehome) // If bees are chilling in their nest, they're not actively looking for targets
|
||||
idle = min(100, ++idle)
|
||||
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
|
||||
toggle_ai(AI_ON)
|
||||
forceMove(beehome.drop_location())
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
boss.atb.refund(boss_cost)
|
||||
|
||||
/mob/living/simple_animal/hostile/boss/paper_wizard/copy
|
||||
desc = "tis a ruse!"
|
||||
desc = "'Tis a ruse!"
|
||||
health = 1
|
||||
maxHealth = 1
|
||||
alpha = 200
|
||||
|
||||
@@ -1,81 +1,101 @@
|
||||
/mob/living/simple_animal/hostile/carp
|
||||
name = "space carp"
|
||||
desc = "A ferocious, fang-bearing creature that resembles a fish."
|
||||
icon_state = "carp"
|
||||
icon_living = "carp"
|
||||
icon_dead = "carp_dead"
|
||||
icon_gib = "carp_gib"
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/carpmeat = 2)
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "hits"
|
||||
emote_taunt = list("gnashes")
|
||||
taunt_chance = 30
|
||||
speed = 0
|
||||
maxHealth = 25
|
||||
health = 25
|
||||
devourable = TRUE
|
||||
no_vore = FALSE
|
||||
|
||||
harm_intent_damage = 8
|
||||
obj_damage = 50
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
speak_emote = list("gnashes")
|
||||
|
||||
//Space carp aren't affected by cold.
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
|
||||
faction = list("carp")
|
||||
movement_type = FLYING
|
||||
pressure_resistance = 200
|
||||
gold_core_spawnable = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/Process_Spacemove(movement_dir = 0)
|
||||
return 1 //No drifting in space for space carp! //original comments do not steal
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/AttackingTarget()
|
||||
. = ..()
|
||||
if(. && ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.adjustStaminaLoss(8)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/holocarp
|
||||
icon_state = "holocarp"
|
||||
icon_living = "holocarp"
|
||||
maxbodytemp = INFINITY
|
||||
gold_core_spawnable = 0
|
||||
del_on_death = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/megacarp
|
||||
icon = 'icons/mob/broadMobs.dmi'
|
||||
name = "Mega Space Carp"
|
||||
desc = "A ferocious, fang bearing creature that resembles a shark. This one seems especially ticked off."
|
||||
icon_state = "megacarp"
|
||||
icon_living = "megacarp"
|
||||
icon_dead = "megacarp_dead"
|
||||
icon_gib = "megacarp_gib"
|
||||
maxHealth = 65
|
||||
health = 65
|
||||
pixel_x = -16
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
|
||||
obj_damage = 80
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 20
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/cayenne
|
||||
name = "Cayenne"
|
||||
desc = "A failed Syndicate experiment in weaponized space carp technology, it now serves as a lovable mascot."
|
||||
gender = FEMALE
|
||||
speak_emote = list("squeaks")
|
||||
gold_core_spawnable = 0
|
||||
faction = list("syndicate")
|
||||
AIStatus = AI_OFF
|
||||
#define REGENERATION_DELAY 60 // After taking damage, how long it takes for automatic regeneration to begin for megacarps (ty robustin!)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp
|
||||
name = "space carp"
|
||||
desc = "A ferocious, fang-bearing creature that resembles a fish."
|
||||
icon_state = "carp"
|
||||
icon_living = "carp"
|
||||
icon_dead = "carp_dead"
|
||||
icon_gib = "carp_gib"
|
||||
speak_chance = 0
|
||||
turns_per_move = 5
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/carpmeat = 2)
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "hits"
|
||||
emote_taunt = list("gnashes")
|
||||
taunt_chance = 30
|
||||
speed = 0
|
||||
maxHealth = 25
|
||||
health = 25
|
||||
|
||||
harm_intent_damage = 8
|
||||
obj_damage = 50
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
speak_emote = list("gnashes")
|
||||
|
||||
//Space carp aren't affected by cold.
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
faction = list("carp")
|
||||
movement_type = FLYING
|
||||
pressure_resistance = 200
|
||||
gold_core_spawnable = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/Process_Spacemove(movement_dir = 0)
|
||||
return 1 //No drifting in space for space carp! //original comments do not steal
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/AttackingTarget()
|
||||
. = ..()
|
||||
if(. && ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.adjustStaminaLoss(8)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/holocarp
|
||||
icon_state = "holocarp"
|
||||
icon_living = "holocarp"
|
||||
maxbodytemp = INFINITY
|
||||
gold_core_spawnable = 0
|
||||
del_on_death = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/megacarp
|
||||
icon = 'icons/mob/broadMobs.dmi'
|
||||
name = "Mega Space Carp"
|
||||
desc = "A ferocious, fang bearing creature that resembles a shark. This one seems especially ticked off."
|
||||
icon_state = "megacarp"
|
||||
icon_living = "megacarp"
|
||||
icon_dead = "megacarp_dead"
|
||||
icon_gib = "megacarp_gib"
|
||||
maxHealth = 20
|
||||
health = 20
|
||||
pixel_x = -16
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
|
||||
obj_damage = 80
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 20
|
||||
|
||||
var/regen_cooldown = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/megacarp/Initialize()
|
||||
. = ..()
|
||||
name = "[pick(GLOB.megacarp_first_names)] [pick(GLOB.megacarp_last_names)]"
|
||||
melee_damage_lower += rand(2, 10)
|
||||
melee_damage_upper += rand(10,20)
|
||||
maxHealth += rand(30,60)
|
||||
move_to_delay = rand(3,7)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/megacarp/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
. = ..()
|
||||
if(.)
|
||||
regen_cooldown = world.time + REGENERATION_DELAY
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/megacarp/Life()
|
||||
. = ..()
|
||||
if(regen_cooldown < world.time)
|
||||
heal_overall_damage(4)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/cayenne
|
||||
name = "Cayenne"
|
||||
desc = "A failed Syndicate experiment in weaponized space carp technology, it now serves as a lovable mascot."
|
||||
gender = FEMALE
|
||||
speak_emote = list("squeaks")
|
||||
gold_core_spawnable = 0
|
||||
faction = list("syndicate")
|
||||
AIStatus = AI_OFF
|
||||
|
||||
#undef REGENERATION_DELAY
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/simple_animal/hostile/faithless
|
||||
name = "The Faithless"
|
||||
desc = "The Wish Granter's faith in humanity, incarnate"
|
||||
desc = "The Wish Granter's faith in humanity, incarnate."
|
||||
icon_state = "faithless"
|
||||
icon_living = "faithless"
|
||||
icon_dead = "faithless_dead"
|
||||
@@ -41,4 +41,4 @@
|
||||
var/mob/living/carbon/C = target
|
||||
C.Knockdown(60)
|
||||
C.visible_message("<span class='danger'>\The [src] knocks down \the [C]!</span>", \
|
||||
"<span class='userdanger'>\The [src] knocks you down!</span>")
|
||||
"<span class='userdanger'>\The [src] knocks you down!</span>")
|
||||
|
||||
@@ -206,6 +206,7 @@
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
poison_type = "frost_oil"
|
||||
color = rgb(114,228,250)
|
||||
gold_core_spawnable = 0
|
||||
|
||||
@@ -214,6 +215,7 @@
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
poison_type = "frost_oil"
|
||||
color = rgb(114,228,250)
|
||||
gold_core_spawnable = 0
|
||||
|
||||
@@ -222,6 +224,7 @@
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
poison_type = "frost_oil"
|
||||
color = rgb(114,228,250)
|
||||
gold_core_spawnable = 0
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead.
|
||||
var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses
|
||||
var/attack_same = 0 //Set us to 1 to allow us to attack our own faction
|
||||
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
|
||||
var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such
|
||||
var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects.
|
||||
|
||||
@@ -88,7 +87,7 @@
|
||||
DestroySurroundings()
|
||||
if(!MoveToTarget(possible_targets)) //if we lose our target
|
||||
if(AIShouldSleep(possible_targets)) // we try to acquire a new one
|
||||
AIStatus = AI_IDLE // otherwise we go idle
|
||||
toggle_ai(AI_IDLE) // otherwise we go idle
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user)
|
||||
@@ -289,7 +288,7 @@
|
||||
target = null
|
||||
LoseSearchObjects()
|
||||
if(AIStatus == AI_IDLE)
|
||||
AIStatus = AI_ON
|
||||
toggle_ai(AI_ON)
|
||||
FindTarget()
|
||||
else if(target != null && prob(40))//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one
|
||||
FindTarget()
|
||||
@@ -362,7 +361,6 @@
|
||||
else if(projectiletype)
|
||||
var/obj/item/projectile/P = new projectiletype(startloc)
|
||||
playsound(src, projectilesound, 100, 1)
|
||||
P.current = startloc
|
||||
P.starting = startloc
|
||||
P.firer = src
|
||||
P.yo = targeted_atom.y - startloc.y
|
||||
@@ -370,6 +368,7 @@
|
||||
if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space
|
||||
newtonian_move(get_dir(targeted_atom, targets_from))
|
||||
P.original = targeted_atom
|
||||
P.preparePixelProjectile(targeted_atom, src)
|
||||
P.fire()
|
||||
return P
|
||||
|
||||
@@ -424,7 +423,7 @@
|
||||
if(AI_IDLE)
|
||||
if(FindTarget(possible_targets, 1))
|
||||
. = 1
|
||||
AIStatus = AI_ON //Wake up for more than one Life() cycle.
|
||||
toggle_ai(AI_ON) //Wake up for more than one Life() cycle.
|
||||
else
|
||||
. = 0
|
||||
|
||||
@@ -455,3 +454,9 @@
|
||||
if(!value)
|
||||
value = initial(search_objects)
|
||||
search_objects = value
|
||||
|
||||
/mob/living/simple_animal/hostile/consider_wakeup()
|
||||
..()
|
||||
if(AIStatus == AI_IDLE && FindTarget(ListTargets(), 1))
|
||||
toggle_ai(AI_ON)
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
|
||||
/obj/effect/temp_visual/mook_dust
|
||||
name = "dust"
|
||||
desc = "it's just a dust cloud!"
|
||||
desc = "It's just a dust cloud!"
|
||||
icon = 'icons/mob/jungle/mook.dmi'
|
||||
icon_state = "mook_leap_cloud"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
@@ -182,12 +182,7 @@
|
||||
return
|
||||
var/turf/our_turf = get_turf(src)
|
||||
var/obj/item/projectile/seedling/readied_shot = new /obj/item/projectile/seedling(our_turf)
|
||||
readied_shot.current = our_turf
|
||||
readied_shot.starting = our_turf
|
||||
readied_shot.firer = src
|
||||
readied_shot.original = target
|
||||
readied_shot.yo = target.y - our_turf.y + rand(-1,1)
|
||||
readied_shot.xo = target.x - our_turf.x + rand(-1,1)
|
||||
readied_shot.preparePixelProjectile(target, src, null, rand(-10, 10))
|
||||
readied_shot.fire()
|
||||
playsound(src, projectilesound, 100, 1)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/no_mech/Initialize()
|
||||
. = ..()
|
||||
wanted_objects = typecacheof(/obj/mecha/combat, ignore_root_path=TRUE)
|
||||
wanted_objects = typecacheof(/obj/mecha/combat, TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/nanotrasen //nanotrasen are syndies! no it's just a weird path.
|
||||
name = "Nanotrasen Mecha Pilot"
|
||||
@@ -101,7 +101,7 @@
|
||||
targets_from = src
|
||||
|
||||
//Find a new mecha
|
||||
wanted_objects = typecacheof(/obj/mecha/combat, ignore_root_path=TRUE)
|
||||
wanted_objects = typecacheof(/obj/mecha/combat, TRUE)
|
||||
var/search_aggressiveness = 2
|
||||
for(var/obj/mecha/combat/C in range(vision_range,src))
|
||||
if(is_valid_mecha(C))
|
||||
|
||||
@@ -93,7 +93,7 @@ Difficulty: Medium
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Move(atom/newloc)
|
||||
if(dashing || (newloc && newloc.z == z && (istype(newloc, /turf/open/lava) || istype(newloc, /turf/open/chasm)))) //we're not stupid!
|
||||
if(dashing || (newloc && newloc.z == z && (islava(newloc) || ischasm(newloc)))) //we're not stupid!
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -159,18 +159,18 @@ Difficulty: Medium
|
||||
Shoot(target)
|
||||
changeNext_move(CLICK_CD_RANGE)
|
||||
|
||||
//I'm still of the belief that this entire proc needs to be wiped from existence.
|
||||
// do not take my touching of it to be endorsement of it. ~mso
|
||||
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop()
|
||||
if(next_move <= world.time)
|
||||
stoplag(1)
|
||||
.() //retry
|
||||
return
|
||||
sleep((next_move - world.time) * 1.5)
|
||||
while(!QDELETED(target) && next_move <= world.time) //this is done this way because next_move can change to be sooner while we sleep.
|
||||
stoplag(1)
|
||||
sleep((next_move - world.time) * 1.5) //but don't ask me what the fuck this is about
|
||||
if(QDELETED(target))
|
||||
return
|
||||
if(dashing || next_move > world.time || !Adjacent(target))
|
||||
if(dashing && next_move <= world.time)
|
||||
next_move = world.time + 1
|
||||
.() //recurse
|
||||
INVOKE_ASYNC(src, .proc/quick_attack_loop) //lets try that again.
|
||||
return
|
||||
AttackingTarget()
|
||||
|
||||
@@ -186,7 +186,7 @@ Difficulty: Medium
|
||||
var/turf_dist_to_target = 0
|
||||
if(!QDELETED(dash_target))
|
||||
turf_dist_to_target += get_dist(dash_target, O)
|
||||
if(get_dist(src, O) >= MINER_DASH_RANGE && turf_dist_to_target <= self_dist_to_target && !istype(O, /turf/open/lava) && !istype(O, /turf/open/chasm))
|
||||
if(get_dist(src, O) >= MINER_DASH_RANGE && turf_dist_to_target <= self_dist_to_target && !islava(O) && !ischasm(O))
|
||||
var/valid = TRUE
|
||||
for(var/turf/T in getline(own_turf, O))
|
||||
if(is_blocked_turf(T, TRUE))
|
||||
|
||||
@@ -164,7 +164,6 @@ Difficulty: Very Hard
|
||||
return
|
||||
var/turf/startloc = get_turf(src)
|
||||
var/obj/item/projectile/P = new /obj/item/projectile/colossus(startloc)
|
||||
P.current = startloc
|
||||
P.starting = startloc
|
||||
P.firer = src
|
||||
if(marker)
|
||||
@@ -617,7 +616,7 @@ Difficulty: Very Hard
|
||||
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
mob_size = MOB_SIZE_TINY
|
||||
gold_core_spawnable = 0
|
||||
gold_core_spawnable = TRUE
|
||||
verb_say = "warps"
|
||||
verb_ask = "floats inquisitively"
|
||||
verb_exclaim = "zaps"
|
||||
@@ -635,7 +634,6 @@ Difficulty: Very Hard
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
AIStatus = AI_OFF
|
||||
stop_automated_movement = 1
|
||||
gold_core_spawnable = TRUE
|
||||
var/heal_power = 5
|
||||
|
||||
/mob/living/simple_animal/hostile/lightgeist/Initialize()
|
||||
@@ -664,12 +662,7 @@ Difficulty: Very Hard
|
||||
activation_method = ACTIVATE_TOUCH
|
||||
cooldown_add = 50
|
||||
activation_sound = 'sound/magic/timeparadox2.ogg'
|
||||
var/list/banned_items_typecache = list(/obj/item/storage, /obj/item/implant, /obj/item/implanter, /obj/item/disk/nuclear, /obj/item/projectile, /obj/item/spellbook)
|
||||
|
||||
/obj/machinery/anomalous_crystal/refresher/Initialize()
|
||||
. = ..()
|
||||
banned_items_typecache = typecacheof(banned_items_typecache)
|
||||
|
||||
var/static/list/banned_items_typecache = typecacheof(list(/obj/item/storage, /obj/item/implant, /obj/item/implanter, /obj/item/disk/nuclear, /obj/item/projectile, /obj/item/spellbook))
|
||||
|
||||
/obj/machinery/anomalous_crystal/refresher/ActivationReaction(mob/user, method)
|
||||
if(..())
|
||||
@@ -758,7 +751,7 @@ Difficulty: Very Hard
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/exit_possession
|
||||
name = "Exit Possession"
|
||||
desc = "Exits the body you are possessing"
|
||||
desc = "Exits the body you are possessing."
|
||||
charge_max = 60
|
||||
clothes_req = 0
|
||||
invocation_type = "none"
|
||||
|
||||
@@ -385,6 +385,7 @@ Difficulty: Medium
|
||||
melee_damage_lower = 30
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
|
||||
loot = list()
|
||||
crusher_loot = list()
|
||||
butcher_results = list(/obj/item/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
|
||||
|
||||
@@ -129,7 +129,7 @@ Difficulty: Hard
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/hierophant/CanAttack(atom/the_target)
|
||||
. = ..()
|
||||
if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permenant targets
|
||||
if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permanent targets
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/hierophant/GiveTarget(new_target)
|
||||
|
||||
@@ -137,14 +137,14 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
|
||||
/mob/living/simple_animal/hostile/swarmer/ai/Move(atom/newloc)
|
||||
if(newloc)
|
||||
if(newloc.z == z) //so these actions are Z-specific
|
||||
if(istype(newloc, /turf/open/lava))
|
||||
if(islava(newloc))
|
||||
var/turf/open/lava/L = newloc
|
||||
if(!L.is_safe())
|
||||
StartAction(20)
|
||||
new /obj/structure/lattice/catwalk/swarmer_catwalk(newloc)
|
||||
return FALSE
|
||||
|
||||
if(istype(newloc, /turf/open/chasm) && !throwing)
|
||||
if(ischasm(newloc) && !throwing)
|
||||
throw_at(get_edge_target_turf(src, get_dir(src, newloc)), 7 , 3, spin = FALSE) //my planet needs me
|
||||
return FALSE
|
||||
|
||||
@@ -172,16 +172,9 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
|
||||
search_objects = 1
|
||||
attack_all_objects = TRUE //attempt to nibble everything
|
||||
lose_patience_timeout = 150
|
||||
var/static/list/sharedWanted = list(/turf/closed/mineral, /turf/closed/wall) //eat rocks and walls
|
||||
var/static/list/sharedWanted = typecacheof(list(/turf/closed/mineral, /turf/closed/wall)) //eat rocks and walls
|
||||
var/static/list/sharedIgnore = list()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/ai/resource/Initialize()
|
||||
. = ..()
|
||||
sharedWanted = typecacheof(sharedWanted)
|
||||
sharedIgnore = typecacheof(sharedIgnore)
|
||||
|
||||
|
||||
//This handles viable things to eat/attack
|
||||
//Place specific cases of AI derpiness here
|
||||
//Most can be left to the automatic Gain/LosePatience() system
|
||||
@@ -239,18 +232,15 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
|
||||
|
||||
//So swarmers can learn what is and isn't food
|
||||
/mob/living/simple_animal/hostile/swarmer/ai/resource/proc/add_type_to_wanted(typepath)
|
||||
LAZYINITLIST(sharedWanted)
|
||||
if(!sharedWanted[typepath])// this and += is faster than |=
|
||||
sharedWanted += typecacheof(typepath)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/ai/resource/proc/add_type_to_ignore(typepath)
|
||||
LAZYINITLIST(sharedIgnore)
|
||||
if(!sharedIgnore[typepath])
|
||||
sharedIgnore += typecacheof(typepath)
|
||||
|
||||
|
||||
|
||||
//RANGED SWARMER
|
||||
/mob/living/simple_animal/hostile/swarmer/ai/ranged_combat
|
||||
icon_state = "swarmer_ranged"
|
||||
@@ -299,7 +289,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
|
||||
//Used so they can survive lavaland better
|
||||
/obj/structure/lattice/catwalk/swarmer_catwalk
|
||||
name = "swarmer catwalk"
|
||||
desc = "a catwalk-like mesh, produced by swarmers to allow them to navigate hostile terrain."
|
||||
desc = "A catwalk-like mesh, produced by swarmers to allow them to navigate hostile terrain."
|
||||
icon = 'icons/obj/smooth_structures/swarmer_catwalk.dmi'
|
||||
icon_state = "swarmer_catwalk"
|
||||
|
||||
|
||||
@@ -34,4 +34,7 @@
|
||||
|
||||
//Space bats need no air to fly in.
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
minbodytemp = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/bat/Process_Spacemove(movement_dir = 0)
|
||||
return 1
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/simple_animal/hostile/retaliate/clown
|
||||
name = "Clown"
|
||||
desc = "A denizen of clown planet"
|
||||
desc = "A denizen of clown planet."
|
||||
icon = 'icons/mob/simple_human.dmi'
|
||||
icon_state = "clown"
|
||||
icon_living = "clown"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
del_on_death = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/nanotrasenpeace
|
||||
/mob/living/simple_animal/hostile/retaliate/nanotrasenpeace //this should be in a different file
|
||||
name = "Nanotrasen Private Security Officer"
|
||||
desc = "An officer part of Nanotrasen's private security force."
|
||||
icon = 'icons/mob/simple_human.dmi'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/statue
|
||||
name = "statue" // matches the name of the statue with the flesh-to-stone spell
|
||||
desc = "An incredibly lifelike marble carving. Its eyes seems to follow you.." // same as an ordinary statue with the added "eye following you" description
|
||||
desc = "An incredibly lifelike marble carving. Its eyes seem to follow you.." // same as an ordinary statue with the added "eye following you" description
|
||||
icon = 'icons/obj/statue.dmi'
|
||||
icon_state = "human_male"
|
||||
icon_living = "human_male"
|
||||
@@ -45,8 +45,6 @@
|
||||
sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS
|
||||
anchored = TRUE
|
||||
|
||||
gold_core_spawnable = 1
|
||||
|
||||
var/cannot_be_seen = 1
|
||||
var/mob/living/creator = null
|
||||
|
||||
|
||||
@@ -43,12 +43,12 @@
|
||||
..()
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/T = src.loc
|
||||
if(T.air && T.air.gases["co2"])
|
||||
var/co2 = T.air.gases["co2"][MOLES]
|
||||
if(T.air && T.air.gases[/datum/gas/carbon_dioxide])
|
||||
var/co2 = T.air.gases[/datum/gas/carbon_dioxide][MOLES]
|
||||
if(co2 > 0)
|
||||
if(prob(25))
|
||||
var/amt = min(co2, 9)
|
||||
T.air.gases["co2"][MOLES] -= amt
|
||||
T.air.gases[/datum/gas/carbon_dioxide][MOLES] -= amt
|
||||
T.atmos_spawn_air("o2=[amt]")
|
||||
|
||||
/mob/living/simple_animal/hostile/tree/AttackingTarget()
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/tree/festivus
|
||||
name = "festivus pole"
|
||||
desc = "serenity now... SERENITY NOW!"
|
||||
desc = "Serenity now... SERENITY NOW!"
|
||||
icon_state = "festivus_pole"
|
||||
icon_living = "festivus_pole"
|
||||
icon_dead = "festivus_pole"
|
||||
|
||||
@@ -109,13 +109,13 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
layer = MOB_LAYER
|
||||
origin_tech = "biotech=6"
|
||||
var/list/banned_mobs()
|
||||
var/list/banned_mobs
|
||||
|
||||
/obj/item/asteroid/fugu_gland/afterattack(atom/target, mob/user, proximity_flag)
|
||||
if(proximity_flag && isanimal(target))
|
||||
var/mob/living/simple_animal/A = target
|
||||
if(A.buffed || (A.type in banned_mobs) || A.stat)
|
||||
to_chat(user, "<span class='warning'>Something's interfering with the [src]'s effects. It's no use.</span>")
|
||||
to_chat(user, "<span class='warning'>Something's interfering with [src]'s effects. It's no use.</span>")
|
||||
return
|
||||
A.buffed++
|
||||
A.maxHealth *= 1.5
|
||||
|
||||
@@ -514,7 +514,8 @@
|
||||
return
|
||||
|
||||
walk_to(src, parrot_interest, 1, parrot_speed)
|
||||
if(isStuck()) return
|
||||
if(isStuck())
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
@@ -534,7 +535,8 @@
|
||||
return
|
||||
|
||||
walk_to(src, parrot_perch, 1, parrot_speed)
|
||||
if(isStuck()) return
|
||||
if(isStuck())
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
@@ -547,7 +549,8 @@
|
||||
walk_away(src, parrot_interest, 1, parrot_speed)
|
||||
/*if(parrot_been_shot > 0)
|
||||
parrot_been_shot-- didn't work anyways, and besides, any bullet poly survives isn't worth the speed boost.*/
|
||||
if(isStuck()) return
|
||||
if(isStuck())
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
@@ -586,7 +589,8 @@
|
||||
//Otherwise, fly towards the mob!
|
||||
else
|
||||
walk_to(src, parrot_interest, 1, parrot_speed)
|
||||
if(isStuck()) return
|
||||
if(isStuck())
|
||||
return
|
||||
|
||||
return
|
||||
//-----STATE MISHAP
|
||||
@@ -901,9 +905,6 @@
|
||||
|
||||
/mob/living/simple_animal/parrot/Poly/Life()
|
||||
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
rounds_survived = max(++rounds_survived,1)
|
||||
if(rounds_survived > longest_survival)
|
||||
longest_survival = rounds_survived
|
||||
Write_Memory(FALSE)
|
||||
memory_saved = TRUE
|
||||
..()
|
||||
@@ -969,7 +970,7 @@
|
||||
|
||||
/mob/living/simple_animal/parrot/Poly/ghost
|
||||
name = "The Ghost of Poly"
|
||||
desc = "Doomed to squawk the earth."
|
||||
desc = "Doomed to squawk the Earth."
|
||||
color = "#FFFFFF77"
|
||||
speak_chance = 20
|
||||
status_flags = GODMODE
|
||||
@@ -1004,7 +1005,6 @@
|
||||
parrot_interest = null
|
||||
H.visible_message("<span class='danger'>[src] dive bombs into [H]'s chest and vanishes!</span>", "<span class='userdanger'>[src] dive bombs into your chest, vanishing! This can't be good!</span>")
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/clock_hawk
|
||||
name = "clock hawk"
|
||||
desc = "Cbyl jnaan penpxre! Fdhnnnjx!"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/mob/living/simple_animal/shade
|
||||
name = "Shade"
|
||||
real_name = "Shade"
|
||||
desc = "A bound spirit"
|
||||
desc = "A bound spirit."
|
||||
gender = PLURAL
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "shade"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user