Rework how darkspawn devour will works (#22957)

* rework progress

* Update thrall_tumor.dm

* tweaks

* more words and number tweaks

* Update thrall_tumor.dm
This commit is contained in:
Molti
2025-01-14 07:01:26 -06:00
committed by GitHub
parent 3d35c4f22d
commit 4c9f485cf5
9 changed files with 98 additions and 166 deletions

View File

@@ -144,8 +144,6 @@
#define STATUS_EFFECT_BROKEN_WILL /datum/status_effect/broken_will //A 30-second sleep effect, ends instantly upon taking enough damage in a single hit. //Yogs
#define STATUS_EFFECT_DEVOURED_WILL /datum/status_effect/devoured_will //A 3 minute long status effect that prevents using devour will on the owner
#define STATUS_EFFECT_AMOK /datum/status_effect/amok //Makes the target automatically strike out at adjecent non-heretics.
#define STATUS_EFFECT_CLOUDSTRUCK /datum/status_effect/cloudstruck //blinds and applies an overlay.

View File

@@ -1084,13 +1084,6 @@
icon_state = "broken_will"
alerttooltipstyle = "alien"
//used to prevent the use of devour will on the target
/datum/status_effect/devoured_will
id = "devoured_will"
status_type = STATUS_EFFECT_UNIQUE
duration = 3 MINUTES
alert_type = null
/datum/status_effect/eldritch
duration = 15 SECONDS
status_type = STATUS_EFFECT_REPLACE

View File

@@ -170,8 +170,8 @@
H.leave_victim()
return FALSE
if(I && I.owner == target)
if(istype(I, /obj/item/organ/shadowtumor))//Thralls resist deconversion
var/obj/item/organ/shadowtumor/tumor = I
if(istype(I, /obj/item/organ/shadowtumor/thrall))//Thralls resist deconversion
var/obj/item/organ/shadowtumor/thrall/tumor = I
if(tumor.resist(target))
return FALSE
display_results(user, target, span_notice("You successfully extract [I] from [target]'s [parse_zone(target_zone)]."),

View File

@@ -86,7 +86,7 @@
name = "darkspawn progression abilities"
desc = "me no think so good"
shadow_flags = ALL_DARKSPAWN_CLASSES
learned_abilities = list(/datum/action/cooldown/spell/sacrament, /datum/action/cooldown/spell/touch/restrain_body, /datum/action/cooldown/spell/touch/devour_will)
learned_abilities = list(/datum/action/cooldown/spell/sacrament, /datum/action/cooldown/spell/touch/devour_will)
////////////////////////////////////////////////////////////////////////////////////
//----------------------Specialization innate Upgrades----------------------------//

View File

@@ -18,7 +18,8 @@
//////////////////////////////////////////////////////////////////////////
/datum/action/cooldown/spell/touch/devour_will
name = "Devour Will"
desc = "Creates a dark bead that can be used on a human to begin draining the lucidity and willpower from a living target, knocking them unconscious for a time.<br>Being interrupted will knock you down for a time."
desc = "Creates a dark bead that can be used on a human to begin draining the lucidity and willpower from a living target, knocking them unconscious for a time.\
<br>Being interrupted will knock you down for a time."
panel = "Darkspawn"
button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi'
sound = null
@@ -61,11 +62,16 @@
if(target.stat == DEAD)
to_chat(caster, span_warning("[target] is too weak to drain."))
return
if(target.has_status_effect(STATUS_EFFECT_DEVOURED_WILL))
to_chat(caster, span_warning("[target]'s mind has not yet recovered enough willpower to be worth devouring."))
return
if(get_shadow_tumor(target))
to_chat(owner, span_danger("[target] already has a dark bead lodged within their psyche."))
return FALSE
var/datum/team/darkspawn/team = darkspawn.get_team()
if(!team)
CRASH("darkspawn without a team is trying to thrall someone")
caster.Immobilize(1 SECONDS) // So they don't accidentally move while beading
target.Immobilize(10 SECONDS) //we remove this if it's canceled early
target.silent += 5
caster.balloon_alert(caster, "Cera ko...")
@@ -76,134 +82,53 @@
eating = TRUE
if(!do_after(caster, 5 SECONDS, target))
to_chat(caster, span_danger("Being interrupted causes a backlash of psionic power."))
caster.Immobilize(5 SECONDS)
caster.Knockdown(10 SECONDS)
to_chat(target, span_boldwarning("All right... You're all right."))
caster.Knockdown(5 SECONDS)
target.SetImmobilized(0)
eating = FALSE
return FALSE
eating = FALSE
if(target.has_status_effect(STATUS_EFFECT_DEVOURED_WILL))
to_chat(caster, span_warning("[target]'s mind has not yet recovered enough willpower to be worth devouring."))
return
if(get_shadow_tumor(target))
to_chat(owner, span_danger("[target] already has a dark bead lodged within their psyche."))
return FALSE
//put the victim to sleep before the visible_message proc so the victim doesn't see it
to_chat(target, span_progenitor("You suddenly feel... empty. Thoughts try to form, but flit away. You slip into a deep, deep slumber..."))
playsound(target, 'yogstation/sound/magic/devour_will_end.ogg', 75, FALSE)
target.playsound_local(target, 'yogstation/sound/magic/devour_will_victim.ogg', 50, FALSE)
target.Unconscious(5 SECONDS)
//get how much lucidity and willpower will be given
var/willpower_amount = 2
var/lucidity_amount = 1
if(HAS_TRAIT(target, TRAIT_DARKSPAWN_DEVOURED)) //change the numbers before text
lucidity_amount = 0
willpower_amount *= 0.5
willpower_amount = round(willpower_amount) //make sure it's a whole number still
//format the text output to the darkspawn
var/list/self_text = list()
caster.balloon_alert(caster, "...akkraup'dej")
self_text += span_velvet("You devour [target]'s will.")
if(HAS_TRAIT(target, TRAIT_DARKSPAWN_DEVOURED))
self_text += span_warning("[target]'s mind is already damaged by previous devouring and has granted less willpower and no lucidity.")
else
self_text += span_velvet("This individual's lucidity brings you one step closer to the sacrament...")
self_text += span_warning("After meddling with [target]'s mind, they will grant less willpower and no lucidity any future times their will is devoured.")
self_text += span_warning("[target] is now severely weakened and will take some time to recover.")
caster.visible_message(span_warning("[caster] gently lowers [target] to the ground..."), self_text.Join("<br>"))
var/obj/item/organ/shadowtumor/bead = target.getorganslot(ORGAN_SLOT_BRAIN_TUMOR)
if(!bead || !istype(bead))
bead = new
bead.Insert(target, FALSE, FALSE)
bead.antag_team = team
//pass out the willpower and lucidity to the darkspawns
var/datum/team/darkspawn/team = darkspawn.get_team()
if(team)
team.grant_willpower(willpower_amount)
team.grant_lucidity(lucidity_amount)
if(!HAS_TRAIT(target, TRAIT_DARKSPAWN_DEVOURED))
ADD_TRAIT(target, TRAIT_DARKSPAWN_DEVOURED, type)
self_text += span_velvet("You place a dark bead deep within [target]'s psyche.")
self_text += span_velvet("This individual's lucidity brings you one step closer to the sacrament...")
self_text += span_velvet("You also feed off their will to fuel your growth, generating 2 willpower.")
self_text += span_velvet("No further attempts to drain this individual will provide willpower or lucidity.")
team.grant_willpower(2)
team.grant_lucidity(1)
else
self_text += span_velvet("You replace the dark bead deep within [target]'s psyche.")
//apply the long-term debuffs to the victim
caster.visible_message(span_warning("[caster] gently lowers [target] to the ground..."), self_text.Join("<br>"))
//apply the long-term debuff to the victim
target.apply_status_effect(STATUS_EFFECT_BROKEN_WILL)
target.apply_status_effect(STATUS_EFFECT_DEVOURED_WILL)
ADD_TRAIT(target, TRAIT_DARKSPAWN_DEVOURED, type)
return TRUE
//////////////////////////////////////////////////////////////////////////
//--------------------------Glorified handcuffs-------------------------//
//////////////////////////////////////////////////////////////////////////
/datum/action/cooldown/spell/touch/restrain_body
name = "Restrain body"
desc = "Forms rudimentary restraints on a target's hands."
panel = "Darkspawn"
button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi'
sound = null
background_icon_state = "bg_alien"
overlay_icon_state = "bg_alien_border"
buttontooltipstyle = "alien"
button_icon_state = "restrain_body"
check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_LYING | AB_CHECK_CONSCIOUS
spell_requirements = SPELL_REQUIRES_HUMAN
invocation_type = INVOCATION_NONE
hand_path = /obj/item/melee/touch_attack/darkspawn
resource_costs = list(ANTAG_RESOURCE_DARKSPAWN = 5)
//Boolean on whether we're tying someone's hands
var/tying = FALSE
/datum/action/cooldown/spell/touch/restrain_body/can_cast_spell(feedback)
if(tying)
return
return ..()
/datum/action/cooldown/spell/touch/restrain_body/is_valid_target(atom/cast_on)
return iscarbon(cast_on)
/datum/action/cooldown/spell/touch/restrain_body/cast_on_hand_hit(obj/item/melee/touch_attack/hand, mob/living/carbon/target, mob/living/carbon/caster)
var/datum/antagonist/darkspawn/darkspawn = isdarkspawn(caster)
if(!darkspawn || tying || target == caster) //no tying yourself
return
if(is_team_darkspawn(target))
to_chat(caster, span_warning("You cannot restrain allies."))
return
if(!istype(target))
to_chat(caster, span_warning("[target]'s mind is too pitiful to be of any use."))
return
if(target.handcuffed)
to_chat(caster, span_warning("[target] is already restrained."))
return
caster.balloon_alert(caster, "Koce ra...")
to_chat(caster, span_velvet("You begin restraining [target]..."))
playsound(target, 'yogstation/sound/ambience/antag/veil_mind_gasp.ogg', 50, TRUE)
tying = TRUE
if(!do_after(caster, 1.5 SECONDS, target, progress = FALSE))
tying = FALSE
return FALSE
tying = FALSE
target.silent += 5
if(target.handcuffed)
to_chat(caster, span_warning("[target] is already restrained."))
return
playsound(target, 'yogstation/sound/magic/devour_will_form.ogg', 50, TRUE)
target.set_handcuffed(new /obj/item/restraints/handcuffs/darkspawn(target))
target.update_handcuffed()
return TRUE
//the restrains in question
/obj/item/restraints/handcuffs/darkspawn
name = "shadow stitched restraints"
desc = "Bindings created by stitching together shadows."
icon_state = "handcuffAlien"
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
breakouttime = 30 SECONDS
flags_1 = NONE
item_flags = DROPDEL
/obj/item/restraints/handcuffs/darkspawn/Initialize(mapload)
. = ..()
add_atom_colour(COLOR_VELVET, FIXED_COLOUR_PRIORITY)
//////////////////////////////////////////////////////////////////////////
//-----------------------Recall shuttle ability-------------------------//
//////////////////////////////////////////////////////////////////////////

View File

@@ -51,12 +51,12 @@
var/datum/antagonist/darkspawn/master = isdarkspawn(caster)
if(!isthrall(target))
if(!target.has_status_effect(STATUS_EFFECT_DEVOURED_WILL))
to_chat(owner, span_danger("[target]'s will is still too strong to thrall."))
return FALSE
if(master.willpower < willpower_cost)
to_chat(owner, span_danger("You do not have enough will to thrall [target]."))
return FALSE
if(!get_shadow_tumor(target))
to_chat(owner, span_danger("[target] does not have a shadow bead for you to enhance."))
return FALSE
owner.balloon_alert(owner, "Krx'lna tyhx graha...")
to_chat(owner, span_velvet("You begin to channel your psionic powers through [target]'s mind."))

View File

@@ -8,10 +8,10 @@
slot = ORGAN_SLOT_BRAIN_TUMOR
///How many process ticks the organ can be in light before it evaporates
var/organ_health = 3
///adds a cooldown to the resist so a thrall ipc or preternis can't weaponize it
COOLDOWN_DECLARE(resist_cooldown)
///How long the resist cooldown is
var/cooldown_length = 15 SECONDS
///Cached darkspawn team that gets the willpower
var/datum/team/darkspawn/antag_team
///How much willpower is granted by this tumor
var/willpower_amount = 1
/obj/item/organ/shadowtumor/New()
..()
@@ -22,9 +22,6 @@
..()
/obj/item/organ/shadowtumor/process()
if(!isthrall(owner))
qdel(src)
return
if(isturf(loc))
var/turf/T = loc
var/light_count = T.get_lumcount()
@@ -37,12 +34,31 @@
qdel(src)
else
organ_health = min(organ_health+0.5, 3)
if(owner && owner.stat != DEAD && antag_team)
antag_team.willpower_progress(willpower_amount)
/obj/item/organ/shadowtumor/on_find(mob/living/finder)
. = ..()
finder.visible_message(span_danger("[finder] opens up [owner]'s skull, revealing a pulsating black mass, with red tendrils attaching it to [owner.p_their()] brain."))
/obj/item/organ/shadowtumor/proc/resist(mob/living/carbon/M)
////////////////////////////////////////////////////////////////////////////////////
//------------------------------Thrall version------------------------------------//
////////////////////////////////////////////////////////////////////////////////////
/obj/item/organ/shadowtumor/thrall
//provides extra willpower because willpower was spent to thrall someone
willpower_amount = 2
///adds a cooldown to the resist so a thrall ipc or preternis can't weaponize it
COOLDOWN_DECLARE(resist_cooldown)
///How long the resist cooldown is
var/cooldown_length = 15 SECONDS
/obj/item/organ/shadowtumor/thrall/process()
if(!isthrall(owner))
qdel(src)
return
return ..()
/obj/item/organ/shadowtumor/thrall/proc/resist(mob/living/carbon/M)
if(QDELETED(src))
return FALSE
if(!(M.stat == CONSCIOUS))//Thralls cannot be deconverted while awake

View File

@@ -8,6 +8,10 @@
var/list/datum/mind/thralls = list()
///The number of drains required to perform the sacrament
var/required_succs = 10 //How many succs are needed (this is changed in pre_setup, so it scales based on pop)
///How much progress towards generating a willpower via tumors
var/current_willpower_progress = 0
///How much progress until another willpower is awarded
var/max_willpower_progress = 100
///How many drains have happened so far
var/lucidity = 0
///The max number of people that can be actively converted
@@ -109,13 +113,19 @@
////////////////////////////////////////////////////////////////////////////////////
//-----------------------------Special antag procs--------------------------------//
////////////////////////////////////////////////////////////////////////////////////
/datum/team/darkspawn/proc/grant_willpower(amount = 1, silent = FALSE)
/datum/team/darkspawn/proc/willpower_progress(amount = 1)
current_willpower_progress += amount
if(current_willpower_progress >= max_willpower_progress)
current_willpower_progress -= max_willpower_progress
max_willpower_progress *= 1.1 //gets harder to get more willpower with every willpower granted to reduce snowballing
grant_willpower(1)
//give a willpower to every darkspawn on the team
/datum/team/darkspawn/proc/grant_willpower(amount = 1)
for(var/datum/mind/master in members)
if(master.has_antag_datum(/datum/antagonist/darkspawn)) //sanity check
var/datum/antagonist/darkspawn/antag = master.has_antag_datum(/datum/antagonist/darkspawn)
antag.willpower += amount
if(!silent && master.current)
to_chat(master.current, span_velvet("You have gained [amount] willpower."))
/datum/team/darkspawn/proc/grant_lucidity(amount = 1)
lucidity += amount

View File

@@ -1,3 +1,15 @@
/**
* Helper proc to check if someone has a shadow tumor
*/
/proc/get_shadow_tumor(mob/living/source)
if(!istype(source))
return
var/obj/item/organ/tumor = source.getorganslot(ORGAN_SLOT_BRAIN_TUMOR)
if(!tumor || !istype(tumor, /obj/item/organ/shadowtumor)) //if they somehow lose their tumor in an unusual way
return
return tumor
/datum/antagonist/thrall
name = "Darkspawn Thrall"
job_rank = ROLE_DARKSPAWN
@@ -7,10 +19,6 @@
antag_moodlet = /datum/mood_event/thrall
///The abilities granted to the thrall
var/list/abilities = list(/datum/action/cooldown/spell/toggle/nightvision, /datum/action/cooldown/spell/pointed/darkspawn_build/thrall_eye/thrall)
///How many ticks towards willpower generation has happened so far
var/current_willpower_progress = 0
///Amount of progress required to generate willpower, increases every time
var/current_willpower_max = 80
///The darkspawn team that the thrall is on
var/datum/team/darkspawn/team
@@ -70,10 +78,12 @@
new_spell.Grant(current_mob)
if(isliving(current_mob))
var/obj/item/organ/shadowtumor/ST = current_mob.getorganslot(ORGAN_SLOT_BRAIN_TUMOR)
var/obj/item/organ/shadowtumor/thrall/ST = current_mob.getorganslot(ORGAN_SLOT_BRAIN_TUMOR)
if(!ST || !istype(ST))
ST = new
ST.Insert(current_mob, FALSE, FALSE)
if(team)
ST.antag_team = team
/datum/antagonist/thrall/remove_innate_effects(mob/living/mob_override)
var/mob/living/current_mob = mob_override || owner.current
@@ -94,8 +104,8 @@
if(spells.type in abilities)//no keeping your abilities
spells.Remove(current_mob)
qdel(spells)
var/obj/item/organ/tumor = current_mob.getorganslot(ORGAN_SLOT_BRAIN_TUMOR)
if(tumor && istype(tumor, /obj/item/organ/shadowtumor))
var/obj/item/organ/tumor = get_shadow_tumor(current_mob)
if(tumor)
qdel(tumor)
current_mob.update_sight()
@@ -132,33 +142,13 @@
overlays += overlay
////////////////////////////////////////////////////////////////////////////////////
//--------------------------Passive willpower gen---------------------------------//
//-----------Check if the thrall has a tumor, if not, dethrall them---------------//
////////////////////////////////////////////////////////////////////////////////////
/datum/antagonist/thrall/proc/thrall_life(mob/living/source, seconds_per_tick, times_fired)
if(!source || source.stat == DEAD)
return
var/obj/item/organ/tumor = source.getorganslot(ORGAN_SLOT_BRAIN_TUMOR)
if(!tumor || !istype(tumor, /obj/item/organ/shadowtumor)) //if they somehow lose their tumor in an unusual way
if(!get_shadow_tumor(source)) //if they somehow lose their tumor in an unusual way
source.remove_thrall()
return
var/found_other = FALSE
for(var/mob/living/thing in range(10, source))
if(!thing.client) //gotta be an actual player (hope no one goes afk)
continue
if(is_team_darkspawn(thing))
continue
if(!can_see(source, thing, 10))
continue
found_other = TRUE
if(found_other)
current_willpower_progress += seconds_per_tick
if(current_willpower_progress >= current_willpower_max)
current_willpower_max *= 2
current_willpower_progress = 0
team.grant_willpower(1, TRUE)
////////////////////////////////////////////////////////////////////////////////////
//-------------------------------Antag greet--------------------------------------//