mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
[MIRROR] Cortical Borer Fixes (#12031)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
committed by
GitHub
parent
5290e9b81c
commit
3ead20716e
6
code/__defines/borer.dm
Normal file
6
code/__defines/borer.dm
Normal file
@@ -0,0 +1,6 @@
|
||||
#define BORER_MAX_CHEMS 80
|
||||
#define BORER_POWER_COST_TORTURE 5
|
||||
#define BORER_POWER_COST_SECRETE 25
|
||||
#define BORER_POWER_COST_REPRODUCE 50
|
||||
|
||||
#define BORER_PSYCHIC_SAY_MINIMUM_CHEMS 20
|
||||
@@ -410,6 +410,13 @@
|
||||
name = "chemical storage"
|
||||
icon_state = "power_display"
|
||||
|
||||
/atom/movable/screen/borer
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
/atom/movable/screen/borer/chems
|
||||
name = "chemical storage"
|
||||
icon_state = "power_display"
|
||||
|
||||
/atom/movable/screen/wizard
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ var/datum/antagonist/borer/borers
|
||||
role_type = BE_ALIEN
|
||||
role_text = "Cortical Borer"
|
||||
role_text_plural = "Cortical Borers"
|
||||
mob_path = /mob/living/simple_mob/animal/borer
|
||||
mob_path = /mob/living/simple_mob/animal/borer/roundstart // Use roundstart borer, or ghostcheck makes it take forever to enter mob when assigned
|
||||
bantype = "Borer"
|
||||
welcome_text = "Use your Infest power to crawl into the ear of a host and fuse with their brain. You can only take control temporarily, and at risk of hurting your host, so be clever and careful; your host is encouraged to help you however they can. Talk to your fellow borers with :x."
|
||||
antag_indicator = "brainworm"
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
M = new /mob/living/carbon/human(get_turf(source))
|
||||
M.real_name = source.real_name
|
||||
M.name = M.real_name
|
||||
if(!isnull(source.mind))
|
||||
source.mind.transfer_to(M)
|
||||
M.ckey = source.ckey
|
||||
add_antagonist(M.mind, 1, 0, 1) // Equip them and move them to spawn.
|
||||
return M
|
||||
|
||||
@@ -192,11 +192,12 @@
|
||||
|
||||
update_icon()
|
||||
|
||||
if(!M.has_brain_worms())
|
||||
update_use_power(USE_POWER_ACTIVE)
|
||||
enter_vr()
|
||||
else
|
||||
if(M.has_brain_worms())
|
||||
to_chat(user, span_warning("\The [src] rejects [M] with a sharp beep."))
|
||||
return
|
||||
|
||||
update_use_power(USE_POWER_ACTIVE)
|
||||
enter_vr()
|
||||
return
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/go_out()
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
dat += "<br>"
|
||||
// if (M.reagents && M.reagents.get_reagent_amount(REAGENT_ID_INAPROVALINE))
|
||||
// user.show_message(span_notice("Bloodstream Analysis located [M.reagents:get_reagent_amount(REAGENT_ID_INAPROVALINE)] units of rejuvenation chemicals."))
|
||||
if (M.has_brain_worms())
|
||||
if (advscan >= 2 && M.has_brain_worms()) // Borers need to hide
|
||||
dat += span_warning("Subject suffering from aberrant brain activity. Recommend further scanning.")
|
||||
dat += "<br>"
|
||||
else if (M.getBrainLoss() >= 60 || !M.has_brain())
|
||||
|
||||
@@ -19,11 +19,14 @@
|
||||
/obj/item/motiontracker/Initialize(mapload)
|
||||
RegisterSignal(SSmotiontracker, COMSIG_MOVABLE_MOTIONTRACKER, PROC_REF(handle_motion_tracking))
|
||||
. = ..()
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.motiontracker_subscribe()
|
||||
|
||||
/obj/item/motiontracker/Destroy(force, ...)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.motiontracker_subscribe()
|
||||
M.motiontracker_unsubscribe()
|
||||
UnregisterSignal(SSmotiontracker, COMSIG_MOVABLE_MOTIONTRACKER)
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -71,6 +71,11 @@
|
||||
|
||||
if(stat == DEAD)
|
||||
return 0
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/has_worm = has_brain_worms()
|
||||
if(has_worm) // This is our host's problem to deal with
|
||||
has_worm.detatch()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_DEATH, src, gibbed)
|
||||
|
||||
|
||||
@@ -1,66 +1,3 @@
|
||||
//Brain slug proc for voluntary removal of control.
|
||||
/mob/living/carbon/proc/release_control()
|
||||
|
||||
set category = "Abilities.Brainslug"
|
||||
set name = "Release Control"
|
||||
set desc = "Release control of your host's body."
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
|
||||
|
||||
if(B && B.host_brain)
|
||||
to_chat(src, span_danger("You withdraw your probosci, releasing control of [B.host_brain]"))
|
||||
|
||||
B.detatch()
|
||||
|
||||
remove_verb(src, /mob/living/carbon/proc/release_control)
|
||||
remove_verb(src, /mob/living/carbon/proc/punish_host)
|
||||
remove_verb(src, /mob/living/carbon/proc/spawn_larvae)
|
||||
|
||||
else
|
||||
to_chat(src, span_danger("ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !"))
|
||||
|
||||
//Brain slug proc for tormenting the host.
|
||||
/mob/living/carbon/proc/punish_host()
|
||||
set category = "Abilities.Brainslug"
|
||||
set name = "Torment host"
|
||||
set desc = "Punish your host with agony."
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
|
||||
|
||||
if(!B)
|
||||
return
|
||||
|
||||
if(B.host_brain.ckey)
|
||||
to_chat(src, span_danger("You send a punishing spike of psychic agony lancing into your host's brain."))
|
||||
if (!can_feel_pain())
|
||||
to_chat(B.host_brain, span_warning("You feel a strange sensation as a foreign influence prods your mind."))
|
||||
to_chat(src, span_danger("It doesn't seem to be as effective as you hoped."))
|
||||
else
|
||||
to_chat(B.host_brain, span_danger(span_large("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")))
|
||||
|
||||
/mob/living/carbon/proc/spawn_larvae()
|
||||
set category = "Abilities.Brainslug"
|
||||
set name = "Reproduce"
|
||||
set desc = "Spawn several young."
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
|
||||
|
||||
if(!B)
|
||||
return
|
||||
|
||||
if(B.chemicals >= 100)
|
||||
to_chat(src, span_danger("Your host twitches and quivers as you rapidly excrete a larva from your sluglike body."))
|
||||
visible_message(span_danger("\The [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!"))
|
||||
B.chemicals -= 100
|
||||
B.has_reproduced = 1
|
||||
|
||||
vomit(1)
|
||||
new /mob/living/simple_mob/animal/borer(get_turf(src))
|
||||
|
||||
else
|
||||
to_chat(src, span_warning("You do not have enough chemicals stored to reproduce."))
|
||||
return
|
||||
|
||||
/mob/living/proc/toggle_active_cloaking() // Borrowed from Rogue Star, thanks guys!
|
||||
set category = "Abilities.General"
|
||||
set name = "Toggle Active Cloaking"
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
status_flags = CANPUSH
|
||||
pass_flags = PASSTABLE
|
||||
movement_cooldown = 1.5
|
||||
mob_size = MOB_TINY // no landmines for you
|
||||
|
||||
universal_understand = TRUE
|
||||
can_be_antagged = TRUE
|
||||
@@ -35,16 +36,37 @@
|
||||
var/antag = TRUE // If false, will avoid setting up objectives and events
|
||||
|
||||
var/chemicals = 10 // A resource used for reproduction and powers.
|
||||
var/max_chemicals = 250 // Max of said resource.
|
||||
var/true_name = null // String used when speaking among other worms.
|
||||
var/controlling = FALSE // Used in human death ceck.
|
||||
var/docile = FALSE // Sugar can stop borers from acting.
|
||||
var/docile_counter = 0 // How long we are docile for
|
||||
|
||||
var/has_reproduced = FALSE
|
||||
var/used_dominate // world.time when the dominate power was last used.
|
||||
var/datum/ghost_query/Q // Used to unregister our signal
|
||||
|
||||
can_be_drop_prey = FALSE
|
||||
vent_crawl_time = 30 // faster vent crawler
|
||||
|
||||
var/static/borer_chem_list = list(
|
||||
// Antag utlity
|
||||
"Repair Brain Tissue" = list(REAGENT_ID_ALKYSINE, 5),
|
||||
"Repair Brute" = list(REAGENT_ID_BICARIDINE, 10),
|
||||
"Repair Burn" = list(REAGENT_ID_KELOTANE, 10),
|
||||
"Enhance Speed" = list(REAGENT_ID_HYPERZINE, 10),
|
||||
// Stablization
|
||||
"Stablize Mind" = list(REAGENT_ID_CITALOPRAM, 10),
|
||||
"Stablize Nerves" = list(REAGENT_ID_ADRANOL, 10),
|
||||
"Stablize Bleeding" = list(REAGENT_ID_INAPROVALINE, 5),
|
||||
"Stablize Infection" = list(REAGENT_ID_SPACEACILLIN, 15),
|
||||
"Stablize Pain" = list(REAGENT_ID_TRAMADOL, 5),
|
||||
// Scene tools
|
||||
"Make Drunk" = list(REAGENT_ID_ETHANOL, 5),
|
||||
"Cure Drunk" = list(REAGENT_ID_ETHYLREDOXRAZINE, 10),
|
||||
"Euphoric High" = list(REAGENT_ID_BLISS, 5),
|
||||
"Mood Stimulant" = list(REAGENT_ID_APHRODISIAC, 5),
|
||||
// Borer last resport
|
||||
"Revive Dead Host" = null
|
||||
)
|
||||
|
||||
/mob/living/simple_mob/animal/borer/roundstart
|
||||
roundstart = TRUE
|
||||
@@ -53,18 +75,19 @@
|
||||
antag = FALSE
|
||||
|
||||
/mob/living/simple_mob/animal/borer/Login()
|
||||
..()
|
||||
. = ..()
|
||||
if(antag && mind)
|
||||
borers.add_antagonist(mind)
|
||||
|
||||
/mob/living/simple_mob/animal/borer/Initialize(mapload)
|
||||
add_language("Cortical Link")
|
||||
|
||||
add_verb(src, /mob/living/proc/ventcrawl)
|
||||
add_verb(src, /mob/living/proc/hide)
|
||||
motiontracker_subscribe()
|
||||
|
||||
true_name = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]"
|
||||
..()
|
||||
|
||||
. = ..()
|
||||
|
||||
if(!roundstart && antag)
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
@@ -72,52 +95,145 @@
|
||||
/mob/living/simple_mob/animal/borer/LateInitialize()
|
||||
request_player()
|
||||
|
||||
/mob/living/simple_mob/animal/borer/Destroy()
|
||||
. = ..()
|
||||
motiontracker_unsubscribe()
|
||||
QDEL_NULL(ghost_check)
|
||||
if(host)
|
||||
detatch()
|
||||
leave_host()
|
||||
|
||||
/mob/living/simple_mob/animal/borer/handle_special()
|
||||
if(host && !stat && !host.stat)
|
||||
// Handle docility.
|
||||
if(host.reagents.has_reagent(REAGENT_ID_SUGAR) && !docile)
|
||||
var/message = "You feel the soporific flow of sugar in your host's blood, lulling you into docility."
|
||||
var/target = controlling ? host : src
|
||||
to_chat(target, span_warning(message))
|
||||
docile = TRUE
|
||||
|
||||
else if(docile)
|
||||
var/message = "You shake off your lethargy as the sugar leaves your host's blood."
|
||||
var/target = controlling ? host : src
|
||||
to_chat(target, span_notice(message))
|
||||
docile = FALSE
|
||||
|
||||
// Chem regen.
|
||||
if(chemicals < max_chemicals)
|
||||
chemicals++
|
||||
|
||||
// Control stuff.
|
||||
if(controlling)
|
||||
if(docile)
|
||||
to_chat(host, span_warning("You are feeling far too docile to continue controlling your host..."))
|
||||
host.release_control()
|
||||
return
|
||||
|
||||
if(prob(5))
|
||||
host.adjustBrainLoss(0.1)
|
||||
|
||||
if(prob(host.brainloss/20))
|
||||
host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_v","gasp"))]")
|
||||
handle_chemicals()
|
||||
handle_docile()
|
||||
handle_braindamage()
|
||||
|
||||
/mob/living/simple_mob/animal/borer/get_status_tab_items()
|
||||
. = ..()
|
||||
. += "Chemicals: [chemicals]"
|
||||
. += "Chemicals: [FLOOR(chemicals,1)]"
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/handle_chemicals()
|
||||
if(stat == DEAD || !host || host.stat == DEAD)
|
||||
return
|
||||
if(chemicals >= BORER_MAX_CHEMS || docile)
|
||||
return
|
||||
|
||||
var/chem_before = chemicals
|
||||
if(controlling)
|
||||
chemicals += 0.25
|
||||
else
|
||||
chemicals += 0.1
|
||||
var/new_chem = FLOOR(chemicals/10,1)
|
||||
if(new_chem > FLOOR(chem_before/10,1))
|
||||
to_chat(host, span_alien("Your chemicals have increased to [new_chem * 10]"))
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/handle_docile()
|
||||
if(stat == DEAD)
|
||||
docile_counter = 0
|
||||
return
|
||||
|
||||
// Start docile
|
||||
if(host && (host.reagents.has_reagent(REAGENT_ID_SUGAR) || host.ingested.has_reagent(REAGENT_ID_SUGAR)))
|
||||
docile_counter = 5 SECONDS
|
||||
if(!docile)
|
||||
var/message = "You feel the soporific flow of sugar in your host's blood, lulling you into docility."
|
||||
var/target = controlling ? host : src
|
||||
to_chat(target, span_danger( message))
|
||||
docile = TRUE
|
||||
|
||||
// Drop control if docile
|
||||
if(controlling && docile)
|
||||
to_chat(host, span_vdanger("You are feeling far too docile to continue controlling your host..."))
|
||||
host.release_control()
|
||||
return
|
||||
|
||||
// wear it off
|
||||
docile_counter--
|
||||
if(docile_counter > 0)
|
||||
return
|
||||
|
||||
// End docile
|
||||
if(docile)
|
||||
to_chat(controlling ? host : src, span_notice("You shake off your lethargy as the sugar leaves your host's blood."))
|
||||
docile = FALSE
|
||||
docile_counter = 0
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/handle_braindamage()
|
||||
if(QDELETED(src) || !host || QDELETED(host) || !controlling)
|
||||
return
|
||||
if(prob(2))
|
||||
host.adjustBrainLoss(0.1)
|
||||
if(prob(host.brainloss/20))
|
||||
host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_v","gasp"))]")
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/can_use_power_in_host()
|
||||
if(QDELETED(src))
|
||||
return FALSE
|
||||
if(!host || QDELETED(host))
|
||||
to_chat(src, span_warning("You are not inside a host body."))
|
||||
return FALSE
|
||||
if(stat)
|
||||
to_chat(controlling ? host : src, span_warning("You cannot that that in your current state."))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/can_use_power_controlling_host()
|
||||
if(!can_use_power_in_host())
|
||||
return FALSE
|
||||
if(!controlling)
|
||||
to_chat(controlling ? host : src, span_warning("You need to be in complete control to do this."))
|
||||
return FALSE
|
||||
if(host.stat)
|
||||
to_chat(controlling ? host : src, span_warning("Your host is in no condition to do that."))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/can_use_power_docile()
|
||||
if(docile)
|
||||
to_chat(controlling ? host : src, span_info("You are feeling far too docile to do that."))
|
||||
return !docile
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/use_chems(amount)
|
||||
if(chemicals < amount)
|
||||
to_chat(controlling ? host : src, span_warning("You don't have enough chemicals, requires [amount]! Currently you have [FLOOR(chemicals,1)]."))
|
||||
return FALSE
|
||||
chemicals -= amount
|
||||
to_chat(controlling ? host : src, span_info("You use [amount] chemicals, [FLOOR(chemicals,1)] remain."))
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_mob/animal/borer/handle_regular_hud_updates()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(borer_chem_display)
|
||||
borer_chem_display.invisibility = INVISIBILITY_NONE
|
||||
switch(chemicals)
|
||||
if(0 to 9)
|
||||
borer_chem_display.icon_state = "ling_chems0e"
|
||||
if(10 to 19)
|
||||
borer_chem_display.icon_state = "ling_chems10e"
|
||||
if(20 to 29)
|
||||
borer_chem_display.icon_state = "ling_chems20e"
|
||||
if(30 to 39)
|
||||
borer_chem_display.icon_state = "ling_chems30e"
|
||||
if(40 to 49)
|
||||
borer_chem_display.icon_state = "ling_chems40e"
|
||||
if(50 to 59)
|
||||
borer_chem_display.icon_state = "ling_chems50e"
|
||||
if(60 to 69)
|
||||
borer_chem_display.icon_state = "ling_chems60e"
|
||||
if(70 to 79)
|
||||
borer_chem_display.icon_state = "ling_chems70e"
|
||||
if(80 to INFINITY)
|
||||
borer_chem_display.icon_state = "ling_chems80e"
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/detatch()
|
||||
if(!host || !controlling)
|
||||
return
|
||||
|
||||
if(ishuman(host))
|
||||
var/mob/living/carbon/human/H = host
|
||||
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
|
||||
if(head)
|
||||
head.implants -= src
|
||||
|
||||
var/obj/item/organ/external/head = host.get_organ(BP_HEAD)
|
||||
if(head)
|
||||
head.implants -= src
|
||||
controlling = FALSE
|
||||
|
||||
host.remove_language("Cortical Link")
|
||||
@@ -125,6 +241,7 @@
|
||||
remove_verb(host, /mob/living/carbon/proc/punish_host)
|
||||
remove_verb(host, /mob/living/carbon/proc/spawn_larvae)
|
||||
|
||||
// This entire section is awful and a relic of ancient times. It needs to be replaced
|
||||
if(host_brain)
|
||||
// these are here so bans and multikey warnings are not triggered on the wrong people when ckey is changed.
|
||||
// computer_id and IP are not updated magically on their own in offline mobs -walter0o
|
||||
@@ -160,7 +277,7 @@
|
||||
host.lastKnownIP = b2h_ip
|
||||
|
||||
qdel(host_brain)
|
||||
|
||||
// End horrible ip swapping code for bans
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/leave_host()
|
||||
if(!host)
|
||||
@@ -169,32 +286,16 @@
|
||||
if(host.mind)
|
||||
borers.remove_antagonist(host.mind)
|
||||
|
||||
forceMove(get_turf(host))
|
||||
|
||||
if(!QDELETED(src))
|
||||
forceMove(get_turf(host.loc))
|
||||
unset_machine()
|
||||
|
||||
if(ishuman(host))
|
||||
var/mob/living/carbon/human/H = host
|
||||
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
|
||||
if(head)
|
||||
head.implants -= src
|
||||
|
||||
var/obj/item/organ/external/head = host.get_organ(BP_HEAD)
|
||||
if(head)
|
||||
head.implants -= src
|
||||
host.unset_machine()
|
||||
host = null
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/request_player()
|
||||
Q = new /datum/ghost_query/borer()
|
||||
RegisterSignal(Q, COMSIG_GHOST_QUERY_COMPLETE, PROC_REF(get_winner))
|
||||
Q.query() // This will sleep the proc for awhile.
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/get_winner()
|
||||
SIGNAL_HANDLER
|
||||
if(Q && Q.candidates.len) //Q should NEVER get deleted but...whatever, sanity.
|
||||
var/mob/observer/dead/D = Q.candidates[1]
|
||||
transfer_personality(D)
|
||||
UnregisterSignal(Q, COMSIG_GHOST_QUERY_COMPLETE)
|
||||
QDEL_NULL(Q) //get rid of the query
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/transfer_personality(mob/candidate)
|
||||
if(!candidate)
|
||||
return
|
||||
@@ -206,17 +307,25 @@
|
||||
mind.assigned_role = JOB_CORTICAL_BORER
|
||||
mind.special_role = JOB_CORTICAL_BORER
|
||||
|
||||
// TODO - This needs to be made into something more pref friendly if it's ever going to be used on virgo.
|
||||
to_chat(src, span_notice("You are a cortical borer! You are a brain slug that worms its way \
|
||||
into the head of its victim. Use stealth, persuasion and your powers of mind control to keep you, \
|
||||
your host and your eventual spawn safe and warm."))
|
||||
to_chat(src, "You can speak to your victim with <b>say</b>, to other borers with <b>say :x</b>, and use your Abilities tab to access powers.")
|
||||
|
||||
/mob/living/simple_mob/animal/borer/cannot_use_vents()
|
||||
return
|
||||
return host || stat
|
||||
|
||||
/mob/living/simple_mob/animal/borer/extra_huds(var/datum/hud/hud,var/icon/ui_style,var/list/hud_elements)
|
||||
// Chem hud
|
||||
borer_chem_display = new /atom/movable/screen/borer/chems()
|
||||
borer_chem_display.screen_loc = ui_ling_chemical_display
|
||||
borer_chem_display.icon_state = "ling_chems"
|
||||
hud_elements |= borer_chem_display
|
||||
|
||||
/mob/living/simple_mob/animal/borer/UnarmedAttack(var/atom/A, var/proximity)
|
||||
if(ismob(loc))
|
||||
to_chat(src, span_warning("You cannot interact with that from inside a host!"))
|
||||
to_chat(src, span_notice("You cannot interact with that from inside a host!"))
|
||||
return
|
||||
. = ..()
|
||||
|
||||
@@ -230,7 +339,7 @@
|
||||
|
||||
if(stat >= DEAD)
|
||||
return say_dead(message)
|
||||
else if(stat)
|
||||
if(stat)
|
||||
return
|
||||
|
||||
if(client && client.prefs.muted & MUTE_IC)
|
||||
@@ -247,10 +356,10 @@
|
||||
return
|
||||
|
||||
if(!host)
|
||||
if(chemicals >= 30)
|
||||
if(chemicals >= BORER_PSYCHIC_SAY_MINIMUM_CHEMS)
|
||||
to_chat(src, span_alien("..You emit a psionic pulse with an encoded message.."))
|
||||
var/list/nearby_mobs = list()
|
||||
for(var/mob/living/LM in view(src, 1 + round(6 * (chemicals / max_chemicals))))
|
||||
for(var/mob/living/LM in view(src, 1 + round(6 * (chemicals / BORER_MAX_CHEMS))))
|
||||
if(LM == src)
|
||||
continue
|
||||
if(!LM.stat)
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
|
||||
/mob/living/captive_brain/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
|
||||
|
||||
if (src.client)
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, span_red("You cannot speak in IC (muted)."))
|
||||
return
|
||||
|
||||
if(istype(src.loc, /mob/living/simple_mob/animal/borer))
|
||||
if(istype(loc, /mob/living/simple_mob/animal/borer))
|
||||
|
||||
message = sanitize(message)
|
||||
if (!message)
|
||||
@@ -21,7 +21,7 @@
|
||||
if (stat == 2)
|
||||
return say_dead(message)
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/B = src.loc
|
||||
var/mob/living/simple_mob/animal/borer/B = loc
|
||||
to_chat(src, "You whisper silently, \"[message]\"")
|
||||
to_chat(B.host, "The captive mind of [src] whispers, \"[message]\"")
|
||||
|
||||
@@ -41,24 +41,19 @@
|
||||
|
||||
/mob/living/captive_brain/process_resist()
|
||||
//Resisting control by an alien mind.
|
||||
if(istype(src.loc, /mob/living/simple_mob/animal/borer))
|
||||
var/mob/living/simple_mob/animal/borer/B = src.loc
|
||||
var/mob/living/captive_brain/H = src
|
||||
|
||||
to_chat(H, span_danger("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds)."))
|
||||
if(istype(loc, /mob/living/simple_mob/animal/borer))
|
||||
var/mob/living/simple_mob/animal/borer/B = loc
|
||||
to_chat(src, span_danger("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds)."))
|
||||
to_chat(B.host, span_danger("You feel the captive mind of [src] begin to resist your control."))
|
||||
|
||||
spawn(rand(200,250)+B.host.brainloss)
|
||||
if(!B || !B.controlling) return
|
||||
|
||||
B.host.adjustBrainLoss(rand(0.1,0.5))
|
||||
to_chat(H, span_danger("With an immense exertion of will, you regain control of your body!"))
|
||||
to_chat(B.host, span_danger("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you."))
|
||||
B.detatch()
|
||||
remove_verb(src, /mob/living/carbon/proc/release_control)
|
||||
remove_verb(src, /mob/living/carbon/proc/punish_host)
|
||||
remove_verb(src, /mob/living/carbon/proc/spawn_larvae)
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(break_control_of_borer)), (rand(20,25) + (B.host.brainloss/10)) SECONDS, TIMER_DELETE_ME)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
..()
|
||||
/mob/living/captive_brain/proc/break_control_of_borer()
|
||||
var/mob/living/simple_mob/animal/borer/B = loc
|
||||
if(!B || !B.controlling)
|
||||
return
|
||||
to_chat(src, span_danger("With an immense exertion of will, you regain control of your body!"))
|
||||
to_chat(B.host, span_danger("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you."))
|
||||
B.host.adjustBrainLoss(rand(0.1,0.5))
|
||||
B.detatch()
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Assume control of a borer's host, putting the borer's client in control, and putting the other into a dominated brain.
|
||||
*/
|
||||
/mob/living/simple_mob/animal/borer/verb/bond_brain()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Assume Control"
|
||||
set desc = "Fully connect to the brain of your host."
|
||||
|
||||
if(!can_use_power_in_host())
|
||||
return
|
||||
if(!can_use_power_docile())
|
||||
return
|
||||
if(host.stat == DEAD)
|
||||
to_chat(src, span_warning("Your host is in no condition to do that."))
|
||||
return
|
||||
|
||||
to_chat(src, span_alien("You begin delicately adjusting your connection to the host brain..."))
|
||||
addtimer(CALLBACK(src, PROC_REF(finish_bond_brain)), 100 + (host.brainloss * 5), TIMER_DELETE_ME)
|
||||
|
||||
// This entire section is awful and a relic of ancient times. It needs to be replaced
|
||||
/mob/living/simple_mob/animal/borer/proc/finish_bond_brain()
|
||||
PRIVATE_PROC(TRUE)
|
||||
RETURN_TYPE(null)
|
||||
|
||||
if(!host || QDELETED(src) || controlling)
|
||||
return
|
||||
if(host.stat == DEAD)
|
||||
to_chat(src, span_warning("Your host is in no condition to do that."))
|
||||
return
|
||||
|
||||
to_chat(src, span_alien("You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system."))
|
||||
to_chat(host, span_danger("You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours."))
|
||||
host.add_language("Cortical Link")
|
||||
|
||||
// host -> brain
|
||||
var/h2b_id = host.computer_id
|
||||
var/h2b_ip= host.lastKnownIP
|
||||
host.computer_id = null
|
||||
host.lastKnownIP = null
|
||||
|
||||
qdel(host_brain)
|
||||
host_brain = new(src)
|
||||
host_brain.ckey = host.ckey
|
||||
host_brain.name = host.name
|
||||
|
||||
if(!host_brain.computer_id)
|
||||
host_brain.computer_id = h2b_id
|
||||
|
||||
if(!host_brain.lastKnownIP)
|
||||
host_brain.lastKnownIP = h2b_ip
|
||||
|
||||
// self -> host
|
||||
var/s2h_id = src.computer_id
|
||||
var/s2h_ip= src.lastKnownIP
|
||||
src.computer_id = null
|
||||
src.lastKnownIP = null
|
||||
|
||||
host.ckey = src.ckey
|
||||
|
||||
if(!host.computer_id)
|
||||
host.computer_id = s2h_id
|
||||
if(!host.lastKnownIP)
|
||||
host.lastKnownIP = s2h_ip
|
||||
controlling = TRUE
|
||||
|
||||
add_verb(host, /mob/living/carbon/proc/release_control)
|
||||
add_verb(host, /mob/living/carbon/proc/punish_host)
|
||||
if(antag)
|
||||
add_verb(host, /mob/living/carbon/proc/spawn_larvae)
|
||||
// End horrible ip swapping code for bans
|
||||
|
||||
/**
|
||||
* Releases manual control of the borer from a mind-dominated host. Returning control to the original mind.
|
||||
*/
|
||||
/mob/living/simple_mob/animal/borer/verb/release_host()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Release Host"
|
||||
set desc = "Slither out of your host."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, span_warning("You are not inside a host body."))
|
||||
return
|
||||
if(stat)
|
||||
to_chat(src, span_warning("You cannot leave your host in your current state."))
|
||||
return
|
||||
if(!can_use_power_docile())
|
||||
return
|
||||
|
||||
to_chat(src, span_alien("You begin disconnecting from [host]'s synapses and prodding at their internal ear canal."))
|
||||
if(!host.stat)
|
||||
to_chat(host, span_danger("An odd, uncomfortable pressure begins to build inside your skull, behind your ear..."))
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(finish_release_host)), 10 SECONDS, TIMER_DELETE_ME)
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/finish_release_host()
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
if(!host || QDELETED(src))
|
||||
return
|
||||
|
||||
if(stat)
|
||||
to_chat(src, span_warning("You cannot release your host in your current state."))
|
||||
return
|
||||
|
||||
to_chat(src, span_alien("You wiggle out of [host]'s ear and plop to the ground."))
|
||||
if(host.mind)
|
||||
if(!host.stat)
|
||||
to_chat(host, span_danger("Something slimy wiggles out of your ear and plops to the ground!"))
|
||||
to_chat(host, span_danger("As though waking from a dream, you shake off the insidious mind control of the brain worm. Your thoughts are your own again."))
|
||||
|
||||
detatch()
|
||||
leave_host()
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Brain slug proc for voluntary removal of control.
|
||||
*/
|
||||
/mob/living/carbon/proc/release_control()
|
||||
|
||||
set category = "Abilities.Brainslug"
|
||||
set name = "Release Control"
|
||||
set desc = "Release control of your host's body."
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
|
||||
if(!B)
|
||||
return
|
||||
if(!B.host_brain)
|
||||
return
|
||||
|
||||
to_chat(src, span_alien("You withdraw your probosci, releasing control of [B.host_brain]"))
|
||||
B.detatch()
|
||||
|
||||
/**
|
||||
* Brain slug proc for tormenting the host.
|
||||
*/
|
||||
/mob/living/carbon/proc/punish_host()
|
||||
set category = "Abilities.Brainslug"
|
||||
set name = "Torment host"
|
||||
set desc = "Punish your host with agony."
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
|
||||
if(!B)
|
||||
return
|
||||
if(!B.host_brain)
|
||||
return
|
||||
if(!B.can_use_power_docile())
|
||||
return
|
||||
if(!B.use_chems(BORER_POWER_COST_TORTURE))
|
||||
return
|
||||
|
||||
to_chat(src, span_alien("You send a punishing spike of psychic agony lancing into your host's brain."))
|
||||
if(!B.host_brain.client || !can_feel_pain())
|
||||
to_chat(B.host_brain, span_warning("You feel a strange sensation as a foreign influence prods your mind."))
|
||||
to_chat(src, span_danger("It doesn't seem to be as effective as you hoped."))
|
||||
return
|
||||
to_chat(B.host_brain, span_danger(span_large("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")))
|
||||
|
||||
/**
|
||||
* Brain slug proc for spitting up new borers. They are ghostjoin by default, but are infertile.
|
||||
*/
|
||||
/mob/living/carbon/proc/spawn_larvae()
|
||||
set category = "Abilities.Brainslug"
|
||||
set name = "Reproduce"
|
||||
set desc = "Spawn several young."
|
||||
|
||||
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
|
||||
if(!B || !B.can_use_power_controlling_host())
|
||||
return
|
||||
if(!B.can_use_power_docile())
|
||||
return
|
||||
if(!B.antag)
|
||||
to_chat(src, span_warning("You cannot reproduce, you are infertile!"))
|
||||
return
|
||||
if(!B.use_chems(BORER_POWER_COST_REPRODUCE))
|
||||
return
|
||||
|
||||
to_chat(src, span_alien("Your host twitches and quivers as you rapidly excrete a larva from your sluglike body."))
|
||||
visible_message(span_danger("\The [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!"))
|
||||
|
||||
do_vomit(lost_nutrition = 1) // Needs to be instant
|
||||
new /mob/living/simple_mob/animal/borer/non_antag(get_turf(src))
|
||||
B.has_reproduced = TRUE
|
||||
@@ -1,43 +1,55 @@
|
||||
/mob/living/simple_mob/animal/borer/verb/release_host()
|
||||
/**
|
||||
* Put a nearby target to sleep to allow for infestation.
|
||||
*/
|
||||
/mob/living/simple_mob/animal/borer/verb/knockout_victim()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Release Host"
|
||||
set desc = "Slither out of your host."
|
||||
set name = "Knockout Victim"
|
||||
set desc = "Use your psychic influence to put a target into a temporary catatonic state."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, span_warning("You are not inside a host body."))
|
||||
if(world.time - used_dominate < 150)
|
||||
to_chat(src, span_warning("You cannot use that ability again so soon."))
|
||||
return
|
||||
if(host)
|
||||
to_chat(src, span_warning("You cannot do that from within a host body."))
|
||||
return
|
||||
|
||||
if(stat)
|
||||
to_chat(src, span_warning("You cannot leave your host in your current state."))
|
||||
|
||||
if(docile)
|
||||
to_chat(src, span_blue("You are feeling far too docile to do that."))
|
||||
to_chat(src, span_warning("You cannot do that in your current state."))
|
||||
return
|
||||
|
||||
if(!host || !src) return
|
||||
var/attack_range = 5
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/carbon/human/attackable in view(attack_range,src))
|
||||
if(attackable.stat != DEAD && !attackable.has_brain_worms())
|
||||
choices += attackable
|
||||
if(world.time - used_dominate < 150)
|
||||
to_chat(src, span_warning("You cannot use that ability again so soon."))
|
||||
return
|
||||
|
||||
to_chat(src, span_warning("You begin disconnecting from [host]'s synapses and prodding at their internal ear canal."))
|
||||
if(!choices.len)
|
||||
to_chat(src, span_notice("There are no viable targets within range..."))
|
||||
return
|
||||
var/mob/living/carbon/human/attack_target = choices[1]
|
||||
if(choices.len > 1)
|
||||
tgui_input_list(src, "Who do you wish to dominate?", "Target Choice", choices)
|
||||
|
||||
if(!host.stat)
|
||||
to_chat(host, span_warning("An odd, uncomfortable pressure begins to build inside your skull, behind your ear..."))
|
||||
if(!attack_target || QDELETED(src))
|
||||
return
|
||||
if(!(attack_target in view(attack_range,src)))
|
||||
to_chat(src, span_warning("\The [attack_target] escaped your influence..."))
|
||||
return
|
||||
if(attack_target.has_brain_worms())
|
||||
to_chat(src, span_warning("You cannot influence someone who is already infested!"))
|
||||
return
|
||||
|
||||
spawn(100)
|
||||
|
||||
if(!host || !src) return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, span_warning("You cannot release your host in your current state."))
|
||||
return
|
||||
|
||||
to_chat(src, span_warning("You wiggle out of [host]'s ear and plop to the ground."))
|
||||
if(host.mind)
|
||||
if(!host.stat)
|
||||
to_chat(host, span_danger("Something slimy wiggles out of your ear and plops to the ground!"))
|
||||
to_chat(host, span_danger("As though waking from a dream, you shake off the insidious mind control of the brain worm. Your thoughts are your own again."))
|
||||
|
||||
detatch()
|
||||
leave_host()
|
||||
to_chat(src, span_alien("You focus your psychic lance on [attack_target] and freeze their limbs with a wave of terrible dread."))
|
||||
to_chat(attack_target, span_vdanger("You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing."))
|
||||
attack_target.Sleeping(10) // This was paralyze, but it resulted in players instantly screaming over radio. So get slept nerds.
|
||||
used_dominate = world.time
|
||||
add_attack_logs(src, attack_target, "psychic knockout (borer)")
|
||||
|
||||
/**
|
||||
* Crawls inside of a target mob, and adds the borer as an implant to the mob's brain. If no brain exists the body will become a borer husk zombie.
|
||||
*/
|
||||
/mob/living/simple_mob/animal/borer/verb/infest()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Infest"
|
||||
@@ -46,311 +58,190 @@
|
||||
if(host)
|
||||
to_chat(src, span_warning("You are already within a host."))
|
||||
return
|
||||
|
||||
if(stat)
|
||||
to_chat(src, span_warning("You cannot infest a target in your current state."))
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/carbon/C in view(1,src))
|
||||
if(src.Adjacent(C))
|
||||
choices += C
|
||||
|
||||
for(var/mob/living/carbon/human/check_target in view(1,src))
|
||||
if(Adjacent(check_target) && !check_target.has_brain_worms())
|
||||
choices += check_target
|
||||
if(!choices.len)
|
||||
to_chat(src, span_warning("There are no viable hosts within range..."))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/M = tgui_input_list(src, "Who do you wish to infest?", "Target Choice", choices)
|
||||
var/mob/living/carbon/human/infest_target = choices[1]
|
||||
if(choices.len > 1)
|
||||
infest_target = tgui_input_list(src, "Who do you wish to infest?", "Target Choice", choices)
|
||||
if(QDELETED(infest_target) || QDELETED(src))
|
||||
return
|
||||
infest_target(infest_target)
|
||||
|
||||
if(!M || !src) return
|
||||
|
||||
if(!(src.Adjacent(M))) return
|
||||
|
||||
if(M.has_brain_worms())
|
||||
/// Infests mob with borer.
|
||||
/mob/living/simple_mob/animal/borer/proc/infest_target(mob/living/carbon/human/infest_target)
|
||||
if(!istype(infest_target))
|
||||
to_chat(src, span_warning("\The [infest_target] is not suitable for infestation..."))
|
||||
return
|
||||
if(!(Adjacent(infest_target)))
|
||||
to_chat(src, span_warning("\The [infest_target] has escaped your range..."))
|
||||
return
|
||||
if(infest_target.has_brain_worms())
|
||||
to_chat(src, span_warning("You cannot infest someone who is already infested!"))
|
||||
return
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/entering_timer = 30
|
||||
var/protected = FALSE
|
||||
var/obj/item/organ/external/E = infest_target.organs_by_name[BP_HEAD]
|
||||
if(!E || E.is_stump())
|
||||
to_chat(src, span_warning("\The [infest_target] does not have a head!"))
|
||||
|
||||
var/obj/item/organ/external/E = H.organs_by_name[BP_HEAD]
|
||||
if(!E || E.is_stump())
|
||||
to_chat(src, span_warning("\The [H] does not have a head!"))
|
||||
|
||||
if(!H.should_have_organ(O_BRAIN))
|
||||
to_chat(src, span_warning("\The [H] does not seem to have an ear canal to breach."))
|
||||
return
|
||||
|
||||
if(H.check_head_coverage())
|
||||
to_chat(src, span_warning("You cannot get through that host's protective gear."))
|
||||
return
|
||||
|
||||
to_chat(M, "Something slimy begins probing at the opening of your ear canal...")
|
||||
to_chat(src, span_warning("You slither up [M] and begin probing at their ear canal..."))
|
||||
|
||||
if(!do_after(src, 3 SECONDS, target = M))
|
||||
to_chat(src, span_warning("As [M] moves away, you are dislodged and fall to the ground."))
|
||||
if(!infest_target.should_have_organ(O_BRAIN))
|
||||
to_chat(src, span_warning("\The [infest_target] does not seem to have an ear canal to breach."))
|
||||
return
|
||||
if(infest_target.check_head_coverage())
|
||||
to_chat(src, span_alien("You begin to flatten and squirm into \the [infest_target]'s helmet to find a way inside them."))
|
||||
entering_timer = 55
|
||||
protected = TRUE
|
||||
|
||||
if(!M || !src) return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, span_warning("You cannot infest a target in your current state."))
|
||||
return
|
||||
|
||||
if(M in view(1, src))
|
||||
to_chat(src, span_warning("You wiggle into [M]'s ear."))
|
||||
if(!M.stat)
|
||||
to_chat(M, "Something disgusting and slimy wiggles into your ear!")
|
||||
|
||||
src.host = M
|
||||
src.forceMove(M)
|
||||
|
||||
//Update their traitor status.
|
||||
if(host.mind)
|
||||
borers.add_antagonist_mind(host.mind, 1, borers.faction_role_text, borers.faction_welcome)
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/I = H.internal_organs_by_name[O_BRAIN]
|
||||
if(!I) // No brain organ, so the borer moves in and replaces it permanently.
|
||||
replace_brain()
|
||||
else
|
||||
// If they're in normally, implant removal can get them out.
|
||||
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
|
||||
head.implants += src
|
||||
|
||||
return
|
||||
if(!protected)
|
||||
to_chat(infest_target, span_vdanger("Something slimy begins probing at the opening of your ear canal..."))
|
||||
else
|
||||
to_chat(infest_target, span_vdanger("Something slimy begins trying to find a way past your helmet..."))
|
||||
to_chat(src, span_alien("You slither up to \the [infest_target] and begin probing at their ear canal..."))
|
||||
|
||||
if(!do_after(src, entering_timer, target = infest_target))
|
||||
to_chat(src, span_danger("As [infest_target] moves away, you are dislodged and fall to the ground."))
|
||||
return
|
||||
if(!infest_target || QDELETED(src))
|
||||
return
|
||||
if(stat)
|
||||
to_chat(src, span_warning("You cannot infest \the [infest_target] in your current state."))
|
||||
return
|
||||
if(!(Adjacent(infest_target)))
|
||||
to_chat(src, span_warning("They are no longer in range!"))
|
||||
return
|
||||
|
||||
/*
|
||||
/mob/living/simple_mob/animal/borer/verb/devour_brain()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Devour Brain"
|
||||
set desc = "Take permanent control of a dead host."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, span_warning("You are not inside a host body."))
|
||||
if(!infest_target.internal_organs_by_name[O_BRAIN]) // See section below about replace_brain() being disabled
|
||||
to_chat(src, span_danger("\The [infest_target] has no brain to bond to!"))
|
||||
return
|
||||
|
||||
if(host.stat != 2)
|
||||
to_chat(src, span_warning("Your host is still alive."))
|
||||
to_chat(src, span_alien("You wiggle into [infest_target]'s ear."))
|
||||
if(!infest_target.stat)
|
||||
to_chat(infest_target, span_vdanger("Something disgusting and slimy wiggles into your ear!"))
|
||||
host = infest_target
|
||||
forceMove(host)
|
||||
|
||||
//Update their traitor status.
|
||||
if(host.mind)
|
||||
borers.add_antagonist_mind(host.mind, 1, borers.faction_role_text, borers.faction_welcome)
|
||||
|
||||
/* This is likely not desired, and has some major issues with ghost behavior. Disabling for now
|
||||
// No brain organ, so the borer moves in and replaces it permanently.
|
||||
if(!host.internal_organs_by_name[O_BRAIN])
|
||||
add_attack_logs(src, host, "merged with brainless body (borer)")
|
||||
replace_brain()
|
||||
return
|
||||
*/
|
||||
|
||||
if(stat)
|
||||
to_chat(src, span_warning("You cannot do that in your current state."))
|
||||
|
||||
if(docile)
|
||||
to_chat(src, span_warning(span_blue("You are feeling far too docile to do that.")))
|
||||
return
|
||||
|
||||
|
||||
to_chat(src, span_danger("It only takes a few moments to render the dead host brain down into a nutrient-rich slurry..."))
|
||||
replace_brain()
|
||||
*/
|
||||
|
||||
// BRAIN WORM ZOMBIES AAAAH.
|
||||
/mob/living/simple_mob/animal/borer/proc/replace_brain()
|
||||
|
||||
var/mob/living/carbon/human/H = host
|
||||
|
||||
if(!istype(host))
|
||||
to_chat(src, span_warning("This host does not have a suitable brain."))
|
||||
return
|
||||
|
||||
to_chat(src, span_danger("You settle into the empty brainpan and begin to expand, fusing inextricably with the dead flesh of [H]."))
|
||||
|
||||
H.add_language("Cortical Link")
|
||||
|
||||
if(host.stat == 2)
|
||||
add_verb(H, /mob/living/carbon/human/proc/jumpstart)
|
||||
|
||||
add_verb(H, /mob/living/carbon/human/proc/psychic_whisper)
|
||||
add_verb(H, /mob/living/carbon/human/proc/tackle)
|
||||
if(antag)
|
||||
add_verb(H, /mob/living/carbon/proc/spawn_larvae)
|
||||
|
||||
if(H.client)
|
||||
H.ghostize(0)
|
||||
|
||||
if(src.mind)
|
||||
src.mind.special_role = "Borer Husk"
|
||||
src.mind.transfer_to(host)
|
||||
|
||||
H.ChangeToHusk()
|
||||
|
||||
var/obj/item/organ/internal/borer/B = new(H)
|
||||
H.internal_organs_by_name[O_BRAIN] = B
|
||||
H.internal_organs |= B
|
||||
|
||||
var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD)
|
||||
affecting.implants -= src
|
||||
|
||||
var/s2h_id = src.computer_id
|
||||
var/s2h_ip= src.lastKnownIP
|
||||
src.computer_id = null
|
||||
src.lastKnownIP = null
|
||||
|
||||
if(!H.computer_id)
|
||||
H.computer_id = s2h_id
|
||||
|
||||
if(!H.lastKnownIP)
|
||||
H.lastKnownIP = s2h_ip
|
||||
// If they're in normally, implant removal can get them out.
|
||||
var/obj/item/organ/external/head = host.get_organ(BP_HEAD)
|
||||
head.implants += src
|
||||
add_attack_logs(src, host, "infested target (borer)")
|
||||
|
||||
/**
|
||||
* Releases chemicals from the borer into their host. Can be used as a standalone chemist in your head for an antag cooperating with their borer.
|
||||
*/
|
||||
/mob/living/simple_mob/animal/borer/verb/secrete_chemicals()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Secrete Chemicals"
|
||||
set desc = "Push some chemicals into your host's bloodstream."
|
||||
set desc = "Drain some chemicals into your host's bloodstream."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, span_warning("You are not inside a host body."))
|
||||
if(!can_use_power_in_host())
|
||||
return
|
||||
if(!can_use_power_docile())
|
||||
return
|
||||
if(controlling)
|
||||
to_chat(src, span_warning("You cannot do that while in full control of a host."))
|
||||
return
|
||||
|
||||
if(stat)
|
||||
to_chat(src, span_warning("You cannot secrete chemicals in your current state."))
|
||||
|
||||
if(docile)
|
||||
to_chat(src, span_warning(span_blue("You are feeling far too docile to do that.")))
|
||||
return
|
||||
|
||||
if(chemicals < 50)
|
||||
to_chat(src, span_warning("You don't have enough chemicals!"))
|
||||
|
||||
var/chem = tgui_input_list(src, "Select a chemical to secrete.", "Chemicals", list(REAGENT_ID_ALKYSINE,REAGENT_ID_BICARIDINE,REAGENT_ID_HYPERZINE,REAGENT_ID_TRAMADOL))
|
||||
|
||||
if(!chem || chemicals < 50 || !host || controlling || !src || stat) //Sanity check.
|
||||
return
|
||||
|
||||
to_chat(src, span_bolddanger("You squirt a measure of [chem] from your reservoirs into [host]'s bloodstream."))
|
||||
host.reagents.add_reagent(chem, 10)
|
||||
chemicals -= 50
|
||||
|
||||
/mob/living/simple_mob/animal/borer/verb/dominate_victim()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Paralyze Victim"
|
||||
set desc = "Freeze the limbs of a potential host with supernatural fear."
|
||||
|
||||
if(world.time - used_dominate < 150)
|
||||
to_chat(src, span_warning("You cannot use that ability again so soon."))
|
||||
return
|
||||
|
||||
if(host)
|
||||
to_chat(src, span_warning("You cannot do that from within a host body."))
|
||||
return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, span_warning("You cannot do that in your current state."))
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/carbon/C in view(3,src))
|
||||
if(C.stat != 2)
|
||||
choices += C
|
||||
|
||||
if(world.time - used_dominate < 150)
|
||||
to_chat(src, span_warning("You cannot use that ability again so soon."))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/M = tgui_input_list(src, "Who do you wish to dominate?", "Target Choice", choices)
|
||||
|
||||
if(!M || !src) return
|
||||
|
||||
if(M.has_brain_worms())
|
||||
to_chat(src, span_warning("You cannot infest someone who is already infested!"))
|
||||
return
|
||||
|
||||
to_chat(src, span_red("You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread."))
|
||||
to_chat(M, span_red("You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing."))
|
||||
M.Weaken(10)
|
||||
|
||||
used_dominate = world.time
|
||||
|
||||
/mob/living/simple_mob/animal/borer/verb/bond_brain()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Assume Control"
|
||||
set desc = "Fully connect to the brain of your host."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, span_warning("You are not inside a host body."))
|
||||
return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, span_warning("You cannot do that in your current state."))
|
||||
return
|
||||
|
||||
if(docile)
|
||||
to_chat(src, span_blue("You are feeling far too docile to do that."))
|
||||
return
|
||||
|
||||
to_chat(src, span_warning("You begin delicately adjusting your connection to the host brain..."))
|
||||
|
||||
spawn(100+(host.brainloss*5))
|
||||
|
||||
if(!host || !src || controlling)
|
||||
var/injection_choice = tgui_input_list(src, "Select a chemical to secrete.", "Chemicals", borer_chem_list)
|
||||
if(injection_choice == "Revive Dead Host")
|
||||
if(!can_use_power_in_host())
|
||||
return
|
||||
else
|
||||
|
||||
to_chat(src, span_bolddanger("You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system."))
|
||||
to_chat(host, span_bolddanger("You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours."))
|
||||
host.add_language("Cortical Link")
|
||||
|
||||
// host -> brain
|
||||
var/h2b_id = host.computer_id
|
||||
var/h2b_ip= host.lastKnownIP
|
||||
host.computer_id = null
|
||||
host.lastKnownIP = null
|
||||
|
||||
qdel(host_brain)
|
||||
host_brain = new(src)
|
||||
|
||||
host_brain.ckey = host.ckey
|
||||
|
||||
host_brain.name = host.name
|
||||
|
||||
if(!host_brain.computer_id)
|
||||
host_brain.computer_id = h2b_id
|
||||
|
||||
if(!host_brain.lastKnownIP)
|
||||
host_brain.lastKnownIP = h2b_ip
|
||||
|
||||
// self -> host
|
||||
var/s2h_id = src.computer_id
|
||||
var/s2h_ip= src.lastKnownIP
|
||||
src.computer_id = null
|
||||
src.lastKnownIP = null
|
||||
|
||||
host.ckey = src.ckey
|
||||
|
||||
if(!host.computer_id)
|
||||
host.computer_id = s2h_id
|
||||
|
||||
if(!host.lastKnownIP)
|
||||
host.lastKnownIP = s2h_ip
|
||||
|
||||
controlling = 1
|
||||
|
||||
add_verb(host, /mob/living/carbon/proc/release_control)
|
||||
add_verb(host, /mob/living/carbon/proc/punish_host)
|
||||
if(antag)
|
||||
add_verb(host, /mob/living/carbon/proc/spawn_larvae)
|
||||
|
||||
if(controlling)
|
||||
to_chat(src, span_warning("You cannot do that while in full control of a host."))
|
||||
return
|
||||
if(!can_use_power_docile())
|
||||
return
|
||||
if(host.stat != DEAD)
|
||||
to_chat(src, span_danger("Your host must be dead!"))
|
||||
return
|
||||
if(HUSK in host.mutations)
|
||||
to_chat(src, span_danger("Your host is too destroyed to revive."))
|
||||
return
|
||||
if(!host.can_defib)
|
||||
to_chat(src, span_vdanger("Your host's brain is not connected to its body!"))
|
||||
return
|
||||
if(!use_chems(BORER_POWER_COST_SECRETE))
|
||||
return
|
||||
to_chat(src, span_alien("You squirt an intense mix of chemicals from your reservoirs into [host]'s bloodstream."))
|
||||
add_attack_logs(src, host, "jumpstart host (borer)")
|
||||
host.jumpstart()
|
||||
return
|
||||
|
||||
// Is this even legal to do still? We had to wait for a selection...
|
||||
if(!can_use_power_in_host())
|
||||
return
|
||||
if(!can_use_power_docile())
|
||||
return
|
||||
if(controlling)
|
||||
to_chat(src, span_warning("You cannot do that while in full control of a host."))
|
||||
return
|
||||
|
||||
// Get the chem we're injecting
|
||||
var/list/injection_data = borer_chem_list[injection_choice]
|
||||
if(!injection_data) //Sanity check.
|
||||
return
|
||||
var/injecting_chem = injection_data[1]
|
||||
var/injectsize = injection_data[2]
|
||||
if(!injecting_chem || !injectsize)
|
||||
return
|
||||
|
||||
// Finally get to injecting
|
||||
if(!use_chems(BORER_POWER_COST_SECRETE))
|
||||
return
|
||||
var/datum/reagent/inject_reagent = SSchemistry.chemical_reagents[injecting_chem]
|
||||
if(!inject_reagent)
|
||||
CRASH("Invalid chem reagent [injecting_chem], in borer chemical injection.")
|
||||
|
||||
add_attack_logs(src, host, "chemical injection [inject_reagent] (borer)")
|
||||
to_chat(src, span_alien("You squirt a measure of [inject_reagent] from your reservoirs into [host]'s bloodstream."))
|
||||
host.bloodstr.add_reagent(injecting_chem, injectsize)
|
||||
|
||||
/// Does some basic regeneration on a host
|
||||
/mob/living/carbon/human/proc/jumpstart()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Revive Host"
|
||||
set desc = "Send a jolt of electricity through your host, reviving them."
|
||||
|
||||
if(stat != 2)
|
||||
to_chat(src, "Your host is already alive.")
|
||||
return
|
||||
|
||||
// This is meant to be a bit silly, cause borers don't have much options otherwise
|
||||
remove_verb(src, /mob/living/carbon/human/proc/jumpstart)
|
||||
visible_message(span_warning("With a hideous, rattling moan, [src] shudders back to life!"))
|
||||
visible_message(span_danger("With a hideous, rattling moan, [src] shudders back to life!"))
|
||||
|
||||
// Dump damage or we won't be able to revive properly
|
||||
setHalLoss(0)
|
||||
setOxyLoss(0)
|
||||
adjustBruteLoss(-20)
|
||||
adjustFireLoss(-20)
|
||||
adjust_nutrition(-200)
|
||||
|
||||
// Boilerplate revivial
|
||||
rejuvenate()
|
||||
restore_blood()
|
||||
fixblood()
|
||||
update_canmove()
|
||||
|
||||
// Get some healing in us
|
||||
bloodstr.add_reagent(REAGENT_BICARIDINE, 5)
|
||||
bloodstr.add_reagent(REAGENT_KELOTANE, 5)
|
||||
bloodstr.add_reagent(REAGENT_ID_TRAMADOL, 5)
|
||||
bloodstr.add_reagent(REAGENT_ID_ALKYSINE, 5)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/mob/living/simple_mob/animal/borer
|
||||
var/datum/ghost_query/ghost_check // Used to unregister our signal
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/request_player()
|
||||
ghost_check = new /datum/ghost_query/borer()
|
||||
RegisterSignal(ghost_check, COMSIG_GHOST_QUERY_COMPLETE, PROC_REF(get_winner))
|
||||
ghost_check.query() // This will sleep the proc for awhile.
|
||||
|
||||
/mob/living/simple_mob/animal/borer/proc/get_winner()
|
||||
SIGNAL_HANDLER
|
||||
if(ghost_check && ghost_check.candidates.len) //ghost_check should NEVER get deleted but...whatever, sanity.
|
||||
var/mob/observer/dead/D = ghost_check.candidates[1]
|
||||
transfer_personality(D)
|
||||
UnregisterSignal(ghost_check, COMSIG_GHOST_QUERY_COMPLETE)
|
||||
QDEL_NULL(ghost_check) //get rid of the query
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Consumes the brain of a dead host, turning it into a husk zombie.
|
||||
*
|
||||
* Disabled currently due to ghosting behavior, allows you to enter a dead body ghost around for meta knowledge, then return and jumpstart the host.
|
||||
* Ideally a borer is about cooperating with your host in some way, and not just killing and eating their brain to go full single player antag anyway...
|
||||
*/
|
||||
/mob/living/simple_mob/animal/borer/verb/devour_brain()
|
||||
set category = "Abilities.Borer"
|
||||
set name = "Devour Brain"
|
||||
set desc = "Take permanent control of a dead host."
|
||||
|
||||
if(!can_use_power_in_host())
|
||||
return
|
||||
if(!can_use_power_docile())
|
||||
return
|
||||
if(host.stat != DEAD)
|
||||
to_chat(src, span_warning("Your host is still alive."))
|
||||
return
|
||||
|
||||
to_chat(src, span_alien("It only takes a few moments to render the dead host brain down into a nutrient-rich slurry..."))
|
||||
add_attack_logs(src, host, "devour host brain (borer)")
|
||||
replace_brain()
|
||||
|
||||
/// BRAIN WORM ZOMBIES AAAAH. Husks mob and turns them into a borer zombie.
|
||||
/mob/living/simple_mob/animal/borer/proc/replace_brain()
|
||||
if(!istype(host))
|
||||
to_chat(src, span_warning("This host does not have a suitable brain."))
|
||||
return
|
||||
to_chat(src, span_alien("You settle into the empty brainpan and begin to expand, fusing inextricably with the dead flesh of [host]."))
|
||||
|
||||
host.add_language("Cortical Link")
|
||||
|
||||
if(host.stat == DEAD)
|
||||
add_verb(host, /mob/living/carbon/human/proc/jumpstart)
|
||||
add_verb(host, /mob/living/carbon/human/proc/psychic_whisper)
|
||||
add_verb(host, /mob/living/carbon/human/proc/tackle)
|
||||
if(antag)
|
||||
add_verb(host, /mob/living/carbon/proc/spawn_larvae)
|
||||
|
||||
// Zombify
|
||||
if(host.client)
|
||||
host.ghostize(FALSE)
|
||||
if(mind)
|
||||
mind.special_role = "Borer Husk"
|
||||
mind.transfer_to(host)
|
||||
host.ChangeToHusk()
|
||||
|
||||
// Convert into borer brain
|
||||
var/obj/item/organ/internal/borer/borer_organ = new(host)
|
||||
host.internal_organs_by_name[O_BRAIN] = borer_organ
|
||||
host.internal_organs |= borer_organ
|
||||
var/obj/item/organ/external/affecting = host.get_organ(BP_HEAD)
|
||||
affecting.implants -= src
|
||||
|
||||
// This section is awful and a relic of ancient times. It needs to be replaced
|
||||
var/s2h_id = computer_id
|
||||
var/s2h_ip= lastKnownIP
|
||||
computer_id = null
|
||||
lastKnownIP = null
|
||||
|
||||
if(!host.computer_id)
|
||||
host.computer_id = s2h_id
|
||||
|
||||
if(!host.lastKnownIP)
|
||||
host.lastKnownIP = s2h_ip
|
||||
// End ip trickery
|
||||
@@ -42,6 +42,7 @@
|
||||
var/atom/movable/screen/gun/run/gun_run_icon = null
|
||||
var/atom/movable/screen/gun/mode/gun_setting_icon = null
|
||||
var/atom/movable/screen/ling/chems/ling_chem_display = null
|
||||
var/atom/movable/screen/borer/chems/borer_chem_display = null
|
||||
var/atom/movable/screen/wizard/energy/wiz_energy_display = null
|
||||
var/atom/movable/screen/wizard/instability/wiz_instability_display = null
|
||||
var/atom/movable/screen/autowhisper_display = null
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "code\__defines\belly_messages.dm"
|
||||
#include "code\__defines\belly_modes_vr.dm"
|
||||
#include "code\__defines\blueprints.dm"
|
||||
#include "code\__defines\borer.dm"
|
||||
#include "code\__defines\borg_overlays.dm"
|
||||
#include "code\__defines\callbacks.dm"
|
||||
#include "code\__defines\changeling.dm"
|
||||
@@ -3659,7 +3660,10 @@
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\alien animals\teppi.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\borer\borer.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\borer\borer_captive.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\borer\borer_control.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\borer\borer_host_powers.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\borer\borer_powers.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\borer\borer_query.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\farm animals\chicken.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\farm animals\cow.dm"
|
||||
#include "code\modules\mob\living\simple_mob\subtypes\animal\farm animals\goat.dm"
|
||||
|
||||
Reference in New Issue
Block a user