Various Borer fixes (#18969)

I changed add_antag to add_antag_mind in borer/LateLogin because the
former proc re-created the borer, causing it to drop the src/client
reference. The only notable difference I observe is the antag noise
doesn't play, which could be added manually if needed. Alternative
methods to solve this would be welcome, though. I did have an
alternative method
[here](https://github.com/Aurorastation/Aurora.3/commit/5d4157588baa0998f499aba7678bf8c6551247ca),
but that only "fixed" the ghost spawner, not admin possession. I also
say "fixed" because that method does not give the post ghost-spawn
message.


Fixes #18600 

- The implant check was only checking for objs, which the borer implant
is not. The borer was also erroneously being removed from the implants
list when releasing control back to their host.

Fixes #18281 

- This had a few pain points. psi was null, so it made the callback for
activating powers fail. Once that was fixed, it caused many RTEs when
trying to draw the HUD/screen for the powers. Refactoring a few
encoding/decoding procs fixed that.
Fixing these issues fixed borer monkeys not being able to speak TCB,
which is strange because I thought I'd seen a borer monkey speaking TCB
during a round where the psychic bug existed.

Fixes #9621 

- For this, I switched rejuvenate to revive. This lets them move, and
also does not kill them again due to brain damage. If it proves to be
too strong, it can be tweaked, but I did want to get brain devouring
working for this PR.

- There's also the jumpstart verb, which seems will never be used with
this revive in place (or even before, with the rejuvenate). I suppose it
can be used if they die again after reviving.

- Should a message be added to the revive given during the devouring
process? Jumpstart gives one:

`visible_message(SPAN_WARNING("With a hideous, rattling moan, [src]
shudders back to life!"))`

Fixes #9523


Also fixes borers not being able to infest someone they are being held
by.

Existing Issues not addressed by this PR:
- Infesting a monkey does not give you the monkey's health HUD (because
it doesn't exist?). Assuming and releasing control will show it, though.
- Borer antag overlay icons on Mobs seems inconsistent. potentially due
to testing methods with clientless mobs
- Borers cannot use psychic lance while being held
- Psi aura on first receiving powers. Equip first ability and drop to
fix.

---------

Signed-off-by: AlaunusLux <89751433+AlaunusLux@users.noreply.github.com>
This commit is contained in:
AlaunusLux
2024-06-08 16:54:28 +00:00
committed by GitHub
parent 1217ede72f
commit 6bf406067c
8 changed files with 108 additions and 42 deletions
@@ -46,9 +46,11 @@
/mob/living/simple_animal/borer/LateLogin()
..()
if(mind)
borers.add_antagonist(mind)
if(client && host)
client.screen += host.healths
borers.add_antagonist_mind(mind, 1, borers.role_text, borers.welcome_text)
if(client)
client.init_verbs()
if(host)
client.screen += host.healths
/mob/living/simple_animal/borer/Initialize()
. = ..()
@@ -111,11 +113,6 @@
if(ability_bar)
QDEL_NULL(ability_bar)
if(istype(host,/mob/living/carbon/human))
var/mob/living/carbon/human/H = host
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
head.implants -= src
controlling = FALSE
host.remove_language(LANGUAGE_BORER)
@@ -38,6 +38,14 @@
detach()
leave_host()
/mob/living/simple_animal/borer/proc/is_held_by(var/mob/living/carbon/M)
if (istype(usr.loc, /obj/item/holder))
var/obj/item/holder/H = usr.loc
if (istype(H.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/held_by = H.loc
return held_by == M
return FALSE
/mob/living/simple_animal/borer/verb/infest()
set category = "Abilities"
@@ -56,6 +64,12 @@
if(src.Adjacent(C))
choices += C
if (istype(usr.loc, /obj/item/holder))
var/obj/item/holder/H = usr.loc
if (istype(H.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/held_by = H.loc
choices += held_by
if(!length(choices))
to_chat(src, SPAN_NOTICE("There are no viable hosts within range."))
return
@@ -73,7 +87,7 @@
return
if(!M || !src)
return
if(!Adjacent(M))
if(!Adjacent(M) && !is_held_by(M))
return
if(M.has_brain_worms())
to_chat(src, SPAN_WARNING("You cannot infest someone who is already infested!"))
@@ -103,7 +117,7 @@
to_chat(M, SPAN_WARNING("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,30))
if(!do_after(src,30) && !is_held_by(M))
to_chat(src, SPAN_WARNING("As [M] moves away, you are dislodged and fall to the ground."))
return
if(!M || !src)
@@ -112,7 +126,7 @@
to_chat(src, SPAN_NOTICE("You cannot infest a target in your current state."))
return
if(M in view(1, src))
if((M in view(1, src)) || is_held_by(M))
to_chat(src, SPAN_NOTICE("You wiggle into [M]'s ear."))
if(!M.stat)
to_chat(M, SPAN_DANGER("Something disgusting and slimy wiggles into your ear!"))
@@ -121,7 +135,7 @@
src.host.status_flags |= PASSEMOTES
src.forceMove(M)
if(client)
if(client && host.healths)
client.screen += host.healths
//Update their traitor status.
@@ -187,6 +201,8 @@
if(src.mind)
src.mind.special_role = "Borer Husk"
src.mind.transfer_to(host)
if(host.client)
host.client.init_verbs()
var/obj/item/organ/internal/borer/B = new(H)
var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD)
@@ -207,8 +223,8 @@
H.lastKnownIP = s2h_ip
// Since the host is dead, we want to kick it back into action immediately, then redo it to ensure they're good to go
H.rejuvenate()
addtimer(CALLBACK(H, PROC_REF(rejuvenate)), 30)
H.revive()
addtimer(CALLBACK(H, PROC_REF(revive)), 30)
/mob/living/simple_animal/borer/verb/secrete_chemicals()
set category = "Abilities"
@@ -481,9 +497,14 @@
return
to_chat(src, SPAN_NOTICE("You succeed in interfacing with the host's zona bovinae, this will be a painful process for them."))
host.awaken_psi_basic("something in your head")
host.psi.psi_points = 3 /// You don't get a lot at the start.
host.psi = new(host)
host.add_language(LANGUAGE_TCB) // if we don't have TCB, give them TCB | this allows monkey borers to RP
host.awaken_psi_basic("something in your head")
addtimer(CALLBACK(src, PROC_REF(set_starting_psi_points)), 4.7 SECONDS)
/mob/living/simple_animal/borer/proc/set_starting_psi_points()
host.psi.psi_points = 3// You don't get a lot at the start.
host.psi.last_psionic_rank = host.psi.psionic_rank
/mob/living/simple_animal/borer/verb/advance_psionics()
set category = "Abilities"
+1 -1
View File
@@ -18,7 +18,7 @@
/singleton/psionic_power/proc/apply(var/mob/living/carbon/human/H)
if(H.ability_master)
var/obj/spellbutton/spell = new(H, spell_path, name, icon_state)
H.ability_master.add_psionic_ability(spell, icon_state, src)
H.ability_master.add_psionic_ability(spell, icon_state, src, H)
H.psi.psionic_powers |= type
return TRUE
else
+2 -2
View File
@@ -184,12 +184,12 @@
if(length(affected.implants))
var/list/implants = list()
var/shrapnel_present = FALSE
for(var/obj/I in affected.implants)
for(var/I in affected.implants)
implants += I
if(!istype(I, /obj/item/implant))
shrapnel_present = TRUE
for(var/obj/I in implants)
for(var/I in implants)
/// Prioritize shrapnel instead of stuff like loyalty implants.
if(shrapnel_present && istype(I, /obj/item/implant))
continue