From 565a5882ff6f83a90799f152f491c87158f8fdc8 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 2 Aug 2023 22:23:58 -0500 Subject: [PATCH 001/756] start of WORK --- code/__DEFINES/{yogs_defines}/mobs.dm | 3 - yogstation.dme | 2 + .../game/gamemodes/darkspawn/shadow_step.dm | 23 +++++++ .../game/gamemodes/darkspawn/shadow_store.dm | 43 +++++++++++++ .../antagonists/darkspawn/darkspawn.dm | 1 + .../carbon/human/species_types/darkspawn.dm | 60 ++++++++----------- 6 files changed, 93 insertions(+), 39 deletions(-) create mode 100644 yogstation/code/game/gamemodes/darkspawn/shadow_step.dm create mode 100644 yogstation/code/game/gamemodes/darkspawn/shadow_store.dm diff --git a/code/__DEFINES/{yogs_defines}/mobs.dm b/code/__DEFINES/{yogs_defines}/mobs.dm index ef4f0e0aaf6f..cbe1ac1f9f0b 100644 --- a/code/__DEFINES/{yogs_defines}/mobs.dm +++ b/code/__DEFINES/{yogs_defines}/mobs.dm @@ -10,7 +10,4 @@ #define DARKSPAWN_DIM_LIGHT 0.2 //light of this intensity suppresses healing and causes very slow burn damage #define DARKSPAWN_BRIGHT_LIGHT 0.3 //light of this intensity causes rapid burn damage - #define DARKSPAWN_DARK_HEAL 5 //how much damage of each type (with fire damage half rate) is healed in the dark -#define DARKSPAWN_LIGHT_BURN 7 //how much damage the darkspawn receives per tick in lit areas - #define MONKIFY_BLOOD_COEFFICIENT (BLOOD_VOLUME_MONKEY/BLOOD_VOLUME_GENERIC) //the ratio of monkey to human blood volume so a 100% blood volume monkey will not instantly die when you turn it into a human with ~58% blood volume diff --git a/yogstation.dme b/yogstation.dme index 4caf9b9031ab..43618b31b9bb 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3823,6 +3823,8 @@ #include "yogstation\code\game\gamemodes\clown_ops\bananium_bomb.dm" #include "yogstation\code\game\gamemodes\darkspawn\darkspawn.dm" #include "yogstation\code\game\gamemodes\darkspawn\darkspawn_hud.dm" +#include "yogstation\code\game\gamemodes\darkspawn\shadow_step.dm" +#include "yogstation\code\game\gamemodes\darkspawn\shadow_store.dm" #include "yogstation\code\game\gamemodes\darkspawn\veil.dm" #include "yogstation\code\game\gamemodes\gangs\dominator.dm" #include "yogstation\code\game\gamemodes\gangs\gang_items.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm new file mode 100644 index 000000000000..4de8f8b63fe1 --- /dev/null +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm @@ -0,0 +1,23 @@ +/datum/component/shadow_step + dupe_mode = COMPONENT_DUPE_ALLOWED + + var/speedboost = -1 + +/datum/component/shadow_step/Initialize() + if(!ishuman(parent)) + return COMPONENT_INCOMPATIBLE + +/datum/component/shadow_step/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(apply_darkness_speed)) + +/datum/component/shadow_step/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_MOVABLE_PRE_MOVE) + C.remove_movespeed_modifier(type) + +/datum/component/shadow_step/proc/apply_darkness_speed() + var/turf/T = get_turf(parent) + var/light_amount = T.get_lumcount() + if(light_amount > DARKSPAWN_BRIGHT_LIGHT) + parent.remove_movespeed_modifier(type) + else + parent.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=speedboost, blacklisted_movetypes=(FLYING|FLOATING)) diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm new file mode 100644 index 000000000000..183dd04fef6c --- /dev/null +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm @@ -0,0 +1,43 @@ + +#define SCOUT (1<<0) +#define FIGHTER (1<<1) +#define WARLOCK (1<<2) + +/datum/shadow_store + ///Name of the effect + var/name = "Basic knowledge" + ///Description of the effect + var/desc = "Basic knowledge of forbidden arts." + ///Icon that gets displayed + var/icon = "" + ///Cost of knowledge in souls + var/cost = 0 + ///What specialization can buy this + var/shadow_flags = NONE + +///Check to see if they should be shown the ability +/datum/shadow_store/proc/check_show(mob/user) + SHOULD_CALL_PARENT(TRUE) //for now + var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(!edgy) + return FALSE + if(!(edgy.specialization & shadow_flags)) + return FALSE + return TRUE + +///When the button to purchase is clicked +/datum/shadow_store/proc/on_purchase(mob/user) + var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(!edgy) + return FALSE + if(!(edgy.specialization & shadow_flags))//they shouldn't even be shown it in the first place, but just in case + return FALSE + if(edgy.lucidity < cost) + return FALSE + + edgy.lucidity -= cost + activate(user) + return TRUE + +///If the purchase goes through, this gets called +/datum/shadow_store/proc/activate(mob/user) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index efce18199e62..184b433e7d20 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -31,6 +31,7 @@ var/datum/antag_menu/psi_web/psi_web //Antag menu used for opening the UI var/datum/action/innate/darkspawn/psi_web/psi_web_action //Used to link the menu with our antag datum + var/specialization = NONE // Antagonist datum things like assignment // diff --git a/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm b/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm index 6d9808c035f0..ca2809c15057 100644 --- a/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm +++ b/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm @@ -14,10 +14,11 @@ species_traits = list(NOBLOOD,NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYESPRITES,NOFLASH) inherent_traits = list(TRAIT_NOGUNS, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE, TRAIT_NOBREATH, TRAIT_RADIMMUNE, TRAIT_VIRUSIMMUNE, TRAIT_PIERCEIMMUNE, TRAIT_NODISMEMBER, TRAIT_NOHUNGER) mutanteyes = /obj/item/organ/eyes/night_vision/alien - var/list/upgrades = list() COOLDOWN_DECLARE(reflect_cd_1) COOLDOWN_DECLARE(reflect_cd_2) COOLDOWN_DECLARE(reflect_cd_3) + var/dark_healing = 5 + var/light_burning = 7 /datum/species/darkspawn/bullet_act(obj/projectile/P, mob/living/carbon/human/H) if(prob(50) && (COOLDOWN_FINISHED(src, reflect_cd_1) || COOLDOWN_FINISHED(src, reflect_cd_2) || COOLDOWN_FINISHED(src, reflect_cd_3))) @@ -45,45 +46,32 @@ C.bubble_icon = initial(C.bubble_icon) /datum/species/darkspawn/spec_life(mob/living/carbon/human/H) - handle_upgrades(H) H.bubble_icon = "darkspawn" var/turf/T = H.loc if(istype(T)) var/light_amount = T.get_lumcount() - if(light_amount < DARKSPAWN_DIM_LIGHT) //rapid healing and stun reduction in the darkness - var/healing_amount = DARKSPAWN_DARK_HEAL - if(upgrades["dark_healing"]) - healing_amount *= 1.25 - H.adjustBruteLoss(-healing_amount) - H.adjustFireLoss(-healing_amount) - H.adjustToxLoss(-healing_amount) - H.adjustStaminaLoss(-healing_amount * 20) - H.AdjustStun(-healing_amount * 40) - H.AdjustKnockdown(-healing_amount * 40) - H.AdjustUnconscious(-healing_amount * 40) - H.SetSleeping(0) - H.setOrganLoss(ORGAN_SLOT_BRAIN,0) - H.setCloneLoss(0) - else if(light_amount < DARKSPAWN_BRIGHT_LIGHT && !upgrades["light_resistance"]) //not bright, but still dim - H.adjustFireLoss(1) - else if(light_amount > DARKSPAWN_BRIGHT_LIGHT && !H.has_status_effect(STATUS_EFFECT_CREEP)) //but quick death in the light - if(upgrades["spacewalking"] && isspaceturf(T)) - return - else if(!upgrades["light_resistance"]) - to_chat(H, span_userdanger("The light burns you!")) - H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) - H.adjustFireLoss(DARKSPAWN_LIGHT_BURN) - else - to_chat(H, span_userdanger("The light singes you!")) - H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 50 * light_amount), TRUE) - H.adjustFireLoss(DARKSPAWN_LIGHT_BURN * 0.5) + switch(light_amount) + if(0 to DARKSPAWN_DIM_LIGHT) //rapid healing and stun reduction in the darkness + H.adjustBruteLoss(-dark_healing) + H.adjustFireLoss(-dark_healing) + H.adjustToxLoss(-dark_healing) + H.adjustStaminaLoss(-dark_healing * 20) + H.AdjustStun(-dark_healing * 40) + H.AdjustKnockdown(-dark_healing * 40) + H.AdjustUnconscious(-dark_healing * 40) + H.adjustCloneLoss(-dark_healing) + H.SetSleeping(0) + H.setOrganLoss(ORGAN_SLOT_BRAIN,0) + if(DARKSPAWN_DIM_LIGHT to DARKSPAWN_BRIGHT_LIGHT) //not bright, but still dim + if(!H.has_status_effect(STATUS_EFFECT_CREEP)) + to_chat(H, span_userdanger("The light singes you!")) + H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 40 * light_amount), TRUE) + H.adjustCloneLoss(light_burning * 0.2) + if(DARKSPAWN_BRIGHT_LIGHT to DARKSPAWN_BRIGHT_LIGHT) //but quick death in the light + if(!H.has_status_effect(STATUS_EFFECT_CREEP)) + to_chat(H, span_userdanger("The light burns you!")) + H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) + H.adjustCloneLoss(light_burning) /datum/species/darkspawn/spec_death(gibbed, mob/living/carbon/human/H) playsound(H, 'yogstation/sound/creatures/darkspawn_death.ogg', 50, FALSE) - -/datum/species/darkspawn/proc/handle_upgrades(mob/living/carbon/human/H) - var/datum/antagonist/darkspawn/darkspawn - if(H.mind) - darkspawn = H.mind.has_antag_datum(/datum/antagonist/darkspawn) - if(darkspawn) - upgrades = darkspawn.upgrades From b58bb21b05a7de0a2078fd2a1f52ed693ce54132 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 2 Aug 2023 22:32:48 -0500 Subject: [PATCH 002/756] store --- .../game/gamemodes/darkspawn/shadow_step.dm | 2 -- .../game/gamemodes/darkspawn/shadow_store.dm | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm index 4de8f8b63fe1..529dcaa20616 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm @@ -1,6 +1,4 @@ /datum/component/shadow_step - dupe_mode = COMPONENT_DUPE_ALLOWED - var/speedboost = -1 /datum/component/shadow_step/Initialize() diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm index 183dd04fef6c..a297b3fd0936 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm @@ -41,3 +41,38 @@ ///If the purchase goes through, this gets called /datum/shadow_store/proc/activate(mob/user) + return + + +/* + Purchases to select spec +*/ +/datum/shadow_store/scout + name = "shadow step" + desc = "shadow step" + +/datum/shadow_store/scout/activate(mob/user) + user.LoadComponent(/datum/component/walk/shadow) + user.AddComponent(/datum/component/shadow_step) + var/datum/antagonist/darkspawn/edgy = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(edgy)//there's NO way they get here without it + edgy.specialization = SCOUT + + +/datum/shadow_store/fighter + name = "shadow step" + desc = "shadow step" + +/datum/shadow_store/fighter/activate(mob/user) + var/datum/antagonist/darkspawn/edgy = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(edgy)//there's NO way they get here without it + edgy.specialization = FIGHTER + +/datum/shadow_store/warlock + name = "shadow step" + desc = "shadow step" + +/datum/shadow_store/warlock/activate(mob/user) + var/datum/antagonist/darkspawn/edgy = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(edgy)//there's NO way they get here without it ... right? + edgy.specialization = WARLOCK From 958af0d0a4f1e13c13d2e95f4649aac6527bef3b Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 3 Aug 2023 18:12:43 -0500 Subject: [PATCH 003/756] more work --- yogstation.dme | 1 - .../game/gamemodes/darkspawn/shadow_store.dm | 107 ++++++++++- .../antagonists/darkspawn/crawling_shadows.dm | 1 - .../antagonists/darkspawn/darkspawn.dm | 178 +++--------------- .../darkspawn_abilities/__psi_web.dm | 91 --------- .../darkspawn/darkspawn_abilities/_divulge.dm | 1 - .../darkspawn_abilities/_sacrament.dm | 1 - .../darkspawn/darkspawn_abilities/creep.dm | 1 - .../darkspawn_abilities/devour_will.dm | 1 - .../darkspawn/darkspawn_abilities/pass.dm | 1 - .../darkspawn/darkspawn_abilities/tagalong.dm | 1 - .../darkspawn/darkspawn_ability.dm | 2 - 12 files changed, 134 insertions(+), 252 deletions(-) delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/__psi_web.dm diff --git a/yogstation.dme b/yogstation.dme index 43618b31b9bb..2f8ea9966b48 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3970,7 +3970,6 @@ #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_ability.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_progenitor.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrade.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\__psi_web.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_divulge.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_sacrament.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\crawling_shadows.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm index a297b3fd0936..df30751b9ee2 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm @@ -3,6 +3,82 @@ #define FIGHTER (1<<1) #define WARLOCK (1<<2) +//Used to access the Psi Web to buy abilities. +//Accesses the Psi Web, which darkspawn use to purchase abilities using lucidity. Lucidity is drained from people using the Devour Will ability. +/datum/antag_menu/shadow_store + name = "psi web" + ui_name = "PsiWeb" + +/datum/antag_menu/shadow_store/ui_data(mob/user) + var/list/data = list() + var/datum/antagonist/darkspawn/darkspawn = antag_datum + + if(!istype(darkspawn)) + CRASH("darkspawn menu started with wrong datum.") + + data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / [darkspawn.lucidity_needed] unique drained total" + + var/list/upgrades = list() + + for(var/path in subtypesof(/datum/shadow_store)) + var/datum/shadow_store/selection = path + + if(!selection.check_show(user)) + continue + + var/list/AL = list() + AL["name"] = initial(selection.name) + AL["desc"] = initial(selection.desc) + AL["psi_cost"] = initial(selection.psi_cost) + AL["lucidity_cost"] = initial(ability.lucidity_price) + AL["can_purchase"] = darkspawn.lucidity >= initial(ability.lucidity_price) + + upgrades += list(AL) + + data["upgrades"] = upgrades + + return data + +/datum/antag_menu/shadow_store/ui_act(action, params) + if(..()) + return + var/datum/antagonist/darkspawn/darkspawn = antag_datum + switch(action) + if("purchase") + if(istype(params["id"], /datum/shadow_store)) + var/datum/shadow_store/selected = params["id"] + selected.on_purchase(darkspawn?.owner?.current) + +//ability for using the shadow store +/datum/action/innate/darkspawn/shadow_store + name = "Psi Web" + id = "psi_web" + desc = "Access the Mindlink directly to unlock and upgrade your supernatural powers." + button_icon_state = "psi_web" + check_flags = AB_CHECK_CONSCIOUS + psi_cost = 0 + var/datum/antag_menu/psi_web/psi_web + +/datum/action/innate/darkspawn/shadow_store/New(our_target) + . = ..() + if(istype(our_target, /datum/antag_menu/psi_web)) + psi_web = our_target + else + CRASH("psi_web action created with non web.") + +/datum/action/innate/darkspawn/shadow_store/Destroy() + psi_web = null + return ..() + +/datum/action/innate/darkspawn/shadow_store/Activate() + if(!darkspawn) + return + to_chat(usr, "You retreat inwards and touch the Mindlink...") + psi_web.ui_interact(usr) + return TRUE + + +//shadow store datums (upgrades and abilities) /datum/shadow_store ///Name of the effect var/name = "Basic knowledge" @@ -10,10 +86,16 @@ var/desc = "Basic knowledge of forbidden arts." ///Icon that gets displayed var/icon = "" - ///Cost of knowledge in souls - var/cost = 0 + ///Cost of to learn this + var/lucidity_cost = 0 + ///Cost of to cast this + var/psi_cost = 0 ///What specialization can buy this var/shadow_flags = NONE + ///what ability is granted if any + var/learned_ability + ///what is printed when learned + var/learn_text ///Check to see if they should be shown the ability /datum/shadow_store/proc/check_show(mob/user) @@ -23,6 +105,8 @@ return FALSE if(!(edgy.specialization & shadow_flags)) return FALSE + if(edgy.has_upgrade(name))//if they already have it + return FALSE return TRUE ///When the button to purchase is clicked @@ -35,14 +119,31 @@ if(edgy.lucidity < cost) return FALSE + if(learn_text) + to_chat(user, span_velvet(learn_text)) + edgy.add_upgrade(name) edgy.lucidity -= cost activate(user) return TRUE ///If the purchase goes through, this gets called /datum/shadow_store/proc/activate(mob/user) - return + var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(!edgy) + return + if(learned_ability) + var/datum/action/innate/darkspawn/action = new learned_ability + action.Grant(user) +///if for whatever reason the ability needs to be removed +/datum/shadow_store/proc/remove(mob/user) + var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(!edgy) + return + edgy.remove_upgrade(name) + if(learned_ability) + var/datum/action/innate/darkspawn/action = new learned_ability + action.Remove(user) /* Purchases to select spec diff --git a/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm b/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm index ee01d084a31d..030822f3fd1a 100644 --- a/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm +++ b/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm @@ -121,7 +121,6 @@ id = "end_shadows" desc = "Reverts you to your humanoid form." button_icon_state = "crawling_shadows" - blacklisted = TRUE /datum/action/innate/darkspawn/end_shadows/Activate() qdel(owner) //edgi diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 184b433e7d20..e7157e684652 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -24,12 +24,12 @@ //Lucidity variables var/lucidity = 3 //Lucidity is used to buy abilities and is gained by using Devour Will var/lucidity_drained = 0 //How much lucidity has been drained from unique players + var/lucidity_needed = 20 //how much lucidity is needed to win - //Ability and upgrade variables - var/list/abilities = list() //An associative list ("id" = ability datum) containing the abilities the darkspawn has + //upgrade variables var/list/upgrades = list() //An associative list ("id" = null or TRUE) containing the passive upgrades the darkspawn has - var/datum/antag_menu/psi_web/psi_web //Antag menu used for opening the UI - var/datum/action/innate/darkspawn/psi_web/psi_web_action //Used to link the menu with our antag datum + var/datum/antag_menu/shadow_store/shadow_store //Antag menu used for opening the UI + var/datum/action/innate/darkspawn/shadow_Store/shadow_store_action //Used to link the menu with our antag datum var/specialization = NONE @@ -40,7 +40,9 @@ owner.special_role = "darkspawn" owner.current.hud_used.psi_counter.invisibility = 0 update_psi_hud() - add_ability("divulge") + var/datum/action/innate/darkspawn/divulge/action = new() + action.Grant(owner.current) + action.darkspawn = src addtimer(CALLBACK(src, PROC_REF(begin_force_divulge)), 23 MINUTES) //this won't trigger if they've divulged when the proc runs START_PROCESSING(SSprocessing, src) var/datum/objective/darkspawn/O = new @@ -91,93 +93,12 @@ //Admin panel stuff /datum/antagonist/darkspawn/antag_panel_data() - . = "Abilities:
" - for(var/V in abilities) - var/datum/action/innate/darkspawn/D = has_ability(V) - if(D && istype(D)) - . += "[D.name] ([D.id])
" - . += "
Upgrades:
" + . = "Upgrades:
" for(var/V in upgrades) . += "[V]
" -/datum/antagonist/darkspawn/get_admin_commands() - . = ..() - .["Give Ability"] = CALLBACK(src, PROC_REF(admin_give_ability)) - .["Take Ability"] = CALLBACK(src, PROC_REF(admin_take_ability)) - if(darkspawn_state == MUNDANE) - .["Divulge"] = CALLBACK(src, PROC_REF(divulge)) - .["Force-Divulge (Obvious)"] = CALLBACK(src, PROC_REF(force_divulge)) - else if(darkspawn_state == DIVULGED) - .["Give Upgrade"] = CALLBACK(src, PROC_REF(admin_give_upgrade)) - .["[psi]/[psi_cap] Psi"] = CALLBACK(src, PROC_REF(admin_edit_psi)) - .["[lucidity] Lucidity"] = CALLBACK(src, PROC_REF(admin_edit_lucidity)) - .["[lucidity_drained] / [SSticker.mode.required_succs] Unique Lucidity"] = CALLBACK(src, PROC_REF(admin_edit_lucidity_drained)) - .["Sacrament (ENDS THE ROUND)"] = CALLBACK(src, PROC_REF(sacrament)) - -/datum/antagonist/darkspawn/proc/admin_give_ability(mob/admin) - var/id = stripped_input(admin, "Enter an ability ID, for \"all\" to give all of them.", "Give Ability") - if(!id) - return - if(has_ability(id)) - to_chat(admin, span_warning("[owner.current] already has this ability!")) - return - if(id != "all") - add_ability(id) - to_chat(admin, span_notice("Gave [owner.current] the ability \"[id]\".")) - else - for(var/V in subtypesof(/datum/action/innate/darkspawn)) - var/datum/action/innate/darkspawn/D = V - if(!has_ability(initial(D.id)) && !initial(D.blacklisted)) - add_ability(initial(D.id)) - to_chat(admin, span_notice("Gave [owner.current] all abilities.")) - -/datum/antagonist/darkspawn/proc/admin_take_ability(mob/admin) - var/id = stripped_input(admin, "Enter an ability ID.", "Take Ability") - if(!id) - return - if(!has_ability(id)) - to_chat(admin, span_warning("[owner.current] does not have this ability!")) - return - remove_ability(id) - to_chat(admin, span_danger("Took from [owner.current] the ability \"[id]\".")) - -/datum/antagonist/darkspawn/proc/admin_give_upgrade(mob/admin) - var/id = stripped_input(admin, "Enter an upgrade ID, for \"all\" to give all of them.", "Give Upgrade") - if(!id) - return - if(has_upgrade(id)) - to_chat(admin, span_warning("[owner.current] already has this upgrade!")) - return - if(id != "all") - add_upgrade(id) - to_chat(admin, span_notice("Gave [owner.current] the upgrade \"[id]\".")) - else - for(var/V in subtypesof(/datum/darkspawn_upgrade)) - var/datum/darkspawn_upgrade/D = V - if(!has_upgrade(initial(D.id))) - add_upgrade(initial(D.id)) - to_chat(admin, span_notice("Gave [owner.current] all upgrades.")) - -/datum/antagonist/darkspawn/proc/admin_edit_psi(mob/admin) - var/new_psi = input(admin, "Enter a new psi amount. (Current: [psi]/[psi_cap])", "Change Psi", psi) as null|num - if(!new_psi) - return - new_psi = clamp(new_psi, 0, psi_cap) - psi = new_psi - -/datum/antagonist/darkspawn/proc/admin_edit_lucidity(mob/admin) - var/newcidity = input(admin, "Enter a new lucidity amount. (Current: [lucidity])", "Change Lucidity", lucidity) as null|num - if(!newcidity) - return - newcidity = max(0, newcidity) - lucidity = newcidity - -/datum/antagonist/darkspawn/proc/admin_edit_lucidity_drained(mob/admin) - var/newcidity = input(admin, "Enter a new lucidity amount. (Current: [lucidity_drained])", "Change Lucidity Drained", lucidity_drained) as null|num - if(!newcidity) - return - newcidity = max(0, newcidity) - lucidity_drained = newcidity +//i have deleted all admin procs because i don't want to have to worry about those while reworking it, they can be added in a later PR +//i'm making this rework for the players (and for me) not the admins /datum/antagonist/darkspawn/greet() to_chat(owner.current, "You are a darkspawn!") @@ -245,61 +166,27 @@ var/atom/movable/screen/counter = owner.current.hud_used.psi_counter counter.maptext = ANTAG_MAPTEXT(psi, COLOR_DARKSPAWN_PSI) -/datum/antagonist/darkspawn/proc/regain_abilities() - for(var/A in abilities) - var/datum/action/innate/darkspawn/ability = abilities[A] - if(ability) - ability.Remove(ability.owner) - ability.Grant(owner.current) +/datum/antagonist/darkspawn/proc/regain_upgrades() + for(var/A in upgrades) + var/datum/shadow_store/upgrade = upgrades[A] + if(upgrade) + upgrade.remove(owner.current) + upgrade.activate(owner.current) -/datum/antagonist/darkspawn/proc/has_ability(id) - if(isnull(abilities[id])) - return - return abilities[id] +/datum/antagonist/darkspawn/proc/has_upgrade(id) + return upgrades[id] -/datum/antagonist/darkspawn/proc/add_ability(id, silent, no_cost) +/datum/antagonist/darkspawn/proc/add_upgrade(id) if(has_ability(id)) - return - for(var/V in subtypesof(/datum/action/innate/darkspawn)) - var/datum/action/innate/darkspawn/D = V - if(initial(D.id) == id) - var/datum/action/innate/darkspawn/action = new D - action.Grant(owner.current) - action.darkspawn = src - abilities[id] = action - if(!silent) - to_chat(owner.current, span_velvet("You have learned the [action.name] ability.")) - if(!no_cost) - lucidity = max(0, lucidity - action.lucidity_price) - return TRUE - -/datum/antagonist/darkspawn/proc/remove_ability(id, silent) - if(!has_ability(id)) - return - var/datum/action/innate/darkspawn/D = abilities[id] - if(!silent) - to_chat(owner.current, span_velvet("You have lost the [D.name] ability.")) - D.Remove(owner.current) - abilities -= D - QDEL_NULL(D) + return FALSE + upgrades[id] = id return TRUE -/datum/antagonist/darkspawn/proc/has_upgrade(id) - return upgrades[id] - -/datum/antagonist/darkspawn/proc/add_upgrade(id, silent, no_cost) - if(has_upgrade(id)) - return - for(var/V in subtypesof(/datum/darkspawn_upgrade)) - var/datum/darkspawn_upgrade/_U = V - if(initial(_U.id) == id) - var/datum/darkspawn_upgrade/U = new _U(src) - upgrades[id] = TRUE - if(!silent) - to_chat(owner.current, "You have adapted the \"[U.name]\" upgrade.") - if(!no_cost) - lucidity = max(0, lucidity - initial(U.lucidity_price)) - U.unlock() +/datum/antagonist/darkspawn/proc/remove_upgrade(id) + if(!has_ability(id)) + return FALSE + upgrades -= id + return TRUE /datum/antagonist/darkspawn/proc/begin_force_divulge() if(darkspawn_state != MUNDANE) @@ -340,15 +227,10 @@ user.fully_heal() user.set_species(/datum/species/darkspawn) show_to_ghosts = TRUE - //Handles psi_web granting, has to be different to fulfill everything - psi_web = new(src) - psi_web_action = new(psi_web) - psi_web_action.Grant(owner.current) - psi_web_action.darkspawn = src - abilities[psi_web_action.id] = psi_web_action - add_ability("sacrament", TRUE) - add_ability("devour_will", TRUE) - add_ability("pass", TRUE) + shadow_store = new(src) + shadow_store_action = new(shadow_store) + shadow_store_action.Grant(owner.current) + shadow_store_action.darkspawn = src remove_ability("divulge", TRUE) darkspawn_state = DIVULGED diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/__psi_web.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/__psi_web.dm deleted file mode 100644 index 3b46959fd6e4..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/__psi_web.dm +++ /dev/null @@ -1,91 +0,0 @@ -//Used to access the Psi Web to buy abilities. -//Accesses the Psi Web, which darkspawn use to purchase abilities using lucidity. Lucidity is drained from people using the Devour Will ability. -/datum/antag_menu/psi_web - name = "psi web" - ui_name = "PsiWeb" - -/datum/antag_menu/psi_web/ui_data(mob/user) - var/list/data = list() - var/datum/antagonist/darkspawn/darkspawn = antag_datum - - if(!istype(darkspawn)) - CRASH("darkspawn menu started with wrong datum.") - - data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / 20 unique drained total" - - var/list/abilities = list() - var/list/upgrades = list() - - for(var/path in subtypesof(/datum/action/innate/darkspawn)) - var/datum/action/innate/darkspawn/ability = path - - if(initial(ability.blacklisted)) - continue - - var/list/AL = list() //This is mostly copy-pasted from the cellular emporium, but it should be fine regardless - AL["name"] = initial(ability.name) - AL["id"] = initial(ability.id) - AL["desc"] = initial(ability.desc) - AL["psi_cost"] = "[initial(ability.psi_cost)][initial(ability.psi_addendum)]" - AL["lucidity_cost"] = initial(ability.lucidity_price) - AL["owned"] = darkspawn.has_ability(initial(ability.id)) - AL["can_purchase"] = !AL["owned"] && darkspawn.lucidity >= initial(ability.lucidity_price) - - abilities += list(AL) - - data["abilities"] = abilities - - for(var/path in subtypesof(/datum/darkspawn_upgrade)) - var/datum/darkspawn_upgrade/upgrade = path - - var/list/DE = list() - DE["name"] = initial(upgrade.name) - DE["id"] = initial(upgrade.id) - DE["desc"] = initial(upgrade.desc) - DE["lucidity_cost"] = initial(upgrade.lucidity_price) - DE["owned"] = darkspawn.has_upgrade(initial(upgrade.id)) - DE["can_purchase"] = !DE["owned"] && darkspawn.lucidity >= initial(upgrade.lucidity_price) - - upgrades += list(DE) - - data["upgrades"] = upgrades - - return data - -/datum/antag_menu/psi_web/ui_act(action, params) - if(..()) - return - var/datum/antagonist/darkspawn/darkspawn = antag_datum - switch(action) - if("unlock") - darkspawn.add_ability(params["id"]) - if("upgrade") - darkspawn.add_upgrade(params["id"]) - -/datum/action/innate/darkspawn/psi_web - name = "Psi Web" - id = "psi_web" - desc = "Access the Mindlink directly to unlock and upgrade your supernatural powers." - button_icon_state = "psi_web" - check_flags = AB_CHECK_CONSCIOUS - blacklisted = TRUE - psi_cost = 0 - var/datum/antag_menu/psi_web/psi_web - -/datum/action/innate/darkspawn/psi_web/New(our_target) - . = ..() - if(istype(our_target, /datum/antag_menu/psi_web)) - psi_web = our_target - else - CRASH("psi_web action created with non web.") - -/datum/action/innate/darkspawn/psi_web/Destroy() - psi_web = null - return ..() - -/datum/action/innate/darkspawn/psi_web/Activate() - if(!darkspawn) - return - to_chat(usr, "You retreat inwards and touch the Mindlink...") - psi_web.ui_interact(usr) - return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 4ce18f334fee..34daa3db78e7 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -5,7 +5,6 @@ desc = "Sheds your human disguise. This is obvious and so should be done in a secluded area. You cannot reverse this." button_icon_state = "divulge" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_LYING - blacklisted = TRUE /datum/action/innate/darkspawn/divulge/Activate() set waitfor = FALSE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index b6561a5d0fd4..a77db6a3e7e3 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -5,7 +5,6 @@ desc = "Ascends into a progenitor. Unless someone else has performed the Sacrament, you must have drained lucidity from 15-30 (check your objective) different people for this to work, and purchased all passive upgrades." button_icon_state = "sacrament" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS - blacklisted = TRUE //baseline var/datum/looping_sound/sacrament/soundloop /datum/action/innate/darkspawn/sacrament/Activate() diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/creep.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/creep.dm index 5887ec46ca63..b8404f43d6e3 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/creep.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/creep.dm @@ -6,7 +6,6 @@ button_icon_state = "creep" check_flags = AB_CHECK_CONSCIOUS psi_cost = 5 - psi_addendum = " to activate and per second" lucidity_price = 2 /datum/action/innate/darkspawn/creep/IsAvailable(feedback = FALSE) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm index b049adf68f3f..14ba6bf27645 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm @@ -7,7 +7,6 @@ button_icon_state = "devour_will" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_LYING | AB_CHECK_CONSCIOUS psi_cost = 5 - blacklisted = TRUE var/list/victims //A list of people we've used the bead on recently; we can't drain them again so soon var/last_victim diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index 014c3fb1b205..3c0f31d4f6e7 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -5,7 +5,6 @@ desc = "Twists an active arm into tendrils with many important uses. Examine the tendrils to see a list of uses." button_icon_state = "pass" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS - blacklisted = TRUE //baseline /datum/action/innate/darkspawn/pass/IsAvailable(feedback = FALSE) if(istype(owner, /mob/living/simple_animal/hostile/crawling_shadows) || istype(owner, /mob/living/simple_animal/hostile/darkspawn_progenitor) || !owner.get_empty_held_indexes() && !active) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm index 266a88842076..f03e3fb8df32 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm @@ -6,7 +6,6 @@ button_icon_state = "tagalong" check_flags = AB_CHECK_CONSCIOUS psi_cost = 30 - psi_addendum = ", but is free to cancel" lucidity_price = 2 var/datum/status_effect/tagalong/tagalong diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_ability.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_ability.dm index 06b5a9a63697..610b823ee583 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_ability.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_ability.dm @@ -8,9 +8,7 @@ buttontooltipstyle = "alien" var/psi_cost = 0 //How much psi the ability costs to use - var/psi_addendum = "" //If applicable, descriptive text shown after the cost var/lucidity_price = 0 //How much lucidity the ability costs to buy; if this is 0, it isn't listed on the catalog - var/blacklisted = FALSE //If the ability can't be gained from the psi web var/in_use = FALSE //For channeled/cast-time abilities var/datum/antagonist/darkspawn/darkspawn //Linked antag datum for drawing lucidity and psi From 69dc0fe85702a690257f093d8c5fbcc25b787ce7 Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 3 Aug 2023 18:21:46 -0500 Subject: [PATCH 004/756] psuedocode go brrrrr --- .../game/gamemodes/darkspawn/shadow_store.dm | 22 +++++++++---------- .../antagonists/darkspawn/darkspawn.dm | 16 +++++++++----- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm index df30751b9ee2..e4b0e8e92f86 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm @@ -30,8 +30,8 @@ AL["name"] = initial(selection.name) AL["desc"] = initial(selection.desc) AL["psi_cost"] = initial(selection.psi_cost) - AL["lucidity_cost"] = initial(ability.lucidity_price) - AL["can_purchase"] = darkspawn.lucidity >= initial(ability.lucidity_price) + AL["lucidity_cost"] = initial(selection.lucidity_price) + AL["can_purchase"] = darkspawn.lucidity >= initial(selection.lucidity_price) upgrades += list(AL) @@ -57,24 +57,24 @@ button_icon_state = "psi_web" check_flags = AB_CHECK_CONSCIOUS psi_cost = 0 - var/datum/antag_menu/psi_web/psi_web + var/datum/antag_menu/shadow_store/shadow_store /datum/action/innate/darkspawn/shadow_store/New(our_target) . = ..() - if(istype(our_target, /datum/antag_menu/psi_web)) - psi_web = our_target + if(istype(our_target, /datum/antag_menu/shadow_store)) + shadow_store = our_target else CRASH("psi_web action created with non web.") /datum/action/innate/darkspawn/shadow_store/Destroy() - psi_web = null + shadow_store = null return ..() /datum/action/innate/darkspawn/shadow_store/Activate() if(!darkspawn) return to_chat(usr, "You retreat inwards and touch the Mindlink...") - psi_web.ui_interact(usr) + shadow_store.ui_interact(usr) return TRUE @@ -116,13 +116,12 @@ return FALSE if(!(edgy.specialization & shadow_flags))//they shouldn't even be shown it in the first place, but just in case return FALSE - if(edgy.lucidity < cost) + if(edgy.lucidity < lucidity_cost) return FALSE if(learn_text) to_chat(user, span_velvet(learn_text)) - edgy.add_upgrade(name) - edgy.lucidity -= cost + edgy.lucidity -= lucidity_cost activate(user) return TRUE @@ -131,6 +130,7 @@ var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) if(!edgy) return + edgy.add_upgrade(src) if(learned_ability) var/datum/action/innate/darkspawn/action = new learned_ability action.Grant(user) @@ -140,7 +140,7 @@ var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) if(!edgy) return - edgy.remove_upgrade(name) + edgy.remove_upgrade(src) if(learned_ability) var/datum/action/innate/darkspawn/action = new learned_ability action.Remove(user) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index e7157e684652..6d1a373a8f2d 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -29,7 +29,7 @@ //upgrade variables var/list/upgrades = list() //An associative list ("id" = null or TRUE) containing the passive upgrades the darkspawn has var/datum/antag_menu/shadow_store/shadow_store //Antag menu used for opening the UI - var/datum/action/innate/darkspawn/shadow_Store/shadow_store_action //Used to link the menu with our antag datum + var/datum/action/innate/darkspawn/shadow_store/shadow_store_action //Used to link the menu with our antag datum var/specialization = NONE @@ -43,6 +43,7 @@ var/datum/action/innate/darkspawn/divulge/action = new() action.Grant(owner.current) action.darkspawn = src + upgrades += action addtimer(CALLBACK(src, PROC_REF(begin_force_divulge)), 23 MINUTES) //this won't trigger if they've divulged when the proc runs START_PROCESSING(SSprocessing, src) var/datum/objective/darkspawn/O = new @@ -177,13 +178,13 @@ return upgrades[id] /datum/antagonist/darkspawn/proc/add_upgrade(id) - if(has_ability(id)) + if(has_upgrade(id)) return FALSE upgrades[id] = id return TRUE /datum/antagonist/darkspawn/proc/remove_upgrade(id) - if(!has_ability(id)) + if(!has_upgrade(id)) return FALSE upgrades -= id return TRUE @@ -231,7 +232,8 @@ shadow_store_action = new(shadow_store) shadow_store_action.Grant(owner.current) shadow_store_action.darkspawn = src - remove_ability("divulge", TRUE) + if(/datum/action/innate/darkspawn/divulge in upgrades) + upgrades[/datum/action/innate/darkspawn/divulge].remove darkspawn_state = DIVULGED /datum/antagonist/darkspawn/proc/sacrament() @@ -239,8 +241,10 @@ if(!SSticker.mode.sacrament_done) set_security_level(SEC_LEVEL_GAMMA) addtimer(CALLBACK(src, PROC_REF(sacrament_shuttle_call)), 50) - for(var/V in abilities) - remove_ability(abilities[V], TRUE) + for(var/A in upgrades) + var/datum/shadow_store/upgrade = upgrades[A] + if(upgrade) + upgrade.remove(owner.current) for(var/datum/action/innate/darkspawn/leftover_ability in user.actions) leftover_ability.Remove(user) QDEL_NULL(leftover_ability) From b13c34b2ce75307682e9e962f31c6de27abfe23a Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 01:28:54 -0500 Subject: [PATCH 005/756] DELETE --- code/__DEFINES/role_preferences.dm | 2 - code/__DEFINES/span.dm | 1 - code/__DEFINES/{yogs_defines}/antagonists.dm | 3 +- code/__DEFINES/{yogs_defines}/is_helpers.dm | 4 - code/datums/achievements/achievements.dm | 2 +- code/datums/mutations/body.dm | 1 - .../dynamic/dynamic_rulesets_roundstart.dm | 44 - code/game/objects/items/cardboard_cutouts.dm | 5 - code/modules/admin/sql_ban_system.dm | 2 +- code/modules/admin/topic.dm | 7 - code/modules/admin/verbs/one_click_antag.dm | 1 - .../antagonists/clockcult/clockcult.dm | 1 - code/modules/antagonists/cult/cult.dm | 1 - .../antagonists/revolution/revolution.dm | 1 - code/modules/events/darkspawn.dm | 2 +- code/modules/mob/living/living.dm | 1 - config/game_options.txt | 2 - yogstation.dme | 8 - .../game/gamemodes/shadowling/shadowling.dm | 274 ---- .../modules/admin/verbs/one_click_antag.dm | 30 +- .../shadowling/ascendant_shadowling.dm | 48 - .../antagonists/shadowling/shadowling.dm | 114 -- .../shadowling/shadowling_abilities.dm | 1199 ----------------- .../shadowling/shadowling_items.dm | 42 - .../special_shadowling_abilities.dm | 228 ---- .../modules/antagonists/shadowling/thrall.dm | 71 - .../chemistry/reagents/other_reagents.dm | 21 - .../surgery/organs/shadowling_organs.dm | 70 - 28 files changed, 5 insertions(+), 2180 deletions(-) delete mode 100644 yogstation/code/game/gamemodes/shadowling/shadowling.dm delete mode 100644 yogstation/code/modules/antagonists/shadowling/ascendant_shadowling.dm delete mode 100644 yogstation/code/modules/antagonists/shadowling/shadowling.dm delete mode 100644 yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm delete mode 100644 yogstation/code/modules/antagonists/shadowling/shadowling_items.dm delete mode 100644 yogstation/code/modules/antagonists/shadowling/special_shadowling_abilities.dm delete mode 100644 yogstation/code/modules/antagonists/shadowling/thrall.dm delete mode 100644 yogstation/code/modules/surgery/organs/shadowling_organs.dm diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index d835e5a0fea7..93f2c9a80542 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -41,7 +41,6 @@ #define ROLE_LAVALAND "Lavaland" #define ROLE_INTERNAL_AFFAIRS "Internal Affairs Agent" #define ROLE_FUGITIVE "Fugitive" -#define ROLE_SHADOWLING "Shadowling" // Yogs #define ROLE_VAMPIRE "Vampire" // Yogs #define ROLE_GANG "gangster" // Yogs #define ROLE_DARKSPAWN "darkspawn" // Yogs @@ -91,7 +90,6 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_OBSESSED = /datum/antagonist/obsessed, ROLE_INTERNAL_AFFAIRS = /datum/antagonist/traitor/internal_affairs, ROLE_FUGITIVE = /datum/antagonist/fugitive, - ROLE_SHADOWLING = /datum/antagonist/shadowling, // Yogs ROLE_VAMPIRE = /datum/antagonist/vampire, // Yogs ROLE_GANG = /datum/antagonist/gang, // Yogs ROLE_DARKSPAWN = /datum/antagonist/darkspawn, // Yogs diff --git a/code/__DEFINES/span.dm b/code/__DEFINES/span.dm index 3baac161ae41..0725bb3f547e 100644 --- a/code/__DEFINES/span.dm +++ b/code/__DEFINES/span.dm @@ -147,7 +147,6 @@ #define span_servradio(str) ("" + str + "") #define span_sevtug(str) ("" + str + "") #define span_sevtug_small(str) ("" + str + "") -#define span_shadowling(str) ("" + str + "") #define span_singing(str) ("" + str + "") #define span_slime(str) ("" + str + "") #define span_small(str) ("" + str + "") diff --git a/code/__DEFINES/{yogs_defines}/antagonists.dm b/code/__DEFINES/{yogs_defines}/antagonists.dm index 6007a5e48b67..9b6b434a60b2 100644 --- a/code/__DEFINES/{yogs_defines}/antagonists.dm +++ b/code/__DEFINES/{yogs_defines}/antagonists.dm @@ -1,6 +1,5 @@ #define ANTAG_DATUM_VAMPIRE /datum/antagonist/vampire #define ANTAG_DATUM_THRALL /datum/antagonist/thrall -#define ANTAG_DATUM_SLING /datum/antagonist/shadowling #define ANTAG_DATUM_DARKSPAWN /datum/antagonist/darkspawn #define ANTAG_DATUM_VEIL /datum/antagonist/veil #define ANTAG_DATUM_INFILTRATOR /datum/antagonist/infiltrator @@ -9,4 +8,4 @@ #define NOT_DOMINATING -1 #define MAX_LEADERS_GANG 3 -#define INITIAL_DOM_ATTEMPTS 3 \ No newline at end of file +#define INITIAL_DOM_ATTEMPTS 3 diff --git a/code/__DEFINES/{yogs_defines}/is_helpers.dm b/code/__DEFINES/{yogs_defines}/is_helpers.dm index 28755915f3c4..5b09dbdf96f2 100644 --- a/code/__DEFINES/{yogs_defines}/is_helpers.dm +++ b/code/__DEFINES/{yogs_defines}/is_helpers.dm @@ -1,7 +1,3 @@ -#define is_thrall(M) (istype(M, /mob/living) && M.mind?.has_antag_datum(/datum/antagonist/thrall)) -#define is_shadow(M) (istype(M, /mob/living) && M.mind?.has_antag_datum(/datum/antagonist/shadowling)) -#define is_shadow_or_thrall(M) (is_thrall(M) || is_shadow(M)) - #define isdarkspawn(A) (A?.mind?.has_antag_datum(/datum/antagonist/darkspawn)) #define isveil(A) (A?.mind?.has_antag_datum(/datum/antagonist/veil)) #define is_darkspawn_or_veil(A) (A.mind && isdarkspawn(A) || isveil(A)) diff --git a/code/datums/achievements/achievements.dm b/code/datums/achievements/achievements.dm index c78c87ff3c06..55fe019e0cea 100644 --- a/code/datums/achievements/achievements.dm +++ b/code/datums/achievements/achievements.dm @@ -93,7 +93,7 @@ id = 13 /datum/achievement/greentext/slingascend - name = "The Dark Shadow" + name = "The Dark Shadow (retired)" desc = "As a shadowling, ascend successfully" id = 14 diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index c0280d80b7cf..b4ae9b40c162 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -199,7 +199,6 @@ var/glow = 3.5 var/range = 2.5 var/glow_color - var/current_nullify_timer // For veil yogstation\code\modules\antagonists\shadowling\shadowling_abilities.dm power_coeff = 1 conflicts = list(/datum/mutation/human/glow/anti, /datum/mutation/human/radiantburst) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 90666766ad0f..01e68e8b5da3 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -840,50 +840,6 @@ spawn_meteors(ramp_up_final, wavetype) -////////////////////////////////////////////// -// // -// SHADOWLINGS // -// // -////////////////////////////////////////////// - -/datum/dynamic_ruleset/roundstart/shadowling - name = "Shadowling" - antag_flag = ROLE_SHADOWLING - antag_datum = /datum/antagonist/shadowling - protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Research Director", "Chief Engineer", "Chief Medical Officer", "Brig Physician") - restricted_roles = list("Cyborg", "AI") - required_candidates = 3 - weight = 3 - cost = 30 - requirements = list(90,80,80,70,60,40,30,30,20,10) - flags = HIGH_IMPACT_RULESET - minimum_players = 30 - antag_cap = 3 - minimum_players = 32 - -/datum/dynamic_ruleset/roundstart/shadowling/ready(population, forced = FALSE) - required_candidates = get_antag_cap(population) - . = ..() - -/datum/dynamic_ruleset/roundstart/shadowling/pre_execute(population) /// DON'T BREAK PLEASE - Xoxeyos 3/13/2021 - . = ..() - var/shadowlings = get_antag_cap(population) - for(var/shadowling_number = 1 to shadowlings) - if(candidates.len <= 0) - break - var/mob/M = pick_n_take(candidates) - assigned += M.mind - M.mind.special_role = ROLE_SHADOWLING - M.mind.restricted_roles = restricted_roles - log_game("[key_name(M)] has been selected as a Shadowling") - return TRUE - -/datum/dynamic_ruleset/roundstart/shadowling/proc/check_shadow_death() - return FALSE - -//Xoxeyos Here, I've added this Shadowling shit in, I have no idea what I'm doing, if there were mistakes made -//feel free to make changes, if it crashes, or just doesn't give anyone roles. - ////////////////////////////////////////////// // // // VAMPIRE // diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm index d3f3f94d52f2..2a3a967d2b1c 100644 --- a/code/game/objects/items/cardboard_cutouts.dm +++ b/code/game/objects/items/cardboard_cutouts.dm @@ -22,7 +22,6 @@ "Clockwork Cultist" = image(icon = src.icon, icon_state = "cutout_servant"), "Revolutionary" = image(icon = src.icon, icon_state = "cutout_viva"), "Wizard" = image(icon = src.icon, icon_state = "cutout_wizard"), - "Shadowling" = image(icon = src.icon, icon_state = "cutout_shadowling"), "Xenomorph" = image(icon = src.icon, icon_state = "cutout_fukken_xeno"), "Xenomorph Maid" = image(icon = src.icon, icon_state = "cutout_lusty"), "Swarmer" = image(icon = src.icon, icon_state = "cutout_swarmer"), @@ -152,10 +151,6 @@ name = "[pick(GLOB.wizard_first)], [pick(GLOB.wizard_second)]" desc = "A cardboard cutout of a wizard." icon_state = "cutout_wizard" - if("Shadowling") - name = "Unknown" - desc = "A cardboard cutout of a shadowling." - icon_state = "cutout_shadowling" if("Xenomorph") name = "alien hunter ([rand(1, 999)])" desc = "A cardboard cutout of a xenomorph." diff --git a/code/modules/admin/sql_ban_system.dm b/code/modules/admin/sql_ban_system.dm index da6408ac1485..2d2ffef95445 100644 --- a/code/modules/admin/sql_ban_system.dm +++ b/code/modules/admin/sql_ban_system.dm @@ -300,7 +300,7 @@ ROLE_REV, ROLE_REVENANT, ROLE_SINFULDEMON, ROLE_REV_HEAD, ROLE_SERVANT_OF_RATVAR, ROLE_SYNDICATE, ROLE_TRAITOR, ROLE_WIZARD, ROLE_GANG, ROLE_VAMPIRE, - ROLE_SHADOWLING, ROLE_DARKSPAWN, ROLE_ZOMBIE, ROLE_HERETIC)) //ROLE_REV_HEAD is excluded from this because rev jobbans are handled by ROLE_REV + ROLE_DARKSPAWN, ROLE_ZOMBIE, ROLE_HERETIC)) //ROLE_REV_HEAD is excluded from this because rev jobbans are handled by ROLE_REV for(var/department in long_job_lists) output += "
" break_counter = 0 diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index f8032d2a705a..b6c298d0f0a2 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -206,13 +206,6 @@ else message_admins("[key_name_admin(usr)] tried to create a revenant. Unfortunately, there were no candidates available.") log_admin("[key_name(usr)] failed to create a revenant.") - if("shadowling") - if(makeShadowling()) - message_admins("[key_name(usr)] created a shadowling.") - log_admin("[key_name(usr)] created a shadowling.") - else - message_admins("[key_name_admin(usr)] tried to create a shadowling. Unfortunately, there were no candidates available.") - log_admin("[key_name(usr)] failed to create a shadowling.") if("darkspawn") if(makeDarkspawn()) message_admins("[key_name(usr)] created a darkspawn.") diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 2aee88e9a327..a95ab8a4750b 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -24,7 +24,6 @@ Make CentCom Response Team (Requires Ghosts)
Make Abductor Team (Requires Ghosts)
Make Revenant (Requires Ghost)
- Make Shadowling
Make Darkspawn
Make Vampire
Make Infiltration Team (Requires Ghosts) diff --git a/code/modules/antagonists/clockcult/clockcult.dm b/code/modules/antagonists/clockcult/clockcult.dm index 99396e877ddd..c55c552c3d4a 100644 --- a/code/modules/antagonists/clockcult/clockcult.dm +++ b/code/modules/antagonists/clockcult/clockcult.dm @@ -44,7 +44,6 @@ var/list/no_team_antag = list( /datum/antagonist/rev, /datum/antagonist/darkspawn, - /datum/antagonist/shadowling, /datum/antagonist/cult, /datum/antagonist/zombie ) diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index 03e17fee9c51..587a68096e24 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -53,7 +53,6 @@ /datum/antagonist/rev, /datum/antagonist/clockcult, /datum/antagonist/darkspawn, - /datum/antagonist/shadowling, /datum/antagonist/zombie ) for(var/datum/antagonist/NTA in new_owner.antag_datums) diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index 51de65512872..94edb2008759 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -22,7 +22,6 @@ var/list/no_team_antag = list( /datum/antagonist/clockcult, /datum/antagonist/darkspawn, - /datum/antagonist/shadowling, /datum/antagonist/cult, /datum/antagonist/zombie ) diff --git a/code/modules/events/darkspawn.dm b/code/modules/events/darkspawn.dm index caae30f2770a..ab8b45230cce 100644 --- a/code/modules/events/darkspawn.dm +++ b/code/modules/events/darkspawn.dm @@ -4,7 +4,7 @@ max_occurrences = 0 //Disabled min_players = 30 dynamic_should_hijack = TRUE - gamemode_blacklist = list("darkspawn", "shadowling") + gamemode_blacklist = list("darkspawn") /datum/round_event/ghost_role/darkspawn minimum_required = 1 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index ecd70371f442..3c4d089b27a6 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1492,7 +1492,6 @@ /datum/antagonist/cult, /datum/antagonist/darkspawn, /datum/antagonist/rev, - /datum/antagonist/shadowling, /datum/antagonist/veil ) for(var/antagcheck in bad_antags) diff --git a/config/game_options.txt b/config/game_options.txt index fdda42c87c8b..9d0c91918bef 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -126,7 +126,6 @@ PROBABILITY CULT 5 PROBABILITY CLOCKWORK_CULT 5 # Snowflakes -PROBABILITY SHADOWLING 0 PROBABILITY WIZARD 8 PROBABILITY NUCLEAR 9 PROBABILITY MALF 0 @@ -162,7 +161,6 @@ CONTINUOUS CHANGELING CONTINUOUS WIZARD CONTINUOUS HIVEMIND #CONTINUOUS MALF -CONTINUOUS SHADOWLING CONTINUOUS VAMPIRE CONTINUOUS DYNAMIC CONTINUOUS HERESY diff --git a/yogstation.dme b/yogstation.dme index 2f8ea9966b48..9726cd7cabf2 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3832,7 +3832,6 @@ #include "yogstation\code\game\gamemodes\gangs\gangs.dm" #include "yogstation\code\game\gamemodes\gangs\gangtool.dm" #include "yogstation\code\game\gamemodes\infiltration\infiltration.dm" -#include "yogstation\code\game\gamemodes\shadowling\shadowling.dm" #include "yogstation\code\game\gamemodes\traitor\internal_affairs.dm" #include "yogstation\code\game\gamemodes\vampire\grave_fever.dm" #include "yogstation\code\game\gamemodes\vampire\traitor_vamp.dm" @@ -4007,12 +4006,6 @@ #include "yogstation\code\modules\antagonists\nukeop\clownop.dm" #include "yogstation\code\modules\antagonists\nukeop\nukeop.dm" #include "yogstation\code\modules\antagonists\nukeop\equipment\nuclearbomb.dm" -#include "yogstation\code\modules\antagonists\shadowling\ascendant_shadowling.dm" -#include "yogstation\code\modules\antagonists\shadowling\shadowling.dm" -#include "yogstation\code\modules\antagonists\shadowling\shadowling_abilities.dm" -#include "yogstation\code\modules\antagonists\shadowling\shadowling_items.dm" -#include "yogstation\code\modules\antagonists\shadowling\special_shadowling_abilities.dm" -#include "yogstation\code\modules\antagonists\shadowling\thrall.dm" #include "yogstation\code\modules\antagonists\slaughter\slaughter.dm" #include "yogstation\code\modules\antagonists\traitor\datum_mindslave.dm" #include "yogstation\code\modules\antagonists\traitor\datum_traitor.dm" @@ -4260,7 +4253,6 @@ #include "yogstation\code\modules\surgery\healing_surgeries.dm" #include "yogstation\code\modules\surgery\organs\heart.dm" #include "yogstation\code\modules\surgery\organs\lungs.dm" -#include "yogstation\code\modules\surgery\organs\shadowling_organs.dm" #include "yogstation\code\modules\uplink\uplink_item.dm" #include "yogstation\code\modules\vending\fishing.dm" #include "yogstation\code\modules\webhook\webhook.dm" diff --git a/yogstation/code/game/gamemodes/shadowling/shadowling.dm b/yogstation/code/game/gamemodes/shadowling/shadowling.dm deleted file mode 100644 index 44b224ba7e78..000000000000 --- a/yogstation/code/game/gamemodes/shadowling/shadowling.dm +++ /dev/null @@ -1,274 +0,0 @@ -#define LIGHT_HEAL_THRESHOLD 2 -#define LIGHT_DAMAGE_TAKEN 6 -#define LIGHT_DAM_THRESHOLD 0.25 - -/* -SHADOWLING: A gamemode based on previously-run events -Aliens called shadowlings are on the station. -These shadowlings can 'enthrall' crew members and enslave them. -They also burn in the light but heal rapidly whilst in the dark. -The game will end under two conditions: - 1. The shadowlings die - 2. The emergency shuttle docks at CentCom -Shadowling strengths: - - The dark - - Hard vacuum (They are not affected by it, but are affected by starlight!) - - Their thralls who are not harmed by the light - - Stealth -Shadowling weaknesses: - - The light - - Fire - - Enemy numbers - - Burn-based weapons and items (flashbangs, lasers, etc.) -Shadowlings start off disguised as normal crew members, and they only have two abilities: Hatch and Enthrall. -They can still enthrall and perhaps complete their objectives in this form. -Hatch will, after a short time, cast off the human disguise and assume the shadowling's true identity. -They will then assume the normal shadowling form and gain their abilities. -The shadowling will seem OP, and that's because it kinda is. Being restricted to the dark while being alone most of the time is extremely difficult and as such the shadowling needs powerful abilities. -Made by Xhuis -*/ -/* - GAMEMODE -*/ -/datum/game_mode - var/list/datum/mind/shadows = list() - var/list/datum/mind/thralls = list() - var/required_thralls = 15 //How many thralls are needed (this is changed in pre_setup, so it scales based on pop) - var/shadowling_ascended = FALSE //If at least one shadowling has ascended - var/thrall_ratio = 1 - -/datum/game_mode/proc/replace_jobbaned_player(mob/living/M, role_type, pref) - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [role_type]?", "[role_type]", null, pref, 50, M) - var/mob/dead/observer/theghost = null - if(candidates.len) - theghost = pick(candidates) - to_chat(M, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") - message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)]) to replace a jobbaned player.") - M.ghostize(0) - M.key = theghost.key - -/datum/game_mode/shadowling - name = "shadowling" - config_tag = "shadowling" - antag_flag = ROLE_SHADOWLING - required_players = 38 - required_enemies = 3 - recommended_enemies = 3 - enemy_minimum_age = 14 - restricted_jobs = list("AI", "Cyborg") - protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Research Director", "Chief Engineer", "Chief Medical Officer", "Brig Physician") - title_icon = "ss13" - -/datum/game_mode/shadowling/announce() - to_chat(world, "The current game mode is - Shadowling!") - to_chat(world, "There are alien [span_shadowling("shadowlings")] on the station. Crew: Kill the shadowlings before they can enthrall the crew. Shadowlings: Enthrall the crew while remaining in hiding.") - -/datum/game_mode/shadowling/pre_setup() - if(CONFIG_GET(flag/protect_roles_from_antagonist)) - restricted_jobs += protected_jobs - if(CONFIG_GET(flag/protect_assistant_from_antagonist)) - restricted_jobs += "Assistant" - var/shadowlings = max(3, round(num_players()/14)) - while(shadowlings) - var/datum/mind/shadow = pick(antag_candidates) - shadows += shadow - antag_candidates -= shadow - shadow.special_role = "Shadowling" - shadow.restricted_roles = restricted_jobs - shadowlings-- - var/thrall_scaling = round(num_players() / 3) - required_thralls = clamp(thrall_scaling, 15, 30) - thrall_ratio = required_thralls / 15 - return TRUE - -/datum/game_mode/shadowling/generate_report() - return "Sightings of strange alien creatures have been observed in your area. These aliens supposedly possess the ability to enslave unwitting personnel and leech from their power. \ - Be wary of dark areas and ensure all lights are kept well-maintained. Closely monitor all crew for suspicious behavior and perform dethralling surgery if they have obvious tells. Investigate all \ - reports of odd or suspicious sightings in maintenance." - -/datum/game_mode/shadowling/post_setup() - for(var/T in shadows) - var/datum/mind/shadow = T - log_game("[shadow.key] (ckey) has been selected as a Shadowling.") - shadow.current.add_sling() - . = ..() - return - -/datum/game_mode/shadowling/proc/check_shadow_victory() - return shadowling_ascended - -/datum/game_mode/shadowling/proc/check_shadow_death() - for(var/SM in get_antag_minds(/datum/antagonist/shadowling)) - var/datum/mind/shadow_mind = SM - if(istype(shadow_mind)) - var/turf/T = get_turf(shadow_mind.current) - if((shadow_mind) && (shadow_mind.current.stat != DEAD) && T && is_station_level(T.z) && ishuman(shadow_mind.current)) - return FALSE - return TRUE - -/datum/game_mode/shadowling/check_finished() - . = ..() - if(check_shadow_death()) - return TRUE - -/datum/game_mode/proc/auto_declare_completion_shadowling() - var/text = "" - if(shadows.len) - text += "
The shadowlings were:" - for(var/S in shadows) - var/datum/mind/shadow = S - text += printplayer(shadow) - text += "
" - if(thralls.len) - text += "
The thralls were:" - for(var/T in thralls) - var/datum/mind/thrall = T - text += printplayer(thrall) - text += "
" - to_chat(world, text) - -/datum/game_mode/shadowling/set_round_result() - ..() - if(check_shadow_victory()) - SSticker.mode_result = "win - shadowlings have ascended" - else - SSticker.mode_result = "loss - staff stopped the shadowlings" - -/* - MISCELLANEOUS -*/ -/datum/species/shadow/ling - //Normal shadowpeople but with enhanced effects - name = "Shadowling" - id = "shadowling" - say_mod = "chitters" - species_traits = list(NOBLOOD,NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYESPRITES,NOFLASH) - inherent_traits = list(TRAIT_NOGUNS, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE, TRAIT_NOBREATH, TRAIT_RADIMMUNE, TRAIT_VIRUSIMMUNE, TRAIT_PIERCEIMMUNE) - no_equip = list(ITEM_SLOT_MASK, ITEM_SLOT_EYES, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_ICLOTHING, ITEM_SLOT_SUITSTORE) - nojumpsuit = TRUE - mutanteyes = /obj/item/organ/eyes/night_vision/alien/sling - burnmod = 1.5 //1.5x burn damage, 2x is excessive - heatmod = 1.5 - var/mutable_appearance/eyes_overlay - var/shadow_charges = 3 - var/last_charge = 0 - -/datum/species/shadow/ling/negates_gravity(mob/living/carbon/human/H) - return TRUE - -/datum/species/shadow/ling/on_species_gain(mob/living/carbon/human/C) - C.draw_yogs_parts(TRUE) - eyes_overlay = mutable_appearance('yogstation/icons/mob/sling.dmi', "eyes", 25) - C.add_overlay(eyes_overlay) - RegisterSignal(C, COMSIG_MOVABLE_MOVED, PROC_REF(apply_darkness_speed)) - . = ..() - -/datum/species/shadow/ling/on_species_loss(mob/living/carbon/human/C) - C.draw_yogs_parts(FALSE) - UnregisterSignal(C, COMSIG_MOVABLE_MOVED) - C.remove_movespeed_modifier(id) - if(eyes_overlay) - C.cut_overlay(eyes_overlay) - QDEL_NULL(eyes_overlay) - . = ..() - -/datum/species/shadow/ling/spec_life(mob/living/carbon/human/H) - H.nutrition = NUTRITION_LEVEL_WELL_FED //i aint never get hongry - if(isturf(H.loc)) - var/turf/T = H.loc - var/light_amount = T.get_lumcount() - if(light_amount > LIGHT_DAM_THRESHOLD) //Can survive in very small light levels. Also doesn't take damage while incorporeal, for shadow walk purposes - H.adjustCloneLoss(LIGHT_DAMAGE_TAKEN) - if(H.stat != DEAD) - to_chat(H, span_userdanger("The light burns you!")) //Message spam to say "GET THE FUCK OUT" - H.playsound_local(get_turf(H), 'sound/weapons/sear.ogg', 150, 1, pressure_affected = FALSE) - else if (light_amount < LIGHT_HEAL_THRESHOLD && !istype(H.loc, /obj/effect/dummy/phased_mob/shadowling)) //Can't heal while jaunting - H.heal_overall_damage(5,5) - H.adjustToxLoss(-5) - H.adjustOrganLoss(ORGAN_SLOT_BRAIN, -25) //Shad O. Ling gibbers, "CAN U BE MY THRALL?!!" - H.adjustCloneLoss(-5) - H.SetKnockdown(0) - H.SetStun(0) - H.SetParalyzed(0) - var/charge_time = 400 - ((SSticker.mode.thralls && SSticker.mode.thralls.len) || 0)*10 - if(world.time >= charge_time+last_charge) - shadow_charges = min(shadow_charges + 1, 3) - last_charge = world.time - -/datum/species/shadow/ling/bullet_act(obj/projectile/P, mob/living/carbon/human/H) - var/turf/T = H.loc - if(istype(T) && shadow_charges > 0) - var/light_amount = T.get_lumcount() - if(light_amount < LIGHT_DAM_THRESHOLD) - H.visible_message(span_danger("The shadows around [H] ripple as they absorb \the [P]!")) - playsound(T, "bullet_miss", 75, 1) - shadow_charges = min(shadow_charges - 1, 0) - return -1 - return 0 - -/datum/species/shadow/ling/proc/apply_darkness_speed(mob/living/carbon/C) - var/turf/T = get_turf(C) - var/light_amount = T.get_lumcount() - if(light_amount > LIGHT_DAM_THRESHOLD) - C.remove_movespeed_modifier(id) - else - C.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING)) - - -/datum/species/shadow/ling/lesser //Empowered thralls. Obvious, but powerful - name = "Lesser Shadowling" - id = "l_shadowling" - say_mod = "chitters" - species_traits = list(NOBLOOD,NO_DNA_COPY,NOTRANSSTING,NOEYESPRITES,NOFLASH) - inherent_traits = list(TRAIT_NOBREATH, TRAIT_RADIMMUNE, TRAIT_PIERCEIMMUNE, TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTCOLD) - burnmod = 1.25 - heatmod = 1.25 - brutemod = 0.75 - -/datum/species/shadow/ling/lesser/spec_life(mob/living/carbon/human/H) - H.nutrition = NUTRITION_LEVEL_WELL_FED //i aint never get hongry - if(isturf(H.loc)) - var/turf/T = H.loc - var/light_amount = T.get_lumcount() - if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move) - H.adjustCloneLoss(LIGHT_DAMAGE_TAKEN/2) - else if (light_amount < LIGHT_HEAL_THRESHOLD) - H.heal_overall_damage(4,4) - H.adjustToxLoss(-5) - H.adjustOrganLoss(ORGAN_SLOT_BRAIN, -25) - H.adjustCloneLoss(-5) - -/mob/living/proc/add_thrall() - if(!istype(mind)) - return FALSE - return mind.add_antag_datum(ANTAG_DATUM_THRALL) - -/mob/living/proc/add_sling() - if(!istype(mind)) - return FALSE - return mind.add_antag_datum(ANTAG_DATUM_SLING) - -/mob/living/proc/remove_thrall() - if(!istype(mind)) - return FALSE - return mind.remove_antag_datum(ANTAG_DATUM_THRALL) - -/mob/living/proc/remove_sling() - if(!istype(mind)) - return FALSE - return mind.remove_antag_datum(ANTAG_DATUM_SLING) - -/datum/game_mode/shadowling/generate_credit_text() - var/list/round_credits = list() - var/len_before_addition - - round_credits += "

The Shadowlings:

" - len_before_addition = round_credits.len - for(var/datum/mind/shadow in shadows) - round_credits += "

[shadow.name] as a Shadowling

" - if(len_before_addition == round_credits.len) - round_credits += list("

The Shadowlings have moved to the shadows!

", "

We couldn't locate them!

") - round_credits += "
" - - round_credits += ..() - return round_credits diff --git a/yogstation/code/modules/admin/verbs/one_click_antag.dm b/yogstation/code/modules/admin/verbs/one_click_antag.dm index 9bb312e20ae4..a79c62c2352f 100644 --- a/yogstation/code/modules/admin/verbs/one_click_antag.dm +++ b/yogstation/code/modules/admin/verbs/one_click_antag.dm @@ -1,31 +1,3 @@ -//Shadowling -/datum/admins/proc/makeShadowling() - var/datum/game_mode/shadowling/temp = new - if(CONFIG_GET(flag/protect_roles_from_antagonist)) - temp.restricted_jobs += temp.protected_jobs - if(CONFIG_GET(flag/protect_assistant_from_antagonist)) - temp.restricted_jobs += "Assistant" - var/list/mob/living/carbon/human/candidates = list() - var/mob/living/carbon/human/H - for(var/mob/living/carbon/human/applicant in GLOB.player_list) - if(ROLE_DARKSPAWN in applicant.client.prefs.be_special) - if(!applicant.stat || !applicant.mind) - continue - if(applicant.mind.special_role) - continue - if(is_banned_from(applicant.ckey, "shadowling") || is_banned_from(applicant.ckey, "Syndicate")) - continue - if(!temp.age_check(applicant.client) || (applicant.job in temp.restricted_jobs)) - continue - if(is_shadow_or_thrall(applicant)) - continue - candidates += applicant - if(candidates.len) - H = pick(candidates) - H.add_sling() - return TRUE - return FALSE - //Darkspawn /datum/admins/proc/makeDarkspawn() var/datum/game_mode/darkspawn/temp = new @@ -36,7 +8,7 @@ var/list/mob/living/carbon/human/candidates = list() var/mob/living/carbon/human/H for(var/mob/living/carbon/human/applicant in GLOB.player_list) - if(ROLE_SHADOWLING in applicant.client.prefs.be_special) + if(ROLE_DARKSPAWN in applicant.client.prefs.be_special) if(!applicant.stat || !applicant.mind) continue if(applicant.mind.special_role) diff --git a/yogstation/code/modules/antagonists/shadowling/ascendant_shadowling.dm b/yogstation/code/modules/antagonists/shadowling/ascendant_shadowling.dm deleted file mode 100644 index b97ea0ee1262..000000000000 --- a/yogstation/code/modules/antagonists/shadowling/ascendant_shadowling.dm +++ /dev/null @@ -1,48 +0,0 @@ -/mob/living/simple_animal/ascendant_shadowling - name = "ascendant shadowling" - desc = "HOLY SHIT RUN THE FUCK AWAY- RAAAAAAA!" - icon = 'yogstation/icons/mob/mob.dmi' - icon_state = "shadowling_ascended" - icon_living = "shadowling_ascended" - verb_say = "telepathically thunders" - verb_ask = "telepathically thunders" - verb_exclaim = "telepathically thunders" - verb_yell = "telepathically thunders" - force_threshold = INFINITY //Can't die by normal means - health = 9999 - maxHealth = 9999 - speed = 0 - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - response_help = "pokes" - response_disarm = "flails at" - response_harm = "flails at" - harm_intent_damage = 0 - melee_damage_lower = 160 //Was 60, buffed - melee_damage_upper = 160 - attacktext = "rends" - attack_sound = 'sound/weapons/slash.ogg' - minbodytemp = 0 - maxbodytemp = INFINITY - environment_smash = 3 - faction = list("faithless") - speech_span = SPAN_REALLYBIG //screw it someone else can figure out how to put both SPAN_YELL and SPAN_REALLYBIG on a speech_span later - -/mob/living/simple_animal/ascendant_shadowling/Initialize(mapload) - . = ..() - LoadComponent(/datum/component/walk) - -/mob/living/simple_animal/ascendant_shadowling/Process_Spacemove(movement_dir = 0) - return TRUE //copypasta from carp code - -/mob/living/simple_animal/ascendant_shadowling/ex_act(severity) - return FALSE //You think an ascendant can be hurt by bombs? HA - -/mob/living/simple_animal/ascendant_shadowling/singularity_act() - to_chat(src, "BURNS--")) - spawn(30) - if(QDELETED(M)) - return - M.visible_message(span_warning("[M] suddenly bloats and explodes!")) - to_chat(M,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA----") - playsound(M, 'sound/magic/Disintegrate.ogg', 100, 1) - M.gib() - return ..() - -/datum/antagonist/shadowling/greet() - to_chat(owner, "
You are a shadowling!") - to_chat(owner, "Currently, you are disguised as an employee aboard [station_name()].") - to_chat(owner, "In your limited state, you have three abilities: Enthrall, Hatch, and Hivemind Commune.") - to_chat(owner, "Any other shadowlings are your allies. You must assist them as they shall assist you.") - to_chat(owner, "You require [SSticker.mode.required_thralls || 15] thralls to ascend.
") - SEND_SOUND(owner.current, sound('yogstation/sound/ambience/antag/sling.ogg')) - -/datum/antagonist/shadowling/proc/check_shadow_death() - for(var/SM in get_antag_minds(/datum/antagonist/shadowling)) - var/datum/mind/shadow_mind = SM - if(istype(shadow_mind)) - var/turf/T = get_turf(shadow_mind.current) - if((shadow_mind) && (shadow_mind.current.stat != DEAD) && T && is_station_level(T.z) && ishuman(shadow_mind.current)) - return FALSE - return TRUE - -/datum/antagonist/shadowling/roundend_report() - return "[owner ? printplayer(owner) : "Unnamed Shadowling"]" - -/datum/antagonist/shadowling/roundend_report_header() - if(SSticker.mode.shadowling_ascended) //Doesn't end instantly - this is hacky and I don't know of a better way ~X - return "The shadowlings have ascended and taken over the station!
" - else if(!SSticker.mode.shadowling_ascended && check_shadow_death()) //If the shadowlings have ascended, they can not lose the round - return "The shadowlings have been killed by the crew!
" - else if(!SSticker.mode.shadowling_ascended && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE) - return "The crew escaped the station before the shadowlings could ascend!
" - else - return "The shadowlings have failed!
" - -/datum/antagonist/shadowling/roundend_report_footer() - if(!LAZYLEN(SSticker.mode.thralls)) - return "The shadowlings have not managed to convert anyone!
" - -/datum/objective/ascend - explanation_text = "Ascend to your true form by use of the Ascendance ability. This may only be used with 15 or more collective thralls, while hatched, and is unlocked with the Collective Mind ability." - -/datum/objective/ascend/check_completion() - if(..()) - return TRUE - return (SSticker && SSticker.mode && SSticker.mode.shadowling_ascended) - -/datum/objective/ascend/update_explanation_text() - explanation_text = "Ascend to your true form by use of the Ascendance ability. This may only be used with [SSticker.mode.required_thralls] or more collective thralls, while hatched, and is unlocked with the Collective Mind ability." - -/mob/living/carbon/human/get_status_tab_items() - . = ..() - if((dna && dna.species) && istype(dna.species, /datum/species/shadow/ling)) - var/datum/species/shadow/ling/SL = dna.species - . += "Shadowy Shield Charges: [SL.shadow_charges]" - -/datum/antagonist/shadowling/get_preview_icon() - var/icon/shadowling_icon = icon('yogstation/icons/mob/mob.dmi', "shadowling_ascended") - - shadowling_icon.Scale(ANTAGONIST_PREVIEW_ICON_SIZE, ANTAGONIST_PREVIEW_ICON_SIZE) - - return shadowling_icon diff --git a/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm b/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm deleted file mode 100644 index db2087d4c817..000000000000 --- a/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm +++ /dev/null @@ -1,1199 +0,0 @@ -#define EMPOWERED_THRALL_LIMIT 3 - -/datum/action/cooldown/spell/proc/shadowling_check(mob/living/carbon/human/H) //what the fuck was this shit - if(!H || !istype(H)) - return FALSE - if(H.dna && H.dna.species && H.dna.species.id == "shadowling" && is_shadow(H)) - return TRUE - if(H.dna && H.dna.species && H.dna.species.id == "l_shadowling" && is_thrall(H)) - return TRUE - if(!is_shadow_or_thrall(owner)) - to_chat(owner, span_warning("You can't wrap your head around how to do this.")) - - if(is_thrall(owner)) - to_chat(owner, span_warning("You aren't powerful enough to do this.")) - - if(is_shadow(owner)) - to_chat(owner, span_warning("Your telepathic ability is suppressed. Hatch or use Rapid Re-Hatch first.")) - return FALSE - -/datum/action/cooldown/spell/pointed/sling - ranged_mousepointer = 'icons/effects/mouse_pointers/cult_target.dmi' - var/mob/living/user - -/datum/action/cooldown/spell/pointed/sling/InterceptClickOn(mob/living/caller, params, atom/t) - . = ..() - if(!.) - return FALSE - if(!isliving(t)) - to_chat(caller, span_warning("You may only use this ability on living things!")) - return FALSE - user = caller - target = t - if(!shadowling_check(user)) - return FALSE - - return TRUE - -/datum/action/cooldown/spell/pointed/sling/proc/revert_cast() - unset_click_ability(owner) - -/datum/action/cooldown/spell/pointed/sling/proc/start_recharge() - build_all_button_icons() - -/datum/action/cooldown/spell/pointed/sling/glare //Stuns and mutes a human target for 10 seconds - name = "Glare" - desc = "Disrupts the target's motor and speech abilities. Much more effective within two meters." - panel = "Shadowling Abilities" - button_icon_state = "glare" - button_icon = 'yogstation/icons/mob/actions.dmi' - - cooldown_time = 30 SECONDS - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/pointed/sling/glare/InterceptClickOn(mob/living/caller, params, atom/target_atom) - . = ..() - if(!.) - return FALSE - if(!target_atom || !iscarbon(target_atom)) - revert_cast() - return FALSE - var/mob/living/carbon/target = target_atom - if(!caller.getorganslot(ORGAN_SLOT_EYES)) - to_chat(owner, span_warning("You need eyes to glare!")) - revert_cast() - return FALSE - if(target.stat) - to_chat(owner, span_warning("[target] must be conscious!")) - revert_cast() - return FALSE - if(is_shadow_or_thrall(target)) - to_chat(owner, span_warning("You cannot glare at allies!")) - revert_cast() - return FALSE - var/mob/living/carbon/human/M = target - usr.visible_message(span_warning("[owner]'s eyes flash a purpleish-red!")) - var/distance = get_dist(target, owner) - if (distance <= 2) - target.visible_message(span_danger("[target] suddendly collapses...")) - to_chat(target, span_userdanger("A purple light flashes across your vision, and you lose control of your movements!")) - target.Paralyze(10 SECONDS) - M.silent += 10 - else //Distant glare - var/loss = 100 - (distance * 10) - target.adjustStaminaLoss(loss) - if(iscarbon(target)) - target.adjust_stutter(loss) - else if(issilicon(target)) - target.adjust_stutter(distance) - to_chat(target, span_userdanger("A purple light flashes across your vision, and exhaustion floods your body...")) - target.visible_message(span_danger("[target] looks very tired...")) - start_recharge() - unset_click_ability(owner) - return TRUE - -/datum/action/cooldown/spell/aoe/veil //Puts out most nearby lights except for flares and yellow slime cores - name = "Veil" - desc = "Extinguishes most nearby light sources." - panel = "Shadowling Abilities" - button_icon_state = "veil" - button_icon = 'yogstation/icons/mob/actions.dmi' - - cooldown_time = 12 SECONDS //Short cooldown because people can just turn the lights back on - aoe_radius = 5 - var/admin_override = FALSE //Requested by Shadowlight213. Allows anyone to cast the spell, not just shadowlings. - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/aoe/proc/extinguishItem(obj/item/I, cold = FALSE) //Does not darken items held by mobs due to mobs having separate luminosity, use extinguish_mob() or write your own proc. - var/blacklisted_lights = list(/obj/item/flashlight/flare, /obj/item/flashlight/slime) - if(istype(I, /obj/item/flashlight)) - var/obj/item/flashlight/F = I - if(F.light_on || F.on) - if(cold) - if(is_type_in_list(F, blacklisted_lights)) - F.visible_message(span_warning("The sheer cold shatters [F]!")) - qdel(F) - else - return - if(is_type_in_list(I, blacklisted_lights)) - I.visible_message(span_danger("[I] dims slightly before scattering the shadows around it.")) - return F.light_power //Necessary because flashlights become 0-luminosity when held. I don't make the rules of lightcode. - F.on = FALSE - F.set_light_on(FALSE) - F.update_brightness() - else if(istype(I, /obj/item/pda)) - var/obj/item/pda/P = I - P.set_light_on(FALSE) - I.set_light_on(FALSE) - return I.luminosity - -/datum/action/cooldown/spell/aoe/proc/extinguish_mob(mob/living/H, cold = FALSE) - for(var/obj/item/F in H) - if(cold) - extinguishItem(F, TRUE) - extinguishItem(F) - if(iscarbon(H)) - var/mob/living/carbon/M = H - var/datum/mutation/human/glow/G = M.dna.get_mutation(GLOWY) - if(G) - G.glowth.set_light(0, 0) // Set glowy to no light - if(G.current_nullify_timer) - deltimer(G.current_nullify_timer) // Stacks - G.current_nullify_timer = addtimer(CALLBACK(src, PROC_REF(giveGlowyBack), M), 40 SECONDS, TIMER_STOPPABLE) - -/datum/action/cooldown/spell/aoe/proc/giveGlowyBack(mob/living/carbon/M) - if(!M) - return - var/datum/mutation/human/glow/G = M.dna.get_mutation(GLOWY) - if(G) - G.modify() // Re-sets glowy - G.current_nullify_timer = null - -/datum/action/cooldown/spell/aoe/veil/cast_on_thing_in_aoe(atom/target, atom/user) - if(!shadowling_check(owner) && !admin_override) - return - to_chat(owner, span_shadowling("You silently disable all nearby lights.")) - var/turf/T = get_turf(owner) - for(var/datum/light_source/LS in T.get_affecting_lights()) - var/atom/LO = LS.source_atom - if(isitem(LO)) - extinguishItem(LO) - continue - if(istype(LO, /obj/machinery/light)) - var/obj/machinery/light/L = LO - L.on = FALSE - L.visible_message(span_warning("[L] flickers and falls dark.")) - L.update(0) - L.set_light(0) - continue - if(istype(LO, /obj/machinery/computer) || istype(LO, /obj/machinery/power/apc)) - LO.set_light(0) - LO.visible_message(span_warning("[LO] grows dim, its screen barely readable.")) - continue - if(ismob(LO)) - extinguish_mob(LO) - if(istype(LO, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/borg = LO - if(!borg.lamp_cooldown) - borg.smash_headlamp() - if(istype(LO, /obj/machinery/camera)) - LO.set_light(0) - if(prob(10)) - LO.emp_act(2) - continue - if(istype(LO, /obj/mecha)) - var/obj/mecha/M = LO - M.set_light(0) - M.lights = FALSE - if(istype(LO, /obj/machinery/power/floodlight)) - var/obj/machinery/power/floodlight/FL = LO - FL.change_setting(2) // Set floodlight to lowest setting - if(istype(LO, /obj/structure/light_prism)) - qdel(LO) - - for(var/obj/structure/glowshroom/G in orange(7, user)) //High radius because glowshroom spam wrecks shadowlings - if(G.light_power > 0) - var/obj/structure/glowshroom/shadowshroom/S = new /obj/structure/glowshroom/shadowshroom(G.loc) //I CAN FEEL THE WARP OVERTAKING ME! IT IS A GOOD PAIN! - S.generation = G.generation - G.visible_message(span_warning("[G] suddenly turns dark!")) - qdel(G) - for(var/turf/open/floor/grass/fairy/F in view(7, user)) - if(F.light_power > 0) - F.visible_message(span_warning("[F] suddenly turns dark!")) - F.ChangeTurf(/turf/open/floor/grass/fairy/dark, flags = CHANGETURF_INHERIT_AIR) - for(var/obj/structure/marker_beacon/M in view(7, user)) - M.deconstruct() - -/datum/action/cooldown/spell/aoe/flashfreeze //Stuns and freezes nearby people - a bit more effective than a changeling's cryosting - name = "Icy Veins" - desc = "Instantly freezes the blood of nearby people, stunning them and causing burn damage while hampering their movement." - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "icy_veins" - - panel = "Shadowling Abilities" - sound = 'sound/effects/ghost2.ogg' - aoe_radius = 3 - cooldown_time = 1 MINUTES - var/special_lights = list(/obj/item/flashlight/flare, /obj/item/flashlight/slime) - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/aoe/flashfreeze/cast_on_thing_in_aoe(atom/target, atom/user) - if(!shadowling_check(owner)) - return - to_chat(owner, span_shadowling("You freeze the nearby air.")) - if(isturf(target)) - var/turf/T = target - for(var/mob/living/carbon/M in T.contents) - if(is_shadow_or_thrall(M)) - if(M == user) //No message for the user, of course - continue - else - to_chat(M, span_danger("You feel a blast of paralyzingly cold air wrap around you and flow past, but you are unaffected!")) - continue - to_chat(M, span_userdanger("A wave of shockingly cold air engulfs you!")) - M.Stun(2) - M.apply_damage(5, BURN) - if(M.bodytemperature) - M.adjust_bodytemperature(-100, 50) - if(M.reagents) - M.reagents.add_reagent(/datum/reagent/consumable/frostoil, 5) //some amount of a cryo sting fucked if I care - M.reagents.add_reagent(/datum/reagent/shadowfrost, 5) - extinguish_mob(M, TRUE) - for(var/obj/item/F in T.contents) - extinguishItem(F, TRUE) - -/datum/action/cooldown/spell/pointed/enthrall //Turns a target into the shadowling's slave. This overrides all previous loyalties - name = "Enthrall" - desc = "Allows you to enslave a conscious, non-braindead, non-catatonic human to your will. This takes some time to cast." - panel = "Shadowling Abilities" - button_icon_state = "enthrall" - button_icon = 'yogstation/icons/mob/actions.dmi' - - cast_range = 1 //Adjacent to user - var/enthralling = FALSE - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/pointed/enthrall/InterceptClickOn(mob/living/caller, params, atom/target_atom) - . = ..() - if(!.) - return FALSE - var/mob/living/carbon/human/user = owner - listclearnulls(SSticker.mode.thralls) - if(!(user.mind in SSticker.mode.shadows)) return - if(user.dna.species.id != "shadowling") - if(SSticker.mode.thralls.len >= 5) - return FALSE - var/mob/living/target = target_atom - if(!target.key || !target.mind) - to_chat(user, span_warning("The target has no mind!")) - return FALSE - if(target.stat) - to_chat(user, span_warning("The target must be conscious!")) - return FALSE - if(is_shadow_or_thrall(target)) - to_chat(user, span_warning("You can not enthrall allies!")) - return FALSE - if(!ishuman(target)) - to_chat(user, span_warning("You can only enthrall humans!")) - return FALSE - if(enthralling) - to_chat(user, span_warning("You are already enthralling!")) - return FALSE - if(!target.client) - to_chat(user, span_warning("[target]'s mind is vacant of activity.")) - enthralling = TRUE - for(var/progress = 0, progress <= 3, progress++) - switch(progress) - if(1) - to_chat(user, span_notice("You place your hands to [target]'s head...")) - user.visible_message(span_warning("[user] places their hands onto the sides of [target]'s head!")) - if(2) - to_chat(user, span_notice("You begin preparing [target]'s mind as a blank slate...")) - user.visible_message(span_warning("[user]'s palms flare a bright red against [target]'s temples!")) - to_chat(target, span_danger("A terrible red light floods your mind. You collapse as conscious thought is wiped away.")) - target.Knockdown(12 SECONDS) - if(HAS_TRAIT(target, TRAIT_MINDSHIELD)) - if(ispreternis(target)) - to_chat(user, span_notice("Your servant's mind has been corrupted by other machinery. You begin to shut down the implant preventing your command - this will take some time...")) - user.visible_message(span_warning("[user] growls in frustration, then dips their head with determination!")) - else - to_chat(user, span_notice("They are protected by an implant. You begin to shut down the nanobots in their brain - this will take some time...")) - user.visible_message(span_warning("[user] pauses, then dips their head in concentration!")) - to_chat(target, span_boldannounce("You feel your mental protection faltering!")) - if(!do_after(user, 65 SECONDS, target)) //65 seconds to remove a loyalty implant. yikes! - to_chat(user, span_warning("The enthralling has been interrupted - your target's mind returns to its previous state.")) - to_chat(target, span_userdanger("You wrest yourself away from [user]'s hands and compose yourself!")) - enthralling = FALSE - return - to_chat(user, span_notice("The nanobots composing the mindshield implant have been rendered inert. Now to continue.")) - user.visible_message(span_warning("[user] relaxes again.")) - for(var/obj/item/implant/mindshield/L in target) - if(L) - qdel(L) - to_chat(target, span_boldannounce("Your mental protection unexpectedly falters, dims, dies.")) - if(3) - to_chat(user, span_notice("You begin planting the tumor that will control the new thrall...")) - user.visible_message(span_warning("A strange energy passes from [user]'s hands into [target]'s head!")) - to_chat(target, span_boldannounce("You feel your memories twisting, morphing. A sense of horror dominates your mind.")) - if(!do_after(user, 7 SECONDS, target)) //around 21 seconds total for enthralling, 86 for someone with a loyalty implant - to_chat(user, span_warning("The enthralling has been interrupted - your target's mind returns to its previous state.")) - to_chat(target, span_userdanger("You wrest yourself away from [user]'s hands and compose yourself!")) - enthralling = FALSE - return - enthralling = FALSE - to_chat(user, span_shadowling("You have enthralled [target.real_name]!")) - target.visible_message(span_big("[target] looks to have experienced a revelation!"), \ - span_warning("False faces all dark not real not real not--")) - target.setOxyLoss(0) //In case the shadowling was choking them out - if(iscarbon(target)) - var/mob/living/carbon/M = target - var/datum/mutation/human/glow/G = M.dna.get_mutation(GLOWY) - if(G) - M.dna.remove_mutation(GLOWY) - target.mind.special_role = "thrall" - var/obj/item/organ/internal/shadowtumor/ST = new - ST.Insert(target, FALSE, FALSE) - target.add_thrall() - if(target.reagents.has_reagent(/datum/reagent/consumable/frostoil)) //Stabilize body temp incase the sling froze them earlier - target.reagents.remove_reagent(/datum/reagent/consumable/frostoil) - to_chat(target, span_notice("You feel warmer... It feels good.")) - target.bodytemperature = 310 - - return TRUE - -/datum/action/cooldown/spell/shadowling_hivemind //Lets a shadowling talk to its allies - name = "Hivemind Commune" - desc = "Allows you to silently communicate with all other shadowlings and thralls." - panel = "Shadowling Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "commune" - - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/shadowling_hivemind/cast(atom/cast_on) - . = ..() - if(!.) - return FALSE - if(!is_shadow(owner)) - to_chat(owner, span_warning("You must be a shadowling to do that!")) - return - var/text = sanitize(tgui_input_text(owner, "What do you want to say your thralls and fellow shadowlings?.", "Hive Chat", "")) - if(!text) - return - var/my_message = "\[Shadowling\] [owner.real_name]: [text]" - for(var/mob/M in GLOB.mob_list) - if(is_shadow_or_thrall(M)) - to_chat(M, my_message) - if(M in GLOB.dead_mob_list) - to_chat(M, "(F) [my_message]") - log_say("[owner.real_name]/[owner.key] : [text]") - - return TRUE - -/datum/action/cooldown/spell/shadowling_regenarmor //Resets a shadowling's species to normal, removes genetic defects, and re-equips their armor - name = "Rapid Re-Hatch" - desc = "Re-forms protective chitin that may be lost during cloning or similar processes." - panel = "Shadowling Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "regen_armor" - - cooldown_time = 1 MINUTES - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/shadowling_regenarmor/cast(mob/living/carbon/human/user) - . = ..() - if(!.) - return FALSE - if(!is_shadow(user)) - to_chat(user, span_warning("You must be a shadowling to do this!")) - return - user.visible_message(span_warning("[user]'s skin suddenly bubbles and shifts around their body!"), \ - span_shadowling("You regenerate your protective armor and cleanse your form of defects.")) - user.setCloneLoss(0) - user.equip_to_slot_or_del(new /obj/item/clothing/suit/space/shadowling(user), ITEM_SLOT_OCLOTHING) - user.equip_to_slot_or_del(new /obj/item/clothing/head/shadowling(user), ITEM_SLOT_HEAD) - user.set_species(/datum/species/shadow/ling) - - return TRUE - -/datum/action/cooldown/spell/collective_mind //Lets a shadowling bring together their thralls' strength, granting new abilities and a headcount - name = "Collective Hivemind" - desc = "Gathers the power of all of your thralls and compares it to what is needed for ascendance. Also gains you new abilities." - panel = "Shadowling Abilities" - button_icon_state = "collective_mind" - button_icon = 'yogstation/icons/mob/actions.dmi' - - cooldown_time = 10 SECONDS //10 second cooldown to prevent spam - spell_requirements = SPELL_REQUIRES_HUMAN - - var/blind_smoke_acquired = FALSE - var/screech_acquired = FALSE - var/reviveThrallAcquired = FALSE - var/null_charge_acquired = FALSE - -/datum/action/cooldown/spell/collective_mind/cast(mob/living/carbon/human/user) - . = ..() - if(!.) - return FALSE - if(!shadowling_check(user)) - return - var/thralls = 0 - var/victory_threshold = SSticker.mode.required_thralls - var/mob/M - to_chat(user, span_shadowling("You focus your telepathic energies abound, harnessing and drawing together the strength of your thralls.")) - for(M in GLOB.alive_mob_list) - if(is_thrall(M)) - thralls++ - to_chat(M, span_shadowling("You feel hooks sink into your mind and pull.")) - if(!do_after(user, 3 SECONDS, user)) - to_chat(user, span_warning("Your concentration has been broken. The mental hooks you have sent out now retract into your mind.")) - return - if(thralls >= CEILING(3 * SSticker.mode.thrall_ratio, 1) && !screech_acquired) - screech_acquired = TRUE - to_chat(user, span_shadowling("The power of your thralls has granted you the Sonic Screech ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms.")) - var/datum/action/cooldown/spell/aoe/unearthly_screech/screech = new(M) - screech.Grant(M) - if(thralls >= CEILING(5 * SSticker.mode.thrall_ratio, 1) && !blind_smoke_acquired) - blind_smoke_acquired = TRUE - to_chat(user, "The power of your thralls has granted you the Blinding Smoke ability. It will create a choking cloud that will blind any non-thralls who enter. \ - ") - to_chat(user, "The power of your thralls has granted you the Dark Acceleration ability. This will allow you to turn one of your thralls into a weaker shadowling. \ - ") - var/datum/action/cooldown/spell/pointed/empower_thrall/empower = new(M) - empower.Grant(M) - var/datum/action/cooldown/spell/blindness_smoke/smoke = new(M) - smoke.Grant(M) - if(thralls >= CEILING(7 * SSticker.mode.thrall_ratio, 1) && !null_charge_acquired) - null_charge_acquired = TRUE - to_chat(user, "The power of your thralls has granted you the Null Charge ability. This ability will drain an APC's contents to the void, preventing it from recharging \ - or sending power until repaired.") - var/datum/action/cooldown/spell/null_charge/null_charge = new(M) - null_charge.Grant(M) - if(thralls >= CEILING(9 * SSticker.mode.thrall_ratio, 1) && !reviveThrallAcquired) - reviveThrallAcquired = TRUE - to_chat(user, "The power of your thralls has granted you the Black Recuperation ability. This will, after a short time, bring a dead thrall completely back to life \ - with no bodily defects.") - var/datum/action/cooldown/spell/pointed/revive_thrall/revive = new(M) - revive.Grant(M) - if(thralls < victory_threshold) - to_chat(user, span_shadowling("You do not have the power to ascend. You require [victory_threshold] thralls, but only [thralls] living thralls are present.")) - else if(thralls >= victory_threshold) - to_chat(user, span_shadowling("You are now powerful enough to ascend. Use the Ascendance ability when you are ready.")) - to_chat(user, span_shadowling("You may find Ascendance in the Shadowling Evolution tab.")) - for(M in GLOB.alive_mob_list) - if(is_shadow(M)) - var/datum/action/cooldown/spell/collective_mind/CM - if(CM in M.actions) - M.actions -= CM - qdel(CM) - for(var/datum/action/cooldown/spell/shadowling_hatch/hatch in M.actions) - LAZYREMOVE(M.actions, hatch) - var/datum/action/cooldown/spell/shadowling_ascend/ascend = new(M) - ascend.Grant(M) - if(M == user) - to_chat(user, span_shadowling("You project this power to the rest of the shadowlings.")) - else - to_chat(M, span_shadowling("[user.real_name] has coalesced the strength of the thralls. You can draw upon it at any time to ascend. (Shadowling Evolution Tab)")) //Tells all the other shadowlings - - return TRUE - -/datum/action/cooldown/spell/null_charge - name = "Null Charge" - desc = "Empties an APC, preventing it from recharging until fixed." - panel = "Shadowling Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "null_charge" - - cooldown_time = 1 MINUTES - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/null_charge/cast(mob/living/carbon/human/user) - . = ..() - if(!.) - return FALSE - if(!shadowling_check(user)) - return - - var/list/local_objs = view(1, user) - var/obj/machinery/power/apc/target_apc - for(var/object in local_objs) - if(istype(object, /obj/machinery/power/apc)) - target_apc = object - break - - if(!target_apc) - to_chat(user, span_warning("You must stand next to an APC to drain it!")) - return - - //Free veil since you have to stand next to the thing for a while to depower it. - target_apc.set_light(0) - target_apc.visible_message(span_warning("The [target_apc] flickers and begins to grow dark.")) - - to_chat(user, span_shadowling("You dim the APC's screen and carefully begin siphoning its power into the void.")) - if(!do_after(user, 15 SECONDS, target_apc)) - //Whoops! The APC's light turns back on - to_chat(user, span_shadowling("Your concentration breaks and the APC suddenly repowers!")) - target_apc.set_light(2) - target_apc.visible_message(span_warning("The [target_apc] begins glowing brightly!")) - else - //We did it - to_chat(user, span_shadowling("You return the APC's power to the void, disabling it.")) - target_apc.cell?.charge = 0 //Sent to the shadow realm - target_apc.chargemode = 0 //Won't recharge either until an engineer hits the button - target_apc.charging = 0 - target_apc.update_appearance(UPDATE_ICON) - - return TRUE - -/datum/action/cooldown/spell/blindness_smoke //Spawns a cloud of smoke that blinds non-thralls/shadows and grants slight healing to shadowlings and their allies - name = "Blindness Smoke" - desc = "Spews a cloud of smoke which will blind enemies." - panel = "Shadowling Abilities" - button_icon_state = "black_smoke" - button_icon = 'yogstation/icons/mob/actions.dmi' - - sound = 'sound/effects/bamf.ogg' - cooldown_time = 1 MINUTES - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/blindness_smoke/cast(mob/living/carbon/human/user) //Extremely hacky - . = ..() - if(!.) - return FALSE - if(!shadowling_check(user)) - return - user.visible_message(span_warning("[user] bends over and coughs out a cloud of black smoke!")) - to_chat(user, span_shadowling("You regurgitate a vast cloud of blinding smoke.")) - var/obj/item/reagent_containers/glass/beaker/large/B = new /obj/item/reagent_containers/glass/beaker/large(user.loc) //hacky - B.reagents.clear_reagents() //Just in case! - B.invisibility = INFINITY //This ought to do the trick - B.reagents.add_reagent(/datum/reagent/shadowling_blindness_smoke, 10) - var/datum/effect_system/fluid_spread/smoke/chem/S = new - S.attach(B) - if(S) - S.set_up(4, location = B.loc, carry = B.reagents) - S.start() - qdel(B) - return TRUE - -/datum/action/cooldown/spell/aoe/unearthly_screech //Damages nearby windows, confuses nearby carbons, and outright stuns silly cones - name = "Sonic Screech" - desc = "Deafens, stuns, and confuses nearby people. Also shatters windows." - panel = "Shadowling Abilities" - button_icon_state = "screech" - button_icon = 'yogstation/icons/mob/actions.dmi' - - sound = 'sound/effects/screech.ogg' - aoe_radius = 7 - cooldown_time = 30 SECONDS - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/aoe/unearthly_screech/cast_on_thing_in_aoe(atom/target_atom, mob/living/user) - if(!shadowling_check(user)) - return - user.audible_message(span_warning("[user] lets out a horrible scream!")) - if(isturf(target)) - var/turf/T = target_atom - for(var/mob/target in T.contents) - if(is_shadow_or_thrall(target)) - if(target == user) //No message for the user, of course - continue - else - continue - if(iscarbon(target)) - var/mob/living/carbon/M = target - to_chat(M, span_danger("A spike of pain drives into your head and scrambles your thoughts!")) - M.adjust_confusion(10 SECONDS) - M.adjustEarDamage(0, 30)//as bad as a changeling shriek - else if(issilicon(target)) - var/mob/living/silicon/S = target - to_chat(S, span_warning("ERROR $!(@ ERROR )#^! SENSORY OVERLOAD \[$(!@#")) - playsound(S, 'sound/machines/warning-buzzer.ogg', 50, 1) - var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread - sp.set_up(5, 1, S) - sp.start() - S.Paralyze(5 SECONDS) - for(var/obj/structure/window/W in T.contents) - W.take_damage(rand(80, 100)) - -/datum/action/cooldown/spell/pointed/empower_thrall //turns a thrall into a lesser shadowling - name = "Dark Acceleration" - desc = "Empowers a thrall. You can only have 3 empowered thralls at a time. Empowered thralls become lesser versions of yourself, gaining a small selection of your abilities as well as your healing in the dark and aversion to light." - panel = "Shadowling Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "darksight" - - cast_range = 1 - cooldown_time = 1 MINUTES - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/pointed/empower_thral/InterceptClickOn(mob/living/user, params, atom/target) - . = ..() - if(!.) - return FALSE - if(!shadowling_check(user)) - return - if(!ishuman(target)) - return - var/mob/living/carbon/human/thrallToEmpower = target - if(!is_thrall(thrallToEmpower)) - to_chat(user, span_warning("[thrallToEmpower] is not a thrall.")) - return - if(thrallToEmpower.stat != CONSCIOUS) - to_chat(user, span_warning("[thrallToEmpower] must be conscious to become empowered.")) - return - if(thrallToEmpower.dna.species.id == "l_shadowling") - to_chat(user, span_warning("[thrallToEmpower] is already empowered.")) - return - var/empowered_thralls = 0 - for(var/datum/mind/M in SSticker.mode.thralls) - if(!ishuman(M.current)) - return - var/mob/living/carbon/human/H = M.current - if(H.dna.species.id == "l_shadowling") - empowered_thralls++ - if(empowered_thralls >= EMPOWERED_THRALL_LIMIT) - to_chat(user, span_warning("You cannot spare this much energy. There are too many empowered thralls.")) - return - user.visible_message(span_danger("[user] places their hands over [thrallToEmpower]'s face, red light shining from beneath."), \ - span_shadowling("You place your hands on [thrallToEmpower]'s face and begin gathering energy...")) - to_chat(thrallToEmpower, span_userdanger("[user] places their hands over your face. You feel energy gathering. Stand still...")) - if(!do_after(user, 8 SECONDS, thrallToEmpower)) - to_chat(user, span_warning("Your concentration snaps. The flow of energy ebbs.")) - return - to_chat(user, span_shadowling("You release a massive surge of power into [thrallToEmpower]!")) - user.visible_message(span_boldannounce("Red lightning surges into [thrallToEmpower]'s face!")) - playsound(thrallToEmpower, 'sound/weapons/Egloves.ogg', 50, 1) - playsound(thrallToEmpower, 'sound/machines/defib_zap.ogg', 50, 1) - user.Beam(thrallToEmpower,icon_state="red_lightning",time=1) - thrallToEmpower.Knockdown(5) - thrallToEmpower.visible_message(span_warning("[thrallToEmpower] collapses, their skin and face distorting!"), \ - span_userdanger("AAAAAAAAAAAAAAAAAAAGH-")) - if (!do_after(user, 5, thrallToEmpower)) - thrallToEmpower.Unconscious(1 MINUTES) - thrallToEmpower.visible_message(span_warning("[thrallToEmpower] gasps, and passes out!"), span_warning("That... feels nice....")) - to_chat(user, span_warning("We have been interrupted! [thrallToEmpower] will need to rest to recover.")) - return - thrallToEmpower.visible_message(span_warning("[thrallToEmpower] slowly rises, no longer recognizable as human."), \ - "You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \ - darkness but wither slowly in light. In addition, Lesser Glare has been upgraded into it's true form, and you've been given the ability to turn off nearby lights.") - thrallToEmpower.set_species(/datum/species/shadow/ling/lesser) - for(var/datum/action/cooldown/spell/pointed/lesser_glare/lglare in thrallToEmpower.actions) - LAZYREMOVE(thrallToEmpower.actions, lglare) - - var/datum/action/cooldown/spell/pointed/sling/glare/sglare = new(thrallToEmpower) - sglare.Grant(thrallToEmpower) - - var/datum/action/cooldown/spell/aoe/veil/veil = new(thrallToEmpower) - veil.Grant(thrallToEmpower) - - var/datum/action/cooldown/spell/jaunt/void_jaunt/jaunt = new(thrallToEmpower) - jaunt.Grant(thrallToEmpower) - -/datum/action/cooldown/spell/pointed/revive_thrall //Completely revives a dead thrall - name = "Black Recuperation" - desc = "Revives or empowers a thrall." - panel = "Shadowling Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "revive_thrall" - - cast_range = 1 - cooldown_time = 1 MINUTES - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/pointed/revive_thrall/InterceptClickOn(mob/living/user, params, atom/target) - . = ..() - if(!.) - return FALSE - if(!shadowling_check(user)) - return - if(!ishuman(target)) - return - var/mob/living/carbon/human/thrallToRevive = target - if(!is_thrall(thrallToRevive)) - to_chat(user, span_warning("[thrallToRevive] is not a thrall.")) - return - if(thrallToRevive.stat != DEAD) - to_chat(user, span_warning("[thrallToRevive] is not dead.")) - return - if(HAS_TRAIT(thrallToRevive, TRAIT_BADDNA)) - to_chat(user, span_warning("[thrallToRevive] is too far gone.")) - return - - user.visible_message(span_danger("[user] kneels over [thrallToRevive], placing their hands on \his chest."), \ - span_shadowling("You crouch over the body of your thrall and begin gathering energy...")) - thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.", source = thrallToRevive) - if(!do_after(user, 3 SECONDS, thrallToRevive)) - to_chat(user, span_warning("Your concentration snaps. The flow of energy ebbs.")) - return - to_chat(user, span_shadowling("You release a massive surge of power into [thrallToRevive]!")) - user.visible_message(span_boldannounce("Red lightning surges from [user]'s hands into [thrallToRevive]'s chest!")) - playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1) - playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1) - user.Beam(thrallToRevive,icon_state="red_lightning",time=1) - if(thrallToRevive.revive(full_heal = 1)) - thrallToRevive.visible_message( - span_boldannounce("[thrallToRevive] heaves in breath, dim red light shining in their eyes."), \ - span_shadowling("You have returned. One of your masters has brought you from the darkness beyond."), \ - ) - thrallToRevive.Knockdown(4) - thrallToRevive.emote("gasp") - playsound(thrallToRevive, "bodyfall", 50, 1) - if (!do_after(user, 2 SECONDS, thrallToRevive)) - thrallToRevive.Knockdown(50) - thrallToRevive.Unconscious(500) - thrallToRevive.visible_message(span_boldannounce("[thrallToRevive] collapses in exhaustion."), \ - span_warning("You collapse in exhaustion... nap..... dark.")) - - return TRUE - -/datum/action/cooldown/spell/pointed/shadowling_extend_shuttle - name = "Destroy Engines" - desc = "Sacrifice a thrall to extend the time of the emergency shuttle's arrival by fifteen minutes. This can only be used once." - panel = "Shadowling Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "extend_shuttle" - - cast_range = 1 - cooldown_time = 1 MINUTES - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/pointed/shadowling_extend_shuttle/InterceptClickOn(mob/living/user, params, atom/target_atom) - . = ..() - if(!.) - return FALSE - if(!shadowling_check(user)) - return - if(!ishuman(target_atom)) - return - var/mob/living/carbon/human/target = target_atom - if(target.stat) - return - if(!is_thrall(target)) - to_chat(user, span_warning("[target] must be a thrall.")) - return - if(SSshuttle.emergency.mode != SHUTTLE_CALL) - to_chat(user, "span class='warning'>The shuttle must be inbound only to the station.") - return - var/mob/living/carbon/human/M = target - user.visible_message(span_warning("[user]'s eyes flash a bright red!"), \ - span_notice("You begin to draw [M]'s life force.")) - M.visible_message(span_warning("[M]'s face falls slack, their jaw slightly distending."), \ - span_boldannounce("You are suddenly transported... far, far away...")) - if(!do_after(user, 5 SECONDS, M)) - to_chat(M, span_warning("You are snapped back to reality, your haze dissipating!")) - to_chat(user, span_warning("You have been interrupted. The draw has failed.")) - return - to_chat(user, span_notice("You project [M]'s life force toward the approaching shuttle, extending its arrival duration!")) - M.visible_message(span_warning("[M]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing."), \ - span_warning("...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...")) - M.dust() - - if(SSshuttle.emergency.mode == SHUTTLE_CALL) - var/more_minutes = 9000 - var/timer = SSshuttle.emergency.timeLeft() - timer += more_minutes - priority_announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 15 minutes...", "System Failure", 'sound/misc/notice1.ogg') - SSshuttle.emergency.setTimer(timer) - SSshuttle.emergencyNoRecall = TRUE - user.actions.Remove(src) //Can only be used once! - qdel(src) - - return TRUE - -//Loosely adapted from the Nightmare's Shadow Walk, but different enough that -//inheriting would have been more hacky code. -//Unlike Shadow Walk, jaunting shadowlings can move through lit areas unmolested, -//but take a constant stamina penalty while jaunting. -/datum/action/cooldown/spell/jaunt/void_jaunt - name = "Void Jaunt" - desc = "Move through the void for a time, avoiding mortal eyes and lights." - panel = "Shadowling Abilities" - button_icon = 'icons/mob/actions/actions_spells.dmi' - button_icon_state = "jaunt" - - cooldown_time = 80 SECONDS - spell_requirements = SPELL_REQUIRES_HUMAN - var/apply_damage = TRUE - -/datum/action/cooldown/spell/jaunt/void_jaunt/cast(mob/living/user) - . = ..() - if(!.) - return FALSE - if(iscarbon(user)) //If we're not an ascendant sling - var/mob/living/carbon/C = user - if(C.on_fire) - user.visible_message(span_boldwarning("[user]'s body shudders and flickers into darkness for a moment!"), - span_shadowling("The void rejects the flames engulfing your body, throwing you back into the burning light!")) - return - if(!shadowling_check(user) && !istype(user, /mob/living/simple_animal/ascendant_shadowling)) - return - if(is_jaunting(user)) - exit_jaunt() - return - else - playsound(get_turf(user), 'sound/magic/ethereal_enter.ogg', 50, 1, -1) - if(apply_damage) - user.visible_message(span_boldwarning("[user] melts into the shadows!"), - span_shadowling("Steeling yourself, you dive into the void.")) - else - user.visible_message(span_boldwarning("[user] melts into the shadows!"), - span_shadowling("You allow yourself to fall into the void.")) - user.SetAllImmobility(0) - user.setStaminaLoss(0, 0) - var/obj/effect/dummy/phased_mob/shadowling/S2 = new(get_turf(user.loc)) - S2.apply_damage = apply_damage - user.forceMove(S2) - S2.jaunter = user - S2.jaunt_spell = src - - return TRUE - -//Both have to be high to cancel out natural regeneration -#define VOIDJAUNT_STAM_PENALTY_DARK 10 -#define VOIDJAUNT_STAM_PENALTY_LIGHT 35 - -/obj/effect/dummy/phased_mob/shadowling - name = "darkness" - icon = 'icons/effects/effects.dmi' - icon_state = "nothing" - var/canmove = TRUE - density = FALSE - anchored = TRUE - invisibility = 60 - resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - - var/apply_damage = TRUE - var/move_delay = 0 //Time until next move allowed - var/move_speed = 2 //Deciseconds per move - - var/datum/action/cooldown/spell/jaunt/void_jaunt/jaunt_spell //what spell we actually came from (for forced cooldown) - -/obj/effect/dummy/phased_mob/shadowling/relaymove(mob/user, direction) - if(move_delay > world.time && apply_damage) //Ascendants get no slowdown - return - - move_delay = world.time + move_speed - var/turf/newLoc = get_step(src,direction) - forceMove(newLoc) - -/obj/effect/dummy/phased_mob/shadowling/proc/check_light_level() - var/turf/T = get_turf(src) - var/light_amount = T.get_lumcount() - if(!isliving(jaunter)) - return - var/mob/living/jaunter_living = jaunter - if(light_amount > LIGHT_DAM_THRESHOLD) //Increased penalty - jaunter_living.apply_damage(VOIDJAUNT_STAM_PENALTY_LIGHT, STAMINA) - else - jaunter_living.apply_damage(VOIDJAUNT_STAM_PENALTY_DARK, STAMINA) - -/obj/effect/dummy/phased_mob/shadowling/eject_jaunter(mob/living/unjaunter, turf/loc_override, forced) - if(unjaunter) - unjaunter.forceMove(get_turf(src)) - if(forced) - unjaunter.visible_message(span_boldwarning("A dark shape stumbles from a hole in the air and collapses!"), - span_shadowling("Straining, you use the last of your energy to force yourself from the void.")) - else - unjaunter.visible_message(span_boldwarning("A dark shape tears itself from nothingness!"), - span_shadowling("You exit the void.")) - - playsound(get_turf(jaunter), 'sound/magic/ethereal_exit.ogg', 50, 1, -1) - jaunt_spell?.StartCooldown() - jaunter = null - qdel(src) - -/obj/effect/dummy/phased_mob/shadowling/Initialize(mapload) - . = ..() - START_PROCESSING(SSobj, src) - -/obj/effect/dummy/phased_mob/shadowling/Destroy() - STOP_PROCESSING(SSobj, src) - . = ..() - -/obj/effect/dummy/phased_mob/shadowling/process() - if(!jaunter) - qdel(src) - if(jaunter.loc != src) - qdel(src) - - if(apply_damage) - check_light_level() - - //True if jaunter entered stamcrit - var/mob/living/jaunter_living = jaunter - if(jaunter_living.IsParalyzed()) - eject_jaunter(forced = TRUE) - return - -/obj/effect/dummy/phased_mob/shadowling/ex_act() - return - -/obj/effect/dummy/phased_mob/shadowling/bullet_act() - return BULLET_ACT_FORCE_PIERCE - -/obj/effect/dummy/phased_mob/shadowling/singularity_act() - return - -#undef VOIDJAUNT_STAM_PENALTY_DARK -#undef VOIDJAUNT_STAM_PENALTY_LIGHT - - -// THRALL ABILITIES BEYOND THIS POINT // -/datum/action/cooldown/spell/pointed/lesser_glare //a defensive ability, nothing else. can't be used to stun people, steal tasers, etc. Just good for escaping - name = "Lesser Glare" - desc = "Makes a single target dizzy for a bit." - panel = "Thrall Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "glare" - ranged_mousepointer = 'icons/effects/mouse_pointers/cult_target.dmi' - - cooldown_time = 45 SECONDS - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/pointed/lesser_glare/InterceptClickOn(mob/living/carbon/user, params, atom/target) - . = ..() - if(!.) - return FALSE - if(!user.getorganslot(ORGAN_SLOT_EYES)) - to_chat(user, span_warning("You need eyes to glare!")) - return - if(!ishuman(target) || !target) - to_chat(user, span_warning("You may only glare at humans!")) - return - var/mob/living/carbon/human/M = target - if(M.stat) - to_chat(user, span_warning("[target] must be conscious!")) - return - if(is_shadow_or_thrall(M)) - to_chat(user, span_warning("You cannot glare at allies!")) - return - user.visible_message(span_warning("[user]'s eyes flash a bright red!")) - target.visible_message(span_danger("[target] suddendly looks dizzy and nauseous...")) - if(in_range(target, user)) - to_chat(target, span_userdanger("Your gaze is forcibly drawn into [user]'s eyes, and you suddendly feel dizzy and nauseous...")) - else //Only alludes to the thrall if the target is close by - to_chat(target, span_userdanger("Red lights suddenly dance in your vision, and you suddendly feel dizzy and nauseous...")) - M.adjust_confusion(25 SECONDS) - M.adjust_jitter(50 SECONDS) - if(prob(25)) - M.vomit(10) - - return TRUE - -/datum/action/cooldown/spell/lesser_shadow_walk //Thrall version of Shadow Walk, only works in darkness, doesn't grant phasing, but gives near-invisibility - name = "Guise" - desc = "Wraps your form in shadows, making you harder to see." - panel = "Thrall Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "shadow_walk" - - cooldown_time = 2 MINUTES - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/lesser_shadow_walk/proc/reappear(mob/living/carbon/human/user) - user.visible_message(span_warning("[user] appears from nowhere!"), span_shadowling("Your shadowy guise slips away.")) - user.alpha = initial(user.alpha) - -/datum/action/cooldown/spell/lesser_shadow_walk/cast(mob/living/carbon/human/user) - . = ..() - if(!.) - return FALSE - user.visible_message(span_warning("[user] suddenly fades away!"), span_shadowling("You veil yourself in darkness, making you harder to see.")) - user.alpha = 10 - addtimer(CALLBACK(src, PROC_REF(reappear), user), 10 SECONDS) - - return TRUE - -/datum/action/cooldown/spell/thrall_night_vision //Toggleable night vision for thralls - name = "Thrall Darksight" - desc = "Allows you to see in the dark!" - button_icon_state = "darksight" - button_icon = 'yogstation/icons/mob/actions.dmi' - - spell_requirements = NONE - -/datum/action/cooldown/spell/thrall_night_vision/cast(mob/living/carbon/human/user) - . = ..() - if(!.) - return FALSE - if(!is_shadow_or_thrall(user)) - return - var/obj/item/organ/eyes/eyes = user.getorganslot(ORGAN_SLOT_EYES) - if(!eyes) - return - eyes.sight_flags = initial(eyes.sight_flags) - switch(eyes.lighting_alpha) - if (LIGHTING_PLANE_ALPHA_VISIBLE) - eyes.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE - eyes.see_in_dark = 8 - if (LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE) - eyes.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE - if (LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE) - eyes.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE - else - eyes.lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE - eyes.see_in_dark = 2 //default - user.update_sight() - - return TRUE - -/datum/action/cooldown/spell/lesser_shadowling_hivemind //Lets a thrall talk with their allies - name = "Lesser Commune" - desc = "Allows you to silently communicate with all other shadowlings and thralls." - panel = "Thrall Abilities" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "commune" - - cooldown_time = 5 SECONDS - spell_requirements = SPELL_REQUIRES_HUMAN - -/datum/action/cooldown/spell/lesser_shadowling_hivemind/cast(mob/living/carbon/human/user) - . = ..() - if(!.) - return FALSE - if(!is_shadow_or_thrall(user)) - to_chat(user, span_warning("As you attempt to commune with the others, an agonizing spike of pain drives itself into your head!")) - user.apply_damage(10, BRUTE, "head") - return - var/text = stripped_input(user, "What do you want to say your masters and fellow thralls?.", "Lesser Commune", "") - if(!text) - return - text = span_shadowling("\[Thrall\] [user.real_name]: [text]") - for(var/T in GLOB.alive_mob_list) - var/mob/M = T - if(is_shadow_or_thrall(M)) - to_chat(M, text) - if(isobserver(M)) - to_chat(M, "(F) [text]") - log_say("[user.real_name]/[user.key] : [text]") - - return TRUE - -// ASCENDANT ABILITIES BEYOND THIS POINT // -// YES THEY'RE OP, BUT THEY'VE WON AT THE POINT WHERE THEY HAVE THIS, SO WHATEVER. // -/datum/action/cooldown/spell/pointed/sling/annihilate //Gibs someone instantly. - name = "Annihilate" - desc = "Gibs someone instantly." - panel = "Ascendant" - button_icon_state = "annihilate" - button_icon = 'yogstation/icons/mob/actions.dmi' - - sound = 'sound/magic/Staff_Chaos.ogg' - spell_requirements = NONE - -/datum/action/cooldown/spell/pointed/sling/annihilate/InterceptClickOn(mob/living/caller, params, atom/target) - . = ..() - if(!.) - return FALSE - var/mob/living/boom = target - if(user.incorporeal_move) - to_chat(user, span_warning("You are not in the same plane of existence. Unphase first.")) - revert_cast() - return - if(is_shadow(boom)) //Used to not work on thralls. Now it does so you can PUNISH THEM LIKE THE WRATHFUL GOD YOU ARE. - to_chat(user, "Making an ally explode seems unwise.") - revert_cast() - return - if(istype(boom, /mob/living/simple_animal/pet/dog/corgi)) - to_chat(user, "Not even we are that bad of monsters..") - revert_cast() - return - if (!boom.is_holding(/obj/item/storage/backpack/holding)) //so people actually have a chance to kill ascended slings without being insta-sploded - user.visible_message(span_warning("[user]'s markings flare as they gesture at [boom]!"), \ - span_shadowling("You direct a lance of telekinetic energy into [boom].")) - if(iscarbon(boom)) - playsound(boom, 'sound/magic/Disintegrate.ogg', 100, 1) - boom.visible_message(span_userdanger("[boom] explodes!")) - boom.gib() - else - to_chat(user, "The telekinetic energy is absorbed by the bluespace portal in [boom]'s hand!") - to_chat(boom, "You feel a slight recoil from the bag of holding!") - -/datum/action/cooldown/spell/pointed/sling/hypnosis //Enthralls someone instantly. Nonlethal alternative to Annihilate - name = "Hypnosis" - desc = "Instantly enthralls a human." - panel = "Ascendant" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "enthrall" - - spell_requirements = NONE - -/datum/action/cooldown/spell/pointed/sling/hypnosis/InterceptClickOn(mob/living/caller, params, atom/target_atom) - . = ..() - if(!.) - return - if(!iscarbon(target_atom)) - return - var/mob/living/carbon/target = target_atom - if(user.incorporeal_move) - revert_cast() - to_chat(user, span_warning("You are not in the same plane of existence. Unphase first.")) - return - if(is_shadow_or_thrall(target)) - to_chat(user, span_warning("You cannot enthrall an ally.")) - revert_cast() - return - if(!target.ckey || !target.mind) - to_chat(user, span_warning("The target has no mind.")) - revert_cast() - return - if(target.stat) - to_chat(user, span_warning("The target must be conscious.")) - revert_cast() - return - if(!ishuman(target)) - to_chat(user, span_warning("You can only enthrall humans.")) - revert_cast() - return - to_chat(user, span_shadowling("You instantly rearrange [target]'s memories, hyptonitizing them into a thrall.")) - to_chat(target, span_userdanger("An agonizing spike of pain drives into your mind, and--")) - target.mind.special_role = "thrall" - target.add_thrall() - -/datum/action/cooldown/spell/aoe/ascendant_storm //Releases bolts of lightning to everyone nearby - name = "Lightning Storm" - desc = "Shocks everyone nearby." - panel = "Ascendant" - button_icon_state = "lightning_storm" - button_icon = 'yogstation/icons/mob/actions.dmi' - - sound = 'sound/magic/lightningbolt.ogg' - aoe_radius = 6 - cooldown_time = 10 SECONDS - spell_requirements = NONE - -/datum/action/cooldown/spell/aoe/ascendant_storm/cast_on_thing_in_aoe(turf/victim, mob/living/user) - if(user.incorporeal_move) - to_chat(user, span_warning("You are not in the same plane of existence. Unphase first.")) - return - user.visible_message(span_warning("A massive ball of lightning appears in [user]'s hands and flares out!"), \ - span_shadowling("You conjure a ball of lightning and release it.")) - for(var/mob/living/carbon/human/target in view(aoe_radius)) - if(is_shadow_or_thrall(target)) - continue - to_chat(target, span_userdanger("You're struck by a bolt of lightning!")) - target.apply_damage(10, BURN) - playsound(target, 'sound/magic/LightningShock.ogg', 50, 1) - target.Knockdown(8 SECONDS) - user.Beam(target,icon_state="red_lightning",time=10) - -/datum/action/cooldown/spell/shadowling_hivemind_ascendant //Large, all-caps text in shadowling chat - name = "Ascendant Commune" - desc = "Allows you to LOUDLY communicate with all other shadowlings and thralls." - panel = "Ascendant" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "commune" - - spell_requirements = NONE - -/datum/action/cooldown/spell/shadowling_hivemind_ascendant/cast(mob/living/carbon/human/user) - . = ..() - if(!.) - return FALSE - var/text = sanitize(tgui_input_text(user, "What do you want to say to fellow thralls and shadowlings?.", "Hive Chat", "")) - if(!text) - return - text = "\[Ascendant\] [user.real_name]: [text]" - for(var/mob/M in GLOB.mob_list) - if(is_shadow_or_thrall(M)) - to_chat(M, text) - if(isobserver(M)) - to_chat(M, "(F) [text]") - log_say("[user.real_name]/[user.key] : [text]") - -/datum/action/cooldown/spell/pointed/sling/instant_enthrall //Enthralls someone instantly. Nonlethal alternative to Annihilate - name = "Subjugate" - desc = "Instantly enthrall a weakling." - panel = "Ascendant" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "gore" - - spell_requirements = NONE - -/datum/action/cooldown/spell/jaunt/void_jaunt/ascendant - name = "Void Walk" - desc = "Move invisibly through the void between worlds, shielded from mortal eyes." - panel = "Ascendant" - - apply_damage = FALSE diff --git a/yogstation/code/modules/antagonists/shadowling/shadowling_items.dm b/yogstation/code/modules/antagonists/shadowling/shadowling_items.dm deleted file mode 100644 index c1f40312c7d6..000000000000 --- a/yogstation/code/modules/antagonists/shadowling/shadowling_items.dm +++ /dev/null @@ -1,42 +0,0 @@ -/obj/item/clothing/suit/space/shadowling - name = "chitin shell" - desc = "A dark, semi-transparent shell. Protects against vacuum, but not against the light of the stars." //Still takes damage from spacewalking but is immune to space itself - mob_overlay_icon = 'yogstation/icons/mob/clothing/suit/suit.dmi' - icon = 'yogstation/icons/obj/clothing/suits.dmi' - icon_state = "sl_shell" - item_state = "sl_shell" - body_parts_covered = FULL_BODY //Shadowlings are immune to space - cold_protection = FULL_BODY - min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - flags_inv = HIDEGLOVES | HIDESHOES | HIDEJUMPSUIT - slowdown = 0 - heat_protection = null //You didn't expect a light-sensitive creature to have heat resistance, did you? - max_heat_protection_temperature = null - armor = list(MELEE = 30, BULLET = 30, LASER = 0, ENERGY = 0, BOMB = 25, BIO = 100, RAD = 100) - item_flags = ABSTRACT | DROPDEL - clothing_flags = THICKMATERIAL | STOPSPRESSUREDAMAGE - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - -/obj/item/clothing/suit/space/shadowling/Initialize(mapload) - .=..() - ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) - -/obj/item/clothing/head/shadowling - name = "chitin helm" - desc = "A helmet-like enclosure of the head." - mob_overlay_icon = 'yogstation/icons/mob/clothing/suit/suit.dmi' - icon = 'yogstation/icons/obj/clothing/hats.dmi' - icon_state = "sl_head" - item_state = "sl_head" - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT - heat_protection = HEAD - max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT - armor = list(MELEE = 30, BULLET = 30, LASER = 0, ENERGY = 0, BOMB = 25, BIO = 100, RAD = 100) - clothing_flags = STOPSPRESSUREDAMAGE - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - item_flags = ABSTRACT | DROPDEL - -/obj/item/clothing/head/shadowling/Initialize(mapload) - .=..() - ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) diff --git a/yogstation/code/modules/antagonists/shadowling/special_shadowling_abilities.dm b/yogstation/code/modules/antagonists/shadowling/special_shadowling_abilities.dm deleted file mode 100644 index 4b1b2f9f39a0..000000000000 --- a/yogstation/code/modules/antagonists/shadowling/special_shadowling_abilities.dm +++ /dev/null @@ -1,228 +0,0 @@ -//In here: Hatch and Ascendance -/datum/action/cooldown/spell/shadowling_hatch - name = "Hatch" - desc = "Casts off your disguise." - panel = "Shadowling Evolution" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "hatch" - - cooldown_time = 5 MINUTES - spell_requirements = SPELL_REQUIRES_HUMAN - -/obj/structure/alien/resin/wall/shadowling //For chrysalis - name = "chrysalis wall" - desc = "Some sort of purple substance in an egglike shape. It pulses and throbs from within and seems impenetrable." - max_integrity = INFINITY - -/datum/action/cooldown/spell/shadowling_hatch/cast(mob/living/user) - . = ..() - if(!.) - return FALSE - if(user.stat || !ishuman(user) || !user || !is_shadow(user) || user.isinspace()) - return - var/mob/living/carbon/human/H = user - var/hatch_or_no = tgui_alert(H,"Are you sure you want to hatch? You cannot undo this!","Ello",list("Yes","No")) - switch(hatch_or_no) - if("No") - to_chat(H, span_warning("You decide against hatching for now.")) - return - if("Yes") - H.notransform = TRUE - H.visible_message(span_warning("[H]'s things suddenly slip off. They hunch over and vomit up a copious amount of purple goo which begins to shape around them!"), \ - span_shadowling("You remove any equipment which would hinder your hatching and begin regurgitating the resin which will protect you.")) - var/temp_flags = H.status_flags - H.status_flags |= GODMODE //Can't die while hatching - H.unequip_everything() - if(!do_after(H, 5 SECONDS)) - return - var/turf/shadowturf = get_turf(user) - for(var/turf/open/floor/F in orange(1, user)) - new /obj/structure/alien/resin/wall/shadowling(F) - for(var/obj/structure/alien/resin/wall/shadowling/R in shadowturf) //extremely hacky - qdel(R) - new /obj/structure/alien/weeds/node(shadowturf) //Dim lighting in the chrysalis -- removes itself afterwards - H.visible_message(span_warning("A chrysalis forms around [H], sealing them inside."), \ - span_shadowling("You create your chrysalis and begin to contort within.")) - if(!do_after(H, 10 SECONDS)) - return - H.visible_message(span_warning("The skin on [H]'s back begins to split apart. Black spines slowly emerge from the divide."), \ - span_shadowling("Spines pierce your back. Your claws break apart your fingers. You feel excruciating pain as your true form begins its exit.")) - if(!do_after(H, 9 SECONDS)) - return - H.visible_message(span_warning("[H], skin shifting, begins tearing at the walls around them."), \ - span_shadowling("Your false skin slips away. You begin tearing at the fragile membrane protecting you.")) - if(!do_after(H, 8 SECONDS)) - return - playsound(H.loc, 'sound/weapons/slash.ogg', 25, 1) - to_chat(H, "You rip and slice.") - if(!do_after(H, 1 SECONDS)) - return - playsound(H.loc, 'sound/weapons/slashmiss.ogg', 25, 1) - to_chat(H, "The chrysalis falls like water before you.") - if(!do_after(H, 1 SECONDS)) - return - playsound(H.loc, 'sound/weapons/slice.ogg', 25, 1) - to_chat(H, "You are free!") - H.status_flags = temp_flags - if(!do_after(H, 1 SECONDS)) - return - playsound(H.loc, 'sound/effects/ghost.ogg', 100, 1) - var/newNameId = pick(GLOB.nightmare_names) - var/oldName = H.real_name - GLOB.nightmare_names.Remove(newNameId) - H.real_name = newNameId - H.name = user.real_name - H.notransform = FALSE - to_chat(H, "YOU LIVE!!!") - var/hatchannounce = "[oldName] has hatched into the Shadowling [newNameId]!" - for(var/T in GLOB.alive_mob_list) - var/mob/M = T - if(is_shadow_or_thrall(M)) - to_chat(M, hatchannounce) - for(var/T in GLOB.dead_mob_list) - var/mob/M = T - to_chat(M, "(F) [hatchannounce]") - for(var/obj/structure/alien/resin/wall/shadowling/W in orange(1, H)) - playsound(W, 'sound/effects/splat.ogg', 50, 1) - qdel(W) - for(var/obj/structure/alien/weeds/node/N in shadowturf) - qdel(N) - H.visible_message(span_warning("The chrysalis explodes in a shower of purple flesh and fluid!")) - H.underwear = "Nude" - H.undershirt = "Nude" - H.socks = "Nude" - H.faction |= "faithless" - for(var/datum/antagonist/shadowling/antag_datum in H.mind.antag_datums) - antag_datum.show_to_ghosts = TRUE - H.LoadComponent(/datum/component/walk/shadow) - - H.equip_to_slot_or_del(new /obj/item/clothing/suit/space/shadowling(H), ITEM_SLOT_OCLOTHING) - H.equip_to_slot_or_del(new /obj/item/clothing/head/shadowling(H), ITEM_SLOT_HEAD) - H.set_species(/datum/species/shadow/ling) //can't be a shadowling without being a shadowling - H.dna.remove_all_mutations(list(MUT_NORMAL, MUT_EXTRA), TRUE) - Remove(H) - if(!do_after(H, 10 SECONDS)) - return - to_chat(H, span_shadowling("Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies.")) - - var/datum/action/cooldown/spell/pointed/enthrall/enthrall = new(H) - enthrall.Grant(H) - - var/datum/action/cooldown/spell/pointed/sling/glare/glare = new(H) - glare.Grant(H) - - var/datum/action/cooldown/spell/aoe/veil/veil = new(H) - veil.Grant(H) - - var/datum/action/cooldown/spell/jaunt/void_jaunt/void_jaunt = new(H) - void_jaunt.Grant(H) - - var/datum/action/cooldown/spell/jaunt/shadow_walk/shadow_walk = new(H) - shadow_walk.Grant(H) - - var/datum/action/cooldown/spell/aoe/flashfreeze/flashfreeze = new(H) - flashfreeze.Grant(H) - - var/datum/action/cooldown/spell/collective_mind/mind = new(H) - mind.Grant(H) - - var/datum/action/cooldown/spell/shadowling_regenarmor/regen_armor = new(H) - regen_armor.Grant(H) - - var/datum/action/cooldown/spell/pointed/shadowling_extend_shuttle/shuttle_extend = new(H) - shuttle_extend.Grant(H) - - return TRUE - -/datum/action/cooldown/spell/shadowling_ascend - name = "Ascend" - desc = "Enters your true form." - panel = "Shadowling Evolution" - button_icon = 'yogstation/icons/mob/actions.dmi' - button_icon_state = "ascend" - - cooldown_time = 5 MINUTES - spell_requirements = NONE - -/datum/action/cooldown/spell/shadowling_ascend/before_cast(mob/living/user) - . = ..() - if(!.) - return - var/mob/living/carbon/human/H = user - if(!shadowling_check(H)) - return - var/hatch_or_no = tgui_alert(H,"It is time to ascend. Are you sure about this?",,list("Yes","No")) - switch(hatch_or_no) - if("No") - to_chat(H, span_warning("You decide against ascending for now.")) - return - if("Yes") - H.notransform = 1 - H.visible_message(span_warning("[H]'s things suddenly slip off. They gently rise into the air, red light glowing in their eyes."), \ - span_shadowling("You rise into the air and get ready for your transformation.")) - for(var/obj/item/I in H) //drops all items - H.unequip_everything(I) - if(!do_after(H, 5 SECONDS)) - return - H.visible_message(span_warning("[H]'s skin begins to crack and harden."), \ - span_shadowling("Your flesh begins creating a shield around yourself.")) - if(!do_after(H, 10 SECONDS)) - return - H.visible_message(span_warning("The small horns on [H]'s head slowly grow and elongate."), \ - span_shadowling("Your body continues to mutate. Your telepathic abilities grow.")) //y-your horns are so big, senpai...!~ - if(!do_after(H, 9 SECONDS)) - return - H.visible_message(span_warning("[H]'s body begins to violently stretch and contort."), \ - span_shadowling("You begin to rend apart the final barriers to godhood.")) - if(!do_after(H, 4 SECONDS)) - return - to_chat(H, "Yes!") - if(!do_after(H, 1 SECONDS)) - return - to_chat(H, "[span_big("YES!!")]") - if(!do_after(H, 1 SECONDS)) - return - to_chat(H, "[span_reallybig("YE--")]") - if(!do_after(H, 0.1 SECONDS)) - return - for(var/mob/living/M in orange(7, H)) - M.Knockdown(10) - to_chat(M, span_userdanger("An immense pressure slams you onto the ground!")) - send_to_playing_players("\"VYSHA NERADA YEKHEZET U'RUU!!\"") - sound_to_playing_players('sound/hallucinations/veryfar_noise.ogg') - for(var/obj/machinery/power/apc/A in GLOB.apcs_list) - A.overload_lighting() - SSachievements.unlock_achievement(/datum/achievement/greentext/slingascend, H.client) - var/mob/A = new /mob/living/simple_animal/ascendant_shadowling(H.loc) - for(var/datum/action/spell in H.actions) - if(spell == src) - continue - spell.Remove(H) - H.mind.transfer_to(A) - A.name = H.real_name - if(A.real_name) - A.real_name = H.real_name - H.invisibility = 60 //This is pretty bad, but is also necessary for the shuttle call to function properly - H.forceMove(A) - if(!SSticker.mode.shadowling_ascended) - set_security_level(SEC_LEVEL_GAMMA) - SSshuttle.emergencyCallTime = 1800 - SSshuttle.emergency.request(null, 0.3) - SSshuttle.emergencyNoRecall = TRUE - SSticker.mode.shadowling_ascended = TRUE - var/datum/action/cooldown/spell/pointed/sling/annihilate/annihilate = new(A) - annihilate.Grant(A) - - var/datum/action/cooldown/spell/pointed/sling/hypnosis/hypnosis = new(A) - hypnosis.Grant(A) - - var/datum/action/cooldown/spell/aoe/ascendant_storm/storm = new(A) - storm.Grant(A) - - var/datum/action/cooldown/spell/jaunt/void_jaunt/ascendant/jaunt = new(A) - jaunt.Grant(A) - - var/datum/action/cooldown/spell/shadowling_hivemind_ascendant/hivemind = new(A) - hivemind.Grant(A) - Remove(A) - qdel(H) diff --git a/yogstation/code/modules/antagonists/shadowling/thrall.dm b/yogstation/code/modules/antagonists/shadowling/thrall.dm deleted file mode 100644 index c25d821af63a..000000000000 --- a/yogstation/code/modules/antagonists/shadowling/thrall.dm +++ /dev/null @@ -1,71 +0,0 @@ -GLOBAL_LIST_INIT(thrall_spell_types, typecacheof(list(/datum/action/cooldown/spell/lesser_shadowling_hivemind, /datum/action/cooldown/spell/pointed/lesser_glare, /datum/action/cooldown/spell/lesser_shadow_walk, /datum/action/cooldown/spell/thrall_night_vision))) - -/datum/antagonist/thrall - name = "Shadowling Thrall" - job_rank = ROLE_SHADOWLING - antag_hud_name = "thrall" - roundend_category = "thralls" - antagpanel_category = "Shadowlings" - antag_moodlet = /datum/mood_event/thrall - -/datum/antagonist/thrall/can_be_owned(datum/mind/new_owner) - . = ..() - if(.) - var/list/no_team_antag = list( - /datum/antagonist/rev, - /datum/antagonist/clockcult, - /datum/antagonist/darkspawn, - /datum/antagonist/cult, - /datum/antagonist/zombie - ) - for(var/datum/antagonist/NTA in new_owner.antag_datums) - if(NTA.type in no_team_antag) - return FALSE - -/datum/antagonist/thrall/on_gain() - . = ..() - SSticker.mode.thralls += owner - owner.special_role = "thrall" - message_admins("[key_name_admin(owner.current)] was enthralled by a shadowling!") - log_game("[key_name(owner.current)] was enthralled by a shadowling!") - for(var/datum/action/cooldown/spell/spells as anything in GLOB.thrall_spell_types) - spells = new(owner.current) - spells.Grant(owner.current) - -/datum/antagonist/thrall/apply_innate_effects(mob/living/mob_override) - . = ..() - var/mob/living/current_mob = mob_override || owner.current - add_team_hud(current_mob, /datum/antagonist/shadowling) - -/datum/antagonist/thrall/on_removal() - SSticker.mode.thralls -= owner - message_admins("[key_name_admin(owner.current)] was dethralled!") - log_game("[key_name(owner.current)] was dethralled!") - owner.special_role = null - for(var/datum/action/cooldown/spell/spells in owner.current.actions) - if(is_type_in_typecache(spells, GLOB.thrall_spell_types)) //only remove thrall spells! - spells.Remove(owner.current) - var/mob/living/M = owner.current - if(issilicon(M)) - M.audible_message(span_notice("[M] lets out a short blip, followed by a low-pitched beep.")) - to_chat(M,span_userdanger("You have been turned into a[ iscyborg(M) ? " cyborg" : "n AI" ]! You are no longer a thrall! Though you try, you cannot remember anything about your servitude...")) - else - M.visible_message(span_big("[M] looks like their mind is their own again!")) - to_chat(M,span_userdanger("A piercing white light floods your eyes. Your mind is your own again! Though you try, you cannot remember anything about the shadowlings or your time under their command...")) - M.update_sight() - return ..() - -/datum/antagonist/thrall/greet() - to_chat(owner, span_shadowling("You see the truth. Reality has been torn away and you realize what a fool you've been.")) - if(ispreternis(owner.current)) - to_chat(owner, span_shadowling("The shadowlings- your creators, have returned to become gods. Serve them above all else and ensure they complete their goals.")) - else - to_chat(owner, span_shadowling("The shadowlings are your masters. Serve them above all else and ensure they complete their goals.")) - to_chat(owner, span_shadowling("You may not harm other thralls or the shadowlings. However, you do not need to obey other thralls.")) - to_chat(owner, span_shadowling("Your body has been irreversibly altered. The attentive can see this - you may conceal it by wearing a mask.")) - to_chat(owner, span_shadowling("Though not nearly as powerful as your masters, you possess some weak powers. These can be found in the Thrall Abilities tab.")) - to_chat(owner, span_shadowling("You may communicate with your allies by using the Lesser Commune ability.")) - SEND_SOUND(owner.current, sound('yogstation/sound/ambience/antag/thrall.ogg')) - -/datum/antagonist/thrall/roundend_report() - return "[printplayer(owner)]" diff --git a/yogstation/code/modules/reagents/chemistry/reagents/other_reagents.dm b/yogstation/code/modules/reagents/chemistry/reagents/other_reagents.dm index 39fb2af3f4c2..f220ada58d99 100644 --- a/yogstation/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/yogstation/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -16,27 +16,6 @@ if((methods & (PATCH|INGEST|INJECT)) || ((methods & VAPOR) && prob(min(reac_volume,100)*permeability))) L.ForceContractDisease(new /datum/disease/cluwnification(), FALSE, TRUE) -/datum/reagent/shadowling_blindness_smoke - name = "odd black liquid" - description = "<::ERROR::> CANNOT ANALYZE REAGENT <::ERROR::>" - color = "#000000" //Complete black (RGB: 0, 0, 0) - metabolization_rate = 100 //lel - -/datum/reagent/shadowling_blindness_smoke/on_mob_life(mob/living/M) - if(!is_shadow_or_thrall(M)) - to_chat(M, span_warning("You breathe in the black smoke, and your eyes burn horribly!")) - M.blind_eyes(5) - if(prob(25)) - M.visible_message("[M] claws at their eyes!") - M.Stun(3, 0) - . = 1 - else - to_chat(M, span_notice("You breathe in the black smoke, and you feel revitalized!")) - M.adjustOxyLoss(-2, 0) - M.adjustToxLoss(-2, 0) - . = 1 - return ..() || . - /datum/reagent/shadowfrost name = "Shadowfrost" description = "A dark liquid that seems to slow down anything that comes into contact with it." diff --git a/yogstation/code/modules/surgery/organs/shadowling_organs.dm b/yogstation/code/modules/surgery/organs/shadowling_organs.dm deleted file mode 100644 index 309ac0e96d12..000000000000 --- a/yogstation/code/modules/surgery/organs/shadowling_organs.dm +++ /dev/null @@ -1,70 +0,0 @@ -//Snowflake spot for putting sling organ related stuff -/obj/item/organ/eyes/night_vision/alien/sling - name = "shadowling eyes" - desc = "The eyes of a spooky shadowling!" - -/obj/item/organ/internal/shadowtumor - name = "black tumor" - desc = "A tiny black mass with red tendrils trailing from it. It seems to shrivel in the light." - icon_state = "blacktumor" - w_class = 1 - zone = "head" - slot = "brain_tumor" - var/organ_health = 3 - -/obj/item/organ/internal/shadowtumor/New() - ..() - START_PROCESSING(SSobj, src) - -/obj/item/organ/internal/shadowtumor/Destroy() - STOP_PROCESSING(SSobj, src) - ..() - -/obj/item/organ/internal/shadowtumor/process() - if(isturf(loc)) - var/turf/T = loc - var/light_count = T.get_lumcount() - if(light_count > LIGHT_DAM_THRESHOLD && organ_health > 0) //Die in the light - organ_health-- - else if(light_count < LIGHT_HEAL_THRESHOLD && organ_health < 3) //Heal in the dark - organ_health++ - if(organ_health <= 0) - visible_message(span_warning("[src] collapses in on itself!")) - qdel(src) - else - organ_health = min(organ_health+0.5, 3) - -/obj/item/organ/internal/shadowtumor/Insert(mob/living/carbon/M, special, drop_if_replaced) - . = ..() - M.add_thrall() - -/obj/item/organ/internal/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/internal/shadowtumor/Remove(mob/living/carbon/M, special) - if(M.dna.species.id == "l_shadowling") //Empowered thralls cannot be deconverted - to_chat(M, span_shadowling("NOT LIKE THIS!")) - M.visible_message(span_danger("[M] suddenly slams upward and knocks down everyone!")) - M.resting = FALSE //Remove all stuns - M.SetStun(0, 0) - M.SetKnockdown(0) - M.SetUnconscious(0) - for(var/mob/living/user in range(2, src)) - if(iscarbon(user)) - var/mob/living/carbon/C = user - C.Knockdown(6) - C.adjustBruteLoss(20) - else if(issilicon(user)) - var/mob/living/silicon/S = user - S.Knockdown(8) - S.adjustBruteLoss(20) - playsound(S, 'sound/effects/bang.ogg', 50, 1) - return FALSE - var/obj/item/organ/eyes/eyes = M.getorganslot(ORGAN_SLOT_EYES) - eyes.lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE - eyes.sight_flags = initial(eyes.sight_flags) - M.update_sight() - M.remove_thrall() - M.visible_message(span_warning("A strange black mass falls from [M]'s head!")) - return ..() From 2721bad838efcc2a6de3a9f2c0901a6bedcd3faf Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 17:03:30 -0500 Subject: [PATCH 006/756] cleanup --- code/__DEFINES/is_helpers.dm | 2 +- code/__DEFINES/{yogs_defines}/antagonists.dm | 1 - code/datums/elements/frozen.dm | 4 ++ code/datums/traits/negative.dm | 2 +- .../items/implants/implant_mindshield.dm | 2 +- .../bloodsuckers/clans/clan_lasombra.dm | 42 +++++++++++++++++++ .../mob/living/carbon/human/examine.dm | 10 ----- .../nanites/nanite_programs/buffing.dm | 2 - .../carbon/human/species_types/plantpeople.dm | 2 +- .../modules/mob/living/silicon/robot/login.dm | 4 +- 10 files changed, 51 insertions(+), 20 deletions(-) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index b8bf4aba9d65..fd258eb6cdfe 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -15,7 +15,7 @@ #define isnan(x) ( isnum((x)) && ((x) != (x)) ) -#define isinternalorgan(A) (istype(A, /obj/item/organ/internal)) +//#define isinternalorgan(A) (istype(A, /obj/item/organ/internal)) uncomment if we port tg organ code //Turfs //#define isturf(A) (istype(A, /turf)) This is actually a byond built-in. Added here for completeness sake. diff --git a/code/__DEFINES/{yogs_defines}/antagonists.dm b/code/__DEFINES/{yogs_defines}/antagonists.dm index 9b6b434a60b2..7bcefcb93988 100644 --- a/code/__DEFINES/{yogs_defines}/antagonists.dm +++ b/code/__DEFINES/{yogs_defines}/antagonists.dm @@ -1,5 +1,4 @@ #define ANTAG_DATUM_VAMPIRE /datum/antagonist/vampire -#define ANTAG_DATUM_THRALL /datum/antagonist/thrall #define ANTAG_DATUM_DARKSPAWN /datum/antagonist/darkspawn #define ANTAG_DATUM_VEIL /datum/antagonist/veil #define ANTAG_DATUM_INFILTRATOR /datum/antagonist/infiltrator diff --git a/code/datums/elements/frozen.dm b/code/datums/elements/frozen.dm index eb7da45e8f6f..fabcb5aedd7a 100644 --- a/code/datums/elements/frozen.dm +++ b/code/datums/elements/frozen.dm @@ -18,12 +18,14 @@ target_obj.add_atom_colour(GLOB.freon_color_matrix, TEMPORARY_COLOUR_PRIORITY) target_obj.alpha -= 25 + /* uncomment if we end up porting tg organ code if (isinternalorgan(target)) var/obj/item/organ/internal/organ = target organ.organ_flags |= ORGAN_FROZEN else if (isbodypart(target)) for(var/obj/item/organ/internal/organ in target_obj.contents) organ.organ_flags |= ORGAN_FROZEN + */ RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) RegisterSignal(target, COMSIG_MOVABLE_THROW_LANDED, PROC_REF(shatter_on_throw)) @@ -38,12 +40,14 @@ obj_source.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, GLOB.freon_color_matrix) obj_source.alpha += 25 + /* uncomment if we end up porting tg organ code if (isinternalorgan(source)) var/obj/item/organ/internal/organ = source organ.organ_flags &= ~ORGAN_FROZEN else if (isbodypart(source)) for(var/obj/item/organ/internal/organ in obj_source.contents) organ.organ_flags &= ~ORGAN_FROZEN + */ return ..() diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index f6b1817a5f97..f94c6e21d548 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -192,7 +192,7 @@ /datum/quirk/nyctophobia/on_process() var/mob/living/carbon/human/H = quirk_holder - if((H.dna.species.id in list("shadow", "nightmare", "darkspawn")) || (H.mind && (H.mind.has_antag_datum(ANTAG_DATUM_THRALL) || H.mind.has_antag_datum(ANTAG_DATUM_SLING) || H.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) || H.mind.has_antag_datum(ANTAG_DATUM_VEIL)))) //yogs - thrall & sling check + if((H.dna.species.id in list("shadow", "nightmare", "darkspawn")) || (H.mind && (H.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) || H.mind.has_antag_datum(ANTAG_DATUM_VEIL)))) //yogs - thrall & sling check return //we're tied with the dark, so we don't get scared of it; don't cleanse outright to avoid cheese var/turf/T = get_turf(quirk_holder) var/lums = T.get_lumcount() diff --git a/code/game/objects/items/implants/implant_mindshield.dm b/code/game/objects/items/implants/implant_mindshield.dm index 153448b4ba7d..345fd6255cfd 100644 --- a/code/game/objects/items/implants/implant_mindshield.dm +++ b/code/game/objects/items/implants/implant_mindshield.dm @@ -39,7 +39,7 @@ target.visible_message(span_warning("[target] seems to resist the implant!"), span_warning("You feel something interfering with your mental conditioning, but you resist it!")) removed(target, TRUE) return FALSE - if(target.mind.has_antag_datum(/datum/antagonist/gang/boss) || is_shadow_or_thrall(target) || target.mind.has_antag_datum(/datum/antagonist/mindslave)) + if(target.mind.has_antag_datum(/datum/antagonist/gang/boss) || target.mind.has_antag_datum(/datum/antagonist/mindslave)) if(!silent) target.visible_message(span_warning("[target] seems to resist the implant!"), span_warning("You feel something interfering with your mental conditioning, but you resist it!")) removed(target, TRUE) diff --git a/code/modules/antagonists/bloodsuckers/clans/clan_lasombra.dm b/code/modules/antagonists/bloodsuckers/clans/clan_lasombra.dm index 88758963a2af..1bd48e7e7d59 100644 --- a/code/modules/antagonists/bloodsuckers/clans/clan_lasombra.dm +++ b/code/modules/antagonists/bloodsuckers/clans/clan_lasombra.dm @@ -60,3 +60,45 @@ for(var/datum/action/cooldown/spell/power in powers) power = new(vassaldatum.owner.current) power.Grant(vassaldatum.owner.current) + + +// rip shadowlings, but suckers gotta keep their abilities +/datum/action/cooldown/spell/pointed/lesser_glare //a defensive ability, nothing else. can't be used to stun people, steal tasers, etc. Just good for escaping + name = "Lesser Glare" + desc = "Makes a single target dizzy for a bit." + button_icon = 'yogstation/icons/mob/actions.dmi' + button_icon_state = "glare" + ranged_mousepointer = 'icons/effects/mouse_pointers/cult_target.dmi' + + cooldown_time = 45 SECONDS + spell_requirements = SPELL_REQUIRES_HUMAN + +/datum/action/cooldown/spell/pointed/lesser_glare/InterceptClickOn(mob/living/carbon/user, params, atom/target) + . = ..() + if(!.) + return FALSE + if(!user.getorganslot(ORGAN_SLOT_EYES)) + to_chat(user, span_warning("You need eyes to glare!")) + return + if(!ishuman(target) || !target) + to_chat(user, span_warning("You may only glare at humans!")) + return + var/mob/living/carbon/human/M = target + if(M.stat) + to_chat(user, span_warning("[target] must be conscious!")) + return + if(is_shadow_or_thrall(M)) + to_chat(user, span_warning("You cannot glare at allies!")) + return + user.visible_message(span_warning("[user]'s eyes flash a bright red!")) + target.visible_message(span_danger("[target] suddendly looks dizzy and nauseous...")) + if(in_range(target, user)) + to_chat(target, span_userdanger("Your gaze is forcibly drawn into [user]'s eyes, and you suddendly feel dizzy and nauseous...")) + else //Only alludes to the thrall if the target is close by + to_chat(target, span_userdanger("Red lights suddenly dance in your vision, and you suddendly feel dizzy and nauseous...")) + M.adjust_confusion(25 SECONDS) + M.adjust_jitter(50 SECONDS) + if(prob(25)) + M.vomit(10) + + return TRUE diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 5dc0bc67485d..f14bd5830b8a 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -361,12 +361,6 @@ if(stun_absorption[i]["end_time"] > world.time && stun_absorption[i]["examine_message"]) msg += "[t_He] [t_is][stun_absorption[i]["examine_message"]]\n" - if(!glasses && mind && mind.has_antag_datum(ANTAG_DATUM_THRALL)) - if(getorganslot(ORGAN_SLOT_EYES)) - msg += "[t_His] eyes seem unnaturally dark and soulless.\n" // I'VE BECOME SO NUMB, I CAN'T FEEL YOU THERE - else - msg += "The pair of holes where [t_His] eyes would be seem unnaturally dark and soulless.\n" - if((!glasses || !wear_suit) && mind?.has_antag_datum(ANTAG_DATUM_VEIL)) msg += "[t_His] whole body is covered in sigils!\n" @@ -615,10 +609,6 @@ else if(l_limbs_missing >= 2 && r_limbs_missing >= 2) msg += "[t_He] [p_do()]n't seem all there.\n" - - if(!glasses && mind && mind.has_antag_datum(ANTAG_DATUM_THRALL)) - msg += "[t_His] eyes seem unnaturally dark and soulless.\n" // I'VE BECOME SO NUMB, I CAN'T FEEL YOU THERE - if (length(msg)) . += span_warning("[msg.Join("")]") diff --git a/code/modules/research/nanites/nanite_programs/buffing.dm b/code/modules/research/nanites/nanite_programs/buffing.dm index 38da771f9098..b30fb9868d8d 100644 --- a/code/modules/research/nanites/nanite_programs/buffing.dm +++ b/code/modules/research/nanites/nanite_programs/buffing.dm @@ -112,8 +112,6 @@ return if(host_mob.mind.has_antag_datum(/datum/antagonist/gang, TRUE)) return - if(is_shadow_or_thrall(host_mob)) - return if(host_mob.mind.has_antag_datum(/datum/antagonist/veil) || host_mob.mind.has_antag_datum(/datum/antagonist/darkspawn)) return ADD_TRAIT(host_mob, TRAIT_MINDSHIELD, "nanites") diff --git a/yogstation/code/modules/mob/living/carbon/human/species_types/plantpeople.dm b/yogstation/code/modules/mob/living/carbon/human/species_types/plantpeople.dm index 452ab77a369c..d78af29791f4 100644 --- a/yogstation/code/modules/mob/living/carbon/human/species_types/plantpeople.dm +++ b/yogstation/code/modules/mob/living/carbon/human/species_types/plantpeople.dm @@ -59,7 +59,7 @@ C.faction -= "vines" /datum/species/pod/spec_life(mob/living/carbon/human/H) - if(H.stat == DEAD || H.stat == UNCONSCIOUS || (H.mind && H.mind.has_antag_datum(ANTAG_DATUM_THRALL))) + if(H.stat == DEAD || H.stat == UNCONSCIOUS) return if(IS_BLOODSUCKER(H) && !HAS_TRAIT(H, TRAIT_MASQUERADE)) return diff --git a/yogstation/code/modules/mob/living/silicon/robot/login.dm b/yogstation/code/modules/mob/living/silicon/robot/login.dm index 781a72d168e0..279698547d22 100644 --- a/yogstation/code/modules/mob/living/silicon/robot/login.dm +++ b/yogstation/code/modules/mob/living/silicon/robot/login.dm @@ -1,6 +1,4 @@ /mob/living/silicon/robot/Login() ..() if(mind) - remove_thrall() - remove_sling() - remove_vampire() \ No newline at end of file + remove_vampire() From 9911eae6f663266b360880cef646f3a97e4269ac Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 18:19:09 -0500 Subject: [PATCH 007/756] work --- code/__DEFINES/traits.dm | 1 + code/datums/dna.dm | 2 + .../game/gamemodes/darkspawn/shadow_store.dm | 112 +++++++++--------- .../antagonists/darkspawn/darkspawn.dm | 25 +--- 4 files changed, 64 insertions(+), 76 deletions(-) diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 433a4a5095f2..381a8a7f57b2 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -191,6 +191,7 @@ #define TRAIT_NOLIMBDISABLE "no_limb_disable" #define TRAIT_EASILY_WOUNDED "easy_limb_wound" #define TRAIT_HARDLY_WOUNDED "hard_limb_wound" +#define TRAIT_SPECIESLOCK "species_lock" //prevent species from changing while they have the trait #define TRAIT_TOXINLOVER "toxinlover" #define TRAIT_TOXIMMUNE "toxin_immune" #define TRAIT_NOBREATH "no_breath" diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 7762da8d707f..af844ca4424a 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -471,6 +471,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) + if(HAS_TRAIT(src, TRAIT_SPECIESLOCK))//can't swap species + return if(mrace && has_dna()) var/datum/species/new_race if(ispath(mrace)) diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm index e4b0e8e92f86..cce52caa3c07 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm @@ -3,11 +3,16 @@ #define FIGHTER (1<<1) #define WARLOCK (1<<2) +#define STORE_OFFENSE "offense" //things that you use and it fucks someone up +#define STORE_UTILITY "utility" //things that you use and it does something less straightforward +#define STORE_PASSIVE "passives" //things that always happen all the time + //Used to access the Psi Web to buy abilities. //Accesses the Psi Web, which darkspawn use to purchase abilities using lucidity. Lucidity is drained from people using the Devour Will ability. /datum/antag_menu/shadow_store name = "psi web" ui_name = "PsiWeb" + var/list/show_categories = list(STORE_OFFENSE, STORE_UTILITY, STORE_PASSIVE) /datum/antag_menu/shadow_store/ui_data(mob/user) var/list/data = list() @@ -18,24 +23,32 @@ data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / [darkspawn.lucidity_needed] unique drained total" - var/list/upgrades = list() + for(var/category in show_categories) + var/list/category_data = list() + category_data["name"] = category - for(var/path in subtypesof(/datum/shadow_store)) - var/datum/shadow_store/selection = path + var/list/upgrades = list() + for(var/path in subtypesof(/datum/shadow_store)) + var/datum/shadow_store/selection = new path - if(!selection.check_show(user)) - continue + if(!selection.check_show(user)) + continue - var/list/AL = list() - AL["name"] = initial(selection.name) - AL["desc"] = initial(selection.desc) - AL["psi_cost"] = initial(selection.psi_cost) - AL["lucidity_cost"] = initial(selection.lucidity_price) - AL["can_purchase"] = darkspawn.lucidity >= initial(selection.lucidity_price) + var/list/AL = list() + AL["name"] = selection.name + AL["desc"] = selection.desc + AL["psi_cost"] = selection.psi_cost + AL["lucidity_cost"] = selection.lucidity_price + AL["can_purchase"] = darkspawn.lucidity >= selection.lucidity_price + AL["type_path"] = selection.type + + if(category == selection.menutab) + upgrades += list(AL) - upgrades += list(AL) + qdel(selection) - data["upgrades"] = upgrades + categorydata["upgrades"] = upgrades + data["categories"] += list(category_data) return data @@ -43,11 +56,15 @@ if(..()) return var/datum/antagonist/darkspawn/darkspawn = antag_datum + if(!istype(darkspawn)) + return switch(action) if("purchase") - if(istype(params["id"], /datum/shadow_store)) - var/datum/shadow_store/selected = params["id"] - selected.on_purchase(darkspawn?.owner?.current) + var/upgradePath = text2path(params["upgradePath"]) + if(!ispath(upgradePath, /datum/shadow_store)) + return FALSE + var/datum/shadow_store/selected = new upgradePath + selected.on_purchase(darkspawn?.owner?.current) //ability for using the shadow store /datum/action/innate/darkspawn/shadow_store @@ -96,55 +113,51 @@ var/learned_ability ///what is printed when learned var/learn_text + ///what tab of the antag menu does it fall under + var/menutab + ///The antag datum of the owner(used for modifying) + var/datum/antagonist/darkspawn/owner ///Check to see if they should be shown the ability /datum/shadow_store/proc/check_show(mob/user) - SHOULD_CALL_PARENT(TRUE) //for now - var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(!edgy) + if(!menutab) + return FALSE + owner = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(!owner) return FALSE - if(!(edgy.specialization & shadow_flags)) + if(shadow_flags && !(owner.specialization & shadow_flags)) return FALSE - if(edgy.has_upgrade(name))//if they already have it + if(locate(type) in owner.upgrades)//if they already have it return FALSE return TRUE ///When the button to purchase is clicked /datum/shadow_store/proc/on_purchase(mob/user) - var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(!edgy) + owner = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(!owner) return FALSE - if(!(edgy.specialization & shadow_flags))//they shouldn't even be shown it in the first place, but just in case + if(shadow_flags && !(owner.specialization & shadow_flags))//they shouldn't even be shown it in the first place, but just in case return FALSE - if(edgy.lucidity < lucidity_cost) + if(owner.lucidity < lucidity_cost) return FALSE if(learn_text) to_chat(user, span_velvet(learn_text)) - edgy.lucidity -= lucidity_cost + owner.lucidity -= lucidity_cost activate(user) return TRUE ///If the purchase goes through, this gets called /datum/shadow_store/proc/activate(mob/user) - var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(!edgy) + if(!owner)//no clue how it got here, but alright return - edgy.add_upgrade(src) + owner.upgrades |= src //add it to the list + if(learn_text) + to_chat(user, learn_text) if(learned_ability) var/datum/action/innate/darkspawn/action = new learned_ability action.Grant(user) -///if for whatever reason the ability needs to be removed -/datum/shadow_store/proc/remove(mob/user) - var/datum/antagonist/darkspawn/edgy= user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(!edgy) - return - edgy.remove_upgrade(src) - if(learned_ability) - var/datum/action/innate/darkspawn/action = new learned_ability - action.Remove(user) - /* Purchases to select spec */ @@ -155,25 +168,18 @@ /datum/shadow_store/scout/activate(mob/user) user.LoadComponent(/datum/component/walk/shadow) user.AddComponent(/datum/component/shadow_step) - var/datum/antagonist/darkspawn/edgy = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(edgy)//there's NO way they get here without it - edgy.specialization = SCOUT - + owner.specialization = SCOUT /datum/shadow_store/fighter - name = "shadow step" - desc = "shadow step" + name = "fighter" + desc = "fighter" /datum/shadow_store/fighter/activate(mob/user) - var/datum/antagonist/darkspawn/edgy = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(edgy)//there's NO way they get here without it - edgy.specialization = FIGHTER + owner.specialization = FIGHTER /datum/shadow_store/warlock - name = "shadow step" - desc = "shadow step" + name = "warlock" + desc = "warlock" /datum/shadow_store/warlock/activate(mob/user) - var/datum/antagonist/darkspawn/edgy = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(edgy)//there's NO way they get here without it ... right? - edgy.specialization = WARLOCK + owner.specialization = WARLOCK diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 6d1a373a8f2d..281fdc330916 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -74,7 +74,7 @@ for(var/DM in get_antag_minds(/datum/antagonist/darkspawn)) var/datum/mind/dark_mind = DM if(istype(dark_mind)) - if((dark_mind) && (dark_mind.current.stat != DEAD) && ishuman(dark_mind.current)) + if((dark_mind?.current?.stat != DEAD) && ishuman(dark_mind.current)) return FALSE return TRUE @@ -167,28 +167,6 @@ var/atom/movable/screen/counter = owner.current.hud_used.psi_counter counter.maptext = ANTAG_MAPTEXT(psi, COLOR_DARKSPAWN_PSI) -/datum/antagonist/darkspawn/proc/regain_upgrades() - for(var/A in upgrades) - var/datum/shadow_store/upgrade = upgrades[A] - if(upgrade) - upgrade.remove(owner.current) - upgrade.activate(owner.current) - -/datum/antagonist/darkspawn/proc/has_upgrade(id) - return upgrades[id] - -/datum/antagonist/darkspawn/proc/add_upgrade(id) - if(has_upgrade(id)) - return FALSE - upgrades[id] = id - return TRUE - -/datum/antagonist/darkspawn/proc/remove_upgrade(id) - if(!has_upgrade(id)) - return FALSE - upgrades -= id - return TRUE - /datum/antagonist/darkspawn/proc/begin_force_divulge() if(darkspawn_state != MUNDANE) return @@ -227,6 +205,7 @@ to_chat(user, "Your mind has expanded. The Psi Web is now available. Avoid the light. Keep to the shadows. Your time will come.") user.fully_heal() user.set_species(/datum/species/darkspawn) + ADD_TRAIT(user, TRAIT_SPECIESLOCK, "darkspawn divulge") //prevent them from swapping species which can fuck stuff up show_to_ghosts = TRUE shadow_store = new(src) shadow_store_action = new(shadow_store) From d923044e9e3400cda50afc2238c53242408e5e9e Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 18:36:49 -0500 Subject: [PATCH 008/756] more --- code/modules/mob/living/login.dm | 4 ---- .../code/game/gamemodes/darkspawn/shadow_step.dm | 10 ++++++---- .../code/game/gamemodes/darkspawn/shadow_store.dm | 6 +++--- .../code/modules/antagonists/darkspawn/darkspawn.dm | 5 ++--- .../darkspawn/darkspawn_abilities/_divulge.dm | 3 ++- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index 5b4098da9021..5d784fbcf3ac 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -19,8 +19,4 @@ if(changeling) changeling.regain_powers() - var/datum/antagonist/darkspawn/darkspawn = mind.has_antag_datum(/datum/antagonist/darkspawn) - if(darkspawn) - darkspawn.regain_abilities() - src.client.init_verbs() diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm index 529dcaa20616..a828bea54d00 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm @@ -1,21 +1,23 @@ /datum/component/shadow_step var/speedboost = -1 + var/mob/living/carbon/human/owner /datum/component/shadow_step/Initialize() if(!ishuman(parent)) return COMPONENT_INCOMPATIBLE + owner = parent /datum/component/shadow_step/RegisterWithParent() RegisterSignal(parent, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(apply_darkness_speed)) /datum/component/shadow_step/UnregisterFromParent() UnregisterSignal(parent, COMSIG_MOVABLE_PRE_MOVE) - C.remove_movespeed_modifier(type) + owner.remove_movespeed_modifier(type) /datum/component/shadow_step/proc/apply_darkness_speed() - var/turf/T = get_turf(parent) + var/turf/T = get_turf(owner) var/light_amount = T.get_lumcount() if(light_amount > DARKSPAWN_BRIGHT_LIGHT) - parent.remove_movespeed_modifier(type) + owner.remove_movespeed_modifier(type) else - parent.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=speedboost, blacklisted_movetypes=(FLYING|FLOATING)) + owner.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=speedboost, blacklisted_movetypes=(FLYING|FLOATING)) diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm index cce52caa3c07..3c6b6097c1f8 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm @@ -38,8 +38,8 @@ AL["name"] = selection.name AL["desc"] = selection.desc AL["psi_cost"] = selection.psi_cost - AL["lucidity_cost"] = selection.lucidity_price - AL["can_purchase"] = darkspawn.lucidity >= selection.lucidity_price + AL["lucidity_cost"] = selection.lucidity_cost + AL["can_purchase"] = darkspawn.lucidity >= selection.lucidity_cost AL["type_path"] = selection.type if(category == selection.menutab) @@ -47,7 +47,7 @@ qdel(selection) - categorydata["upgrades"] = upgrades + category_data["upgrades"] = upgrades data["categories"] += list(category_data) return data diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 281fdc330916..83e71c605ca9 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -196,7 +196,7 @@ /datum/antagonist/darkspawn/proc/divulge(forced = FALSE) if(darkspawn_state >= DIVULGED) - return + return FALSE if(forced) owner.current.visible_message( span_boldwarning("[owner.current]'s skin sloughs off, revealing black flesh covered in symbols!"), @@ -211,9 +211,8 @@ shadow_store_action = new(shadow_store) shadow_store_action.Grant(owner.current) shadow_store_action.darkspawn = src - if(/datum/action/innate/darkspawn/divulge in upgrades) - upgrades[/datum/action/innate/darkspawn/divulge].remove darkspawn_state = DIVULGED + return TRUE /datum/antagonist/darkspawn/proc/sacrament() var/mob/living/carbon/human/user = owner.current diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 34daa3db78e7..0de0bedce708 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -79,7 +79,6 @@ L.flash_act(1, 1) L.Knockdown(5 SECONDS) var/old_name = user.real_name - darkspawn.divulge() var/processed_message = span_velvet("\[Mindlink\] [old_name] has removed their human disguise and is now [user.real_name].") for(var/T in GLOB.alive_mob_list) var/mob/M = T @@ -88,3 +87,5 @@ for(var/T in GLOB.dead_mob_list) var/mob/M = T to_chat(M, "(F) [processed_message]") + if(darkspawn.divulge()) + user.Remove(src)//they don't need it anymore From faacb591db26ff33763b963adb0a9dd6dcab1afd Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 18:42:05 -0500 Subject: [PATCH 009/756] it compiles! --- code/game/gamemodes/game_mode.dm | 10 ++++++++++ .../antagonists/bloodsuckers/clans/clan_lasombra.dm | 3 --- .../code/modules/antagonists/darkspawn/darkspawn.dm | 4 ---- .../darkspawn/darkspawn_abilities/_divulge.dm | 2 +- .../darkspawn/darkspawn_abilities/_sacrament.dm | 9 --------- .../darkspawn/darkspawn_objects/dark_bead.dm | 6 +----- 6 files changed, 12 insertions(+), 22 deletions(-) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 4674ca43b4ba..b99598f64f90 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -140,6 +140,16 @@ replacementmode.make_antag_chance(character) return +//replace someone that's job banned +/datum/game_mode/proc/replace_jobbaned_player(mob/living/M, role_type, pref) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [role_type]?", "[role_type]", null, pref, 50, M) + var/mob/dead/observer/theghost = null + if(candidates.len) + theghost = pick(candidates) + to_chat(M, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") + message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)]) to replace a jobbaned player.") + M.ghostize(0) + M.key = theghost.key /// Allows rounds to basically be "rerolled" should the initial premise fall through. Also known as mulligan antags. /datum/game_mode/proc/convert_roundtype() diff --git a/code/modules/antagonists/bloodsuckers/clans/clan_lasombra.dm b/code/modules/antagonists/bloodsuckers/clans/clan_lasombra.dm index 1bd48e7e7d59..18ff7dbddbbd 100644 --- a/code/modules/antagonists/bloodsuckers/clans/clan_lasombra.dm +++ b/code/modules/antagonists/bloodsuckers/clans/clan_lasombra.dm @@ -87,9 +87,6 @@ if(M.stat) to_chat(user, span_warning("[target] must be conscious!")) return - if(is_shadow_or_thrall(M)) - to_chat(user, span_warning("You cannot glare at allies!")) - return user.visible_message(span_warning("[user]'s eyes flash a bright red!")) target.visible_message(span_danger("[target] suddendly looks dizzy and nauseous...")) if(in_range(target, user)) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 83e71c605ca9..087cce910482 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -219,10 +219,6 @@ if(!SSticker.mode.sacrament_done) set_security_level(SEC_LEVEL_GAMMA) addtimer(CALLBACK(src, PROC_REF(sacrament_shuttle_call)), 50) - for(var/A in upgrades) - var/datum/shadow_store/upgrade = upgrades[A] - if(upgrade) - upgrade.remove(owner.current) for(var/datum/action/innate/darkspawn/leftover_ability in user.actions) leftover_ability.Remove(user) QDEL_NULL(leftover_ability) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 0de0bedce708..c263c554f49d 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -88,4 +88,4 @@ var/mob/M = T to_chat(M, "(F) [processed_message]") if(darkspawn.divulge()) - user.Remove(src)//they don't need it anymore + Remove(user)//they don't need it anymore diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index a77db6a3e7e3..ff10b8639441 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -14,15 +14,6 @@ if(!darkspawn || darkspawn.lucidity_drained < SSticker.mode.required_succs) to_chat(usr, span_warning("You do not have enough unique lucidity! ([darkspawn.lucidity_drained] / [SSticker.mode.required_succs])")) return - var/list/unpurchased_upgrades = list() - for(var/V in subtypesof(/datum/darkspawn_upgrade)) - var/datum/darkspawn_upgrade/D = V - if(!darkspawn.has_upgrade(initial(D.id))) - unpurchased_upgrades += initial(D.name) - if(unpurchased_upgrades.len) - var/upgrade_string = unpurchased_upgrades.Join(", ") - to_chat(usr, "[span_warning("You have not purchased all passive upgrades! You are missing:")] [span_danger("[upgrade_string].")]") - return if(alert(usr, "The Sacrament is ready! Are you prepared?", name, "Yes", "No") == "No") return in_use = TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm index 48b4bc757cc9..48e49fdf5620 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm @@ -34,11 +34,7 @@ if(!darkspawn || eating || L == user) //no eating urself ;))))))) return if(!istype(L, /mob/living/carbon)) - to_chat(user, "[L]'s mind is not powerful enough to be of use.") - return - linked_ability = darkspawn.has_ability("devour_will") - if(!linked_ability) //how did you even get this? - qdel(src) + to_chat(user, span_warning("[L]'s mind is not powerful enough to be of use.")) return if(!L.mind || isdarkspawn(L)) to_chat(user, span_warning("You cannot drain allies or the mindless.")) From 7aa5230823732920e2ccbaf3a79cb54d93c1af29 Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 23:09:35 -0500 Subject: [PATCH 010/756] Update shadow_store.dm --- yogstation/code/game/gamemodes/darkspawn/shadow_store.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm index 3c6b6097c1f8..2766b6cfcff1 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm @@ -22,7 +22,7 @@ CRASH("darkspawn menu started with wrong datum.") data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / [darkspawn.lucidity_needed] unique drained total" - + data["specialization"] = darkspawn.specialization for(var/category in show_categories) var/list/category_data = list() category_data["name"] = category From f6cbebfae1dc21a44cd14bfa97ee47dfad3745ac Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 23:28:54 -0500 Subject: [PATCH 011/756] rename and ethereal fix --- code/__DEFINES/{yogs_defines}/mobs.dm | 2 +- .../game/gamemodes/darkspawn/shadow_store.dm | 54 +++++++++---------- .../antagonists/darkspawn/darkspawn.dm | 12 ++--- .../darkspawn/darkspawn_abilities/_divulge.dm | 9 ++-- .../carbon/human/species_types/darkspawn.dm | 2 +- 5 files changed, 40 insertions(+), 39 deletions(-) diff --git a/code/__DEFINES/{yogs_defines}/mobs.dm b/code/__DEFINES/{yogs_defines}/mobs.dm index cbe1ac1f9f0b..b1ba7d41b22d 100644 --- a/code/__DEFINES/{yogs_defines}/mobs.dm +++ b/code/__DEFINES/{yogs_defines}/mobs.dm @@ -8,6 +8,6 @@ #define REGEN_BLOOD_REQUIREMENT 40 // The amount of "blood" that a slimeperson consumes when regenerating a single limb. #define DARKSPAWN_DIM_LIGHT 0.2 //light of this intensity suppresses healing and causes very slow burn damage -#define DARKSPAWN_BRIGHT_LIGHT 0.3 //light of this intensity causes rapid burn damage +#define DARKSPAWN_BRIGHT_LIGHT 0.4 //light of this intensity causes rapid burn damage #define MONKIFY_BLOOD_COEFFICIENT (BLOOD_VOLUME_MONKEY/BLOOD_VOLUME_GENERIC) //the ratio of monkey to human blood volume so a 100% blood volume monkey will not instantly die when you turn it into a human with ~58% blood volume diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm index 2766b6cfcff1..183726f25541 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm @@ -9,12 +9,12 @@ //Used to access the Psi Web to buy abilities. //Accesses the Psi Web, which darkspawn use to purchase abilities using lucidity. Lucidity is drained from people using the Devour Will ability. -/datum/antag_menu/shadow_store +/datum/antag_menu/psi_web name = "psi web" ui_name = "PsiWeb" var/list/show_categories = list(STORE_OFFENSE, STORE_UTILITY, STORE_PASSIVE) -/datum/antag_menu/shadow_store/ui_data(mob/user) +/datum/antag_menu/psi_web/ui_data(mob/user) var/list/data = list() var/datum/antagonist/darkspawn/darkspawn = antag_datum @@ -28,8 +28,8 @@ category_data["name"] = category var/list/upgrades = list() - for(var/path in subtypesof(/datum/shadow_store)) - var/datum/shadow_store/selection = new path + for(var/path in subtypesof(/datum/psi_web)) + var/datum/psi_web/selection = new path if(!selection.check_show(user)) continue @@ -52,7 +52,7 @@ return data -/datum/antag_menu/shadow_store/ui_act(action, params) +/datum/antag_menu/psi_web/ui_act(action, params) if(..()) return var/datum/antagonist/darkspawn/darkspawn = antag_datum @@ -61,42 +61,42 @@ switch(action) if("purchase") var/upgradePath = text2path(params["upgradePath"]) - if(!ispath(upgradePath, /datum/shadow_store)) + if(!ispath(upgradePath, /datum/psi_web)) return FALSE - var/datum/shadow_store/selected = new upgradePath + var/datum/psi_web/selected = new upgradePath selected.on_purchase(darkspawn?.owner?.current) //ability for using the shadow store -/datum/action/innate/darkspawn/shadow_store +/datum/action/innate/darkspawn/psi_web name = "Psi Web" id = "psi_web" desc = "Access the Mindlink directly to unlock and upgrade your supernatural powers." button_icon_state = "psi_web" check_flags = AB_CHECK_CONSCIOUS psi_cost = 0 - var/datum/antag_menu/shadow_store/shadow_store + var/datum/antag_menu/psi_web/psi_web -/datum/action/innate/darkspawn/shadow_store/New(our_target) +/datum/action/innate/darkspawn/psi_web/New(our_target) . = ..() - if(istype(our_target, /datum/antag_menu/shadow_store)) - shadow_store = our_target + if(istype(our_target, /datum/antag_menu/psi_web)) + psi_web = our_target else CRASH("psi_web action created with non web.") -/datum/action/innate/darkspawn/shadow_store/Destroy() - shadow_store = null +/datum/action/innate/darkspawn/psi_web/Destroy() + psi_web = null return ..() -/datum/action/innate/darkspawn/shadow_store/Activate() +/datum/action/innate/darkspawn/psi_web/Activate() if(!darkspawn) return to_chat(usr, "You retreat inwards and touch the Mindlink...") - shadow_store.ui_interact(usr) + psi_web.ui_interact(usr) return TRUE //shadow store datums (upgrades and abilities) -/datum/shadow_store +/datum/psi_web ///Name of the effect var/name = "Basic knowledge" ///Description of the effect @@ -110,7 +110,7 @@ ///What specialization can buy this var/shadow_flags = NONE ///what ability is granted if any - var/learned_ability + var/datum/action/innate/darkspawn/learned_ability ///what is printed when learned var/learn_text ///what tab of the antag menu does it fall under @@ -119,7 +119,7 @@ var/datum/antagonist/darkspawn/owner ///Check to see if they should be shown the ability -/datum/shadow_store/proc/check_show(mob/user) +/datum/psi_web/proc/check_show(mob/user) if(!menutab) return FALSE owner = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) @@ -132,7 +132,7 @@ return TRUE ///When the button to purchase is clicked -/datum/shadow_store/proc/on_purchase(mob/user) +/datum/psi_web/proc/on_purchase(mob/user) owner = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) if(!owner) return FALSE @@ -148,7 +148,7 @@ return TRUE ///If the purchase goes through, this gets called -/datum/shadow_store/proc/activate(mob/user) +/datum/psi_web/proc/activate(mob/user) if(!owner)//no clue how it got here, but alright return owner.upgrades |= src //add it to the list @@ -161,25 +161,25 @@ /* Purchases to select spec */ -/datum/shadow_store/scout +/datum/psi_web/scout name = "shadow step" desc = "shadow step" -/datum/shadow_store/scout/activate(mob/user) +/datum/psi_web/scout/activate(mob/user) user.LoadComponent(/datum/component/walk/shadow) user.AddComponent(/datum/component/shadow_step) owner.specialization = SCOUT -/datum/shadow_store/fighter +/datum/psi_web/fighter name = "fighter" desc = "fighter" -/datum/shadow_store/fighter/activate(mob/user) +/datum/psi_web/fighter/activate(mob/user) owner.specialization = FIGHTER -/datum/shadow_store/warlock +/datum/psi_web/warlock name = "warlock" desc = "warlock" -/datum/shadow_store/warlock/activate(mob/user) +/datum/psi_web/warlock/activate(mob/user) owner.specialization = WARLOCK diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 087cce910482..0554b335473b 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -28,8 +28,8 @@ //upgrade variables var/list/upgrades = list() //An associative list ("id" = null or TRUE) containing the passive upgrades the darkspawn has - var/datum/antag_menu/shadow_store/shadow_store //Antag menu used for opening the UI - var/datum/action/innate/darkspawn/shadow_store/shadow_store_action //Used to link the menu with our antag datum + var/datum/antag_menu/psi_web/psi_web //Antag menu used for opening the UI + var/datum/action/innate/darkspawn/psi_web/psi_web_action //Used to link the menu with our antag datum var/specialization = NONE @@ -207,10 +207,10 @@ user.set_species(/datum/species/darkspawn) ADD_TRAIT(user, TRAIT_SPECIESLOCK, "darkspawn divulge") //prevent them from swapping species which can fuck stuff up show_to_ghosts = TRUE - shadow_store = new(src) - shadow_store_action = new(shadow_store) - shadow_store_action.Grant(owner.current) - shadow_store_action.darkspawn = src + psi_web = new(src) + psi_web_action = new(psi_web) + psi_web_action.Grant(owner.current) + psi_web_action.darkspawn = src darkspawn_state = DIVULGED return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index c263c554f49d..0ce1e37de049 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -13,8 +13,9 @@ if(!ishuman(user)) to_chat(user, span_warning("You need to be human-er to do that!")) return - if(isethereal(user)) - user.set_light(0) + if(isethereal(user))//disable the light for long enough to start divulge + user.dna.species.spec_emp_act(user, EMP_HEAVY) + if(spot.get_lumcount() > DARKSPAWN_DIM_LIGHT) to_chat(user, span_warning("You are only able to divulge in darkness!")) return @@ -68,8 +69,8 @@ sleep(4.5 SECONDS) user.Shake(5, 5, 11 SECONDS) for(var/i in 1 to 20) - to_chat(user, "[pick("I- I- I-", "Mind-", "Sigils-", "Can't think-", "POWER-","TAKE-", "M-M-MOOORE-")]") - sleep(0.11 SECONDS) //Spooky flavor message spam + to_chat(user, "[pick("I- I- I-", "Mind-", "Sigils-", "Can't think-", "POWER-","TAKE-", "M-M-MOOORE-", "THINK")]") + sleep(0.1 SECONDS) //Spooky flavor message spam user.visible_message(span_userdanger("A tremendous shockwave emanates from [user]!"), "YOU ARE FREE!!") playsound(user, 'yogstation/sound/magic/divulge_end.ogg', 50, 0) animate(user, color = initial(user.color), pixel_y = initial(user.pixel_y), time = 3 SECONDS) diff --git a/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm b/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm index ca2809c15057..fe95c6df42c5 100644 --- a/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm +++ b/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm @@ -67,7 +67,7 @@ to_chat(H, span_userdanger("The light singes you!")) H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 40 * light_amount), TRUE) H.adjustCloneLoss(light_burning * 0.2) - if(DARKSPAWN_BRIGHT_LIGHT to DARKSPAWN_BRIGHT_LIGHT) //but quick death in the light + if(DARKSPAWN_BRIGHT_LIGHT to INFINITY) //but quick death in the light if(!H.has_status_effect(STATUS_EFFECT_CREEP)) to_chat(H, span_userdanger("The light burns you!")) H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) From 65aaef9331ca544141c66ad5d3bbdb42a6450fb0 Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 23:33:48 -0500 Subject: [PATCH 012/756] rename --- yogstation.dme | 2 +- .../game/gamemodes/darkspawn/{shadow_store.dm => psi_web.dm} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename yogstation/code/game/gamemodes/darkspawn/{shadow_store.dm => psi_web.dm} (100%) diff --git a/yogstation.dme b/yogstation.dme index 9726cd7cabf2..7798aa0f7b7b 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3823,8 +3823,8 @@ #include "yogstation\code\game\gamemodes\clown_ops\bananium_bomb.dm" #include "yogstation\code\game\gamemodes\darkspawn\darkspawn.dm" #include "yogstation\code\game\gamemodes\darkspawn\darkspawn_hud.dm" +#include "yogstation\code\game\gamemodes\darkspawn\psi_web.dm" #include "yogstation\code\game\gamemodes\darkspawn\shadow_step.dm" -#include "yogstation\code\game\gamemodes\darkspawn\shadow_store.dm" #include "yogstation\code\game\gamemodes\darkspawn\veil.dm" #include "yogstation\code\game\gamemodes\gangs\dominator.dm" #include "yogstation\code\game\gamemodes\gangs\gang_items.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_store.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm similarity index 100% rename from yogstation/code/game/gamemodes/darkspawn/shadow_store.dm rename to yogstation/code/game/gamemodes/darkspawn/psi_web.dm From abdb4d8159e6df4cb268d816a5f62eac450d4c42 Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 23:54:13 -0500 Subject: [PATCH 013/756] more tweaks --- yogstation/code/game/gamemodes/darkspawn/psi_web.dm | 7 +++---- yogstation/code/modules/antagonists/darkspawn/darkspawn.dm | 7 +++++-- .../mob/living/carbon/human/species_types/darkspawn.dm | 6 ++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 183726f25541..27e85fbc7606 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -22,7 +22,9 @@ CRASH("darkspawn menu started with wrong datum.") data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / [darkspawn.lucidity_needed] unique drained total" - data["specialization"] = darkspawn.specialization + data["specialization"] = darkspawn.specialization //whether or not they've picked their specialization + + for(var/category in show_categories) var/list/category_data = list() category_data["name"] = category @@ -37,7 +39,6 @@ var/list/AL = list() AL["name"] = selection.name AL["desc"] = selection.desc - AL["psi_cost"] = selection.psi_cost AL["lucidity_cost"] = selection.lucidity_cost AL["can_purchase"] = darkspawn.lucidity >= selection.lucidity_cost AL["type_path"] = selection.type @@ -105,8 +106,6 @@ var/icon = "" ///Cost of to learn this var/lucidity_cost = 0 - ///Cost of to cast this - var/psi_cost = 0 ///What specialization can buy this var/shadow_flags = NONE ///what ability is granted if any diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 0554b335473b..a1a1b59ecc77 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -26,11 +26,14 @@ var/lucidity_drained = 0 //How much lucidity has been drained from unique players var/lucidity_needed = 20 //how much lucidity is needed to win + //Default light damage variables (modified by some abilities) + var/dark_healing = 5 + var/light_burning = 7 + //upgrade variables - var/list/upgrades = list() //An associative list ("id" = null or TRUE) containing the passive upgrades the darkspawn has + var/list/upgrades = list() //A list of all the upgrades we currently have (actual objects, not just typepaths) var/datum/antag_menu/psi_web/psi_web //Antag menu used for opening the UI var/datum/action/innate/darkspawn/psi_web/psi_web_action //Used to link the menu with our antag datum - var/specialization = NONE // Antagonist datum things like assignment // diff --git a/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm b/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm index fe95c6df42c5..3e24402ed77a 100644 --- a/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm +++ b/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm @@ -45,6 +45,12 @@ . = ..() C.bubble_icon = initial(C.bubble_icon) +/datum/species/darkspawn/spec_updatehealth(mob/living/carbon/human/H) + if(H.mind?.has_antag_datum(ROLE_DARKSPAWN)) + var/datum/antagonist/darkspawn/antag = H.mind.has_antag_datum(ROLE_DARKSPAWN) + dark_healing = antag.dark_healing + light_burning = antag.light_burning + /datum/species/darkspawn/spec_life(mob/living/carbon/human/H) H.bubble_icon = "darkspawn" var/turf/T = H.loc From 8d1e8d529e99af92dcd238c7c923cfba8df94de8 Mon Sep 17 00:00:00 2001 From: Molti Date: Mon, 9 Oct 2023 23:57:04 -0500 Subject: [PATCH 014/756] Update psi_web.dm --- yogstation/code/game/gamemodes/darkspawn/psi_web.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 27e85fbc7606..165a4029548a 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -162,7 +162,7 @@ */ /datum/psi_web/scout name = "shadow step" - desc = "shadow step" + desc = "GO FAST, TOUCH GRASS" /datum/psi_web/scout/activate(mob/user) user.LoadComponent(/datum/component/walk/shadow) @@ -171,14 +171,14 @@ /datum/psi_web/fighter name = "fighter" - desc = "fighter" + desc = "me no think so good" /datum/psi_web/fighter/activate(mob/user) owner.specialization = FIGHTER /datum/psi_web/warlock name = "warlock" - desc = "warlock" + desc = "apartment \"complex\"... really? I find it quite simple" /datum/psi_web/warlock/activate(mob/user) owner.specialization = WARLOCK From 604162b304b838b8003a2fa0327f2012282951f9 Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 00:25:48 -0500 Subject: [PATCH 015/756] Update psi_web.dm --- .../code/game/gamemodes/darkspawn/psi_web.dm | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 165a4029548a..5f0f2cca21d0 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -182,3 +182,25 @@ /datum/psi_web/warlock/activate(mob/user) owner.specialization = WARLOCK + + + +/datum/psi_web/castertest + name = "warlock ability" + desc = "apartment \"complex\"... really? I find it quite simple" + shadow_flags = WARLOCK + +/datum/psi_web/fightertest + name = "fighter ability" + desc = "me no think so good" + shadow_flags = SCOUT + +/datum/psi_web/scouttest + name = "scout ability" + desc = "GO FAST, TOUCH GRASS" + shadow_flags = SCOUT + +/datum/psi_web/everyone + name = "universal ability" + desc = "everyone should see this" + shadow_flags = SCOUT | WARLOCK | FIGHTER From 6dfa229aac8148743d104f8687df79c80c5ea383 Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 00:29:34 -0500 Subject: [PATCH 016/756] ahhhhhhhh --- tgui/packages/tgui/interfaces/{PsiWeb.js => PsiWeb.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tgui/packages/tgui/interfaces/{PsiWeb.js => PsiWeb.tsx} (100%) diff --git a/tgui/packages/tgui/interfaces/PsiWeb.js b/tgui/packages/tgui/interfaces/PsiWeb.tsx similarity index 100% rename from tgui/packages/tgui/interfaces/PsiWeb.js rename to tgui/packages/tgui/interfaces/PsiWeb.tsx From f8b709c67f3b9d5c2212bece2c9de600205bf24d Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 15:19:09 -0500 Subject: [PATCH 017/756] merge species --- code/__DEFINES/mobs.dm | 3 +- code/datums/brain_damage/magic.dm | 2 +- code/datums/diseases/advance/symptoms/heal.dm | 2 +- .../dynamic/dynamic_rulesets_midround.dm | 4 +- code/modules/events/darkspawn.dm | 2 +- code/modules/events/nightmare.dm | 2 +- code/modules/events/swarmer.dm | 2 +- code/modules/events/zombie_infection.dm | 4 +- .../human/species_types/shadowpeople.dm | 110 +++++++++++++++--- .../spells/spell_types/jaunt/shadow_walk.dm | 4 +- .../antagonists/darkspawn/darkspawn.dm | 2 +- .../carbon/human/species_types/darkspawn.dm | 83 ------------- 12 files changed, 106 insertions(+), 114 deletions(-) delete mode 100644 yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 098932955614..22d64e802a36 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -270,7 +270,8 @@ #define MEGAFAUNA_DEFAULT_RECOVERY_TIME 5 -#define SHADOW_SPECIES_LIGHT_THRESHOLD 0.2 +#define SHADOW_SPECIES_DIM_LIGHT 0.2 +#define SHADOW_SPECIES_BRIGHT_LIGHT 0.4 // Offsets defines diff --git a/code/datums/brain_damage/magic.dm b/code/datums/brain_damage/magic.dm index a8920076b464..74b983815a7a 100644 --- a/code/datums/brain_damage/magic.dm +++ b/code/datums/brain_damage/magic.dm @@ -18,7 +18,7 @@ var/turf/T = owner.loc if(istype(T)) var/light_amount = T.get_lumcount() - if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) //if there's enough light, start dying + if(light_amount > SHADOW_SPECIES_DIM_LIGHT) //if there's enough light, start dying if(world.time > next_damage_warning) to_chat(owner, span_warning("The light burns you!")) next_damage_warning = world.time + 100 //Avoid spamming diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 7696fdea5e02..786460502f29 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -205,7 +205,7 @@ if(isturf(M.loc)) //else, there's considered to be no light var/turf/T = M.loc light_amount = min(1,T.get_lumcount()) - 0.5 - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) return power /datum/symptom/heal/darkness/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 0b5069abaa5a..053ae78eb1e1 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -483,7 +483,7 @@ for(var/X in GLOB.xeno_spawn) var/turf/T = X var/light_amount = T.get_lumcount() - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) spawn_locs += T if(!spawn_locs.len) return FALSE @@ -640,7 +640,7 @@ for(var/X in GLOB.xeno_spawn) var/turf/T = X var/light_amount = T.get_lumcount() - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) spawn_locs += T if(!spawn_locs.len) diff --git a/code/modules/events/darkspawn.dm b/code/modules/events/darkspawn.dm index ab8b45230cce..e52e5b2b53b8 100644 --- a/code/modules/events/darkspawn.dm +++ b/code/modules/events/darkspawn.dm @@ -19,7 +19,7 @@ var/list/spawn_locs = list() for(var/turf/T in GLOB.xeno_spawn) var/light_amount = T.get_lumcount() - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) spawn_locs += T if(!spawn_locs.len) diff --git a/code/modules/events/nightmare.dm b/code/modules/events/nightmare.dm index 99f98c6b46d8..f8de79b470b3 100644 --- a/code/modules/events/nightmare.dm +++ b/code/modules/events/nightmare.dm @@ -26,7 +26,7 @@ for(var/X in GLOB.xeno_spawn) var/turf/T = X var/light_amount = T.get_lumcount() - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) spawn_locs += T if(!spawn_locs.len) diff --git a/code/modules/events/swarmer.dm b/code/modules/events/swarmer.dm index 1cdeee0edba6..56c4d9d5d8ff 100644 --- a/code/modules/events/swarmer.dm +++ b/code/modules/events/swarmer.dm @@ -18,7 +18,7 @@ for(var/x in GLOB.xeno_spawn) var/turf/spawn_turf = x var/light_amount = spawn_turf.get_lumcount() - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) spawn_locs += spawn_turf if(!spawn_locs.len) message_admins("No valid spawn locations found in GLOB.xeno_spawn, aborting swarmer spawning...") diff --git a/code/modules/events/zombie_infection.dm b/code/modules/events/zombie_infection.dm index 779be8ee0254..81aa39fbb88b 100644 --- a/code/modules/events/zombie_infection.dm +++ b/code/modules/events/zombie_infection.dm @@ -27,7 +27,7 @@ for(var/X in GLOB.xeno_spawn) var/turf/T = X var/light_amount = T.get_lumcount() - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) spawn_locs += T if(!spawn_locs.len) @@ -43,4 +43,4 @@ message_admins("[ADMIN_LOOKUPFLW(S)] has been made into a Zombie by an event.") log_game("[key_name(S)] was spawned as a Zombie by an event.") spawned_mobs += S - return SUCCESSFUL_SPAWN \ No newline at end of file + return SUCCESSFUL_SPAWN diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index c4b8bd0be8d4..98f303f1a7fa 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -1,5 +1,6 @@ #define HEART_RESPAWN_THRESHHOLD 40 #define HEART_SPECIAL_SHADOWIFY 2 +#define DARKSPAWN_REFLECT_COOLDOWN 15 SECONDS /datum/species/shadow // Humans cursed to stay in the darkness, lest their life forces drain. They regain health in shadow and die in light. @@ -14,17 +15,52 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC mutanteyes = /obj/item/organ/eyes/night_vision - + var/shadow_charges = 0 + var/charge_time = DARKSPAWN_REFLECT_COOLDOWN + var/last_charge = 0 + var/powerful_heal = FALSE + var/dark_healing = 1 + var/light_burning = 1 + +/datum/species/shadow/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) + if(prob(50) && shadow_charges > 0) + H.visible_message(span_danger("The shadows around [H] ripple as they absorb \the [P]!")) + playsound(H, "bullet_miss", 75, 1) + shadow_charges = min(shadow_charges - 1, 0) + return -1 + return 0 /datum/species/shadow/spec_life(mob/living/carbon/human/H) + H.bubble_icon = "darkspawn" var/turf/T = H.loc if(istype(T)) var/light_amount = T.get_lumcount() - - if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) //if there's enough light, start dying - H.take_overall_damage(1,1, 0, BODYPART_ORGANIC) - else if (light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) //heal in the dark - H.heal_overall_damage(1,1, 0, BODYPART_ORGANIC) + switch(light_amount) + if(0 to SHADOW_SPECIES_DIM_LIGHT) //rapid healing and stun reduction in the darkness + H.adjustBruteLoss(-dark_healing) + H.adjustFireLoss(-dark_healing) + H.adjustCloneLoss(-dark_healing) + if(powerful_heal) //only darkspawn and nightmare get this + H.adjustToxLoss(-dark_healing) + H.adjustStaminaLoss(-dark_healing * 20) + H.AdjustStun(-dark_healing * 40) + H.AdjustKnockdown(-dark_healing * 40) + H.AdjustUnconscious(-dark_healing * 40) + H.SetSleeping(0) + H.setOrganLoss(ORGAN_SLOT_BRAIN,0) + if(SHADOW_SPECIES_DIM_LIGHT to SHADOW_SPECIES_BRIGHT_LIGHT) //not bright, but still dim + if(!H.has_status_effect(STATUS_EFFECT_CREEP)) + to_chat(H, span_userdanger("The light singes you!")) + H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 40 * light_amount), TRUE) + H.adjustCloneLoss(light_burning * 0.2) + if(SHADOW_SPECIES_BRIGHT_LIGHT to INFINITY) //but quick death in the light + if(!H.has_status_effect(STATUS_EFFECT_CREEP)) + to_chat(H, span_userdanger("The light burns you!")) + H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) + H.adjustCloneLoss(light_burning) + if(world.time >= charge_time+last_charge) + shadow_charges = min(shadow_charges + 1, 3) + last_charge = world.time /datum/species/shadow/check_roundstart_eligible() if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) @@ -80,6 +116,7 @@ return to_add +////////////////////////////////////////////////////////////////////////////////// /datum/species/shadow/nightmare name = "Nightmare" plural_form = null @@ -92,6 +129,8 @@ mutanteyes = /obj/item/organ/eyes/night_vision/nightmare mutant_organs = list(/obj/item/organ/heart/nightmare) mutantbrain = /obj/item/organ/brain/nightmare + + var/shadow_charges = 1 var/info_text = "You are a Nightmare. The ability shadow walk allows unlimited, unrestricted movement in the dark while activated. \ Your light eater will destroy any light producing objects you attack, as well as destroy any lights a living creature may be holding. You will automatically dodge gunfire and melee attacks when on a dark tile. If killed, you will eventually revive if left in darkness." @@ -102,21 +141,56 @@ C.fully_replace_character_name("[C.real_name]","[pick(GLOB.nightmare_names)]") // Yogs -- fixes nightmares not having special spooky names. this proc takes the old name first, and *THEN* the new name! -/datum/species/shadow/nightmare/bullet_act(obj/projectile/P, mob/living/carbon/human/H) - var/turf/T = H.loc - if(istype(T)) - var/light_amount = T.get_lumcount() - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) - H.visible_message(span_danger("[H] dances in the shadows, evading [P]!")) - playsound(T, "bullet_miss", 75, 1) - return BULLET_ACT_FORCE_PIERCE - return ..() - /datum/species/shadow/nightmare/check_roundstart_eligible() return FALSE -//Organs +///////////////////////////ANTAG//////////////////////////////////////// +/datum/species/shadow/darkspawn + name = "Darkspawn" + id = "darkspawn" + limbs_id = "darkspawn" + sexes = FALSE + nojumpsuit = TRUE + changesource_flags = MIRROR_BADMIN | MIRROR_MAGIC | WABBAJACK | ERT_SPAWN //never put this in the pride pool because they look super valid + siemens_coeff = 0 + brutemod = 0.9 + heatmod = 1.5 + no_equip = list(ITEM_SLOT_MASK, ITEM_SLOT_OCLOTHING, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_ICLOTHING, ITEM_SLOT_SUITSTORE, ITEM_SLOT_HEAD) + species_traits = list(NOBLOOD,NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYESPRITES,NOFLASH) + inherent_traits = list(TRAIT_NOGUNS, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE, TRAIT_NOBREATH, TRAIT_RADIMMUNE, TRAIT_VIRUSIMMUNE, TRAIT_PIERCEIMMUNE, TRAIT_NODISMEMBER, TRAIT_NOHUNGER) + mutanteyes = /obj/item/organ/eyes/night_vision/alien + + powerful_heal = TRUE + shadow_charges = 3 + dark_healing = 5 + light_burning = 7 + +/datum/species/shadow/darkspawn/on_species_gain(mob/living/carbon/C, datum/species/old_species) + . = ..() + C.real_name = "[pick(GLOB.nightmare_names)]" + C.name = C.real_name + if(C.mind) + C.mind.name = C.real_name + C.dna.real_name = C.real_name + +/datum/species/shadow/darkspawn/on_species_loss(mob/living/carbon/C) + . = ..() + C.bubble_icon = initial(C.bubble_icon) + +/datum/species/shadow/spec_life(mob/living/carbon/human/H) + H.bubble_icon = "darkspawn" + . = ..() + +/datum/species/shadow/darkspawn/spec_updatehealth(mob/living/carbon/human/H) + if(H.mind?.has_antag_datum(ROLE_DARKSPAWN)) + var/datum/antagonist/darkspawn/antag = H.mind.has_antag_datum(ROLE_DARKSPAWN) + dark_healing = antag.dark_healing + light_burning = antag.light_burning + +/datum/species/shadow/darkspawn/spec_death(gibbed, mob/living/carbon/human/H) + playsound(H, 'yogstation/sound/creatures/darkspawn_death.ogg', 50, FALSE) +/////////////////////////////Organs///////////////////////////////////// /obj/item/organ/brain/nightmare name = "tumorous mass" desc = "A fleshy growth that was dug out of the skull of a Nightmare." @@ -190,7 +264,7 @@ if(istype(T)) var/light_amount = T.get_lumcount() - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) respawn_progress++ playsound(owner,'sound/effects/singlebeat.ogg',40,1) if(respawn_progress >= HEART_RESPAWN_THRESHHOLD) diff --git a/code/modules/spells/spell_types/jaunt/shadow_walk.dm b/code/modules/spells/spell_types/jaunt/shadow_walk.dm index 1b36a0e69501..4b2a1d8b908d 100644 --- a/code/modules/spells/spell_types/jaunt/shadow_walk.dm +++ b/code/modules/spells/spell_types/jaunt/shadow_walk.dm @@ -24,7 +24,7 @@ if(is_jaunting(owner)) return TRUE var/turf/cast_turf = get_turf(owner) - if(cast_turf.get_lumcount() >= SHADOW_SPECIES_LIGHT_THRESHOLD) + if(cast_turf.get_lumcount() >= SHADOW_SPECIES_DIM_LIGHT) if(feedback) to_chat(owner, span_warning("It isn't dark enough here!")) return FALSE @@ -112,7 +112,7 @@ /obj/effect/dummy/phased_mob/shadow/proc/check_light_level(location_to_check) var/turf/T = get_turf(location_to_check) var/light_amount = T.get_lumcount() - if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) // jaunt ends + if(light_amount > SHADOW_SPECIES_DIM_LIGHT) // jaunt ends return TRUE /** diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index a1a1b59ecc77..2022a81121bc 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -207,7 +207,7 @@ var/mob/living/carbon/human/user = owner.current to_chat(user, "Your mind has expanded. The Psi Web is now available. Avoid the light. Keep to the shadows. Your time will come.") user.fully_heal() - user.set_species(/datum/species/darkspawn) + user.set_species(/datum/species/shadow/darkspawn) ADD_TRAIT(user, TRAIT_SPECIESLOCK, "darkspawn divulge") //prevent them from swapping species which can fuck stuff up show_to_ghosts = TRUE psi_web = new(src) diff --git a/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm b/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm deleted file mode 100644 index 3e24402ed77a..000000000000 --- a/yogstation/code/modules/mob/living/carbon/human/species_types/darkspawn.dm +++ /dev/null @@ -1,83 +0,0 @@ -#define DARKSPAWN_REFLECT_COOLDOWN 15 SECONDS - -/datum/species/darkspawn - name = "Darkspawn" - id = "darkspawn" - limbs_id = "darkspawn" - sexes = FALSE - nojumpsuit = TRUE - changesource_flags = MIRROR_BADMIN | MIRROR_MAGIC | WABBAJACK | ERT_SPAWN //never put this in the pride pool because they look super valid - siemens_coeff = 0 - brutemod = 0.9 - heatmod = 1.5 - no_equip = list(ITEM_SLOT_MASK, ITEM_SLOT_OCLOTHING, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_ICLOTHING, ITEM_SLOT_SUITSTORE, ITEM_SLOT_HEAD) - species_traits = list(NOBLOOD,NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYESPRITES,NOFLASH) - inherent_traits = list(TRAIT_NOGUNS, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE, TRAIT_NOBREATH, TRAIT_RADIMMUNE, TRAIT_VIRUSIMMUNE, TRAIT_PIERCEIMMUNE, TRAIT_NODISMEMBER, TRAIT_NOHUNGER) - mutanteyes = /obj/item/organ/eyes/night_vision/alien - COOLDOWN_DECLARE(reflect_cd_1) - COOLDOWN_DECLARE(reflect_cd_2) - COOLDOWN_DECLARE(reflect_cd_3) - var/dark_healing = 5 - var/light_burning = 7 - -/datum/species/darkspawn/bullet_act(obj/projectile/P, mob/living/carbon/human/H) - if(prob(50) && (COOLDOWN_FINISHED(src, reflect_cd_1) || COOLDOWN_FINISHED(src, reflect_cd_2) || COOLDOWN_FINISHED(src, reflect_cd_3))) - if(COOLDOWN_FINISHED(src, reflect_cd_1)) - COOLDOWN_START(src, reflect_cd_1, DARKSPAWN_REFLECT_COOLDOWN) - else if(COOLDOWN_FINISHED(src, reflect_cd_2)) - COOLDOWN_START(src, reflect_cd_2, DARKSPAWN_REFLECT_COOLDOWN) - else if(COOLDOWN_FINISHED(src, reflect_cd_3)) - COOLDOWN_START(src, reflect_cd_3, DARKSPAWN_REFLECT_COOLDOWN) - H.visible_message(span_danger("The shadows around [H] ripple as they absorb \the [P]!")) - playsound(H, "bullet_miss", 75, 1) - return -1 - return 0 - -/datum/species/darkspawn/on_species_gain(mob/living/carbon/C, datum/species/old_species) - . = ..() - C.real_name = "[pick(GLOB.nightmare_names)]" - C.name = C.real_name - if(C.mind) - C.mind.name = C.real_name - C.dna.real_name = C.real_name - -/datum/species/darkspawn/on_species_loss(mob/living/carbon/C) - . = ..() - C.bubble_icon = initial(C.bubble_icon) - -/datum/species/darkspawn/spec_updatehealth(mob/living/carbon/human/H) - if(H.mind?.has_antag_datum(ROLE_DARKSPAWN)) - var/datum/antagonist/darkspawn/antag = H.mind.has_antag_datum(ROLE_DARKSPAWN) - dark_healing = antag.dark_healing - light_burning = antag.light_burning - -/datum/species/darkspawn/spec_life(mob/living/carbon/human/H) - H.bubble_icon = "darkspawn" - var/turf/T = H.loc - if(istype(T)) - var/light_amount = T.get_lumcount() - switch(light_amount) - if(0 to DARKSPAWN_DIM_LIGHT) //rapid healing and stun reduction in the darkness - H.adjustBruteLoss(-dark_healing) - H.adjustFireLoss(-dark_healing) - H.adjustToxLoss(-dark_healing) - H.adjustStaminaLoss(-dark_healing * 20) - H.AdjustStun(-dark_healing * 40) - H.AdjustKnockdown(-dark_healing * 40) - H.AdjustUnconscious(-dark_healing * 40) - H.adjustCloneLoss(-dark_healing) - H.SetSleeping(0) - H.setOrganLoss(ORGAN_SLOT_BRAIN,0) - if(DARKSPAWN_DIM_LIGHT to DARKSPAWN_BRIGHT_LIGHT) //not bright, but still dim - if(!H.has_status_effect(STATUS_EFFECT_CREEP)) - to_chat(H, span_userdanger("The light singes you!")) - H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 40 * light_amount), TRUE) - H.adjustCloneLoss(light_burning * 0.2) - if(DARKSPAWN_BRIGHT_LIGHT to INFINITY) //but quick death in the light - if(!H.has_status_effect(STATUS_EFFECT_CREEP)) - to_chat(H, span_userdanger("The light burns you!")) - H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) - H.adjustCloneLoss(light_burning) - -/datum/species/darkspawn/spec_death(gibbed, mob/living/carbon/human/H) - playsound(H, 'yogstation/sound/creatures/darkspawn_death.ogg', 50, FALSE) From 56c2350db4d2a12cdca662f08be3edcbc55f2373 Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 16:49:56 -0500 Subject: [PATCH 018/756] port light eater component and datums --- code/__DEFINES/dcs/signals/signals_object.dm | 16 ++ code/__DEFINES/is_helpers.dm | 2 + code/datums/components/light_eater.dm | 66 +++++++ code/datums/elements/light_eaten.dm | 72 +++++++ code/datums/elements/light_eater.dm | 187 ++++++++++++++++++ code/game/mecha/mecha.dm | 11 +- .../carbon/human/species_types/ethereal.dm | 8 + .../human/species_types/shadowpeople.dm | 79 +++----- .../modules/mob/living/silicon/robot/robot.dm | 9 + code/modules/power/lighting.dm | 13 +- yogstation.dme | 4 +- 11 files changed, 410 insertions(+), 57 deletions(-) create mode 100644 code/datums/components/light_eater.dm create mode 100644 code/datums/elements/light_eaten.dm create mode 100644 code/datums/elements/light_eater.dm diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index c31218971d51..d8fe1e8f3c5c 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -448,3 +448,19 @@ /// from /obj/item/detective_scanner/scan(): (mob/user, list/extra_data) #define COMSIG_DETECTIVE_SCANNED "det_scanned" + +// /datum/element/light_eater +///from base of [/datum/element/light_eater/proc/table_buffet]: (list/light_queue, datum/light_eater) +#define COMSIG_LIGHT_EATER_QUEUE "light_eater_queue" +///from base of [/datum/element/light_eater/proc/devour]: (datum/light_eater) +#define COMSIG_LIGHT_EATER_ACT "light_eater_act" + ///Prevents the default light eater behavior from running in case of immunity or custom behavior + #define COMPONENT_BLOCK_LIGHT_EATER (1<<0) +///from base of [/datum/element/light_eater/proc/devour]: (atom/eaten_light) +#define COMSIG_LIGHT_EATER_DEVOUR "light_eater_devour" + + +/// Flag for when /afterattack potentially acts on an item. +/// Used for the swap hands/drop tutorials to know when you might just be trying to do something normally. +/// Does not necessarily imply success, or even that it did hit an item, just intent. +#define COMPONENT_AFTERATTACK_PROCESSED_ITEM (1<<0) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index fd258eb6cdfe..b8c65e05d37b 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -257,6 +257,8 @@ GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list( #define isprojectile(A) (istype(A, /obj/projectile)) +#define isprojectilespell(A) (istype(A, /obj/item/projectile/magic)) + #define isgun(A) (istype(A, /obj/item/gun)) #define is_reagent_container(O) (istype(O, /obj/item/reagent_containers)) diff --git a/code/datums/components/light_eater.dm b/code/datums/components/light_eater.dm new file mode 100644 index 000000000000..c3712939dad2 --- /dev/null +++ b/code/datums/components/light_eater.dm @@ -0,0 +1,66 @@ +/** + * Makes anything it attaches to capable of removing something's ability to produce light until it is destroyed + * + * The permanent version of this is [/datum/element/light_eater] + */ +/datum/component/light_eater + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// Tracks things this light eater has eaten + var/list/eaten_lights + +/datum/component/light_eater/Initialize(list/_eaten) + if(!isatom(parent) && !istype(parent, /datum/reagent)) + return COMPONENT_INCOMPATIBLE + + . = ..() + if(!LAZYLEN(_eaten)) + return + + LAZYINITLIST(eaten_lights) + var/list/cached_eaten_lights = eaten_lights + for(var/morsel in _eaten) + LAZYSET(cached_eaten_lights, morsel, TRUE) + RegisterSignal(morsel, COMSIG_PARENT_QDELETING, PROC_REF(deref_eaten_light)) + +/datum/component/light_eater/Destroy(force, silent) + for(var/light in eaten_lights) + var/atom/eaten_light = light + eaten_light.RemoveElement(/datum/element/light_eaten) + UnregisterSignal(eaten_light, COMSIG_PARENT_QDELETING) + eaten_lights = null + return ..() + +/datum/component/light_eater/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_LIGHT_EATER_DEVOUR, PROC_REF(on_devour)) + parent.AddElement(/datum/element/light_eater) + +/datum/component/light_eater/UnregisterFromParent() + . = ..() + parent.RemoveElement(/datum/element/light_eater) + UnregisterSignal(parent, COMSIG_LIGHT_EATER_DEVOUR) + +/datum/component/light_eater/InheritComponent(datum/component/C, i_am_original, list/_eaten) + . = ..() + if(!LAZYLEN(_eaten)) + return + + LAZYINITLIST(eaten_lights) + var/list/cached_eaten_lights = eaten_lights + for(var/morsel in _eaten) + RegisterSignal(morsel, COMSIG_PARENT_QDELETING, PROC_REF(deref_eaten_light)) + LAZYSET(cached_eaten_lights, morsel, TRUE) + +/// Handles storing references to lights eaten by the light eater. +/datum/component/light_eater/proc/on_devour(datum/source, atom/morsel) + SIGNAL_HANDLER + LAZYSET(eaten_lights, morsel, TRUE) + RegisterSignal(morsel, COMSIG_PARENT_QDELETING, PROC_REF(deref_eaten_light)) + return NONE + +/// Handles dereferencing deleted lights. +/datum/component/light_eater/proc/deref_eaten_light(atom/eaten_light, force) + SIGNAL_HANDLER + UnregisterSignal(eaten_light, COMSIG_PARENT_QDELETING) + LAZYREMOVE(eaten_lights, eaten_light) + return NONE diff --git a/code/datums/elements/light_eaten.dm b/code/datums/elements/light_eaten.dm new file mode 100644 index 000000000000..51394a89da50 --- /dev/null +++ b/code/datums/elements/light_eaten.dm @@ -0,0 +1,72 @@ +/** + * Makes anything that it attaches to incapable of producing light + */ +/datum/element/light_eaten + element_flags = ELEMENT_DETACH_ON_HOST_DESTROY // Detach for turfs + +/datum/element/light_eaten/Attach(atom/target) + if(!isatom(target)) + return ELEMENT_INCOMPATIBLE + + . = ..() + var/atom/atom_target = target + RegisterSignal(atom_target, COMSIG_ATOM_SET_LIGHT_POWER, PROC_REF(block_light_power)) + RegisterSignal(atom_target, COMSIG_ATOM_SET_LIGHT_RANGE, PROC_REF(block_light_range)) + RegisterSignal(atom_target, COMSIG_ATOM_SET_LIGHT_ON, PROC_REF(block_light_on)) + RegisterSignal(atom_target, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) + + /// Because the lighting system does not like movable lights getting set_light() called. + switch(atom_target.light_system) + if(STATIC_LIGHT) + target.set_light(0, 0, null, l_on = FALSE) + else + target.set_light_power(0) + target.set_light_range(0) + target.set_light_on(FALSE) + +/datum/element/light_eaten/Detach(datum/source) + UnregisterSignal(source, list( + COMSIG_ATOM_SET_LIGHT_POWER, + COMSIG_ATOM_SET_LIGHT_RANGE, + COMSIG_ATOM_SET_LIGHT_ON, + COMSIG_PARENT_EXAMINE, + )) + return ..() + +/// Prevents the light power of the target atom from exceeding 0 or increasing. +/datum/element/light_eaten/proc/block_light_power(atom/eaten_light, new_power) + SIGNAL_HANDLER + if(new_power > 0) + return COMPONENT_BLOCK_LIGHT_UPDATE + if(new_power > eaten_light.light_power) + return COMPONENT_BLOCK_LIGHT_UPDATE + return NONE + +/// Prevents the light range of the target atom from exceeding 0 while the light power is greater than 0. +/datum/element/light_eaten/proc/block_light_range(atom/eaten_light, new_range) + SIGNAL_HANDLER + if(new_range <= 0) + return NONE + if(eaten_light.light_power <= 0) + return NONE + return COMPONENT_BLOCK_LIGHT_UPDATE + +/// Prevents the light from turning on while the light power is greater than 0. +/datum/element/light_eaten/proc/block_light_on(atom/eaten_light, new_on) + SIGNAL_HANDLER + if(!new_on) + return NONE + if(eaten_light.light_power <= 0) + return NONE + return COMPONENT_BLOCK_LIGHT_UPDATE + +/// Signal handler for light eater flavortext +/datum/element/light_eaten/proc/on_examine(atom/eaten_light, mob/examiner, list/examine_text) + SIGNAL_HANDLER + examine_text += span_warning("It's dark and empty...") + if(isliving(examiner) && prob(20)) + var/mob/living/target = examiner + examine_text += span_danger("You can feel something in [eaten_light.p_them()] gnash at your eyes!") + target.blind_eyes(5 SECONDS) + target.blur_eyes(10 SECONDS) + return NONE diff --git a/code/datums/elements/light_eater.dm b/code/datums/elements/light_eater.dm new file mode 100644 index 000000000000..c8135ca55b7a --- /dev/null +++ b/code/datums/elements/light_eater.dm @@ -0,0 +1,187 @@ +/** + * Makes anything it attaches to capable of permanently removing something's ability to produce light. + * + * The temporary equivalent is [/datum/component/light_eater] + */ +/datum/element/light_eater + +/datum/element/light_eater/Attach(datum/target) + if(isatom(target)) + if(ismovable(target)) + if(ismachinery(target) || isstructure(target)) + RegisterSignal(target, COMSIG_PROJECTILE_ON_HIT, PROC_REF(on_projectile_hit)) + RegisterSignal(target, COMSIG_MOVABLE_IMPACT, PROC_REF(on_throw_impact)) + if(isitem(target)) + if(isgun(target)) + RegisterSignal(target, COMSIG_PROJECTILE_ON_HIT, PROC_REF(on_projectile_hit)) + RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack)) + RegisterSignal(target, COMSIG_ITEM_HIT_REACT, PROC_REF(on_hit_reaction)) + else if(isprojectile(target)) + RegisterSignal(target, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(on_projectile_self_hit)) + else if(isprojectilespell(target)) + RegisterSignal(target, COMSIG_PROJECTILE_ON_HIT, PROC_REF(on_projectile_hit)) + else + return ELEMENT_INCOMPATIBLE + + return ..() + +/datum/element/light_eater/Detach(datum/source) + UnregisterSignal(source, list( + COMSIG_MOVABLE_IMPACT, + COMSIG_ITEM_AFTERATTACK, + COMSIG_ITEM_HIT_REACT, + COMSIG_PROJECTILE_ON_HIT, + )) + return ..() + +/** + * Makes the light eater consume all of the lights attached to the target atom. + * + * Arguments: + * - [food][/atom]: The atom to start the search for lights at. + * - [eater][/datum]: The light eater being used in this case. + */ +/datum/element/light_eater/proc/eat_lights(atom/food, datum/eater) + var/list/buffet = table_buffet(food) + if(!LAZYLEN(buffet)) + return 0 + + . = 0 + for(var/morsel in buffet) + . += devour(morsel, eater) + + if(!.) + return + + food.visible_message( + span_danger("Something dark in [eater] lashes out at [food] and [food.p_their()] light goes out in an instant!"), + span_userdanger("You feel something dark in [eater] lash out and gnaw through your light in an instant! It recedes just as fast, but you can feel that [eater.p_theyve()] left something hungry behind."), + span_danger("You feel a gnawing pulse eat at your sight.") + ) + +/** + * Aggregates a list of the light sources attached to the target atom. + * + * Arguments: + * - [comissary][/atom]: The origin node of all of the light sources to search through. + * - [devourer][/datum]: The light eater this element is attached to. Since the element is compatible with reagents this needs to be a datum. + */ +/datum/element/light_eater/proc/table_buffet(atom/commisary, datum/devourer) + . = list() + SEND_SIGNAL(commisary, COMSIG_LIGHT_EATER_QUEUE, ., devourer) + for(var/datum/light_source/morsel as anything in commisary.light_sources) + .[morsel.source_atom] = TRUE + +/** + * Consumes the light on the target, permanently rendering it incapable of producing light + * + * Arguments: + * - [morsel][/atom]: The light-producing thing we are eating + * - [eater][/datum]: The light eater eating the morsel. This is the datum that the element is attached to that started this chain. + */ +/datum/element/light_eater/proc/devour(atom/morsel, datum/eater) + var/static/list/undevourable = typecacheof(list(/turf/open/space)) + if(is_type_in_typecache(morsel, undevourable)) + return FALSE + if(morsel.light_power <= 0 || morsel.light_range <= 0 || !morsel.light_on) + return FALSE + if(SEND_SIGNAL(morsel, COMSIG_LIGHT_EATER_ACT, eater) & COMPONENT_BLOCK_LIGHT_EATER) + return FALSE // Either the light eater can't eat it or it had special behaviors. + + morsel.AddElement(/datum/element/light_eaten) + SEND_SIGNAL(src, COMSIG_LIGHT_EATER_DEVOUR, morsel) + return TRUE + +///////////////////// +// SIGNAL HANDLERS // +///////////////////// + +/** + * Called when a movable source is thrown and strikes a target + * + * Arugments: + * - [source][/atom/movable]: The movable atom that was thrown + * - [hit_atom][/atom]: The target atom that was struck by the source in flight + * - [thrownthing][/datum/thrownthing]: A datum containing the information for the throw + */ +/datum/element/light_eater/proc/on_throw_impact(atom/movable/source, atom/hit_atom, datum/thrownthing/thrownthing) + SIGNAL_HANDLER + eat_lights(hit_atom, source) + return NONE + +/** + * Called when a target is attacked with a source item + * + * Arguments: + * - [source][/obj/item]: The item what was used to strike the target + * - [target][/atom]: The atom being struck by the user with the source + * - [user][/mob/living]: The mob using the source to strike the target + * - proximity: Whether the strike was in melee range so you can't eat lights from cameras + */ +/datum/element/light_eater/proc/on_afterattack(obj/item/source, atom/target, mob/living/user, proximity) + SIGNAL_HANDLER + if(!proximity) + return NONE + eat_lights(target, source) + return COMPONENT_AFTERATTACK_PROCESSED_ITEM + +/** + * Called when a source object is used to block a thrown object, projectile, or attack + * + * Arguments: + * - [source][/obj/item]: The item what was used to block the target + * - [owner][/mob/living/carbon/human]: The mob that blocked the target with the source + * - [hitby][/atom/movable]: The movable that was blocked by the owner with the source + * - attack_text: The text tring that will be used to report that the target was blocked + * - final_block_chance: The probability of blocking the target with the source + * - attack_type: The type of attack that was blocked + */ +/datum/element/light_eater/proc/on_hit_reaction(obj/item/source, mob/living/carbon/human/owner, atom/movable/hitby, attack_text, final_block_chance, damage, attack_type, damage_type) + SIGNAL_HANDLER + if(prob(final_block_chance)) + eat_lights(hitby, source) + return NONE + +/** + * Called when a produced projectile strikes a target atom + * + * Arguments: + * - [source][/datum]: The thing that created the projectile + * - [firer][/atom/movable]: The movable atom that fired the projectile + * - [target][/atom]: The atom that was struck by the projectile + * - angle: The angle the target was struck at + */ +/datum/element/light_eater/proc/on_projectile_hit(datum/source, atom/movable/firer, atom/target, angle) + SIGNAL_HANDLER + eat_lights(target, source) + return NONE + +/** + * Called when a source projectile strikes a target atom + * + * Arguments: + * - [source][/obj/projectile]: The projectile striking the target atom + * - [firer][/atom/movable]: The movable atom that fired the projectile + * - [target][/atom]: The atom that was struck by the projectile + * - angle: The angle the target was struck at + * - hit_limb: The limb that was hit, if the target was a carbon + */ +/datum/element/light_eater/proc/on_projectile_self_hit(obj/item/projectile/source, atom/movable/firer, atom/target, angle, hit_limb) + SIGNAL_HANDLER + eat_lights(target, source) + return NONE + +/** + * Called when a source reagent exposes a target atom + * + * Arguments: + * - [source][/datum/reagent]: The reagents that exposed the target atom + * - [target][/atom]: The atom that was exposed to the light reater reagents + * - reac_volume: The volume of the reagents the target was exposed to + * + * +/datum/element/light_eater/proc/on_expose_atom(datum/reagent/source, atom/target, reac_volume) + SIGNAL_HANDLER + eat_lights(target, source) + return NONE + */ diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 8e6e98fd0169..3c46e2c0169a 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -169,7 +169,16 @@ diag_hud_set_mechhealth() diag_hud_set_mechcell() diag_hud_set_mechstat() - + RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) + +/// Special light eater handling +/obj/mecha/proc/on_light_eater(obj/vehicle/sealed/source, datum/light_eater) + SIGNAL_HANDLER + visible_message(span_danger("[src]'s lights burn out!")) + set_light_on(FALSE) + lights_action.Remove(occupant) + return COMPONENT_BLOCK_LIGHT_EATER + /obj/mecha/update_icon_state() . = ..() if (silicon_pilot && silicon_icon_state) diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index 12d9c0e8ae0c..b81db0a944e4 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -68,9 +68,11 @@ g1 = GETGREENPART(default_color) b1 = GETBLUEPART(default_color) ethereal_light = ethereal.mob_light() + RegisterSignal(ethereal, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) spec_updatehealth(ethereal) /datum/species/ethereal/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) + UnregisterSignal(C, COMSIG_LIGHT_EATER_ACT) QDEL_NULL(ethereal_light) C.set_light(0) return ..() @@ -110,6 +112,12 @@ fixed_mut_color = rgb(128,128,128) ethereal.update_body() +/// Special handling for getting hit with a light eater +/datum/species/ethereal/proc/on_light_eater(mob/living/carbon/human/source, datum/light_eater) + SIGNAL_HANDLER + source.emp_act(EMP_LIGHT) + return COMPONENT_BLOCK_LIGHT_EATER + /datum/species/ethereal/spec_emp_act(mob/living/carbon/human/H, severity) .=..() EMPeffect = TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 98f303f1a7fa..1e81d04eb628 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -15,20 +15,10 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC mutanteyes = /obj/item/organ/eyes/night_vision - var/shadow_charges = 0 - var/charge_time = DARKSPAWN_REFLECT_COOLDOWN - var/last_charge = 0 var/powerful_heal = FALSE var/dark_healing = 1 var/light_burning = 1 -/datum/species/shadow/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) - if(prob(50) && shadow_charges > 0) - H.visible_message(span_danger("The shadows around [H] ripple as they absorb \the [P]!")) - playsound(H, "bullet_miss", 75, 1) - shadow_charges = min(shadow_charges - 1, 0) - return -1 - return 0 /datum/species/shadow/spec_life(mob/living/carbon/human/H) H.bubble_icon = "darkspawn" @@ -58,9 +48,6 @@ to_chat(H, span_userdanger("The light burns you!")) H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) H.adjustCloneLoss(light_burning) - if(world.time >= charge_time+last_charge) - shadow_charges = min(shadow_charges + 1, 3) - last_charge = world.time /datum/species/shadow/check_roundstart_eligible() if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) @@ -129,12 +116,20 @@ mutanteyes = /obj/item/organ/eyes/night_vision/nightmare mutant_organs = list(/obj/item/organ/heart/nightmare) mutantbrain = /obj/item/organ/brain/nightmare - - var/shadow_charges = 1 var/info_text = "You are a Nightmare. The ability shadow walk allows unlimited, unrestricted movement in the dark while activated. \ Your light eater will destroy any light producing objects you attack, as well as destroy any lights a living creature may be holding. You will automatically dodge gunfire and melee attacks when on a dark tile. If killed, you will eventually revive if left in darkness." +/datum/species/shadow/nightmare/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) + var/turf/T = H.loc + if(istype(T)) + var/light_amount = T.get_lumcount() + if(light_amount < SHADOW_SPECIES_DIM_LIGHT) + H.visible_message(span_danger("[H] dances in the shadows, evading [P]!")) + playsound(T, "bullet_miss", 75, 1) + return BULLET_ACT_FORCE_PIERCE + return ..() + /datum/species/shadow/nightmare/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() to_chat(C, "[info_text]") @@ -160,11 +155,24 @@ inherent_traits = list(TRAIT_NOGUNS, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE, TRAIT_NOBREATH, TRAIT_RADIMMUNE, TRAIT_VIRUSIMMUNE, TRAIT_PIERCEIMMUNE, TRAIT_NODISMEMBER, TRAIT_NOHUNGER) mutanteyes = /obj/item/organ/eyes/night_vision/alien + var/shadow_charges = 3 powerful_heal = TRUE shadow_charges = 3 dark_healing = 5 light_burning = 7 +/datum/species/shadow/darkspawn/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) + if(prob(50) && shadow_charges > 0) + H.visible_message(span_danger("The shadows around [H] ripple as they absorb \the [P]!")) + playsound(H, "bullet_miss", 75, 1) + shadow_charges = min(shadow_charges - 1, 0) + addtimer(CALLBACK(src, PROC_REF(regen_shadow)), DARKSPAWN_REFLECT_COOLDOWN)//so they regen on different timers + return BULLET_ACT_BLOCK + return 0 + +/datum/species/shadow/darkspawn/proc/regen_shadow() + shadow_charges = min(shadow_charges++, initial(shadow_charges)) + /datum/species/shadow/darkspawn/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() C.real_name = "[pick(GLOB.nightmare_names)]" @@ -190,6 +198,7 @@ /datum/species/shadow/darkspawn/spec_death(gibbed, mob/living/carbon/human/H) playsound(H, 'yogstation/sound/creatures/darkspawn_death.ogg', 50, FALSE) + /////////////////////////////Organs///////////////////////////////////// /obj/item/organ/brain/nightmare name = "tumorous mass" @@ -281,7 +290,6 @@ respawn_progress = 0 //Weapon - /obj/item/light_eater name = "light eater" //as opposed to heavy eater icon = 'icons/obj/changeling.dmi' @@ -303,44 +311,9 @@ . = ..() ADD_TRAIT(src, TRAIT_NODROP, HAND_REPLACEMENT_TRAIT) AddComponent(/datum/component/butchering, 80, 70) + AddComponent(/datum/component/light_eater) -/obj/item/light_eater/afterattack(atom/movable/AM, mob/user, proximity) - . = ..() - if(!proximity) - return - if(isopenturf(AM)) //So you can actually melee with it - return - if(isliving(AM)) - var/mob/living/L = AM - if(isethereal(AM)) - AM.emp_act(EMP_LIGHT) - - else if(iscyborg(AM)) - var/mob/living/silicon/robot/borg = AM - if(borg.lamp_enabled) - borg.smash_headlamp() - else if(ishuman(AM)) - for(var/obj/item/O in AM.get_all_contents()) - if(O.light_range && O.light_power) - disintegrate(O) - if(L.pulling && L.pulling.light_range && isitem(L.pulling)) - disintegrate(L.pulling) - else if(isitem(AM)) - var/obj/item/I = AM - if(I.light_range && I.light_power) - disintegrate(I) - -/obj/item/light_eater/proc/disintegrate(obj/item/O) - if(istype(O, /obj/item/pda)) - var/obj/item/pda/PDA = O - PDA.set_light_on(FALSE) - PDA.set_light_range(0) //It won't be turning on again. - PDA.update_appearance(UPDATE_ICON) - visible_message(span_danger("The light in [PDA] shorts out!")) - else - visible_message(span_danger("[O] is disintegrated by [src]!")) - O.burn() - playsound(src, 'sound/items/welder.ogg', 50, 1) +#undef DARKSPAWN_REFLECT_COOLDOWN #undef HEART_SPECIAL_SHADOWIFY #undef HEART_RESPAWN_THRESHHOLD diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 22bb114f4910..5f03647ea8b9 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -123,6 +123,7 @@ wires = new /datum/wires/robot(src) ADD_TRAIT(src, TRAIT_EMPPROOF_CONTENTS, "innate_empproof") + RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) RegisterSignal(src, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(charge)) robot_modules_background = new() @@ -344,6 +345,14 @@ if(thruster_button) thruster_button.icon_state = "ionpulse[ionpulse_on]" +/// Special handling for getting hit with a light eater +/mob/living/silicon/robot/proc/on_light_eater(mob/living/silicon/robot/source, datum/light_eater) + SIGNAL_HANDLER + if(lamp_enabled) + smash_headlamp() + return COMPONENT_BLOCK_LIGHT_EATER + + /mob/living/silicon/robot/get_status_tab_items() . = ..() . += "" diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 3e742c88e3b4..4f44e8dd4c8e 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -332,6 +332,8 @@ spawn(1) update(0) + RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) + /obj/machinery/light/Destroy() GLOB.lights.Remove(src) var/area/A = get_area(src) @@ -598,8 +600,6 @@ break_light_tube() - - /obj/machinery/light/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) if(BRUTE) @@ -613,6 +613,15 @@ if(BURN) playsound(src.loc, 'sound/items/welder.ogg', 100, 1) + +/obj/machinery/light/proc/on_light_eater(obj/machinery/light/source, datum/light_eater) + SIGNAL_HANDLER + . = COMPONENT_BLOCK_LIGHT_EATER + if(status == LIGHT_EMPTY) + return + var/obj/item/light/tube = drop_light_tube() + tube?.burn() + return // returns if the light has power /but/ is manually turned off // if a light is turned off, it won't activate emergency power /obj/machinery/light/proc/turned_off() diff --git a/yogstation.dme b/yogstation.dme index 7798aa0f7b7b..6981795a74c1 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -523,6 +523,7 @@ #include "code\datums\components\knockback.dm" #include "code\datums\components\knockoff.dm" #include "code\datums\components\lifesteal.dm" +#include "code\datums\components\light_eater.dm" #include "code\datums\components\lockon_aiming.dm" #include "code\datums\components\magnetic_catch.dm" #include "code\datums\components\material_container.dm" @@ -656,6 +657,8 @@ #include "code\datums\elements\firestacker.dm" #include "code\datums\elements\frozen.dm" #include "code\datums\elements\life_drain.dm" +#include "code\datums\elements\light_eaten.dm" +#include "code\datums\elements\light_eater.dm" #include "code\datums\elements\squish.dm" #include "code\datums\elements\update_icon_blocker.dm" #include "code\datums\helper_datums\events.dm" @@ -4136,7 +4139,6 @@ #include "yogstation\code\modules\mob\living\carbon\human\human_movement.dm" #include "yogstation\code\modules\mob\living\carbon\human\life.dm" #include "yogstation\code\modules\mob\living\carbon\human\species.dm" -#include "yogstation\code\modules\mob\living\carbon\human\species_types\darkspawn.dm" #include "yogstation\code\modules\mob\living\carbon\human\species_types\gorillapeople.dm" #include "yogstation\code\modules\mob\living\carbon\human\species_types\halloween.dm" #include "yogstation\code\modules\mob\living\carbon\human\species_types\jellypeople.dm" From 244c3a5252637dba285802b6a43b22b81a930b82 Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 17:08:14 -0500 Subject: [PATCH 019/756] tweaks --- code/__DEFINES/{yogs_defines}/mobs.dm | 4 +++- .../antagonists/darkspawn/darkspawn_abilities/_divulge.dm | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/{yogs_defines}/mobs.dm b/code/__DEFINES/{yogs_defines}/mobs.dm index b1ba7d41b22d..96334339333b 100644 --- a/code/__DEFINES/{yogs_defines}/mobs.dm +++ b/code/__DEFINES/{yogs_defines}/mobs.dm @@ -8,6 +8,8 @@ #define REGEN_BLOOD_REQUIREMENT 40 // The amount of "blood" that a slimeperson consumes when regenerating a single limb. #define DARKSPAWN_DIM_LIGHT 0.2 //light of this intensity suppresses healing and causes very slow burn damage -#define DARKSPAWN_BRIGHT_LIGHT 0.4 //light of this intensity causes rapid burn damage +#define DARKSPAWN_BRIGHT_LIGHT 0.6 //light of this intensity causes rapid burn damage (high number because movable lights are weird) +//so the problem is that movable lights ALWAYS have a luminosity of 0.5, regardless of power or distance, so even outside of the overlay they still do damage +//at 0.6 being bright they'll still do damage and disable some abilities, but it won't be weaponized #define MONKIFY_BLOOD_COEFFICIENT (BLOOD_VOLUME_MONKEY/BLOOD_VOLUME_GENERIC) //the ratio of monkey to human blood volume so a 100% blood volume monkey will not instantly die when you turn it into a human with ~58% blood volume diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 0ce1e37de049..59f76c2e47e1 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -69,7 +69,7 @@ sleep(4.5 SECONDS) user.Shake(5, 5, 11 SECONDS) for(var/i in 1 to 20) - to_chat(user, "[pick("I- I- I-", "Mind-", "Sigils-", "Can't think-", "POWER-","TAKE-", "M-M-MOOORE-", "THINK")]") + to_chat(user, "[pick("I- I- I-", "Mind-", "Sigils-", "Can't think-", "POWER-","TAKE-", "M-M-MOOORE-", "THINK!!!")]") sleep(0.1 SECONDS) //Spooky flavor message spam user.visible_message(span_userdanger("A tremendous shockwave emanates from [user]!"), "YOU ARE FREE!!") playsound(user, 'yogstation/sound/magic/divulge_end.ogg', 50, 0) From 211e49bab7f619627e87812342334584000d93dd Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 17:16:21 -0500 Subject: [PATCH 020/756] pass --- code/datums/components/overlay_lighting.dm | 2 +- .../code/game/gamemodes/darkspawn/psi_web.dm | 1 + .../darkspawn_objects/umbral_tendrils.dm | 32 ++----------------- 3 files changed, 5 insertions(+), 30 deletions(-) diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index 11c9cc451217..29acfb952745 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -273,7 +273,7 @@ turn_off() range = clamp(CEILING(new_range, 0.5), 1, 6) var/pixel_bounds = ((range - 1) * 64) + 32 - lumcount_range = CEILING(range, 1) + lumcount_range = CEILING(range - 1, 1) visible_mask.icon = light_overlays["[pixel_bounds]"] if(pixel_bounds == 32) visible_mask.transform = null diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 5f0f2cca21d0..071ec2b60a19 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -172,6 +172,7 @@ /datum/psi_web/fighter name = "fighter" desc = "me no think so good" + learned_ability = /datum/action/innate/darkspawn/pass /datum/psi_web/fighter/activate(mob/user) owner.specialization = FIGHTER diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm index 756e9b87ce41..0f0d5ce170c7 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm @@ -17,6 +17,7 @@ /obj/item/umbral_tendrils/Initialize(mapload, new_darkspawn) . = ..() ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) + AddComponent(/datum/component/light_eater) darkspawn = new_darkspawn for(var/obj/item/umbral_tendrils/U in loc) if(U != src) @@ -52,24 +53,8 @@ if(!darkspawn) return if(proximity) - if(istype(target, /obj/structure/glowshroom)) - visible_message(span_warning("[src] tears [target] to shreds!")) - qdel(target) - if(isliving(target)) - var/mob/living/L = target - if(isethereal(target)) - target.emp_act(EMP_LIGHT) - for(var/obj/item/O in target.get_all_contents()) - if(O.light_range && O.light_power) - disintegrate(O) - if(L.pulling && L.pulling.light_range && isitem(L.pulling)) - disintegrate(L.pulling) - else if(isitem(target)) - var/obj/item/I = target - if(I.light_range && I.light_power) - disintegrate(I) // Double hit structures if duality - else if(!QDELETED(target) && (isstructure(target) || ismachinery(target)) && twin && user.get_active_held_item() == src) + if(!QDELETED(target) && (isstructure(target) || ismachinery(target)) && twin && user.get_active_held_item() == src) target.attackby(twin, user) switch(user.a_intent) //Note that airlock interactions can be found in airlock.dm. if(INTENT_HELP) @@ -78,17 +63,6 @@ if(INTENT_HARM) tendril_swing(user, target) -/obj/item/umbral_tendrils/proc/disintegrate(obj/item/O) - if(istype(O, /obj/item/pda)) - var/obj/item/pda/PDA = O - PDA.set_light_on(FALSE) - PDA.update_appearance(UPDATE_ICON) - visible_message(span_danger("The light in [PDA] shorts out!")) - else - visible_message(span_danger("[O] is disintegrated by [src]!")) - O.burn() - playsound(src, 'sound/items/welder.ogg', 50, 1) - /obj/item/umbral_tendrils/proc/tendril_jump(mob/living/user, turf/open/target) //throws the user towards the target turf if(!darkspawn.has_psi(10)) to_chat(user, span_warning("You need at least 10 Psi to jump!")) @@ -98,7 +72,7 @@ return to_chat(user, span_velvet("You pull yourself towards [target].")) playsound(user, 'sound/magic/tail_swing.ogg', 10, TRUE) - user.throw_at(target, 5, 3) + user.throw_at(target, 5, 3, user, FALSE) darkspawn.use_psi(10) /obj/item/umbral_tendrils/proc/tendril_swing(mob/living/user, mob/living/target) //swing the tendrils to knock someone down From f913540ad54192fcc266b6e68d86d03aaf662e65 Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 17:27:34 -0500 Subject: [PATCH 021/756] define swaps --- code/__DEFINES/mobs.dm | 6 ++++-- code/__DEFINES/{yogs_defines}/mobs.dm | 5 ----- code/datums/status_effects/neutral.dm | 2 +- .../living/carbon/human/species_types/shadowpeople.dm | 7 ++++--- .../code/game/gamemodes/darkspawn/shadow_step.dm | 2 +- .../modules/antagonists/darkspawn/crawling_shadows.dm | 2 +- .../darkspawn/darkspawn_abilities/_divulge.dm | 2 +- .../darkspawn/darkspawn_abilities/tagalong.dm | 2 +- .../darkspawn/darkspawn_objects/umbral_tendrils.dm | 10 ++++------ 9 files changed, 17 insertions(+), 21 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 22d64e802a36..7fe8c48dec6e 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -270,8 +270,10 @@ #define MEGAFAUNA_DEFAULT_RECOVERY_TIME 5 -#define SHADOW_SPECIES_DIM_LIGHT 0.2 -#define SHADOW_SPECIES_BRIGHT_LIGHT 0.4 +#define SHADOW_SPECIES_DIM_LIGHT 0.2 //light of this intensity suppresses healing and causes very slow burn damage +#define SHADOW_SPECIES_BRIGHT_LIGHT 0.6 //light of this intensity causes rapid burn damage (high number because movable lights are weird) +//so the problem is that movable lights ALWAYS have a luminosity of 0.5, regardless of power or distance, so even at the edge of the overlay they still do damage +//at 0.6 being bright they'll still do damage and disable some abilities, but it won't be weaponized // Offsets defines diff --git a/code/__DEFINES/{yogs_defines}/mobs.dm b/code/__DEFINES/{yogs_defines}/mobs.dm index 96334339333b..816023c8161a 100644 --- a/code/__DEFINES/{yogs_defines}/mobs.dm +++ b/code/__DEFINES/{yogs_defines}/mobs.dm @@ -7,9 +7,4 @@ #define REGEN_BLOOD_REQUIREMENT 40 // The amount of "blood" that a slimeperson consumes when regenerating a single limb. -#define DARKSPAWN_DIM_LIGHT 0.2 //light of this intensity suppresses healing and causes very slow burn damage -#define DARKSPAWN_BRIGHT_LIGHT 0.6 //light of this intensity causes rapid burn damage (high number because movable lights are weird) -//so the problem is that movable lights ALWAYS have a luminosity of 0.5, regardless of power or distance, so even outside of the overlay they still do damage -//at 0.6 being bright they'll still do damage and disable some abilities, but it won't be weaponized - #define MONKIFY_BLOOD_COEFFICIENT (BLOOD_VOLUME_MONKEY/BLOOD_VOLUME_GENERIC) //the ratio of monkey to human blood volume so a 100% blood volume monkey will not instantly die when you turn it into a human with ~58% blood volume diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 78d592e69a37..756ec0b30b40 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -172,7 +172,7 @@ qdel(src) return cached_location = get_turf(shadowing) - if(cached_location.get_lumcount() < DARKSPAWN_DIM_LIGHT) + if(cached_location.get_lumcount() < SHADOW_SPECIES_DIM_LIGHT) owner.forceMove(cached_location) shadowing.visible_message(span_warning("[owner] suddenly appears from the dark!")) to_chat(owner, span_warning("You are forced out of [shadowing]'s shadow!")) diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 1e81d04eb628..73d071e08a3e 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -251,6 +251,8 @@ ..() if(special != HEART_SPECIAL_SHADOWIFY) blade = new/obj/item/light_eater + blade.force = 25 + blade.armour_penetration = 35 M.put_in_hands(blade) START_PROCESSING(SSobj, src) @@ -295,8 +297,8 @@ icon = 'icons/obj/changeling.dmi' icon_state = "arm_blade" item_state = "arm_blade" - force = 25 - armour_penetration = 35 + force = 15 + armour_penetration = 20 lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi' righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi' item_flags = ABSTRACT | DROPDEL @@ -313,7 +315,6 @@ AddComponent(/datum/component/butchering, 80, 70) AddComponent(/datum/component/light_eater) - #undef DARKSPAWN_REFLECT_COOLDOWN #undef HEART_SPECIAL_SHADOWIFY #undef HEART_RESPAWN_THRESHHOLD diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm b/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm index a828bea54d00..e46e14fc9e9c 100644 --- a/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm +++ b/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm @@ -17,7 +17,7 @@ /datum/component/shadow_step/proc/apply_darkness_speed() var/turf/T = get_turf(owner) var/light_amount = T.get_lumcount() - if(light_amount > DARKSPAWN_BRIGHT_LIGHT) + if(light_amount > SHADOW_SPECIES_BRIGHT_LIGHT) owner.remove_movespeed_modifier(type) else owner.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=speedboost, blacklisted_movetypes=(FLYING|FLOATING)) diff --git a/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm b/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm index 030822f3fd1a..7cf566cb8810 100644 --- a/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm +++ b/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm @@ -63,7 +63,7 @@ ..() var/turf/T = get_turf(src) var/lums = T.get_lumcount() - if(lums < DARKSPAWN_BRIGHT_LIGHT) + if(lums < SHADOW_SPECIES_BRIGHT_LIGHT) invisibility = INVISIBILITY_OBSERVER //Invisible in complete darkness speed = -1 //Faster, too alpha = 255 diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 59f76c2e47e1..879e3df5cfd6 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -16,7 +16,7 @@ if(isethereal(user))//disable the light for long enough to start divulge user.dna.species.spec_emp_act(user, EMP_HEAVY) - if(spot.get_lumcount() > DARKSPAWN_DIM_LIGHT) + if(spot.get_lumcount() > SHADOW_SPECIES_DIM_LIGHT) to_chat(user, span_warning("You are only able to divulge in darkness!")) return if(alert(user, "You are ready to divulge. Are you sure?", name, "Yes", "No") == "No") diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm index f03e3fb8df32..20b1fb46d50a 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm @@ -29,7 +29,7 @@ var/turf/T for(var/mob/living/L in range(7, owner) - owner) T = get_turf(L) - if(!isdarkspawn(L) && L.stat != DEAD && T.get_lumcount() >= DARKSPAWN_DIM_LIGHT) + if(!isdarkspawn(L) && L.stat != DEAD && T.get_lumcount() >= SHADOW_SPECIES_DIM_LIGHT) targets += L if(!targets.len) to_chat(owner, span_warning("There is nobody nearby in any lit areas!")) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm index 0f0d5ce170c7..fe1b1927fb1e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm @@ -2,7 +2,7 @@ /obj/item/umbral_tendrils name = "umbral tendrils" desc = "A mass of pulsing, chitonous tendrils with exposed violet flesh." - force = 15 + force = 30 icon = 'yogstation/icons/obj/darkspawn_items.dmi' icon_state = "umbral_tendrils" item_state = "umbral_tendrils" @@ -23,8 +23,8 @@ if(U != src) twin = U U.twin = src - force = 12 - U.force = 12 + force *= 0.8 + U.force *= 0.8 /obj/item/umbral_tendrils/Destroy() if(!QDELETED(twin)) @@ -52,9 +52,7 @@ /obj/item/umbral_tendrils/afterattack(atom/target, mob/living/user, proximity) if(!darkspawn) return - if(proximity) - // Double hit structures if duality - if(!QDELETED(target) && (isstructure(target) || ismachinery(target)) && twin && user.get_active_held_item() == src) + if(twin && proximity && !QDELETED(target) && (isstructure(target) || ismachinery(target)) && user.get_active_held_item() == src) target.attackby(twin, user) switch(user.a_intent) //Note that airlock interactions can be found in airlock.dm. if(INTENT_HELP) From e2c77fecbbdd63df559001ddfb4851c1e33fd602 Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 17:34:00 -0500 Subject: [PATCH 022/756] Update umbral_tendrils.dm --- .../antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm index fe1b1927fb1e..d281ad931411 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm @@ -53,7 +53,7 @@ if(!darkspawn) return if(twin && proximity && !QDELETED(target) && (isstructure(target) || ismachinery(target)) && user.get_active_held_item() == src) - target.attackby(twin, user) + target.attackby(twin, user) switch(user.a_intent) //Note that airlock interactions can be found in airlock.dm. if(INTENT_HELP) if(isopenturf(target)) From 97cc1d00d41614becb0fc2939d0e6e0e09c2a182 Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 17:35:22 -0500 Subject: [PATCH 023/756] Update game_options.txt --- config/game_options.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/game_options.txt b/config/game_options.txt index 9d0c91918bef..b376d8a0163c 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -104,7 +104,6 @@ ALERT_DELTA Destruction of the station is imminent. All crew are instructed to o ## Set to 0 to disable that mode. # New -PROBABILITY DARKSPAWN 2 PROBABILITY HERESY 6 PROBABILITY INFILTRATION 0 PROBABILITY BLOODSUCKER 5 @@ -120,6 +119,7 @@ PROBABILITY CHANGELING 3 PROBABILITY VAMPIRE 0 # Group antags +PROBABILITY DARKSPAWN 6 PROBABILITY REVOLUTION 8 PROBABILITY GANG 0 PROBABILITY CULT 5 From 2039837b5b1aee4acfc5cbcd75845e8868b53a8c Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 17:36:52 -0500 Subject: [PATCH 024/756] Update psi_web.dm --- yogstation/code/game/gamemodes/darkspawn/psi_web.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 071ec2b60a19..4a66c68617cd 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -166,7 +166,6 @@ /datum/psi_web/scout/activate(mob/user) user.LoadComponent(/datum/component/walk/shadow) - user.AddComponent(/datum/component/shadow_step) owner.specialization = SCOUT /datum/psi_web/fighter @@ -197,10 +196,13 @@ shadow_flags = SCOUT /datum/psi_web/scouttest - name = "scout ability" + name = "scout ability (dark speed)" desc = "GO FAST, TOUCH GRASS" shadow_flags = SCOUT +/datum/psi_web/scouttest/activate(mob/user) + user.AddComponent(/datum/component/shadow_step) + /datum/psi_web/everyone name = "universal ability" desc = "everyone should see this" From 8842073229546d2265255aa14130996230fd66dd Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 17:52:20 -0500 Subject: [PATCH 025/756] Update psi_web.dm --- yogstation/code/game/gamemodes/darkspawn/psi_web.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 4a66c68617cd..7767de45d51e 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -193,7 +193,7 @@ /datum/psi_web/fightertest name = "fighter ability" desc = "me no think so good" - shadow_flags = SCOUT + shadow_flags = FIGHTER /datum/psi_web/scouttest name = "scout ability (dark speed)" From feb789f7019c95ac4845710cae2981b39bfafafc Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 18:07:49 -0500 Subject: [PATCH 026/756] Update overlay_lighting.dm --- code/datums/components/overlay_lighting.dm | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index 29acfb952745..c645e413a0e3 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -93,6 +93,7 @@ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_COLOR, PROC_REF(set_color)) RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_ON, PROC_REF(on_toggle)) RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_FLAGS, PROC_REF(on_light_flags_change)) + RegisterSignal(parent, COMSIG_LIGHT_EATER_QUEUE, PROC_REF(on_light_eater)) var/atom/movable/movable_parent = parent if(movable_parent.light_flags & LIGHT_ATTACHED) overlay_lighting_flags |= LIGHTING_ATTACHED @@ -117,6 +118,7 @@ COMSIG_ATOM_SET_LIGHT_COLOR, COMSIG_ATOM_SET_LIGHT_ON, COMSIG_ATOM_SET_LIGHT_FLAGS, + COMSIG_LIGHT_EATER_QUEUE, )) if(overlay_lighting_flags & LIGHTING_ON) turn_off() @@ -181,11 +183,13 @@ if(old_parent_attached_to == current_holder) RegisterSignal(old_parent_attached_to, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel)) RegisterSignal(old_parent_attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) + RegisterSignal(old_parent_attached_to, COMSIG_LIGHT_EATER_QUEUE, PROC_REF(on_light_eater)) if(parent_attached_to) if(parent_attached_to == current_holder) - UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE)) RegisterSignal(parent_attached_to, COMSIG_PARENT_QDELETING, PROC_REF(on_parent_attached_to_qdel)) RegisterSignal(parent_attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_attached_to_moved)) + RegisterSignal(parent_attached_to, COMSIG_LIGHT_EATER_QUEUE, PROC_REF(on_light_eater)) check_holder() @@ -195,7 +199,7 @@ return if(current_holder) if(current_holder != parent && current_holder != parent_attached_to) - UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE)) if(overlay_lighting_flags & LIGHTING_ON) remove_dynamic_lumi(current_holder) current_holder = new_holder @@ -206,6 +210,7 @@ add_dynamic_lumi(new_holder) if(new_holder != parent && new_holder != parent_attached_to) RegisterSignal(new_holder, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel)) + RegisterSignal(new_holder, COMSIG_LIGHT_EATER_QUEUE, PROC_REF(on_light_eater)) RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) @@ -375,6 +380,11 @@ var/turf/lit_turf = t lit_turf.dynamic_lumcount -= difference +/// Handles putting the source for overlay lights into the light eater queue since we aren't tracked by [/atom/var/light_sources] +/datum/component/overlay_lighting/proc/on_light_eater(datum/source, list/light_queue, datum/light_eater) + SIGNAL_HANDLER + light_queue[parent] = TRUE + return NONE #undef LIGHTING_ON #undef LIGHTING_ATTACHED From e586fbb33f6929a3096aef0686482621ee943e1b Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 18:12:18 -0500 Subject: [PATCH 027/756] Update light_eaten.dm --- code/datums/elements/light_eaten.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/elements/light_eaten.dm b/code/datums/elements/light_eaten.dm index 51394a89da50..0b2a7d198ab3 100644 --- a/code/datums/elements/light_eaten.dm +++ b/code/datums/elements/light_eaten.dm @@ -18,7 +18,7 @@ /// Because the lighting system does not like movable lights getting set_light() called. switch(atom_target.light_system) if(STATIC_LIGHT) - target.set_light(0, 0, null, l_on = FALSE) + target.set_light(0, 0, null) else target.set_light_power(0) target.set_light_range(0) From 2dcb63c134130873ffa10ba0bea5fa8829ed4a7a Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 10 Oct 2023 22:48:34 -0500 Subject: [PATCH 028/756] Update umbral_tendrils.dm --- .../darkspawn/darkspawn_objects/umbral_tendrils.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm index d281ad931411..9fed8ad7406a 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm @@ -37,7 +37,7 @@ to_chat(user, "Functions:") to_chat(user, span_velvet("Help intent: Click on an open tile within seven tiles to jump to it for 10 Psi.")) to_chat(user, span_velvet("Disarm intent: Click on an airlock to force it open for 15 Psi (or 30 if it's bolted.)")) - to_chat(user, span_velvet("Harm intent: Fire a projectile that travels up to five tiles, knocking down[twin ? " and pulling forwards" : ""] the first creature struck.")) + to_chat(user, span_velvet("Grab intent: Fire a projectile that travels up to five tiles, knocking down[twin ? " and pulling forwards" : ""] the first creature struck.")) to_chat(user, span_velvet("The tendrils will break any lights hit in melee,")) to_chat(user, span_velvet("The tendrils will shatter light fixtures instantly, as opposed to in several attacks.")) to_chat(user, span_velvet("Also functions to pry open depowered airlocks on any intent other than harm.")) @@ -58,7 +58,7 @@ if(INTENT_HELP) if(isopenturf(target)) tendril_jump(user, target) - if(INTENT_HARM) + if(INTENT_GRAB) tendril_swing(user, target) /obj/item/umbral_tendrils/proc/tendril_jump(mob/living/user, turf/open/target) //throws the user towards the target turf From c3dcddd52db1933aec234b607d2a1e748ac080ea Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 15:22:17 -0500 Subject: [PATCH 029/756] removemidround --- code/modules/events/darkspawn.dm | 55 -------------------------------- yogstation.dme | 1 - 2 files changed, 56 deletions(-) delete mode 100644 code/modules/events/darkspawn.dm diff --git a/code/modules/events/darkspawn.dm b/code/modules/events/darkspawn.dm deleted file mode 100644 index e52e5b2b53b8..000000000000 --- a/code/modules/events/darkspawn.dm +++ /dev/null @@ -1,55 +0,0 @@ -/datum/round_event_control/darkspawn - name = "Spawn Darkspawn(s)" - typepath = /datum/round_event/ghost_role/darkspawn - max_occurrences = 0 //Disabled - min_players = 30 - dynamic_should_hijack = TRUE - gamemode_blacklist = list("darkspawn") - -/datum/round_event/ghost_role/darkspawn - minimum_required = 1 - role_name = "darkspawn" - fakeable = FALSE - -/datum/round_event/ghost_role/darkspawn/spawn_role() - var/list/candidates = get_candidates(ROLE_DARKSPAWN, null, ROLE_DARKSPAWN) - if(!candidates.len) - return NOT_ENOUGH_PLAYERS - - var/list/spawn_locs = list() - for(var/turf/T in GLOB.xeno_spawn) - var/light_amount = T.get_lumcount() - if(light_amount < SHADOW_SPECIES_DIM_LIGHT) - spawn_locs += T - - if(!spawn_locs.len) - message_admins("No valid spawn locations found, aborting...") - return MAP_ERROR - - var/darkspawn_to_spawn = 1 - var/datum/job/hos = SSjob.GetJob("Head of Security") - var/datum/job/warden = SSjob.GetJob("Warden") - var/datum/job/officers = SSjob.GetJob("Security Officer") - var/sec_amount = hos.current_positions + warden.current_positions + officers.current_positions - if(sec_amount >= 5 && candidates.len >= 2 && spawn_locs.len >= 2) - darkspawn_to_spawn = 2 - - for(var/i=0,i Date: Wed, 11 Oct 2023 15:32:33 -0500 Subject: [PATCH 030/756] work on passives --- yogstation.dme | 2 - .../code/game/gamemodes/darkspawn/psi_web.dm | 57 +++++++++++++------ .../darkspawn_upgrades/dark_healing.dm | 7 --- .../darkspawn/darkspawn_upgrades/psi_cap.dm | 9 --- 4 files changed, 41 insertions(+), 34 deletions(-) delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/dark_healing.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/psi_cap.dm diff --git a/yogstation.dme b/yogstation.dme index ca0bc5ac6057..1a6ca9fb5e22 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3987,9 +3987,7 @@ #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\psionic_barrier.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\simulacrum.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\umbral_tendrils.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\dark_healing.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\light_resistance.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\psi_cap.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\psi_regen.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\spacewalking.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\twin_tendrils.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 7767de45d51e..a0b728819feb 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -115,42 +115,42 @@ ///what tab of the antag menu does it fall under var/menutab ///The antag datum of the owner(used for modifying) - var/datum/antagonist/darkspawn/owner + var/datum/antagonist/darkspawn/darkspawn ///Check to see if they should be shown the ability /datum/psi_web/proc/check_show(mob/user) - if(!menutab) + if(!menutab && shadow_flags) return FALSE - owner = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(!owner) + darkspawn = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(!darkspawn) return FALSE - if(shadow_flags && !(owner.specialization & shadow_flags)) + if(shadow_flags && !(darkspawn.specialization & shadow_flags)) return FALSE - if(locate(type) in owner.upgrades)//if they already have it + if(locate(type) in darkspawn.upgrades)//if they already have it return FALSE return TRUE ///When the button to purchase is clicked /datum/psi_web/proc/on_purchase(mob/user) - owner = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) - if(!owner) + darkspawn = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) + if(!darkspawn) return FALSE - if(shadow_flags && !(owner.specialization & shadow_flags))//they shouldn't even be shown it in the first place, but just in case + if(shadow_flags && !(darkspawn.specialization & shadow_flags))//they shouldn't even be shown it in the first place, but just in case return FALSE - if(owner.lucidity < lucidity_cost) + if(darkspawn.lucidity < lucidity_cost) return FALSE if(learn_text) to_chat(user, span_velvet(learn_text)) - owner.lucidity -= lucidity_cost + darkspawn.lucidity -= lucidity_cost activate(user) return TRUE ///If the purchase goes through, this gets called /datum/psi_web/proc/activate(mob/user) - if(!owner)//no clue how it got here, but alright + if(!darkspawn)//no clue how it got here, but alright return - owner.upgrades |= src //add it to the list + darkspawn.upgrades |= src //add it to the list if(learn_text) to_chat(user, learn_text) if(learned_ability) @@ -166,7 +166,7 @@ /datum/psi_web/scout/activate(mob/user) user.LoadComponent(/datum/component/walk/shadow) - owner.specialization = SCOUT + darkspawn.specialization = SCOUT /datum/psi_web/fighter name = "fighter" @@ -174,14 +174,14 @@ learned_ability = /datum/action/innate/darkspawn/pass /datum/psi_web/fighter/activate(mob/user) - owner.specialization = FIGHTER + darkspawn.specialization = FIGHTER /datum/psi_web/warlock name = "warlock" desc = "apartment \"complex\"... really? I find it quite simple" /datum/psi_web/warlock/activate(mob/user) - owner.specialization = WARLOCK + darkspawn.specialization = WARLOCK @@ -207,3 +207,28 @@ name = "universal ability" desc = "everyone should see this" shadow_flags = SCOUT | WARLOCK | FIGHTER + + +//////////////////////////////////////////////////////////////////////////////////// +//--------------------------------Passive Upgrades--------------------------------// +//////////////////////////////////////////////////////////////////////////////////// +//Increases max Psi by 25. +/datum/psi_web/psi_cap + name = "\'Psi\' Sigils" + desc = "The Atlwjz sigils, representing Psi, are etched onto the forehead. Unlocking these sigils increases your maximum Psi by 25." + lucidity_price = 2 + menu_tab = STORE_PASSIVE + +/datum/psi_web/psi_cap/activate(mob/user) + darkspawn.psi_cap += 25 + +//Increases healing in darkness by 25%. +/datum/psi_web/dark_healing + name = "\'Mending\' Sigil" + id = "dark_healing" + desc = "The Naykranu sigil, representing perseverence, is etched onto the back. Unlocking this sigil increases your healing in darkness by 25%." + lucidity_price = 1 + menu_tab = STORE_PASSIVE + +/datum/psi_web/dark_healing/activate(mob/user) + darkspawn.dark_healing *= 1.25 diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/dark_healing.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/dark_healing.dm deleted file mode 100644 index f77c20eaf20a..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/dark_healing.dm +++ /dev/null @@ -1,7 +0,0 @@ -//Increases healing in darkness by 25%. -//Check species_types/darkspawn.dm for effects. -/datum/darkspawn_upgrade/dark_healing - name = "\'Mending\' Sigil" - id = "dark_healing" - desc = "The Naykranu sigil, representing perseverence, is etched onto the back. Unlocking this sigil increases your healing in darkness by 25%." - lucidity_price = 1 diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/psi_cap.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/psi_cap.dm deleted file mode 100644 index c85e8bda23e7..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/psi_cap.dm +++ /dev/null @@ -1,9 +0,0 @@ -//Increases max Psi by 25. -/datum/darkspawn_upgrade/psi_cap - name = "\'Psi\' Sigils" - id = "psi_cap" - desc = "The Atlwjz sigils, representing Psi, are etched onto the forehead. Unlocking these sigils increases your maximum Psi by 25." - lucidity_price = 2 - -/datum/darkspawn_upgrade/psi_cap/apply_effects() - darkspawn.psi_cap += 25 From c440e38ff46f4b3a840b954e9162f33d0525e38d Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 15:40:08 -0500 Subject: [PATCH 031/756] morepassives --- code/__DEFINES/traits.dm | 3 +++ .../human/species_types/shadowpeople.dm | 4 ++++ yogstation.dme | 2 -- .../code/game/gamemodes/darkspawn/psi_web.dm | 21 +++++++++++++++++++ .../darkspawn/darkspawn_upgrades/psi_regen.dm | 10 --------- .../darkspawn_upgrades/spacewalking.dm | 6 ------ 6 files changed, 28 insertions(+), 18 deletions(-) delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/psi_regen.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/spacewalking.dm diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 381a8a7f57b2..301eceff8583 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -466,3 +466,6 @@ #define TRAIT_RADSTORM_IMMUNE "radstorm_immune" #define TRAIT_VOIDSTORM_IMMUNE "voidstorm_immune" #define TRAIT_WEATHER_IMMUNE "weather_immune" //Immune to ALL weather effects. + +///Darkspawn traits +#define TRAIT_DARKSPAWN_SPACEWALK "darkspawn_spacewalk" //lets darkspawns spacewalk safely diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 73d071e08a3e..977104b20005 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -39,11 +39,15 @@ H.SetSleeping(0) H.setOrganLoss(ORGAN_SLOT_BRAIN,0) if(SHADOW_SPECIES_DIM_LIGHT to SHADOW_SPECIES_BRIGHT_LIGHT) //not bright, but still dim + if(HAS_TRAIT(H, TRAIT_SPACEWALK) && isspaceturf(T)) + return if(!H.has_status_effect(STATUS_EFFECT_CREEP)) to_chat(H, span_userdanger("The light singes you!")) H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 40 * light_amount), TRUE) H.adjustCloneLoss(light_burning * 0.2) if(SHADOW_SPECIES_BRIGHT_LIGHT to INFINITY) //but quick death in the light + if(HAS_TRAIT(H, TRAIT_SPACEWALK) && isspaceturf(T)) + return if(!H.has_status_effect(STATUS_EFFECT_CREEP)) to_chat(H, span_userdanger("The light burns you!")) H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) diff --git a/yogstation.dme b/yogstation.dme index 1a6ca9fb5e22..7682b4fb4957 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3988,8 +3988,6 @@ #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\simulacrum.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\umbral_tendrils.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\light_resistance.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\psi_regen.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\spacewalking.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\twin_tendrils.dm" #include "yogstation\code\modules\antagonists\gang\gang.dm" #include "yogstation\code\modules\antagonists\gang\gang_datums.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index a0b728819feb..18188de0cdd9 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -232,3 +232,24 @@ /datum/psi_web/dark_healing/activate(mob/user) darkspawn.dark_healing *= 1.25 + +//Provides immunity to starlight. +/datum/psi_web/spacewalking + name = "\'Starlight\' Sigils" + desc = "The Jaxqhw sigils, representing the void, are etched multiple times across the body. Unlocking these sigils provides the ability to walk freely in space without fear of starlight." + lucidity_price = 3 + menu_tab = STORE_PASSIVE + +/datum/psi_web/spacewalking/activate(mob/user) + ADD_TRAIT(user, TRAIT_DARKSPAWN_SPACEWALK, "starlight sigils") + +//Decreases the Psi regeneration delay by 3 ticks and increases Psi regeneration threshold to 25. +/datum/psi_web/psi_regen + name = "\'Recovery\' Sigil" + desc = "The Mqeygjao sigil, representing swiftness, is etched onto the forehead. Unlocking this sigil causes your Psi to regenerate 3 ticks sooner, and you will regenerate up to 25 Psi instead of 20." + lucidity_price = 1 + menu_tab = STORE_PASSIVE + +/datum/psi_web/psi_regen/activate(mob/user) + darkspawn.psi_regen += 5 + darkspawn.psi_regen_delay -= 3 diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/psi_regen.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/psi_regen.dm deleted file mode 100644 index 6aead6117cc3..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/psi_regen.dm +++ /dev/null @@ -1,10 +0,0 @@ -//Decreases the Psi regeneration delay by 3 ticks and increases Psi regeneration threshold to 25. -/datum/darkspawn_upgrade/psi_regen - name = "\'Recovery\' Sigil" - id = "psi_regen" - desc = "The Mqeygjao sigil, representing swiftness, is etched onto the forehead. Unlocking this sigil causes your Psi to regenerate 3 ticks sooner, and you will regenerate up to 25 Psi instead of 20." - lucidity_price = 1 - -/datum/darkspawn_upgrade/psi_regen/apply_effects() - darkspawn.psi_regen = 25 - darkspawn.psi_regen_delay -= 3 diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/spacewalking.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/spacewalking.dm deleted file mode 100644 index f8bd4ef55073..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/spacewalking.dm +++ /dev/null @@ -1,6 +0,0 @@ -//Provides immunity to starlight. -/datum/darkspawn_upgrade/spacewalking - name = "\'Starlight\' Sigils" - id = "spacewalking" - desc = "The Jaxqhw sigils, representing the void, are etched multiple times across the body. Unlocking these sigils provides the ability to walk freely in space without fear of starlight." - lucidity_price = 3 From f8bfc9e004a7ad458f6e7097299b4cf4bbbf738e Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 15:48:42 -0500 Subject: [PATCH 032/756] passives --- code/__DEFINES/traits.dm | 1 + .../human/species_types/shadowpeople.dm | 28 ++++++----- yogstation.dme | 2 - .../code/game/gamemodes/darkspawn/psi_web.dm | 46 ++++++++++++++++--- .../darkspawn/darkspawn_abilities/pass.dm | 5 +- .../darkspawn_upgrades/light_resistance.dm | 7 --- .../darkspawn_upgrades/twin_tendrils.dm | 9 ---- 7 files changed, 59 insertions(+), 39 deletions(-) delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/light_resistance.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/twin_tendrils.dm diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 301eceff8583..a5f75baa5dfd 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -469,3 +469,4 @@ ///Darkspawn traits #define TRAIT_DARKSPAWN_SPACEWALK "darkspawn_spacewalk" //lets darkspawns spacewalk safely +#define TRAIT_DARKSPAWN_LIGHTRES "darkspawn_lightres" //lets darkspawns spacewalk safely diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 977104b20005..be3f15c09dac 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -39,19 +39,23 @@ H.SetSleeping(0) H.setOrganLoss(ORGAN_SLOT_BRAIN,0) if(SHADOW_SPECIES_DIM_LIGHT to SHADOW_SPECIES_BRIGHT_LIGHT) //not bright, but still dim - if(HAS_TRAIT(H, TRAIT_SPACEWALK) && isspaceturf(T)) - return - if(!H.has_status_effect(STATUS_EFFECT_CREEP)) - to_chat(H, span_userdanger("The light singes you!")) - H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 40 * light_amount), TRUE) - H.adjustCloneLoss(light_burning * 0.2) + if(HAS_TRAIT(H, TRAIT_DARKSPAWN_SPACEWALK) && isspaceturf(T)) + break + if(HAS_TRAIT(H, TRAIT_DARKSPAWN_LIGHTRES)) + break + if(H.has_status_effect(STATUS_EFFECT_CREEP)) + break + to_chat(H, span_userdanger("The light singes you!")) + H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 40 * light_amount), TRUE) + H.adjustCloneLoss(light_burning * 0.2) if(SHADOW_SPECIES_BRIGHT_LIGHT to INFINITY) //but quick death in the light - if(HAS_TRAIT(H, TRAIT_SPACEWALK) && isspaceturf(T)) - return - if(!H.has_status_effect(STATUS_EFFECT_CREEP)) - to_chat(H, span_userdanger("The light burns you!")) - H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) - H.adjustCloneLoss(light_burning) + if(HAS_TRAIT(H, TRAIT_DARKSPAWN_SPACEWALK) && isspaceturf(T)) + break + if(H.has_status_effect(STATUS_EFFECT_CREEP)) + break + to_chat(H, span_userdanger("The light burns you!")) + H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) + H.adjustCloneLoss(light_burning) /datum/species/shadow/check_roundstart_eligible() if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) diff --git a/yogstation.dme b/yogstation.dme index 7682b4fb4957..0bac16db6f6f 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3987,8 +3987,6 @@ #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\psionic_barrier.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\simulacrum.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\umbral_tendrils.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\light_resistance.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrades\twin_tendrils.dm" #include "yogstation\code\modules\antagonists\gang\gang.dm" #include "yogstation\code\modules\antagonists\gang\gang_datums.dm" #include "yogstation\code\modules\antagonists\gang\gang_hud.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 18188de0cdd9..e7363ef4089b 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -218,10 +218,23 @@ desc = "The Atlwjz sigils, representing Psi, are etched onto the forehead. Unlocking these sigils increases your maximum Psi by 25." lucidity_price = 2 menu_tab = STORE_PASSIVE + shadow_flags = WARLOCK /datum/psi_web/psi_cap/activate(mob/user) darkspawn.psi_cap += 25 +//Decreases the Psi regeneration delay by 3 ticks and increases Psi regeneration threshold to 25. +/datum/psi_web/psi_regen + name = "\'Recovery\' Sigil" + desc = "The Mqeygjao sigil, representing swiftness, is etched onto the forehead. Unlocking this sigil causes your Psi to regenerate 3 ticks sooner, and you will regenerate up to 25 Psi instead of 20." + lucidity_price = 1 + menu_tab = STORE_PASSIVE + shadow_flags = WARLOCK + +/datum/psi_web/psi_regen/activate(mob/user) + darkspawn.psi_regen += 5 + darkspawn.psi_regen_delay -= 3 + //Increases healing in darkness by 25%. /datum/psi_web/dark_healing name = "\'Mending\' Sigil" @@ -229,27 +242,46 @@ desc = "The Naykranu sigil, representing perseverence, is etched onto the back. Unlocking this sigil increases your healing in darkness by 25%." lucidity_price = 1 menu_tab = STORE_PASSIVE + shadow_flags = FIGHTER | SCOUT /datum/psi_web/dark_healing/activate(mob/user) darkspawn.dark_healing *= 1.25 +//Halves lightburn damage and gives resistance to dim light. +/datum/psi_web/light_resistance + name = "\'Lightward\' Sigil" + desc = "The Lnkpayp sigil, representing imperviousness, is etched onto the abdomen. Unlocking this sigil halves light damage taken and protects from dim light." + lucidity_price = 2 + menu_tab = STORE_PASSIVE + shadow_flags = FIGHTER + +/datum/psi_web/light_resistance/activate(mob/user) + darkspawn.light_damage /= 2 + ADD_TRAIT(user, TRAIT_DARKSPAWN_LIGHTRES, "lightward sigils") + //Provides immunity to starlight. /datum/psi_web/spacewalking name = "\'Starlight\' Sigils" desc = "The Jaxqhw sigils, representing the void, are etched multiple times across the body. Unlocking these sigils provides the ability to walk freely in space without fear of starlight." lucidity_price = 3 menu_tab = STORE_PASSIVE + shadow_flags = FIGHTER | SCOUT /datum/psi_web/spacewalking/activate(mob/user) ADD_TRAIT(user, TRAIT_DARKSPAWN_SPACEWALK, "starlight sigils") -//Decreases the Psi regeneration delay by 3 ticks and increases Psi regeneration threshold to 25. -/datum/psi_web/psi_regen - name = "\'Recovery\' Sigil" - desc = "The Mqeygjao sigil, representing swiftness, is etched onto the forehead. Unlocking this sigil causes your Psi to regenerate 3 ticks sooner, and you will regenerate up to 25 Psi instead of 20." +//Using Pass will now form two tendrils if possible. +//Attacking with one set of tendrils will attack with the other. +//This also speeds up most actions they have. +//Check pass.dm and umbral_tendrils.dm for effects. +/datum/psi_web/twin_tendrils + name = "\'Duality\' Sigils" + desc = "The Zkqxha sigils, representing duality, are etched onto the arms. Unlocking these sigils causes Pass to form tendrils in both hands if possible, which empowers both." lucidity_price = 1 + shadow_flags = FIGHTER menu_tab = STORE_PASSIVE -/datum/psi_web/psi_regen/activate(mob/user) - darkspawn.psi_regen += 5 - darkspawn.psi_regen_delay -= 3 +/datum/psi_web/twin_tendrils/activate(mob/user) + var/datum/action/innate/darkspawn/pass/spell = locate() in darkspawn.upgrades + if(spell) + spell.twin = TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index 3c0f31d4f6e7..6a506fa7333e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -5,6 +5,7 @@ desc = "Twists an active arm into tendrils with many important uses. Examine the tendrils to see a list of uses." button_icon_state = "pass" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS + var/twin = FALSE /datum/action/innate/darkspawn/pass/IsAvailable(feedback = FALSE) if(istype(owner, /mob/living/simple_animal/hostile/crawling_shadows) || istype(owner, /mob/living/simple_animal/hostile/darkspawn_progenitor) || !owner.get_empty_held_indexes() && !active) @@ -14,7 +15,7 @@ /datum/action/innate/darkspawn/pass/process() ..() active = locate(/obj/item/umbral_tendrils) in owner - if(darkspawn.upgrades["twin_tendrils"]) + if(twin) name = "Twinned Pass" desc = "Twists one or both of your arms into tendrils with many uses." @@ -24,7 +25,7 @@ to_chat(owner, span_warning("Stand up first!")) return var/list/hands_free = owner.get_empty_held_indexes() - if(!darkspawn.upgrades["twin_tendrils"] || hands_free.len < 2) + if(!twin || hands_free.len < 2) owner.visible_message(span_warning("[owner]'s arm contorts into tentacles!"), "ikna
\ [span_notice("You transform your arm into umbral tendrils. Examine them to see possible uses.")]") playsound(owner, 'yogstation/sound/magic/pass_create.ogg', 50, 1) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/light_resistance.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/light_resistance.dm deleted file mode 100644 index e4e60b9f1c6f..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/light_resistance.dm +++ /dev/null @@ -1,7 +0,0 @@ -//Halves lightburn damage and gives resistance to dim light. -//Check species_types/darkspawn.dm for effects. -/datum/darkspawn_upgrade/light_resistance - name = "\'Lightward\' Sigil" - id = "light_resistance" - desc = "The Lnkpayp sigil, representing imperviousness, is etched onto the abdomen. Unlocking this sigil halves light damage taken and protects from dim light." - lucidity_price = 2 diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/twin_tendrils.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/twin_tendrils.dm deleted file mode 100644 index 4bf95bf71d7d..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrades/twin_tendrils.dm +++ /dev/null @@ -1,9 +0,0 @@ -//Using Pass will now form two tendrils if possible. -//Attacking with one set of tendrils will attack with the other. -//This also speeds up most actions they have. -//Check pass.dm and umbral_tendrils.dm for effects. -/datum/darkspawn_upgrade/twin_tendrils - name = "\'Duality\' Sigils" - id = "twin_tendrils" - desc = "The Zkqxha sigils, representing duality, are etched onto the arms. Unlocking these sigils causes Pass to form tendrils in both hands if possible, which empowers both." - lucidity_price = 1 From feb018fac2a942b298ed78be9aec7b071f57328f Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 16:10:43 -0500 Subject: [PATCH 033/756] Update psi_web.dm --- yogstation/code/game/gamemodes/darkspawn/psi_web.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index e7363ef4089b..309ef0b4e738 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -273,7 +273,7 @@ //Using Pass will now form two tendrils if possible. //Attacking with one set of tendrils will attack with the other. //This also speeds up most actions they have. -//Check pass.dm and umbral_tendrils.dm for effects. +//Check pass.dm and for the effect. /datum/psi_web/twin_tendrils name = "\'Duality\' Sigils" desc = "The Zkqxha sigils, representing duality, are etched onto the arms. Unlocking these sigils causes Pass to form tendrils in both hands if possible, which empowers both." From 278247b24a559d907c22194f2a3d29884cb760ed Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 18:47:58 -0500 Subject: [PATCH 034/756] abilities work --- code/modules/spells/spell.dm | 26 +++++++++- yogstation.dme | 1 - .../code/game/gamemodes/darkspawn/psi_web.dm | 10 ++-- .../antagonists/darkspawn/darkspawn.dm | 1 - .../darkspawn/darkspawn_abilities/pass.dm | 11 ++-- .../darkspawn/darkspawn_ability.dm | 51 ------------------- 6 files changed, 34 insertions(+), 66 deletions(-) delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_ability.dm diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index b3a73046b8cb..58e125ef9226 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -85,6 +85,9 @@ /// The amount of smoke to create on cast. This is a range, so a value of 5 will create enough smoke to cover everything within 5 steps. var/smoke_amt = 0 + ///used for darkspawn, if there is a psi cost, it will try to check for a darkspawn datum + var/psi_cost = 0 //can var edit psi_cost to 0 to make darkspawn abilities usable by non-darkspawns + /datum/action/cooldown/spell/Grant(mob/grant_to) // If our spell is mind-bound, we only wanna grant it to our mind if(istype(target, /datum/mind)) @@ -130,7 +133,15 @@ if(!can_cast_spell()) return FALSE - return ..() + . = ..() + + // Add this after the parent call so psi is only consumed when the ability WILL happen + if(psi_cost && .) + if(owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN))//sanity check + var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + darkspawn.psi -= psi_cost + return TRUE + return FALSE /datum/action/cooldown/spell/set_click_ability(mob/on_who) if(SEND_SIGNAL(on_who, COMSIG_MOB_SPELL_ACTIVATED, src) & SPELL_CANCEL_CAST) @@ -171,6 +182,19 @@ to_chat(owner, span_warning("You must dedicate yourself to silence first!")) return FALSE + //used for darkspawn spells + if(psi_cost) + if(owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) + var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + if(darkspawn.psi < psi_cost) + if(feedback) + owner.balloon_alert(owner, span_warning("Not enough psi!")) + return FALSE + else + if(feedback) + to_chat(owner, span_warning("Your mind is incapable of comprehending this ability!")) + return FALSE + // If the spell requires the user has no antimagic equipped, and they're holding antimagic // that corresponds with the spell's antimagic, then they can't actually cast the spell if((spell_requirements & SPELL_REQUIRES_NO_ANTIMAGIC) && !owner.can_cast_magic(antimagic_flags)) diff --git a/yogstation.dme b/yogstation.dme index 0bac16db6f6f..00432771589e 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3968,7 +3968,6 @@ #include "yogstation\code\modules\antagonists\blob\blob\blobs\core.dm" #include "yogstation\code\modules\antagonists\darkspawn\crawling_shadows.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_ability.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_progenitor.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrade.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_divulge.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 309ef0b4e738..f6c8b2d0c3e2 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -68,7 +68,7 @@ selected.on_purchase(darkspawn?.owner?.current) //ability for using the shadow store -/datum/action/innate/darkspawn/psi_web +/datum/action/innate/psi_web name = "Psi Web" id = "psi_web" desc = "Access the Mindlink directly to unlock and upgrade your supernatural powers." @@ -77,20 +77,18 @@ psi_cost = 0 var/datum/antag_menu/psi_web/psi_web -/datum/action/innate/darkspawn/psi_web/New(our_target) +/datum/action/innate/psi_web/New(our_target) . = ..() if(istype(our_target, /datum/antag_menu/psi_web)) psi_web = our_target else CRASH("psi_web action created with non web.") -/datum/action/innate/darkspawn/psi_web/Destroy() +/datum/action/innate/psi_web/Destroy() psi_web = null return ..() -/datum/action/innate/darkspawn/psi_web/Activate() - if(!darkspawn) - return +/datum/action/innate/psi_web/Activate() to_chat(usr, "You retreat inwards and touch the Mindlink...") psi_web.ui_interact(usr) return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 2022a81121bc..ebb7b5ef3526 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -213,7 +213,6 @@ psi_web = new(src) psi_web_action = new(psi_web) psi_web_action.Grant(owner.current) - psi_web_action.darkspawn = src darkspawn_state = DIVULGED return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index 6a506fa7333e..19e0a6263ae1 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -1,25 +1,24 @@ //Equips umbral tendrils with many uses. -/datum/action/innate/darkspawn/pass +/datum/action/innate/pass name = "Pass" - id = "pass" desc = "Twists an active arm into tendrils with many important uses. Examine the tendrils to see a list of uses." button_icon_state = "pass" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS var/twin = FALSE -/datum/action/innate/darkspawn/pass/IsAvailable(feedback = FALSE) +/datum/action/innate/pass/IsAvailable(feedback = FALSE) if(istype(owner, /mob/living/simple_animal/hostile/crawling_shadows) || istype(owner, /mob/living/simple_animal/hostile/darkspawn_progenitor) || !owner.get_empty_held_indexes() && !active) return return ..() -/datum/action/innate/darkspawn/pass/process() +/datum/action/innate/pass/process() ..() active = locate(/obj/item/umbral_tendrils) in owner if(twin) name = "Twinned Pass" desc = "Twists one or both of your arms into tendrils with many uses." -/datum/action/innate/darkspawn/pass/Activate() +/datum/action/innate/pass/Activate() var/mob/living/carbon/C = owner if(!(C.mobility_flags & MOBILITY_STAND)) to_chat(owner, span_warning("Stand up first!")) @@ -41,7 +40,7 @@ owner.put_in_hands(T) return TRUE -/datum/action/innate/darkspawn/pass/Deactivate() +/datum/action/innate/pass/Deactivate() owner.visible_message(span_warning("[owner]'s tentacles transform back!"), "haoo
\ [span_notice("You dispel the tendrils.")]") playsound(owner, 'yogstation/sound/magic/pass_dispel.ogg', 50, 1) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_ability.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_ability.dm deleted file mode 100644 index 610b823ee583..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_ability.dm +++ /dev/null @@ -1,51 +0,0 @@ -/datum/action/innate/darkspawn - name = "darkspawn ability" - var/id //The ability's ID, for giving, taking and such - desc = "This probably shouldn't exist." - button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' - background_icon_state = "bg_alien" - overlay_icon_state = "bg_alien_border" - buttontooltipstyle = "alien" - - var/psi_cost = 0 //How much psi the ability costs to use - var/lucidity_price = 0 //How much lucidity the ability costs to buy; if this is 0, it isn't listed on the catalog - var/in_use = FALSE //For channeled/cast-time abilities - var/datum/antagonist/darkspawn/darkspawn //Linked antag datum for drawing lucidity and psi - -/datum/action/innate/darkspawn/New() - ..() - START_PROCESSING(SSfastprocess, src) - -/datum/action/innate/darkspawn/Destroy() - STOP_PROCESSING(SSfastprocess, src) - return ..() - -/datum/action/innate/darkspawn/process() - build_all_button_icons() //so as to be consistent with psi costs and situational requirements, keep the button updated - -/datum/action/innate/darkspawn/Trigger() - var/activated = FALSE - if(!IsAvailable(feedback = TRUE)) - return - if(!active) - activated = Activate() - else - activated = Deactivate() - if(darkspawn) - darkspawn.use_psi(psi_cost * activated) - -/datum/action/innate/darkspawn/IsAvailable(feedback = FALSE) - if(!darkspawn) - return - if(!darkspawn.has_psi(psi_cost)) - if (feedback) - owner.balloon_alert(owner, "not enough psi!") - return - if(in_use) - if (feedback) - owner.balloon_alert(owner, "already in use!") - return - . = ..() - -/datum/action/innate/darkspawn/proc/reset() - in_use = FALSE From 030924782134538e2cd9a3c8c7d39fea83fe35de Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 18:59:32 -0500 Subject: [PATCH 035/756] DELETE --- yogstation.dme | 9 -- .../code/game/gamemodes/darkspawn/psi_web.dm | 8 +- .../antagonists/darkspawn/crawling_shadows.dm | 132 ------------------ .../antagonists/darkspawn/darkspawn.dm | 7 +- .../darkspawn/darkspawn_abilities/_divulge.dm | 4 +- .../darkspawn_abilities/_sacrament.dm | 8 +- .../darkspawn_abilities/crawling_shadows.dm | 23 --- .../darkspawn/darkspawn_abilities/creep.dm | 30 ---- .../darkspawn_abilities/demented_outburst.dm | 61 -------- .../darkspawn_abilities/silver_tongue.dm | 58 -------- .../darkspawn_abilities/simulacrum.dm | 23 --- .../darkspawn/darkspawn_abilities/tagalong.dm | 48 ------- .../darkspawn_abilities/time_dilation.dm | 22 --- .../darkspawn_abilities/veil_mind.dm | 45 ------ .../darkspawn/darkspawn_objects/dark_bead.dm | 4 +- 15 files changed, 14 insertions(+), 468 deletions(-) delete mode 100644 yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/crawling_shadows.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/creep.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/demented_outburst.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/silver_tongue.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/simulacrum.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/time_dilation.dm delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/veil_mind.dm diff --git a/yogstation.dme b/yogstation.dme index 00432771589e..a1d961ad82e6 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3966,22 +3966,13 @@ #include "yogstation\code\modules\antagonists\_common\antag_menu.dm" #include "yogstation\code\modules\antagonists\abductor\equipment\abduction_outfits.dm" #include "yogstation\code\modules\antagonists\blob\blob\blobs\core.dm" -#include "yogstation\code\modules\antagonists\darkspawn\crawling_shadows.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_progenitor.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrade.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_divulge.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_sacrament.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\crawling_shadows.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\creep.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\demented_outburst.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\devour_will.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\pass.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\silver_tongue.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\simulacrum.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\tagalong.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\time_dilation.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\veil_mind.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\dark_bead.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\psionic_barrier.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\simulacrum.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index f6c8b2d0c3e2..49b1e1d1e8bb 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -107,7 +107,7 @@ ///What specialization can buy this var/shadow_flags = NONE ///what ability is granted if any - var/datum/action/innate/darkspawn/learned_ability + var/datum/action/learned_ability ///what is printed when learned var/learn_text ///what tab of the antag menu does it fall under @@ -152,7 +152,7 @@ if(learn_text) to_chat(user, learn_text) if(learned_ability) - var/datum/action/innate/darkspawn/action = new learned_ability + var/datum/action/action = new learned_ability action.Grant(user) /* @@ -169,7 +169,7 @@ /datum/psi_web/fighter name = "fighter" desc = "me no think so good" - learned_ability = /datum/action/innate/darkspawn/pass + learned_ability = /datum/action/innate/pass /datum/psi_web/fighter/activate(mob/user) darkspawn.specialization = FIGHTER @@ -280,6 +280,6 @@ menu_tab = STORE_PASSIVE /datum/psi_web/twin_tendrils/activate(mob/user) - var/datum/action/innate/darkspawn/pass/spell = locate() in darkspawn.upgrades + var/datum/action/innate/pass/spell = locate() in darkspawn.upgrades if(spell) spell.twin = TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm b/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm deleted file mode 100644 index 7cf566cb8810..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/crawling_shadows.dm +++ /dev/null @@ -1,132 +0,0 @@ -/mob/living/simple_animal/hostile/crawling_shadows - name = "crawling shadows" - desc = "A formless mass of blackness with two huge, clawed hands and piercing white eyes." - icon = 'icons/effects/effects.dmi' //Placeholder sprite - icon_state = "blank_dspawn" - icon_living = "blank_dspawn" - response_help = "backs away from" - response_disarm = "shoves away" - response_harm = "flails at" - speed = 0 - ventcrawler = TRUE - maxHealth = 125 - health = 125 - - harm_intent_damage = 5 - obj_damage = 50 - melee_damage_lower = 5 //it has a built in stun if you want to kill someone kill them like a man - melee_damage_upper = 5 - attacktext = "claws" - attack_sound = 'sound/magic/demon_attack1.ogg' - speak_emote = list("whispers") - - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = INFINITY - - movement_type = FLYING - pressure_resistance = INFINITY - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - gold_core_spawnable = FALSE - - del_on_death = TRUE - deathmessage = "tremble, break form, and disperse!" - deathsound = 'yogstation/sound/magic/devour_will_victim.ogg' - - var/move_count = 0 //For spooky sound effects - var/knocking_out = FALSE - var/mob/living/darkspawn_mob - -/mob/living/simple_animal/hostile/crawling_shadows/New() - ..() - addtimer(CALLBACK(src, PROC_REF(check_darkspawn)), 1) - -/mob/living/simple_animal/hostile/crawling_shadows/Destroy() - if(darkspawn_mob && mind) - visible_message(span_warning("[src] transforms into a humanoid figure!"), span_warning("You return to your normal form.")) - playsound(src, 'yogstation/sound/magic/devour_will_end.ogg', 50, 1) - if(mind) - mind.transfer_to(darkspawn_mob) - darkspawn_mob.forceMove(get_turf(src)) - darkspawn_mob.status_flags &= ~GODMODE - return ..() - -/mob/living/simple_animal/hostile/crawling_shadows/Move() - move_count++ - if(move_count >= 5) - playsound(src, "crawling_shadows_walk", 25, 0) - move_count = 0 - ..() - -/mob/living/simple_animal/hostile/crawling_shadows/Life(seconds_per_tick = SSMOBS_DT, times_fired) - ..() - var/turf/T = get_turf(src) - var/lums = T.get_lumcount() - if(lums < SHADOW_SPECIES_BRIGHT_LIGHT) - invisibility = INVISIBILITY_OBSERVER //Invisible in complete darkness - speed = -1 //Faster, too - alpha = 255 - else - invisibility = initial(invisibility) - speed = 0 - alpha = min(lums * 60, 255) //Slowly becomes more visible in brighter light - -/mob/living/simple_animal/hostile/crawling_shadows/death(gibbed) - if(darkspawn_mob) - mind.transfer_to(darkspawn_mob) - ..(gibbed) - -/mob/living/simple_animal/hostile/crawling_shadows/proc/check_darkspawn() - if(!darkspawn_mob) - qdel(src) - return - darkspawn_mob.forceMove(src) - darkspawn_mob.status_flags |= GODMODE - darkspawn_mob.mind.transfer_to(src) - to_chat(src, span_warning("This will last for around a minute.")) - var/datum/action/innate/darkspawn/end_shadows/E = new - E.Grant(src) - QDEL_IN(src, 600) - -/mob/living/simple_animal/hostile/crawling_shadows/AttackingTarget() - if(ishuman(target) && !knocking_out) - var/mob/living/carbon/human/H = target - if(H.stat) - return ..() - knocking_out = TRUE - visible_message(span_warning("[src] pick up [H] and dangle \him in the air!"), span_notice("You pluck [H] from the ground...")) - to_chat(H, span_userdanger("[src] grab you and dangle you in the air!")) - H.Stun(30) - H.pixel_y += 4 - if(!do_after(src, 1 SECONDS, target)) - H.pixel_y -= 4 - knocking_out = FALSE - return - visible_message(span_warning("[src] gently press a hand against [H]'s face, and \he falls limp..."), span_notice("You quietly incapacitate [H].")) - H.pixel_y -= 4 - to_chat(H, span_userdanger("[src] press a hand to your face, and docility comes over you...")) - H.Paralyze(60) - knocking_out = FALSE - return TRUE - else if(istype(target, /obj/machinery/door)) - forceMove(get_turf(target)) - visible_message(span_warning("Shadows creep through [target]..."), span_notice("You slip through [target].")) - return - ..() - - -/datum/action/innate/darkspawn/end_shadows - name = "End Crawling Shadows" - id = "end_shadows" - desc = "Reverts you to your humanoid form." - button_icon_state = "crawling_shadows" - -/datum/action/innate/darkspawn/end_shadows/Activate() - qdel(owner) //edgi - qdel(src) - -/datum/action/innate/darkspawn/end_shadows/IsAvailable(feedback = FALSE) - if(istype(owner, /mob/living/simple_animal/hostile/crawling_shadows)) - return TRUE - return FALSE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index ebb7b5ef3526..85e4b024c25e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -33,7 +33,7 @@ //upgrade variables var/list/upgrades = list() //A list of all the upgrades we currently have (actual objects, not just typepaths) var/datum/antag_menu/psi_web/psi_web //Antag menu used for opening the UI - var/datum/action/innate/darkspawn/psi_web/psi_web_action //Used to link the menu with our antag datum + var/datum/action/innate/psi_web/psi_web_action //Used to link the menu with our antag datum var/specialization = NONE // Antagonist datum things like assignment // @@ -43,7 +43,7 @@ owner.special_role = "darkspawn" owner.current.hud_used.psi_counter.invisibility = 0 update_psi_hud() - var/datum/action/innate/darkspawn/divulge/action = new() + var/datum/action/innate/divulge/action = new() action.Grant(owner.current) action.darkspawn = src upgrades += action @@ -221,9 +221,6 @@ if(!SSticker.mode.sacrament_done) set_security_level(SEC_LEVEL_GAMMA) addtimer(CALLBACK(src, PROC_REF(sacrament_shuttle_call)), 50) - for(var/datum/action/innate/darkspawn/leftover_ability in user.actions) - leftover_ability.Remove(user) - QDEL_NULL(leftover_ability) // Spawn the cosmic progenitor var/mob/living/simple_animal/hostile/darkspawn_progenitor/progenitor = new(get_turf(user)) user.status_flags |= GODMODE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 879e3df5cfd6..a7474ff4e135 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -1,12 +1,12 @@ //A channeled ability that turns the darkspawn into their main form. -/datum/action/innate/darkspawn/divulge +/datum/action/innate/divulge name = "Divulge" id = "divulge" desc = "Sheds your human disguise. This is obvious and so should be done in a secluded area. You cannot reverse this." button_icon_state = "divulge" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_LYING -/datum/action/innate/darkspawn/divulge/Activate() +/datum/action/innate/divulge/Activate() set waitfor = FALSE var/mob/living/carbon/human/user = usr var/turf/spot = get_turf(user) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index ff10b8639441..e223d5f125c1 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -1,5 +1,5 @@ //Turns the darkspawn into a progenitor. -/datum/action/innate/darkspawn/sacrament +/datum/action/innate/sacrament name = "Sacrament" id = "sacrament" desc = "Ascends into a progenitor. Unless someone else has performed the Sacrament, you must have drained lucidity from 15-30 (check your objective) different people for this to work, and purchased all passive upgrades." @@ -7,7 +7,7 @@ check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS var/datum/looping_sound/sacrament/soundloop -/datum/action/innate/darkspawn/sacrament/Activate() +/datum/action/innate/sacrament/Activate() if(SSticker.mode.sacrament_done) darkspawn.sacrament() return @@ -65,11 +65,11 @@ animate(user, pixel_y = user.pixel_y + 20, time = 4 SECONDS) addtimer(CALLBACK(darkspawn, TYPE_PROC_REF(/datum/antagonist/darkspawn, sacrament)), 4 SECONDS) -/datum/action/innate/darkspawn/sacrament/proc/unleashed_psi(turf/T) +/datum/action/innate/sacrament/proc/unleashed_psi(turf/T) playsound(T, 'yogstation/sound/magic/divulge_end.ogg', 25, FALSE) new/obj/effect/temp_visual/revenant/cracks(T) -/datum/action/innate/darkspawn/sacrament/proc/shatter_lights() +/datum/action/innate/sacrament/proc/shatter_lights() if(SSticker.mode.sacrament_done) return for(var/obj/machinery/light/light in SSmachines.processing) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/crawling_shadows.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/crawling_shadows.dm deleted file mode 100644 index 360ead2cc1ee..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/crawling_shadows.dm +++ /dev/null @@ -1,23 +0,0 @@ -//Assumes a stealthier form for sixty seconds or until cancelled. -/datum/action/innate/darkspawn/crawling_shadows - name = "Crawling Shadows" - id = "crawling_shadows" - desc = "Assumes a shadowy form for a minute that can crawl through vents and squeeze through the cracks in doors. You can also knock people out by attacking them." - button_icon_state = "crawling_shadows" - check_flags = AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS - psi_cost = 60 - lucidity_price = 2 //probably going to replace creep with this - -/datum/action/innate/darkspawn/crawling_shadows/IsAvailable(feedback = FALSE) - var/mob/living/L = owner - if(L.has_status_effect(STATUS_EFFECT_TAGALONG)) - return - return ..() - -/datum/action/innate/darkspawn/crawling_shadows/Activate() - owner.visible_message(span_warning("[owner] falls to the ground and transforms into a shadowy creature!"), "sa iahz sepd zwng\n\ - [span_notice("You assume a stealthier form.")]") - playsound(owner, 'yogstation/sound/magic/devour_will_end.ogg', 50, 1) - var/mob/living/simple_animal/hostile/crawling_shadows/CS = new /mob/living/simple_animal/hostile/crawling_shadows(get_turf(owner)) - CS.darkspawn_mob = owner - return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/creep.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/creep.dm deleted file mode 100644 index b8404f43d6e3..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/creep.dm +++ /dev/null @@ -1,30 +0,0 @@ -//Allows you to move through light unimpeded while active. Drains 5 Psi per second. -/datum/action/innate/darkspawn/creep - name = "Creep" - id = "creep" - desc = "Grants immunity to lightburn while active. Can be toggled on and off. Drains 5 Psi per second." - button_icon_state = "creep" - check_flags = AB_CHECK_CONSCIOUS - psi_cost = 5 - lucidity_price = 2 - -/datum/action/innate/darkspawn/creep/IsAvailable(feedback = FALSE) - if(istype(owner, /mob/living/simple_animal/hostile/crawling_shadows)) - return - return ..() - -/datum/action/innate/darkspawn/creep/process() - var/mob/living/L = owner - active = L.has_status_effect(STATUS_EFFECT_CREEP) - -/datum/action/innate/darkspawn/creep/Activate() - var/mob/living/L = owner - owner.visible_message(span_warning("Velvety shadows coalesce around [owner]!"), span_velvet("odeahz
You begin using Psi to shield yourself from lightburn.")) - playsound(owner, 'yogstation/sound/magic/devour_will_victim.ogg', 50, TRUE) - L.apply_status_effect(STATUS_EFFECT_CREEP, darkspawn) - -/datum/action/innate/darkspawn/creep/Deactivate() - var/mob/living/L = owner - to_chat(owner, span_velvet("You release your grip on the shadows.")) - playsound(owner, 'yogstation/sound/magic/devour_will_end.ogg', 50, TRUE) - L.remove_status_effect(STATUS_EFFECT_CREEP) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/demented_outburst.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/demented_outburst.dm deleted file mode 100644 index e9f7ef0a0ade..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/demented_outburst.dm +++ /dev/null @@ -1,61 +0,0 @@ -//Emits a shockwave that blasts everyone and everything nearby far away. People close to the user are deafened and stunned. -/datum/action/innate/darkspawn/demented_outburst - name = "Demented Outburst" - id = "demented_outburst" - desc = "Deafens and confuses listeners after a five-second charge period, knocking away everyone nearby. Costs 50 Psi." - button_icon_state = "demented_outburst" - check_flags = AB_CHECK_CONSCIOUS - psi_cost = 50 //big boom = big cost - lucidity_price = 2 - -/datum/action/innate/darkspawn/demented_outburst/Activate() - in_use = TRUE - owner.visible_message(span_boldwarning("[owner] begins to growl as their chitin hardens..."), "cap...
\ - [span_danger("You begin harnessing your power...")]") - playsound(owner, 'yogstation/sound/magic/demented_outburst_charge.ogg', 50, 0) - addtimer(CALLBACK(src, PROC_REF(outburst), owner), 50) - addtimer(CALLBACK(src, PROC_REF(reset)), 50) - return TRUE - -/datum/action/innate/darkspawn/demented_outburst/IsAvailable(feedback = FALSE) - if(istype(owner, /mob/living/simple_animal/hostile/crawling_shadows)) - return - return ..() - -/datum/action/innate/darkspawn/demented_outburst/proc/outburst() - in_use = FALSE - if(!owner || owner.stat) - return - owner.visible_message(span_userdanger("[owner] lets out a deafening scream!"), "WSWU!
\ - [span_danger("You let out a deafening outburst!")]") - playsound(owner, 'yogstation/sound/magic/demented_outburst_scream.ogg', 75, 0) - var/list/thrown_atoms = list() - for(var/turf/T in view(5, owner)) - for(var/atom/movable/AM in T) - thrown_atoms += AM - for(var/V in thrown_atoms) - var/atom/movable/AM = V - if(AM == owner || AM.anchored) - continue - var/distance = get_dist(owner, AM) - var/turf/target = get_edge_target_turf(owner, get_dir(owner, get_step_away(AM, owner))) - AM.throw_at(target, ((clamp((5 - (clamp(distance - 2, 0, distance))), 3, 5))), 1, owner) - if(iscarbon(AM)) - var/mob/living/carbon/C = AM - if(distance <= 1) //you done fucked up now - C.visible_message(span_warning("The blast sends [C] flying!"), span_userdanger("The force sends you flying!")) - C.Paralyze(50) - C.Knockdown(50) - C.adjustBruteLoss(10) - C.soundbang_act(1, 5, 15, 5) - else if(distance <= 3) - C.visible_message(span_warning("The blast knocks [C] off their feet!"), span_userdanger("The force bowls you over!")) - C.Paralyze(25) - C.Knockdown(30) - C.soundbang_act(1, 3, 5, 0) - if(iscyborg(AM)) - var/mob/living/silicon/robot/R = AM - R.visible_message(span_warning("The blast sends [R] flying!"), span_userdanger("The force sends you flying!")) - R.Paralyze(100) //fuck borgs - R.soundbang_act(1, 5, 15, 5) - return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/silver_tongue.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/silver_tongue.dm deleted file mode 100644 index b7bb50dbeaa7..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/silver_tongue.dm +++ /dev/null @@ -1,58 +0,0 @@ -//Can be used on a communications console to recall the shuttle. Leaves visible evidence. -/datum/action/innate/darkspawn/silver_tongue - name = "Silver Tongue" - id = "silver_tongue" - desc = "When used near a communications console, allows you to forcefully transmit a message to Central Command, initiating a shuttle recall. Only usable if the shuttle is inbound. Costs 60 Psi." - button_icon_state = "silver_tongue" - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_IMMOBILE - psi_cost = 60 - lucidity_price = 1 //Very niche, so low cost - -/datum/action/innate/darkspawn/silver_tongue/IsAvailable(feedback = FALSE) - if(SSshuttle.emergency.mode != SHUTTLE_CALL) - return - return ..() - -/datum/action/innate/darkspawn/silver_tongue/Activate() - in_use = TRUE - var/obj/machinery/computer/communications/C = locate() in range(1, owner) - if(!C) - to_chat(owner, span_warning("There are no communications consoles nearby")) - return - if(C.stat) - to_chat(owner, span_warning("[C] is depowered.")) - return - owner.visible_message(span_warning("[owner] briefly touches [src]'s screen, and the keys begin to move by themselves!"), \ - "[pick("Oknnu. Pda ywlpwej swo hkccaz ej.", "Pda aiancajyu eo kran. Oknnu bkn swopejc ukqn peia.", "We swo knzanaz xu Hws Psk. Whh ckkz jks.")]
\ - [span_velvet("You begin transmitting a recall message to Central Command...")]") - play_recall_sounds(C) - if(!do_after(owner, 8 SECONDS, C)) - in_use = FALSE - return - if(!C) - in_use = FALSE - return - if(C.stat) - to_chat(owner, span_warning("[C] has lost power.")) - in_use = FALSE - return - in_use = FALSE - SSshuttle.emergency.cancel() - to_chat(owner, span_velvet("The ruse was a success. The shuttle is on its way back.")) - return TRUE - -/datum/action/innate/darkspawn/silver_tongue/proc/play_recall_sounds(obj/machinery/C) //neato sound effects - set waitfor = FALSE - for(var/i in 1 to 4) - sleep(1 SECONDS) - if(!C || C.stat) - return - playsound(C, "terminal_type", 50, TRUE) - if(prob(25)) - playsound(C, 'sound/machines/terminal_alert.ogg', 50, FALSE) - do_sparks(5, TRUE, get_turf(C)) - playsound(C, 'sound/machines/terminal_prompt.ogg', 50, FALSE) - sleep(0.5 SECONDS) - if(!C || C.stat) - return - playsound(C, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/simulacrum.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/simulacrum.dm deleted file mode 100644 index 25d43b187186..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/simulacrum.dm +++ /dev/null @@ -1,23 +0,0 @@ -//Creates an illusionary copy of the caster that runs in their direction for ten seconds and then vanishes. -/datum/action/innate/darkspawn/simulacrum - name = "Simulacrum" - id = "simulacrum" - desc = "Creates an illusion that closely resembles you. The illusion will run forward for ten seconds. Costs 20 Psi." - button_icon_state = "simulacrum" - check_flags = AB_CHECK_CONSCIOUS - psi_cost = 20 - lucidity_price = 1 - -/datum/action/innate/darkspawn/simulacrum/Activate() - if(isliving(owner.loc)) - var/mob/living/L = owner.loc - L.visible_message(span_warning("[owner] breaks away from [L]'s shadow!"), \ - span_userdanger("You feel a sense of freezing cold pass through you!")) - to_chat(owner, span_velvet("zayaera
You create an illusion of yourself.")) - else - owner.visible_message(span_warning("[owner] splits in two!"), \ - span_velvet("zayaera
You create an illusion of yourself.")) - playsound(owner, 'yogstation/sound/magic/devour_will_form.ogg', 50, 1) - var/obj/effect/simulacrum/simulacrum = new(get_turf(owner)) - simulacrum.mimic(owner) - return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm deleted file mode 100644 index 20b1fb46d50a..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/tagalong.dm +++ /dev/null @@ -1,48 +0,0 @@ -//Melds with a mob's shadow, allowing the caster to "shadow" (HA) them while they're not in darkness. -/datum/action/innate/darkspawn/tagalong - name = "Tagalong" - id = "tagalong" - desc = "Melds with a target's shadow, causing you to invisibly follow them. Only works in lit areas, and you will be forced out if you hold any items. Costs 30 Psi." - button_icon_state = "tagalong" - check_flags = AB_CHECK_CONSCIOUS - psi_cost = 30 - lucidity_price = 2 - var/datum/status_effect/tagalong/tagalong - -/datum/action/innate/darkspawn/tagalong/IsAvailable(feedback = FALSE) - if(istype(owner, /mob/living/simple_animal/hostile/crawling_shadows)) - return - return ..() - -/datum/action/innate/darkspawn/tagalong/process() - psi_cost = 30 * isnull(tagalong) - -/datum/action/innate/darkspawn/tagalong/Activate() - if(tagalong) - QDEL_NULL(tagalong) - return - if(owner.get_active_held_item() || owner.get_inactive_held_item()) - to_chat(owner, span_warning("Your hands must be empty to accompany someone!")) - return - var/list/targets = list() - var/mob/living/target - var/turf/T - for(var/mob/living/L in range(7, owner) - owner) - T = get_turf(L) - if(!isdarkspawn(L) && L.stat != DEAD && T.get_lumcount() >= SHADOW_SPECIES_DIM_LIGHT) - targets += L - if(!targets.len) - to_chat(owner, span_warning("There is nobody nearby in any lit areas!")) - return - if(targets.len == 1) - target = targets[1] - else - target = input(owner, "Choose a target to accompany.", "Tagalong") as null|anything in targets - if(!target) - return - var/mob/living/L = owner - tagalong = L.apply_status_effect(STATUS_EFFECT_TAGALONG, target) - to_chat(owner, "iahz
\ - You slip into [target]'s shadow. This will last five minutes, until canceled, or you are forced out.
") - owner.forceMove(target) - return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/time_dilation.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/time_dilation.dm deleted file mode 100644 index 87a5a930090d..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/time_dilation.dm +++ /dev/null @@ -1,22 +0,0 @@ -//Greatly speeds up reflexes and recovery, at a massive Psi cost. -/datum/action/innate/darkspawn/time_dilation - name = "Time Dilation" - id = "time_dilation" - desc = "Greatly increases reaction times and action speed, and provides immunity to slowdown. This lasts for 1 minute. Costs 75 Psi." - button_icon_state = "time_dilation" - check_flags = AB_CHECK_CONSCIOUS - psi_cost = 75 - lucidity_price = 3 - -/datum/action/innate/darkspawn/time_dilation/IsAvailable(feedback = FALSE) - if(..() && !istype(owner, /mob/living/simple_animal/hostile/crawling_shadows)) - var/mob/living/L = owner - return !L.has_status_effect(STATUS_EFFECT_TIME_DILATION) - -/datum/action/innate/darkspawn/time_dilation/Activate() - var/mob/living/L = owner - L.apply_status_effect(STATUS_EFFECT_TIME_DILATION) - L.visible_message(span_warning("[L] howls as their body moves at wild speeds!"), \ - span_velvet("ckppw ck bwop
Your sigils howl out light as your body moves at incredible speed!")) - playsound(L, 'yogstation/sound/creatures/darkspawn_howl.ogg', 50, TRUE) - return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/veil_mind.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/veil_mind.dm deleted file mode 100644 index a26fff650ceb..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/veil_mind.dm +++ /dev/null @@ -1,45 +0,0 @@ -//Converts people within three tiles of the caster into veils. Also confuses noneligible targets and stuns silicons. -/datum/action/innate/darkspawn/veil_mind - name = "Veil Mind" - id = "veil_mind" - desc = "Converts nearby eligible targets into veils. To be eligible, they must be alive and recently drained by Devour Will." - button_icon_state = "veil_mind" - check_flags = AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS - psi_cost = 60 //since this is only useful when cast directly after a succ it should be pretty expensive - lucidity_price = 2 - -/datum/action/innate/darkspawn/veil_mind/Activate() - var/mob/living/carbon/human/H = owner - if(!H.can_speak_vocal()) - to_chat(H, span_warning("You can't speak!")) - return - owner.visible_message(span_warning("[owner]'s sigils flare as they inhale..."), "dawn kqn okjc...
\ - [span_notice("You take a deep breath...")]") - playsound(owner, 'yogstation/sound/ambience/antag/veil_mind_gasp.ogg', 25) - if(!do_after(owner, 1 SECONDS, owner)) - return - owner.visible_message(span_boldwarning("[owner] lets out a chilling cry!"), "...wjz oanra
\ - [span_notice("You veil the minds of everyone nearby.")]") - playsound(owner, 'yogstation/sound/ambience/antag/veil_mind_scream.ogg', 100) - for(var/mob/living/L in view(3, owner)) - if(L == owner) - continue - if(issilicon(L)) - to_chat(L, span_ownerdanger("$@!) ERR: RECEPTOR OVERLOAD ^![L.real_name] has become a veil!")) - else - to_chat(L, span_boldwarning("...and it scrambles your thoughts!")) - L.dir = pick(GLOB.cardinals) - L.adjust_confusion(2 SECONDS) - return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm index 48e49fdf5620..c8da91813297 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm @@ -12,7 +12,7 @@ light_power = 0.3 light_range = 2 var/eating = FALSE //If we're devouring someone's will - var/datum/action/innate/darkspawn/devour_will/linked_ability //The ability that keeps data for us + var/datum/action/cooldown/spell/devour_will/linked_ability //The ability that keeps data for us var/full_restore = TRUE /obj/item/dark_bead/Initialize(mapload) @@ -105,6 +105,6 @@ L.Unconscious(15) L.apply_effect(EFFECT_STUTTER, 20) L.apply_status_effect(STATUS_EFFECT_BROKEN_WILL) - addtimer(CALLBACK(linked_ability, TYPE_PROC_REF(/datum/action/innate/darkspawn/devour_will, make_eligible), L), 600) + addtimer(CALLBACK(linked_ability, TYPE_PROC_REF(/datum/action/cooldown/spell/devour_will, make_eligible), L), 600) qdel(src, force = TRUE) return TRUE From ab8fbc5236d67dcd2ee277d6d7758c545dd2babf Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 19:00:04 -0500 Subject: [PATCH 036/756] even more --- yogstation.dme | 1 - .../darkspawn/darkspawn_upgrade.dm | 21 ------------------- 2 files changed, 22 deletions(-) delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrade.dm diff --git a/yogstation.dme b/yogstation.dme index a1d961ad82e6..23ec9cc9994f 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3968,7 +3968,6 @@ #include "yogstation\code\modules\antagonists\blob\blob\blobs\core.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_progenitor.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_upgrade.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_divulge.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_sacrament.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\devour_will.dm" diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrade.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrade.dm deleted file mode 100644 index e30405cb0a53..000000000000 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_upgrade.dm +++ /dev/null @@ -1,21 +0,0 @@ -//Passive upgrades. These are applied as soon as they're purchased and then delete themselves. -/datum/darkspawn_upgrade - var/name = "darkspawn upgrade" - var/desc = "This is an upgrade." - var/id - var/lucidity_price = 0 //How much lucidity an upgrade costs to buy - var/datum/antagonist/darkspawn/darkspawn //The datum buying this upgrade - -/datum/darkspawn_upgrade/New(darkspawn_datum) - ..() - darkspawn = darkspawn_datum - -/datum/darkspawn_upgrade/proc/unlock() - if(!darkspawn) - return - apply_effects() - qdel(src) - return TRUE - -/datum/darkspawn_upgrade/proc/apply_effects() - return From 4ac525f735afb31a3497ec942deac3e9893efbc6 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 19:08:06 -0500 Subject: [PATCH 037/756] work --- .../darkspawn/darkspawn_abilities/_divulge.dm | 4 +++ .../darkspawn_abilities/devour_will.dm | 32 +++++++------------ .../darkspawn/darkspawn_objects/dark_bead.dm | 4 +-- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index a7474ff4e135..d99afbb8d2aa 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -43,6 +43,8 @@ for(var/turf/T in RANGE_TURFS(1, user)) new/obj/structure/psionic_barrier(T, 500) for(var/stage in 1 to 3) + if(isethereal(user))//keep the light disabled + user.dna.species.spec_emp_act(user, EMP_HEAVY) switch(stage) if(1) user.visible_message(span_userdanger("Vibrations pass through the air. [user]'s eyes begin to glow a deep violet."), \ @@ -63,6 +65,8 @@ animate(user, color = initial(user.color), pixel_y = initial(user.pixel_y), time = 1 SECONDS) in_use = FALSE return + if(isethereal(user))//keep the light disabled + user.dna.species.spec_emp_act(user, EMP_HEAVY) playsound(user, 'yogstation/sound/magic/divulge_ending.ogg', 50, 0) user.visible_message(span_userdanger("[user] rises into the air, crackling with power!"), "Your mind...! can't--- THINK--") animate(user, pixel_y = user.pixel_y + 8, time = 6 SECONDS) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm index 14ba6bf27645..8af11e939e5b 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm @@ -1,5 +1,5 @@ //After a brief charge-up, equips a temporary dark bead that can be used on a human to knock them out and drain their will, making them vulnerable to conversion. -/datum/action/innate/darkspawn/devour_will +/datum/action/cooldown/spell/devour_will name = "Devour Will" id = "devour_will" desc = "Creates a dark bead that can be used on a human to fully recharge Psi, gain one lucidity, and knock them unconscious. The victim will be stunned for the duration of the channel, being interrupted \ @@ -7,28 +7,20 @@ button_icon_state = "devour_will" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_LYING | AB_CHECK_CONSCIOUS psi_cost = 5 - var/list/victims //A list of people we've used the bead on recently; we can't drain them again so soon + var/list/victims = list()//A list of people we've used the bead on recently; we can't drain them again so soon var/last_victim -/datum/action/innate/darkspawn/devour_will/New() - ..() - victims = list() +/datum/action/cooldown/spell/devour_will/Activate() + if(..()) + owner.visible_message(span_warning("A glowing black orb appears in [owner]'s hand!"), "pwga...iejz
\ + You form a dark bead in your hand.
") + playsound(owner, 'yogstation/sound/magic/devour_will_form.ogg', 50, 1) + var/obj/item/dark_bead/B = new + owner.put_in_hands(B) + B.linked_ability = src + return TRUE -/datum/action/innate/darkspawn/devour_will/IsAvailable(feedback = FALSE) - if(!owner || istype(owner, /mob/living/simple_animal/hostile/crawling_shadows) ||istype(owner, /mob/living/simple_animal/hostile/darkspawn_progenitor) || !owner.get_empty_held_indexes()) - return - return ..() - -/datum/action/innate/darkspawn/devour_will/Activate() - owner.visible_message(span_warning("A glowing black orb appears in [owner]'s hand!"), "pwga...iejz
\ - You form a dark bead in your hand.
") - playsound(owner, 'yogstation/sound/magic/devour_will_form.ogg', 50, 1) - var/obj/item/dark_bead/B = new - owner.put_in_hands(B) - B.linked_ability = src - return TRUE - -/datum/action/innate/darkspawn/devour_will/proc/make_eligible(mob/living/L) +/datum/action/cooldown/spell/devour_will/proc/make_eligible(mob/living/L) if(!L || !victims[L]) return victims[L] = FALSE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm index c8da91813297..ad03f55e43e8 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm @@ -91,7 +91,7 @@ darkspawn.psi = darkspawn.psi_cap else //no getting free lucidity from veils that wouldn't be fun. They'll still count towards winning though. darkspawn.psi += 20 - if(linked_ability.victims[L] == FALSE) + if(linked_ability.victims[L]) to_chat(user, " You have already drained this individual previously, and their lucidity will not contribute any more to the sacrament!") else to_chat(user, " This individual's lucidity brings you one step closer to the sacrament...") @@ -105,6 +105,6 @@ L.Unconscious(15) L.apply_effect(EFFECT_STUTTER, 20) L.apply_status_effect(STATUS_EFFECT_BROKEN_WILL) - addtimer(CALLBACK(linked_ability, TYPE_PROC_REF(/datum/action/cooldown/spell/devour_will, make_eligible), L), 600) + addtimer(CALLBACK(linked_ability, TYPE_PROC_REF(/datum/action/cooldown/spell/devour_will, make_eligible), L), 60 SECONDS) qdel(src, force = TRUE) return TRUE From 824531b8e39712be32fe219a8cba9f875186b11c Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 19:31:13 -0500 Subject: [PATCH 038/756] compiles again --- .../human/species_types/shadowpeople.dm | 10 ++++---- .../code/game/gamemodes/darkspawn/psi_web.dm | 23 ++++++++----------- .../antagonists/darkspawn/darkspawn.dm | 1 - .../darkspawn/darkspawn_abilities/_divulge.dm | 17 +++++++++++--- .../darkspawn_abilities/_sacrament.dm | 16 ++++++++++++- .../darkspawn_abilities/devour_will.dm | 5 +++- .../darkspawn/darkspawn_abilities/pass.dm | 8 +++---- 7 files changed, 52 insertions(+), 28 deletions(-) diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index be3f15c09dac..61159746f131 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -40,19 +40,19 @@ H.setOrganLoss(ORGAN_SLOT_BRAIN,0) if(SHADOW_SPECIES_DIM_LIGHT to SHADOW_SPECIES_BRIGHT_LIGHT) //not bright, but still dim if(HAS_TRAIT(H, TRAIT_DARKSPAWN_SPACEWALK) && isspaceturf(T)) - break + return if(HAS_TRAIT(H, TRAIT_DARKSPAWN_LIGHTRES)) - break + return if(H.has_status_effect(STATUS_EFFECT_CREEP)) - break + return to_chat(H, span_userdanger("The light singes you!")) H.playsound_local(H, 'sound/weapons/sear.ogg', max(30, 40 * light_amount), TRUE) H.adjustCloneLoss(light_burning * 0.2) if(SHADOW_SPECIES_BRIGHT_LIGHT to INFINITY) //but quick death in the light if(HAS_TRAIT(H, TRAIT_DARKSPAWN_SPACEWALK) && isspaceturf(T)) - break + return if(H.has_status_effect(STATUS_EFFECT_CREEP)) - break + return to_chat(H, span_userdanger("The light burns you!")) H.playsound_local(H, 'sound/weapons/sear.ogg', max(40, 65 * light_amount), TRUE) H.adjustCloneLoss(light_burning) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 49b1e1d1e8bb..cbbd18de6eeb 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -43,7 +43,7 @@ AL["can_purchase"] = darkspawn.lucidity >= selection.lucidity_cost AL["type_path"] = selection.type - if(category == selection.menutab) + if(category == selection.menu_tab) upgrades += list(AL) qdel(selection) @@ -70,11 +70,9 @@ //ability for using the shadow store /datum/action/innate/psi_web name = "Psi Web" - id = "psi_web" desc = "Access the Mindlink directly to unlock and upgrade your supernatural powers." button_icon_state = "psi_web" check_flags = AB_CHECK_CONSCIOUS - psi_cost = 0 var/datum/antag_menu/psi_web/psi_web /datum/action/innate/psi_web/New(our_target) @@ -111,13 +109,13 @@ ///what is printed when learned var/learn_text ///what tab of the antag menu does it fall under - var/menutab + var/menu_tab ///The antag datum of the owner(used for modifying) var/datum/antagonist/darkspawn/darkspawn ///Check to see if they should be shown the ability /datum/psi_web/proc/check_show(mob/user) - if(!menutab && shadow_flags) + if(!menu_tab && shadow_flags) return FALSE darkspawn = user.mind?.has_antag_datum(/datum/antagonist/darkspawn) if(!darkspawn) @@ -214,7 +212,7 @@ /datum/psi_web/psi_cap name = "\'Psi\' Sigils" desc = "The Atlwjz sigils, representing Psi, are etched onto the forehead. Unlocking these sigils increases your maximum Psi by 25." - lucidity_price = 2 + lucidity_cost = 2 menu_tab = STORE_PASSIVE shadow_flags = WARLOCK @@ -225,7 +223,7 @@ /datum/psi_web/psi_regen name = "\'Recovery\' Sigil" desc = "The Mqeygjao sigil, representing swiftness, is etched onto the forehead. Unlocking this sigil causes your Psi to regenerate 3 ticks sooner, and you will regenerate up to 25 Psi instead of 20." - lucidity_price = 1 + lucidity_cost = 1 menu_tab = STORE_PASSIVE shadow_flags = WARLOCK @@ -236,9 +234,8 @@ //Increases healing in darkness by 25%. /datum/psi_web/dark_healing name = "\'Mending\' Sigil" - id = "dark_healing" desc = "The Naykranu sigil, representing perseverence, is etched onto the back. Unlocking this sigil increases your healing in darkness by 25%." - lucidity_price = 1 + lucidity_cost = 1 menu_tab = STORE_PASSIVE shadow_flags = FIGHTER | SCOUT @@ -249,19 +246,19 @@ /datum/psi_web/light_resistance name = "\'Lightward\' Sigil" desc = "The Lnkpayp sigil, representing imperviousness, is etched onto the abdomen. Unlocking this sigil halves light damage taken and protects from dim light." - lucidity_price = 2 + lucidity_cost = 2 menu_tab = STORE_PASSIVE shadow_flags = FIGHTER /datum/psi_web/light_resistance/activate(mob/user) - darkspawn.light_damage /= 2 + darkspawn.light_burning /= 2 ADD_TRAIT(user, TRAIT_DARKSPAWN_LIGHTRES, "lightward sigils") //Provides immunity to starlight. /datum/psi_web/spacewalking name = "\'Starlight\' Sigils" desc = "The Jaxqhw sigils, representing the void, are etched multiple times across the body. Unlocking these sigils provides the ability to walk freely in space without fear of starlight." - lucidity_price = 3 + lucidity_cost = 3 menu_tab = STORE_PASSIVE shadow_flags = FIGHTER | SCOUT @@ -275,7 +272,7 @@ /datum/psi_web/twin_tendrils name = "\'Duality\' Sigils" desc = "The Zkqxha sigils, representing duality, are etched onto the arms. Unlocking these sigils causes Pass to form tendrils in both hands if possible, which empowers both." - lucidity_price = 1 + lucidity_cost = 1 shadow_flags = FIGHTER menu_tab = STORE_PASSIVE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 85e4b024c25e..2400da4c574d 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -45,7 +45,6 @@ update_psi_hud() var/datum/action/innate/divulge/action = new() action.Grant(owner.current) - action.darkspawn = src upgrades += action addtimer(CALLBACK(src, PROC_REF(begin_force_divulge)), 23 MINUTES) //this won't trigger if they've divulged when the proc runs START_PROCESSING(SSprocessing, src) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index d99afbb8d2aa..8d1b5ea09728 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -1,10 +1,19 @@ //A channeled ability that turns the darkspawn into their main form. /datum/action/innate/divulge name = "Divulge" - id = "divulge" desc = "Sheds your human disguise. This is obvious and so should be done in a secluded area. You cannot reverse this." button_icon_state = "divulge" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_LYING + var/in_use = FALSE + +/datum/action/innate/divulge/IsAvailable(feedback) + if(!isdarkspawn(owner)) + return FALSE + if(in_use) + if (feedback) + owner.balloon_alert(owner, "already in use!") + return + . = ..() /datum/action/innate/divulge/Activate() set waitfor = FALSE @@ -92,5 +101,7 @@ for(var/T in GLOB.dead_mob_list) var/mob/M = T to_chat(M, "(F) [processed_message]") - if(darkspawn.divulge()) - Remove(user)//they don't need it anymore + if(isdarkspawn(owner))//sanity check + var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + if(darkspawn.divulge()) + Remove(user)//they don't need it anymore diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index e223d5f125c1..c1d0e01ea146 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -1,11 +1,25 @@ //Turns the darkspawn into a progenitor. /datum/action/innate/sacrament name = "Sacrament" - id = "sacrament" desc = "Ascends into a progenitor. Unless someone else has performed the Sacrament, you must have drained lucidity from 15-30 (check your objective) different people for this to work, and purchased all passive upgrades." button_icon_state = "sacrament" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS var/datum/looping_sound/sacrament/soundloop + var/datum/antagonist/darkspawn/darkspawn + var/in_use + +/datum/action/innate/sacrament/New(Target) + . = ..() + if(!isdarkspawn(owner)) + Remove(owner) + darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + +/datum/action/innate/sacrament/IsAvailable(feedback) + if(in_use) + if (feedback) + owner.balloon_alert(owner, "already in use!") + return + . = ..() /datum/action/innate/sacrament/Activate() if(SSticker.mode.sacrament_done) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm index 8af11e939e5b..7c2ac5db8a45 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm @@ -1,9 +1,12 @@ //After a brief charge-up, equips a temporary dark bead that can be used on a human to knock them out and drain their will, making them vulnerable to conversion. /datum/action/cooldown/spell/devour_will name = "Devour Will" - id = "devour_will" desc = "Creates a dark bead that can be used on a human to fully recharge Psi, gain one lucidity, and knock them unconscious. The victim will be stunned for the duration of the channel, being interrupted \ will knock both you and the victim down. Costs 5 Psi." + button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' + background_icon_state = "bg_alien" + overlay_icon_state = "bg_alien_border" + buttontooltipstyle = "alien" button_icon_state = "devour_will" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_LYING | AB_CHECK_CONSCIOUS psi_cost = 5 diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index 19e0a6263ae1..b0069359d5b9 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -7,8 +7,8 @@ var/twin = FALSE /datum/action/innate/pass/IsAvailable(feedback = FALSE) - if(istype(owner, /mob/living/simple_animal/hostile/crawling_shadows) || istype(owner, /mob/living/simple_animal/hostile/darkspawn_progenitor) || !owner.get_empty_held_indexes() && !active) - return + if(!isdarkspawn(owner)) + return FALSE return ..() /datum/action/innate/pass/process() @@ -28,7 +28,7 @@ owner.visible_message(span_warning("[owner]'s arm contorts into tentacles!"), "ikna
\ [span_notice("You transform your arm into umbral tendrils. Examine them to see possible uses.")]") playsound(owner, 'yogstation/sound/magic/pass_create.ogg', 50, 1) - var/obj/item/umbral_tendrils/T = new(owner, darkspawn) + var/obj/item/umbral_tendrils/T = new(owner, owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) owner.put_in_hands(T) else owner.visible_message(span_warning("[owner]'s arms contort into tentacles!"), "ikna ikna
\ @@ -36,7 +36,7 @@ playsound(owner, 'yogstation/sound/magic/pass_create.ogg', 50, TRUE) addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(playsound), owner, 'yogstation/sound/magic/pass_create.ogg', 50, TRUE), 1) for(var/i in 1 to 2) - var/obj/item/umbral_tendrils/T = new(owner, darkspawn) + var/obj/item/umbral_tendrils/T = new(owner, owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) owner.put_in_hands(T) return TRUE From 8573eab0dde83940dc1dbe353013277f858c0c04 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 19:52:27 -0500 Subject: [PATCH 039/756] rework regen --- code/modules/spells/spell.dm | 6 +++--- .../code/game/gamemodes/darkspawn/psi_web.dm | 4 ++++ .../antagonists/darkspawn/darkspawn.dm | 21 +++++++------------ .../darkspawn/darkspawn_abilities/_divulge.dm | 4 ++++ .../darkspawn_abilities/_sacrament.dm | 4 ++++ .../darkspawn/darkspawn_abilities/pass.dm | 4 ++++ 6 files changed, 26 insertions(+), 17 deletions(-) diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 58e125ef9226..a985504cf696 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -139,7 +139,7 @@ if(psi_cost && .) if(owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN))//sanity check var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) - darkspawn.psi -= psi_cost + darkspawn.use_psi(psi_cost) return TRUE return FALSE @@ -184,9 +184,9 @@ //used for darkspawn spells if(psi_cost) - if(owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) + if(isdarkspawn(owner)) var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) - if(darkspawn.psi < psi_cost) + if(darkspawn.has_psi(psi_cost)) if(feedback) owner.balloon_alert(owner, span_warning("Not enough psi!")) return FALSE diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index cbbd18de6eeb..fbe882431651 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -71,6 +71,10 @@ /datum/action/innate/psi_web name = "Psi Web" desc = "Access the Mindlink directly to unlock and upgrade your supernatural powers." + button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' + background_icon_state = "bg_alien" + overlay_icon_state = "bg_alien_border" + buttontooltipstyle = "alien" button_icon_state = "psi_web" check_flags = AB_CHECK_CONSCIOUS var/datum/antag_menu/psi_web/psi_web diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 2400da4c574d..9acb5cdb0627 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -17,8 +17,7 @@ var/psi_cap = 100 //Max Psi by default var/psi_regen = 20 //How much Psi will regenerate after using an ability var/psi_regen_delay = 5 //How many ticks need to pass before Psi regenerates - var/psi_regen_ticks = 0 //When this hits 0, regenerate Psi and return to psi_regen_delay - var/psi_used_since_regen = 0 //How much Psi has been used since we last regenerated + COOLDOWN_DECLARE(psi_cooldown)//When this finishes it's cooldown, regenerate Psi and restart var/psi_regenerating = FALSE //Used to prevent duplicate regen proc calls //Lucidity variables @@ -126,10 +125,8 @@ /datum/antagonist/darkspawn/process() //This is here since it controls most of the Psi stuff psi = min(psi, psi_cap) - if(psi != psi_cap) - psi_regen_ticks-- - if(!psi_regen_ticks) - regenerate_psi() + if(psi != psi_cap && COOLDOWN_FINISHED(src, psi_cooldown)) + regenerate_psi() update_psi_hud() /datum/antagonist/darkspawn/proc/has_psi(amt) @@ -138,8 +135,7 @@ /datum/antagonist/darkspawn/proc/use_psi(amt) if(!has_psi(amt)) return - psi_regen_ticks = psi_regen_delay - psi_used_since_regen += amt + COOLDOWN_START(src, psi_cooldown, psi_regen_delay) psi -= amt psi = round(psi, 0.2) update_psi_hud() @@ -150,16 +146,13 @@ if(psi_regenerating) return psi_regenerating = TRUE - var/total_regen = min(psi_regen, psi_used_since_regen) - for(var/i in 1 to psi_cap) //tick it up very quickly instead of just increasing it by the regen; also include a failsafe to avoid infinite loops - if(!total_regen || psi >= psi_cap) + for(var/i in 1 to psi_regen) //tick it up very quickly instead of just increasing it by the regen; also include a failsafe to avoid infinite loops + if(psi >= psi_cap) break psi = min(psi + 1, psi_cap) - total_regen-- update_psi_hud() sleep(0.05 SECONDS) - psi_used_since_regen = 0 - psi_regen_ticks = psi_regen_delay + COOLDOWN_START(src, psi_cooldown, psi_regen_delay) psi_regenerating = FALSE return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 8d1b5ea09728..aae71bdcf6fc 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -2,6 +2,10 @@ /datum/action/innate/divulge name = "Divulge" desc = "Sheds your human disguise. This is obvious and so should be done in a secluded area. You cannot reverse this." + button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' + background_icon_state = "bg_alien" + overlay_icon_state = "bg_alien_border" + buttontooltipstyle = "alien" button_icon_state = "divulge" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_LYING var/in_use = FALSE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index c1d0e01ea146..8a2d2ad6ab1c 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -2,6 +2,10 @@ /datum/action/innate/sacrament name = "Sacrament" desc = "Ascends into a progenitor. Unless someone else has performed the Sacrament, you must have drained lucidity from 15-30 (check your objective) different people for this to work, and purchased all passive upgrades." + button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' + background_icon_state = "bg_alien" + overlay_icon_state = "bg_alien_border" + buttontooltipstyle = "alien" button_icon_state = "sacrament" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS var/datum/looping_sound/sacrament/soundloop diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index b0069359d5b9..1efbc14a2e3b 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -2,6 +2,10 @@ /datum/action/innate/pass name = "Pass" desc = "Twists an active arm into tendrils with many important uses. Examine the tendrils to see a list of uses." + button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' + background_icon_state = "bg_alien" + overlay_icon_state = "bg_alien_border" + buttontooltipstyle = "alien" button_icon_state = "pass" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS var/twin = FALSE From b40f3367faf92c638f5a0f545d3e80aeef2302d3 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 20:20:47 -0500 Subject: [PATCH 040/756] add ToggledSpells --- code/modules/spells/spell.dm | 17 +++++------ .../spells/spell_types/toggle/_toggle.dm | 29 +++++++++++++++++++ yogstation.dme | 1 + .../code/game/gamemodes/darkspawn/psi_web.dm | 13 +++++---- .../antagonists/darkspawn/darkspawn.dm | 4 +-- .../darkspawn/darkspawn_abilities/_divulge.dm | 7 +++-- .../darkspawn_abilities/_sacrament.dm | 13 +++++---- .../darkspawn_abilities/devour_will.dm | 1 + .../darkspawn/darkspawn_abilities/pass.dm | 11 +++---- 9 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 code/modules/spells/spell_types/toggle/_toggle.dm diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index a985504cf696..de871de562e8 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -133,15 +133,7 @@ if(!can_cast_spell()) return FALSE - . = ..() - - // Add this after the parent call so psi is only consumed when the ability WILL happen - if(psi_cost && .) - if(owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN))//sanity check - var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) - darkspawn.use_psi(psi_cost) - return TRUE - return FALSE + return ..() /datum/action/cooldown/spell/set_click_ability(mob/on_who) if(SEND_SIGNAL(on_who, COMSIG_MOB_SPELL_ACTIVATED, src) & SPELL_CANCEL_CAST) @@ -186,7 +178,7 @@ if(psi_cost) if(isdarkspawn(owner)) var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) - if(darkspawn.has_psi(psi_cost)) + if(!darkspawn.has_psi(psi_cost)) if(feedback) owner.balloon_alert(owner, span_warning("Not enough psi!")) return FALSE @@ -272,6 +264,11 @@ var/precast_result = before_cast(cast_on) if(precast_result & SPELL_CANCEL_CAST) return FALSE + + //sanity check, they shouldn't be able to get here without being darkspawn if it has a psi cost + if(psi_cost && isdarkspawn(owner)) + var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + darkspawn.use_psi(psi_cost) // Spell is officially being cast if(!(precast_result & SPELL_NO_FEEDBACK)) diff --git a/code/modules/spells/spell_types/toggle/_toggle.dm b/code/modules/spells/spell_types/toggle/_toggle.dm new file mode 100644 index 000000000000..a798d9e551d2 --- /dev/null +++ b/code/modules/spells/spell_types/toggle/_toggle.dm @@ -0,0 +1,29 @@ +///basically just a copy of how part of /datum/action/innate works, but as a spell typepath +/datum/action/cooldown/spell/toggle + /// Whether we're active or not + var/active = FALSE + +/datum/action/cooldown/spell/toggle/cast(atom/cast_on) + if(!..()) + return FALSE + + // We're not a click action (we're a toggle or otherwise) + var/active_status = active + if(active_status) + Enable() + else + Disable() + + if(active != active_status) + build_all_button_icons(UPDATE_BUTTON_STATUS) + + return TRUE + +/datum/action/cooldown/spell/toggle/is_action_active(atom/movable/screen/movable/action_button/current_button) + return active + +/datum/action/cooldown/spell/toggle/proc/Enable() + return + +/datum/action/cooldown/spell/toggle/proc/Disable() + return diff --git a/yogstation.dme b/yogstation.dme index 23ec9cc9994f..bfe5d2b95e8a 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3576,6 +3576,7 @@ #include "code\modules\spells\spell_types\teleport\_teleport.dm" #include "code\modules\spells\spell_types\teleport\blink.dm" #include "code\modules\spells\spell_types\teleport\teleport.dm" +#include "code\modules\spells\spell_types\toggle\_toggle.dm" #include "code\modules\spells\spell_types\touch\_touch.dm" #include "code\modules\spells\spell_types\touch\duffelbag_curse.dm" #include "code\modules\spells\spell_types\touch\flesh_to_stone.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index fbe882431651..ada1bb60b143 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -68,9 +68,10 @@ selected.on_purchase(darkspawn?.owner?.current) //ability for using the shadow store -/datum/action/innate/psi_web +/datum/action/cooldown/spell/psi_web name = "Psi Web" desc = "Access the Mindlink directly to unlock and upgrade your supernatural powers." + panel = null button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" @@ -79,18 +80,18 @@ check_flags = AB_CHECK_CONSCIOUS var/datum/antag_menu/psi_web/psi_web -/datum/action/innate/psi_web/New(our_target) +/datum/action/cooldown/spell/psi_web/New(our_target) . = ..() if(istype(our_target, /datum/antag_menu/psi_web)) psi_web = our_target else CRASH("psi_web action created with non web.") -/datum/action/innate/psi_web/Destroy() +/datum/action/cooldown/spell/psi_web/Destroy() psi_web = null return ..() -/datum/action/innate/psi_web/Activate() +/datum/action/cooldown/spell/psi_web/Activate() to_chat(usr, "You retreat inwards and touch the Mindlink...") psi_web.ui_interact(usr) return TRUE @@ -171,7 +172,7 @@ /datum/psi_web/fighter name = "fighter" desc = "me no think so good" - learned_ability = /datum/action/innate/pass + learned_ability = /datum/action/cooldown/spell/toggle/pass /datum/psi_web/fighter/activate(mob/user) darkspawn.specialization = FIGHTER @@ -281,6 +282,6 @@ menu_tab = STORE_PASSIVE /datum/psi_web/twin_tendrils/activate(mob/user) - var/datum/action/innate/pass/spell = locate() in darkspawn.upgrades + var/datum/action/cooldown/spell/toggle/pass/spell = locate() in darkspawn.upgrades if(spell) spell.twin = TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 9acb5cdb0627..6f5a9e3ff290 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -32,7 +32,7 @@ //upgrade variables var/list/upgrades = list() //A list of all the upgrades we currently have (actual objects, not just typepaths) var/datum/antag_menu/psi_web/psi_web //Antag menu used for opening the UI - var/datum/action/innate/psi_web/psi_web_action //Used to link the menu with our antag datum + var/datum/action/cooldown/spell/psi_web/psi_web_action //Used to link the menu with our antag datum var/specialization = NONE // Antagonist datum things like assignment // @@ -42,7 +42,7 @@ owner.special_role = "darkspawn" owner.current.hud_used.psi_counter.invisibility = 0 update_psi_hud() - var/datum/action/innate/divulge/action = new() + var/datum/action/cooldown/spell/divulge/action = new() action.Grant(owner.current) upgrades += action addtimer(CALLBACK(src, PROC_REF(begin_force_divulge)), 23 MINUTES) //this won't trigger if they've divulged when the proc runs diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index aae71bdcf6fc..53584c0e5ad2 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -1,7 +1,8 @@ //A channeled ability that turns the darkspawn into their main form. -/datum/action/innate/divulge +/datum/action/cooldown/spell/divulge name = "Divulge" desc = "Sheds your human disguise. This is obvious and so should be done in a secluded area. You cannot reverse this." + panel = null button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" @@ -10,7 +11,7 @@ check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_LYING var/in_use = FALSE -/datum/action/innate/divulge/IsAvailable(feedback) +/datum/action/cooldown/spell/divulge/IsAvailable(feedback) if(!isdarkspawn(owner)) return FALSE if(in_use) @@ -19,7 +20,7 @@ return . = ..() -/datum/action/innate/divulge/Activate() +/datum/action/cooldown/spell/divulge/Activate() set waitfor = FALSE var/mob/living/carbon/human/user = usr var/turf/spot = get_turf(user) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index 8a2d2ad6ab1c..b0628b180c11 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -1,7 +1,8 @@ //Turns the darkspawn into a progenitor. -/datum/action/innate/sacrament +/datum/action/cooldown/spell/sacrament name = "Sacrament" desc = "Ascends into a progenitor. Unless someone else has performed the Sacrament, you must have drained lucidity from 15-30 (check your objective) different people for this to work, and purchased all passive upgrades." + panel = null button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" @@ -12,20 +13,20 @@ var/datum/antagonist/darkspawn/darkspawn var/in_use -/datum/action/innate/sacrament/New(Target) +/datum/action/cooldown/spell/sacrament/New(Target) . = ..() if(!isdarkspawn(owner)) Remove(owner) darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) -/datum/action/innate/sacrament/IsAvailable(feedback) +/datum/action/cooldown/spell/sacrament/IsAvailable(feedback) if(in_use) if (feedback) owner.balloon_alert(owner, "already in use!") return . = ..() -/datum/action/innate/sacrament/Activate() +/datum/action/cooldown/spell/sacrament/Activate() if(SSticker.mode.sacrament_done) darkspawn.sacrament() return @@ -83,11 +84,11 @@ animate(user, pixel_y = user.pixel_y + 20, time = 4 SECONDS) addtimer(CALLBACK(darkspawn, TYPE_PROC_REF(/datum/antagonist/darkspawn, sacrament)), 4 SECONDS) -/datum/action/innate/sacrament/proc/unleashed_psi(turf/T) +/datum/action/cooldown/spell/sacrament/proc/unleashed_psi(turf/T) playsound(T, 'yogstation/sound/magic/divulge_end.ogg', 25, FALSE) new/obj/effect/temp_visual/revenant/cracks(T) -/datum/action/innate/sacrament/proc/shatter_lights() +/datum/action/cooldown/spell/sacrament/proc/shatter_lights() if(SSticker.mode.sacrament_done) return for(var/obj/machinery/light/light in SSmachines.processing) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm index 7c2ac5db8a45..08775732c4bc 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm @@ -3,6 +3,7 @@ name = "Devour Will" desc = "Creates a dark bead that can be used on a human to fully recharge Psi, gain one lucidity, and knock them unconscious. The victim will be stunned for the duration of the channel, being interrupted \ will knock both you and the victim down. Costs 5 Psi." + panel = null button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index 1efbc14a2e3b..080281e0c958 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -1,7 +1,8 @@ //Equips umbral tendrils with many uses. -/datum/action/innate/pass +/datum/action/cooldown/spell/toggle/pass name = "Pass" desc = "Twists an active arm into tendrils with many important uses. Examine the tendrils to see a list of uses." + panel = null button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" @@ -10,19 +11,19 @@ check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS var/twin = FALSE -/datum/action/innate/pass/IsAvailable(feedback = FALSE) +/datum/action/cooldown/spell/toggle/pass/IsAvailable(feedback = FALSE) if(!isdarkspawn(owner)) return FALSE return ..() -/datum/action/innate/pass/process() +/datum/action/cooldown/spell/toggle/pass/process() ..() active = locate(/obj/item/umbral_tendrils) in owner if(twin) name = "Twinned Pass" desc = "Twists one or both of your arms into tendrils with many uses." -/datum/action/innate/pass/Activate() +/datum/action/cooldown/spell/toggle/pass/Enable() var/mob/living/carbon/C = owner if(!(C.mobility_flags & MOBILITY_STAND)) to_chat(owner, span_warning("Stand up first!")) @@ -44,7 +45,7 @@ owner.put_in_hands(T) return TRUE -/datum/action/innate/pass/Deactivate() +/datum/action/cooldown/spell/toggle/pass/Disable() owner.visible_message(span_warning("[owner]'s tentacles transform back!"), "haoo
\ [span_notice("You dispel the tendrils.")]") playsound(owner, 'yogstation/sound/magic/pass_dispel.ogg', 50, 1) From b0e75a96f11281d753c618220b2196053805bbb4 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 20:23:23 -0500 Subject: [PATCH 041/756] lol wizard robes --- .../antagonists/darkspawn/darkspawn_abilities/_divulge.dm | 1 + .../antagonists/darkspawn/darkspawn_abilities/_sacrament.dm | 1 + .../antagonists/darkspawn/darkspawn_abilities/devour_will.dm | 1 + .../modules/antagonists/darkspawn/darkspawn_abilities/pass.dm | 1 + 4 files changed, 4 insertions(+) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 53584c0e5ad2..49df92c12d0c 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -9,6 +9,7 @@ buttontooltipstyle = "alien" button_icon_state = "divulge" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_LYING + spell_requirements = NONE var/in_use = FALSE /datum/action/cooldown/spell/divulge/IsAvailable(feedback) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index b0628b180c11..272985b11e80 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -9,6 +9,7 @@ buttontooltipstyle = "alien" button_icon_state = "sacrament" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS + spell_requirements = NONE var/datum/looping_sound/sacrament/soundloop var/datum/antagonist/darkspawn/darkspawn var/in_use diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm index 08775732c4bc..15b73052768e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm @@ -10,6 +10,7 @@ buttontooltipstyle = "alien" button_icon_state = "devour_will" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_LYING | AB_CHECK_CONSCIOUS + spell_requirements = NONE psi_cost = 5 var/list/victims = list()//A list of people we've used the bead on recently; we can't drain them again so soon var/last_victim diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index 080281e0c958..36c919278509 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -9,6 +9,7 @@ buttontooltipstyle = "alien" button_icon_state = "pass" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS + spell_requirements = NONE var/twin = FALSE /datum/action/cooldown/spell/toggle/pass/IsAvailable(feedback = FALSE) From 9fc58e0e45e86bc5eeced39509dcd8b96d3f1beb Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 20:33:04 -0500 Subject: [PATCH 042/756] work --- .../spells/spell_types/toggle/_toggle.dm | 11 ++++------- .../code/game/gamemodes/darkspawn/psi_web.dm | 5 +++-- .../darkspawn/darkspawn_abilities/_divulge.dm | 3 ++- .../darkspawn_abilities/_sacrament.dm | 3 ++- .../darkspawn_abilities/devour_will.dm | 18 +++++++++--------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/code/modules/spells/spell_types/toggle/_toggle.dm b/code/modules/spells/spell_types/toggle/_toggle.dm index a798d9e551d2..75b7c34e74e6 100644 --- a/code/modules/spells/spell_types/toggle/_toggle.dm +++ b/code/modules/spells/spell_types/toggle/_toggle.dm @@ -7,15 +7,12 @@ if(!..()) return FALSE - // We're not a click action (we're a toggle or otherwise) - var/active_status = active - if(active_status) - Enable() - else + if(active) Disable() + else + Enable() - if(active != active_status) - build_all_button_icons(UPDATE_BUTTON_STATUS) + build_all_button_icons(UPDATE_BUTTON_STATUS) return TRUE diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index ada1bb60b143..c2cf2c533ecb 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -78,6 +78,7 @@ buttontooltipstyle = "alien" button_icon_state = "psi_web" check_flags = AB_CHECK_CONSCIOUS + spell_requirements = NONE var/datum/antag_menu/psi_web/psi_web /datum/action/cooldown/spell/psi_web/New(our_target) @@ -91,10 +92,10 @@ psi_web = null return ..() -/datum/action/cooldown/spell/psi_web/Activate() +/datum/action/cooldown/spell/psi_web/cast(atom/cast_on) + . = ..() to_chat(usr, "You retreat inwards and touch the Mindlink...") psi_web.ui_interact(usr) - return TRUE //shadow store datums (upgrades and abilities) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 49df92c12d0c..fe727d967424 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -21,7 +21,8 @@ return . = ..() -/datum/action/cooldown/spell/divulge/Activate() +/datum/action/cooldown/spell/divulge/cast(atom/cast_on) + . = ..() set waitfor = FALSE var/mob/living/carbon/human/user = usr var/turf/spot = get_turf(user) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index 272985b11e80..fe1d38d96a02 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -27,7 +27,8 @@ return . = ..() -/datum/action/cooldown/spell/sacrament/Activate() +/datum/action/cooldown/spell/sacrament/cast(atom/cast_on) + . = ..() if(SSticker.mode.sacrament_done) darkspawn.sacrament() return diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm index 15b73052768e..4845e821ddbc 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm @@ -15,15 +15,15 @@ var/list/victims = list()//A list of people we've used the bead on recently; we can't drain them again so soon var/last_victim -/datum/action/cooldown/spell/devour_will/Activate() - if(..()) - owner.visible_message(span_warning("A glowing black orb appears in [owner]'s hand!"), "pwga...iejz
\ - You form a dark bead in your hand.
") - playsound(owner, 'yogstation/sound/magic/devour_will_form.ogg', 50, 1) - var/obj/item/dark_bead/B = new - owner.put_in_hands(B) - B.linked_ability = src - return TRUE +/datum/action/cooldown/spell/devour_will/cast(atom/cast_on) + . = ..() + owner.visible_message(span_warning("A glowing black orb appears in [owner]'s hand!"), "pwga...iejz
\ + You form a dark bead in your hand.
") + playsound(owner, 'yogstation/sound/magic/devour_will_form.ogg', 50, 1) + var/obj/item/dark_bead/B = new + owner.put_in_hands(B) + B.linked_ability = src + return TRUE /datum/action/cooldown/spell/devour_will/proc/make_eligible(mob/living/L) if(!L || !victims[L]) From aa576cd7ae30c470be848820b25bfdac8ef61caa Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 21:09:37 -0500 Subject: [PATCH 043/756] fixing work --- code/__DEFINES/magic.dm | 3 +++ code/modules/spells/spell.dm | 6 +++++ .../spells/spell_types/toggle/_toggle.dm | 7 +---- yogstation.dme | 1 + .../code/game/gamemodes/darkspawn/psi_web.dm | 5 +++- .../antagonists/darkspawn/darkspawn.dm | 6 +++++ .../darkspawn/darkspawn_abilities/_divulge.dm | 6 ++--- .../darkspawn_abilities/_sacrament.dm | 2 +- .../darkspawn_abilities/devour_will.dm | 2 +- .../darkspawn_abilities/light_eater.dm | 27 +++++++++++++++++++ .../darkspawn/darkspawn_abilities/pass.dm | 15 ++--------- .../darkspawn_objects/umbral_tendrils.dm | 9 ++++--- 12 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm diff --git a/code/__DEFINES/magic.dm b/code/__DEFINES/magic.dm index 7eeae378337c..02ed7cf3a5b7 100644 --- a/code/__DEFINES/magic.dm +++ b/code/__DEFINES/magic.dm @@ -60,6 +60,9 @@ #define SPELL_REQUIRES_MIND (1 << 6) /// Whether the spell requires the caster have a mime vow (mindless mobs will succeed this check regardless). #define SPELL_REQUIRES_MIME_VOW (1 << 7) +/// Whether the spell requires the caster be a darkspawn. +#define SPELL_REQUIRES_DARKSPAWN (1 << 8) + /// Whether the spell can be cast, even if the caster is unable to speak the invocation /// (effectively making the invocation flavor, instead of required). #define SPELL_CASTABLE_WITHOUT_INVOCATION (1 << 8) diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index de871de562e8..50c113bceb35 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -174,6 +174,12 @@ to_chat(owner, span_warning("You must dedicate yourself to silence first!")) return FALSE + if((spell_requirements & SPELL_REQUIRES_DARKSPAWN) && !isdarkspawn(owner)) + // In the future this can be moved out of spell checks exactly + if(feedback) + to_chat(owner, span_warning("You must dedicate yourself to silence first!")) + return FALSE + //used for darkspawn spells if(psi_cost) if(isdarkspawn(owner)) diff --git a/code/modules/spells/spell_types/toggle/_toggle.dm b/code/modules/spells/spell_types/toggle/_toggle.dm index 75b7c34e74e6..e7b48a78b658 100644 --- a/code/modules/spells/spell_types/toggle/_toggle.dm +++ b/code/modules/spells/spell_types/toggle/_toggle.dm @@ -4,18 +4,13 @@ var/active = FALSE /datum/action/cooldown/spell/toggle/cast(atom/cast_on) - if(!..()) - return FALSE - if(active) Disable() else Enable() - + active = !active build_all_button_icons(UPDATE_BUTTON_STATUS) - return TRUE - /datum/action/cooldown/spell/toggle/is_action_active(atom/movable/screen/movable/action_button/current_button) return active diff --git a/yogstation.dme b/yogstation.dme index bfe5d2b95e8a..a7cdbbe06805 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3972,6 +3972,7 @@ #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_divulge.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_sacrament.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\devour_will.dm" +#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\light_eater.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\pass.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\dark_bead.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\psionic_barrier.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index c2cf2c533ecb..73442f780ebc 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -78,7 +78,7 @@ buttontooltipstyle = "alien" button_icon_state = "psi_web" check_flags = AB_CHECK_CONSCIOUS - spell_requirements = NONE + spell_requirements = SPELL_REQUIRES_DARKSPAWN var/datum/antag_menu/psi_web/psi_web /datum/action/cooldown/spell/psi_web/New(our_target) @@ -177,6 +177,9 @@ /datum/psi_web/fighter/activate(mob/user) darkspawn.specialization = FIGHTER + var/datum/action/cooldown/spell/toggle/light_eater/spell = locate() in darkspawn.upgrades + if(spell) + spell.Remove(user) /datum/psi_web/warlock name = "warlock" diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 6f5a9e3ff290..919a8965e537 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -205,6 +205,12 @@ psi_web = new(src) psi_web_action = new(psi_web) psi_web_action.Grant(owner.current) + var/datum/action/cooldown/spell/devour_will/devour = new(src) + upgrades |= devour + devour.Grant(owner.current) + var/datum/action/cooldown/spell/toggle/light_eater/eater = new(src) + upgrades |= eater + eater.Grant(owner.current) darkspawn_state = DIVULGED return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index fe727d967424..f053528d3599 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -9,12 +9,10 @@ buttontooltipstyle = "alien" button_icon_state = "divulge" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_LYING - spell_requirements = NONE + spell_requirements = SPELL_REQUIRES_DARKSPAWN var/in_use = FALSE /datum/action/cooldown/spell/divulge/IsAvailable(feedback) - if(!isdarkspawn(owner)) - return FALSE if(in_use) if (feedback) owner.balloon_alert(owner, "already in use!") @@ -22,8 +20,8 @@ . = ..() /datum/action/cooldown/spell/divulge/cast(atom/cast_on) - . = ..() set waitfor = FALSE + . = ..() var/mob/living/carbon/human/user = usr var/turf/spot = get_turf(user) if(!ishuman(user)) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index fe1d38d96a02..64fd2100b59e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -9,7 +9,7 @@ buttontooltipstyle = "alien" button_icon_state = "sacrament" check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS - spell_requirements = NONE + spell_requirements = SPELL_REQUIRES_DARKSPAWN var/datum/looping_sound/sacrament/soundloop var/datum/antagonist/darkspawn/darkspawn var/in_use diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm index 4845e821ddbc..c6cd36f6175e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm @@ -10,7 +10,7 @@ buttontooltipstyle = "alien" button_icon_state = "devour_will" check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_LYING | AB_CHECK_CONSCIOUS - spell_requirements = NONE + spell_requirements = SPELL_REQUIRES_DARKSPAWN psi_cost = 5 var/list/victims = list()//A list of people we've used the bead on recently; we can't drain them again so soon var/last_victim diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm new file mode 100644 index 000000000000..6477b0013f77 --- /dev/null +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm @@ -0,0 +1,27 @@ +/datum/action/cooldown/spell/toggle/light_eater + name = "Light Eater" + desc = "Twists an active arm blade of all-consuming shadow." + panel = null + button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' + background_icon_state = "bg_alien" + overlay_icon_state = "bg_alien_border" + buttontooltipstyle = "alien" + button_icon_state = "pass" + check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS | AB_CHECK_LYING + spell_requirements = SPELL_REQUIRES_DARKSPAWN + +/datum/action/cooldown/spell/toggle/light_eater/Enable() + var/list/hands_free = owner.get_empty_held_indexes() + if(hands_free.len) + owner.visible_message(span_warning("[owner]'s arm contorts into tentacles!"), "ikna
\ + [span_notice("You transform your arm into umbral tendrils. Examine them to see possible uses.")]") + playsound(owner, 'yogstation/sound/magic/pass_create.ogg', 50, 1) + var/obj/item/light_eater/T = new(owner, owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) + owner.put_in_hands(T) + +/datum/action/cooldown/spell/toggle/light_eater/Disable() + owner.visible_message(span_warning("[owner]'s tentacles transform back!"), "haoo
\ + [span_notice("You dispel the tendrils.")]") + playsound(owner, 'yogstation/sound/magic/pass_dispel.ogg', 50, 1) + for(var/obj/item/light_eater/T in owner) + qdel(T) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index 36c919278509..b34858661986 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -8,15 +8,10 @@ overlay_icon_state = "bg_alien_border" buttontooltipstyle = "alien" button_icon_state = "pass" - check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS - spell_requirements = NONE + check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS | AB_CHECK_LYING + spell_requirements = SPELL_REQUIRES_DARKSPAWN var/twin = FALSE -/datum/action/cooldown/spell/toggle/pass/IsAvailable(feedback = FALSE) - if(!isdarkspawn(owner)) - return FALSE - return ..() - /datum/action/cooldown/spell/toggle/pass/process() ..() active = locate(/obj/item/umbral_tendrils) in owner @@ -25,10 +20,6 @@ desc = "Twists one or both of your arms into tendrils with many uses." /datum/action/cooldown/spell/toggle/pass/Enable() - var/mob/living/carbon/C = owner - if(!(C.mobility_flags & MOBILITY_STAND)) - to_chat(owner, span_warning("Stand up first!")) - return var/list/hands_free = owner.get_empty_held_indexes() if(!twin || hands_free.len < 2) owner.visible_message(span_warning("[owner]'s arm contorts into tentacles!"), "ikna
\ @@ -44,7 +35,6 @@ for(var/i in 1 to 2) var/obj/item/umbral_tendrils/T = new(owner, owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) owner.put_in_hands(T) - return TRUE /datum/action/cooldown/spell/toggle/pass/Disable() owner.visible_message(span_warning("[owner]'s tentacles transform back!"), "haoo
\ @@ -52,4 +42,3 @@ playsound(owner, 'yogstation/sound/magic/pass_dispel.ogg', 50, 1) for(var/obj/item/umbral_tendrils/T in owner) qdel(T) - return TRUE diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm index 9fed8ad7406a..ac9fac8b7b7a 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm @@ -50,13 +50,14 @@ twin.attack(target, user, FALSE) /obj/item/umbral_tendrils/afterattack(atom/target, mob/living/user, proximity) + . = ..() if(!darkspawn) return if(twin && proximity && !QDELETED(target) && (isstructure(target) || ismachinery(target)) && user.get_active_held_item() == src) target.attackby(twin, user) switch(user.a_intent) //Note that airlock interactions can be found in airlock.dm. if(INTENT_HELP) - if(isopenturf(target)) + if(!target.density && isopenturf(get_turf(target))) tendril_jump(user, target) if(INTENT_GRAB) tendril_swing(user, target) @@ -114,7 +115,7 @@ . = TRUE if(isliving(target)) var/mob/living/L = target - if(!iscyborg(target)) + if(iscarbon(target)) playsound(target, 'yogstation/sound/magic/pass_attack.ogg', 50, TRUE) if(!twinned) target.visible_message(span_warning("[firer]'s [name] slam into [target], knocking them off their feet!"), \ @@ -127,7 +128,7 @@ span_userdanger("You're suddenly dragged across the floor!")) L.Knockdown(8 SECONDS) //these can't hit people who are already on the ground but they can be spammed to all shit addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(playsound), target, 'yogstation/sound/magic/pass_attack.ogg', 50, TRUE), 1) - else + else if(issilicon(target)) var/mob/living/silicon/robot/R = target R.toggle_headlamp(TRUE) //disable headlamps target.visible_message(span_warning("[firer]'s [name] smashes into [target]'s chassis!"), \ @@ -136,4 +137,6 @@ playsound(R, 'sound/effects/bang.ogg', 50, TRUE) R.Paralyze(40) //this is the only real anti-borg spell get R.adjustBruteLoss(10) + else + return BULLET_ACT_FORCE_PIERCE //ignore things that don't matter From d65a32f0c5cebdcaf905501c372683b2cbdb0992 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 21:10:57 -0500 Subject: [PATCH 044/756] Update pass.dm --- .../modules/antagonists/darkspawn/darkspawn_abilities/pass.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index b34858661986..bfb70a1b5be8 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -13,7 +13,7 @@ var/twin = FALSE /datum/action/cooldown/spell/toggle/pass/process() - ..() + . = ..() active = locate(/obj/item/umbral_tendrils) in owner if(twin) name = "Twinned Pass" From e4e94e740eb0e6656185c03ace8aaaffc7000b59 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 21:37:48 -0500 Subject: [PATCH 045/756] more button stuff --- .../spells/spell_types/toggle/_toggle.dm | 18 ++++++++++++++---- .../darkspawn_abilities/light_eater.dm | 4 ++++ .../darkspawn/darkspawn_abilities/pass.dm | 4 ++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/code/modules/spells/spell_types/toggle/_toggle.dm b/code/modules/spells/spell_types/toggle/_toggle.dm index e7b48a78b658..b0bdead4b0b2 100644 --- a/code/modules/spells/spell_types/toggle/_toggle.dm +++ b/code/modules/spells/spell_types/toggle/_toggle.dm @@ -3,13 +3,23 @@ /// Whether we're active or not var/active = FALSE +/datum/action/cooldown/spell/toggle/New() + ..() + START_PROCESSING(SSfastprocess, src) + +/datum/action/cooldown/spell/toggle/Destroy() + STOP_PROCESSING(SSfastprocess, src) + return ..() + +/datum/action/cooldown/spell/toggle/process() + build_all_button_icons(ALL) //so as to be consistent with situational requirements, keep the button updated + /datum/action/cooldown/spell/toggle/cast(atom/cast_on) + active = !active if(active) - Disable() - else Enable() - active = !active - build_all_button_icons(UPDATE_BUTTON_STATUS) + else + Disable() /datum/action/cooldown/spell/toggle/is_action_active(atom/movable/screen/movable/action_button/current_button) return active diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm index 6477b0013f77..cce3bd1ce6f7 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm @@ -10,6 +10,10 @@ check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS | AB_CHECK_LYING spell_requirements = SPELL_REQUIRES_DARKSPAWN +/datum/action/cooldown/spell/toggle/pass/process() + active = owner.is_holding_item_of_type(/obj/item/light_eater) + . = ..() + /datum/action/cooldown/spell/toggle/light_eater/Enable() var/list/hands_free = owner.get_empty_held_indexes() if(hands_free.len) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index bfb70a1b5be8..da3075e1dc08 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -13,11 +13,11 @@ var/twin = FALSE /datum/action/cooldown/spell/toggle/pass/process() - . = ..() - active = locate(/obj/item/umbral_tendrils) in owner + active = owner.is_holding_item_of_type(/obj/item/umbral_tendrils) if(twin) name = "Twinned Pass" desc = "Twists one or both of your arms into tendrils with many uses." + . = ..() /datum/action/cooldown/spell/toggle/pass/Enable() var/list/hands_free = owner.get_empty_held_indexes() From 6b798ecd3d7c41f0efae9df9e08d9f167a4c8857 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 11 Oct 2023 23:52:38 -0500 Subject: [PATCH 046/756] oh no, team --- yogstation.dme | 1 + .../code/modules/antagonists/darkspawn/darkspawn.dm | 3 +++ .../darkspawn/darkspawn_abilities/_sacrament.dm | 12 ++++++------ .../darkspawn/darkspawn_objects/dark_bead.dm | 1 + .../modules/antagonists/darkspawn/darkspawn_team.dm | 0 5 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_team.dm diff --git a/yogstation.dme b/yogstation.dme index a7cdbbe06805..5fa83510be17 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3969,6 +3969,7 @@ #include "yogstation\code\modules\antagonists\blob\blob\blobs\core.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_progenitor.dm" +#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_team.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_divulge.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_sacrament.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\devour_will.dm" diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 919a8965e537..3c679fe60185 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -202,6 +202,9 @@ user.set_species(/datum/species/shadow/darkspawn) ADD_TRAIT(user, TRAIT_SPECIESLOCK, "darkspawn divulge") //prevent them from swapping species which can fuck stuff up show_to_ghosts = TRUE + var/datum/action/cooldown/spell/sacrament/final = new(src) + final.Grant(owner.current) + final.darkspawn = src psi_web = new(src) psi_web_action = new(psi_web) psi_web_action.Grant(owner.current) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index 64fd2100b59e..17349ca1d02e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -14,17 +14,17 @@ var/datum/antagonist/darkspawn/darkspawn var/in_use -/datum/action/cooldown/spell/sacrament/New(Target) - . = ..() - if(!isdarkspawn(owner)) - Remove(owner) - darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) - /datum/action/cooldown/spell/sacrament/IsAvailable(feedback) if(in_use) if (feedback) owner.balloon_alert(owner, "already in use!") return + if(!darkspawn) + return + if(darkspawn.lucidity_drained < darkspawn.lucidity_needed) + if (feedback) + owner.balloon_alert(owner, "not enough lucidity drained!") + return . = ..() /datum/action/cooldown/spell/sacrament/cast(atom/cast_on) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm index ad03f55e43e8..8f894b802bbd 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm @@ -95,6 +95,7 @@ to_chat(user, " You have already drained this individual previously, and their lucidity will not contribute any more to the sacrament!") else to_chat(user, " This individual's lucidity brings you one step closer to the sacrament...") + darkspawn.lucidity++ darkspawn.lucidity_drained++ darkspawn.update_psi_hud() diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_team.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_team.dm new file mode 100644 index 000000000000..e69de29bb2d1 From b9f729e3d63e6bc343e9ac6cfa2244953d6a75c5 Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 12 Oct 2023 00:10:53 -0500 Subject: [PATCH 047/756] Revert "oh no, team" This reverts commit 259b6472f8ba597dd32ec8229c2fe0c65348e1fd. --- yogstation.dme | 1 - .../code/modules/antagonists/darkspawn/darkspawn.dm | 3 --- .../darkspawn/darkspawn_abilities/_sacrament.dm | 12 ++++++------ .../darkspawn/darkspawn_objects/dark_bead.dm | 1 - .../modules/antagonists/darkspawn/darkspawn_team.dm | 0 5 files changed, 6 insertions(+), 11 deletions(-) delete mode 100644 yogstation/code/modules/antagonists/darkspawn/darkspawn_team.dm diff --git a/yogstation.dme b/yogstation.dme index 5fa83510be17..a7cdbbe06805 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3969,7 +3969,6 @@ #include "yogstation\code\modules\antagonists\blob\blob\blobs\core.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_progenitor.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_team.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_divulge.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_sacrament.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\devour_will.dm" diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 3c679fe60185..919a8965e537 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -202,9 +202,6 @@ user.set_species(/datum/species/shadow/darkspawn) ADD_TRAIT(user, TRAIT_SPECIESLOCK, "darkspawn divulge") //prevent them from swapping species which can fuck stuff up show_to_ghosts = TRUE - var/datum/action/cooldown/spell/sacrament/final = new(src) - final.Grant(owner.current) - final.darkspawn = src psi_web = new(src) psi_web_action = new(psi_web) psi_web_action.Grant(owner.current) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index 17349ca1d02e..64fd2100b59e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -14,17 +14,17 @@ var/datum/antagonist/darkspawn/darkspawn var/in_use +/datum/action/cooldown/spell/sacrament/New(Target) + . = ..() + if(!isdarkspawn(owner)) + Remove(owner) + darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + /datum/action/cooldown/spell/sacrament/IsAvailable(feedback) if(in_use) if (feedback) owner.balloon_alert(owner, "already in use!") return - if(!darkspawn) - return - if(darkspawn.lucidity_drained < darkspawn.lucidity_needed) - if (feedback) - owner.balloon_alert(owner, "not enough lucidity drained!") - return . = ..() /datum/action/cooldown/spell/sacrament/cast(atom/cast_on) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm index 8f894b802bbd..ad03f55e43e8 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm @@ -95,7 +95,6 @@ to_chat(user, " You have already drained this individual previously, and their lucidity will not contribute any more to the sacrament!") else to_chat(user, " This individual's lucidity brings you one step closer to the sacrament...") - darkspawn.lucidity++ darkspawn.lucidity_drained++ darkspawn.update_psi_hud() diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_team.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_team.dm deleted file mode 100644 index e69de29bb2d1..000000000000 From c142c67908210a604c89da7a3f7a1de94c164119 Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 12 Oct 2023 00:19:21 -0500 Subject: [PATCH 048/756] easier --- yogstation/code/game/gamemodes/darkspawn/darkspawn.dm | 7 ++----- yogstation/code/game/gamemodes/darkspawn/psi_web.dm | 2 +- yogstation/code/modules/antagonists/darkspawn/darkspawn.dm | 1 - .../antagonists/darkspawn/darkspawn_objects/dark_bead.dm | 6 ++++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/darkspawn.dm b/yogstation/code/game/gamemodes/darkspawn/darkspawn.dm index 7877abae56fc..24faa5b660d7 100644 --- a/yogstation/code/game/gamemodes/darkspawn/darkspawn.dm +++ b/yogstation/code/game/gamemodes/darkspawn/darkspawn.dm @@ -1,8 +1,7 @@ -/datum/game_mode +/datum/game_mode //this is a mess, to-do, rework darkspawns to use teams var/list/datum/mind/darkspawn = list() var/list/datum/mind/veils = list() var/required_succs = 20 //How many succs are needed (this is changed in pre_setup, so it scales based on pop) - var/succ_ratio = 1 var/sacrament_done = FALSE //If at least one darkspawn has finished the Sacrament /datum/game_mode/darkspawn @@ -34,9 +33,7 @@ darkboi.special_role = "Darkspawn" darkboi.restricted_roles = restricted_jobs darkbois-- - var/succ_scaling = round(num_players() / 3) - required_succs = clamp(succ_scaling, 15, 30) - succ_ratio = required_succs / 15 + required_succs = clamp(round(num_players() / 3), 15, 30) return TRUE /datum/game_mode/darkspawn/generate_report() diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 73442f780ebc..aac0d70fc7f3 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -21,7 +21,7 @@ if(!istype(darkspawn)) CRASH("darkspawn menu started with wrong datum.") - data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / [darkspawn.lucidity_needed] unique drained total" + data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / [SSticker.mode.required_succs] unique drained total" data["specialization"] = darkspawn.specialization //whether or not they've picked their specialization diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index 919a8965e537..a81f7b38dc57 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -23,7 +23,6 @@ //Lucidity variables var/lucidity = 3 //Lucidity is used to buy abilities and is gained by using Devour Will var/lucidity_drained = 0 //How much lucidity has been drained from unique players - var/lucidity_needed = 20 //how much lucidity is needed to win //Default light damage variables (modified by some abilities) var/dark_healing = 5 diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm index ad03f55e43e8..2c8e29c196d6 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/dark_bead.dm @@ -95,8 +95,10 @@ to_chat(user, " You have already drained this individual previously, and their lucidity will not contribute any more to the sacrament!") else to_chat(user, " This individual's lucidity brings you one step closer to the sacrament...") - darkspawn.lucidity++ - darkspawn.lucidity_drained++ + for(var/datum/mind/dark_mind in get_antag_minds(/datum/antagonist/darkspawn)) + var/datum/antagonist/darkspawn/teammate = dark_mind.has_antag_datum(/datum/antagonist/darkspawn) + teammate.lucidity++ + teammate.lucidity_drained++ darkspawn.update_psi_hud() linked_ability.victims[L] = TRUE linked_ability.last_victim = L.ckey From b75c24f880f674d57d4018321ff3cfb64f8a2cb8 Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 12 Oct 2023 15:02:43 -0500 Subject: [PATCH 049/756] Update PsiWeb.tsx --- tgui/packages/tgui/interfaces/PsiWeb.tsx | 56 +----------------------- 1 file changed, 1 insertion(+), 55 deletions(-) diff --git a/tgui/packages/tgui/interfaces/PsiWeb.tsx b/tgui/packages/tgui/interfaces/PsiWeb.tsx index 562f3d73f83b..0b9c325fe9d6 100644 --- a/tgui/packages/tgui/interfaces/PsiWeb.tsx +++ b/tgui/packages/tgui/interfaces/PsiWeb.tsx @@ -2,58 +2,4 @@ import { useBackend } from '../backend'; import { Button, LabeledList, Section, Box } from '../components'; import { Window } from '../layouts'; -export const PsiWeb = (props, context) => { - const { act, data } = useBackend(context); - return ( - - -
- - - {data.lucidity} - - -
-
- - {data.abilities.map(ability => ( - - - {ability.desc} - Psi use cost: {ability.psi_cost} - Cost to unlock: {ability.lucidity_cost} -
-
- - {data.upgrades.map(upgrade => ( - - - {upgrade.desc} - Cost to unlock: {upgrade.lucidity_cost} -
-
-
- ); -}; +// chubby please do your thing From cd2e4a00482a8a0df675997151c5050b4bb9f346 Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 12 Oct 2023 15:27:25 -0500 Subject: [PATCH 050/756] work on lint --- code/modules/mob/living/carbon/human/species_types/ethereal.dm | 2 +- code/modules/spells/spell_types/toggle/_toggle.dm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm index b81db0a944e4..1e0215806dcd 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -115,7 +115,7 @@ /// Special handling for getting hit with a light eater /datum/species/ethereal/proc/on_light_eater(mob/living/carbon/human/source, datum/light_eater) SIGNAL_HANDLER - source.emp_act(EMP_LIGHT) + spec_emp_act(source, EMP_LIGHT) return COMPONENT_BLOCK_LIGHT_EATER /datum/species/ethereal/spec_emp_act(mob/living/carbon/human/H, severity) diff --git a/code/modules/spells/spell_types/toggle/_toggle.dm b/code/modules/spells/spell_types/toggle/_toggle.dm index b0bdead4b0b2..6fa127377805 100644 --- a/code/modules/spells/spell_types/toggle/_toggle.dm +++ b/code/modules/spells/spell_types/toggle/_toggle.dm @@ -15,6 +15,7 @@ build_all_button_icons(ALL) //so as to be consistent with situational requirements, keep the button updated /datum/action/cooldown/spell/toggle/cast(atom/cast_on) + . = ..() active = !active if(active) Enable() From ec89b6be802b5d307b7d75e940580c796162ed72 Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 12 Oct 2023 15:42:03 -0500 Subject: [PATCH 051/756] checks --- .../darkspawn/darkspawn_abilities/devour_will.dm | 7 +++++++ .../darkspawn/darkspawn_abilities/light_eater.dm | 9 ++++++++- .../antagonists/darkspawn/darkspawn_abilities/pass.dm | 7 +++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm index c6cd36f6175e..f8284bd3bf20 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/devour_will.dm @@ -15,6 +15,13 @@ var/list/victims = list()//A list of people we've used the bead on recently; we can't drain them again so soon var/last_victim +/datum/action/cooldown/spell/devour_will/can_cast_spell(feedback) + if(!owner.get_empty_held_indexes()) + if(feedback) + to_chat(owner, span_warning("You need an empty hand for this!")) + return FALSE + . = ..() + /datum/action/cooldown/spell/devour_will/cast(atom/cast_on) . = ..() owner.visible_message(span_warning("A glowing black orb appears in [owner]'s hand!"), "pwga...iejz
\ diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm index cce3bd1ce6f7..95f2b731d2ec 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm @@ -10,10 +10,17 @@ check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_CONSCIOUS | AB_CHECK_LYING spell_requirements = SPELL_REQUIRES_DARKSPAWN -/datum/action/cooldown/spell/toggle/pass/process() +/datum/action/cooldown/spell/toggle/light_eater/process() active = owner.is_holding_item_of_type(/obj/item/light_eater) . = ..() +/datum/action/cooldown/spell/toggle/light_eater/can_cast_spell(feedback) + if(!owner.get_empty_held_indexes()) + if(feedback) + to_chat(owner, span_warning("You need an empty hand for this!")) + return FALSE + . = ..() + /datum/action/cooldown/spell/toggle/light_eater/Enable() var/list/hands_free = owner.get_empty_held_indexes() if(hands_free.len) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index da3075e1dc08..1d21fe2537ab 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -12,6 +12,13 @@ spell_requirements = SPELL_REQUIRES_DARKSPAWN var/twin = FALSE +/datum/action/cooldown/spell/toggle/pass/can_cast_spell(feedback) + if(!owner.get_empty_held_indexes()) + if(feedback) + to_chat(owner, span_warning("You need an empty hand for this!")) + return FALSE + . = ..() + /datum/action/cooldown/spell/toggle/pass/process() active = owner.is_holding_item_of_type(/obj/item/umbral_tendrils) if(twin) From 055d2e154749474d515199173d2fa64cdd12d1f1 Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 12 Oct 2023 15:45:58 -0500 Subject: [PATCH 052/756] more checks --- code/datums/traits/negative.dm | 2 +- code/modules/spells/spell.dm | 4 ++-- .../darkspawn/darkspawn_abilities/_divulge.dm | 2 +- .../darkspawn/darkspawn_abilities/_sacrament.dm | 2 +- .../darkspawn/darkspawn_abilities/light_eater.dm | 12 ++++++------ 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index f94c6e21d548..a03f9af747c2 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -192,7 +192,7 @@ /datum/quirk/nyctophobia/on_process() var/mob/living/carbon/human/H = quirk_holder - if((H.dna.species.id in list("shadow", "nightmare", "darkspawn")) || (H.mind && (H.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) || H.mind.has_antag_datum(ANTAG_DATUM_VEIL)))) //yogs - thrall & sling check + if((H.dna.species.id in list("shadow", "nightmare", "darkspawn")) || is_darkspawn_or_veil(H)) return //we're tied with the dark, so we don't get scared of it; don't cleanse outright to avoid cheese var/turf/T = get_turf(quirk_holder) var/lums = T.get_lumcount() diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 50c113bceb35..e649e37b9b90 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -183,7 +183,7 @@ //used for darkspawn spells if(psi_cost) if(isdarkspawn(owner)) - var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + var/datum/antagonist/darkspawn/darkspawn = isdarkspawn(owner) if(!darkspawn.has_psi(psi_cost)) if(feedback) owner.balloon_alert(owner, span_warning("Not enough psi!")) @@ -273,7 +273,7 @@ //sanity check, they shouldn't be able to get here without being darkspawn if it has a psi cost if(psi_cost && isdarkspawn(owner)) - var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + var/datum/antagonist/darkspawn/darkspawn = isdarkspawn(owner) darkspawn.use_psi(psi_cost) // Spell is officially being cast diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index f053528d3599..7c70e5118a4c 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -107,6 +107,6 @@ var/mob/M = T to_chat(M, "(F) [processed_message]") if(isdarkspawn(owner))//sanity check - var/datum/antagonist/darkspawn/darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + var/datum/antagonist/darkspawn/darkspawn = isdarkspawn(owner) if(darkspawn.divulge()) Remove(user)//they don't need it anymore diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm index 64fd2100b59e..3ba2a11b5f5e 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_sacrament.dm @@ -18,7 +18,7 @@ . = ..() if(!isdarkspawn(owner)) Remove(owner) - darkspawn = owner.mind.has_antag_datum(ANTAG_DATUM_DARKSPAWN) + darkspawn = isdarkspawn(owner) /datum/action/cooldown/spell/sacrament/IsAvailable(feedback) if(in_use) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm index 95f2b731d2ec..bbb17e22b3bf 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/light_eater.dm @@ -1,6 +1,6 @@ /datum/action/cooldown/spell/toggle/light_eater name = "Light Eater" - desc = "Twists an active arm blade of all-consuming shadow." + desc = "Twists an active arm into a blade of all-consuming shadow." panel = null button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' background_icon_state = "bg_alien" @@ -24,15 +24,15 @@ /datum/action/cooldown/spell/toggle/light_eater/Enable() var/list/hands_free = owner.get_empty_held_indexes() if(hands_free.len) - owner.visible_message(span_warning("[owner]'s arm contorts into tentacles!"), "ikna
\ - [span_notice("You transform your arm into umbral tendrils. Examine them to see possible uses.")]") + owner.visible_message(span_warning("[owner]'s arm contorts into a blade!"), "ikna
\ + [span_notice("You transform your arm into a blade.")]") playsound(owner, 'yogstation/sound/magic/pass_create.ogg', 50, 1) - var/obj/item/light_eater/T = new(owner, owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) + var/obj/item/light_eater/T = new(owner) owner.put_in_hands(T) /datum/action/cooldown/spell/toggle/light_eater/Disable() - owner.visible_message(span_warning("[owner]'s tentacles transform back!"), "haoo
\ - [span_notice("You dispel the tendrils.")]") + owner.visible_message(span_warning("[owner]'s blade transform back!"), "haoo
\ + [span_notice("You dispel the blade.")]") playsound(owner, 'yogstation/sound/magic/pass_dispel.ogg', 50, 1) for(var/obj/item/light_eater/T in owner) qdel(T) From cabbe726b8c36caae21c46e47fa7ffd79c432b19 Mon Sep 17 00:00:00 2001 From: Molti Date: Thu, 12 Oct 2023 16:29:33 -0500 Subject: [PATCH 053/756] Update pass.dm --- .../antagonists/darkspawn/darkspawn_abilities/pass.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm index 1d21fe2537ab..e40ee750466f 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/pass.dm @@ -1,7 +1,7 @@ //Equips umbral tendrils with many uses. /datum/action/cooldown/spell/toggle/pass name = "Pass" - desc = "Twists an active arm into tendrils with many important uses. Examine the tendrils to see a list of uses." + desc = "Twists an active arm into a mass of tendrils with many important uses. Examine the tendrils to see a list of uses." panel = null button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' background_icon_state = "bg_alien" @@ -32,7 +32,7 @@ owner.visible_message(span_warning("[owner]'s arm contorts into tentacles!"), "ikna
\ [span_notice("You transform your arm into umbral tendrils. Examine them to see possible uses.")]") playsound(owner, 'yogstation/sound/magic/pass_create.ogg', 50, 1) - var/obj/item/umbral_tendrils/T = new(owner, owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) + var/obj/item/umbral_tendrils/T = new(owner, isdarkspawn(owner)) owner.put_in_hands(T) else owner.visible_message(span_warning("[owner]'s arms contort into tentacles!"), "ikna ikna
\ @@ -40,7 +40,7 @@ playsound(owner, 'yogstation/sound/magic/pass_create.ogg', 50, TRUE) addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(playsound), owner, 'yogstation/sound/magic/pass_create.ogg', 50, TRUE), 1) for(var/i in 1 to 2) - var/obj/item/umbral_tendrils/T = new(owner, owner.mind?.has_antag_datum(ANTAG_DATUM_DARKSPAWN)) + var/obj/item/umbral_tendrils/T = new(owner, isdarkspawn(owner) ) owner.put_in_hands(T) /datum/action/cooldown/spell/toggle/pass/Disable() From bb02d7c40f50ee18616d7597e9c6bd0533738274 Mon Sep 17 00:00:00 2001 From: Molti Date: Fri, 13 Oct 2023 14:26:53 -0500 Subject: [PATCH 054/756] move --- .../mob/living/carbon/human/species_types/shadowpeople.dm | 1 + yogstation.dme | 2 +- .../antagonists/darkspawn/darkspawn_abilities}/shadow_step.dm | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename yogstation/code/{game/gamemodes/darkspawn => modules/antagonists/darkspawn/darkspawn_abilities}/shadow_step.dm (100%) diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 61159746f131..62ed394a43de 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -168,6 +168,7 @@ shadow_charges = 3 dark_healing = 5 light_burning = 7 + //owner.current.remove_language(/datum/language/darkspawn) /datum/species/shadow/darkspawn/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) if(prob(50) && shadow_charges > 0) diff --git a/yogstation.dme b/yogstation.dme index a7cdbbe06805..6a7b40ab8f03 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3827,7 +3827,6 @@ #include "yogstation\code\game\gamemodes\darkspawn\darkspawn.dm" #include "yogstation\code\game\gamemodes\darkspawn\darkspawn_hud.dm" #include "yogstation\code\game\gamemodes\darkspawn\psi_web.dm" -#include "yogstation\code\game\gamemodes\darkspawn\shadow_step.dm" #include "yogstation\code\game\gamemodes\darkspawn\veil.dm" #include "yogstation\code\game\gamemodes\gangs\dominator.dm" #include "yogstation\code\game\gamemodes\gangs\gang_items.dm" @@ -3974,6 +3973,7 @@ #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\devour_will.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\light_eater.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\pass.dm" +#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\shadow_step.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\dark_bead.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\psionic_barrier.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_objects\simulacrum.dm" diff --git a/yogstation/code/game/gamemodes/darkspawn/shadow_step.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/shadow_step.dm similarity index 100% rename from yogstation/code/game/gamemodes/darkspawn/shadow_step.dm rename to yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/shadow_step.dm From 71e19b360cc497a65c743041248a43b5d0aa5364 Mon Sep 17 00:00:00 2001 From: Molti Date: Fri, 13 Oct 2023 14:31:10 -0500 Subject: [PATCH 055/756] achievement --- code/datums/achievements/achievements.dm | 6 +++--- .../code/modules/antagonists/darkspawn/darkspawn.dm | 12 ++++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/code/datums/achievements/achievements.dm b/code/datums/achievements/achievements.dm index 55fe019e0cea..717fe8869d04 100644 --- a/code/datums/achievements/achievements.dm +++ b/code/datums/achievements/achievements.dm @@ -92,9 +92,9 @@ desc = "As a changeling, complete your objectives" id = 13 -/datum/achievement/greentext/slingascend - name = "The Dark Shadow (retired)" - desc = "As a shadowling, ascend successfully" +/datum/achievement/greentext/darkspawn + name = "The Dark Shadow" + desc = "As a darkspawn, ascend successfully" id = 14 /datum/achievement/death diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index a81f7b38dc57..cd220a33c45b 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -120,8 +120,9 @@ return TRUE return (SSticker.mode.sacrament_done) -// Darkspawn-related things like Psi // - +//////////////////////////////////////////////////////////////////////////////////// +//------------------------------Psi regen and usage-------------------------------// +//////////////////////////////////////////////////////////////////////////////////// /datum/antagonist/darkspawn/process() //This is here since it controls most of the Psi stuff psi = min(psi, psi_cap) if(psi != psi_cap && COOLDOWN_FINISHED(src, psi_cooldown)) @@ -161,6 +162,9 @@ var/atom/movable/screen/counter = owner.current.hud_used.psi_counter counter.maptext = ANTAG_MAPTEXT(psi, COLOR_DARKSPAWN_PSI) +//////////////////////////////////////////////////////////////////////////////////// +//-------------------------------------Divulge------------------------------------// +//////////////////////////////////////////////////////////////////////////////////// /datum/antagonist/darkspawn/proc/begin_force_divulge() if(darkspawn_state != MUNDANE) return @@ -213,6 +217,9 @@ darkspawn_state = DIVULGED return TRUE +//////////////////////////////////////////////////////////////////////////////////// +//-----------------------------------Sacrament------------------------------------// +//////////////////////////////////////////////////////////////////////////////////// /datum/antagonist/darkspawn/proc/sacrament() var/mob/living/carbon/human/user = owner.current if(!SSticker.mode.sacrament_done) @@ -220,6 +227,7 @@ addtimer(CALLBACK(src, PROC_REF(sacrament_shuttle_call)), 50) // Spawn the cosmic progenitor var/mob/living/simple_animal/hostile/darkspawn_progenitor/progenitor = new(get_turf(user)) + SSachievements.unlock_achievement(/datum/achievement/greentext/darkspawn, user.client) user.status_flags |= GODMODE user.mind.transfer_to(progenitor) var/datum/action/cooldown/spell/list_target/progenitor_curse/curse = new(progenitor) From 59e385a68846a25a7c00700d15daa97c62360c77 Mon Sep 17 00:00:00 2001 From: Molti Date: Fri, 13 Oct 2023 14:37:45 -0500 Subject: [PATCH 056/756] forgor --- code/modules/language/language_holder.dm | 6 ++++++ .../mob/living/carbon/human/species_types/shadowpeople.dm | 6 +++--- yogstation/code/modules/antagonists/darkspawn/darkspawn.dm | 2 -- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index ecc628ceee93..f624ff78481e 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -372,6 +372,12 @@ Key procs spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), /datum/language/felinid = list(LANGUAGE_ATOM)) +/datum/language_holder/darkspawn + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/darkspawn = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/darkspawn = list(LANGUAGE_ATOM)) + /datum/language_holder/spiderbot understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), /datum/language/felinid = list(LANGUAGE_ATOM), ///Spiderbots, I am sorry for making you understand this shit diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 62ed394a43de..9ef7a6291383 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -15,11 +15,11 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC mutanteyes = /obj/item/organ/eyes/night_vision + species_language_holder = /datum/language_holder/darkspawn var/powerful_heal = FALSE var/dark_healing = 1 var/light_burning = 1 - /datum/species/shadow/spec_life(mob/living/carbon/human/H) H.bubble_icon = "darkspawn" var/turf/T = H.loc @@ -168,7 +168,6 @@ shadow_charges = 3 dark_healing = 5 light_burning = 7 - //owner.current.remove_language(/datum/language/darkspawn) /datum/species/shadow/darkspawn/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) if(prob(50) && shadow_charges > 0) @@ -207,7 +206,8 @@ /datum/species/shadow/darkspawn/spec_death(gibbed, mob/living/carbon/human/H) playsound(H, 'yogstation/sound/creatures/darkspawn_death.ogg', 50, FALSE) - +/datum/species/shadow/darkspawn/check_roundstart_eligible() + return FALSE /////////////////////////////Organs///////////////////////////////////// /obj/item/organ/brain/nightmare name = "tumorous mass" diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm index cd220a33c45b..7d2108927b3f 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm @@ -35,7 +35,6 @@ var/specialization = NONE // Antagonist datum things like assignment // - /datum/antagonist/darkspawn/on_gain() SSticker.mode.darkspawn += owner owner.special_role = "darkspawn" @@ -92,7 +91,6 @@ return "The darkspawn have failed!
" //Admin panel stuff - /datum/antagonist/darkspawn/antag_panel_data() . = "Upgrades:
" for(var/V in upgrades) From 29d1e15e3b6b3d2f5e9aabc147c0f8eae2ca2a33 Mon Sep 17 00:00:00 2001 From: Molti Date: Sat, 14 Oct 2023 20:59:36 -0500 Subject: [PATCH 057/756] Update battleroyale.dm --- yogstation/code/game/gamemodes/battle_royale/battleroyale.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yogstation/code/game/gamemodes/battle_royale/battleroyale.dm b/yogstation/code/game/gamemodes/battle_royale/battleroyale.dm index c29a3e9ddb1b..633258f4176d 100644 --- a/yogstation/code/game/gamemodes/battle_royale/battleroyale.dm +++ b/yogstation/code/game/gamemodes/battle_royale/battleroyale.dm @@ -354,7 +354,7 @@ GLOBAL_VAR(stormdamage) var/mob/living/culprit if(isprojectile(hitby))//get the person that shot the projectile - var/obj/item/projectile/thing + var/obj/projectile/thing if(isliving(thing.firer)) culprit = thing.firer else if(isitem(hitby))//get the person holding the item From 04b199006b074c3c5754752cd23d650d23aa4a49 Mon Sep 17 00:00:00 2001 From: Molti Date: Sat, 14 Oct 2023 21:00:25 -0500 Subject: [PATCH 058/756] conflicts --- code/__DEFINES/is_helpers.dm | 2 +- code/datums/elements/light_eater.dm | 2 +- .../mob/living/carbon/human/species_types/shadowpeople.dm | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index b8c65e05d37b..06f49b87a4c1 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -257,7 +257,7 @@ GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list( #define isprojectile(A) (istype(A, /obj/projectile)) -#define isprojectilespell(A) (istype(A, /obj/item/projectile/magic)) +#define isprojectilespell(A) (istype(A, /obj/projectile/magic)) #define isgun(A) (istype(A, /obj/item/gun)) diff --git a/code/datums/elements/light_eater.dm b/code/datums/elements/light_eater.dm index c8135ca55b7a..b9e97607d4b6 100644 --- a/code/datums/elements/light_eater.dm +++ b/code/datums/elements/light_eater.dm @@ -166,7 +166,7 @@ * - angle: The angle the target was struck at * - hit_limb: The limb that was hit, if the target was a carbon */ -/datum/element/light_eater/proc/on_projectile_self_hit(obj/item/projectile/source, atom/movable/firer, atom/target, angle, hit_limb) +/datum/element/light_eater/proc/on_projectile_self_hit(obj/projectile/source, atom/movable/firer, atom/target, angle, hit_limb) SIGNAL_HANDLER eat_lights(target, source) return NONE diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 9ef7a6291383..e02fa7eff655 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -128,7 +128,7 @@ var/info_text = "You are a Nightmare. The ability shadow walk allows unlimited, unrestricted movement in the dark while activated. \ Your light eater will destroy any light producing objects you attack, as well as destroy any lights a living creature may be holding. You will automatically dodge gunfire and melee attacks when on a dark tile. If killed, you will eventually revive if left in darkness." -/datum/species/shadow/nightmare/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) +/datum/species/shadow/nightmare/bullet_act(obj/projectile/P, mob/living/carbon/human/H) var/turf/T = H.loc if(istype(T)) var/light_amount = T.get_lumcount() @@ -169,7 +169,7 @@ dark_healing = 5 light_burning = 7 -/datum/species/shadow/darkspawn/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) +/datum/species/shadow/darkspawn/bullet_act(obj/projectile/P, mob/living/carbon/human/H) if(prob(50) && shadow_charges > 0) H.visible_message(span_danger("The shadows around [H] ripple as they absorb \the [P]!")) playsound(H, "bullet_miss", 75, 1) From 5e830f0d392d9a7b730284b588e1487600c6777e Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 17 Oct 2023 20:56:46 -0500 Subject: [PATCH 059/756] Update psi_web.dm --- yogstation/code/game/gamemodes/darkspawn/psi_web.dm | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index aac0d70fc7f3..6631d97b0e78 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -145,19 +145,16 @@ if(learn_text) to_chat(user, span_velvet(learn_text)) darkspawn.lucidity -= lucidity_cost + darkspawn.upgrades |= src //add it to the list + if(learned_ability) + var/datum/action/action = new learned_ability + action.Grant(user) activate(user) return TRUE ///If the purchase goes through, this gets called /datum/psi_web/proc/activate(mob/user) - if(!darkspawn)//no clue how it got here, but alright - return - darkspawn.upgrades |= src //add it to the list - if(learn_text) - to_chat(user, learn_text) - if(learned_ability) - var/datum/action/action = new learned_ability - action.Grant(user) + return /* Purchases to select spec From 89bdab23b688a71984f57d134fae69941a22b079 Mon Sep 17 00:00:00 2001 From: Molti Date: Tue, 17 Oct 2023 20:58:16 -0500 Subject: [PATCH 060/756] Update psi_web.dm --- yogstation/code/game/gamemodes/darkspawn/psi_web.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm index 6631d97b0e78..d457a865ec7b 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/game/gamemodes/darkspawn/psi_web.dm @@ -174,7 +174,7 @@ /datum/psi_web/fighter/activate(mob/user) darkspawn.specialization = FIGHTER - var/datum/action/cooldown/spell/toggle/light_eater/spell = locate() in darkspawn.upgrades + var/datum/action/cooldown/spell/toggle/light_eater/spell = locate() in user.actions if(spell) spell.Remove(user) @@ -283,6 +283,6 @@ menu_tab = STORE_PASSIVE /datum/psi_web/twin_tendrils/activate(mob/user) - var/datum/action/cooldown/spell/toggle/pass/spell = locate() in darkspawn.upgrades + var/datum/action/cooldown/spell/toggle/pass/spell = locate() in user.actions if(spell) spell.twin = TRUE From 4ab21aa5390c6bbd5395b00f613920a47df754b1 Mon Sep 17 00:00:00 2001 From: Chubbygummibear Date: Tue, 24 Oct 2023 20:07:14 -0700 Subject: [PATCH 061/756] reorganize --- .../tgui/interfaces/AntagInfoDarkspawn.tsx | 340 ++++++++++++++++++ tgui/packages/tgui/interfaces/PsiWeb.tsx | 5 - yogstation.dme | 6 +- .../{darkspawn.dm => darkspawn_antag.dm} | 54 +++ .../antagonists}/darkspawn/psi_web.dm | 90 ----- .../antagonists}/darkspawn/veil.dm | 0 6 files changed, 397 insertions(+), 98 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/AntagInfoDarkspawn.tsx delete mode 100644 tgui/packages/tgui/interfaces/PsiWeb.tsx rename yogstation/code/modules/antagonists/darkspawn/{darkspawn.dm => darkspawn_antag.dm} (87%) rename yogstation/code/{game/gamemodes => modules/antagonists}/darkspawn/psi_web.dm (69%) rename yogstation/code/{game/gamemodes => modules/antagonists}/darkspawn/veil.dm (100%) diff --git a/tgui/packages/tgui/interfaces/AntagInfoDarkspawn.tsx b/tgui/packages/tgui/interfaces/AntagInfoDarkspawn.tsx new file mode 100644 index 000000000000..68483a77d08e --- /dev/null +++ b/tgui/packages/tgui/interfaces/AntagInfoDarkspawn.tsx @@ -0,0 +1,340 @@ +import { useBackend, useLocalState } from '../backend'; +import { Section, Stack, Box, Tabs, Button, BlockQuote } from '../components'; +import { Window } from '../layouts'; +import { BooleanLike } from 'common/react'; +import { ObjectivePrintout, Objective, ReplaceObjectivesButton } from './common/Objectives'; + +const hereticRed = { + color: '#e03c3c', +}; + +const hereticBlue = { + fontWeight: 'bold', + color: '#2185d0', +}; + +const hereticPurple = { + fontWeight: 'bold', + color: '#bd54e0', +}; + +const hereticGreen = { + fontWeight: 'bold', + color: '#20b142', +}; + +const hereticYellow = { + fontWeight: 'bold', + color: 'yellow', +}; + +type Knowledge = { + path: string; + name: string; + desc: string; + gainFlavor: string; + cost: number; + disabled: boolean; + hereticPath: string; + color: string; +}; + +type KnowledgeInfo = { + learnableKnowledge: Knowledge[]; + learnedKnowledge: Knowledge[]; +}; + +type Info = { + charges: number; + total_sacrifices: number; + ascended: BooleanLike; + objectives: Objective[]; + can_change_objective: BooleanLike; +}; + +const IntroductionSection = (props, context) => { + const { data, act } = useBackend(context); + const { objectives, ascended, can_change_objective } = data; + + return ( + + +
+ + + + + + + + {!ascended && ( + + + } + /> + + )} + +
+
+
+ ); +}; + +const FlavorSection = () => { + return ( + + + + + Another day at a meaningless job. You feel a  + shimmer +  around you, as a realization of something  + strange +  in the air unfolds. You look inwards and discover something + that will change your life. + + + + + The Gates of Mansus +  open up to your mind. + + + + + ); +}; + +const GuideSection = () => { + return ( + + + + - Find reality smashing  + influences +  around the station invisible to the normal eye and  + use your codex on them to harvest them for  + knowledge points. + + + - Use your  + Living Heart +  to track down  + sacrifice targets, but be careful: + You are able to target other heretics, so be careful whom you hunt. + This action is tied to your heart - if you lose it, you must + complete a ritual to regain it. + + + - Draw a  + transmutation rune by using a + your codex on the floor. This rune allows you to complete + rituals and sacrifices. + + + - Follow your Living Heart to find + your targets. Bring them back to a  + transmutation rune once you have killed them  + sacrifice them for  + knowledge points. The Mansus{' '} + ONLY accepts targets pointed to by the  + Living Heart. + + + - Each Lore-Specific upgrade will be available after gaining three research of the previous tier. + This means you need three tier one abilities before you can claim your Grasp Mark, + then three tier two abilities before you can claim your Blade Upgrade. + As it follows, three tier three abilities are required before you unlock your Ascension Rite. + + + - Accomplish all of your research to be able to learn the{' '} + final ritual. Complete the ritual + to become all powerful! + + + + ); +}; + +const InformationSection = (props, context) => { + const { data } = useBackend(context); + const { charges, total_sacrifices, ascended } = data; + return ( + + + {!!ascended && ( + + + You have + + + ASCENDED + + ! + + + + )} + + You have {charges || 0}  + + knowledge point{charges !== 1 ? 's' : ''} + + . + + + You have made a total of  + {total_sacrifices || 0}  + sacrifices. + + + + ); +}; + +const ResearchedKnowledge = (props, context) => { + const { data } = useBackend(context); + const { learnedKnowledge } = data; + + return ( + +
+ + {(!learnedKnowledge.length && 'None!') || + learnedKnowledge.map((learned) => ( + +
+
+ ); +}; + +const KnowledgeShop = (props, context) => { + const { data, act } = useBackend(context); + const { learnableKnowledge } = data; + + return ( + +
+ {(!learnableKnowledge && 'None!') || + learnableKnowledge.map((toLearn) => ( + +
+
+ ); +}; + +const ResearchInfo = (props, context) => { + const { data } = useBackend(context); + const { charges } = data; + + return ( + + + + + You have {charges || 0}  + + knowledge point{charges !== 1 ? 's' : ''} + {' '} + to spend. + + + + + + + + + + + ); +}; + +export const AntagInfoDarkspawn = (props, context) => { + const { data } = useBackend(context); + const { ascended } = data; + + const [currentTab, setTab] = useLocalState(context, 'currentTab', 0); + + return ( + + + + + + setTab(0)}> + Information + + setTab(1)}> + Research + + + + + {(currentTab === 0 && ) || } + + + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/PsiWeb.tsx b/tgui/packages/tgui/interfaces/PsiWeb.tsx deleted file mode 100644 index 0b9c325fe9d6..000000000000 --- a/tgui/packages/tgui/interfaces/PsiWeb.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, Section, Box } from '../components'; -import { Window } from '../layouts'; - -// chubby please do your thing diff --git a/yogstation.dme b/yogstation.dme index a4d8a0c5f10e..4be7432fe9b5 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -3843,8 +3843,6 @@ #include "yogstation\code\game\gamemodes\clown_ops\bananium_bomb.dm" #include "yogstation\code\game\gamemodes\darkspawn\darkspawn.dm" #include "yogstation\code\game\gamemodes\darkspawn\darkspawn_hud.dm" -#include "yogstation\code\game\gamemodes\darkspawn\psi_web.dm" -#include "yogstation\code\game\gamemodes\darkspawn\veil.dm" #include "yogstation\code\game\gamemodes\gangs\dominator.dm" #include "yogstation\code\game\gamemodes\gangs\gang_items.dm" #include "yogstation\code\game\gamemodes\gangs\gang_pen.dm" @@ -3983,8 +3981,10 @@ #include "yogstation\code\modules\antagonists\_common\antag_menu.dm" #include "yogstation\code\modules\antagonists\abductor\equipment\abduction_outfits.dm" #include "yogstation\code\modules\antagonists\blob\blob\blobs\core.dm" -#include "yogstation\code\modules\antagonists\darkspawn\darkspawn.dm" +#include "yogstation\code\modules\antagonists\darkspawn\darkspawn_antag.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_progenitor.dm" +#include "yogstation\code\modules\antagonists\darkspawn\psi_web.dm" +#include "yogstation\code\modules\antagonists\darkspawn\veil.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_divulge.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\_sacrament.dm" #include "yogstation\code\modules\antagonists\darkspawn\darkspawn_abilities\devour_will.dm" diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_antag.dm similarity index 87% rename from yogstation/code/modules/antagonists/darkspawn/darkspawn.dm rename to yogstation/code/modules/antagonists/darkspawn/darkspawn_antag.dm index 8b52f6db6006..3fb76fe7c9ce 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_antag.dm @@ -9,6 +9,7 @@ antagpanel_category = "Darkspawn" job_rank = ROLE_DARKSPAWN antag_hud_name = "darkspawn" + ui_name = "AntagInfoDarkspawn" var/darkspawn_state = MUNDANE //0 for normal crew, 1 for divulged, and 2 for progenitor antag_moodlet = /datum/mood_event/sling @@ -34,6 +35,59 @@ var/datum/action/cooldown/spell/psi_web/psi_web_action //Used to link the menu with our antag datum var/specialization = NONE +/datum/antagonist/darkspawn/ui_data(mob/user) + var/list/data = list() + var/datum/antagonist/darkspawn/darkspawn = antag_datum + + if(!istype(darkspawn)) + CRASH("darkspawn menu started with wrong datum.") + + data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / [SSticker.mode.required_succs] unique drained total" + data["specialization"] = darkspawn.specialization //whether or not they've picked their specialization + + + for(var/category in show_categories) + var/list/category_data = list() + category_data["name"] = category + + var/list/upgrades = list() + for(var/path in subtypesof(/datum/psi_web)) + var/datum/psi_web/selection = new path + + if(!selection.check_show(user)) + continue + + var/list/AL = list() + AL["name"] = selection.name + AL["desc"] = selection.desc + AL["lucidity_cost"] = selection.lucidity_cost + AL["can_purchase"] = darkspawn.lucidity >= selection.lucidity_cost + AL["type_path"] = selection.type + + if(category == selection.menu_tab) + upgrades += list(AL) + + qdel(selection) + + category_data["upgrades"] = upgrades + data["categories"] += list(category_data) + + return data + +/datum/antagonist/darkspawn/ui_act(action, params) + if(..()) + return + var/datum/antagonist/darkspawn/darkspawn = antag_datum + if(!istype(darkspawn)) + return + switch(action) + if("purchase") + var/upgradePath = text2path(params["upgradePath"]) + if(!ispath(upgradePath, /datum/psi_web)) + return FALSE + var/datum/psi_web/selected = new upgradePath + selected.on_purchase(darkspawn?.owner?.current) + // Antagonist datum things like assignment // /datum/antagonist/darkspawn/on_gain() SSticker.mode.darkspawn += owner diff --git a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm b/yogstation/code/modules/antagonists/darkspawn/psi_web.dm similarity index 69% rename from yogstation/code/game/gamemodes/darkspawn/psi_web.dm rename to yogstation/code/modules/antagonists/darkspawn/psi_web.dm index d457a865ec7b..219b47e2185e 100644 --- a/yogstation/code/game/gamemodes/darkspawn/psi_web.dm +++ b/yogstation/code/modules/antagonists/darkspawn/psi_web.dm @@ -7,96 +7,6 @@ #define STORE_UTILITY "utility" //things that you use and it does something less straightforward #define STORE_PASSIVE "passives" //things that always happen all the time -//Used to access the Psi Web to buy abilities. -//Accesses the Psi Web, which darkspawn use to purchase abilities using lucidity. Lucidity is drained from people using the Devour Will ability. -/datum/antag_menu/psi_web - name = "psi web" - ui_name = "PsiWeb" - var/list/show_categories = list(STORE_OFFENSE, STORE_UTILITY, STORE_PASSIVE) - -/datum/antag_menu/psi_web/ui_data(mob/user) - var/list/data = list() - var/datum/antagonist/darkspawn/darkspawn = antag_datum - - if(!istype(darkspawn)) - CRASH("darkspawn menu started with wrong datum.") - - data["lucidity"] = "[darkspawn.lucidity] | [darkspawn.lucidity_drained] / [SSticker.mode.required_succs] unique drained total" - data["specialization"] = darkspawn.specialization //whether or not they've picked their specialization - - - for(var/category in show_categories) - var/list/category_data = list() - category_data["name"] = category - - var/list/upgrades = list() - for(var/path in subtypesof(/datum/psi_web)) - var/datum/psi_web/selection = new path - - if(!selection.check_show(user)) - continue - - var/list/AL = list() - AL["name"] = selection.name - AL["desc"] = selection.desc - AL["lucidity_cost"] = selection.lucidity_cost - AL["can_purchase"] = darkspawn.lucidity >= selection.lucidity_cost - AL["type_path"] = selection.type - - if(category == selection.menu_tab) - upgrades += list(AL) - - qdel(selection) - - category_data["upgrades"] = upgrades - data["categories"] += list(category_data) - - return data - -/datum/antag_menu/psi_web/ui_act(action, params) - if(..()) - return - var/datum/antagonist/darkspawn/darkspawn = antag_datum - if(!istype(darkspawn)) - return - switch(action) - if("purchase") - var/upgradePath = text2path(params["upgradePath"]) - if(!ispath(upgradePath, /datum/psi_web)) - return FALSE - var/datum/psi_web/selected = new upgradePath - selected.on_purchase(darkspawn?.owner?.current) - -//ability for using the shadow store -/datum/action/cooldown/spell/psi_web - name = "Psi Web" - desc = "Access the Mindlink directly to unlock and upgrade your supernatural powers." - panel = null - button_icon = 'yogstation/icons/mob/actions/actions_darkspawn.dmi' - background_icon_state = "bg_alien" - overlay_icon_state = "bg_alien_border" - buttontooltipstyle = "alien" - button_icon_state = "psi_web" - check_flags = AB_CHECK_CONSCIOUS - spell_requirements = SPELL_REQUIRES_DARKSPAWN - var/datum/antag_menu/psi_web/psi_web - -/datum/action/cooldown/spell/psi_web/New(our_target) - . = ..() - if(istype(our_target, /datum/antag_menu/psi_web)) - psi_web = our_target - else - CRASH("psi_web action created with non web.") - -/datum/action/cooldown/spell/psi_web/Destroy() - psi_web = null - return ..() - -/datum/action/cooldown/spell/psi_web/cast(atom/cast_on) - . = ..() - to_chat(usr, "You retreat inwards and touch the Mindlink...") - psi_web.ui_interact(usr) - //shadow store datums (upgrades and abilities) /datum/psi_web diff --git a/yogstation/code/game/gamemodes/darkspawn/veil.dm b/yogstation/code/modules/antagonists/darkspawn/veil.dm similarity index 100% rename from yogstation/code/game/gamemodes/darkspawn/veil.dm rename to yogstation/code/modules/antagonists/darkspawn/veil.dm From f0f9d82ac18d8d543e26e58426f27d47604dfee2 Mon Sep 17 00:00:00 2001 From: Chubbygummibear Date: Wed, 25 Oct 2023 15:39:47 -0700 Subject: [PATCH 062/756] just antag --- yogstation/code/modules/antagonists/darkspawn/darkspawn_antag.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_antag.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_antag.dm index 3fb76fe7c9ce..bd91e0f7a5b5 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_antag.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_antag.dm @@ -37,7 +37,6 @@ /datum/antagonist/darkspawn/ui_data(mob/user) var/list/data = list() - var/datum/antagonist/darkspawn/darkspawn = antag_datum if(!istype(darkspawn)) CRASH("darkspawn menu started with wrong datum.") From 7f266ca56f9a6cf7ae792b117d3cc44d115a34a0 Mon Sep 17 00:00:00 2001 From: Molti Date: Wed, 25 Oct 2023 19:11:52 -0500 Subject: [PATCH 063/756] shorten divulge --- .../darkspawn/darkspawn_abilities/_divulge.dm | 11 +++++------ yogstation/sound/magic/divulge_01.ogg | Bin 137229 -> 90827 bytes yogstation/sound/magic/divulge_02.ogg | Bin 243813 -> 157721 bytes yogstation/sound/magic/divulge_03.ogg | Bin 729807 -> 151934 bytes 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm index 7c70e5118a4c..d27239f90900 100644 --- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm +++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_abilities/_divulge.dm @@ -52,10 +52,9 @@ user.visible_message(span_danger("[user] slowly rises into the air, their belongings falling away, and begins to shimmer..."), \ "You begin the removal of your human disguise. You will be completely vulnerable during this time.") user.setDir(SOUTH) - for(var/obj/item/I in user) - user.dropItemToGround(I) + user.unequip_everything() for(var/turf/T in RANGE_TURFS(1, user)) - new/obj/structure/psionic_barrier(T, 500) + new/obj/structure/psionic_barrier(T, 35 SECONDS) for(var/stage in 1 to 3) if(isethereal(user))//keep the light disabled user.dna.species.spec_emp_act(user, EMP_HEAVY) @@ -67,14 +66,14 @@ if(2) user.visible_message(span_userdanger("Gravity fluctuates. Psychic tendrils extend outward and feel blindly around the area."), \ span_velvet("Gravity around you fluctuates. You tentatively reach out, feel with your mind.")) - user.Shake(0, 3, 750) //50 loops in a second times 15 seconds = 750 loops + user.Shake(0, 3, 500) //50 loops in a second times 15 seconds = 750 loops playsound(user, 'yogstation/sound/magic/divulge_02.ogg', 40, 0) if(3) user.visible_message(span_userdanger("Sigils form along [user]'s body. \His skin blackens as \he glows a blinding purple."), \ span_velvet("Your body begins to warp. Sigils etch themselves upon your flesh.")) - animate(user, color = list(rgb(0, 0, 0), rgb(0, 0, 0), rgb(0, 0, 0), rgb(0, 0, 0)), time = 15 SECONDS) //Produces a slow skin-blackening effect + animate(user, color = list(rgb(0, 0, 0), rgb(0, 0, 0), rgb(0, 0, 0), rgb(0, 0, 0)), time = 10 SECONDS) //Produces a slow skin-blackening effect playsound(user, 'yogstation/sound/magic/divulge_03.ogg', 50, 0) - if(!do_after(user, 15 SECONDS, user)) + if(!do_after(user, 10 SECONDS, user)) user.visible_message(span_warning("[user] falls to the ground!"), span_userdanger("Your transformation was interrupted!")) animate(user, color = initial(user.color), pixel_y = initial(user.pixel_y), time = 1 SECONDS) in_use = FALSE diff --git a/yogstation/sound/magic/divulge_01.ogg b/yogstation/sound/magic/divulge_01.ogg index 280ce9b2db0b265ad6d5d3d46b4a9adbf4231c55..b89f8e0bd087a1c6840033cc09dc761db123441b 100644 GIT binary patch delta 86092 zcmY&obwC;{=JL%ZAZL7nbj_q`uopd_tj&0kvZQHi(-2TtGW88789@eb&Q0t{e zt@$aU8g^^|3SZg6LLC4O_`jo_{(p<5(p>%+d?w2O)?oi$(M!`+qe^`Je`5sVr-QSx zl?z9V9X=i#3kx?32Puu3nW>wJmAwV2r2S7TX9s(`nxs)=5J2O9xBYLs|Gp)Shk{SU zz(7sSz}(%{-q_yU*-_ctHQ3tK+S=FD+Cjm{LT}S@)R%Snr;HbV)H~3n5nE zAg&pqmKEe_q<5Xe>samWz=+F7i8r4^s7WaL7=4v{<%i1;SRBqLm>OPC=Ujn&EgWd; zGyxrIAkxzVC?7QF!A!XXnd?`-C}VEi*-HaZ;Xk}+IVo=5+1@JX`(V|JVZkoHoF@q( zU6p)=#ezYubV@l-3N|7bq<>k-Rq&`bbYBl$>{N503q4br&k+C`LIc8sTF4LMYI?#@ z(a57I$ZCSaUDdd6N0iHE^s-{C^{St+ZXoz}`h6@|4Y3E|h5*h96C1oc68v~^!^yWC z3*-}>JxRh5-bl!n6lAETws`!PR}6_Nyb-ikyo76hjR4M#;+jsY!QU+iF*Pm8$mXcW zbcu6hLzw=X*KL9mc42k`;T-Rq*k>i4*6eQ#X>X3)1hH9#>E^~a_~utQb{Y!&8=#ny zmQFxFY2B$-19t7JbWJ=!q~%rmi9(@p7=oVMuGvbA!FLg|tB@%s4EZ?ei@hWX^HJ2Q zKOhws{msB@w>?$o>Q+OBLk?{6XlX#`ImRtIuyH$=6&E^kYePOdhbTA6fXt*EELf>H zsh2NlYH;eRPF4YsNgz1u9*xAO45D}J>~|iK3855O3lAfiB`X9#N4ZBH;L&9<$;+j_ zj2g`nrFr1O;&=v^vQD zfL*-dCy$S4rZXEbo;wR_d&dP<**1ze3Ky#@LAVwfM zut1%dWCHFPU!`!5FCcWA#+t(D%h(J6h^yB#Trz(?f>O$wWC=m_EO>{+ft{J1UiwGK zJmRR(d|Ugc7$Vv5FeP1oKzR8xoUq}J@#D70ECuno5`hjMtqQrT!;qe)N#k)DJ<~s> z`x+{7*&WIWsui*;O}|vFeL_c9Y}AcB8L&nWyYwF4ARP>y&D`_yf3+|v zz#LuO>SLIonix0NHyE0wQXciNYX=92#?Wv<0yg0d4)|lu?rtBPK&qZ%{f!Y^!6G(P zcAB(BV&edX-zf!W;VB^}fw+Fc+U&0ixAC{G9xa=vDnAuHkA>Fv_-CP^58e-cc#opc zsoaFU$r_-hz~M7-B{EF6pw+nUNSYdzi^pq)#~4HeO|vh&CYnrCNCh~BZCWk2=N0uI z9hTl99~!!t)u*8EgUnN)LFt-qN$Q!M=?dV^g>L@(UAPjWzG7fBsRmu9A7S^ZWajqS zf8&w?e4p?{58Bh<%)tDi5KKx_*knYr*s7ZS=tfL{G5E#0h^8LBjXhVCfF{|^Yjr{9 z8c_?wnTZRAV1Z)Zk4$W3s&9GHR01X84+5C8Q)|T>{_nGeAg@n%wN;x%gW4?z9TSOM zW(ZxYda^>{%gu(GynI5+ynNugoYowyh*(U_Un})%if-?DYRnLOr>#AA zT+Zkif~jMvH&)D0&|L`Q=lE>(y6>o%Wo+8H+sD4G8fXuPaf-ATiRSL!+pPYQ@SoVZYfX^wy&3s^=%X5256#D#x?s$Pp%IWL&8Q4E-1Xh#Jj zme1H%jvg4t7UsfdE^ael!){*m>H!lm9*AcgradLtR!^2%|Q zA+&>~FVI^m7zDOMHp*-#(;hCMk1)Ci-T52f4|HG`dG#E;siBZS3%C{xi(Ka3e05l1 zfI1eRzG9tc#i)wD-#5aH8}e-NE3Va3@H*9n*|m&^}rFOQ%b%n^fje>^LkSXsHtodnRyK|xj`|p%b!QaHJ zxjB`|0Ggv;iw{ka_ryAt=@8#?pX$FBlisg>|JV;@LGW+8M|s}b8=DmNnKfKN)N+M` z1a$IUJW~&1lY4j)EZzJ{6`OmCoCStDR;*5;MC512uE(Ey^<^CF*)4cz<}o&+wZSc1FXI$TM;?dVO~e6{IqGXQb1 zIrBqlbkofG!8Sceo|;8!t0FOD7O%Y+D{&{Vx-FlB_idwMsqQJQZdtsRl$c`{t9hAI zzU!n&>m$@!R9U@O)1*6Wotw&a5Y3>Dg*v#vGy!0fj_Aa_I;`|??az|;Ozj0=jVyuic0E(@w5$4Nx+*5%7pmSGs-2zpLbAc+eXV3bshC@=mBHF87P=U#zwNH`Wj&xUNcsEM>#7lD2zT(LK%~Slp6JLY$V4u;K~0fVyYbv6iu_G7@%^VC@^-m&hI)guc4? zDHkpR5l?}JdQ9F$3xg`v-Xrn+=EU8GmD^dbkv3W2!3V8~<*j`UQfnUfU;XXZ-bA~% z#&o-c6%F{r&sdhu#|Z)YvAFv5{NM>~tx3f}<%MLk8bwzAWbSyS-z#G-avo>xc$FiS7!j3;)lO=xJ;F9IE z8L-kt@$L|W1V!M14q%Ul5vP^<4ZPS9g8TSfwb3&~f>hO~SDz=!@M%Zho$bx;MSpD5 z*A{8O5HUhIK%y}E+M*Fw7L9z$jV>MIcYUqOcd$~eLLdhJ0TA=s-MD;%zduWwop=JT z9N&l6?{+q!Ytav?H-jey)@@CAGIJdHqCKM}tqe?UF~4+x2wy+Msk_9?_@}#w*1XJg zMIeNR-ABL6j{BE9IZ?0!%(2aTrjIf$j!b#gh@W>a`L>UJ*#H%?FzuAnRUyk~gvqk& zg`@KZ7e<b)WbNSpczly;{r!Jdkqw7NPwUG#-2s20(4mu>xB2uH@PmzC_Kw@Kuu@@tUMeb zpQ2VajiqYvE;B8uS%2ih*NNxzejG)aY23oxX`xu5HQd3n#3=GnkgU`oloej!{=k`6 zyQ?!_V3_}wJjri*%o;nwJl1a} zsXX&};MR%~Sm_@dKvs8!;N*Y3(u(qt9m#I877KPle2~x3tVyb`S<$3DiiTow| z@0vFl)!v8W$hs-X#6Jp|m3NEDhpvYF4n}u_alio4Emr6h@-`noh@3yxzWY07fdc3k zd9eXn9c$09$IoFFl*8!5g^f`gkS1p`(8`j?;|*KpG_Ikr(x&_l@fUxE|3wmB6E@s7 zcay7B94~xxXMsng`up)WPL7ND(#n+VkayA>D>pE3<(k60hs0DB0j=gNgD8{^yRUFL z{h{(9yN%CTdhs7W8RL(+DIxH!ge2@CWdnUd)|QFgke&D!uXwA!q@PS^0(`aCe1DrJ zc*%}Uh^Xxy4@G~Yg}RQRhO;>gr%d;`0!&Rc0hNSe>Y49uJ1!~--w|L9>o*nnEuyAx zt)+*S)}vhf=cHcubk;<2Rq)b++$tzDfT;RFoR7Z)i#$lAy9i+ljsaFIiuk50$aUKw zCVOH7m0FvTbFn2R8yvWui z?m9x>xXXQ`Fb7A6LvN)3hde15KqejIJ=T)!cY_Dnm6A6oYT0Qpe=AK-KN)s)0F31j z^$_nx582G&pVdx9S{y^Yf)?4(0q0Rr)4=r3AeOq6huMiDHSEdREcbd1XYlyP)6W7L ztq~Es`B+9)-v-^D52mlqKhXe+vH@$|%;Ng|rzH%e`5;}1o$G?x+^sn2d|W`R`??NA z{r%PNl4@}LvKXLmS#j)TDUFRTGF$hW{|t0zRs-17lo3PTdjYK47AE1r?~4?WEx->x zV})Ob9x?0XtR0O6$igC8F_ad|IQ*g^1i(PLpj8kh- z9KPpAn1kvy=LN@?UJ*p<9~7i5%D1JFCoVMC;j&xzzED2$BVastT$hQW1B_BW z#EMdNU0-g3%?5of%#Q6K8(u)G)f~b4nNyaqOYVTku*zg$x>`5H8TfV-^l0)1VLa%?VvG_^g zjI62s8sjnYDFOcPQ2~c7aSnkuKIh{-!^~TkEAKocnUv>)92cxv%u=9p*C}5Y#?!M%8yo#36_KJ=*i4sVRlwy>3hZ%#%Lj zmOI6f`Ue5PbTyo7sJ1_h?cCL?E4%MSQ)Q=%>BvC6X!?Dxsk;8|uyj?yT zzAftY?O3i70H`;7;Ri+A@Y#}CR4N%k!hY&Vx72EQe)ap%YK$Az813)k3mu-9+;?f=M6DJZq$wJb zK9L*MlXlvB-$_XGxxYEvrBs^Bz#Og^NBmnY_k0TRn6 zXx>e-vc1)dM1jnj@%zhU$Zx)jtT?ni@XfwX?N0{duD;1z$U}*OF)a%sSWC0RHVrD9 z3E1;am9l!c$mgv~=Mk}TJa#wq_e^ZAwT__BwUOdc_+>6N${SIZJH;yZF08GQ;EucV zUWiVDjl`(^1z5uqJAEabsR}%Ch`r@k(#$Hs0f3|8ve1X-sJ+4qe|6GZ!As#~A<4CV zq0*x=Ya9xhEa+Th<4OMgD$RbT=APq;OSYb1IZVFQHi)MOzcNNM*troraL>yRE$<@2 zV56B<#3mU5>^qnU1hJmouJ$!}5=p+kYm9$?@*zFdDjOIeefK*1W}(5om#FQ`#;T3q zN+~RY`q4@&Y{c71F!D|cPw(uR4pwA*P>qu*KTw~s5A;sHUW)%sQ)YSEZIV}xzb;*p z9PjoR0hChAkL&srR9exo7GZHr4ysbR8{zeVA3hucyjN30!U~6Y7j>PuwM-}|Pyw0r8RJ#Bc91AQ*O0$06f}TU))6WyGBYrM z%bV#n=;nT6-^_68t7EdEuC~egG)3p_ii&+?ld71tYU#?MAvQV$YXl4jZ;`w;MxB>D zq>&Joh!AOD30PJvC2J=}Q!E>@Tu5GHQSg{>@W;grvGVBxc_g!_3}29!lkqX9)d$}{ zw&2fqY#DA3@5h-T$=d$!v$tF6a$zkdG5C8eATjGEExmcVWWV+=-Z@r zPvtG+C_{g16E4=7m;wlYo!vw6xTYxTVNNpqG6m{3lC2CC$nh|pVwZY@nsj8swu40C#&m2VIgdGZJI>Meh? zb__U^dOjL+6H%S;Y0o!l1ihC5JZe+pJyl6J24-(Hy8kMdaWY!_;}+&}*cMEGtW;8M ze4>)r%kk4a%H)~h+IW^nJnd?k6q*X+3ELq4vd^C@NM)h|E{D&!i>K###br?vgUC|J zKL*`c(dh`wQ;JZC!E6oPNJcHc_HkYrs7nESn2XGT-*ammX${}+gAmJF-7~C<4DaFc z?RS7&J{Fd49T!uOkZ`zJ!DM=38p`0G2XN290*>t^wG2D_<<>8M#dIf_J%PBNs^BGH zak!2Bjpb$inznJ-vK{1pkImnjKw*02&vFw!1z_oF7gpYgZyy+YU0GSw(fF>oTWUGA zDCV2Oi%lW1E(Q&s*$aX*?M#%t)eIc3RtwJ#mT*G8Gk1mi8Qx{feAS#({alPCs0i|4 z*;*Q|rps(_n)mf{`UZ!E5$9n=cp<>70?#cX)_lTBM+th`gD2k?HW~XZP({6L{5K-Q zfhfST-?^ErQjtoI+r~-r5*7`OJ0szTHSiVhZQLbKbzt%AGEG^xP&1B8$2hbug{@04 z>8e&YTRwDuX12Wh1;ze{2#y?X4s(L<;7z12=LUk+?{>O5d>SGLfRK&dInmjK(G3T~ zt+(jCdZ3X~ce2(`v^;Yt9ssn#yI)5pf>)|m%S>eFvgy-grh=csa=t~^n#NY}@u~z& z36>ze2tvvn`+Nq=8)8-p1$SfpNF0b78^ow97l8OymnP90ijoO+A0Vjgh0@75Aj=XGiTrnz!1|0rRi{Hp{QGmw$7_^|OuU__@{XIzuP*g8%}u z?tJPzR}vzVeq*94S>|%*!2c{|N)LHj3!lEUpA9M++NSgCPMAQyY@tW~u!8yuG*?V@ z1e`PvRAgQx+pP0i$vVEuoh0RlDbNqa39DE&7g`^&^=F<@9Z(V2iWiN6eBb<>@oQZs zJ<0D~ef_Zy>s-xM?LwcfiWTCpAt_{KulrSez1xHNf3h=YZxX)Tn9N(S82~6)?xW^RHOdv$> zRRiE2*LL1MS>t{RdED>L{XTGbe%{r2XQp6vU!>^uo9Exi!#SRELLkv-nXleFvA7*5 zKUYmY(7?^~`;JzkJsPd-)5I*C&$(&#my!}g{Z~|_+1RD2OfgwPZqJt*$lSwu#-uS{ z@|mykG@UhAl?u}CqH4dIJ9)NM|{|~(h{_E6YEDd+8 z^vC;l=X?%-CA^*{aA{)M!TtC*CM-e^ujRhROT8ZD z>6TRdJGst{X{7#jQe=&mdY@-g%28L0DL2zVI5;wX!h(x*Z4M(d z>5Jt}s)Ky9s8gcT4-O+ny1Bu&C%BPUGRc{lrDh}>LdXwLdf>01!N*mPe=HDMjA31^ zjoK2>-38nCA5&_J+u_x)68CMAhmw-`5211t?R3O6r2L)tK}q&vZpef4{aVKK?fw)MQwCDe;ItlJe%HcV zx8`t6Kg`blrg5zM>mL(}&v?&2&!*$sFksA-=#Z&?0a%rdsBIWzg}Q#IVK)5oqj4`V zkhk??e(AEC9FKSs_S;lK6h}I8ognORY&$|*N$R$hvd{i1!%7WV6|);aiW6hh2j$dz z#>0Q=@kSn^xD6sYivc?24c_?|(?pLD{4Au=e)%`jIXMqk=K?Z^y)H>JmvmO|?H=cn zI)NGFv~dwj7;!?I4Tk70m>YBOl^&_t7s*!)j+9(P7;|rRo36bgVE`-l(ysUY9}upF zIn6G&>UH0b`;z0Ie&!Q=>o{3+1SQ&0W^BBv8!I$O5r<7FZwcuu8enlWyK*PF(*due zvtsyjC9MDO0ejl~rcGA^m1SZt&)lFs9I3dnf<6kkNo6*v#$okhn3JL0c8h9sIiv zt|?Fk&R>&zsq_PIJYQXeAR@l&^8%PS;#WJCd4*VrM(2Wdk;Enh(Ga{p#uE6n(Gqg` zghi`nAA10pqx8Dj-v+^=GGn7UO> zPyr?C5qgJY+J_N%u=rG5Ab(^b0-`zhTOFRoXU-J2dK^I=WR7snP7-u68^AN4#mm>_ z%$g_jQy1pj&_x}6xJ4KT%-LVY_MeMhH8pqMO_!S-1&xDsbn5sG$QFqUhLIg`>bR`H z?!xKtoC1VlHa)*6wC`_2RwvdorAL#DMZLSHI_oMT+WWyu;S9x)AnuY!BPcnAx!rG~ zFMP>BUe{eaSjod&^+7I+j{DvGzcw^uTe~l&5GD^9+r^Bbws|$VK|mv#Gw7cy^V{qx z%4!x55~F2!Nxo_1W{iM*P0h%LA{xNup2)SSnh*ZF!A960f+@e$SF4Qj7#INufw3;t zuA25`q0Uyx7}m)pkZDl4*u*l_gAyM#Yk=gnfytvlj;R_|6zNeM^xqw!XTD?+Y%26*7gM3-{%o*8AE)%@!H z0sn*wVWL*SGp-I&R}<3z_z^&W?vMY6*CGFvYx&~kLMpXCVmHW7Tohn&U@CzeCf;Vxv#jH$Wf3A z3W$KOE&ssmQCU zL%3>-CV=eJlfdP=v5)o19JsyAyM(Y8uC>Q{!=f{EJy^Wf%;(oxQ<*9{fiPmU>bQ}V z^+9SIy6kdss-B-+Z6#&qr`Co02Ce%KLX0*KvCLdExm-;SdiGCat>1gMwGmN$mzTb- zy5+l?V-Ex~^4W0Wq}b>|T6hWfc`I6E$9*^xFB6g0PaDjw#~j_9EP(JIBe9IMm0!4tWTF*f9 zNRTJo^u)Zsndup ziC=I-H-rIzn{H?pExpu+Api?I@=Z&>Zn9r(Cyx2VnTJ=6?qO1bx2GgtBn0{|x)u}{ zpsvg0QKdGBsr{r+zp75jQ9=;-M6I6C!(b7_nzChfV9steiwCXX1#N;v8As=@yjtT_;``cy36&Op!DtrSl{QCKcm4vx^;a3`cM`6z z#(q8~UI!j?N+!*@s!V8dJ}biv3vB{$k7z?|ek_3ipQq^`+FY7O55apu5q(Euv4$`P zX&5z^~0{@)ChTn|TQ zLWA*7Oo(tlClfF_`cT{yXTj3BsEk}zNr$?b-aBdY1s?$Ne=g*#5abOjT0`(? zl5BwPm(BttCb8?^Cy6i235L+HWL`*ezbK{6W8zavzW2C_Cy;O@iRCcWBltbl> zu+Vvh>@tDL01V~-8A%i{VK%qL>ZOE*~Up$vi) zkho!mr4X2oFo>nn(vt(bUX*&UWwlUg)~p(*o@hOOV@6)*HQFy1PSUUP5`~|tmyFJb zf8O)UR9}F$l6he;y*XaWgnZlskI^h!S6*6RaLO&P`Z=7V#;1>$g5pT>>b7ia>Z3gc z8_wLYV5&aCR_Y&hj-Q))xKx(YP7B(lA%ReV*w+PSSR0x*_&` zz$c;on?F2uC!W774DqMj#)))e1>V5w2ZPBs!|Y2mnPx}`xIrE*nKV=|0EhhLLCSTP zIw)gQCmD_3bMP{Lx!x3|;4-zYnr1 zP1K0fzrW0k4UNT7wcrNTsbZ?}E%~cm-mMnjn7_xtRVv{X!DV6+vebKAgE#WJJv$Tw zGS&cwZf|bStg0Ig$UPM0$66qd-}1-W!p>ZaR*yFNuFmlwYI*ZE!*d^A@9in zOGA~_dx;F&idF`5S-sVd@@8>8UgsueG{T3zZ_yIHoyYu;x7*KZsL5GU7FRJ5d>vrO zcZD~XgT;-vP7t1<`t97!CUFw6m71LSF@@1JUEk=mTd0a=URo$FOA$c$-kDYU&y-rm z+OG3b-+9gCrYi;5h})|UcnQRw#40TzcW@M(0o7pXx;I^iq*a4pJWD=E-Ea@wY?Aer zHwF&s$VQiz# z#a3;0?B6E@hXOUNx@whRu(si|F&_spKWi`cup6bowB#ZVwSyP^xv$MX<{Zn2a$Jtc zghX4xA?Zj~Sj_;v!7T$%gI9gdtaVcx9sF&{v+gJ(R~HL|{f9_#vu4!mH+?j4H7t!;SKrxF=GSTEF+CT5z1%<9+NNEE67IIDf% z*Tr9bn`dYd<>hu}-F4p9vNjJ@*oAvGkz8nl+S4~oRFmHCr(RcT^AK5NN=1e^Z3yF% zKjx`br7=>GI6Q~}3VaWs@Bz0wlgKB2I2kY;C{S0*@A%(lDV%<<$6p2nWzEGcjE6ul zTeTTrHx3=oltva5E?7g`$2SZ*nrGdyz2m1cBjQ_BzIQ*-iK=ksRz9JSQIOW50jiKFaOD9FvDZ93VB^!4AJ-+O>18cuL3;2Ov=Nm(RorG*ookI4-Wn+M(SK4rDeq#IE4Lo;eGj(__Erekxub3+w zs|I_}MJWgm$dO>VvlO>TjdxKv(`fG12Red(pByW@F(mp{u{98fv!e-i-v21Pje2FO zfyjX8ZzqVKFupBzo<}ErOgB@R6AqqogfF|nJm)s1cvw>OG{L2)xo_o01(Pa*%q3#7 zDhdWh%)jyAzK{6xCI%(9*>J)dh72I@k43yN%2#U!c=l0^LVD-*c{sZNAeYu&1m%Au z;Goz}Zj64hr!ZLO<2lZ zDPs)S%vkKE(ylaN5<&6nIyH_#3%=Y#61g@x=75&&W3M|MkikA#`E5l&-gH7eYIlJH zD30o1=-_SY%S+G@b4a6|hNWAFAWEvg_$A#O4G;NAePR8>s%T|lJBWvnRM&`!!6ueBr+0LyhTiW@6QogF+ z1rpVhLQnY+s)%sqk+(eFKFiyqBCeRQzh{rUcg|lQ1sKaz$k)(0eJ;ZPxi~T@m)R=< ze6;C1Ty*5^8L2qB3Mc{b`fKNxC9lGpf^FW3f?6IUmM#NAGh(=Ci^O=1(AERh$1}UD zR5q+CY;~JnLRh}1P0JB&WFE>8pVl42Srj|ALVI=!;}B+y*c9D2R5V5k2Wq2rm;i<3 zy3i9!3%W+_^Lpnss4$W~kbTzSV)p)}@hE;6V=^KJnUcjs>~_$pv4dMMhm6*Tq*fbb zR};63xJin+kq(eucbmW?77}7Sp3YB+IgG(~B!NwkRKf9JK3P{2gl0b(MsKaCEBuC8 z0Mx#VBe!#iSzQ$%|82Kex<@1goxqwhIJk6jH4UC(wa=A4%3fCo!fc)fqXPW$d5jg%7Vs_6B*?jJfxoV>*=J7T{C+6S&d+=Rte0xV6^(>G_Sva9mMGQxu{B zyk2%0&IS*_l%GuNf}&IVHSrddl#+CQak#kS-uIEeQE(4JN{dmw`IfQ~|AZf(o8j`Y z=A~Xg%=>Csv)@;9!UEU3eB{C&Vu=~dfOiK)0hK73(t?nXBJ_esO+PrU1E8> zNK+=B_8uowLGp;KtAxmgACSuetP~boPO@ycUYp>!(645)bSVTeou!mE<5|1j&Rl6PX4swo^E0Y!yRd+!k$lgfVL*q;N2P!2gg6fNstIq6`4Qe<=j0 ze^2X5$!VgNhTgX3#^$!sj>g{R#mXqo0iJ4CTj%bsY04EC*e63H@+iP>FNBoNQE1C+vj?@BrNP#c5Y5JX}#% z8Ajo8x}Ci&Fj@`veE3qHMKh5SH{n*MDB#0|EcepPi=m^!n7P*3nNjobfH3~}iscry zE1amuk|aof(WXzLuHp9~fc!kh@B=m|rosx;v>SD-?$;nP)VrXJ^Q31mgjx!G^t?4z z`a0XDu~qWxVG@uizsbS>5{)%wNHr8pSupAQXpo|Hf%%T>wsVR2&)#@`PFzPt{c^nN zbK^&&BYu`BVo?zIUjI&04>E)I$HCY{HZ}Z%Gt@JZGHx<{g}`;9ZC|i1bUXj)lDOC{ zOP`2F^^1n!OL2f;PeEh#5AV@&EZFYM&k~197il%}>G#y$#@eT^g{c=oF0lRiVK5-D zjzce1#4d)CX2sq&a#9?`!xFx~aTYN)2X*}LGz9&547-hUN}~qDu>6EOm)~&Dhp5LSUv$Ji|AaPd*36 z#eh|ee6T`czeAGrLi5GytmG26FXoPM3K~^GaUj4vl_a<(+0(>ddFGHgt{B${jCVG7 z@j)UMi(~m;;-TYsYM+Ag#TC)XC&xSMgbEy!1+ULUM^P6Z1Ss)&A~N@+A6(3ReiYi+ znCNKZ6ApK78o0~hM>cvxdpfS3pBSq@N{1_kkBh2986~3L4w2n!R z{ml!c9053sfF!7e}zmce+e(NMFFb`I{AeB^qsNIx#kPhls<4g+Sz_Dp72@J zLLO#EnHtgG;p?@d>HGEaSNn0T ztt-%yupZZ(GyS?BNQju*SQTxEzHT5EK%iKrIIU)5M`XHiuUGTesCy#NY5rI-_?QlC zjV0S?x4`PPJ$0=wq?Kxs$Bj?VyvoYSxptRnbJWn+~1 zy!KU&1ic(Bw1?@?AjRM(ol#&vL?(X53VSV9T+}-k#@3v+O<%zf^5A)W1r2`%jsJK_ zK+;;(`={6TO5@cG)kF76qTauVPbbJu->5kTwidAJgtr`vEd%QL}{c z!H61-Mn-uKLHY1kCt~VB5~APuP!0u;y0k;WA&^NmE%>1irsW@d`@1F)+`~YaQ2y$Q z$@+G3proNuC+ShUuYy}xc;(21D#k9RVCebsRtHW5R)(n)bBS8z9_omW!% zL-18J@o_?4%_qBZI5w^+$`;5nyFO;?=nvPzF{CVC782czm`53qNS)F^F8()UuUCUi zW!39<-xio7gqF_l(rb%|8sn3?6v(a?yau);V6wd(;-ed0oTB(B%XRu>GWY!(>Fv{-9wl%hRg?a9S-&2z~PlJS`P7RJ|pbCS!hh_Xw_`~TRmn$_$cJ*}S z>F4uD>KC+qoMV)fqO^WiXZhEjd#m^GeD{D+U?cTM5k%y5XiJ_Zrqf*5cVA#8#d!l| zFt;jvgHDt;4P=v!j}M5xcu(&pLum9DCk24`P2k`P7jJw&iHxk|ZG3|_AKZk1iMFD_ z2!4Ac2qLS|rzK_>nAT{>{y9T^lYEd|d3x%sEi6`H!Oq$JtUWgcCTbxx22Yo0E0nV()6D1x=+7cnv+aIiyKDv%C7elajqa3< zM4yF;OCC+SI?smv7lp{!)2`iw6?&^;Y~L1$M=Akxr5B;ZLSJQrQdvy7s5yCkNhk@A z(r>}fM4@b12I<+cHvy|Kb9OrslLW;#;iiw6W8Z;CR+L7+j(FxOxaAHJkwn@5?lDu3 z!L|VtCv$p5OXvc4WacF=^~b(94df;FHr~6JpdKDmXKPN2Ed9XEg{yb@iYg~J7y0o_ z89z&$+cuUs@S`lSTv(F@u)Oe)q0W(ugzL9JkC=p12P*B0)BtchLIC{uI|{2P6s2x< z?1I_JOTdf&LB>RNIaT=WVP}@D3>5K~%$JYzgz<}!pV>mOKR>s|_x1Fc%BMSj@7S*h z_*qhzAS$nP7J2_*M%qMt7Yo%sbETOdiuzka^R<4ZLB{{R`Kuxl_NktJQ+=r3B@VTr z$bt;95(F%zzH1^rbCrdm5_M1i@s5WPY_k(HYIlTbPMX)8UJTX6g`~RV%sihOD@YGV zaO}Q#Nf{?$M&q-rKpI-L4YrBDal)^|QTKA)7|qd%SNUBLfP7(EzDt9t4rnnesxoS5 zpZNIGMLZUCTt>Dp?92e%db4PlzU4!UTQEsZ0eOVjmpCH+u#8q-?)NzV`xx6loqMJWYE1+VuF7)@t*I#Kj-rv#9tqi44BM6=m zP~B-ksrYA;vbuw}6H^wi+ouK~L?F1XolnL8teJ)V@J!lxOsSiEl|wXFic0X$l}N|F z@zri1aBOhqY||NIW4S3v=J~eGF8ug8qdQQh!$vduB==9L+JG)NcWxoGW9B6}0yVVg zk^i&6Zi+p>Jl%z4^BSdC-VwJa|01JrFE*5V)j`>_}`kSAG z@RIMWsRcvnCm9+_o#@3U`Tcb| z_1bQw$o+ALy16?JIc~VuMHMLjX(ZT$wvBsDqa8F0Jus0x{7cC#f(BMK&k-9Y{-5Qq z+Sjb_)B%D8cbowmr%j7a7LAm|1mBD-7X30H+a(z#vUj+pu6$Xz z-FlC|I?H2zm+goP9C7E)1G7qvHcM{%{8QlWR-Av5g@tz^HqDA`M&VfPZ%2a!__DWWKFp$5Udd7z(!i)c#~t zS!x0Qwq;@R(`5Gg3iJT1J6G$=vFPh>OTPt*2F#&mcrxYSLP_o!Nw&TGSzA|+Q&2Sf ztr%^2QoracVE`Y4Qs0hZCSC@vo=$wG{dg1<8trsgf@$EGT487CsY;UZyG!asWN3;H zhZ2R!cZS1FSXh}=q;i>t3?}KeDcRVPj(LyW=^OFsFf3QOILJ#4pwTIV3_;Td_GvA+ z!_G#p^w>tSz1#PR0Xs{fs5cRb2WY%sKYG3_dsx9q;crVwN%h?Sc+cpmb4eQ#UCG30 ztIe?adx}uztluQUsiWr&X5%Dl|9Y1f85_`2l(5OofInYH1!f3j<`ZM!Bn z*-f@>8&8~U+cussd9rQSWOH(-_xuk2fsOmK_l4IhGIY8x z*7AZx3GSsvfjPRR7|Jh6&yI}cu_N*68!_kL%Uxki%@=a#XM~pP!M_bTEc`CH|D|Ec zWY}kX*1X<&fE63nwww|+y{UJ}d{rj=>FoCY@uw-ETlzq6nGM3M>M&E9O)hg+4;+O?f- zg<%>${4|jN+zWO$1q+Z#WY{g{U{sO~&1Z>&Ks!=sm-7>u$6;T?hJmIN;n^pe}g)W63(MAGU2%!V`>M`a$$) zxf<*+eM!t{bGJwpkA1t zLx|iGz1ana9d*zB){54fHVY3tKJX5nnS&`QW4IYTN}6JQ8?%Ml3YJc%^y?6T>+R{% z-*&*d;W)1|bg4UDV1bH9k_2Z_hB0`^&;eXlnN-^Nm{9dt6=Z?#J3osrxC6Ddo^rC* z=Fi)|zM_n$UtA?S4O%{inG>&t^d^}Pk3Tqw`2iBb$M zZ@;K4FvII^jH1Bf`O!8v0ALLbr)yk;TRQF=H<<)M4F+tQ;r`;rt&uC3YEm;M zs09&lMRj4T{vkV!VxNInwgeMraNpj8(loNfJ)X&b&?47ffAOy?g_M?r=JN?BDw)|` z5CEFJy>Q8_OA=Kv2X^DtoU`*x!eI$jI{Wq&(OZEd#W$;|or_=qygT;g`wUdg-LBT! zPYDdX`xp27B5b#mmqK5qsU8ISuMm?liJg3iLZi7oX?r()k;8i2bo5a%QJF3MmTxDIn2j z=@p*!RvBH3ffAUodnTt!Jt@gAi@L2l$S=LvpRSe{>z`@i|1zwP{@F^i2ryPk_ppkD zi|)WMg*}nIcRvV^iQCSJ`7sfq#PDQSBOV?6!Tz%r|NQUAeKMnIVGQ&vwJ$v0gqbIO z>>-OWvW{&D_hw^8iQSmJv`Lp?F*+cZPhg)9VmzAY16VbZZE*33B1}oCA!TU}Pojdx zuF)-{^%WX>a->PRn)M#^XZLuO-wF)IMp1a`ZDUiHI-K@$(B`?7!JMM-%7|OO)d+!i zk9-eq``kUMwD6}z+N5=SFK474@Q%Vd*v|){D>&KuvnAUdDYn0OW?FPmn4Pl71#L_b z-+4`I199)axzuq^QD4t)v9s;Vc=dwcT}3Rm%7pzU$}K|*K}Ax56CUx%2o+%5*^S2K;jA1ON01odm6pK#IXbhtd^w5Vx)!+# z6C>}je!=WIQ{~}MjT>vQyz#>R<6&QNm@RSr7I2KzGTP1CZseFt7 z#ZN$LtH`n8qIE9A>MJyBys$R^!44;9w7+@xC)E!V1dDf+c&Svs(<0f~zYGy!U2TEb z!(=kBN_mi4p-|o^5%}vC|LZWSeetAt4T<7_&^g2ZBatPeT&A*+>g$2)c}`ne?Q zfn2O$HUBI-OZ}gH)2>ppkrnU}Mj|ulLW+5$^$I6Fk*ww`$?$^S5A){Sh}O0|wtI=U zd2@i-j+#P{^V51$l93D{5#uliUVQo z5h8cO9t7!gh{s&5D^n2iNLZU59{7xz!Z`AcaNSJ7=JJ}OxX(+6V+wj(ff{BIm|#=w zJ7~l_@#poKD)4Y3Du{l8kvfNuZCmA^o5Wd>LLHrGXnuyiY9EA(wu)$BcaUh*WrS3`Q8U9y{I%h(IjamEg)@_Y|`0x#<`2tE<+s|1%l@ZW8QZVaY zD&gbCO`f{&lJwSObC);2@|jWwToT@+a}c{2Td(w2_f`XERNnT2gOA(sq7T8%gOeFCW=!$j_XKNh+-5hhcB>BH9m&%Z8?>ifdF z_XLhXMpFQ0rB*$%#tK!Re!JXSv|9e>_-b5^S6vB?OlheG zFHh3I)zao;B`jLfW|tG#p6e3r;2~ngLr+$sbjF~9S=HfURy)b|%|Y5W>_A$;1a;52 zg84TSHX|$O+fH;Xi%}+_E#Ql(vZ=wwn&8{g%1I#GZ-Q8C742_omjOo5>&bZMYdF@j zxxsgSG=ANG8dXpM;cAj@j@~7-$O0!;hN^_tvF%E8&?Z`gS8ET92tkNpkcTUQRWR;k z8q9etl24C*ILV|>NVxK_?allp*p~d0R|&7Cpb@`|pB^%&pyXT4+9?yQ{g8gIj~Syt z`ZJ88Y-h^YxM6_+ja^l~f41s{ZbX&4`Sz*_#9jL;=63S#dvc_Qd%=@*9O@5U| zBt~A_^=drr7Ehv=M3qpq*tdnrf!ajJge3Y z9Q5OI{#JTbpUHcyW%2#(TF%CMQ1O?}8QplCCe?P^x1|f&Y<^f1j3&`q{uM{kb!JHN zI2XI2{6uXq2^R_-Rw}5zzj$Prh%G!Fk3>-2FX#8E17OSk+WokCAOS#^byXqLB;roc zgrne2;nGQP;mU?a3!mT8R;RiY4kE3C=XVf3?oWya%qbpj@aI)2K_)rRE&JXpT|G3!1s;GX1bja2O?|TP zbhyiJ+P5lQO;lHBeK|f|58}2z6l1Oa?A(Dp3ZL`+C`1$c0dsZ-D&c zTbX(I>7lZUc})!GoWI0mu}&jbfr8baib7prU``+wjzyN_bF+N_#CKG08$J?u=_4*@ zhDPGH5|`EgWsZp9QuOA#a}Xn&y8`hW?H_AR659j_bGdHWCFun z6<(W(xwq!doma~%yG`)xNkx5yyH09?{U9JB1nf&GD;EP>nD6fqc45Lc&)x&ao>X&7 zkEtIbDY5OKf9vn@_Ae)n%K9udr9b8f)FCKjTZo21>hpcEuSU5%lYzhXPF*h<;K8Nj z4U`qeQ)vPHWnaGaQ|Y#>=iPt#!$3P5^z|x>#F#80{p$C6rm#gKDltDKq3g=Pkw1Ld z;F-7P29&ORFQt{Snq*ED^Tj@584?k>MxJ&L6372Gb@u@CpsVih<|v_hrDOj{4#NHl zQMgS|(sp=dCcK(eU@j<#R9PsZ)Va}LBoJ#FJF7)DZkq;JIK0RXh=kF=UIC+1q3ViT z7X?ujUAfD-08$@#goBc7v*G&wy?#r?CHS=fs~9y>(l5M1jXiJ|g?LghXX4|9zhm;! zc-yi)CO*-D^ZmBO$LE|pI4Hwm=s9H8H9;#)34?a<{O28a@A9CX-kG}!swV>XRGo=^ zs;y~Q(f0YGGEA$kEDp+2^;A0V)-d*J49o+BjmBM zSGUeGFTE;l4s|cMptOdJQ7;ZnRs7vBjjV9oB27oU#0v|W`yKP_mSBJh(EXCV!-XPLq~t%<&za^ z!n{tX_r55%Uyuw&(P1P#>5sr(QCl9w?o>*bgKk;^jm$>^F25?;GvY%&rM6kN%w-9C zA%*35g}nt}+l=oAWytYnEi0e~jKnDAs%lywqQx7y+y&)W-HbhaD_z^>rP4n~h`TjA zcfmuMK7>i%yyfF2pqj@z2v?%#{(2J}(0$7Af{PC`y2rzdU+A5xcW8uKUa6ZB^;OM+ zxEQ^&-TL%W$-veZ%Joh?=_DL4F+E&N*rmO)zrhz0VRk61KP1^UQPKO{R!B-4ipT(; ztQCT&gk2Bw2r5WSU%Orw2iL$vLl5c<1Gc>VcHU(TNTIX=&L^$>BpBd|rbvWM`j(VY zS+kQEkp%R#^sDdfH01h#VG0>#RbPgiSa9W87HXnd(@cx zhOe#NxSi1d@i-v;56kgCj|0q?T)c18! z;4Qf{_H0pCOb9{h<$PJQv6`t-1{g!cIp}P4z2feD$BvwPD6T25j%(n4Yqf2~yOkqV#uk{p>FM(1Si}pV%Gus&jn<5NZoI zK}CYE4w0?$9C<>Ip2kl7!0TqG`^Mo0RKrj>j4@`ePB0$RmC%ArNLkOkSMU;a`ApN% zEJSmG7R@-2BAoz_Twk^uqu2q$-=%t_I0{l@^XDVP&0n84*&0291 z;M(%E`!TPVk1oHW)i9f#t+{0Ba+*gc+djKA4p`ZL(d(B^vN%ZBSncfTrLz!=(Ezihso*2-rZFkGpE(Oi} znT^S>t5u8#1*ojhRKgv{2q2*Yu0&Y9;29)B`@0AqB);s+Y~1_W>1Tq@t7CdWHhc=3 zYCn0aGOk3LZzpEhGW0FWk^9z7C34JG`V@Me4bau%^qrn-tIIvB4w>j_Y|%4=FTCy3>#^3^&(Buyn3kup8nxiOvF>w86;$G$! zeF