mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
[MIRROR] Shadekin and Xenochimera variable refactor (#10872)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
committed by
GitHub
parent
5b1679c8c7
commit
c6b9ab647c
@@ -829,6 +829,10 @@
|
||||
/// COMSIG used to get messages where they need to go
|
||||
#define COMSIG_VISIBLE_MESSAGE "visible_message"
|
||||
|
||||
// Species Components
|
||||
///from /datum/species/xenochimera/handle_environment_special()
|
||||
#define COMSIG_XENOCHIMERA_COMPONENT "xenochimera_component"
|
||||
|
||||
//Unittest data update
|
||||
#ifdef UNIT_TEST
|
||||
#define COMSIG_UNITTEST_DATA "unittest_send_data"
|
||||
|
||||
@@ -32,10 +32,11 @@
|
||||
/* // Commenting this out for now, will revisit later once I can figure out how to override Click() appropriately.
|
||||
/obj/screen/alert/xenochimera/reconstitution/Click(mob/usr)
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
|
||||
if(H.revive_ready == REVIVING_NOW)
|
||||
to_chat(usr, "We are currently reviving, and will be done in [(H.revive_finished - world.time) / 10] seconds.")
|
||||
else if(H.revive_ready == REVIVING_DONE)
|
||||
var/datum/component/xenochimera/xc = H.get_xenochimera_component()
|
||||
if(xc) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
|
||||
if(xc.revive_ready == REVIVING_NOW)
|
||||
to_chat(usr, "We are currently reviving, and will be done in [(xc.revive_finished - world.time) / 10] seconds.")
|
||||
else if(xc.revive_ready == REVIVING_DONE)
|
||||
to_chat(usr, "You should have a notification + alert for this! Bug report that this is still here!")
|
||||
*/
|
||||
|
||||
@@ -47,7 +48,7 @@
|
||||
/* // Commenting this out for now, will revisit later once I can figure out how to override Click() appropriately.
|
||||
/obj/screen/alert/xenochimera/readytohatch/Click(mob/usr)
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
|
||||
if(H.get_xenochimera_component()) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
|
||||
if(H.revive_ready == REVIVING_DONE) // Sanity check.
|
||||
H.hatch() // Hatch.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
if("energy")
|
||||
var/mob/living/simple_mob/shadekin/SK = usr
|
||||
if(istype(SK))
|
||||
to_chat(usr,span_notice(span_bold("Energy:") + " [SK.energy] ([SK.dark_gains])"))
|
||||
to_chat(usr,span_notice(span_bold("Energy:") + " [SK.comp.dark_energy] ([SK.dark_gains])"))
|
||||
if("shadekin status")
|
||||
var/turf/T = get_turf(usr)
|
||||
if(T)
|
||||
@@ -25,21 +25,22 @@
|
||||
to_chat(usr,span_notice(span_bold("Energy:") + " [H.species.lleill_energy]/[H.species.lleill_energy_max]"))
|
||||
if("danger level")
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(istype(H) && istype(H.species, /datum/species/xenochimera))
|
||||
if(H.feral > 50)
|
||||
var/datum/component/xenochimera/xc = H.get_xenochimera_component()
|
||||
if(xc)
|
||||
if(xc.feral > 50)
|
||||
to_chat(usr, span_warning("You are currently <b>completely feral.</b>"))
|
||||
else if(H.feral > 10)
|
||||
else if(xc.feral > 10)
|
||||
to_chat(usr, span_warning("You are currently <b>crazed and confused.</b>"))
|
||||
else if(H.feral > 0)
|
||||
else if(xc.feral > 0)
|
||||
to_chat(usr, span_warning("You are currently <b>acting on instinct.</b>"))
|
||||
else
|
||||
to_chat(usr, span_notice("You are currently <b>calm and collected.</b>"))
|
||||
if(H.feral > 0)
|
||||
if(xc.feral > 0)
|
||||
var/feral_passing = TRUE
|
||||
if(H.traumatic_shock > min(60, H.nutrition/10))
|
||||
to_chat(usr, span_warning("Your pain prevents you from regaining focus."))
|
||||
feral_passing = FALSE
|
||||
if(H.feral + H.nutrition < 150)
|
||||
if(xc.feral + H.nutrition < 150)
|
||||
to_chat(usr, span_warning("Your hunger prevents you from regaining focus."))
|
||||
feral_passing = FALSE
|
||||
if(H.jitteriness >= 100)
|
||||
@@ -58,16 +59,18 @@
|
||||
to_chat(usr, span_warning("Your hunger is slowly making you unstable."))
|
||||
if("Reconstructing Form") // Allow Viewing Reconstruction Timer + Hatching for 'chimera
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
|
||||
if(H.revive_ready == REVIVING_NOW)
|
||||
to_chat(usr, span_notice("We are currently reviving, and will be done in [round((H.revive_finished - world.time) / 10)] seconds, or [round(((H.revive_finished - world.time) * 0.1) / 60)] minutes."))
|
||||
else if(H.revive_ready == REVIVING_DONE)
|
||||
var/datum/component/xenochimera/xc = H.get_xenochimera_component()
|
||||
if(xc) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
|
||||
if(xc.revive_ready == REVIVING_NOW)
|
||||
to_chat(usr, span_notice("We are currently reviving, and will be done in [round((xc.revive_finished - world.time) / 10)] seconds, or [round(((xc.revive_finished - world.time) * 0.1) / 60)] minutes."))
|
||||
else if(xc.revive_ready == REVIVING_DONE)
|
||||
to_chat(usr, span_warning("You should have a notification + alert for this! Bug report that this is still here!"))
|
||||
|
||||
if("Ready to Hatch") // Allow Viewing Reconstruction Timer + Hatching for 'chimera
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
|
||||
if(H.revive_ready == REVIVING_DONE) // Sanity check.
|
||||
var/datum/component/xenochimera/xc = H.get_xenochimera_component()
|
||||
if(xc) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
|
||||
if(xc.revive_ready == REVIVING_DONE) // Sanity check.
|
||||
H.hatch() // Hatch.
|
||||
|
||||
else
|
||||
|
||||
8
code/datums/components/species/shadekin.dm
Normal file
8
code/datums/components/species/shadekin.dm
Normal file
@@ -0,0 +1,8 @@
|
||||
/datum/component/shadekin
|
||||
var/dark_energy = 100
|
||||
var/max_dark_energy = 100
|
||||
var/dark_energy_infinite = FALSE
|
||||
|
||||
/datum/component/shadekin/Initialize()
|
||||
if(!ishuman(parent) && !issimplekin(parent)) //Both humankin and simplekin can have this component
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
635
code/datums/components/species/xenochimera.dm
Normal file
635
code/datums/components/species/xenochimera.dm
Normal file
@@ -0,0 +1,635 @@
|
||||
/datum/component/xenochimera
|
||||
var/laststress = 0
|
||||
var/mob/living/carbon/human/owner
|
||||
var/feral = 0
|
||||
var/revive_ready = REVIVING_READY
|
||||
var/revive_finished = FALSE
|
||||
var/regen_sounds = list(
|
||||
'sound/effects/mob_effects/xenochimera/regen_1.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_2.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_4.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_3.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_5.ogg'
|
||||
)
|
||||
|
||||
/datum/component/xenochimera/Initialize()
|
||||
if(!ishuman(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
owner = parent
|
||||
RegisterSignal(owner, COMSIG_XENOCHIMERA_COMPONENT, PROC_REF(handle_comp))
|
||||
add_verb(owner, /mob/living/carbon/human/proc/reconstitute_form)
|
||||
|
||||
/datum/component/xenochimera/Destroy(force)
|
||||
UnregisterSignal(owner, COMSIG_XENOCHIMERA_COMPONENT)
|
||||
remove_verb(owner, /mob/living/carbon/human/proc/reconstitute_form)
|
||||
owner = null
|
||||
. = ..()
|
||||
|
||||
/datum/component/xenochimera/proc/handle_comp()
|
||||
if(QDELETED(owner))
|
||||
return
|
||||
handle_feralness()
|
||||
handle_regeneration()
|
||||
|
||||
/datum/component/xenochimera/proc/handle_regeneration()
|
||||
if(revive_ready == REVIVING_NOW || revive_ready == REVIVING_DONE)
|
||||
owner.stunned = 5
|
||||
owner.canmove = 0
|
||||
owner.does_not_breathe = TRUE
|
||||
if(prob(2)) // 2% chance of playing squelchy noise while reviving, which is run roughly every 2 seconds/tick while regenerating.
|
||||
playsound(owner, pick(regen_sounds), 30)
|
||||
owner.visible_message(span_danger("<p>" + span_huge("[owner.name]'s motionless form shudders grotesquely, rippling unnaturally.") + "</p>"))
|
||||
if(!owner.lying)
|
||||
owner.lay_down()
|
||||
|
||||
/datum/component/xenochimera/proc/handle_feralness()
|
||||
//first, calculate how stressed the chimera is
|
||||
|
||||
//Low-ish nutrition has messages and can eventually cause feralness
|
||||
var/hunger = max(0, 150 - owner.nutrition)
|
||||
|
||||
//pain makes feralness a thing
|
||||
var/shock = 0.75*owner.traumatic_shock
|
||||
|
||||
//Caffeinated or otherwise overexcited xenochimera can become feral and have special messages
|
||||
var/jittery = max(0, owner.jitteriness - 100)
|
||||
|
||||
//Are we in danger of ferality?
|
||||
var/danger = FALSE
|
||||
var/feral_state = FALSE
|
||||
|
||||
//finally, calculate the current stress total the chimera is operating under, and the cause
|
||||
var/currentstress = (hunger + shock + jittery)
|
||||
var/cause = "stress"
|
||||
if(hunger > shock && hunger > jittery)
|
||||
cause = "hunger"
|
||||
else if (shock > hunger && shock > jittery)
|
||||
cause = "shock"
|
||||
else if (jittery > shock && jittery > hunger)
|
||||
cause = "jittery"
|
||||
|
||||
//check to see if they go feral if they weren't before
|
||||
if(!feral && !isbelly(owner.loc))
|
||||
// if stress is below 15, no chance of snapping. Also if they weren't feral before, they won't suddenly become feral unless they get MORE stressed
|
||||
if((currentstress > laststress) && prob(clamp(currentstress-15, 0, 100)) )
|
||||
go_feral(currentstress, cause)
|
||||
feral = currentstress //update the local var
|
||||
|
||||
//they didn't go feral, give 'em a chance of hunger messages
|
||||
else if(owner.nutrition <= 200 && prob(0.5))
|
||||
switch(owner.nutrition)
|
||||
if(150 to 200)
|
||||
to_chat(owner,span_info("You feel rather hungry. It might be a good idea to find some some food..."))
|
||||
if(100 to 150)
|
||||
to_chat(owner,span_warning("You feel like you're going to snap and give in to your hunger soon... It would be for the best to find some [pick("food","prey")] to eat..."))
|
||||
danger = TRUE
|
||||
|
||||
//now the check's done, update their brain so it remembers how stressed they were
|
||||
if(!isbelly(owner.loc)) //another sanity check for brain implant shenanigans, also no you don't get to hide in a belly and get your laststress set to a huge amount to skip rolls
|
||||
laststress = currentstress
|
||||
|
||||
// Handle being feral
|
||||
if(feral)
|
||||
//We're feral
|
||||
feral_state = TRUE
|
||||
|
||||
//If they're still stressed, they stay feral
|
||||
if(currentstress >= 15)
|
||||
danger = TRUE
|
||||
feral = max(feral, currentstress)
|
||||
|
||||
else
|
||||
feral = max(0,--feral)
|
||||
|
||||
// Being in a belly or in the darkness decreases stress further. Helps mechanically reward players for staying in darkness + RP'ing appropriately. :9
|
||||
var/turf/T = get_turf(owner)
|
||||
if(feral && (isbelly(owner.loc) || T.get_lumcount() <= 0.1))
|
||||
feral = max(0,--feral)
|
||||
|
||||
//Did we just finish being feral?
|
||||
if(!feral)
|
||||
feral_state = FALSE
|
||||
to_chat(owner,span_info("Your thoughts start clearing, your feral urges having passed - for the time being, at least."))
|
||||
log_and_message_admins("is no longer feral.", owner)
|
||||
update_xenochimera_hud(owner, danger, feral_state)
|
||||
return
|
||||
|
||||
//If they lose enough health to hit softcrit, handle_shock() will keep resetting this. Otherwise, pissed off critters will lose shock faster than they gain it.
|
||||
owner.shock_stage = max(owner.shock_stage-(feral/20), 0)
|
||||
|
||||
//Handle light/dark areas
|
||||
var/turf/T = get_turf(owner)
|
||||
if(!T)
|
||||
update_xenochimera_hud(owner, danger, feral_state)
|
||||
return //Nullspace
|
||||
var/darkish = T.get_lumcount() <= 0.1
|
||||
|
||||
//Don't bother doing heavy lifting if we weren't going to give emotes anyway.
|
||||
if(!prob(1))
|
||||
|
||||
//This is basically the 'lite' version of the below block.
|
||||
var/list/nearby = owner.living_mobs(world.view)
|
||||
|
||||
//Not in the dark, or a belly, and out in the open.
|
||||
if(!darkish && isturf(owner.loc) && !isbelly(owner.loc)) // Added specific check for if in belly
|
||||
|
||||
//Always handle feral if nobody's around and not in the dark.
|
||||
if(!nearby.len)
|
||||
handle_feral()
|
||||
|
||||
//Rarely handle feral if someone is around
|
||||
else if(prob(1))
|
||||
handle_feral()
|
||||
|
||||
//And bail
|
||||
update_xenochimera_hud(owner, danger, feral_state)
|
||||
return
|
||||
|
||||
// In the darkness, or "hidden", or in a belly. No need for custom scene-protection checks as it's just an occational infomessage.
|
||||
if(darkish || !isturf(owner.loc) || isbelly(owner.loc)) // Specific check for if in belly. !isturf should do this, but JUST in case.
|
||||
// If hurt, tell 'em to heal up
|
||||
if (cause == "shock")
|
||||
to_chat(owner,span_info("This place seems safe, secure, hidden, a place to lick your wounds and recover..."))
|
||||
|
||||
//If hungry, nag them to go and find someone or something to eat.
|
||||
else if(cause == "hunger")
|
||||
to_chat(owner,span_info("Secure in your hiding place, your hunger still gnaws at you. You need to catch some food..."))
|
||||
|
||||
//If jittery, etc
|
||||
else if(cause == "jittery")
|
||||
to_chat(owner,span_info("sneakysneakyyesyesyescleverhidingfindthingsyessssss"))
|
||||
|
||||
//Otherwise, just tell them to keep hiding.
|
||||
else
|
||||
to_chat(owner,span_info("...safe..."))
|
||||
|
||||
// NOT in the darkness
|
||||
else
|
||||
|
||||
//Twitch twitch
|
||||
if(!owner.stat)
|
||||
owner.emote("twitch")
|
||||
|
||||
var/list/nearby = owner.living_mobs(world.view)
|
||||
|
||||
// Someone/something nearby
|
||||
if(nearby.len)
|
||||
var/M = pick(nearby)
|
||||
if(cause == "shock")
|
||||
to_chat(owner,span_danger("You're hurt, in danger, exposed, and [M] looks to be a little too close for comfort..."))
|
||||
else
|
||||
to_chat(owner,span_danger("Every movement, every flick, every sight and sound has your full attention, your hunting instincts on high alert... In fact, [M] looks extremely appetizing..."))
|
||||
|
||||
// Nobody around
|
||||
else
|
||||
if(cause == "hunger")
|
||||
to_chat(owner,span_danger("Confusing sights and sounds and smells surround you - scary and disorienting it may be, but the drive to hunt, to feed, to survive, compels you."))
|
||||
else if(cause == "jittery")
|
||||
to_chat(owner,span_danger("yesyesyesyesyesyesgetthethingGETTHETHINGfindfoodsfindpreypounceyesyesyes"))
|
||||
else
|
||||
to_chat(owner,span_danger("Confusing sights and sounds and smells surround you, this place is wrong, confusing, frightening. You need to hide, go to ground..."))
|
||||
|
||||
// HUD update time
|
||||
update_xenochimera_hud(danger, feral_state)
|
||||
|
||||
/datum/component/xenochimera/proc/update_xenochimera_hud(var/danger, var/feral)
|
||||
if(owner.xenochimera_danger_display)
|
||||
owner.xenochimera_danger_display.invisibility = INVISIBILITY_NONE
|
||||
if(danger && feral)
|
||||
owner.xenochimera_danger_display.icon_state = "danger11"
|
||||
else if(danger && !feral)
|
||||
owner.xenochimera_danger_display.icon_state = "danger10"
|
||||
else if(!danger && feral)
|
||||
owner.xenochimera_danger_display.icon_state = "danger01"
|
||||
else
|
||||
owner.xenochimera_danger_display.icon_state = "danger00"
|
||||
|
||||
return
|
||||
|
||||
/datum/component/xenochimera/proc/go_feral(var/stress, var/cause)
|
||||
// Going feral due to hunger
|
||||
if(cause == "hunger")
|
||||
to_chat(owner,span_danger(span_large("Something in your mind flips, your instincts taking over, no longer able to fully comprehend your surroundings as survival becomes your primary concern - you must feed, survive, there is nothing else. Hunt. Eat. Hide. Repeat.")))
|
||||
log_and_message_admins("has gone feral due to hunger.", owner)
|
||||
|
||||
// If they're hurt, chance of snapping.
|
||||
else if(cause == "shock")
|
||||
//If the majority of their shock is due to halloss, give them a different message (3x multiplier on check as halloss is 2x - meaning t_s must be at least 3x for other damage sources to be the greater part)
|
||||
if(3*owner.halloss >= owner.traumatic_shock)
|
||||
to_chat(owner,span_danger(span_large("The pain! It stings! Got to get away! Your instincts take over, urging you to flee, to hide, to go to ground, get away from here...")))
|
||||
log_and_message_admins("has gone feral due to halloss.", owner)
|
||||
|
||||
//Majority due to other damage sources
|
||||
else
|
||||
to_chat(owner,span_danger(span_large("Your fight-or-flight response kicks in, your injuries too much to simply ignore - you need to flee, to hide, survive at all costs - or destroy whatever is threatening you.")))
|
||||
log_and_message_admins("has gone feral due to injury.", owner)
|
||||
|
||||
//No hungry or shock, but jittery
|
||||
else if(cause == "jittery")
|
||||
to_chat(owner,span_warning(span_large("Suddenly, something flips - everything that moves is... potential prey. A plaything. This is great! Time to hunt!")))
|
||||
log_and_message_admins("has gone feral due to jitteriness.", owner)
|
||||
|
||||
else // catch-all just in case something weird happens
|
||||
to_chat(owner,span_warning(span_large("The stress of your situation is too much for you, and your survival instincts kick in!")))
|
||||
log_and_message_admins("has gone feral for unknown reasons.", owner)
|
||||
//finally, set their feral var
|
||||
feral = stress
|
||||
if(!owner.stat)
|
||||
owner.emote("twitch")
|
||||
|
||||
|
||||
/datum/component/xenochimera/proc/handle_feral()
|
||||
if(owner.handling_hal) return
|
||||
owner.handling_hal = 1
|
||||
|
||||
if(owner.client && feral >= 10) // largely a copy of handle_hallucinations() without the fake attackers. Unlike hallucinations, only fires once - if they're still feral they'll get hit again anyway.
|
||||
spawn(rand(200,500)/(feral/10))
|
||||
if(!feral) return //just to avoid fuckery in the event that they un-feral in the time it takes for the spawn to proc
|
||||
var/halpick = rand(1,100)
|
||||
switch(halpick)
|
||||
if(0 to 15) //15% chance
|
||||
//Screwy HUD
|
||||
//to_chat(src, "Screwy HUD")
|
||||
owner.hal_screwyhud = pick(1,2,3,3,4,4)
|
||||
spawn(rand(100,250))
|
||||
owner.hal_screwyhud = 0
|
||||
if(16 to 25) //10% chance
|
||||
//Strange items
|
||||
//to_chat(src, "Traitor Items")
|
||||
if(!owner.halitem)
|
||||
owner.halitem = new
|
||||
var/list/slots_free = list(ui_lhand,ui_rhand)
|
||||
if(owner.l_hand) slots_free -= ui_lhand
|
||||
if(owner.r_hand) slots_free -= ui_rhand
|
||||
if(!owner.belt) slots_free += ui_belt
|
||||
if(!owner.l_store) slots_free += ui_storage1
|
||||
if(!owner.r_store) slots_free += ui_storage2
|
||||
if(slots_free.len)
|
||||
owner.halitem.screen_loc = pick(slots_free)
|
||||
owner.halitem.layer = 50
|
||||
switch(rand(1,6))
|
||||
if(1) //revolver
|
||||
owner.halitem.icon = 'icons/obj/gun.dmi'
|
||||
owner.halitem.icon_state = "revolver"
|
||||
owner.halitem.name = "Revolver"
|
||||
if(2) //c4
|
||||
owner.halitem.icon = 'icons/obj/assemblies.dmi'
|
||||
owner.halitem.icon_state = "plastic-explosive0"
|
||||
owner.halitem.name = "Mysterious Package"
|
||||
if(prob(25))
|
||||
owner.halitem.icon_state = "c4small_1"
|
||||
if(3) //sword
|
||||
owner.halitem.icon = 'icons/obj/weapons.dmi'
|
||||
owner.halitem.icon_state = "sword1"
|
||||
owner.halitem.name = "Sword"
|
||||
if(4) //stun baton
|
||||
owner.halitem.icon = 'icons/obj/weapons.dmi'
|
||||
owner.halitem.icon_state = "stunbaton"
|
||||
owner.halitem.name = "Stun Baton"
|
||||
if(5) //emag
|
||||
owner.halitem.icon = 'icons/obj/card.dmi'
|
||||
owner.halitem.icon_state = "emag"
|
||||
owner.halitem.name = "Cryptographic Sequencer"
|
||||
if(6) //flashbang
|
||||
owner.halitem.icon = 'icons/obj/grenade.dmi'
|
||||
owner.halitem.icon_state = "flashbang1"
|
||||
owner.halitem.name = "Flashbang"
|
||||
if(owner.client) owner.client.screen += owner.halitem
|
||||
spawn(rand(100,250))
|
||||
if(owner.client)
|
||||
owner.client.screen -= owner.halitem
|
||||
owner.halitem = null
|
||||
if(26 to 35) //10% chance
|
||||
//Flashes of danger
|
||||
//to_chat(src, "Danger Flash")
|
||||
if(!owner.halimage)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(owner,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
|
||||
switch(rand(1,3))
|
||||
if(1)
|
||||
//to_chat(src, "Space")
|
||||
owner.halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
|
||||
if(2)
|
||||
//to_chat(src, "Fire")
|
||||
owner.halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER)
|
||||
if(3)
|
||||
//to_chat(src, "C4")
|
||||
owner.halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)
|
||||
|
||||
|
||||
if(owner.client) owner.client.images += owner.halimage
|
||||
spawn(rand(10,50)) //Only seen for a brief moment.
|
||||
if(owner.client) owner.client.images -= owner.halimage
|
||||
owner.halimage = null
|
||||
|
||||
if(36 to 55) //20% chance
|
||||
//Strange audio
|
||||
//to_chat(src, "Strange Audio")
|
||||
switch(rand(1,12))
|
||||
if(1) owner << 'sound/machines/door/old_airlock.ogg'
|
||||
if(2)
|
||||
if(prob(50))owner << 'sound/effects/Explosion1.ogg'
|
||||
else owner << 'sound/effects/Explosion2.ogg'
|
||||
if(3) owner << 'sound/effects/explosionfar.ogg'
|
||||
if(4) owner << 'sound/effects/Glassbr1.ogg'
|
||||
if(5) owner << 'sound/effects/Glassbr2.ogg'
|
||||
if(6) owner << 'sound/effects/Glassbr3.ogg'
|
||||
if(7) owner << 'sound/machines/twobeep.ogg'
|
||||
if(8) owner << 'sound/machines/door/windowdoor.ogg'
|
||||
if(9)
|
||||
//To make it more realistic, I added two gunshots (enough to kill)
|
||||
owner << 'sound/weapons/Gunshot1.ogg'
|
||||
spawn(rand(10,30))
|
||||
owner << 'sound/weapons/Gunshot2.ogg'
|
||||
if(10) owner << 'sound/weapons/smash.ogg'
|
||||
if(11)
|
||||
//Same as above, but with tasers.
|
||||
owner << 'sound/weapons/Taser.ogg'
|
||||
spawn(rand(10,30))
|
||||
owner << 'sound/weapons/Taser.ogg'
|
||||
//Rare audio
|
||||
if(12)
|
||||
//These sounds are (mostly) taken from Hidden: Source
|
||||
var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/Heart Beat.ogg', 'sound/effects/screech.ogg',\
|
||||
'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\
|
||||
'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\
|
||||
'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\
|
||||
'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg')
|
||||
owner << pick(creepyasssounds)
|
||||
if(56 to 60) //5% chance
|
||||
//Flashes of danger
|
||||
//to_chat(src, "Danger Flash")
|
||||
if(!owner.halbody)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(owner,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
switch(rand(1,4))
|
||||
if(1)
|
||||
owner.halbody = image('icons/mob/human.dmi',target,"husk_l",TURF_LAYER)
|
||||
if(2,3)
|
||||
owner.halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
|
||||
if(4)
|
||||
owner.halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER)
|
||||
// if(5)
|
||||
// halbody = image('xcomalien.dmi',target,"chryssalid",TURF_LAYER)
|
||||
|
||||
if(owner.client) owner.client.images += owner.halbody
|
||||
spawn(rand(50,80)) //Only seen for a brief moment.
|
||||
if(owner.client) owner.client.images -= owner.halbody
|
||||
owner.halbody = null
|
||||
if(61 to 85) //25% chance
|
||||
//food
|
||||
if(!owner.halbody)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(owner,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
switch(rand(1,10))
|
||||
if(1)
|
||||
owner.halbody = image('icons/mob/animal.dmi',target,"cow",TURF_LAYER)
|
||||
if(2)
|
||||
owner.halbody = image('icons/mob/animal.dmi',target,"chicken",TURF_LAYER)
|
||||
if(3)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"bigbiteburger",TURF_LAYER)
|
||||
if(4)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"meatbreadslice",TURF_LAYER)
|
||||
if(5)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"sausage",TURF_LAYER)
|
||||
if(6)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"bearmeat",TURF_LAYER)
|
||||
if(7)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"fishfillet",TURF_LAYER)
|
||||
if(8)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"meat",TURF_LAYER)
|
||||
if(9)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"meatstake",TURF_LAYER)
|
||||
if(10)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"monkeysdelight",TURF_LAYER)
|
||||
|
||||
if(owner.client) owner.client.images += owner.halbody
|
||||
spawn(rand(50,80)) //Only seen for a brief moment.
|
||||
if(owner.client) owner.client.images -= owner.halbody
|
||||
owner.halbody = null
|
||||
if(86 to 100) //15% chance
|
||||
//hear voices. Could make the voice pick from nearby creatures, but nearby creatures make feral hallucinations rare so don't bother.
|
||||
var/list/hiddenspeakers = list("Someone distant", "A voice nearby","A familiar voice", "An echoing voice", "A cautious voice", "A scared voice", "Someone around the corner", "Someone", "Something", "Something scary", "An urgent voice", "An angry voice")
|
||||
var/list/speakerverbs = list("calls out", "yells", "screams", "exclaims", "shrieks", "shouts", "hisses", "snarls")
|
||||
var/list/spookyphrases = list("It's over here!","Stop it!", "Hunt it down!", "Get it!", "Quick, over here!", "Anyone there?", "Who's there?", "Catch that thing!", "Stop it! Kill it!", "Anyone there?", "Where is it?", "Find it!", "There it is!")
|
||||
to_chat(owner, span_game(span_say(span_name(pick(hiddenspeakers)) + " [pick(speakerverbs)], \"[pick(spookyphrases)]\"")))
|
||||
|
||||
|
||||
owner.handling_hal = 0
|
||||
return
|
||||
|
||||
/obj/screen/xenochimera
|
||||
icon = 'icons/mob/chimerahud.dmi'
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/obj/screen/xenochimera/danger_level
|
||||
name = "danger level"
|
||||
icon_state = "danger00" //first number is bool of whether or not we're in danger, second is whether or not we're feral
|
||||
alpha = 200
|
||||
|
||||
/mob/living/carbon/human/proc/reconstitute_form() //Scree's race ability.in exchange for: No cloning.
|
||||
set name = "Reconstitute Form"
|
||||
set category = "Abilities.Xenochimera"
|
||||
|
||||
if(is_incorporeal())
|
||||
to_chat(src, "You cannot regenerate while incorporeal.")
|
||||
return
|
||||
// Sanity is mostly handled in chimera_regenerate()
|
||||
if(stat == DEAD)
|
||||
var/confirm = tgui_alert(src, "Are you sure you want to regenerate your corpse? This process can take up to thirty minutes.", "Confirm Regeneration", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
chimera_regenerate()
|
||||
else if (quickcheckuninjured())
|
||||
var/confirm = tgui_alert(src, "Are you sure you want to regenerate? As you are uninjured this will only take 30 seconds and match your appearance to your character slot.", "Confirm Regeneration", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
chimera_regenerate()
|
||||
else
|
||||
var/confirm = tgui_alert(src, "Are you sure you want to completely reconstruct your form? This process can take up to fifteen minutes, depending on how hungry you are, and you will be unable to move.", "Confirm Regeneration", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
chimera_regenerate()
|
||||
|
||||
/mob/living/carbon/human/proc/chimera_regenerate()
|
||||
var/datum/component/xenochimera/xc = get_xenochimera_component()
|
||||
if(!xc)
|
||||
return
|
||||
//If they're already regenerating
|
||||
switch(xc.revive_ready)
|
||||
if(REVIVING_NOW)
|
||||
to_chat(src, "You are already reconstructing, just wait for the reconstruction to finish!")
|
||||
return
|
||||
if(REVIVING_DONE)
|
||||
to_chat(src, "Your reconstruction is done, but you need to hatch now.")
|
||||
return
|
||||
if(xc.revive_ready > world.time)
|
||||
to_chat(src, "You can't use that ability again so soon!")
|
||||
return
|
||||
|
||||
var/time = min(900, (120+780/(1 + nutrition/100))) //capped at 15 mins, roughly 6 minutes at 250 (yellow) nutrition, 4.1 minutes at 500 (grey), cannot be below 2 mins
|
||||
if (quickcheckuninjured()) //if you're completely uninjured, then you get a speedymode - check health first for quickness
|
||||
time = 30
|
||||
|
||||
//Clicked regen while dead.
|
||||
if(stat == DEAD)
|
||||
|
||||
//reviving from dead takes extra nutriment to be provided from outside OR takes twice as long and consumes extra at the end
|
||||
if(!hasnutriment())
|
||||
time = time*2
|
||||
|
||||
to_chat(src, "You begin to reconstruct your form. You will not be able to move during this time. It should take aproximately [round(time)] seconds.")
|
||||
|
||||
//Scary spawnerization.
|
||||
xc.revive_ready = REVIVING_NOW
|
||||
xc.revive_finished = (world.time + time SECONDS) // When do we finish reviving? Allows us to find out when we're done, called by the alert currently.
|
||||
throw_alert("regen", /obj/screen/alert/xenochimera/reconstitution)
|
||||
addtimer(CALLBACK(src, PROC_REF(chimera_regenerate_ready)), time SECONDS, TIMER_DELETE_ME)
|
||||
|
||||
//Clicked regen while NOT dead
|
||||
else
|
||||
to_chat(src, "You begin to reconstruct your form. You will not be able to move during this time. It should take aproximately [round(time)] seconds.")
|
||||
|
||||
//Waiting for regen after being alive
|
||||
xc.revive_ready = REVIVING_NOW
|
||||
xc.revive_finished = (world.time + time SECONDS) // When do we finish reviving? Allows us to find out when we're done, called by the alert currently.
|
||||
throw_alert("regen", /obj/screen/alert/xenochimera/reconstitution)
|
||||
addtimer(CALLBACK(src, PROC_REF(chimera_regenerate_nutrition)), time SECONDS, TIMER_DELETE_ME)
|
||||
|
||||
/mob/living/carbon/human/proc/chimera_regenerate_nutrition()
|
||||
var/datum/component/xenochimera/xc = get_xenochimera_component()
|
||||
if(!xc)
|
||||
return
|
||||
//Slightly different flavour messages
|
||||
if(stat != DEAD || hasnutriment())
|
||||
to_chat(src, span_notice("Consciousness begins to stir as your new body awakens, ready to hatch.."))
|
||||
else
|
||||
to_chat(src, span_warning("Consciousness begins to stir as your battered body struggles to recover from its ordeal.."))
|
||||
add_verb(src, /mob/living/carbon/human/proc/hatch)
|
||||
xc.revive_ready = REVIVING_DONE
|
||||
src << sound('sound/effects/mob_effects/xenochimera/hatch_notification.ogg',0,0,0,30)
|
||||
clear_alert("regen")
|
||||
throw_alert("hatch", /obj/screen/alert/xenochimera/readytohatch)
|
||||
|
||||
/mob/living/carbon/human/proc/chimera_regenerate_ready()
|
||||
var/datum/component/xenochimera/xc = get_xenochimera_component()
|
||||
if(!xc)
|
||||
return
|
||||
// check to see if they've been fixed by outside forces in the meantime such as defibbing
|
||||
if(stat != DEAD)
|
||||
to_chat(src, span_notice("Your body has recovered from its ordeal, ready to regenerate itself again."))
|
||||
xc.revive_ready = REVIVING_READY //reset their cooldown
|
||||
clear_alert("regen")
|
||||
throw_alert("hatch", /obj/screen/alert/xenochimera/readytohatch)
|
||||
|
||||
// Was dead, still dead.
|
||||
else
|
||||
to_chat(src, span_notice("Consciousness begins to stir as your new body awakens, ready to hatch."))
|
||||
add_verb(src, /mob/living/carbon/human/proc/hatch)
|
||||
xc.revive_ready = REVIVING_DONE
|
||||
src << sound('sound/effects/mob_effects/xenochimera/hatch_notification.ogg',0,0,0,30)
|
||||
clear_alert("regen")
|
||||
throw_alert("hatch", /obj/screen/alert/xenochimera/readytohatch)
|
||||
|
||||
/mob/living/carbon/human/proc/hatch()
|
||||
set name = "Hatch"
|
||||
set category = "Abilities.Xenochimera"
|
||||
var/datum/component/xenochimera/xc = get_xenochimera_component()
|
||||
if(!xc)
|
||||
return
|
||||
if(xc.revive_ready != REVIVING_DONE)
|
||||
//Hwhat?
|
||||
remove_verb(src, /mob/living/carbon/human/proc/hatch)
|
||||
return
|
||||
|
||||
var/confirm = tgui_alert(src, "Are you sure you want to hatch right now? This will be very obvious to anyone in view.", "Confirm Regeneration", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
|
||||
//Dead when hatching
|
||||
if(stat == DEAD)
|
||||
// var/sickness_duration = 10 MINUTES //CHOMPedit
|
||||
//Reviving from ded takes extra nutrition - if it isn't provided from outside sources, it comes from you
|
||||
if(!hasnutriment())
|
||||
nutrition=nutrition * 0.75
|
||||
// sickness_duration = 20 MINUTES //CHOMPedit
|
||||
chimera_hatch()
|
||||
// add_modifier(/datum/modifier/resleeving_sickness/chimera, sickness_duration) //CHOMPedit
|
||||
adjustBrainLoss(5) // if they're reviving from dead, they come back with 5 brainloss on top of whatever's unhealed.
|
||||
visible_message(span_warning("<p>" + span_huge("The former corpse staggers to its feet, all its former wounds having vanished...") + "</p>")) //Bloody hell...
|
||||
clear_alert("hatch")
|
||||
return
|
||||
|
||||
//Alive when hatching
|
||||
else
|
||||
chimera_hatch()
|
||||
|
||||
visible_message(span_warning("<p>" + span_huge("[src] rises to \his feet.") + "</p>")) //Bloody hell...
|
||||
clear_alert("hatch")
|
||||
|
||||
/mob/living/carbon/human/proc/chimera_hatch()
|
||||
var/datum/component/xenochimera/xc = get_xenochimera_component()
|
||||
if(!xc)
|
||||
return
|
||||
remove_verb(src, /mob/living/carbon/human/proc/hatch)
|
||||
to_chat(src, span_notice("Your new body awakens, bursting free from your old skin."))
|
||||
//Modify and record values (half nutrition and braindamage)
|
||||
var/old_nutrition = nutrition
|
||||
var/braindamage = min(5, max(0, (brainloss-1) * 0.5)) //brainloss is tricky to heal and might take a couple of goes to get rid of completely.
|
||||
var/uninjured=quickcheckuninjured()
|
||||
//I did have special snowflake code, but this is easier. //It's also EXTREMELY BAD AND LETS THEM SAVEFILE HACK.
|
||||
revive()
|
||||
mutations.Remove(HUSK)
|
||||
setBrainLoss(braindamage)
|
||||
species.update_vore_belly_def_variant()
|
||||
|
||||
if(!uninjured)
|
||||
nutrition = old_nutrition * 0.5
|
||||
//Drop everything
|
||||
for(var/obj/item/W in src)
|
||||
drop_from_inventory(W)
|
||||
//Visual effects
|
||||
var/T = get_turf(src)
|
||||
var/blood_color = species.blood_color
|
||||
var/flesh_color = species.flesh_color
|
||||
new /obj/effect/gibspawner/human/xenochimera(T, null, flesh_color, blood_color)
|
||||
visible_message(span_danger("<p>" + span_huge("The lifeless husk of [src] bursts open, revealing a new, intact copy in the pool of viscera.") + "</p>")) //Bloody hell...
|
||||
playsound(T, 'sound/effects/mob_effects/xenochimera/hatch.ogg', 50)
|
||||
else //lower cost for doing a quick cosmetic revive
|
||||
nutrition = old_nutrition * 0.9
|
||||
|
||||
//Unfreeze some things
|
||||
does_not_breathe = FALSE
|
||||
update_canmove()
|
||||
stunned = 2
|
||||
|
||||
xc.revive_ready = world.time + 10 MINUTES //set the cooldown, Reduced this to 10 minutes, you're playing with fire if you're reviving that often.
|
||||
|
||||
/datum/modifier/resleeving_sickness/chimera //near identical to the regular version, just with different flavortexts
|
||||
name = "imperfect regeneration"
|
||||
desc = "You feel rather weak and unfocused, having just regrown your body not so long ago."
|
||||
|
||||
on_created_text = span_warning(span_large("You feel weak and unsteady, that regeneration having been rougher than most."))
|
||||
on_expired_text = span_notice(span_large("You feel your strength and focus return to you."))
|
||||
|
||||
/obj/effect/gibspawner/human/xenochimera
|
||||
fleshcolor = "#14AD8B"
|
||||
bloodcolor = "#14AD8B"
|
||||
|
||||
|
||||
///This is bad and should not be done this way, but xenochimera was hardcoded in SO many places that it's going to be a hassle to completely undo.
|
||||
/mob/proc/get_feralness()
|
||||
var/datum/component/xenochimera/xc = GetComponent(/datum/component/xenochimera)
|
||||
if(xc)
|
||||
return xc.feral
|
||||
|
||||
/mob/proc/get_xenochimera_component()
|
||||
var/datum/component/xenochimera/xc = GetComponent(/datum/component/xenochimera)
|
||||
if(xc)
|
||||
return xc
|
||||
@@ -504,9 +504,10 @@
|
||||
apply_brain_damage(M)
|
||||
M.adjustHalLoss(40) // CHOMPEdit: Moderate amount of halloss for EVERYONE being defibbed. Defibs feel like being kicked in the chest by a mule. Shit hurts if you're awake.
|
||||
// VOREStation Edits Start: Defib pain
|
||||
if(istype(M.species, /datum/species/xenochimera)) // Only do the following to Xenochimera. Handwave this however you want, this is to balance defibs on an alien race.
|
||||
var/datum/component/xenochimera/xc = M.get_xenochimera_component()
|
||||
if(xc) // Only do the following to Xenochimera. Handwave this however you want, this is to balance defibs on an alien race.
|
||||
M.adjustHalLoss(220) // This hurts a LOT, stacks on top of the previous halloss.
|
||||
M.feral += 100 // If they somehow weren't already feral, force them feral by increasing ferality var directly, to avoid any messy checks. handle_feralness() will immediately set our feral properly according to halloss anyhow.
|
||||
xc.feral += 100 // If they somehow weren't already feral, force them feral by increasing ferality var directly, to avoid any messy checks. handle_feralness() will immediately set our feral properly according to halloss anyhow.
|
||||
// VOREStation Edits End
|
||||
// SSgame_master.adjust_danger(-20) // VOREStation Edit - We don't use SSgame_master yet.
|
||||
|
||||
|
||||
@@ -406,18 +406,18 @@
|
||||
dat += "<br>"
|
||||
dat += span_notice("Subject's pulse: [H.pulse == PULSE_THREADY || H.pulse == PULSE_NONE ? span_red(H.get_pulse(GETPULSE_TOOL) + " bpm") : span_blue(H.get_pulse(GETPULSE_TOOL) + " bpm")].") // VORE Edit: Missed a linebreak here.
|
||||
dat += "<br>"
|
||||
if(istype(H.species, /datum/species/xenochimera)) // VOREStation Edit Start: Visible feedback for medmains on Xenochimera.
|
||||
if(H.stat == DEAD && H.revive_ready == REVIVING_READY && !H.hasnutriment())
|
||||
var/datum/component/xenochimera/xc = H.get_xenochimera_component()
|
||||
if(xc)
|
||||
if(H.stat == DEAD && xc.revive_ready == REVIVING_READY && !H.hasnutriment())
|
||||
dat += span_danger("WARNING: Protein levels low. Subject incapable of reconstitution.")
|
||||
else if(H.revive_ready == REVIVING_NOW)
|
||||
dat += span_warning("Subject is undergoing form reconstruction. Estimated time to finish is in: [round((H.revive_finished - world.time) / 10)] seconds.")
|
||||
else if(H.revive_ready == REVIVING_DONE)
|
||||
else if(xc.revive_ready == REVIVING_NOW)
|
||||
dat += span_warning("Subject is undergoing form reconstruction. Estimated time to finish is in: [round((xc.revive_finished - world.time) / 10)] seconds.")
|
||||
else if(xc.revive_ready == REVIVING_DONE)
|
||||
dat += span_notice("Subject is ready to hatch. Transfer to dark room for holding with food available.")
|
||||
else if(H.stat == DEAD)
|
||||
dat+= span_danger("WARNING: Defib will cause extreme pain and set subject feral. Sedation recommended prior to defibrillation.")
|
||||
else // If they bop them and they're not dead or reviving, give 'em a little notice.
|
||||
dat += span_notice("Subject is a Xenochimera. Treat accordingly.")
|
||||
// VOREStation Edit End
|
||||
user.show_message(dat, 1)
|
||||
if(guide)
|
||||
guide(M, user)
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
icon_state = "atmos_extinguisher0"
|
||||
item_state = "atmos_extinguisher"
|
||||
throwforce = 12
|
||||
force = 12
|
||||
w_class = ITEMSIZE_LARGE
|
||||
force = 3.0
|
||||
max_water = 600
|
||||
spray_particles = 3
|
||||
sprite_name = "atmos_extinguisher"
|
||||
|
||||
@@ -27,15 +27,14 @@
|
||||
to_chat(L, span_danger("The more you move through this darkness, the more you can feel a throbbing, shooting ache in your bones."))
|
||||
if(prob(5))
|
||||
L.visible_message("[L]'s body gives off a faint, sparking, haze...", "Your body gives off a faint, sparking, haze...", runemessage = "gives off a faint, sparking haze")
|
||||
else if(istype(L.species, /datum/species/shadekin))
|
||||
var/obj/item/organ/internal/brain/shadekin/B = L.internal_organs_by_name[O_BRAIN]
|
||||
B.dark_energy += 10
|
||||
var/datum/component/shadekin/comp = L.GetComponent(/datum/component/shadekin)
|
||||
if(comp)
|
||||
comp.dark_energy += 10
|
||||
if(prob(10))
|
||||
to_chat(L, span_notice("You can feel the energy flowing into you!"))
|
||||
else
|
||||
if(prob(0.25))
|
||||
to_chat(L, span_danger("The darkness seethes under your feet..."))
|
||||
L.hallucination += 50
|
||||
else if(prob(0.25))
|
||||
to_chat(L, span_danger("The darkness seethes under your feet..."))
|
||||
L.hallucination += 50
|
||||
|
||||
/turf/simulated/floor/weird_things/dark/proc/add_glow()
|
||||
var/choice = "overlay-[rand(1,6)]"
|
||||
@@ -86,15 +85,14 @@
|
||||
to_chat(L, span_danger("The more you move through this darkness, the more you can feel a throbbing, shooting ache in your bones."))
|
||||
if(prob(5))
|
||||
L.visible_message("[L]'s body gives off a faint, sparking, haze...", "Your body gives off a faint, sparking, haze...", runemessage = "gives off a faint, sparking haze")
|
||||
else if(istype(L.species, /datum/species/shadekin))
|
||||
var/obj/item/organ/internal/brain/shadekin/B = L.internal_organs_by_name[O_BRAIN]
|
||||
B.dark_energy += 10
|
||||
var/datum/component/shadekin/comp = L.GetComponent(/datum/component/shadekin)
|
||||
if(comp)
|
||||
comp.dark_energy += 10
|
||||
if(prob(10))
|
||||
to_chat(L, span_notice("You can feel the energy flowing into you!"))
|
||||
else
|
||||
if(prob(0.25))
|
||||
to_chat(L, span_danger("The darkness seethes under your feet..."))
|
||||
L.hallucination += 50
|
||||
else if(prob(0.25))
|
||||
to_chat(L, span_danger("The darkness seethes under your feet..."))
|
||||
L.hallucination += 50
|
||||
|
||||
/turf/unsimulated/floor/dark/proc/add_glow()
|
||||
var/flip = rand(1,2)
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
shadekin.dir = SOUTH
|
||||
shadekin.ability_flags |= 0x1
|
||||
shadekin.phase_shift() //Homf
|
||||
shadekin.energy = initial(shadekin.energy)
|
||||
shadekin.comp.dark_energy = initial(shadekin.comp.dark_energy)
|
||||
//For fun
|
||||
sleep(1 SECOND)
|
||||
shadekin.dir = WEST
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
shadekin.dir = SOUTH
|
||||
shadekin.ability_flags |= 0x1
|
||||
shadekin.phase_shift() //Homf
|
||||
shadekin.energy = initial(shadekin.energy)
|
||||
shadekin.comp.dark_energy = initial(shadekin.comp.dark_energy)
|
||||
//For fun
|
||||
sleep(1 SECOND)
|
||||
shadekin.dir = WEST
|
||||
|
||||
@@ -131,10 +131,12 @@
|
||||
t_He = "Shi"
|
||||
t_His = "Hir"
|
||||
t_his = "hir"
|
||||
if(revive_ready == REVIVING_NOW || revive_ready == REVIVING_DONE)
|
||||
if(stat == DEAD)
|
||||
return span_warning("[t_His] body is twitching subtly.")
|
||||
else
|
||||
return span_notice("[t_He] [t_appear] to be in some sort of torpor.")
|
||||
if(feral)
|
||||
return span_warning("[t_He] [t_has] a crazed, wild look in [t_his] eyes!")
|
||||
var/datum/component/xenochimera/xc = get_xenochimera_component()
|
||||
if(xc)
|
||||
if((xc.revive_ready == REVIVING_NOW || xc.revive_ready == REVIVING_DONE))
|
||||
if(stat == DEAD)
|
||||
return span_warning("[t_His] body is twitching subtly.")
|
||||
else
|
||||
return span_notice("[t_He] [t_appear] to be in some sort of torpor.")
|
||||
else if(xc.feral)
|
||||
return span_warning("[t_He] [t_has] a crazed, wild look in [t_his] eyes!")
|
||||
|
||||
@@ -832,7 +832,7 @@
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/IsAdvancedToolUser(var/silent)
|
||||
if(feral)
|
||||
if(get_feralness())
|
||||
to_chat(src, span_warning("Your primitive mind can't grasp the concept of that thing."))
|
||||
return 0
|
||||
if(species.has_fine_manipulation)
|
||||
@@ -1311,6 +1311,7 @@
|
||||
|
||||
species.create_organs(src)
|
||||
|
||||
species.apply_components(src)
|
||||
|
||||
maxHealth = species.total_health
|
||||
hunger_rate = species.hunger_factor
|
||||
|
||||
@@ -577,7 +577,7 @@
|
||||
|
||||
// standard CPR ahead, adjust oxy and refresh health
|
||||
if(health > CONFIG_GET(number/health_threshold_crit) && prob(10))
|
||||
if(istype(species, /datum/species/xenochimera))
|
||||
if(get_xenochimera_component())
|
||||
visible_message(span_danger("\The [src]'s body twitches and gurgles a bit."))
|
||||
to_chat(reviver, span_danger("You get the feeling [src] can't be revived by CPR alone."))
|
||||
return // Handle xenochim, can't cpr them back to life
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
var/hungry = (500 - nutrition) / 5 //Fixed 500 here instead of our huge MAX_NUTRITION
|
||||
if (hungry >= 70) . += hungry/50
|
||||
|
||||
if (feral >= 10) //crazy feral animals give less and less of a shit about pain and hunger as they get crazier
|
||||
. = max(species.slowdown, species.slowdown+((.-species.slowdown)/(feral/10))) // As feral scales to damage, this amounts to an effective +1 slowdown cap
|
||||
if (get_feralness() >= 10) //crazy feral animals give less and less of a shit about pain and hunger as they get crazier
|
||||
. = max(species.slowdown, species.slowdown+((.-species.slowdown)/(get_feralness()/10))) // As feral scales to damage, this amounts to an effective +1 slowdown cap
|
||||
if(shock_stage >= 10) . -= 1.5 //this gets a +3 later, feral critters take reduced penalty
|
||||
if(riding_datum) //Bit of slowdown for taur rides if rider is bigger or fatter than mount.
|
||||
var/datum/riding/R = riding_datum
|
||||
|
||||
@@ -80,6 +80,9 @@
|
||||
else if(stat == DEAD && !stasis)
|
||||
handle_defib_timer()
|
||||
|
||||
//Handle any species related components we may have. Ex: Shadekin, Xenochimera, etc. Not STAT checked because those do statchecks in their own code.
|
||||
handle_species_components()
|
||||
|
||||
if(skip_some_updates())
|
||||
return //We go ahead and process them 5 times for HUD images and other stuff though.
|
||||
|
||||
@@ -913,6 +916,9 @@
|
||||
if(species.allergen_reaction & AG_CONFUSE)
|
||||
Confuse(disable_severity/4)
|
||||
|
||||
/mob/living/carbon/human/proc/handle_species_components()
|
||||
species.handle_species_components(src)
|
||||
|
||||
/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment)
|
||||
if(!environment)
|
||||
return
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
/obj/structure/dark_portal/proc/get_shadekin_energy(mob/shade_maybe)
|
||||
if(istype(shade_maybe, /mob/living/simple_mob/shadekin))
|
||||
var/mob/living/simple_mob/shadekin/shadekin = shade_maybe
|
||||
return shadekin.energy
|
||||
return shadekin.comp.dark_energy
|
||||
else if(istype(shade_maybe, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/carbonkin_maybe = shade_maybe
|
||||
return carbonkin_maybe.shadekin_get_energy()
|
||||
@@ -46,7 +46,7 @@
|
||||
/obj/structure/dark_portal/proc/adjust_shadekin_energy(mob/shade_maybe, amount)
|
||||
if(istype(shade_maybe, /mob/living/simple_mob/shadekin))
|
||||
var/mob/living/simple_mob/shadekin/shadekin = shade_maybe
|
||||
shadekin.energy += amount
|
||||
shadekin.comp.dark_energy += amount
|
||||
return
|
||||
else if(istype(shade_maybe, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/carbonkin_maybe = shade_maybe
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
var/manual_respite = FALSE //CHOMPEdit - Dark Respite
|
||||
var/respite_activating = FALSE //CHOMPEdit - Dark Respite
|
||||
var/nutrition_energy_conversion = TRUE //CHOMPEdit - Add toggle to nutrition and energy conversions
|
||||
species_component = /datum/component/shadekin
|
||||
|
||||
/datum/species/shadekin/New()
|
||||
..()
|
||||
@@ -345,42 +346,37 @@
|
||||
update_shadekin_hud(H)
|
||||
|
||||
/datum/species/shadekin/proc/get_energy(var/mob/living/carbon/human/H)
|
||||
var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
|
||||
|
||||
if(!istype(shade_organ))
|
||||
return 0
|
||||
var/datum/component/shadekin/comp = H.GetComponent(/datum/component/shadekin)
|
||||
if(!comp)
|
||||
return FALSE //No component, no energy to be had.
|
||||
//CHOMPEdit - Dark Respite
|
||||
if(H.ability_flags & AB_DARK_RESPITE || H.has_modifier_of_type(/datum/modifier/dark_respite))
|
||||
return 0
|
||||
return FALSE
|
||||
//CHOMPEdit - Dark Respite
|
||||
if(shade_organ.dark_energy_infinite)
|
||||
return shade_organ.max_dark_energy
|
||||
if(comp.dark_energy_infinite)
|
||||
return comp.max_dark_energy
|
||||
|
||||
return shade_organ.dark_energy
|
||||
return comp.dark_energy
|
||||
|
||||
/datum/species/shadekin/proc/get_max_energy(var/mob/living/carbon/human/H)
|
||||
var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
|
||||
|
||||
if(!istype(shade_organ))
|
||||
return 0
|
||||
|
||||
return shade_organ.max_dark_energy - (LAZYLEN(active_dark_maws) * 5)
|
||||
var/datum/component/shadekin/comp = H.GetComponent(/datum/component/shadekin)
|
||||
if(!comp)
|
||||
return FALSE //No component, no energy to be had.
|
||||
return comp.max_dark_energy
|
||||
|
||||
/datum/species/shadekin/proc/set_energy(var/mob/living/carbon/human/H, var/new_energy)
|
||||
var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
|
||||
var/datum/component/shadekin/comp = H.GetComponent(/datum/component/shadekin)
|
||||
if(!comp)
|
||||
return FALSE //No component, no energy to be had.
|
||||
|
||||
if(!istype(shade_organ))
|
||||
return
|
||||
|
||||
shade_organ.dark_energy = CLAMP(new_energy, 0, get_max_energy(H))
|
||||
comp.dark_energy = CLAMP(new_energy, 0, get_max_energy(H))
|
||||
|
||||
/datum/species/shadekin/proc/set_max_energy(var/mob/living/carbon/human/H, var/new_max_energy)
|
||||
var/obj/item/organ/internal/brain/shadekin/shade_organ = H.internal_organs_by_name[O_BRAIN]
|
||||
var/datum/component/shadekin/comp = H.GetComponent(/datum/component/shadekin)
|
||||
if(!comp)
|
||||
return FALSE //No component, no energy to be had.
|
||||
|
||||
if(!istype(shade_organ))
|
||||
return 0
|
||||
|
||||
shade_organ.max_dark_energy = new_max_energy
|
||||
comp.max_dark_energy = new_max_energy
|
||||
|
||||
/datum/species/shadekin/proc/update_shadekin_hud(var/mob/living/carbon/human/H)
|
||||
var/turf/T = get_turf(H)
|
||||
|
||||
@@ -371,6 +371,7 @@
|
||||
var/list/food_preference = list() //RS edit
|
||||
var/food_preference_bonus = 0
|
||||
|
||||
var/datum/component/species_component = null // The component that this species uses. Example: Xenochimera use /datum/component/xenochimera
|
||||
|
||||
// For Lleill and Hanner
|
||||
var/lleill_energy = 200
|
||||
@@ -606,6 +607,23 @@
|
||||
env_trait.handle_environment_special(H)
|
||||
return
|
||||
|
||||
/datum/species/proc/handle_species_components(var/mob/living/carbon/human/H)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
|
||||
//Xenochimera Species Component
|
||||
var/datum/component/xenochimera/xc = H.get_xenochimera_component()
|
||||
if(xc)
|
||||
if(!H.stat || !(xc.revive_ready == REVIVING_NOW || xc.revive_ready == REVIVING_DONE))
|
||||
SEND_SIGNAL(H, COMSIG_XENOCHIMERA_COMPONENT)
|
||||
|
||||
//Shadekin Species Component.
|
||||
/* //For when shadekin actually have their component control everything.
|
||||
var/datum/component/shadekin/sk = H.get_xenochimera_component()
|
||||
if(sk)
|
||||
if(!H.stat || !(xc.revive_ready == REVIVING_NOW || xc.revive_ready == REVIVING_DONE))
|
||||
SEND_SIGNAL(H, COMSIG_SHADEKIN_COMPONENT)
|
||||
*/
|
||||
|
||||
// Used to update alien icons for aliens.
|
||||
/datum/species/proc/handle_login_special(var/mob/living/carbon/human/H)
|
||||
return
|
||||
@@ -757,6 +775,10 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/datum/species/proc/apply_components(var/mob/living/carbon/human/H)
|
||||
if(species_component)
|
||||
H.LoadComponent(species_component)
|
||||
|
||||
/datum/species/proc/produceCopy(var/list/traits, var/mob/living/carbon/human/H, var/custom_base, var/reset_dna = TRUE) // Traitgenes reset_dna flag required, or genes get reset on resleeve
|
||||
ASSERT(src)
|
||||
ASSERT(istype(H))
|
||||
|
||||
@@ -165,12 +165,12 @@
|
||||
/datum/unarmed_attack/claws/chimera //special feral attack that gets stronger as they get angrier
|
||||
|
||||
/datum/unarmed_attack/claws/chimera/get_unarmed_damage(var/mob/living/carbon/human/user)
|
||||
return user.feral/5
|
||||
return user.get_feralness()/5
|
||||
|
||||
/datum/unarmed_attack/claws/chimera/apply_effects(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/armour,var/attack_damage,var/zone)
|
||||
..()
|
||||
if(user.feral && !(target == user))
|
||||
var/selfdamage = ((user.feral/10)-7.5)
|
||||
if(user.get_feralness() && !(target == user))
|
||||
var/selfdamage = ((user.get_feralness()/10)-7.5)
|
||||
if(selfdamage > 0)
|
||||
var/selfdamagezone = null
|
||||
if (user.hand)
|
||||
|
||||
@@ -1701,8 +1701,7 @@
|
||||
tail = "tail"
|
||||
icobase_tail = 1
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/reconstitute_form,
|
||||
///mob/living/carbon/human/proc/sonar_ping,
|
||||
/mob/living/carbon/human/proc/sonar_ping,
|
||||
/mob/living/carbon/human/proc/tie_hair,
|
||||
/mob/living/carbon/human/proc/lick_wounds,
|
||||
/mob/living/carbon/human/proc/shapeshifter_reassemble) //Xenochimera get all the special verbs since they can't select traits.
|
||||
@@ -1753,260 +1752,32 @@
|
||||
|
||||
reagent_tag = IS_CHIMERA
|
||||
|
||||
species_component = /datum/component/xenochimera
|
||||
|
||||
/datum/species/xenochimera/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
//If they're KO'd/dead, or reviving, they're probably not thinking a lot about much of anything.
|
||||
if(!H.stat || !(H.revive_ready == REVIVING_NOW || H.revive_ready == REVIVING_DONE))
|
||||
handle_feralness(H)
|
||||
|
||||
//While regenerating
|
||||
if(H.revive_ready == REVIVING_NOW || H.revive_ready == REVIVING_DONE)
|
||||
H.stunned = 5
|
||||
H.canmove = 0
|
||||
H.does_not_breathe = TRUE
|
||||
var/regen_sounds = H.regen_sounds
|
||||
if(prob(2)) // 2% chance of playing squelchy noise while reviving, which is run roughly every 2 seconds/tick while regenerating.
|
||||
playsound(H, pick(regen_sounds), 30)
|
||||
H.visible_message(span_danger("<p>" + span_huge("[H.name]'s motionless form shudders grotesquely, rippling unnaturally.") + "</p>"))
|
||||
if(!H.lying)
|
||||
H.lay_down()
|
||||
//Cold/pressure effects when not regenerating
|
||||
else
|
||||
var/datum/gas_mixture/environment = H.loc.return_air()
|
||||
var/pressure2 = environment.return_pressure()
|
||||
var/adjusted_pressure2 = H.calculate_affecting_pressure(pressure2)
|
||||
var/datum/gas_mixture/environment = H.loc.return_air()
|
||||
var/pressure2 = environment.return_pressure()
|
||||
var/adjusted_pressure2 = H.calculate_affecting_pressure(pressure2)
|
||||
|
||||
//Very low pressure damage
|
||||
if(adjusted_pressure2 <= 20)
|
||||
H.take_overall_damage(brute=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure")
|
||||
//they handle areas where they can't breathe better than most, but it still lowers their effective health as well as all the other bad stuff that comes with unbreathable environments
|
||||
if(H.getOxyLoss() >= 50)
|
||||
H.does_not_breathe = TRUE
|
||||
//Very low pressure damage
|
||||
if(adjusted_pressure2 <= 20)
|
||||
H.take_overall_damage(brute=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure")
|
||||
//they handle areas where they can't breathe better than most, but it still lowers their effective health as well as all the other bad stuff that comes with unbreathable environments
|
||||
if(H.getOxyLoss() >= 50)
|
||||
H.does_not_breathe = TRUE
|
||||
|
||||
//Cold hurts and gives them pain messages, eventually weakening and paralysing, but doesn't damage or trigger feral.
|
||||
//NB: 'body_temperature' used here is the 'setpoint' species var
|
||||
var/temp_diff = body_temperature - H.bodytemperature
|
||||
if(temp_diff >= 50)
|
||||
H.shock_stage = min(H.shock_stage + (temp_diff/20), 160) // Divided by 20 is the same as previous numbers, but a full scale
|
||||
H.eye_blurry = max(5,H.eye_blurry)
|
||||
|
||||
/datum/species/xenochimera/proc/handle_feralness(var/mob/living/carbon/human/H)
|
||||
//first, calculate how stressed the chimera is
|
||||
var/laststress = 0
|
||||
var/obj/item/organ/internal/brain/B = H.internal_organs_by_name[O_BRAIN]
|
||||
if(B) //if you don't have a chimera brain in a chimera body somehow, you don't get the feraless protection
|
||||
laststress = B.laststress
|
||||
|
||||
//Low-ish nutrition has messages and can eventually cause feralness
|
||||
var/hunger = max(0, 150 - H.nutrition)
|
||||
|
||||
//pain makes feralness a thing
|
||||
var/shock = 0.75*H.traumatic_shock
|
||||
|
||||
//Caffeinated or otherwise overexcited xenochimera can become feral and have special messages
|
||||
var/jittery = max(0, H.jitteriness - 100)
|
||||
|
||||
//To reduce distant object references
|
||||
var/feral = H.feral
|
||||
|
||||
//Are we in danger of ferality?
|
||||
var/danger = FALSE
|
||||
var/feral_state = FALSE
|
||||
|
||||
//finally, calculate the current stress total the chimera is operating under, and the cause
|
||||
var/currentstress = (hunger + shock + jittery)
|
||||
var/cause = "stress"
|
||||
if(hunger > shock && hunger > jittery)
|
||||
cause = "hunger"
|
||||
else if (shock > hunger && shock > jittery)
|
||||
cause = "shock"
|
||||
else if (jittery > shock && jittery > hunger)
|
||||
cause = "jittery"
|
||||
|
||||
//check to see if they go feral if they weren't before
|
||||
if(!feral && !isbelly(H.loc))
|
||||
// if stress is below 15, no chance of snapping. Also if they weren't feral before, they won't suddenly become feral unless they get MORE stressed
|
||||
if((currentstress > laststress) && prob(clamp(currentstress-15, 0, 100)) )
|
||||
go_feral(H, currentstress, cause)
|
||||
feral = currentstress //update the local var
|
||||
|
||||
//they didn't go feral, give 'em a chance of hunger messages
|
||||
else if(H.nutrition <= 200 && prob(0.5))
|
||||
switch(H.nutrition)
|
||||
if(150 to 200)
|
||||
to_chat(H,span_info("You feel rather hungry. It might be a good idea to find some some food..."))
|
||||
if(100 to 150)
|
||||
to_chat(H,span_warning("You feel like you're going to snap and give in to your hunger soon... It would be for the best to find some [pick("food","prey")] to eat..."))
|
||||
danger = TRUE
|
||||
|
||||
//now the check's done, update their brain so it remembers how stressed they were
|
||||
if(B && !isbelly(H.loc)) //another sanity check for brain implant shenanigans, also no you don't get to hide in a belly and get your laststress set to a huge amount to skip rolls
|
||||
B.laststress = currentstress
|
||||
|
||||
// Handle being feral
|
||||
if(feral)
|
||||
//We're feral
|
||||
feral_state = TRUE
|
||||
|
||||
//If they're still stressed, they stay feral
|
||||
if(currentstress >= 15)
|
||||
danger = TRUE
|
||||
feral = max(feral, currentstress)
|
||||
|
||||
else
|
||||
feral = max(0,--feral)
|
||||
|
||||
// Being in a belly or in the darkness decreases stress further. Helps mechanically reward players for staying in darkness + RP'ing appropriately. :9
|
||||
var/turf/T = get_turf(H)
|
||||
if(feral && (isbelly(H.loc) || T.get_lumcount() <= 0.1))
|
||||
feral = max(0,--feral)
|
||||
|
||||
//Set our real mob's var to our temp var
|
||||
H.feral = feral
|
||||
|
||||
//Did we just finish being feral?
|
||||
if(!feral)
|
||||
feral_state = FALSE
|
||||
to_chat(H,span_info("Your thoughts start clearing, your feral urges having passed - for the time being, at least."))
|
||||
log_and_message_admins("is no longer feral.", H)
|
||||
update_xenochimera_hud(H, danger, feral_state)
|
||||
return
|
||||
|
||||
//If they lose enough health to hit softcrit, handle_shock() will keep resetting this. Otherwise, pissed off critters will lose shock faster than they gain it.
|
||||
H.shock_stage = max(H.shock_stage-(feral/20), 0)
|
||||
|
||||
//Handle light/dark areas
|
||||
var/turf/T = get_turf(H)
|
||||
if(!T)
|
||||
update_xenochimera_hud(H, danger, feral_state)
|
||||
return //Nullspace
|
||||
var/darkish = T.get_lumcount() <= 0.1
|
||||
|
||||
//Don't bother doing heavy lifting if we weren't going to give emotes anyway.
|
||||
if(!prob(1))
|
||||
|
||||
//This is basically the 'lite' version of the below block.
|
||||
var/list/nearby = H.living_mobs(world.view)
|
||||
|
||||
//Not in the dark, or a belly, and out in the open.
|
||||
if(!darkish && isturf(H.loc) && !isbelly(H.loc)) // Added specific check for if in belly
|
||||
|
||||
//Always handle feral if nobody's around and not in the dark.
|
||||
if(!nearby.len)
|
||||
H.handle_feral()
|
||||
|
||||
//Rarely handle feral if someone is around
|
||||
else if(prob(1))
|
||||
H.handle_feral()
|
||||
|
||||
//And bail
|
||||
update_xenochimera_hud(H, danger, feral_state)
|
||||
return
|
||||
|
||||
// In the darkness, or "hidden", or in a belly. No need for custom scene-protection checks as it's just an occational infomessage.
|
||||
if(darkish || !isturf(H.loc) || isbelly(H.loc)) // Specific check for if in belly. !isturf should do this, but JUST in case.
|
||||
// If hurt, tell 'em to heal up
|
||||
if (cause == "shock")
|
||||
to_chat(H,span_info("This place seems safe, secure, hidden, a place to lick your wounds and recover..."))
|
||||
|
||||
//If hungry, nag them to go and find someone or something to eat.
|
||||
else if(cause == "hunger")
|
||||
to_chat(H,span_info("Secure in your hiding place, your hunger still gnaws at you. You need to catch some food..."))
|
||||
|
||||
//If jittery, etc
|
||||
else if(cause == "jittery")
|
||||
to_chat(H,span_info("sneakysneakyyesyesyescleverhidingfindthingsyessssss"))
|
||||
|
||||
//Otherwise, just tell them to keep hiding.
|
||||
else
|
||||
to_chat(H,span_info("...safe..."))
|
||||
|
||||
// NOT in the darkness
|
||||
else
|
||||
|
||||
//Twitch twitch
|
||||
if(!H.stat)
|
||||
H.emote("twitch")
|
||||
|
||||
var/list/nearby = H.living_mobs(world.view)
|
||||
|
||||
// Someone/something nearby
|
||||
if(nearby.len)
|
||||
var/M = pick(nearby)
|
||||
if(cause == "shock")
|
||||
to_chat(H,span_danger("You're hurt, in danger, exposed, and [M] looks to be a little too close for comfort..."))
|
||||
else
|
||||
to_chat(H,span_danger("Every movement, every flick, every sight and sound has your full attention, your hunting instincts on high alert... In fact, [M] looks extremely appetizing..."))
|
||||
|
||||
// Nobody around
|
||||
else
|
||||
if(cause == "hunger")
|
||||
to_chat(H,span_danger("Confusing sights and sounds and smells surround you - scary and disorienting it may be, but the drive to hunt, to feed, to survive, compels you."))
|
||||
else if(cause == "jittery")
|
||||
to_chat(H,span_danger("yesyesyesyesyesyesgetthethingGETTHETHINGfindfoodsfindpreypounceyesyesyes"))
|
||||
else
|
||||
to_chat(H,span_danger("Confusing sights and sounds and smells surround you, this place is wrong, confusing, frightening. You need to hide, go to ground..."))
|
||||
|
||||
// HUD update time
|
||||
update_xenochimera_hud(H, danger, feral_state)
|
||||
|
||||
/datum/species/xenochimera/proc/go_feral(var/mob/living/carbon/human/H, var/stress, var/cause)
|
||||
// Going feral due to hunger
|
||||
if(cause == "hunger")
|
||||
to_chat(H,span_danger(span_large("Something in your mind flips, your instincts taking over, no longer able to fully comprehend your surroundings as survival becomes your primary concern - you must feed, survive, there is nothing else. Hunt. Eat. Hide. Repeat.")))
|
||||
log_and_message_admins("has gone feral due to hunger.", H)
|
||||
|
||||
// If they're hurt, chance of snapping.
|
||||
else if(cause == "shock")
|
||||
//If the majority of their shock is due to halloss, give them a different message (3x multiplier on check as halloss is 2x - meaning t_s must be at least 3x for other damage sources to be the greater part)
|
||||
if(3*H.halloss >= H.traumatic_shock)
|
||||
to_chat(H,span_danger(span_large("The pain! It stings! Got to get away! Your instincts take over, urging you to flee, to hide, to go to ground, get away from here...")))
|
||||
log_and_message_admins("has gone feral due to halloss.", H)
|
||||
|
||||
//Majority due to other damage sources
|
||||
else
|
||||
to_chat(H,span_danger(span_large("Your fight-or-flight response kicks in, your injuries too much to simply ignore - you need to flee, to hide, survive at all costs - or destroy whatever is threatening you.")))
|
||||
log_and_message_admins("has gone feral due to injury.", H)
|
||||
|
||||
//No hungry or shock, but jittery
|
||||
else if(cause == "jittery")
|
||||
to_chat(H,span_warning(span_large("Suddenly, something flips - everything that moves is... potential prey. A plaything. This is great! Time to hunt!")))
|
||||
log_and_message_admins("has gone feral due to jitteriness.", H)
|
||||
|
||||
else // catch-all just in case something weird happens
|
||||
to_chat(H,span_warning(span_large("The stress of your situation is too much for you, and your survival instincts kick in!")))
|
||||
log_and_message_admins("has gone feral for unknown reasons.", H)
|
||||
//finally, set their feral var
|
||||
H.feral = stress
|
||||
if(!H.stat)
|
||||
H.emote("twitch")
|
||||
//Cold hurts and gives them pain messages, eventually weakening and paralysing, but doesn't damage or trigger feral.
|
||||
//NB: 'body_temperature' used here is the 'setpoint' species var
|
||||
var/temp_diff = body_temperature - H.bodytemperature
|
||||
if(temp_diff >= 50)
|
||||
H.shock_stage = min(H.shock_stage + (temp_diff/20), 160) // Divided by 20 is the same as previous numbers, but a full scale
|
||||
H.eye_blurry = max(5,H.eye_blurry)
|
||||
|
||||
/datum/species/xenochimera/get_race_key()
|
||||
var/datum/species/real = GLOB.all_species[base_species]
|
||||
return real.race_key
|
||||
|
||||
/datum/species/xenochimera/proc/update_xenochimera_hud(var/mob/living/carbon/human/H, var/danger, var/feral)
|
||||
if(H.xenochimera_danger_display)
|
||||
H.xenochimera_danger_display.invisibility = INVISIBILITY_NONE
|
||||
if(danger && feral)
|
||||
H.xenochimera_danger_display.icon_state = "danger11"
|
||||
else if(danger && !feral)
|
||||
H.xenochimera_danger_display.icon_state = "danger10"
|
||||
else if(!danger && feral)
|
||||
H.xenochimera_danger_display.icon_state = "danger01"
|
||||
else
|
||||
H.xenochimera_danger_display.icon_state = "danger00"
|
||||
|
||||
return
|
||||
|
||||
/obj/screen/xenochimera
|
||||
icon = 'icons/mob/chimerahud.dmi'
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/obj/screen/xenochimera/danger_level
|
||||
name = "danger level"
|
||||
icon_state = "danger00" //first number is bool of whether or not we're in danger, second is whether or not we're feral
|
||||
alpha = 200
|
||||
|
||||
/datum/species/sparkledog //Exists primarily as an april fools joke, along with everything tied to it!
|
||||
name = SPECIES_SPARKLE
|
||||
name_plural = "Sparklies"
|
||||
|
||||
@@ -1,89 +1,4 @@
|
||||
/mob/living/carbon/human/proc/reconstitute_form() //Scree's race ability.in exchange for: No cloning.
|
||||
set name = "Reconstitute Form"
|
||||
set category = "Abilities.General"
|
||||
|
||||
// Sanity is mostly handled in chimera_regenerate()
|
||||
if(stat == DEAD)
|
||||
var/confirm = tgui_alert(src, "Are you sure you want to regenerate your corpse? This process can take up to thirty minutes.", "Confirm Regeneration", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
chimera_regenerate()
|
||||
else if (quickcheckuninjured())
|
||||
var/confirm = tgui_alert(src, "Are you sure you want to regenerate? As you are uninjured this will only take 30 seconds and match your appearance to your character slot.", "Confirm Regeneration", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
chimera_regenerate()
|
||||
else
|
||||
var/confirm = tgui_alert(src, "Are you sure you want to completely reconstruct your form? This process can take up to fifteen minutes, depending on how hungry you are, and you will be unable to move.", "Confirm Regeneration", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
chimera_regenerate()
|
||||
|
||||
/mob/living/carbon/human/proc/chimera_regenerate()
|
||||
//If they're already regenerating
|
||||
switch(revive_ready)
|
||||
if(REVIVING_NOW)
|
||||
to_chat(src, "You are already reconstructing, just wait for the reconstruction to finish!")
|
||||
return
|
||||
if(REVIVING_DONE)
|
||||
to_chat(src, "Your reconstruction is done, but you need to hatch now.")
|
||||
return
|
||||
if(revive_ready > world.time)
|
||||
to_chat(src, "You can't use that ability again so soon!")
|
||||
return
|
||||
|
||||
var/time = min(900, (120+780/(1 + nutrition/100))) //capped at 15 mins, roughly 6 minutes at 250 (yellow) nutrition, 4.1 minutes at 500 (grey), cannot be below 2 mins
|
||||
if (quickcheckuninjured()) //if you're completely uninjured, then you get a speedymode - check health first for quickness
|
||||
time = 30
|
||||
|
||||
//Clicked regen while dead.
|
||||
if(stat == DEAD)
|
||||
|
||||
//reviving from dead takes extra nutriment to be provided from outside OR takes twice as long and consumes extra at the end
|
||||
if(!hasnutriment())
|
||||
time = time*2
|
||||
|
||||
to_chat(src, "You begin to reconstruct your form. You will not be able to move during this time. It should take aproximately [round(time)] seconds.")
|
||||
|
||||
//Scary spawnerization.
|
||||
revive_ready = REVIVING_NOW
|
||||
revive_finished = (world.time + time SECONDS) // When do we finish reviving? Allows us to find out when we're done, called by the alert currently.
|
||||
throw_alert("regen", /obj/screen/alert/xenochimera/reconstitution)
|
||||
spawn(time SECONDS)
|
||||
// check to see if they've been fixed by outside forces in the meantime such as defibbing
|
||||
if(stat != DEAD)
|
||||
to_chat(src, span_notice("Your body has recovered from its ordeal, ready to regenerate itself again."))
|
||||
revive_ready = REVIVING_READY //reset their cooldown
|
||||
clear_alert("regen")
|
||||
throw_alert("hatch", /obj/screen/alert/xenochimera/readytohatch)
|
||||
|
||||
// Was dead, still dead.
|
||||
else
|
||||
to_chat(src, span_notice("Consciousness begins to stir as your new body awakens, ready to hatch."))
|
||||
add_verb(src, /mob/living/carbon/human/proc/hatch)
|
||||
revive_ready = REVIVING_DONE
|
||||
src << sound('sound/effects/mob_effects/xenochimera/hatch_notification.ogg',0,0,0,30)
|
||||
clear_alert("regen")
|
||||
throw_alert("hatch", /obj/screen/alert/xenochimera/readytohatch)
|
||||
|
||||
|
||||
//Clicked regen while NOT dead
|
||||
else
|
||||
to_chat(src, "You begin to reconstruct your form. You will not be able to move during this time. It should take aproximately [round(time)] seconds.")
|
||||
|
||||
//Waiting for regen after being alive
|
||||
revive_ready = REVIVING_NOW
|
||||
revive_finished = (world.time + time SECONDS) // When do we finish reviving? Allows us to find out when we're done, called by the alert currently.
|
||||
throw_alert("regen", /obj/screen/alert/xenochimera/reconstitution)
|
||||
spawn(time SECONDS)
|
||||
|
||||
//Slightly different flavour messages
|
||||
if(stat != DEAD || hasnutriment())
|
||||
to_chat(src, span_notice("Consciousness begins to stir as your new body awakens, ready to hatch.."))
|
||||
else
|
||||
to_chat(src, span_warning("Consciousness begins to stir as your battered body struggles to recover from its ordeal.."))
|
||||
add_verb(src, /mob/living/carbon/human/proc/hatch)
|
||||
revive_ready = REVIVING_DONE
|
||||
src << sound('sound/effects/mob_effects/xenochimera/hatch_notification.ogg',0,0,0,30)
|
||||
clear_alert("regen")
|
||||
throw_alert("hatch", /obj/screen/alert/xenochimera/readytohatch)
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/hasnutriment()
|
||||
@@ -104,287 +19,12 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/human/proc/hatch()
|
||||
set name = "Hatch"
|
||||
set category = "Abilities.General"
|
||||
|
||||
if(revive_ready != REVIVING_DONE)
|
||||
//Hwhat?
|
||||
remove_verb(src, /mob/living/carbon/human/proc/hatch)
|
||||
return
|
||||
|
||||
var/confirm = tgui_alert(src, "Are you sure you want to hatch right now? This will be very obvious to anyone in view.", "Confirm Regeneration", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
|
||||
//Dead when hatching
|
||||
if(stat == DEAD)
|
||||
// var/sickness_duration = 10 MINUTES //CHOMPedit
|
||||
//Reviving from ded takes extra nutrition - if it isn't provided from outside sources, it comes from you
|
||||
if(!hasnutriment())
|
||||
nutrition=nutrition * 0.75
|
||||
// sickness_duration = 20 MINUTES //CHOMPedit
|
||||
chimera_hatch()
|
||||
// add_modifier(/datum/modifier/resleeving_sickness/chimera, sickness_duration) //CHOMPedit
|
||||
adjustBrainLoss(5) // if they're reviving from dead, they come back with 5 brainloss on top of whatever's unhealed.
|
||||
visible_message(span_warning("<p>" + span_huge("The former corpse staggers to its feet, all its former wounds having vanished...") + "</p>")) //Bloody hell...
|
||||
clear_alert("hatch")
|
||||
return
|
||||
|
||||
//Alive when hatching
|
||||
else
|
||||
chimera_hatch()
|
||||
|
||||
visible_message(span_warning("<p>" + span_huge("[src] rises to \his feet.") + "</p>")) //Bloody hell...
|
||||
clear_alert("hatch")
|
||||
|
||||
/mob/living/carbon/human/proc/chimera_hatch()
|
||||
remove_verb(src, /mob/living/carbon/human/proc/hatch)
|
||||
to_chat(src, span_notice("Your new body awakens, bursting free from your old skin."))
|
||||
//Modify and record values (half nutrition and braindamage)
|
||||
var/old_nutrition = nutrition
|
||||
var/braindamage = min(5, max(0, (brainloss-1) * 0.5)) //brainloss is tricky to heal and might take a couple of goes to get rid of completely.
|
||||
var/uninjured=quickcheckuninjured()
|
||||
//I did have special snowflake code, but this is easier.
|
||||
revive()
|
||||
mutations.Remove(HUSK)
|
||||
setBrainLoss(braindamage)
|
||||
species.update_vore_belly_def_variant()
|
||||
|
||||
if(!uninjured)
|
||||
nutrition = old_nutrition * 0.5
|
||||
//Drop everything
|
||||
for(var/obj/item/W in src)
|
||||
drop_from_inventory(W)
|
||||
//Visual effects
|
||||
var/T = get_turf(src)
|
||||
var/blood_color = species.blood_color
|
||||
var/flesh_color = species.flesh_color
|
||||
new /obj/effect/gibspawner/human/xenochimera(T, null, flesh_color, blood_color)
|
||||
visible_message(span_danger("<p>" + span_huge("The lifeless husk of [src] bursts open, revealing a new, intact copy in the pool of viscera.") + "</p>")) //Bloody hell...
|
||||
playsound(T, 'sound/effects/mob_effects/xenochimera/hatch.ogg', 50)
|
||||
else //lower cost for doing a quick cosmetic revive
|
||||
nutrition = old_nutrition * 0.9
|
||||
|
||||
//Unfreeze some things
|
||||
does_not_breathe = FALSE
|
||||
update_canmove()
|
||||
stunned = 2 // CHOMPEdit - Whoops, crawling is a thing now.
|
||||
|
||||
revive_ready = world.time + 10 MINUTES //set the cooldown, Reduced this to 10 minutes, you're playing with fire if you're reviving that often.
|
||||
|
||||
/datum/modifier/resleeving_sickness/chimera //near identical to the regular version, just with different flavortexts
|
||||
name = "imperfect regeneration"
|
||||
desc = "You feel rather weak and unfocused, having just regrown your body not so long ago."
|
||||
|
||||
on_created_text = span_warning(span_large("You feel weak and unsteady, that regeneration having been rougher than most."))
|
||||
on_expired_text = span_notice(span_large("You feel your strength and focus return to you."))
|
||||
|
||||
/mob/living/carbon/human/proc/revivingreset() // keep this as a debug proc or potential future use
|
||||
revive_ready = REVIVING_READY
|
||||
|
||||
/obj/effect/gibspawner/human/xenochimera
|
||||
fleshcolor = "#14AD8B"
|
||||
bloodcolor = "#14AD8B"
|
||||
|
||||
/mob/living/carbon/human/proc/getlightlevel() //easier than having the same code in like three places
|
||||
if(isturf(src.loc)) //else, there's considered to be no light
|
||||
var/turf/T = src.loc
|
||||
return T.get_lumcount() * 5
|
||||
else return 0
|
||||
|
||||
/mob/living/carbon/human/proc/handle_feral()
|
||||
if(handling_hal) return
|
||||
handling_hal = 1
|
||||
|
||||
if(client && feral >= 10) // largely a copy of handle_hallucinations() without the fake attackers. Unlike hallucinations, only fires once - if they're still feral they'll get hit again anyway.
|
||||
spawn(rand(200,500)/(feral/10))
|
||||
if(!feral) return //just to avoid fuckery in the event that they un-feral in the time it takes for the spawn to proc
|
||||
var/halpick = rand(1,100)
|
||||
switch(halpick)
|
||||
if(0 to 15) //15% chance
|
||||
//Screwy HUD
|
||||
//to_chat(src, "Screwy HUD")
|
||||
hal_screwyhud = pick(1,2,3,3,4,4)
|
||||
spawn(rand(100,250))
|
||||
hal_screwyhud = 0
|
||||
if(16 to 25) //10% chance
|
||||
//Strange items
|
||||
//to_chat(src, "Traitor Items")
|
||||
if(!halitem)
|
||||
halitem = new
|
||||
var/list/slots_free = list(ui_lhand,ui_rhand)
|
||||
if(l_hand) slots_free -= ui_lhand
|
||||
if(r_hand) slots_free -= ui_rhand
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
if(!H.belt) slots_free += ui_belt
|
||||
if(!H.l_store) slots_free += ui_storage1
|
||||
if(!H.r_store) slots_free += ui_storage2
|
||||
if(slots_free.len)
|
||||
halitem.screen_loc = pick(slots_free)
|
||||
halitem.layer = 50
|
||||
switch(rand(1,6))
|
||||
if(1) //revolver
|
||||
halitem.icon = 'icons/obj/gun.dmi'
|
||||
halitem.icon_state = "revolver"
|
||||
halitem.name = "Revolver"
|
||||
if(2) //c4
|
||||
halitem.icon = 'icons/obj/assemblies.dmi'
|
||||
halitem.icon_state = "plastic-explosive0"
|
||||
halitem.name = "Mysterious Package"
|
||||
if(prob(25))
|
||||
halitem.icon_state = "c4small_1"
|
||||
if(3) //sword
|
||||
halitem.icon = 'icons/obj/weapons.dmi'
|
||||
halitem.icon_state = "sword1"
|
||||
halitem.name = "Sword"
|
||||
if(4) //stun baton
|
||||
halitem.icon = 'icons/obj/weapons.dmi'
|
||||
halitem.icon_state = "stunbaton"
|
||||
halitem.name = "Stun Baton"
|
||||
if(5) //emag
|
||||
halitem.icon = 'icons/obj/card.dmi'
|
||||
halitem.icon_state = "emag"
|
||||
halitem.name = "Cryptographic Sequencer"
|
||||
if(6) //flashbang
|
||||
halitem.icon = 'icons/obj/grenade.dmi'
|
||||
halitem.icon_state = "flashbang1"
|
||||
halitem.name = "Flashbang"
|
||||
if(client) client.screen += halitem
|
||||
spawn(rand(100,250))
|
||||
if(client)
|
||||
client.screen -= halitem
|
||||
halitem = null
|
||||
if(26 to 35) //10% chance
|
||||
//Flashes of danger
|
||||
//to_chat(src, "Danger Flash")
|
||||
if(!halimage)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(src,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
|
||||
switch(rand(1,3))
|
||||
if(1)
|
||||
//to_chat(src, "Space")
|
||||
halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
|
||||
if(2)
|
||||
//to_chat(src, "Fire")
|
||||
halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER)
|
||||
if(3)
|
||||
//to_chat(src, "C4")
|
||||
halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)
|
||||
|
||||
|
||||
if(client) client.images += halimage
|
||||
spawn(rand(10,50)) //Only seen for a brief moment.
|
||||
if(client) client.images -= halimage
|
||||
halimage = null
|
||||
|
||||
if(36 to 55) //20% chance
|
||||
//Strange audio
|
||||
//to_chat(src, "Strange Audio")
|
||||
switch(rand(1,12))
|
||||
if(1) src << 'sound/machines/door/old_airlock.ogg'
|
||||
if(2)
|
||||
if(prob(50))src << 'sound/effects/Explosion1.ogg'
|
||||
else src << 'sound/effects/Explosion2.ogg'
|
||||
if(3) src << 'sound/effects/explosionfar.ogg'
|
||||
if(4) src << 'sound/effects/Glassbr1.ogg'
|
||||
if(5) src << 'sound/effects/Glassbr2.ogg'
|
||||
if(6) src << 'sound/effects/Glassbr3.ogg'
|
||||
if(7) src << 'sound/machines/twobeep.ogg'
|
||||
if(8) src << 'sound/machines/door/windowdoor.ogg'
|
||||
if(9)
|
||||
//To make it more realistic, I added two gunshots (enough to kill)
|
||||
src << 'sound/weapons/Gunshot1.ogg'
|
||||
spawn(rand(10,30))
|
||||
src << 'sound/weapons/Gunshot2.ogg'
|
||||
if(10) src << 'sound/weapons/smash.ogg'
|
||||
if(11)
|
||||
//Same as above, but with tasers.
|
||||
src << 'sound/weapons/Taser.ogg'
|
||||
spawn(rand(10,30))
|
||||
src << 'sound/weapons/Taser.ogg'
|
||||
//Rare audio
|
||||
if(12)
|
||||
//These sounds are (mostly) taken from Hidden: Source
|
||||
var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/Heart Beat.ogg', 'sound/effects/screech.ogg',\
|
||||
'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\
|
||||
'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\
|
||||
'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\
|
||||
'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg')
|
||||
src << pick(creepyasssounds)
|
||||
if(56 to 60) //5% chance
|
||||
//Flashes of danger
|
||||
//to_chat(src, "Danger Flash")
|
||||
if(!halbody)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(src,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
switch(rand(1,4))
|
||||
if(1)
|
||||
halbody = image('icons/mob/human.dmi',target,"husk_l",TURF_LAYER)
|
||||
if(2,3)
|
||||
halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
|
||||
if(4)
|
||||
halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER)
|
||||
// if(5)
|
||||
// halbody = image('xcomalien.dmi',target,"chryssalid",TURF_LAYER)
|
||||
|
||||
if(client) client.images += halbody
|
||||
spawn(rand(50,80)) //Only seen for a brief moment.
|
||||
if(client) client.images -= halbody
|
||||
halbody = null
|
||||
if(61 to 85) //25% chance
|
||||
//food
|
||||
if(!halbody)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(src,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
switch(rand(1,10))
|
||||
if(1)
|
||||
halbody = image('icons/mob/animal.dmi',target,"cow",TURF_LAYER)
|
||||
if(2)
|
||||
halbody = image('icons/mob/animal.dmi',target,"chicken",TURF_LAYER)
|
||||
if(3)
|
||||
halbody = image('icons/obj/food.dmi',target,"bigbiteburger",TURF_LAYER)
|
||||
if(4)
|
||||
halbody = image('icons/obj/food.dmi',target,"meatbreadslice",TURF_LAYER)
|
||||
if(5)
|
||||
halbody = image('icons/obj/food.dmi',target,"sausage",TURF_LAYER)
|
||||
if(6)
|
||||
halbody = image('icons/obj/food.dmi',target,"bearmeat",TURF_LAYER)
|
||||
if(7)
|
||||
halbody = image('icons/obj/food.dmi',target,"fishfillet",TURF_LAYER)
|
||||
if(8)
|
||||
halbody = image('icons/obj/food.dmi',target,"meat",TURF_LAYER)
|
||||
if(9)
|
||||
halbody = image('icons/obj/food.dmi',target,"meatstake",TURF_LAYER)
|
||||
if(10)
|
||||
halbody = image('icons/obj/food.dmi',target,"monkeysdelight",TURF_LAYER)
|
||||
|
||||
if(client) client.images += halbody
|
||||
spawn(rand(50,80)) //Only seen for a brief moment.
|
||||
if(client) client.images -= halbody
|
||||
halbody = null
|
||||
if(86 to 100) //15% chance
|
||||
//hear voices. Could make the voice pick from nearby creatures, but nearby creatures make feral hallucinations rare so don't bother.
|
||||
var/list/hiddenspeakers = list("Someone distant", "A voice nearby","A familiar voice", "An echoing voice", "A cautious voice", "A scared voice", "Someone around the corner", "Someone", "Something", "Something scary", "An urgent voice", "An angry voice")
|
||||
var/list/speakerverbs = list("calls out", "yells", "screams", "exclaims", "shrieks", "shouts", "hisses", "snarls")
|
||||
var/list/spookyphrases = list("It's over here!","Stop it!", "Hunt it down!", "Get it!", "Quick, over here!", "Anyone there?", "Who's there?", "Catch that thing!", "Stop it! Kill it!", "Anyone there?", "Where is it?", "Find it!", "There it is!")
|
||||
to_chat(src, span_game(span_say(span_name(pick(hiddenspeakers)) + " [pick(speakerverbs)], \"[pick(spookyphrases)]\"")))
|
||||
|
||||
|
||||
handling_hal = 0
|
||||
return
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/bloodsuck()
|
||||
set name = "Partially Drain prey of blood"
|
||||
set desc = "Bites prey and drains them of a significant portion of blood, feeding you in the process. You may only do this once per minute."
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
if(shift_denial)
|
||||
name = shift_denial
|
||||
else
|
||||
name = my_kin.energy >= cost ? "Activate" : "No Energy"
|
||||
name = my_kin.comp.dark_energy >= cost ? "Activate" : "No Energy"
|
||||
return src
|
||||
|
||||
/obj/effect/shadekin_ability/Click(var/location, var/control, var/params)
|
||||
@@ -58,11 +58,11 @@
|
||||
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
to_chat(my_kin,span_warning("Can only use that ability while phase shifted!"))
|
||||
return FALSE
|
||||
else if(my_kin.energy < cost)
|
||||
else if(my_kin.comp.dark_energy < cost)
|
||||
to_chat(my_kin,span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
|
||||
my_kin.energy -= cost
|
||||
my_kin.comp.dark_energy -= cost
|
||||
if(ab_sound)
|
||||
playsound(src,ab_sound,75,1)
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
if(!..())
|
||||
return
|
||||
if(!my_kin.mend_other())
|
||||
my_kin.energy += cost //Refund due to abort
|
||||
my_kin.comp.dark_energy += cost //Refund due to abort
|
||||
/*
|
||||
/datum/modifier/shadekin/heal_boop
|
||||
name = "Shadekin Regen"
|
||||
@@ -188,9 +188,9 @@
|
||||
if(!..())
|
||||
return
|
||||
if(!my_kin.dark_tunneling())
|
||||
my_kin.energy += cost //Refund due to abort
|
||||
my_kin.comp.dark_energy += cost //Refund due to abort
|
||||
else
|
||||
my_kin.energy += 10 //Refund enough to open the dark portal
|
||||
my_kin.comp.dark_energy += 10 //Refund enough to open the dark portal
|
||||
//CHOMPEdit End
|
||||
|
||||
//CHOMPEdit start - Add Dark Maw ability
|
||||
@@ -205,5 +205,5 @@
|
||||
if(!..())
|
||||
return
|
||||
if(!my_kin.dark_maw())
|
||||
my_kin.energy += cost //Refund due to abort
|
||||
my_kin.comp.dark_energy += cost //Refund due to abort
|
||||
//CHOMPEdit End
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
if(shift_denial)
|
||||
name = shift_denial
|
||||
else
|
||||
name = my_kin.energy >= cost ? "Activate" : "No Energy"
|
||||
name = my_kin.comp.dark_energy >= cost ? "Activate" : "No Energy"
|
||||
return src
|
||||
|
||||
/obj/effect/rakshasa_ability/Click(var/location, var/control, var/params)
|
||||
@@ -67,11 +67,11 @@
|
||||
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED))
|
||||
to_chat(my_kin,span_warning("Can only use that ability while phase shifted!"))
|
||||
return FALSE
|
||||
else if(my_kin.energy < cost)
|
||||
else if(my_kin.comp.dark_energy < cost)
|
||||
to_chat(my_kin,span_warning("Not enough energy for that ability!"))
|
||||
return FALSE
|
||||
|
||||
my_kin.energy -= cost
|
||||
my_kin.comp.dark_energy -= cost
|
||||
if(ab_sound)
|
||||
playsound(src,ab_sound,75,1)
|
||||
|
||||
|
||||
@@ -68,8 +68,7 @@
|
||||
var/image/tailimage //Cached tail image
|
||||
|
||||
//Darknesssss
|
||||
var/energy = 100 //For abilities
|
||||
var/energy_adminbuse = FALSE //For adminbuse infinite energy
|
||||
var/datum/component/shadekin/comp = /datum/component/shadekin //Component that holds all the shadekin vars.
|
||||
var/dark_gains = 0 //Last tick's change in energy
|
||||
var/ability_flags = 0 //Flags for active abilities
|
||||
var/obj/screen/darkhud //Holder to update this icon
|
||||
@@ -100,6 +99,7 @@
|
||||
new new_type(loc)
|
||||
flags |= ATOM_INITIALIZED
|
||||
return INITIALIZE_HINT_QDEL
|
||||
comp = LoadComponent(comp)
|
||||
|
||||
if(icon_state == "map_example")
|
||||
icon_state = pick("white","dark","brown")
|
||||
@@ -208,9 +208,9 @@
|
||||
density = FALSE
|
||||
|
||||
//Convert spare nutrition into energy at a certain ratio
|
||||
if(. && nutrition > initial(nutrition) && energy < 100 && !(ability_flags | AB_DARK_RESPITE)) //CHOMPEdit - Dark Respite
|
||||
if(. && nutrition > initial(nutrition) && comp.dark_energy < 100 && !(ability_flags | AB_DARK_RESPITE)) //CHOMPEdit - Dark Respite
|
||||
nutrition = max(0, nutrition-5)
|
||||
energy = min(100,energy+1)
|
||||
comp.dark_energy = min(100,comp.dark_energy+1)
|
||||
if(!client && check_for_observer && check_timer++ > 5)
|
||||
check_timer = 0
|
||||
var/non_kin_count = 0
|
||||
@@ -282,7 +282,7 @@
|
||||
drop_l_hand()
|
||||
drop_r_hand()
|
||||
|
||||
energy = 0
|
||||
comp.dark_energy = 0
|
||||
ability_flags |= AB_DARK_RESPITE
|
||||
invisibility = INVISIBILITY_LEVEL_TWO
|
||||
|
||||
@@ -400,14 +400,14 @@
|
||||
if(darkness >= 0.65)
|
||||
dark_gains = 0.30
|
||||
|
||||
energy = max(0,min(initial(energy),energy + dark_gains))
|
||||
comp.dark_energy = max(0,min(initial(comp.dark_energy),comp.dark_energy + dark_gains))
|
||||
|
||||
if(energy_adminbuse)
|
||||
energy = 100
|
||||
//CHOMPEdit Begin - Dark Respite
|
||||
if(ability_flags & AB_DARK_RESPITE)
|
||||
energy = 0
|
||||
comp.dark_energy = 0
|
||||
//CHOMPEdit End
|
||||
if(comp.dark_energy_infinite)
|
||||
comp.dark_energy = 100
|
||||
|
||||
//Update turf darkness hud
|
||||
if(darkhud)
|
||||
@@ -425,7 +425,7 @@
|
||||
|
||||
//Update energy storage hud
|
||||
if(energyhud)
|
||||
switch(energy)
|
||||
switch(comp.dark_energy)
|
||||
if(80 to INFINITY)
|
||||
energyhud.icon_state = "energy0"
|
||||
if(60 to 80)
|
||||
@@ -517,7 +517,7 @@
|
||||
if(ORANGE_EYES)
|
||||
gains = 5
|
||||
|
||||
energy += gains
|
||||
comp.dark_energy += gains
|
||||
|
||||
//Special hud elements for darkness and energy gains
|
||||
/mob/living/simple_mob/shadekin/extra_huds(var/datum/hud/hud,var/icon/ui_style,var/list/hud_elements)
|
||||
|
||||
@@ -57,12 +57,16 @@
|
||||
Your body feels hot, growing weaker, more tired. Draining. Darkness coming. \
|
||||
You struggle to stay awake while floating helplessly in the goo."
|
||||
player_msg = "You are Rakshasa. You are not to directly harm crew, only consume. You never speak a language."
|
||||
energy_adminbuse = TRUE
|
||||
maxHealth = 1000000000000
|
||||
health = 1000000000000
|
||||
eye_state = "BLUE EYES"
|
||||
eye_icon_state = "e_rakshasa"
|
||||
|
||||
/mob/living/simple_mob/shadekin/red/rakshasa/Initialize(mapload)
|
||||
. = ..()
|
||||
if(comp)
|
||||
comp.dark_energy_infinite = TRUE
|
||||
|
||||
/mob/living/simple_mob/shadekin/blue/luna
|
||||
name = "Luna"
|
||||
desc = "She appears to be a fuzzy critter of some sort. Her eyes shimmer a dark blue, glancing around curiously."
|
||||
|
||||
@@ -19,7 +19,6 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
|
||||
var/mob/living/carbon/brain/brainmob = null
|
||||
var/can_assist = TRUE
|
||||
var/defib_timer = -1
|
||||
var/laststress = 0
|
||||
|
||||
/obj/item/organ/internal/brain/process()
|
||||
..()
|
||||
|
||||
@@ -1,6 +1,2 @@
|
||||
/obj/item/organ/internal/brain/shadekin
|
||||
can_assist = FALSE
|
||||
|
||||
var/dark_energy = 100
|
||||
var/max_dark_energy = 100
|
||||
var/dark_energy_infinite = FALSE
|
||||
|
||||
@@ -142,17 +142,21 @@
|
||||
/decl/chemical_reaction/instant/xenolazarus/on_reaction(var/datum/reagents/holder, var/created_volume) //literally all this does is mash the regenerate button
|
||||
if(ishuman(holder.my_atom))
|
||||
var/mob/living/carbon/human/H = holder.my_atom
|
||||
if(H.stat == DEAD && (/mob/living/carbon/human/proc/reconstitute_form in H.verbs)) //no magical regen for non-regenners, and can't force the reaction on live ones
|
||||
if(H.hasnutriment()) // make sure it actually has the conditions to revive
|
||||
if(H.revive_ready >= 1) // if it's not reviving, start doing so
|
||||
H.revive_ready = REVIVING_READY // overrides the normal cooldown
|
||||
H.visible_message(span_info("[H] shudders briefly, then relaxes, faint movements stirring within."))
|
||||
H.chimera_regenerate()
|
||||
else if (/mob/living/carbon/human/proc/hatch in H.verbs)// already reviving, check if they're ready to hatch
|
||||
H.chimera_hatch()
|
||||
H.visible_message(span_danger(span_huge("[H] violently convulses and then bursts open, revealing a new, intact copy in the pool of viscera."))) // Hope you were wearing waterproofs, doc...
|
||||
H.adjustBrainLoss(10) // they're reviving from dead, so take 10 brainloss
|
||||
else //they're already reviving but haven't hatched. Give a little message to tell them to wait.
|
||||
H.visible_message(span_info("[H] stirs faintly, but doesn't appear to be ready to wake up yet."))
|
||||
else
|
||||
H.visible_message(span_info("[H] twitches for a moment, but remains still.")) // no nutriment
|
||||
var/datum/component/xenochimera/comp = H.GetComponent(/datum/component/xenochimera)
|
||||
if(!comp)
|
||||
return
|
||||
else
|
||||
if(H.stat == DEAD)
|
||||
if(H.hasnutriment()) // make sure it actually has the conditions to revive
|
||||
if(comp.revive_ready >= 1) // if it's not reviving, start doing so
|
||||
comp.revive_ready = REVIVING_READY // overrides the normal cooldown
|
||||
H.visible_message(span_info("[H] shudders briefly, then relaxes, faint movements stirring within."))
|
||||
H.chimera_regenerate()
|
||||
else if(comp.revive_ready == REVIVING_DONE)// already reviving, check if they're ready to hatch
|
||||
H.chimera_hatch()
|
||||
H.visible_message(span_danger(span_huge("[H] violently convulses and then bursts open, revealing a new, intact copy in the pool of viscera."))) // Hope you were wearing waterproofs, doc...
|
||||
H.adjustBrainLoss(10) // they're reviving from dead, so take 10 brainloss
|
||||
else //they're already reviving but haven't hatched. Give a little message to tell them to wait.
|
||||
H.visible_message(span_info("[H] stirs faintly, but doesn't appear to be ready to wake up yet."))
|
||||
else
|
||||
H.visible_message(span_info("[H] twitches for a moment, but remains still.")) // no nutriment
|
||||
|
||||
@@ -101,10 +101,11 @@
|
||||
M.adjust_nutrition(alt_nutriment_factor * removed)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.feral > 0 && H.nutrition > 150 && H.traumatic_shock < 20 && H.jitteriness < 100) //Same check as feral triggers to stop them immediately re-feralling
|
||||
H.feral -= removed * 3 // should calm them down quick, provided they're actually in a state to STAY calm.
|
||||
if (H.feral <=0) //check if they're unferalled
|
||||
H.feral = 0
|
||||
var/datum/component/xenochimera/xc = M.get_xenochimera_component()
|
||||
if(xc && xc.feral > 0 && H.nutrition > 150 && H.traumatic_shock < 20 && H.jitteriness < 100) //Same check as feral triggers to stop them immediately re-feralling
|
||||
xc.feral -= removed * 3 // should calm them down quick, provided they're actually in a state to STAY calm.
|
||||
if (xc.feral <=0) //check if they're unferalled
|
||||
xc.feral = 0
|
||||
to_chat(H, span_info("Your mind starts to clear, soothed into a state of clarity as your senses return."))
|
||||
log_and_message_admins("is no longer feral.", H)
|
||||
|
||||
@@ -466,10 +467,11 @@
|
||||
M.nutrition += (alt_nutriment_factor * removed)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.feral > 0 && H.nutrition > 100 && H.traumatic_shock < min(60, H.nutrition/10) && H.jitteriness < 100) // same check as feral triggers to stop them immediately re-feralling
|
||||
H.feral -= removed * 3 // should calm them down quick, provided they're actually in a state to STAY calm.
|
||||
if (H.feral <=0) //check if they're unferalled
|
||||
H.feral = 0
|
||||
var/datum/component/xenochimera/xc = M.get_xenochimera_component()
|
||||
if(xc && xc.feral > 0 && H.nutrition > 100 && H.traumatic_shock < min(60, H.nutrition/10) && H.jitteriness < 100) // same check as feral triggers to stop them immediately re-feralling
|
||||
xc.feral -= removed * 3 // should calm them down quick, provided they're actually in a state to STAY calm.
|
||||
if (xc.feral <=0) //check if they're unferalled
|
||||
xc.feral = 0
|
||||
to_chat(H, span_info("Your mind starts to clear, soothed into a state of clarity as your senses return."))
|
||||
log_and_message_admins("is no longer feral.", H)
|
||||
|
||||
@@ -555,10 +557,11 @@
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.feral > 0 && H.nutrition > 150 && H.traumatic_shock < 20 && H.jitteriness < 100) //Same check as feral triggers to stop them immediately re-feralling
|
||||
H.feral -= removed * 3 //Should calm them down quick, provided they're actually in a state to STAY calm.
|
||||
if(H.feral <=0) //Check if they're unferalled
|
||||
H.feral = 0
|
||||
var/datum/component/xenochimera/xc = M.get_xenochimera_component()
|
||||
if(xc && xc.feral > 0 && H.nutrition > 150 && H.traumatic_shock < 20 && H.jitteriness < 100) //Same check as feral triggers to stop them immediately re-feralling
|
||||
xc.feral -= removed * 3 //Should calm them down quick, provided they're actually in a state to STAY calm.
|
||||
if(xc.feral <=0) //Check if they're unferalled
|
||||
xc.feral = 0
|
||||
to_chat(H, span_info("Your mind starts to clear, soothed into a state of clarity as your senses return."))
|
||||
log_and_message_admins("is no longer feral.", H)
|
||||
|
||||
|
||||
@@ -7,10 +7,7 @@
|
||||
var/weight = 137 // Weight for mobs for weightgain system
|
||||
var/weight_gain = 1 // How fast you gain weight
|
||||
var/weight_loss = 0.5 // How fast you lose weight
|
||||
var/vore_egg_type = "egg" // Default egg type.
|
||||
var/feral = 0 // How feral the mob is, if at all. Does nothing for non xenochimera at the moment.
|
||||
var/revive_ready = REVIVING_READY // Only used for creatures that have the xenochimera regen ability, so far.
|
||||
var/revive_finished = 0 // Only used for xenochimera regen, allows us to find out when the regen will finish.
|
||||
var/vore_egg_type = "egg" // Default egg type. // Only used for creatures that have the xenochimera regen ability, so far.
|
||||
var/metabolism = 0.0015
|
||||
var/no_vore = FALSE // If the character/mob can vore.
|
||||
var/restrict_vore_ventcrawl = FALSE // Self explanatory
|
||||
@@ -25,13 +22,6 @@
|
||||
var/appendage_color = "#e03997" //Default pink. Used for the 'long_vore' trait.
|
||||
var/appendage_alt_setting = FALSE // Dictates if 'long_vore' user pulls prey to them or not. 1 = user thrown towards target.
|
||||
var/digestion_in_progress = FALSE // Gradual corpse gurgles
|
||||
var/regen_sounds = list(
|
||||
'sound/effects/mob_effects/xenochimera/regen_1.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_2.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_4.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_3.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_5.ogg'
|
||||
)
|
||||
var/trash_catching = FALSE //Toggle for trash throw vore
|
||||
var/list/trait_injection_reagents = list() //List of all the reagents allowed to be used for injection via venom bite
|
||||
var/trait_injection_selected = null //What trait reagent you're injecting.
|
||||
|
||||
@@ -46,15 +46,14 @@
|
||||
to_chat(L, span_danger("The more you move through this darkness, the more you can feel a throbbing, shooting ache in your bones."))
|
||||
if(prob(5))
|
||||
L.visible_message("[L]'s body gives off a faint, sparking, haze...", "Your body gives off a faint, sparking, haze...", runemessage = "gives off a faint, sparking haze")
|
||||
else if(istype(L.species, /datum/species/shadekin))
|
||||
var/obj/item/organ/internal/brain/shadekin/B = L.internal_organs_by_name["brain"]
|
||||
B.dark_energy += 10
|
||||
var/datum/component/shadekin/comp = L.GetComponent(/datum/component/shadekin)
|
||||
if(comp)
|
||||
comp.dark_energy += 10
|
||||
if(prob(10))
|
||||
to_chat(L, span_notice("You can feel the energy flowing into you!"))
|
||||
else
|
||||
if(prob(0.25))
|
||||
to_chat(L, span_danger("The darkness seethes under your feet..."))
|
||||
L.hallucination += 50
|
||||
else if(prob(0.25))
|
||||
to_chat(L, span_danger("The darkness seethes under your feet..."))
|
||||
L.hallucination += 50
|
||||
|
||||
/obj/effect/dark/proc/light_check()
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
var/datum/map_template/shelter/template
|
||||
|
||||
var/ability_cost = 100
|
||||
var/tunnel_time = 60 SECONDS
|
||||
|
||||
if(!shadekin_ability_check())
|
||||
return FALSE
|
||||
@@ -88,7 +89,7 @@
|
||||
smoke.start()
|
||||
|
||||
src.visible_message(span_notice("[src] begins pulling dark energies around themselves."))
|
||||
if(do_after(src, 600)) //60 seconds
|
||||
if(do_after(src, tunnel_time))
|
||||
playsound(src, 'sound/effects/phasein.ogg', 100, 1)
|
||||
src.visible_message(span_notice("[src] finishes pulling dark energies around themselves, creating a portal."))
|
||||
|
||||
|
||||
@@ -536,6 +536,8 @@
|
||||
#include "code\datums\components\crafting\recipes\primitive.dm"
|
||||
#include "code\datums\components\crafting\recipes\survival.dm"
|
||||
#include "code\datums\components\crafting\recipes\weapons.dm"
|
||||
#include "code\datums\components\species\shadekin.dm"
|
||||
#include "code\datums\components\species\xenochimera.dm"
|
||||
#include "code\datums\diseases\_disease.dm"
|
||||
#include "code\datums\diseases\_MobProcs.dm"
|
||||
#include "code\datums\diseases\anxiety.dm"
|
||||
|
||||
Reference in New Issue
Block a user