From 02afac8f5e09de082d376006983e74617fc42d2d Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:46:00 -0700 Subject: [PATCH 001/106] screen alert sprites --- icons/mob/screen_alert.dmi | Bin 39406 -> 44200 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi index ad6e246e92201a10842ff6a21e11b88aa114ed05..af132dd3a6ac637b3092264e42b786e177d0de29 100644 GIT binary patch literal 44200 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
i7_wKp2*2*ld$qaH3d1shJ}ckdRJIt5zF*8dAdU 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 G@c#i$KQHqD literal 39406 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 aP5}}smdtpLn|~PSkG}3boeC|-$o~UEu9SlS From 510f5a53274713508b36890a7c674ddd76067b0b Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:48:47 -0700 Subject: [PATCH 002/106] xeno building sprites --- icons/Xeno/1x1building.dmi | Bin 3118 -> 5340 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/Xeno/1x1building.dmi b/icons/Xeno/1x1building.dmi index b58708b539aa31da5edf14e33948f1fdb00c3188..d4ac402de1aaf9e1e4dd2882681e95bf1683d02b 100644 GIT binary patch delta 5296 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 delta 3056 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 Date: Mon, 28 Oct 2024 11:53:29 -0700 Subject: [PATCH 003/106] map blips sprite (resized) --- icons/UI_Icons/map_blips.dmi | Bin 4197 -> 4243 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/UI_Icons/map_blips.dmi b/icons/UI_Icons/map_blips.dmi index b38bbe215fb77d0aeb079d3a227e105c75aba046..fa6c1cd80f6e316b911512dc2d0df7f058a1973f 100644 GIT binary patch delta 3830 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 delta 3784 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 y-_ Date: Mon, 28 Oct 2024 11:56:20 -0700 Subject: [PATCH 004/106] buyable icons sprites --- icons/UI_Icons/buyable_icons.dmi | Bin 5471 -> 6882 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/UI_Icons/buyable_icons.dmi b/icons/UI_Icons/buyable_icons.dmi index 44bdaec35b984428ba0337e2143a9d28cfdaa14a..e1ce480200489a6c1837f8371b17c650ec9715e9 100644 GIT binary patch delta 6787 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 delta 5381 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 From fff3169784909a7a394f1a29a6eec8b33af54cd4 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:58:05 -0700 Subject: [PATCH 005/106] define signals --- code/__DEFINES/dcs/signals/signals.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/__DEFINES/dcs/signals/signals.dm b/code/__DEFINES/dcs/signals/signals.dm index b13f9720def45..116a9281068e3 100644 --- a/code/__DEFINES/dcs/signals/signals.dm +++ b/code/__DEFINES/dcs/signals/signals.dm @@ -726,6 +726,11 @@ #define COMSIG_XENOMORPH_LEAP_BUMP "xenomorph_leap_bump" //from /mob/living/carbon/xenomorph/bump +//xeno upgrade chambers +#define COMSIG_UPGRADE_CHAMBER_SURVIVAL "upgrade_chamber_survival" +#define COMSIG_UPGRADE_CHAMBER_ATTACK "upgrade_chamber_attack" +#define COMSIG_UPGRADE_CHAMBER_UTILITY "upgrade_chamber_utility" + //human signals #define COMSIG_CLICK_QUICKEQUIP "click_quickequip" From 442f12ecbf6973b40549286590b3c9d3a2909b3e Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:58:27 -0700 Subject: [PATCH 006/106] define movespeed modification --- code/__DEFINES/movespeed_modification.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm index e62b7e8be31af..a3773061e2fd3 100644 --- a/code/__DEFINES/movespeed_modification.dm +++ b/code/__DEFINES/movespeed_modification.dm @@ -32,6 +32,7 @@ #define MOVESPEED_ID_WARLOCK_CHANNELING "WARLOCK_CHANNELING" #define MOVESPEED_ID_XENO_DREAD "DREADXENO" #define MOVESPEED_ID_BEHEMOTH_PRIMAL_WRATH "BEHEMOTH_PRIMAL_WRATH" +#define MOVESPEED_ID_CELERITY_BUFF "UPGRADE_CHAMBER_CELERITY_BUFF" #define MOVESPEED_ID_SIMPLEMOB_VARSPEED "SIMPLEMOB_VARSPEED_MODIFIER" From efe366ed32dff5ec4b7373e19104587f824e8e54 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:02:06 -0700 Subject: [PATCH 007/106] upgrade_chambers.dm initial --- code/modules/xenomorph/upgrade_chambers.dm | 62 ++++++++++++++++++++++ tgmc.dme | 1 + 2 files changed, 63 insertions(+) create mode 100644 code/modules/xenomorph/upgrade_chambers.dm diff --git a/code/modules/xenomorph/upgrade_chambers.dm b/code/modules/xenomorph/upgrade_chambers.dm new file mode 100644 index 0000000000000..2d8d039f9eacf --- /dev/null +++ b/code/modules/xenomorph/upgrade_chambers.dm @@ -0,0 +1,62 @@ +/obj/structure/xeno/upgrade_chamber + name = "upgrade_chamber" + desc = "You shouldnt see this" + icon = 'icons/Xeno/1x1building.dmi' + icon_state = "shell_chamber" + bound_width = 32 + bound_height = 32 + max_integrity = 500 + resistance_flags = UNACIDABLE | DROPSHIP_IMMUNE + xeno_structure_flags = IGNORE_WEED_REMOVAL | CRITICAL_STRUCTURE + +/obj/structure/xeno/upgrade_chamber/Initialize(mapload, _hivenumber) + . = ..() + SSminimaps.add_marker(src, MINIMAP_FLAG_XENO, image('icons/UI_icons/map_blips.dmi', null, "upgrade_chamber", ABOVE_FLOAT_LAYER)) + +/obj/structure/xeno/upgrade_chamber/shell + name = "Shell" + desc = "Shell upgrade chamber" + icon_state = "shell_chamber" + +/obj/structure/xeno/upgrade_chamber/shell/Initialize(mapload, _hivenumber) + . = ..() + set_light(3, 1, COLOR_DARK_CYAN) + GLOB.hive_datums[hivenumber].shell_chambers += src + SEND_GLOBAL_SIGNAL(COMSIG_UPGRADE_CHAMBER_SURVIVAL) + +/obj/structure/xeno/upgrade_chamber/shell/Destroy() + GLOB.hive_datums[hivenumber].shell_chambers -= src + SEND_GLOBAL_SIGNAL(COMSIG_UPGRADE_CHAMBER_SURVIVAL) + return ..() + +/obj/structure/xeno/upgrade_chamber/spur + name = "Spur" + desc = "Spur upgrade chamber" + icon_state = "spur_chamber" + +/obj/structure/xeno/upgrade_chamber/spur/Initialize(mapload, _hivenumber) + . = ..() + set_light(3, 1, COLOR_RED) + GLOB.hive_datums[hivenumber].spur_chambers += src + SEND_GLOBAL_SIGNAL(COMSIG_UPGRADE_CHAMBER_ATTACK) + +/obj/structure/xeno/upgrade_chamber/spur/Destroy() + GLOB.hive_datums[hivenumber].spur_chambers -= src + SEND_GLOBAL_SIGNAL(COMSIG_UPGRADE_CHAMBER_ATTACK) + return ..() + +/obj/structure/xeno/upgrade_chamber/veil + name = "Veil" + desc = "Veil upgrade chamber" + icon_state = "veil_chamber" + +/obj/structure/xeno/upgrade_chamber/veil/Initialize(mapload, _hivenumber) + . = ..() + set_light(3, 1, COLOR_LIME) + GLOB.hive_datums[hivenumber].veil_chambers += src + SEND_GLOBAL_SIGNAL(COMSIG_UPGRADE_CHAMBER_UTILITY) + +/obj/structure/xeno/upgrade_chamber/veil/Destroy() + GLOB.hive_datums[hivenumber].veil_chambers -= src + SEND_GLOBAL_SIGNAL(COMSIG_UPGRADE_CHAMBER_UTILITY) + return ..() diff --git a/tgmc.dme b/tgmc.dme index ba52254287374..ae7f61704a3d3 100644 --- a/tgmc.dme +++ b/tgmc.dme @@ -2279,6 +2279,7 @@ #include "code\modules\xenomorph\spawner.dm" #include "code\modules\xenomorph\trap.dm" #include "code\modules\xenomorph\tunnel.dm" +#include "code\modules\xenomorph\upgrade_chambers.dm" #include "code\modules\xenomorph\xeno_turret.dm" #include "code\modules\xenomorph\xenoplant.dm" #include "code\modules\xenomorph\xenotowers.dm" From 4ed11354a47c2d0a8b09a50b439432413b5b0b01 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:13:35 -0700 Subject: [PATCH 008/106] hive datum initial --- .../mob/living/carbon/xenomorph/hive_datum.dm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm index 2accf2293d193..bb389e868be67 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm @@ -24,6 +24,13 @@ var/list/obj/structure/xeno/pherotower/pherotowers = list() ///list of hivemind cores var/list/obj/structure/xeno/hivemindcore/hivemindcores = list() + ///list of shell upgrade chambers + var/list/obj/structure/xeno/upgrade_chamber/shell/shell_chambers = list() + ///list of spur upgrade chambers + var/list/obj/structure/xeno/upgrade_chamber/spur/spur_chambers = list() + ///list of veil upgrade chambers + var/list/obj/structure/xeno/upgrade_chamber/veil/veil_chambers = list() + var/tier3_xeno_limit var/tier2_xeno_limit /// Queue of all clients wanting to join xeno side @@ -122,6 +129,13 @@ // Pheromone towers for(var/obj/structure/xeno/pherotower/tower AS in GLOB.hive_datums[hivenumber].pherotowers) .["hive_structures"] += list(get_structure_packet(tower)) + // Upgrade chambers + for(var/obj/structure/xeno/upgrade_chamber/shell/chamber AS in GLOB.hive_datums[hivenumber].shell_chambers) + .["hive_structures"] += list(get_structure_packet(chamber)) + for(var/obj/structure/xeno/upgrade_chamber/spur/chamber AS in GLOB.hive_datums[hivenumber].spur_chambers) + .["hive_structures"] += list(get_structure_packet(chamber)) + for(var/obj/structure/xeno/upgrade_chamber/veil/chamber AS in GLOB.hive_datums[hivenumber].veil_chambers) + .["hive_structures"] += list(get_structure_packet(chamber)) // Hivemind cores for(var/obj/structure/xeno/hivemindcore/core AS in GLOB.hive_datums[hivenumber].hivemindcores) .["hive_structures"] += list(get_structure_packet(core)) From 7fc229796db6f9a5a7d042d111752e12ec65d9ef Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:23:21 -0700 Subject: [PATCH 009/106] grammar / comment changes --- code/__DEFINES/dcs/signals/signals.dm | 2 +- code/modules/mob/living/carbon/xenomorph/hive_datum.dm | 6 +++--- code/modules/xenomorph/upgrade_chambers.dm | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/code/__DEFINES/dcs/signals/signals.dm b/code/__DEFINES/dcs/signals/signals.dm index 116a9281068e3..2c5b98718111a 100644 --- a/code/__DEFINES/dcs/signals/signals.dm +++ b/code/__DEFINES/dcs/signals/signals.dm @@ -726,7 +726,7 @@ #define COMSIG_XENOMORPH_LEAP_BUMP "xenomorph_leap_bump" //from /mob/living/carbon/xenomorph/bump -//xeno upgrade chambers +// Xeno xpgrade chambers #define COMSIG_UPGRADE_CHAMBER_SURVIVAL "upgrade_chamber_survival" #define COMSIG_UPGRADE_CHAMBER_ATTACK "upgrade_chamber_attack" #define COMSIG_UPGRADE_CHAMBER_UTILITY "upgrade_chamber_utility" diff --git a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm index bb389e868be67..a7c424e2e877e 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm @@ -24,11 +24,11 @@ var/list/obj/structure/xeno/pherotower/pherotowers = list() ///list of hivemind cores var/list/obj/structure/xeno/hivemindcore/hivemindcores = list() - ///list of shell upgrade chambers + /// List of shell upgrade chambers. var/list/obj/structure/xeno/upgrade_chamber/shell/shell_chambers = list() - ///list of spur upgrade chambers + /// List of spur upgrade chambers. var/list/obj/structure/xeno/upgrade_chamber/spur/spur_chambers = list() - ///list of veil upgrade chambers + /// List of veil upgrade chambers. var/list/obj/structure/xeno/upgrade_chamber/veil/veil_chambers = list() var/tier3_xeno_limit diff --git a/code/modules/xenomorph/upgrade_chambers.dm b/code/modules/xenomorph/upgrade_chambers.dm index 2d8d039f9eacf..719d05adb0a09 100644 --- a/code/modules/xenomorph/upgrade_chambers.dm +++ b/code/modules/xenomorph/upgrade_chambers.dm @@ -1,6 +1,6 @@ /obj/structure/xeno/upgrade_chamber - name = "upgrade_chamber" - desc = "You shouldnt see this" + name = "upgrade chamber" + desc = "You shouldn't see this!" icon = 'icons/Xeno/1x1building.dmi' icon_state = "shell_chamber" bound_width = 32 @@ -14,7 +14,7 @@ SSminimaps.add_marker(src, MINIMAP_FLAG_XENO, image('icons/UI_icons/map_blips.dmi', null, "upgrade_chamber", ABOVE_FLOAT_LAYER)) /obj/structure/xeno/upgrade_chamber/shell - name = "Shell" + name = "Shell Chamber" desc = "Shell upgrade chamber" icon_state = "shell_chamber" @@ -30,7 +30,7 @@ return ..() /obj/structure/xeno/upgrade_chamber/spur - name = "Spur" + name = "Spur Chamber" desc = "Spur upgrade chamber" icon_state = "spur_chamber" @@ -46,7 +46,7 @@ return ..() /obj/structure/xeno/upgrade_chamber/veil - name = "Veil" + name = "Veil Chamber" desc = "Veil upgrade chamber" icon_state = "veil_chamber" From ceebcd2a55f7637b88261046eb58689319fc14c5 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:24:44 -0700 Subject: [PATCH 010/106] define biomass --- code/modules/mob/living/carbon/xenomorph/xeno_defines.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index 624a032f869d3..03f81d4326ae8 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -347,6 +347,8 @@ GLOBAL_LIST_INIT(strain_list, init_glob_strain_list()) ///Will increase by 10 every decisecond if under 0. ///Increases by xeno_caste.regen_ramp_amount every decisecond. If you want to balance this, look at the xeno_caste defines mentioned above. var/regen_power = 0 + /// The amount of biomass stored. Used for Chamber Upgrades. + var/biomass = 0 var/zoom_turf = null From dac3515af77f796ea8403f54996abfe2324a0e39 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:25:48 -0700 Subject: [PATCH 011/106] carry over biomass over evo --- code/modules/mob/living/carbon/xenomorph/evolution.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/evolution.dm b/code/modules/mob/living/carbon/xenomorph/evolution.dm index 6cfccda4b9fb6..06b4f9a38a7af 100644 --- a/code/modules/mob/living/carbon/xenomorph/evolution.dm +++ b/code/modules/mob/living/carbon/xenomorph/evolution.dm @@ -173,6 +173,9 @@ new_xeno.hive?.update_ruler() // Since ruler wasn't set during initialization, update ruler now. transfer_observers_to(new_xeno) + // Carry over the biomass + new_xeno.biomass = biomass + if(new_xeno.health - getBruteLoss(src) - getFireLoss(src) > 0) //Cmon, don't kill the new one! Shouldnt be possible though new_xeno.bruteloss = bruteloss //Transfers the damage over. new_xeno.fireloss = fireloss //Transfers the damage over. From ead6f83e280abe8b446620faa1525b3ef2fc0937 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:26:58 -0700 Subject: [PATCH 012/106] status effects --- code/datums/status_effects/xeno_buffs.dm | 429 +++++++++++++++++++++++ 1 file changed, 429 insertions(+) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 58b9b0963b79a..ebdb34844a251 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -865,3 +865,432 @@ xeno_owner.xeno_melee_damage_modifier -= modifier xeno_owner.remove_filter("frenzy_screech_outline") return ..() + + +// *************************************** +// *********** Upgrade Chambers Buffs - Survival +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_carapace + name = "Carapace" + desc = "Armor increased." + icon_state = "xenobuff_carapace" + +/datum/status_effect/upgrade_carapace + id = "upgrade_carapace" + duration = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/upgrade_carapace + var/mob/living/carbon/xenomorph/buff_owner + var/armor_buff_per_chamber = 5 + var/chamber_scaling = 0 + +/datum/status_effect/upgrade_carapace/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) + chamber_scaling = length(buff_owner.hive.shell_chambers) + buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(armor_buff_per_chamber * chamber_scaling) + return TRUE + +/datum/status_effect/upgrade_carapace/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) + buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(-armor_buff_per_chamber * chamber_scaling) + return ..() + +/datum/status_effect/upgrade_carapace/proc/update_buff() + SIGNAL_HANDLER + buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(armor_buff_per_chamber * (length(buff_owner.hive.shell_chambers) - chamber_scaling)) + chamber_scaling = length(buff_owner.hive.shell_chambers) + +// *************************************** +// *************************************** +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_regeneration + name = "Regeneration" + desc = "Regeneration increased." + icon_state = "xenobuff_regeneration" + +/datum/status_effect/upgrade_regeneration + id = "upgrade_regeneration" + duration = -1 + tick_interval = 5 SECONDS + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/upgrade_regeneration + var/mob/living/carbon/xenomorph/buff_owner + var/regen_buff_per_chamber = 0.05 + var/sunder_regen_per_chamber = 0.33 + var/chamber_scaling = 0 + +/datum/status_effect/upgrade_regeneration/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + chamber_scaling = length(buff_owner.hive.shell_chambers) + return TRUE + +/datum/status_effect/upgrade_regeneration/tick() + chamber_scaling = length(buff_owner.hive.shell_chambers) + if(chamber_scaling > 0) + var/amount = buff_owner.maxHealth * regen_buff_per_chamber * chamber_scaling * (1 + buff_owner.recovery_aura * 0.05) + HEAL_XENO_DAMAGE(buff_owner, amount, FALSE) + buff_owner.adjust_sunder(-sunder_regen_per_chamber * chamber_scaling) + buff_owner.updatehealth() + return ..() + +// *************************************** +// *************************************** +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_vampirism + name = "Vampirism" + desc = "Leech from attacks." + icon_state = "xenobuff_vampirism" + +/datum/status_effect/upgrade_vampirism + id = "upgrade_vampirism" + duration = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/upgrade_vampirism + var/mob/living/carbon/xenomorph/buff_owner + var/leech_buff_per_chamber = 0.033 + var/chamber_scaling = 0 + +/datum/status_effect/upgrade_vampirism/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) + RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_slash)) + chamber_scaling = isxenoravager(buff_owner) ? (length(buff_owner.hive.shell_chambers) * 0.5) : length(buff_owner.hive.shell_chambers) + return TRUE + +/datum/status_effect/upgrade_vampirism/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING) + return ..() + +/datum/status_effect/upgrade_vampirism/proc/update_buff() + SIGNAL_HANDLER + chamber_scaling = isxenoravager(buff_owner) ? (length(buff_owner.hive.shell_chambers) * 0.5) : length(buff_owner.hive.shell_chambers) + +/datum/status_effect/upgrade_vampirism/proc/on_slash(datum/source, mob/living/target) + SIGNAL_HANDLER + if(target.stat == DEAD) + return + if(!ishuman(target)) + return + var/bruteloss_healed = buff_owner.maxHealth * leech_buff_per_chamber * chamber_scaling + var/fireloss_healed = clamp(bruteloss_healed - buff_owner.bruteloss, 0, bruteloss_healed) + buff_owner.adjustBruteLoss(-bruteloss_healed) + buff_owner.adjustFireLoss(-fireloss_healed) + buff_owner.updatehealth() + +// *************************************** +// *********** Upgrade Chambers Buffs - Attack +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_celerity + name = "Celerity" + desc = "Run faster." + icon_state = "xenobuff_attack" + +/datum/status_effect/upgrade_celerity + id = "upgrade_celerity" + duration = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/upgrade_celerity + var/mob/living/carbon/xenomorph/buff_owner + var/speed_buff_per_chamber = 0.1 + var/chamber_scaling = 0 + +/datum/status_effect/upgrade_celerity/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) + chamber_scaling = length(buff_owner.hive.spur_chambers) + buff_owner.add_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF, TRUE, 0, NONE, TRUE, -speed_buff_per_chamber * chamber_scaling) + return TRUE + +/datum/status_effect/upgrade_celerity/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK) + buff_owner.remove_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF) + return ..() + +/datum/status_effect/upgrade_celerity/proc/update_buff() + SIGNAL_HANDLER + chamber_scaling = length(buff_owner.hive.spur_chambers) + buff_owner.add_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF, TRUE, 0, NONE, TRUE, -speed_buff_per_chamber * chamber_scaling) + +// *************************************** +// *************************************** +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_adrenaline + name = "Adrenaline" + desc = "Regenerate plasma." + icon_state = "xenobuff_attack" + +/datum/status_effect/upgrade_adrenaline + id = "upgrade_adrenaline" + duration = -1 + status_type = STATUS_EFFECT_UNIQUE + tick_interval = 5 SECONDS + alert_type = /atom/movable/screen/alert/status_effect/upgrade_adrenaline + var/mob/living/carbon/xenomorph/buff_owner + var/plasma_regen_buff_per_chamber = 0.12 + var/percent_buff_per_chamber = 0.02 + var/chamber_scaling = 0 + +/datum/status_effect/upgrade_adrenaline/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + chamber_scaling = length(buff_owner.hive.spur_chambers) + return TRUE + +/datum/status_effect/upgrade_adrenaline/tick() + if(HAS_TRAIT(buff_owner, TRAIT_NOPLASMAREGEN)) + return + chamber_scaling = length(buff_owner.hive.spur_chambers) + if(chamber_scaling > 0) + buff_owner.gain_plasma(buff_owner.xeno_caste.plasma_gain * plasma_regen_buff_per_chamber * chamber_scaling * (1 + buff_owner.recovery_aura * 0.05) + (buff_owner.xeno_caste.plasma_max * percent_buff_per_chamber * chamber_scaling)) + +// *************************************** +// *************************************** +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_crush + name = "Crush" + desc = "Additional damage to objects." + icon_state = "xenobuff_attack" + +/datum/status_effect/upgrade_crush + id = "upgrade_crush" + duration = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/upgrade_crush + var/mob/living/carbon/xenomorph/buff_owner + var/penetration_buff_per_chamber = 15 + var/chamber_scaling = 0 + +/datum/status_effect/upgrade_crush/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) + RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_OBJ, PROC_REF(on_obj_attack)) + chamber_scaling = length(buff_owner.hive.spur_chambers) + return TRUE + +/datum/status_effect/upgrade_crush/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK) + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_OBJ) + return ..() + +/datum/status_effect/upgrade_crush/proc/update_buff() + SIGNAL_HANDLER + chamber_scaling = length(buff_owner.hive.spur_chambers) + +/datum/status_effect/upgrade_crush/proc/on_obj_attack(datum/source, obj/attacked) + SIGNAL_HANDLER + if(attacked.resistance_flags & XENO_DAMAGEABLE) + attacked.take_damage(buff_owner.xeno_caste.melee_damage, armour_penetration = (penetration_buff_per_chamber * chamber_scaling)) + +// *************************************** +// *********** Upgrade Chambers Buffs - Utility +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_toxin + name = "Toxin" + desc = "Inject toxin on attack." + icon_state = "xenobuff_generic" + +/atom/movable/screen/alert/status_effect/upgrade_toxin/Click() + var/static/list/upgrade_toxin_images_list = list( + DEFILER_OZELOMELYN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_OZELOMELYN), + DEFILER_HEMODILE = image('icons/Xeno/actions.dmi', icon_state = DEFILER_HEMODILE), + DEFILER_TRANSVITOX = image('icons/Xeno/actions.dmi', icon_state = DEFILER_TRANSVITOX), + DEFILER_NEUROTOXIN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_NEUROTOXIN), + DEFILER_ACID = image('icons/Xeno/actions.dmi', icon_state = DEFILER_ACID), + ) + var/datum/status_effect/upgrade_toxin/effect = attached_effect + if(effect.buff_owner.incapacitated(TRUE)) + to_chat(usr, span_warning("Cant do that right now!")) + return + var/datum/reagent/toxin/toxin_choice = show_radial_menu(effect.buff_owner, effect.buff_owner, upgrade_toxin_images_list, radius = 35, require_near = TRUE) + if(!toxin_choice) + return + for(var/toxin in effect.selectable_reagents) + var/datum/reagent/R = GLOB.chemical_reagents_list[toxin] + if(R.name == toxin_choice) + effect.injected_reagent = R.type + break + effect.buff_owner.balloon_alert(effect.buff_owner, "[toxin_choice]") + +/datum/status_effect/upgrade_toxin + id = "upgrade_toxin" + duration = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/upgrade_toxin + var/mob/living/carbon/xenomorph/buff_owner + var/toxin_amount_per_chamber = 1 + var/chamber_scaling = 0 + var/datum/reagent/toxin/injected_reagent = /datum/reagent/toxin/xeno_neurotoxin + var/list/selectable_reagents = list( + /datum/reagent/toxin/xeno_ozelomelyn, + /datum/reagent/toxin/xeno_hemodile, + /datum/reagent/toxin/xeno_transvitox, + /datum/reagent/toxin/xeno_neurotoxin, + /datum/reagent/toxin/acid, + ) + +/datum/status_effect/upgrade_toxin/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) + RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_slash)) + chamber_scaling = length(buff_owner.hive.veil_chambers) + return TRUE + +/datum/status_effect/upgrade_toxin/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING) + return ..() + +/datum/status_effect/upgrade_toxin/proc/update_buff() + SIGNAL_HANDLER + chamber_scaling = length(buff_owner.hive.veil_chambers) + +/datum/status_effect/upgrade_toxin/proc/on_slash(datum/source, mob/living/target) + SIGNAL_HANDLER + if(target.stat == DEAD) + return + if(!ishuman(target)) + return + if(!target?.can_sting()) + return + var/mob/living/carbon/carbon_target = target + chamber_scaling = length(buff_owner.hive.veil_chambers) + carbon_target.reagents.add_reagent(injected_reagent, 1 + toxin_amount_per_chamber * chamber_scaling) + +// *************************************** +// *************************************** +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_pheromones + name = "Pheromones" + desc = "Allows to emit pheromones." + icon_state = "xenobuff_phero" + +/atom/movable/screen/alert/status_effect/upgrade_pheromones/Click() + var/datum/status_effect/upgrade_pheromones/effect = attached_effect + if(effect.buff_owner.incapacitated(TRUE)) + to_chat(usr, span_warning("Cant do that right now!")) + return + var/phero_choice = show_radial_menu(effect.buff_owner, effect.buff_owner, GLOB.pheromone_images_list, radius = 35, require_near = TRUE) + if(!phero_choice) + return + QDEL_NULL(effect.current_aura) + effect.emitted_aura = phero_choice + effect.current_aura = SSaura.add_emitter(effect.buff_owner, phero_choice, 6 + effect.phero_power_per_chamber * effect.chamber_scaling * 2, effect.phero_power_base + effect.phero_power_per_chamber * effect.chamber_scaling, -1, FACTION_XENO, effect.buff_owner.hivenumber) + +/datum/status_effect/upgrade_pheromones + id = "upgrade_pheromones" + duration = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/upgrade_pheromones + var/mob/living/carbon/xenomorph/buff_owner + var/datum/aura_bearer/current_aura + var/phero_power_per_chamber = 1 + var/phero_power_base = 1 + var/chamber_scaling = 0 + var/emitted_aura = AURA_XENO_RECOVERY + +/datum/status_effect/upgrade_pheromones/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) + chamber_scaling = length(buff_owner.hive.veil_chambers) + current_aura = SSaura.add_emitter(buff_owner, AURA_XENO_RECOVERY, 6 + phero_power_per_chamber * chamber_scaling * 2, phero_power_base + phero_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) + return TRUE + +/datum/status_effect/upgrade_pheromones/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) + if(current_aura) + current_aura.stop_emitting() + return ..() + +/datum/status_effect/upgrade_pheromones/proc/update_buff() + SIGNAL_HANDLER + chamber_scaling = length(buff_owner.hive.veil_chambers) + QDEL_NULL(current_aura) + current_aura = SSaura.add_emitter(buff_owner, emitted_aura, 6 + phero_power_per_chamber * chamber_scaling * 2, phero_power_base + phero_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) + +// *************************************** +// *************************************** +// *************************************** +/atom/movable/screen/alert/status_effect/upgrade_trail + name = "Trail" + desc = "We leave an acid trail behind." + icon_state = "xenobuff_generic" + +/atom/movable/screen/alert/status_effect/upgrade_trail/Click() + var/datum/status_effect/upgrade_trail/effect = attached_effect + if(effect.buff_owner.incapacitated(TRUE)) + to_chat(usr, span_warning("Cant do that right now!")) + return + var/i = effect.selectable_trails.Find(effect.selected_trail) + if(length(effect.selectable_trails) == i) + effect.selected_trail = effect.selectable_trails[1] + else + effect.selected_trail = effect.selectable_trails[i+1] + effect.buff_owner.balloon_alert(effect.buff_owner, "[effect.selected_trail.name]") + +/datum/status_effect/upgrade_trail + id = "upgrade_trail" + duration = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/upgrade_trail + var/mob/living/carbon/xenomorph/buff_owner + var/obj/selected_trail = /obj/effect/xenomorph/spray + var/base_chance = 25 + var/chance_per_chamber = 25 + var/chamber_scaling = 0 + var/list/selectable_trails = list( + /obj/effect/xenomorph/spray, + /obj/alien/resin/sticky/thin, + ) + +/datum/status_effect/upgrade_trail/on_apply() + if(!isxeno(owner)) + return FALSE + buff_owner = owner + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) + RegisterSignal(buff_owner, COMSIG_MOVABLE_MOVED, PROC_REF(do_acid_trail)) + chamber_scaling = length(buff_owner.hive.veil_chambers) + return TRUE + +/datum/status_effect/upgrade_trail/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) + UnregisterSignal(buff_owner, COMSIG_MOVABLE_MOVED) + return ..() + +/datum/status_effect/upgrade_trail/proc/update_buff() + SIGNAL_HANDLER + chamber_scaling = length(buff_owner.hive.veil_chambers) + +/datum/status_effect/upgrade_trail/proc/do_acid_trail() + SIGNAL_HANDLER + if(buff_owner.incapacitated(TRUE)) + return + if(prob(base_chance + chance_per_chamber * chamber_scaling)) + var/turf/T = get_turf(buff_owner) + if(T.density || isspaceturf(T)) + return + for(var/obj/O in T.contents) + if(is_type_in_typecache(O, GLOB.no_sticky_resin)) + return + if(selected_trail == /obj/effect/xenomorph/spray) + new selected_trail(T, rand(2 SECONDS, 5 SECONDS)) + for(var/obj/O in T) + O.acid_spray_act(buff_owner) + else + new selected_trail(T) From 76e59f2b874b1f6fd5c627512a4eac5da5ab29a4 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:27:38 -0700 Subject: [PATCH 013/106] define xeno upgrades --- code/__DEFINES/xeno.dm | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 87a0bec6b1ff7..0b2ff3bcec6bc 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -210,3 +210,26 @@ GLOBAL_LIST_INIT(xeno_ai_spawnable, list( /// Life runs every 2 seconds, but we don't want to multiply all healing by 2 due to seconds_per_tick #define XENO_PER_SECOND_LIFE_MOD 0.5 + +GLOBAL_LIST_INIT(xeno_survival_upgrades, list( + /datum/status_effect/upgrade_carapace, + /datum/status_effect/upgrade_regeneration, + /datum/status_effect/upgrade_vampirism, +)) + +GLOBAL_LIST_INIT(xeno_attack_upgrades, list( + /datum/status_effect/upgrade_celerity, + /datum/status_effect/upgrade_adrenaline, + /datum/status_effect/upgrade_crush, +)) + +GLOBAL_LIST_INIT(xeno_utility_upgrades, list( + /datum/status_effect/upgrade_toxin, + /datum/status_effect/upgrade_pheromones, + /datum/status_effect/upgrade_trail, +)) + +#define XENO_UPGRADE_BIOMASS_COST_T1 10 +#define XENO_UPGRADE_BIOMASS_COST_T2 15 +#define XENO_UPGRADE_BIOMASS_COST_T3 20 +#define XENO_UPGRADE_BIOMASS_COST_T4 25 From da8450e5079efffddbedffc1444932f7aa83a74d Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:28:06 -0700 Subject: [PATCH 014/106] define status effects --- code/__DEFINES/status_effects.dm | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 93e24916fad5b..1cccff519e472 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -39,6 +39,22 @@ #define STATUS_EFFECT_DRAIN_SURGE /datum/status_effect/drain_surge +#define STATUS_EFFECT_UPGRADE_REGENERATION /datum/status_effect/upgrade_regeneration + +#define STATUS_EFFECT_UPGRADE_VAMPIRISM /datum/status_effect/upgrade_vampirism + +#define STATUS_EFFECT_UPGRADE_CELERITY /datum/status_effect/upgrade_celerity + +#define STATUS_EFFECT_UPGRADE_ADRENALINE /datum/status_effect/upgrade_adrenaline + +#define STATUS_EFFECT_UPGRADE_CRUSH /datum/status_effect/upgrade_crush + +#define STATUS_EFFECT_UPGRADE_TOXIN /datum/status_effect/upgrade_toxin + +#define STATUS_EFFECT_UPGRADE_PHERO /datum/status_effect/upgrade_pheromones + +#define STATUS_EFFECT_UPGRADE_TRAIL /datum/status_effect/upgrade_trail + #define STATUS_EFFECT_MINDMEND /datum/status_effect/mindmeld #define STATUS_EFFECT_REKNIT_FORM /datum/status_effect/reknit_form From 38e6fe048630cbb77b0a50f6465e61f3d88d5c8c Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:29:13 -0700 Subject: [PATCH 015/106] drain/cocoon give biomass --- code/modules/mob/living/carbon/xenomorph/abilities.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index 51c774ef65351..c49117f550b6f 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -1398,6 +1398,7 @@ victim.do_jitter_animation(2) victim.adjustCloneLoss(20) + X.biomass = min(X.biomass + 15, 100) ADD_TRAIT(victim, TRAIT_PSY_DRAINED, TRAIT_PSY_DRAINED) if(HAS_TRAIT(victim, TRAIT_UNDEFIBBABLE)) @@ -1509,6 +1510,7 @@ victim.dead_ticks = 0 ADD_TRAIT(victim, TRAIT_STASIS, TRAIT_STASIS) X.eject_victim(TRUE, starting_turf) + X.biomass = min(X.biomass + 15, 100) if(owner.client) var/datum/personal_statistics/personal_statistics = GLOB.personal_statistics_list[owner.ckey] personal_statistics.cocooned++ From 7f12b3b663bf6213f1e163f18b3a2779af034629 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:30:17 -0700 Subject: [PATCH 016/106] hive upgrades --- .../living/carbon/xenomorph/hive_upgrades.dm | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm index 0e7f79c9bf16f..c26464539101e 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm @@ -264,6 +264,49 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( to_chat(buyer, span_xenowarning("You cannot build in a dense location!")) return FALSE +/datum/hive_upgrade/building/upgrade_chamber + flags_upgrade = ABILITY_NUCLEARWAR + var/max_chambers = 3 + +/datum/hive_upgrade/building/upgrade_chamber/shell + name = "Shell Upgrade Chamber" + desc = "Constructs a chamber that allows xenos to buy survival mutations. Build up to 3 structures to increase mutation power." + icon = "shell" + psypoint_cost = 200 + building_type = /obj/structure/xeno/upgrade_chamber/shell + +/datum/hive_upgrade/building/upgrade_chamber/shell/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) + . = ..() + if(length(buyer.hive.shell_chambers) >= max_chambers) + to_chat(buyer, span_xenowarning("Hive cannot support more than [max_chambers] active shell chambers!")) + return FALSE + +/datum/hive_upgrade/building/upgrade_chamber/spur + name = "Spur Upgrade Chamber" + desc = "Constructs a chamber that allows xenos to buy attack mutations. Build up to 3 structures to increase mutation power." + icon = "spur" + psypoint_cost = 150 + building_type = /obj/structure/xeno/upgrade_chamber/spur + +/datum/hive_upgrade/building/upgrade_chamber/spur/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) + . = ..() + if(length(buyer.hive.spur_chambers) >= max_chambers) + to_chat(buyer, span_xenowarning("Hive cannot support more than [max_chambers] active spur chambers!")) + return FALSE + +/datum/hive_upgrade/building/upgrade_chamber/veil + name = "Veil Upgrade Chamber" + desc = "Constructs a chamber that allows xenos to buy utility mutations. Build up to 3 structures to increase mutation power." + icon = "veil" + psypoint_cost = 100 + building_type = /obj/structure/xeno/upgrade_chamber/veil + +/datum/hive_upgrade/building/upgrade_chamber/veil/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) + . = ..() + if(length(buyer.hive.veil_chambers) >= max_chambers) + to_chat(buyer, span_xenowarning("Hive cannot support more than [max_chambers] active veil chambers!")) + return FALSE + /datum/hive_upgrade/defence category = "Defences" From dff23624418ae9776c37096cf906156be8738577 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:32:02 -0700 Subject: [PATCH 017/106] upgrade menu / topics --- .../mob/living/carbon/xenomorph/xenoprocs.dm | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index a173fb124683d..2ec2ab14926b2 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -84,6 +84,25 @@ // Checks for can use done in overwatch action. SEND_SIGNAL(src, COMSIG_XENOMORPH_WATCHXENO, target) + if(href_list["carapace_buy"]) + remove_apply_upgrades(GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_CARAPACE) + if(href_list["regeneration_buy"]) + remove_apply_upgrades(GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_REGENERATION) + if(href_list["vampirism_buy"]) + remove_apply_upgrades(GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_VAMPIRISM) + if(href_list["celerity_buy"]) + remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_CELERITY) + if(href_list["adrenalin_buy"]) + remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_ADRENALINE) + if(href_list["crush_buy"]) + remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_CRUSH) + if(href_list["toxin_buy"]) + remove_apply_upgrades(GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_TOXIN) + if(href_list["phero_buy"]) + remove_apply_upgrades(GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_PHERO) + if(href_list["trail_buy"]) + remove_apply_upgrades(GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_TRAIL) + ///Send a message to all xenos. Force forces the message whether or not the hivemind is intact. Target is an atom that is pointed out to the hive. Filter list is a list of xenos we don't message. /proc/xeno_message(message = null, span_class = "xenoannounce", size = 5, hivenumber = XENO_HIVE_NORMAL, force = FALSE, atom/target = null, sound = null, apply_preferences = FALSE, filter_list = null, arrow_type, arrow_color, report_distance = FALSE) if(!message) @@ -580,3 +599,81 @@ /mob/living/carbon/xenomorph/on_eord(turf/destination) revive(TRUE) + + +/mob/living/carbon/xenomorph/verb/upgrade_menu() + set name = "Mutations Menu" + set desc = "See current Upgrade Chambers and get mutations for yourself" + set category = "Alien" + + get_upgrades(src) + +/mob/living/carbon/xenomorph/proc/get_upgrades(mob/living/carbon/xenomorph/user) + var/upgrade_price + switch(xeno_caste.tier) + if(XENO_TIER_ONE) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T1 + if(XENO_TIER_TWO) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T2 + if(XENO_TIER_THREE) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T3 + else + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T4 + var/dat = "
" + + dat += "
Active Upgrade Chambers:" + dat += "
Shell : [length(user?.hive?.shell_chambers)] | Spur : [length(user?.hive?.spur_chambers)] | Veil : [length(user?.hive?.veil_chambers)]" + dat += "
Biomass: [user?.biomass] / 100" + + dat += "
" + + dat += "

List of upgrades:
" + var/shell_chambers_built = length(user?.hive?.shell_chambers) + var/spur_chambers_built = length(user?.hive?.spur_chambers) + var/veil_chambers_built = length(user?.hive?.veil_chambers) + dat += "
SURVIVAL
" + dat += "[shell_chambers_built ? "
Carapace " : "
Carapace "] | Cost: [upgrade_price] | Increase our armor." + dat += "[shell_chambers_built ? "
Regeneration " : "
Regeneration "] | Cost: [upgrade_price] | Increase our health regeneration." + dat += "[shell_chambers_built ? "
Vampirism " : "
Vampirism "] | Cost: [upgrade_price] | Leech from our attacks." + dat += "
ATTACK
" + dat += "[spur_chambers_built ? "
Celerity " : "
Celerity "] | Cost: [upgrade_price] | Increase our movement speed." + dat += "[spur_chambers_built ? "
Adrenalin " : "
Adrenalin "] | Cost: [upgrade_price] | Increase our plasma regeneration." + dat += "[spur_chambers_built ? "
Crush " : "
Crush "] | Cost: [upgrade_price] | Increase our damage to objects." + dat += "
UTILITY
" + dat += "[veil_chambers_built ? "
Toxin " : "
Toxin "] | Cost: [upgrade_price] | Inject neurotoxin into the target." + dat += "[veil_chambers_built ? "
Pheromones " : "
Pheromones "] | Cost: [upgrade_price] | Ability to emit pheromones." + dat += "[veil_chambers_built ? "
Trail " : "
Trail "] | Cost: [upgrade_price] | Leave a trail behind." + + var/datum/browser/popup = new(user, "upgrademenu", "
Mutations Menu
", 600, 600) + popup.set_content(dat) + popup.open() + +/mob/living/carbon/xenomorph/proc/remove_apply_upgrades(list/upgrades_to_remove, datum/status_effect/upgrade_to_apply) + if(incapacitated(TRUE)) + to_chat(usr, span_warning("Cant do that right now!")) + return + var/upgrade_price + switch(xeno_caste.tier) + if(XENO_TIER_ONE) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T1 + if(XENO_TIER_TWO) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T2 + if(XENO_TIER_THREE) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T3 + else + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T4 + if(biomass < upgrade_price) + to_chat(usr, span_warning("You dont have enough biomass!")) + return + var/upgrade = locate(upgrade_to_apply) in status_effects + if(upgrade) + to_chat(usr, span_xenonotice("Existing mutation chosen. No biomass spent.")) + DIRECT_OUTPUT(usr, browse(null, "window=["upgrademenu"]")) + return + biomass -= upgrade_price + to_chat(usr, span_xenonotice("Mutation gained.")) + for(var/datum/status_effect/S AS in upgrades_to_remove) + remove_status_effect(S) + do_jitter_animation(500) + apply_status_effect(upgrade_to_apply) + DIRECT_OUTPUT(usr, browse(null, "window=["upgrademenu"]")) From d091ed55e529fafe3bb0fc5c0ab46d2440807bbc Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:32:53 -0700 Subject: [PATCH 018/106] missing status effect (upgrade_carapace) --- code/__DEFINES/status_effects.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 1cccff519e472..7653d303fb077 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -39,6 +39,8 @@ #define STATUS_EFFECT_DRAIN_SURGE /datum/status_effect/drain_surge +#define STATUS_EFFECT_UPGRADE_CARAPACE /datum/status_effect/upgrade_carapace + #define STATUS_EFFECT_UPGRADE_REGENERATION /datum/status_effect/upgrade_regeneration #define STATUS_EFFECT_UPGRADE_VAMPIRISM /datum/status_effect/upgrade_vampirism From bfbce4407de034b00b39a1b836b831ebc50e79e2 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:33:25 -0700 Subject: [PATCH 019/106] we dont have DEFILER_ACID --- code/datums/status_effects/xeno_buffs.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index ebdb34844a251..cf246ed63aee6 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1107,8 +1107,7 @@ DEFILER_OZELOMELYN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_OZELOMELYN), DEFILER_HEMODILE = image('icons/Xeno/actions.dmi', icon_state = DEFILER_HEMODILE), DEFILER_TRANSVITOX = image('icons/Xeno/actions.dmi', icon_state = DEFILER_TRANSVITOX), - DEFILER_NEUROTOXIN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_NEUROTOXIN), - DEFILER_ACID = image('icons/Xeno/actions.dmi', icon_state = DEFILER_ACID), + DEFILER_NEUROTOXIN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_NEUROTOXIN) ) var/datum/status_effect/upgrade_toxin/effect = attached_effect if(effect.buff_owner.incapacitated(TRUE)) From 86b0ee3bda2874a1d1babb1a373ab4b8557e6fb6 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:33:54 -0700 Subject: [PATCH 020/106] flags_upgrade -> gamemode_flags --- code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm index c26464539101e..0f0dd79f7375c 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm @@ -265,7 +265,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( return FALSE /datum/hive_upgrade/building/upgrade_chamber - flags_upgrade = ABILITY_NUCLEARWAR + gamemode_flags = ABILITY_NUCLEARWAR var/max_chambers = 3 /datum/hive_upgrade/building/upgrade_chamber/shell From 75a3300b77b5d4ca6762efc5c6810afdaf9f0abf Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:36:07 -0700 Subject: [PATCH 021/106] untab --- code/datums/status_effects/xeno_buffs.dm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index cf246ed63aee6..e3a6cb8187596 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1104,11 +1104,11 @@ /atom/movable/screen/alert/status_effect/upgrade_toxin/Click() var/static/list/upgrade_toxin_images_list = list( - DEFILER_OZELOMELYN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_OZELOMELYN), - DEFILER_HEMODILE = image('icons/Xeno/actions.dmi', icon_state = DEFILER_HEMODILE), - DEFILER_TRANSVITOX = image('icons/Xeno/actions.dmi', icon_state = DEFILER_TRANSVITOX), - DEFILER_NEUROTOXIN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_NEUROTOXIN) - ) + DEFILER_OZELOMELYN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_OZELOMELYN), + DEFILER_HEMODILE = image('icons/Xeno/actions.dmi', icon_state = DEFILER_HEMODILE), + DEFILER_TRANSVITOX = image('icons/Xeno/actions.dmi', icon_state = DEFILER_TRANSVITOX), + DEFILER_NEUROTOXIN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_NEUROTOXIN) + ) var/datum/status_effect/upgrade_toxin/effect = attached_effect if(effect.buff_owner.incapacitated(TRUE)) to_chat(usr, span_warning("Cant do that right now!")) From ff86716db1366ae796c0e0b66621354824252f2a Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:37:54 -0700 Subject: [PATCH 022/106] correct image path --- code/datums/status_effects/xeno_buffs.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index e3a6cb8187596..8569cf5b42784 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1104,10 +1104,10 @@ /atom/movable/screen/alert/status_effect/upgrade_toxin/Click() var/static/list/upgrade_toxin_images_list = list( - DEFILER_OZELOMELYN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_OZELOMELYN), - DEFILER_HEMODILE = image('icons/Xeno/actions.dmi', icon_state = DEFILER_HEMODILE), - DEFILER_TRANSVITOX = image('icons/Xeno/actions.dmi', icon_state = DEFILER_TRANSVITOX), - DEFILER_NEUROTOXIN = image('icons/Xeno/actions.dmi', icon_state = DEFILER_NEUROTOXIN) + DEFILER_OZELOMELYN = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_OZELOMELYN), + DEFILER_HEMODILE = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_HEMODILE), + DEFILER_TRANSVITOX = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_TRANSVITOX), + DEFILER_NEUROTOXIN = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_NEUROTOXIN) ) var/datum/status_effect/upgrade_toxin/effect = attached_effect if(effect.buff_owner.incapacitated(TRUE)) From 6243f170738e7f1cd520d2409264481f4eb4c548 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:41:53 -0700 Subject: [PATCH 023/106] build below --- code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm index 0f0dd79f7375c..feb00a3b6086f 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm @@ -266,6 +266,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( /datum/hive_upgrade/building/upgrade_chamber gamemode_flags = ABILITY_NUCLEARWAR + building_loc = 0 var/max_chambers = 3 /datum/hive_upgrade/building/upgrade_chamber/shell From aadd6441972bb6c42a7ff92feac4f64b715e811d Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:07:59 -0700 Subject: [PATCH 024/106] typo --- code/modules/mob/living/carbon/xenomorph/xenoprocs.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index 2ec2ab14926b2..bf7b79237d056 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -92,7 +92,7 @@ remove_apply_upgrades(GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_VAMPIRISM) if(href_list["celerity_buy"]) remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_CELERITY) - if(href_list["adrenalin_buy"]) + if(href_list["adrenaline_buy"]) remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_ADRENALINE) if(href_list["crush_buy"]) remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_CRUSH) @@ -637,7 +637,7 @@ dat += "[shell_chambers_built ? "
Vampirism " : "
Vampirism "] | Cost: [upgrade_price] | Leech from our attacks." dat += "
ATTACK
" dat += "[spur_chambers_built ? "
Celerity " : "
Celerity "] | Cost: [upgrade_price] | Increase our movement speed." - dat += "[spur_chambers_built ? "
Adrenalin " : "
Adrenalin "] | Cost: [upgrade_price] | Increase our plasma regeneration." + dat += "[spur_chambers_built ? "
Adrenaline " : "
Adrenaline "] | Cost: [upgrade_price] | Increase our plasma regeneration." dat += "[spur_chambers_built ? "
Crush " : "
Crush "] | Cost: [upgrade_price] | Increase our damage to objects." dat += "
UTILITY
" dat += "[veil_chambers_built ? "
Toxin " : "
Toxin "] | Cost: [upgrade_price] | Inject neurotoxin into the target." From 84e5796c39d643e7d35f3f12703b79bf0dfe7efc Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:31:00 -0700 Subject: [PATCH 025/106] regen phero does not increase plasma regen --- code/datums/status_effects/xeno_buffs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 8569cf5b42784..8125b1aac6e69 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1052,7 +1052,7 @@ return chamber_scaling = length(buff_owner.hive.spur_chambers) if(chamber_scaling > 0) - buff_owner.gain_plasma(buff_owner.xeno_caste.plasma_gain * plasma_regen_buff_per_chamber * chamber_scaling * (1 + buff_owner.recovery_aura * 0.05) + (buff_owner.xeno_caste.plasma_max * percent_buff_per_chamber * chamber_scaling)) + buff_owner.gain_plasma(buff_owner.xeno_caste.plasma_gain * plasma_regen_buff_per_chamber * chamber_scaling + (buff_owner.xeno_caste.plasma_max * percent_buff_per_chamber * chamber_scaling)) // *************************************** // *************************************** From d063ba3f115269417210cdbcf54ca7d308af0ae3 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:31:15 -0700 Subject: [PATCH 026/106] unused selectable --- code/datums/status_effects/xeno_buffs.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 8125b1aac6e69..056c1514f23fa 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1136,8 +1136,7 @@ /datum/reagent/toxin/xeno_ozelomelyn, /datum/reagent/toxin/xeno_hemodile, /datum/reagent/toxin/xeno_transvitox, - /datum/reagent/toxin/xeno_neurotoxin, - /datum/reagent/toxin/acid, + /datum/reagent/toxin/xeno_neurotoxin ) /datum/status_effect/upgrade_toxin/on_apply() From af60348417657640905c41edc7b08e79731a5ab1 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:32:45 -0700 Subject: [PATCH 027/106] reduce to 1-3 from 2-4 --- code/datums/status_effects/xeno_buffs.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 056c1514f23fa..602a6bcdbca03 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1167,7 +1167,9 @@ return var/mob/living/carbon/carbon_target = target chamber_scaling = length(buff_owner.hive.veil_chambers) - carbon_target.reagents.add_reagent(injected_reagent, 1 + toxin_amount_per_chamber * chamber_scaling) + var/amount_to_inject = toxin_amount_per_chamber * chamber_scaling + if(amount_to_inject) + carbon_target.reagents.add_reagent(injected_reagent, amount_to_inject) // *************************************** // *************************************** From bb17a7513ba6c134a6c45d634a34742689ec75de Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:01:47 -0700 Subject: [PATCH 028/106] typo --- code/__DEFINES/dcs/signals/signals.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/__DEFINES/dcs/signals/signals.dm b/code/__DEFINES/dcs/signals/signals.dm index 2c5b98718111a..09f5e157bb96c 100644 --- a/code/__DEFINES/dcs/signals/signals.dm +++ b/code/__DEFINES/dcs/signals/signals.dm @@ -726,7 +726,7 @@ #define COMSIG_XENOMORPH_LEAP_BUMP "xenomorph_leap_bump" //from /mob/living/carbon/xenomorph/bump -// Xeno xpgrade chambers +// Xeno upgrade chambers #define COMSIG_UPGRADE_CHAMBER_SURVIVAL "upgrade_chamber_survival" #define COMSIG_UPGRADE_CHAMBER_ATTACK "upgrade_chamber_attack" #define COMSIG_UPGRADE_CHAMBER_UTILITY "upgrade_chamber_utility" From 525fce6b2ed947cc1f8f8b5866aacc9ba821992f Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:42:02 -0700 Subject: [PATCH 029/106] chamber building costs increase by 100 --- code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm index feb00a3b6086f..ad6ba7cdc2f16 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm @@ -273,7 +273,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( name = "Shell Upgrade Chamber" desc = "Constructs a chamber that allows xenos to buy survival mutations. Build up to 3 structures to increase mutation power." icon = "shell" - psypoint_cost = 200 + psypoint_cost = 300 building_type = /obj/structure/xeno/upgrade_chamber/shell /datum/hive_upgrade/building/upgrade_chamber/shell/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) @@ -286,7 +286,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( name = "Spur Upgrade Chamber" desc = "Constructs a chamber that allows xenos to buy attack mutations. Build up to 3 structures to increase mutation power." icon = "spur" - psypoint_cost = 150 + psypoint_cost = 250 building_type = /obj/structure/xeno/upgrade_chamber/spur /datum/hive_upgrade/building/upgrade_chamber/spur/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) @@ -299,7 +299,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( name = "Veil Upgrade Chamber" desc = "Constructs a chamber that allows xenos to buy utility mutations. Build up to 3 structures to increase mutation power." icon = "veil" - psypoint_cost = 100 + psypoint_cost = 200 building_type = /obj/structure/xeno/upgrade_chamber/veil /datum/hive_upgrade/building/upgrade_chamber/veil/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) From 286fff26a6225a6e3608078c9df53c5948b07573 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:43:11 -0700 Subject: [PATCH 030/106] up biomass cost by 5 --- code/__DEFINES/xeno.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 0b2ff3bcec6bc..95409e6927f1b 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -229,7 +229,7 @@ GLOBAL_LIST_INIT(xeno_utility_upgrades, list( /datum/status_effect/upgrade_trail, )) -#define XENO_UPGRADE_BIOMASS_COST_T1 10 -#define XENO_UPGRADE_BIOMASS_COST_T2 15 -#define XENO_UPGRADE_BIOMASS_COST_T3 20 -#define XENO_UPGRADE_BIOMASS_COST_T4 25 +#define XENO_UPGRADE_BIOMASS_COST_T1 15 +#define XENO_UPGRADE_BIOMASS_COST_T2 20 +#define XENO_UPGRADE_BIOMASS_COST_T3 25 +#define XENO_UPGRADE_BIOMASS_COST_T4 30 From 90f4db161d64f2731ecaa2e481f313f05b437039 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:44:59 -0700 Subject: [PATCH 031/106] carapace: 5 -> 2.5 --- code/datums/status_effects/xeno_buffs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 44ac110a08d21..7dd49be628bac 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -887,7 +887,7 @@ status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_carapace var/mob/living/carbon/xenomorph/buff_owner - var/armor_buff_per_chamber = 5 + var/armor_buff_per_chamber = 2.5 var/chamber_scaling = 0 /datum/status_effect/upgrade_carapace/on_apply() From 33cad2c733a9bb8fac423a93042f110af7f7c935 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:11:56 -0700 Subject: [PATCH 032/106] regeneration rework -> less health, but on life cycle --- code/datums/status_effects/xeno_buffs.dm | 35 +++++++++++++++++------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 7dd49be628bac..f8aef9f088e18 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -920,12 +920,14 @@ /datum/status_effect/upgrade_regeneration id = "upgrade_regeneration" duration = -1 - tick_interval = 5 SECONDS status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_regeneration var/mob/living/carbon/xenomorph/buff_owner - var/regen_buff_per_chamber = 0.05 + /// The amount of max health to be regenerated everytime the proc 'heal_wounds' is called. + var/health_regen_per_chamber = 0.033 // 3.3% + /// The amount of sunder to be regenerated everything the proc 'heal_wounds' is called. var/sunder_regen_per_chamber = 0.33 + /// The amount of times to multiply health/sunder regen by. var/chamber_scaling = 0 /datum/status_effect/upgrade_regeneration/on_apply() @@ -933,17 +935,30 @@ return FALSE buff_owner = owner chamber_scaling = length(buff_owner.hive.shell_chambers) - return TRUE + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) + RegisterSignal(SSdcs, COMSIG_XENOMORPH_HEALTH_REGEN, PROC_REF(on_heal_wounds)) -/datum/status_effect/upgrade_regeneration/tick() - chamber_scaling = length(buff_owner.hive.shell_chambers) - if(chamber_scaling > 0) - var/amount = buff_owner.maxHealth * regen_buff_per_chamber * chamber_scaling * (1 + buff_owner.recovery_aura * 0.05) - HEAL_XENO_DAMAGE(buff_owner, amount, FALSE) - buff_owner.adjust_sunder(-sunder_regen_per_chamber * chamber_scaling) - buff_owner.updatehealth() +/datum/status_effect/upgrade_regeneration/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) + UnregisterSignal(SSdcs, COMSIG_XENOMORPH_HEALTH_REGEN) return ..() +/// Sets the chamber_scaling to the amount of active survival chambers. +/datum/status_effect/upgrade_regeneration/proc/update_buff() + SIGNAL_HANDLER + chamber_scaling = length(buff_owner.hive.shell_chambers) + +/// Heals the xenomorph a certain amount of health at minimum regardless and even more if in the correct conditions. +/datum/status_effect/upgrade_regeneration/proc/on_heal_wounds(datum/controller/subsystem/processing/dcs/ssdcs, heal_data, seconds_per_tick) + SIGNAL_HANDLER + if(!chamber_scaling || !heal_data[1]) + return + var/health_amount = buff_owner.maxHealth * regen_buff_per_chamber + var/sunder_amount = -sunder_regen_per_chamber * chamber_scaling + HEAL_XENO_DAMAGE(buff_owner, health_amount, FALSE) + buff_owner.adjust_sunder(sunder_amount) + buff_owner.updatehealth() + // *************************************** // *************************************** // *************************************** From c27fe83f4df782023a66620e996b06e8ef95719a Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:12:19 -0700 Subject: [PATCH 033/106] typo --- code/datums/status_effects/xeno_buffs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index f8aef9f088e18..7b8cb9bd64eb6 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -953,7 +953,7 @@ SIGNAL_HANDLER if(!chamber_scaling || !heal_data[1]) return - var/health_amount = buff_owner.maxHealth * regen_buff_per_chamber + var/health_amount = buff_owner.maxHealth * health_regen_per_chamber var/sunder_amount = -sunder_regen_per_chamber * chamber_scaling HEAL_XENO_DAMAGE(buff_owner, health_amount, FALSE) buff_owner.adjust_sunder(sunder_amount) From 1c94a40dd2dfe5dbc81c5fa048915e084d192660 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:23:39 -0700 Subject: [PATCH 034/106] forgot to return true --- code/datums/status_effects/xeno_buffs.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 7b8cb9bd64eb6..d26ca7d0b84ee 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -937,6 +937,7 @@ chamber_scaling = length(buff_owner.hive.shell_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) RegisterSignal(SSdcs, COMSIG_XENOMORPH_HEALTH_REGEN, PROC_REF(on_heal_wounds)) + return TRUE /datum/status_effect/upgrade_regeneration/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) From 593069ab47cd93c3f0b4109fe360d318fd54de48 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:30:45 -0700 Subject: [PATCH 035/106] does not require any regen power --- code/datums/status_effects/xeno_buffs.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index d26ca7d0b84ee..4f02b10550c48 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -952,9 +952,9 @@ /// Heals the xenomorph a certain amount of health at minimum regardless and even more if in the correct conditions. /datum/status_effect/upgrade_regeneration/proc/on_heal_wounds(datum/controller/subsystem/processing/dcs/ssdcs, heal_data, seconds_per_tick) SIGNAL_HANDLER - if(!chamber_scaling || !heal_data[1]) + if(!chamber_scaling) return - var/health_amount = buff_owner.maxHealth * health_regen_per_chamber + var/health_amount = buff_owner.maxHealth * health_regen_per_chamber * chamber_scaling var/sunder_amount = -sunder_regen_per_chamber * chamber_scaling HEAL_XENO_DAMAGE(buff_owner, health_amount, FALSE) buff_owner.adjust_sunder(sunder_amount) From 65ec7254b4dd34b2674695bc9eb1a00a56daab76 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:00:03 -0700 Subject: [PATCH 036/106] even less regen & more comments --- code/datums/status_effects/xeno_buffs.dm | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 4f02b10550c48..a5dfca3dd4c66 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -872,7 +872,6 @@ xeno_owner.remove_filter("frenzy_screech_outline") return ..() - // *************************************** // *********** Upgrade Chambers Buffs - Survival // *************************************** @@ -886,16 +885,19 @@ duration = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_carapace + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner + /// The amount of soft armor given. var/armor_buff_per_chamber = 2.5 + /// The amount of times to multiply the armor buff by. var/chamber_scaling = 0 /datum/status_effect/upgrade_carapace/on_apply() if(!isxeno(owner)) return FALSE buff_owner = owner - RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) chamber_scaling = length(buff_owner.hive.shell_chambers) + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(armor_buff_per_chamber * chamber_scaling) return TRUE @@ -904,6 +906,7 @@ buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(-armor_buff_per_chamber * chamber_scaling) return ..() +/// Sets the chamber_scaling to the amount of active survival chambers and adjusts soft armor accordingly. /datum/status_effect/upgrade_carapace/proc/update_buff() SIGNAL_HANDLER buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(armor_buff_per_chamber * (length(buff_owner.hive.shell_chambers) - chamber_scaling)) @@ -922,9 +925,10 @@ duration = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_regeneration + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner /// The amount of max health to be regenerated everytime the proc 'heal_wounds' is called. - var/health_regen_per_chamber = 0.033 // 3.3% + var/health_regen_per_chamber = 0.02 // 2% /// The amount of sunder to be regenerated everything the proc 'heal_wounds' is called. var/sunder_regen_per_chamber = 0.33 /// The amount of times to multiply health/sunder regen by. @@ -936,12 +940,12 @@ buff_owner = owner chamber_scaling = length(buff_owner.hive.shell_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) - RegisterSignal(SSdcs, COMSIG_XENOMORPH_HEALTH_REGEN, PROC_REF(on_heal_wounds)) + RegisterSignal(buff_owner, COMSIG_XENOMORPH_HEALTH_REGEN, PROC_REF(on_heal_wounds)) return TRUE /datum/status_effect/upgrade_regeneration/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) - UnregisterSignal(SSdcs, COMSIG_XENOMORPH_HEALTH_REGEN) + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_HEALTH_REGEN) return ..() /// Sets the chamber_scaling to the amount of active survival chambers. @@ -949,8 +953,8 @@ SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.shell_chambers) -/// Heals the xenomorph a certain amount of health at minimum regardless and even more if in the correct conditions. -/datum/status_effect/upgrade_regeneration/proc/on_heal_wounds(datum/controller/subsystem/processing/dcs/ssdcs, heal_data, seconds_per_tick) +/// Heals the xenomorph's health and sunder based on assigned variables. +/datum/status_effect/upgrade_regeneration/proc/on_heal_wounds(mob/living/carbon/xenomorph/source_xenomorph, heal_data, seconds_per_tick) SIGNAL_HANDLER if(!chamber_scaling) return @@ -973,8 +977,11 @@ duration = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_vampirism + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner + /// The amount of max health to be regenerated the owner hits an alive human. var/leech_buff_per_chamber = 0.033 + /// The amount of times to multiply the vampirism by. var/chamber_scaling = 0 /datum/status_effect/upgrade_vampirism/on_apply() @@ -983,6 +990,7 @@ buff_owner = owner RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_slash)) + // Ravagers gets half of the effect since they eventually get their own version of vampirism. chamber_scaling = isxenoravager(buff_owner) ? (length(buff_owner.hive.shell_chambers) * 0.5) : length(buff_owner.hive.shell_chambers) return TRUE @@ -991,20 +999,20 @@ UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING) return ..() +/// Sets the chamber_scaling to the amount of active survival chambers. /datum/status_effect/upgrade_vampirism/proc/update_buff() SIGNAL_HANDLER chamber_scaling = isxenoravager(buff_owner) ? (length(buff_owner.hive.shell_chambers) * 0.5) : length(buff_owner.hive.shell_chambers) +/// Heals the xenomorph for hitting a non-dead human by a percentage of their max health. /datum/status_effect/upgrade_vampirism/proc/on_slash(datum/source, mob/living/target) SIGNAL_HANDLER if(target.stat == DEAD) return if(!ishuman(target)) return - var/bruteloss_healed = buff_owner.maxHealth * leech_buff_per_chamber * chamber_scaling - var/fireloss_healed = clamp(bruteloss_healed - buff_owner.bruteloss, 0, bruteloss_healed) - buff_owner.adjustBruteLoss(-bruteloss_healed) - buff_owner.adjustFireLoss(-fireloss_healed) + var/health_amount = buff_owner.maxHealth * leech_buff_per_chamber * chamber_scaling + HEAL_XENO_DAMAGE(buff_owner, health_amount, FALSE) buff_owner.updatehealth() // *************************************** From 7b74ce0721c603aa86a265e0e255efc5424d4475 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:14:32 -0700 Subject: [PATCH 037/106] adrenaline every plasma update / reduce --- code/datums/status_effects/xeno_buffs.dm | 40 ++++++++++++++++++------ 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index a5dfca3dd4c66..ac44d0c0388f5 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -929,7 +929,7 @@ var/mob/living/carbon/xenomorph/buff_owner /// The amount of max health to be regenerated everytime the proc 'heal_wounds' is called. var/health_regen_per_chamber = 0.02 // 2% - /// The amount of sunder to be regenerated everything the proc 'heal_wounds' is called. + /// The amount of sunder to be regenerated everytime the proc 'heal_wounds' is called. var/sunder_regen_per_chamber = 0.33 /// The amount of times to multiply health/sunder regen by. var/chamber_scaling = 0 @@ -1028,16 +1028,19 @@ duration = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_celerity + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner + /// The amount of movement speed the owner get. var/speed_buff_per_chamber = 0.1 + /// The amount of times to multiply the speed by. var/chamber_scaling = 0 /datum/status_effect/upgrade_celerity/on_apply() if(!isxeno(owner)) return FALSE buff_owner = owner - RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) chamber_scaling = length(buff_owner.hive.spur_chambers) + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) buff_owner.add_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF, TRUE, 0, NONE, TRUE, -speed_buff_per_chamber * chamber_scaling) return TRUE @@ -1046,6 +1049,7 @@ buff_owner.remove_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF) return ..() +/// Sets the chamber_scaling to the amount of active survival chambers and adjusts movement speed accordingly. /datum/status_effect/upgrade_celerity/proc/update_buff() SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.spur_chambers) @@ -1065,9 +1069,13 @@ status_type = STATUS_EFFECT_UNIQUE tick_interval = 5 SECONDS alert_type = /atom/movable/screen/alert/status_effect/upgrade_adrenaline + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner - var/plasma_regen_buff_per_chamber = 0.12 - var/percent_buff_per_chamber = 0.02 + /// The amount of plasma to regenerate based on their caste's plasma regeneration. + var/plasma_regen_buff_per_chamber = 0.5 // 5% + /// The amount of plasma to regenerate based on their caste's maximum plasma. + var/plasma_percentage_buff_per_chamber = 0.01 // 1% + /// The amount of times to multiply both plasma regenerations by. var/chamber_scaling = 0 /datum/status_effect/upgrade_adrenaline/on_apply() @@ -1075,14 +1083,28 @@ return FALSE buff_owner = owner chamber_scaling = length(buff_owner.hive.spur_chambers) + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) + RegisterSignal(buff_owner, COMSIG_XENOMORPH_PLASMA_REGEN, PROC_REF(on_plasma_regen)) return TRUE -/datum/status_effect/upgrade_adrenaline/tick() - if(HAS_TRAIT(buff_owner, TRAIT_NOPLASMAREGEN)) - return +/datum/status_effect/upgrade_adrenaline/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK) + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_PLASMA_REGEN) + return ..() + +/// Sets the chamber_scaling to the amount of active survival chambers. +/datum/status_effect/upgrade_adrenaline/proc/update_buff() + SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.spur_chambers) - if(chamber_scaling > 0) - buff_owner.gain_plasma(buff_owner.xeno_caste.plasma_gain * plasma_regen_buff_per_chamber * chamber_scaling + (buff_owner.xeno_caste.plasma_max * percent_buff_per_chamber * chamber_scaling)) + +/// Gives the xenomorph more plasma (according to their plasma regeneration and maximum) everytime they are suppose to regen plasma. +/datum/status_effect/upgrade_adrenaline/proc/on_plasma_regen(mob/living/carbon/xenomorph/source_xenomorph, plasma_mod, seconds_per_tick) + SIGNAL_HANDLER + if(!chamber_scaling) + return + var/plasma_regen_amount = buff_owner.xeno_caste.plasma_gain * plasma_regen_buff_per_chamber * chamber_scaling + var/plasma_max_amount = buff_owner.xeno_caste.plasma_max * plasma_percentage_buff_per_chamber * chamber_scaling + buff_owner.gain_plasma(plasma_regen_amount + plasma_max_amount) // *************************************** // *************************************** From d4ff466094f0a372b257fb46287b89e05e2b81cb Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:22:01 -0700 Subject: [PATCH 038/106] unwanted tick_interval --- code/datums/status_effects/xeno_buffs.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index ac44d0c0388f5..20204320facef 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1067,7 +1067,6 @@ id = "upgrade_adrenaline" duration = -1 status_type = STATUS_EFFECT_UNIQUE - tick_interval = 5 SECONDS alert_type = /atom/movable/screen/alert/status_effect/upgrade_adrenaline /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner From 7e4ad418a49b7a87a16f9177eff5531cd96375f4 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:26:42 -0700 Subject: [PATCH 039/106] typo that was stopping adrenaline from buying --- code/modules/mob/living/carbon/xenomorph/xenoprocs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index bf7b79237d056..cbb5fb031d710 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -637,7 +637,7 @@ dat += "[shell_chambers_built ? "
Vampirism " : "
Vampirism "] | Cost: [upgrade_price] | Leech from our attacks." dat += "
ATTACK
" dat += "[spur_chambers_built ? "
Celerity " : "
Celerity "] | Cost: [upgrade_price] | Increase our movement speed." - dat += "[spur_chambers_built ? "
Adrenaline " : "
Adrenaline "] | Cost: [upgrade_price] | Increase our plasma regeneration." + dat += "[spur_chambers_built ? "
Adrenaline " : "
Adrenaline "] | Cost: [upgrade_price] | Increase our plasma regeneration." dat += "[spur_chambers_built ? "
Crush " : "
Crush "] | Cost: [upgrade_price] | Increase our damage to objects." dat += "
UTILITY
" dat += "[veil_chambers_built ? "
Toxin " : "
Toxin "] | Cost: [upgrade_price] | Inject neurotoxin into the target." From 2b410dabc2e4792374b4bc790e03d30ebe6ba75b Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 21:01:33 -0700 Subject: [PATCH 040/106] reworked plasma regen pt. 2 --- code/datums/status_effects/xeno_buffs.dm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 20204320facef..e7719e49457f9 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1071,7 +1071,7 @@ /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner /// The amount of plasma to regenerate based on their caste's plasma regeneration. - var/plasma_regen_buff_per_chamber = 0.5 // 5% + var/plasma_regen_buff_per_chamber = 0.1 // 10% /// The amount of plasma to regenerate based on their caste's maximum plasma. var/plasma_percentage_buff_per_chamber = 0.01 // 1% /// The amount of times to multiply both plasma regenerations by. @@ -1096,14 +1096,18 @@ SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.spur_chambers) -/// Gives the xenomorph more plasma (according to their plasma regeneration and maximum) everytime they are suppose to regen plasma. +/// Gives the xenomorph more plasma (according to their plasma regeneration and adjusted maximum) everytime they are suppose to regen plasma. /datum/status_effect/upgrade_adrenaline/proc/on_plasma_regen(mob/living/carbon/xenomorph/source_xenomorph, plasma_mod, seconds_per_tick) SIGNAL_HANDLER if(!chamber_scaling) return + var/adjusted_plasma_max = buff_owner.xeno_caste.plasma_max * buff_owner.xeno_caste.plasma_regen_limit var/plasma_regen_amount = buff_owner.xeno_caste.plasma_gain * plasma_regen_buff_per_chamber * chamber_scaling - var/plasma_max_amount = buff_owner.xeno_caste.plasma_max * plasma_percentage_buff_per_chamber * chamber_scaling - buff_owner.gain_plasma(plasma_regen_amount + plasma_max_amount) + var/plasma_max_amount = adjusted_plasma_max * plasma_percentage_buff_per_chamber * chamber_scaling + var/plasma_to_give = plasma_regen_amount + plasma_max_amount * ((buff_owner.resting || buff_owner.lying_angle) ? 2 : 1) + var/plasma_stored_predicted = (buff_owner.plasma_stored + plasma_to_give) + // Give only enough plasma to reach the adjusted amount (for castes like Hivelord). + buff_owner.gain_plasma(plasma_stored_predicted > adjusted_plasma_max ? plasma_stored_predicted - adjusted_plasma_max : plasma_to_give) // *************************************** // *************************************** From e41c556320cff1be7045d0a894de97fcf58b9b25 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 21:11:16 -0700 Subject: [PATCH 041/106] crush changes --- code/datums/status_effects/xeno_buffs.dm | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index e7719e49457f9..03f96efb4a5cd 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1122,17 +1122,22 @@ duration = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_crush + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner - var/penetration_buff_per_chamber = 15 + /// The bonus damage to deal as percentage. + var/damage_buff_per_chamber = 0.333 // 33.3% + /// The armour pentration the damage damage has. + var/penetration_buff_per_chamber = 10 + /// The amount of times to multiply the armour pentration by. var/chamber_scaling = 0 /datum/status_effect/upgrade_crush/on_apply() if(!isxeno(owner)) return FALSE buff_owner = owner + chamber_scaling = length(buff_owner.hive.spur_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_OBJ, PROC_REF(on_obj_attack)) - chamber_scaling = length(buff_owner.hive.spur_chambers) return TRUE /datum/status_effect/upgrade_crush/on_remove() @@ -1146,8 +1151,10 @@ /datum/status_effect/upgrade_crush/proc/on_obj_attack(datum/source, obj/attacked) SIGNAL_HANDLER + if(!chamber_scaling) + return if(attacked.resistance_flags & XENO_DAMAGEABLE) - attacked.take_damage(buff_owner.xeno_caste.melee_damage, armour_penetration = (penetration_buff_per_chamber * chamber_scaling)) + attacked.take_damage(buff_owner.xeno_caste.melee_damage * damage_buff_per_chamber * chamber_scaling, armour_penetration = (penetration_buff_per_chamber * chamber_scaling)) // *************************************** // *********** Upgrade Chambers Buffs - Utility From ab20b36bb82cea0fb33716ab001097ce16bc8933 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 21:13:03 -0700 Subject: [PATCH 042/106] more comments --- code/datums/status_effects/xeno_buffs.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 03f96efb4a5cd..670e1c8de3487 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1049,7 +1049,7 @@ buff_owner.remove_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF) return ..() -/// Sets the chamber_scaling to the amount of active survival chambers and adjusts movement speed accordingly. +/// Sets the chamber_scaling to the amount of active spur chambers and adjusts movement speed accordingly. /datum/status_effect/upgrade_celerity/proc/update_buff() SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.spur_chambers) @@ -1091,7 +1091,7 @@ UnregisterSignal(buff_owner, COMSIG_XENOMORPH_PLASMA_REGEN) return ..() -/// Sets the chamber_scaling to the amount of active survival chambers. +/// Sets the chamber_scaling to the amount of active spur chambers. /datum/status_effect/upgrade_adrenaline/proc/update_buff() SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.spur_chambers) @@ -1145,10 +1145,12 @@ UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_OBJ) return ..() +/// Sets the chamber_scaling to the amount of active spur chambers. /datum/status_effect/upgrade_crush/proc/update_buff() SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.spur_chambers) +/// Deals bonus damage along with armour pentration to the object. /datum/status_effect/upgrade_crush/proc/on_obj_attack(datum/source, obj/attacked) SIGNAL_HANDLER if(!chamber_scaling) From 9a6ff07c94cbbaff7729c819167e8433334376ca Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:33:02 -0700 Subject: [PATCH 043/106] crush and defiler fixes --- code/__DEFINES/xeno.dm | 8 +++ code/datums/status_effects/xeno_buffs.dm | 62 +++++++++++------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 95409e6927f1b..bc35c6151347f 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -92,6 +92,14 @@ GLOBAL_LIST_INIT(defiler_toxin_type_list, list( /datum/reagent/toxin/xeno_ozelomelyn, )) +//List of Defiler toxin images +GLOBAL_LIST_INIT(defiler_toxin_images_list, list( + DEFILER_OZELOMELYN = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_OZELOMELYN), + DEFILER_HEMODILE = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_HEMODILE), + DEFILER_TRANSVITOX = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_TRANSVITOX), + DEFILER_NEUROTOXIN = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_NEUROTOXIN) +)) + //List of toxins improving defile's damage GLOBAL_LIST_INIT(defiler_toxins_typecache_list, typecacheof(list( /datum/reagent/toxin/xeno_ozelomelyn, diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 670e1c8de3487..e2ab5254d0b9c 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1156,7 +1156,15 @@ if(!chamber_scaling) return if(attacked.resistance_flags & XENO_DAMAGEABLE) - attacked.take_damage(buff_owner.xeno_caste.melee_damage * damage_buff_per_chamber * chamber_scaling, armour_penetration = (penetration_buff_per_chamber * chamber_scaling)) + var/adjusted_armour_penetration = penetration_buff_per_chamber * chamber_scaling + var/adjusted_damage = buff_owner.xeno_caste.melee_damage * damage_buff_per_chamber * chamber_scaling + var/expected_damage = round(attacked.modify_by_armor(adjusted_damage, MELEE, adjusted_armour_penetration, null, null), DAMAGE_PRECISION) + var/expected_integrity = max(attacked.obj_integrity - expected_damage, 0) + // Since this signal is called before they actually attack themselves, we do just enough so the main attack does the finishing blow. + if(!expected_integrity) + attacked.take_damage(expected_integrity - 0.1, effects = FALSE, armour_penetration = 100) + return + attacked.take_damage(buff_owner.xeno_caste.melee_damage * damage_buff_per_chamber * chamber_scaling, effects = FALSE, armour_penetration = (penetration_buff_per_chamber * chamber_scaling)) // *************************************** // *********** Upgrade Chambers Buffs - Utility @@ -1167,49 +1175,38 @@ icon_state = "xenobuff_generic" /atom/movable/screen/alert/status_effect/upgrade_toxin/Click() - var/static/list/upgrade_toxin_images_list = list( - DEFILER_OZELOMELYN = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_OZELOMELYN), - DEFILER_HEMODILE = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_HEMODILE), - DEFILER_TRANSVITOX = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_TRANSVITOX), - DEFILER_NEUROTOXIN = image('icons/Xeno/actions/defiler.dmi', icon_state = DEFILER_NEUROTOXIN) - ) - var/datum/status_effect/upgrade_toxin/effect = attached_effect - if(effect.buff_owner.incapacitated(TRUE)) - to_chat(usr, span_warning("Cant do that right now!")) - return - var/datum/reagent/toxin/toxin_choice = show_radial_menu(effect.buff_owner, effect.buff_owner, upgrade_toxin_images_list, radius = 35, require_near = TRUE) + var/datum/status_effect/upgrade_toxin/status_effect = attached_effect + var/datum/reagent/toxin/toxin_choice = show_radial_menu(status_effect.buff_owner, status_effect.buff_owner, GLOB.defiler_toxin_images_list, radius = 35, require_near = TRUE) if(!toxin_choice) return - for(var/toxin in effect.selectable_reagents) - var/datum/reagent/R = GLOB.chemical_reagents_list[toxin] - if(R.name == toxin_choice) - effect.injected_reagent = R.type + for(var/defiler_toxin in GLOB.defiler_toxin_type_list) + var/datum/reagent/reagent = GLOB.chemical_reagents_list[defiler_toxin] + if(reagent.name == toxin_choice) + status_effect.selected_reagent = reagent.type break - effect.buff_owner.balloon_alert(effect.buff_owner, "[toxin_choice]") + status_effect.buff_owner.balloon_alert(status_effect.buff_owner, "[toxin_choice]") /datum/status_effect/upgrade_toxin id = "upgrade_toxin" duration = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_toxin + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner + /// The amount of toxins to inject. var/toxin_amount_per_chamber = 1 + /// The amount of times to multiply the toxin amount by. var/chamber_scaling = 0 - var/datum/reagent/toxin/injected_reagent = /datum/reagent/toxin/xeno_neurotoxin - var/list/selectable_reagents = list( - /datum/reagent/toxin/xeno_ozelomelyn, - /datum/reagent/toxin/xeno_hemodile, - /datum/reagent/toxin/xeno_transvitox, - /datum/reagent/toxin/xeno_neurotoxin - ) + /// Currently selected reagent to inject. + var/datum/reagent/toxin/selected_reagent = /datum/reagent/toxin/xeno_neurotoxin /datum/status_effect/upgrade_toxin/on_apply() if(!isxeno(owner)) return FALSE buff_owner = owner + chamber_scaling = length(buff_owner.hive.veil_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_slash)) - chamber_scaling = length(buff_owner.hive.veil_chambers) return TRUE /datum/status_effect/upgrade_toxin/on_remove() @@ -1217,23 +1214,18 @@ UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING) return ..() +/// Sets the chamber_scaling to the amount of active veil chambers. /datum/status_effect/upgrade_toxin/proc/update_buff() SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.veil_chambers) +/// Injects the human target with a variable amount of the selected reagent. /datum/status_effect/upgrade_toxin/proc/on_slash(datum/source, mob/living/target) SIGNAL_HANDLER - if(target.stat == DEAD) + if(!chamber_scaling || target.stat == DEAD || !ishuman(target) || !target.can_sting()) return - if(!ishuman(target)) - return - if(!target?.can_sting()) - return - var/mob/living/carbon/carbon_target = target - chamber_scaling = length(buff_owner.hive.veil_chambers) - var/amount_to_inject = toxin_amount_per_chamber * chamber_scaling - if(amount_to_inject) - carbon_target.reagents.add_reagent(injected_reagent, amount_to_inject) + var/mob/living/carbon/human/human_target = target + human_target.reagents.add_reagent(selected_reagent, toxin_amount_per_chamber * chamber_scaling) // *************************************** // *************************************** From 63c6902f0658234b8bf3e7de169983af77dc162d Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:03:50 -0700 Subject: [PATCH 044/106] fixes up pheromones and trail --- code/datums/status_effects/xeno_buffs.dm | 61 +++++++++++++++--------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index e2ab5254d0b9c..c766e7593a0bc 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1236,36 +1236,39 @@ icon_state = "xenobuff_phero" /atom/movable/screen/alert/status_effect/upgrade_pheromones/Click() - var/datum/status_effect/upgrade_pheromones/effect = attached_effect - if(effect.buff_owner.incapacitated(TRUE)) - to_chat(usr, span_warning("Cant do that right now!")) - return - var/phero_choice = show_radial_menu(effect.buff_owner, effect.buff_owner, GLOB.pheromone_images_list, radius = 35, require_near = TRUE) + var/datum/status_effect/upgrade_pheromones/status_effect = attached_effect + var/phero_choice = show_radial_menu(status_effect.buff_owner, status_effect.buff_owner, GLOB.pheromone_images_list, radius = 35, require_near = TRUE) if(!phero_choice) return - QDEL_NULL(effect.current_aura) - effect.emitted_aura = phero_choice - effect.current_aura = SSaura.add_emitter(effect.buff_owner, phero_choice, 6 + effect.phero_power_per_chamber * effect.chamber_scaling * 2, effect.phero_power_base + effect.phero_power_per_chamber * effect.chamber_scaling, -1, FACTION_XENO, effect.buff_owner.hivenumber) + QDEL_NULL(status_effect.current_aura) + status_effect.emitted_aura = phero_choice + status_effect.create_aura() /datum/status_effect/upgrade_pheromones id = "upgrade_pheromones" duration = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_pheromones + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner + /// The aura. var/datum/aura_bearer/current_aura - var/phero_power_per_chamber = 1 - var/phero_power_base = 1 - var/chamber_scaling = 0 + /// The aura to emit. var/emitted_aura = AURA_XENO_RECOVERY + /// The initial value of the aura's power. + var/aura_power_base = 1 + /// The phero power to increase by. + var/aura_power_per_chamber = 1 + /// The amount of times to multiply the aura power by. + var/chamber_scaling = 0 /datum/status_effect/upgrade_pheromones/on_apply() if(!isxeno(owner)) return FALSE buff_owner = owner - RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) chamber_scaling = length(buff_owner.hive.veil_chambers) - current_aura = SSaura.add_emitter(buff_owner, AURA_XENO_RECOVERY, 6 + phero_power_per_chamber * chamber_scaling * 2, phero_power_base + phero_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) + create_aura() return TRUE /datum/status_effect/upgrade_pheromones/on_remove() @@ -1274,11 +1277,17 @@ current_aura.stop_emitting() return ..() +/// (Re)creates the aura. +/datum/status_effect/upgrade_pheromones/proc/create_aura() + if(current_aura) + QDEL_NULL(current_aura) + current_aura = SSaura.add_emitter(buff_owner, emitted_aura, 6 + aura_power_per_chamber * chamber_scaling * 2, aura_power_base + aura_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) + +/// Sets the chamber_scaling to the amount of active veil chambers and recreates the aura. /datum/status_effect/upgrade_pheromones/proc/update_buff() SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.veil_chambers) - QDEL_NULL(current_aura) - current_aura = SSaura.add_emitter(buff_owner, emitted_aura, 6 + phero_power_per_chamber * chamber_scaling * 2, phero_power_base + phero_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) + create_aura() // *************************************** // *************************************** @@ -1305,23 +1314,29 @@ duration = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = /atom/movable/screen/alert/status_effect/upgrade_trail + /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner - var/obj/selected_trail = /obj/effect/xenomorph/spray + /// The initial odds of the trail spawning. var/base_chance = 25 + /// The additional chance of the trail starting. var/chance_per_chamber = 25 + /// The amount of times to increase the additional chance of trail spawning by. var/chamber_scaling = 0 + /// The selected trail that will spawn upon moving. + var/obj/selected_trail = /obj/effect/xenomorph/spray + /// A list of trails that can be selected var/list/selectable_trails = list( /obj/effect/xenomorph/spray, - /obj/alien/resin/sticky/thin, + /obj/alien/resin/sticky/thin ) /datum/status_effect/upgrade_trail/on_apply() if(!isxeno(owner)) return FALSE buff_owner = owner - RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) - RegisterSignal(buff_owner, COMSIG_MOVABLE_MOVED, PROC_REF(do_acid_trail)) chamber_scaling = length(buff_owner.hive.veil_chambers) + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) + RegisterSignal(buff_owner, COMSIG_MOVABLE_MOVED, PROC_REF(create_trail)) return TRUE /datum/status_effect/upgrade_trail/on_remove() @@ -1329,15 +1344,17 @@ UnregisterSignal(buff_owner, COMSIG_MOVABLE_MOVED) return ..() +/// Sets the chamber_scaling to the amount of active veil chambers. /datum/status_effect/upgrade_trail/proc/update_buff() SIGNAL_HANDLER chamber_scaling = length(buff_owner.hive.veil_chambers) -/datum/status_effect/upgrade_trail/proc/do_acid_trail() +/// Rolls the dice and creates the selected trail if the dice is right. +/datum/status_effect/upgrade_trail/proc/create_trail() SIGNAL_HANDLER - if(buff_owner.incapacitated(TRUE)) + if(buff_owner.incapacitated() || buff_owner.lying_angle || buff_owner.resting) return - if(prob(base_chance + chance_per_chamber * chamber_scaling)) + if(prob(base_chance + (chance_per_chamber * chamber_scaling))) var/turf/T = get_turf(buff_owner) if(T.density || isspaceturf(T)) return From 275ad77cf13c45c97fd71e35eb21c51df652cd18 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:37:29 -0700 Subject: [PATCH 045/106] decrease health regen a little and halve sunder --- code/datums/status_effects/xeno_buffs.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index c766e7593a0bc..4e360a8b5cf9d 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -928,9 +928,9 @@ /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner /// The amount of max health to be regenerated everytime the proc 'heal_wounds' is called. - var/health_regen_per_chamber = 0.02 // 2% + var/health_regen_per_chamber = 0.015 // 1.5% /// The amount of sunder to be regenerated everytime the proc 'heal_wounds' is called. - var/sunder_regen_per_chamber = 0.33 + var/sunder_regen_per_chamber = 0.166 /// The amount of times to multiply health/sunder regen by. var/chamber_scaling = 0 From 1995997abc497744b56db4b39b5c5582e1a7d60d Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 02:08:13 -0700 Subject: [PATCH 046/106] take_damage fixes --- code/datums/status_effects/xeno_buffs.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 4e360a8b5cf9d..e84271016f5d7 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1162,9 +1162,9 @@ var/expected_integrity = max(attacked.obj_integrity - expected_damage, 0) // Since this signal is called before they actually attack themselves, we do just enough so the main attack does the finishing blow. if(!expected_integrity) - attacked.take_damage(expected_integrity - 0.1, effects = FALSE, armour_penetration = 100) + attacked.take_damage(expected_integrity - 0.1, BRUTE, MELEE, FALSE, armour_penetration = 100) return - attacked.take_damage(buff_owner.xeno_caste.melee_damage * damage_buff_per_chamber * chamber_scaling, effects = FALSE, armour_penetration = (penetration_buff_per_chamber * chamber_scaling)) + attacked.take_damage(buff_owner.xeno_caste.melee_damage * damage_buff_per_chamber * chamber_scaling, BRUTE, MELEE, FALSE, armour_penetration = (penetration_buff_per_chamber * chamber_scaling)) // *************************************** // *********** Upgrade Chambers Buffs - Utility From d110f44aefbf804d1f3344d2b0e737552465f0ce Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 02:08:24 -0700 Subject: [PATCH 047/106] tgui --- .../living/carbon/xenomorph/mutation_datum.dm | 148 ++++++++++++++++++ .../mob/living/carbon/xenomorph/xenoprocs.dm | 72 +-------- tgmc.dme | 1 + .../tgui/interfaces/MutationSelector.tsx | 83 ++++++++++ 4 files changed, 233 insertions(+), 71 deletions(-) create mode 100644 code/modules/mob/living/carbon/xenomorph/mutation_datum.dm create mode 100644 tgui/packages/tgui/interfaces/MutationSelector.tsx diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm new file mode 100644 index 0000000000000..acf0c33b09f30 --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -0,0 +1,148 @@ +GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) + +/datum/mutation_datum + interaction_flags = INTERACT_UI_INTERACT + +/datum/mutation_datum/ui_state(mob/user) + return GLOB.hive_ui_state // Similar purpose. + +/datum/mutation_datum/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "MutationSelector", "Mutation Selector") + ui.open() + +/datum/mutation_datum/ui_data(mob/living/carbon/xenomorph/xeno_user) + var/list/data = list() + + data["shell_chambers"] = length(xeno_user.hive?.shell_chambers) + data["spur_chambers"] = length(xeno_user.hive?.shell_chambers) + data["veil_chambers"] = length(xeno_user.hive?.shell_chambers) + data["biomass"] = xeno_user.biomass + switch(xeno_user.xeno_caste.tier) + if(XENO_TIER_ONE) + data["cost"] = XENO_UPGRADE_BIOMASS_COST_T1 + if(XENO_TIER_TWO) + data["cost"] = XENO_UPGRADE_BIOMASS_COST_T2 + if(XENO_TIER_THREE) + data["cost"] = XENO_UPGRADE_BIOMASS_COST_T3 + else + data["cost"] = XENO_UPGRADE_BIOMASS_COST_T4 + + var/list/upgrades = list( + list( + "category" = "Survival", + "upgrades" = list( + list( + "name" = "Carapace", + "desc" = "Increase our armor." + ), + list( + "name" = "Regeneration", + "desc" = "Increase our health regeneration." + ), + list( + "name" = "Vampirism", + "desc" = "Leech from our attacks." + ) + ) + ), + list( + "category" = "Attack", + "upgrades" = list( + list( + "name" = "Celerity", + "desc" = "Increase our movement speed." + ), + list( + "name" = "Adrenaline", + "desc" = "Increase our plasma regeneration." + ), + list( + "name" = "Crush", + "desc" = "Increase our damage to objects." + ) + ) + ), + list( + "category" = "Utility", + "upgrades" = list( + list( + "name" = "Toxin", + "desc" = "Inject toxins into our target." + ), + list( + "name" = "Pheromones", + "desc" = "Ability to emit pheromones." + ), + list( + "name" = "Trail", + "desc" = "Leave a trail behind." + ) + ) + ) + ) + data["upgrades"] = upgrades + + return data + +/datum/mutation_datum/ui_act(action, params) + . = ..() + if(.) + return + switch(action) + if("purchase") + var/type = params["type"] + if(type == "Carapace") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_CARAPACE) + if(type == "Regeneration") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_REGENERATION) + if(type == "Vampirism") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_VAMPIRISM) + if(type == "Celerity") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_CELERITY) + if(type == "Adrenaline") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_ADRENALINE) + if(type == "Crush") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_CRUSH) + if(type == "Toxin") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_TOXIN) + if(type == "Pheromones") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_PHERO) + if(type == "Trail") + remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_TRAIL) + + SStgui.close_user_uis(usr, src) + +/datum/mutation_datum/proc/remove_apply_upgrades(mob/ui_usr, list/upgrades_to_remove, datum/status_effect/upgrade_to_apply) + if(!isxeno(ui_usr)) + return + var/mob/living/carbon/xenomorph/xeno_user = ui_usr + + var/upgrade_price + switch(xeno_user.xeno_caste.tier) + if(XENO_TIER_ONE) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T1 + if(XENO_TIER_TWO) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T2 + if(XENO_TIER_THREE) + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T3 + else + upgrade_price = XENO_UPGRADE_BIOMASS_COST_T4 + + if(xeno_user.biomass < upgrade_price) + to_chat(usr, span_warning("You don't have enough biomass!")) + return + + var/upgrade = locate(upgrade_to_apply) in xeno_user.status_effects + if(upgrade) + to_chat(usr, span_xenonotice("Existing mutation chosen. No biomass spent.")) + return + + xeno_user.biomass -= upgrade_price + to_chat(xeno_user, span_xenonotice("Mutation gained.")) + for(var/datum/status_effect/removed_status_effect AS in upgrades_to_remove) + xeno_user.remove_status_effect(removed_status_effect) + xeno_user.do_jitter_animation(500) + xeno_user.apply_status_effect(upgrade_to_apply) + diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index cbb5fb031d710..e9e0ee1763da8 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -606,74 +606,4 @@ set desc = "See current Upgrade Chambers and get mutations for yourself" set category = "Alien" - get_upgrades(src) - -/mob/living/carbon/xenomorph/proc/get_upgrades(mob/living/carbon/xenomorph/user) - var/upgrade_price - switch(xeno_caste.tier) - if(XENO_TIER_ONE) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T1 - if(XENO_TIER_TWO) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T2 - if(XENO_TIER_THREE) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T3 - else - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T4 - var/dat = "
" - - dat += "
Active Upgrade Chambers:" - dat += "
Shell : [length(user?.hive?.shell_chambers)] | Spur : [length(user?.hive?.spur_chambers)] | Veil : [length(user?.hive?.veil_chambers)]" - dat += "
Biomass: [user?.biomass] / 100" - - dat += "
" - - dat += "

List of upgrades:
" - var/shell_chambers_built = length(user?.hive?.shell_chambers) - var/spur_chambers_built = length(user?.hive?.spur_chambers) - var/veil_chambers_built = length(user?.hive?.veil_chambers) - dat += "
SURVIVAL
" - dat += "[shell_chambers_built ? "
Carapace " : "
Carapace "] | Cost: [upgrade_price] | Increase our armor." - dat += "[shell_chambers_built ? "
Regeneration " : "
Regeneration "] | Cost: [upgrade_price] | Increase our health regeneration." - dat += "[shell_chambers_built ? "
Vampirism " : "
Vampirism "] | Cost: [upgrade_price] | Leech from our attacks." - dat += "
ATTACK
" - dat += "[spur_chambers_built ? "
Celerity " : "
Celerity "] | Cost: [upgrade_price] | Increase our movement speed." - dat += "[spur_chambers_built ? "
Adrenaline " : "
Adrenaline "] | Cost: [upgrade_price] | Increase our plasma regeneration." - dat += "[spur_chambers_built ? "
Crush " : "
Crush "] | Cost: [upgrade_price] | Increase our damage to objects." - dat += "
UTILITY
" - dat += "[veil_chambers_built ? "
Toxin " : "
Toxin "] | Cost: [upgrade_price] | Inject neurotoxin into the target." - dat += "[veil_chambers_built ? "
Pheromones " : "
Pheromones "] | Cost: [upgrade_price] | Ability to emit pheromones." - dat += "[veil_chambers_built ? "
Trail " : "
Trail "] | Cost: [upgrade_price] | Leave a trail behind." - - var/datum/browser/popup = new(user, "upgrademenu", "
Mutations Menu
", 600, 600) - popup.set_content(dat) - popup.open() - -/mob/living/carbon/xenomorph/proc/remove_apply_upgrades(list/upgrades_to_remove, datum/status_effect/upgrade_to_apply) - if(incapacitated(TRUE)) - to_chat(usr, span_warning("Cant do that right now!")) - return - var/upgrade_price - switch(xeno_caste.tier) - if(XENO_TIER_ONE) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T1 - if(XENO_TIER_TWO) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T2 - if(XENO_TIER_THREE) - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T3 - else - upgrade_price = XENO_UPGRADE_BIOMASS_COST_T4 - if(biomass < upgrade_price) - to_chat(usr, span_warning("You dont have enough biomass!")) - return - var/upgrade = locate(upgrade_to_apply) in status_effects - if(upgrade) - to_chat(usr, span_xenonotice("Existing mutation chosen. No biomass spent.")) - DIRECT_OUTPUT(usr, browse(null, "window=["upgrademenu"]")) - return - biomass -= upgrade_price - to_chat(usr, span_xenonotice("Mutation gained.")) - for(var/datum/status_effect/S AS in upgrades_to_remove) - remove_status_effect(S) - do_jitter_animation(500) - apply_status_effect(upgrade_to_apply) - DIRECT_OUTPUT(usr, browse(null, "window=["upgrademenu"]")) + GLOB.mutation_selector.interact(src) diff --git a/tgmc.dme b/tgmc.dme index 1651cd640e68c..11581277b6023 100644 --- a/tgmc.dme +++ b/tgmc.dme @@ -1786,6 +1786,7 @@ F// DM Environment file for baystation12.dme. #include "code\modules\mob\living\carbon\xenomorph\hive_upgrades.dm" #include "code\modules\mob\living\carbon\xenomorph\life.dm" #include "code\modules\mob\living\carbon\xenomorph\login.dm" +#include "code\modules\mob\living\carbon\xenomorph\mutation_datum.dm" #include "code\modules\mob\living\carbon\xenomorph\saddles.dm" #include "code\modules\mob\living\carbon\xenomorph\say.dm" #include "code\modules\mob\living\carbon\xenomorph\update_icons.dm" diff --git a/tgui/packages/tgui/interfaces/MutationSelector.tsx b/tgui/packages/tgui/interfaces/MutationSelector.tsx new file mode 100644 index 0000000000000..068fd5a264fce --- /dev/null +++ b/tgui/packages/tgui/interfaces/MutationSelector.tsx @@ -0,0 +1,83 @@ +import { useBackend } from '../backend'; +import { + Box, + Button, + Flex, + Section, +} from '../components'; +import { Window } from '../layouts'; + +type Upgrade = { + name: string, + desc: string +} +type UpgradeCategories = { + category: string + upgrades: Upgrade[] +} + +type MutationData = { + shell_chambers: number, + spur_chambers: number, + veil_chambers: number, + biomass: number, + cost: number, + upgrades: UpgradeCategories[] +}; + +export const MutationSelector = (props) => { + const { act, data } = useBackend(); + const { shell_chambers, spur_chambers, veil_chambers, biomass, cost, upgrades } = data; + + return ( + + +
+ + Shell Chambers: {shell_chambers} + + + Spur Chambers: {spur_chambers} + + + + Veil Chambers: {veil_chambers} + +
+ {upgrades.map((upgrade_category) => ( +
+ {upgrade_category.upgrades.map((upgrade) => ( + +
+ ))} +
+
+ ); +}; From 442ed412bad4c8125a920e7c667c775b460a5bd3 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 02:14:15 -0700 Subject: [PATCH 048/106] finishing up tgui --- .../living/carbon/xenomorph/mutation_datum.dm | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index acf0c33b09f30..05d88400fc7fe 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -16,8 +16,8 @@ GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) var/list/data = list() data["shell_chambers"] = length(xeno_user.hive?.shell_chambers) - data["spur_chambers"] = length(xeno_user.hive?.shell_chambers) - data["veil_chambers"] = length(xeno_user.hive?.shell_chambers) + data["spur_chambers"] = length(xeno_user.hive?.spur_chambers) + data["veil_chambers"] = length(xeno_user.hive?.veil_chambers) data["biomass"] = xeno_user.biomass switch(xeno_user.xeno_caste.tier) if(XENO_TIER_ONE) @@ -100,17 +100,17 @@ GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) if(type == "Vampirism") remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_VAMPIRISM) if(type == "Celerity") - remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_CELERITY) + remove_apply_upgrades(usr, GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_CELERITY) if(type == "Adrenaline") - remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_ADRENALINE) + remove_apply_upgrades(usr, GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_ADRENALINE) if(type == "Crush") - remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_CRUSH) + remove_apply_upgrades(usr, GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_CRUSH) if(type == "Toxin") - remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_TOXIN) + remove_apply_upgrades(usr, GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_TOXIN) if(type == "Pheromones") - remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_PHERO) + remove_apply_upgrades(usr, GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_PHERO) if(type == "Trail") - remove_apply_upgrades(usr, GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_TRAIL) + remove_apply_upgrades(usr, GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_TRAIL) SStgui.close_user_uis(usr, src) @@ -139,6 +139,26 @@ GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) to_chat(usr, span_xenonotice("Existing mutation chosen. No biomass spent.")) return + if(!length(xeno_user.hive?.shell_chambers)) + var/is_survival_status_effect = locate(upgrade_to_apply) in GLOB.xeno_survival_upgrades + if(is_survival_status_effect) + to_chat(usr, span_xenonotice("This mutation requires a shell chamber to exist!")) + return + + + if(!length(xeno_user.hive?.spur_chambers)) + var/is_attack_status_effect = locate(upgrade_to_apply) in GLOB.xeno_attack_upgrades + if(is_attack_status_effect) + to_chat(usr, span_xenonotice("This mutation requires a spur chamber to exist!")) + return + + + if(!length(xeno_user.hive?.veil_chambers)) + var/is_utility_status_effect = locate(upgrade_to_apply) in GLOB.xeno_utility_upgrades + if(is_utility_status_effect) + to_chat(usr, span_xenonotice("This mutation requires a veil chamber to exist!")) + return + xeno_user.biomass -= upgrade_price to_chat(xeno_user, span_xenonotice("Mutation gained.")) for(var/datum/status_effect/removed_status_effect AS in upgrades_to_remove) From 9ba5c50c6d4cd613c57069afc0d7ba97e7d29cdb Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 02:16:21 -0700 Subject: [PATCH 049/106] more leftovers --- .../living/carbon/xenomorph/mutation_datum.dm | 1 - .../mob/living/carbon/xenomorph/xenoprocs.dm | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 05d88400fc7fe..6f06e182b2dc4 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -152,7 +152,6 @@ GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) to_chat(usr, span_xenonotice("This mutation requires a spur chamber to exist!")) return - if(!length(xeno_user.hive?.veil_chambers)) var/is_utility_status_effect = locate(upgrade_to_apply) in GLOB.xeno_utility_upgrades if(is_utility_status_effect) diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index e9e0ee1763da8..562a3533e3cd9 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -84,25 +84,6 @@ // Checks for can use done in overwatch action. SEND_SIGNAL(src, COMSIG_XENOMORPH_WATCHXENO, target) - if(href_list["carapace_buy"]) - remove_apply_upgrades(GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_CARAPACE) - if(href_list["regeneration_buy"]) - remove_apply_upgrades(GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_REGENERATION) - if(href_list["vampirism_buy"]) - remove_apply_upgrades(GLOB.xeno_survival_upgrades, STATUS_EFFECT_UPGRADE_VAMPIRISM) - if(href_list["celerity_buy"]) - remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_CELERITY) - if(href_list["adrenaline_buy"]) - remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_ADRENALINE) - if(href_list["crush_buy"]) - remove_apply_upgrades(GLOB.xeno_attack_upgrades, STATUS_EFFECT_UPGRADE_CRUSH) - if(href_list["toxin_buy"]) - remove_apply_upgrades(GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_TOXIN) - if(href_list["phero_buy"]) - remove_apply_upgrades(GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_PHERO) - if(href_list["trail_buy"]) - remove_apply_upgrades(GLOB.xeno_utility_upgrades, STATUS_EFFECT_UPGRADE_TRAIL) - ///Send a message to all xenos. Force forces the message whether or not the hivemind is intact. Target is an atom that is pointed out to the hive. Filter list is a list of xenos we don't message. /proc/xeno_message(message = null, span_class = "xenoannounce", size = 5, hivenumber = XENO_HIVE_NORMAL, force = FALSE, atom/target = null, sound = null, apply_preferences = FALSE, filter_list = null, arrow_type, arrow_color, report_distance = FALSE) if(!message) From 2b5ef8ee21ef787e63f7c471d0d1d105b0403b0e Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 02:26:52 -0700 Subject: [PATCH 050/106] threw this into Prettier.io --- .../tgui/interfaces/MutationSelector.tsx | 74 ++++++++----------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/tgui/packages/tgui/interfaces/MutationSelector.tsx b/tgui/packages/tgui/interfaces/MutationSelector.tsx index 068fd5a264fce..2cb0da9a12198 100644 --- a/tgui/packages/tgui/interfaces/MutationSelector.tsx +++ b/tgui/packages/tgui/interfaces/MutationSelector.tsx @@ -1,76 +1,64 @@ -import { useBackend } from '../backend'; -import { - Box, - Button, - Flex, - Section, -} from '../components'; -import { Window } from '../layouts'; +import { useBackend } from "../backend"; +import { Box, Button, Flex, Section } from "../components"; +import { Window } from "../layouts"; type Upgrade = { - name: string, - desc: string -} + name: string; + desc: string; +}; type UpgradeCategories = { - category: string - upgrades: Upgrade[] -} + category: string; + upgrades: Upgrade[]; +}; type MutationData = { - shell_chambers: number, - spur_chambers: number, - veil_chambers: number, - biomass: number, - cost: number, - upgrades: UpgradeCategories[] + shell_chambers: number; + spur_chambers: number; + veil_chambers: number; + biomass: number; + cost: number; + upgrades: UpgradeCategories[]; }; export const MutationSelector = (props) => { const { act, data } = useBackend(); - const { shell_chambers, spur_chambers, veil_chambers, biomass, cost, upgrades } = data; + const { + shell_chambers, + spur_chambers, + veil_chambers, + biomass, + cost, + upgrades, + } = data; return ( -
- +
+ Shell Chambers: {shell_chambers} - + Spur Chambers: {spur_chambers} - + Veil Chambers: {veil_chambers}
{upgrades.map((upgrade_category) => (
+ key={upgrade_category.category} + > {upgrade_category.upgrades.map((upgrade) => (
- ))} +
+ {survival_mutations.map((mutation) => ( + +
+
+ {attack_mutations.map((mutation) => ( + +
+
+ {utility_mutations.map((mutation) => ( + +
); From bce0dbe6254c8a8efa0d6d2c51f7a590bec1b198 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:10:40 -0700 Subject: [PATCH 055/106] psydrain/cocoon is now socialism at range 7 --- .../mob/living/carbon/xenomorph/abilities.dm | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index fd271751d75f9..f5bc67fd413e4 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -1398,7 +1398,22 @@ victim.do_jitter_animation(2) victim.adjustCloneLoss(20) - X.gain_biomass(15) + + var/list/mob/living/carbon/xenomorph/nearby_friendly_xenos = list() + for(var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(X, 7)) + // Intentionally includes the owner. + if(!X.issamexenohive(nearby_xeno)) + continue + nearby_friendly_xenos += nearby_xeno + + var/amount_of_friendly_xenos = length(nearby_friendly_xenos) + if(amount_of_friendly_xenos > 1) + // Split the reward amongst every xeno nearby, including themselves. + var/biomass_per_xeno = round(15/amount_of_friendly_xenos, 0.1) + for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) + nearby_friendly_xeno.gain_biomass(biomass_per_xeno) + else + X.gain_biomass(15) ADD_TRAIT(victim, TRAIT_PSY_DRAINED, TRAIT_PSY_DRAINED) if(HAS_TRAIT(victim, TRAIT_UNDEFIBBABLE)) @@ -1510,10 +1525,22 @@ victim.dead_ticks = 0 ADD_TRAIT(victim, TRAIT_STASIS, TRAIT_STASIS) X.eject_victim(TRUE, starting_turf) - X.gain_biomass(15) - if(owner.client) - var/datum/personal_statistics/personal_statistics = GLOB.personal_statistics_list[owner.ckey] - personal_statistics.cocooned++ + + var/list/mob/living/carbon/xenomorph/nearby_friendly_xenos = list() + for(var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(X, 7)) + // Intentionally includes the owner. + if(!X.issamexenohive(nearby_xeno)) + continue + nearby_friendly_xenos += nearby_xeno + + var/amount_of_friendly_xenos = length(nearby_friendly_xenos) + if(amount_of_friendly_xenos > 1) + // Split the reward amongst every xeno nearby, including themselves. + var/biomass_per_xeno = round(15/amount_of_friendly_xenos, 0.1) + for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) + nearby_friendly_xeno.gain_biomass(biomass_per_xeno) + else + X.gain_biomass(15) ///////////////////////////////// // blessing Menu From e9dfb3256ec7940640d658f4220b3155884bbfcf Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:16:02 -0700 Subject: [PATCH 056/106] unneeded checks --- .../mob/living/carbon/xenomorph/abilities.dm | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index f5bc67fd413e4..4e99f8e6d3bd0 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -1406,14 +1406,10 @@ continue nearby_friendly_xenos += nearby_xeno - var/amount_of_friendly_xenos = length(nearby_friendly_xenos) - if(amount_of_friendly_xenos > 1) - // Split the reward amongst every xeno nearby, including themselves. - var/biomass_per_xeno = round(15/amount_of_friendly_xenos, 0.1) - for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) - nearby_friendly_xeno.gain_biomass(biomass_per_xeno) - else - X.gain_biomass(15) + // Split the reward amongst every xeno nearby, including themselves. + var/biomass_per_xeno = round(15/length(nearby_friendly_xenos), 0.1) + for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) + nearby_friendly_xeno.gain_biomass(biomass_per_xeno) ADD_TRAIT(victim, TRAIT_PSY_DRAINED, TRAIT_PSY_DRAINED) if(HAS_TRAIT(victim, TRAIT_UNDEFIBBABLE)) @@ -1533,14 +1529,10 @@ continue nearby_friendly_xenos += nearby_xeno - var/amount_of_friendly_xenos = length(nearby_friendly_xenos) - if(amount_of_friendly_xenos > 1) - // Split the reward amongst every xeno nearby, including themselves. - var/biomass_per_xeno = round(15/amount_of_friendly_xenos, 0.1) - for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) - nearby_friendly_xeno.gain_biomass(biomass_per_xeno) - else - X.gain_biomass(15) + // Split the reward amongst every xeno nearby, including themselves. + var/biomass_per_xeno = round(15/length(nearby_friendly_xenos), 0.1) + for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) + nearby_friendly_xeno.gain_biomass(biomass_per_xeno) ///////////////////////////////// // blessing Menu From 6ecfacb41a7f0f546b29ed215a7652bef3514199 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:43:16 -0700 Subject: [PATCH 057/106] ignore this terrible mistake :) --- code/modules/mob/living/carbon/xenomorph/abilities.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index 4e99f8e6d3bd0..05a56666f4ee3 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -1534,6 +1534,10 @@ for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) nearby_friendly_xeno.gain_biomass(biomass_per_xeno) + if(owner.client) + var/datum/personal_statistics/personal_statistics = GLOB.personal_statistics_list[owner.ckey] + personal_statistics.cocooned++ + ///////////////////////////////// // blessing Menu ///////////////////////////////// From d1a8597295c35834ee891e918338780c66bdd298 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Tue, 29 Oct 2024 15:45:41 -0700 Subject: [PATCH 058/106] autodoc --- code/modules/mob/living/carbon/xenomorph/mutation_datum.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 942a1072d6726..99b258571babd 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -73,6 +73,7 @@ GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) SStgui.close_user_uis(usr, src) +/// Tries to purchase a mutation. Denies if possible. Otherwise, removes conflicting mutations and gives the purchased mutation. /datum/mutation_datum/proc/try_purchase_mutation(mob/living/carbon/xenomorph/xeno_purchaser, upgrade_name) if(!upgrade_name) return From 2197116192e930d79077d211e534dc8f3191a766 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Wed, 30 Oct 2024 02:17:23 -0700 Subject: [PATCH 059/106] unused defines & addresses latest comment/review --- code/__DEFINES/status_effects.dm | 18 +- code/__DEFINES/xeno.dm | 33 +- code/datums/status_effects/xeno_buffs.dm | 299 ++++++++---------- .../living/carbon/xenomorph/mutation_datum.dm | 20 +- 4 files changed, 162 insertions(+), 208 deletions(-) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 7653d303fb077..9fed04fcb8169 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -39,23 +39,23 @@ #define STATUS_EFFECT_DRAIN_SURGE /datum/status_effect/drain_surge -#define STATUS_EFFECT_UPGRADE_CARAPACE /datum/status_effect/upgrade_carapace +#define STATUS_EFFECT_UPGRADE_CARAPACE /datum/status_effect/mutation_upgrade/carapace -#define STATUS_EFFECT_UPGRADE_REGENERATION /datum/status_effect/upgrade_regeneration +#define STATUS_EFFECT_UPGRADE_REGENERATION /datum/status_effect/mutation_upgrade/regeneration -#define STATUS_EFFECT_UPGRADE_VAMPIRISM /datum/status_effect/upgrade_vampirism +#define STATUS_EFFECT_UPGRADE_VAMPIRISM /datum/status_effect/mutation_upgrade/vampirism -#define STATUS_EFFECT_UPGRADE_CELERITY /datum/status_effect/upgrade_celerity +#define STATUS_EFFECT_UPGRADE_CELERITY /datum/status_effect/mutation_upgrade/celerity -#define STATUS_EFFECT_UPGRADE_ADRENALINE /datum/status_effect/upgrade_adrenaline +#define STATUS_EFFECT_UPGRADE_ADRENALINE /datum/status_effect/mutation_upgrade/adrenaline -#define STATUS_EFFECT_UPGRADE_CRUSH /datum/status_effect/upgrade_crush +#define STATUS_EFFECT_UPGRADE_CRUSH /datum/status_effect/mutation_upgrade/crush -#define STATUS_EFFECT_UPGRADE_TOXIN /datum/status_effect/upgrade_toxin +#define STATUS_EFFECT_UPGRADE_TOXIN /datum/status_effect/mutation_upgrade/toxin -#define STATUS_EFFECT_UPGRADE_PHERO /datum/status_effect/upgrade_pheromones +#define STATUS_EFFECT_UPGRADE_PHERO /datum/status_effect/mutation_upgrade/pheromones -#define STATUS_EFFECT_UPGRADE_TRAIL /datum/status_effect/upgrade_trail +#define STATUS_EFFECT_UPGRADE_TRAIL /datum/status_effect/mutation_upgrade/trail #define STATUS_EFFECT_MINDMEND /datum/status_effect/mindmeld diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index bc35c6151347f..00e2b35274ff1 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -219,23 +219,28 @@ GLOBAL_LIST_INIT(xeno_ai_spawnable, list( /// Life runs every 2 seconds, but we don't want to multiply all healing by 2 due to seconds_per_tick #define XENO_PER_SECOND_LIFE_MOD 0.5 -GLOBAL_LIST_INIT(xeno_survival_upgrades, list( - /datum/status_effect/upgrade_carapace, - /datum/status_effect/upgrade_regeneration, - /datum/status_effect/upgrade_vampirism, +// Mutations +GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) + +GLOBAL_LIST_INIT(mutation_upgrades_buyable, list( + /datum/mutation_upgrade/survival/carapace, + /datum/mutation_upgrade/survival/regeneration, + /datum/mutation_upgrade/survival/vampirism, + /datum/mutation_upgrade/attack/celerity, + /datum/mutation_upgrade/attack/adrenaline, + /datum/mutation_upgrade/attack/crush, + /datum/mutation_upgrade/utility/toxin, + /datum/mutation_upgrade/utility/pheromones, + /datum/mutation_upgrade/utility/toxin )) -GLOBAL_LIST_INIT(xeno_attack_upgrades, list( - /datum/status_effect/upgrade_celerity, - /datum/status_effect/upgrade_adrenaline, - /datum/status_effect/upgrade_crush, -)) +#define MUTATION_CATEGORY_SURVIVAL "Survival" +#define MUTATION_CATEGORY_ATTACK "Attack" +#define MUTATION_CATEGORY_UTILITY "Utility" -GLOBAL_LIST_INIT(xeno_utility_upgrades, list( - /datum/status_effect/upgrade_toxin, - /datum/status_effect/upgrade_pheromones, - /datum/status_effect/upgrade_trail, -)) +#define MUTATION_STRUCTURE_CHAMBER "shell" +#define MUTATION_STRUCTURE_SPUR "spur" +#define MUTATION_STRUCTURE_VEIL "veil" #define XENO_UPGRADE_BIOMASS_COST_T1 15 #define XENO_UPGRADE_BIOMASS_COST_T2 20 diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 45ead03ff3c33..c2cbc80468ecd 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -875,86 +875,98 @@ // *************************************** // *********** Upgrade Chambers Buffs - Survival // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_carapace +/atom/movable/screen/alert/status_effect/carapace name = "Carapace" desc = "Armor increased." icon_state = "xenobuff_carapace" -/datum/status_effect/upgrade_carapace - id = "upgrade_carapace" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_carapace +/datum/status_effect/mutation_upgrade /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner - /// The amount of soft armor given. - var/armor_buff_per_chamber = 2.5 - /// The amount of times to multiply the armor buff by. + /// The structure to base chamber_scaling on. + var/chamber_structure + /// The amount of times to multiply the main effect by. var/chamber_scaling = 0 -/datum/status_effect/upgrade_carapace/on_apply() +/datum/status_effect/mutation_upgrade/on_apply() if(!isxeno(owner)) return FALSE buff_owner = owner - chamber_scaling = length(buff_owner.hive.shell_chambers) + update_chamber_scaling() + return TRUE + +/// Sets the chamber_scaling based on the amount of chambers in the xeno's hiver. +/datum/status_effect/mutation_upgrade/proc/update_chamber_scaling() + switch(chamber_structure) + if(MUTATION_STRUCTURE_CHAMBER) + chamber_scaling = length(buff_owner.hive?.shell_chambers) + if(MUTATION_STRUCTURE_SPUR) + chamber_scaling = length(buff_owner.hive?.spur_chambers) + if(MUTATION_STRUCTURE_VEIL) + chamber_scaling = length(buff_owner.hive?.veil_chambers) + +/datum/status_effect/mutation_upgrade/carapace + id = "mutation_upgrade_carapace" + alert_type = /atom/movable/screen/alert/status_effect/carapace + chamber_structure = MUTATION_STRUCTURE_CHAMBER + /// The amount of soft armor given. + var/armor_buff_per_chamber = 2.5 + +/datum/status_effect/mutation_upgrade/carapace/on_apply() + if(!..()) + return FALSE RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(armor_buff_per_chamber * chamber_scaling) return TRUE -/datum/status_effect/upgrade_carapace/on_remove() +/datum/status_effect/mutation_upgrade/carapace/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(-armor_buff_per_chamber * chamber_scaling) return ..() /// Sets the chamber_scaling to the amount of active survival chambers and adjusts soft armor accordingly. -/datum/status_effect/upgrade_carapace/proc/update_buff() +/datum/status_effect/mutation_upgrade/carapace/proc/update_buff() SIGNAL_HANDLER buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(armor_buff_per_chamber * (length(buff_owner.hive.shell_chambers) - chamber_scaling)) - chamber_scaling = length(buff_owner.hive.shell_chambers) + update_chamber_scaling() + // *************************************** // *************************************** // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_regeneration +/atom/movable/screen/alert/status_effect/regeneration name = "Regeneration" desc = "Regeneration increased." icon_state = "xenobuff_regeneration" -/datum/status_effect/upgrade_regeneration - id = "upgrade_regeneration" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_regeneration - /// Owner typed as an xenomorph. - var/mob/living/carbon/xenomorph/buff_owner +/datum/status_effect/mutation_upgrade/regeneration + id = "mutation_upgrade_regeneration" + alert_type = /atom/movable/screen/alert/status_effect/regeneration + chamber_structure = MUTATION_STRUCTURE_CHAMBER /// The amount of max health to be regenerated everytime the proc 'heal_wounds' is called. var/health_regen_per_chamber = 0.015 // 1.5% /// The amount of sunder to be regenerated everytime the proc 'heal_wounds' is called. var/sunder_regen_per_chamber = 0.166 - /// The amount of times to multiply health/sunder regen by. - var/chamber_scaling = 0 -/datum/status_effect/upgrade_regeneration/on_apply() - if(!isxeno(owner)) +/datum/status_effect/mutation_upgrade/regeneration/on_apply() + if(!..()) return FALSE - buff_owner = owner - chamber_scaling = length(buff_owner.hive.shell_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_HEALTH_REGEN, PROC_REF(on_heal_wounds)) return TRUE -/datum/status_effect/upgrade_regeneration/on_remove() +/datum/status_effect/mutation_upgrade/regeneration/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) UnregisterSignal(buff_owner, COMSIG_XENOMORPH_HEALTH_REGEN) return ..() /// Sets the chamber_scaling to the amount of active survival chambers. -/datum/status_effect/upgrade_regeneration/proc/update_buff() +/datum/status_effect/mutation_upgrade/regeneration/proc/update_buff() SIGNAL_HANDLER - chamber_scaling = length(buff_owner.hive.shell_chambers) + update_chamber_scaling() /// Heals the xenomorph's health and sunder based on assigned variables. -/datum/status_effect/upgrade_regeneration/proc/on_heal_wounds(mob/living/carbon/xenomorph/source_xenomorph, heal_data, seconds_per_tick) +/datum/status_effect/mutation_upgrade/regeneration/proc/on_heal_wounds(mob/living/carbon/xenomorph/source_xenomorph, heal_data, seconds_per_tick) SIGNAL_HANDLER if(!chamber_scaling) return @@ -967,49 +979,44 @@ // *************************************** // *************************************** // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_vampirism +/atom/movable/screen/alert/status_effect/vampirism name = "Vampirism" desc = "Leech from attacks." icon_state = "xenobuff_vampirism" -/datum/status_effect/upgrade_vampirism - id = "upgrade_vampirism" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_vampirism - /// Owner typed as an xenomorph. - var/mob/living/carbon/xenomorph/buff_owner +/datum/status_effect/mutation_upgrade/vampirism + id = "mutation_upgrade_vampirism" + alert_type = /atom/movable/screen/alert/status_effect/vampirism + chamber_structure = MUTATION_STRUCTURE_CHAMBER /// The amount of max health to be regenerated the owner hits an alive human. var/leech_buff_per_chamber = 0.033 - /// The amount of times to multiply the vampirism by. - var/chamber_scaling = 0 -/datum/status_effect/upgrade_vampirism/on_apply() - if(!isxeno(owner)) +/datum/status_effect/mutation_upgrade/vampirism/on_apply() + if(!..()) return FALSE - buff_owner = owner + // Ravagers gets half of the effect since they eventually get their own version of vampirism. + if(isxenoravager(buff_owner)) + chamber_scaling /= 2 RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_slash)) - // Ravagers gets half of the effect since they eventually get their own version of vampirism. - chamber_scaling = isxenoravager(buff_owner) ? (length(buff_owner.hive.shell_chambers) * 0.5) : length(buff_owner.hive.shell_chambers) return TRUE -/datum/status_effect/upgrade_vampirism/on_remove() +/datum/status_effect/mutation_upgrade/vampirism/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING) return ..() /// Sets the chamber_scaling to the amount of active survival chambers. -/datum/status_effect/upgrade_vampirism/proc/update_buff() +/datum/status_effect/mutation_upgrade/vampirism/proc/update_buff() SIGNAL_HANDLER - chamber_scaling = isxenoravager(buff_owner) ? (length(buff_owner.hive.shell_chambers) * 0.5) : length(buff_owner.hive.shell_chambers) + update_chamber_scaling() + if(isxenoravager(buff_owner)) + chamber_scaling /= 2 /// Heals the xenomorph for hitting a non-dead human by a percentage of their max health. -/datum/status_effect/upgrade_vampirism/proc/on_slash(datum/source, mob/living/target) +/datum/status_effect/mutation_upgrade/vampirism/proc/on_slash(datum/source, mob/living/target) SIGNAL_HANDLER - if(target.stat == DEAD) - return - if(!ishuman(target)) + if(target.stat == DEAD || !ishuman(target)) return var/health_amount = buff_owner.maxHealth * leech_buff_per_chamber * chamber_scaling HEAL_XENO_DAMAGE(buff_owner, health_amount, FALSE) @@ -1018,86 +1025,72 @@ // *************************************** // *********** Upgrade Chambers Buffs - Attack // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_celerity +/atom/movable/screen/alert/status_effect/celerity name = "Celerity" desc = "Run faster." icon_state = "xenobuff_attack" -/datum/status_effect/upgrade_celerity - id = "upgrade_celerity" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_celerity - /// Owner typed as an xenomorph. - var/mob/living/carbon/xenomorph/buff_owner +/datum/status_effect/mutation_upgrade/celerity + id = "mutation_upgrade_celerity" + alert_type = /atom/movable/screen/alert/status_effect/celerity + chamber_structure = MUTATION_STRUCTURE_SPUR /// The amount of movement speed the owner get. var/speed_buff_per_chamber = 0.1 - /// The amount of times to multiply the speed by. - var/chamber_scaling = 0 -/datum/status_effect/upgrade_celerity/on_apply() - if(!isxeno(owner)) +/datum/status_effect/mutation_upgrade/celerity/on_apply() + if(!..()) return FALSE - buff_owner = owner - chamber_scaling = length(buff_owner.hive.spur_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) buff_owner.add_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF, TRUE, 0, NONE, TRUE, -speed_buff_per_chamber * chamber_scaling) return TRUE -/datum/status_effect/upgrade_celerity/on_remove() +/datum/status_effect/mutation_upgrade/celerity/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK) buff_owner.remove_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF) return ..() /// Sets the chamber_scaling to the amount of active spur chambers and adjusts movement speed accordingly. -/datum/status_effect/upgrade_celerity/proc/update_buff() +/datum/status_effect/mutation_upgrade/celerity/proc/update_buff() SIGNAL_HANDLER - chamber_scaling = length(buff_owner.hive.spur_chambers) + update_chamber_scaling() buff_owner.add_movespeed_modifier(MOVESPEED_ID_CELERITY_BUFF, TRUE, 0, NONE, TRUE, -speed_buff_per_chamber * chamber_scaling) // *************************************** // *************************************** // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_adrenaline +/atom/movable/screen/alert/status_effect/adrenaline name = "Adrenaline" desc = "Regenerate plasma." icon_state = "xenobuff_attack" -/datum/status_effect/upgrade_adrenaline - id = "upgrade_adrenaline" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_adrenaline - /// Owner typed as an xenomorph. - var/mob/living/carbon/xenomorph/buff_owner +/datum/status_effect/mutation_upgrade/adrenaline + id = "mutation_upgrade_adrenaline" + alert_type = /atom/movable/screen/alert/status_effect/adrenaline + chamber_structure = MUTATION_STRUCTURE_SPUR /// The amount of plasma to regenerate based on their caste's plasma regeneration. var/plasma_regen_buff_per_chamber = 0.1 // 10% /// The amount of plasma to regenerate based on their caste's maximum plasma. var/plasma_percentage_buff_per_chamber = 0.01 // 1% - /// The amount of times to multiply both plasma regenerations by. - var/chamber_scaling = 0 -/datum/status_effect/upgrade_adrenaline/on_apply() - if(!isxeno(owner)) +/datum/status_effect/mutation_upgrade/adrenaline/on_apply() + if(!..()) return FALSE - buff_owner = owner - chamber_scaling = length(buff_owner.hive.spur_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_PLASMA_REGEN, PROC_REF(on_plasma_regen)) return TRUE -/datum/status_effect/upgrade_adrenaline/on_remove() +/datum/status_effect/mutation_upgrade/adrenaline/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK) UnregisterSignal(buff_owner, COMSIG_XENOMORPH_PLASMA_REGEN) return ..() /// Sets the chamber_scaling to the amount of active spur chambers. -/datum/status_effect/upgrade_adrenaline/proc/update_buff() +/datum/status_effect/mutation_upgrade/adrenaline/proc/update_buff() SIGNAL_HANDLER - chamber_scaling = length(buff_owner.hive.spur_chambers) + update_chamber_scaling() /// Gives the xenomorph more plasma (according to their plasma regeneration and adjusted maximum) everytime they are suppose to regen plasma. -/datum/status_effect/upgrade_adrenaline/proc/on_plasma_regen(mob/living/carbon/xenomorph/source_xenomorph, plasma_mod, seconds_per_tick) +/datum/status_effect/mutation_upgrade/adrenaline/proc/on_plasma_regen(mob/living/carbon/xenomorph/source_xenomorph, plasma_mod, seconds_per_tick) SIGNAL_HANDLER if(!chamber_scaling) return @@ -1112,46 +1105,39 @@ // *************************************** // *************************************** // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_crush +/atom/movable/screen/alert/status_effect/crush name = "Crush" desc = "Additional damage to objects." icon_state = "xenobuff_attack" -/datum/status_effect/upgrade_crush - id = "upgrade_crush" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_crush - /// Owner typed as an xenomorph. - var/mob/living/carbon/xenomorph/buff_owner +/datum/status_effect/mutation_upgrade/crush + id = "mutation_upgrade_crush" + alert_type = /atom/movable/screen/alert/status_effect/crush + chamber_structure = MUTATION_STRUCTURE_SPUR /// The bonus damage to deal as percentage. var/damage_buff_per_chamber = 0.333 // 33.3% /// The armour pentration the damage damage has. var/penetration_buff_per_chamber = 10 - /// The amount of times to multiply the armour pentration by. - var/chamber_scaling = 0 -/datum/status_effect/upgrade_crush/on_apply() - if(!isxeno(owner)) +/datum/status_effect/mutation_upgrade/crush/on_apply() + if(!..()) return FALSE - buff_owner = owner - chamber_scaling = length(buff_owner.hive.spur_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_OBJ, PROC_REF(on_obj_attack)) return TRUE -/datum/status_effect/upgrade_crush/on_remove() +/datum/status_effect/mutation_upgrade/crush/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_ATTACK) UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_OBJ) return ..() /// Sets the chamber_scaling to the amount of active spur chambers. -/datum/status_effect/upgrade_crush/proc/update_buff() +/datum/status_effect/mutation_upgrade/crush/proc/update_buff() SIGNAL_HANDLER - chamber_scaling = length(buff_owner.hive.spur_chambers) + update_chamber_scaling() /// Deals bonus damage along with armour pentration to the object. -/datum/status_effect/upgrade_crush/proc/on_obj_attack(datum/source, obj/attacked) +/datum/status_effect/mutation_upgrade/crush/proc/on_obj_attack(datum/source, obj/attacked) SIGNAL_HANDLER if(!chamber_scaling) return @@ -1169,13 +1155,13 @@ // *************************************** // *********** Upgrade Chambers Buffs - Utility // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_toxin +/atom/movable/screen/alert/status_effect/toxin name = "Toxin" desc = "Inject toxin on attack. Click to change toxin." icon_state = "xenobuff_generic" -/atom/movable/screen/alert/status_effect/upgrade_toxin/Click() - var/datum/status_effect/upgrade_toxin/status_effect = attached_effect +/atom/movable/screen/alert/status_effect/toxin/Click() + var/datum/status_effect/mutation_upgrade/toxin/status_effect = attached_effect var/datum/reagent/toxin/toxin_choice = show_radial_menu(status_effect.buff_owner, status_effect.buff_owner, GLOB.defiler_toxin_images_list, radius = 35, require_near = TRUE) if(!toxin_choice) return @@ -1186,41 +1172,34 @@ break status_effect.buff_owner.balloon_alert(status_effect.buff_owner, "[toxin_choice]") -/datum/status_effect/upgrade_toxin - id = "upgrade_toxin" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_toxin - /// Owner typed as an xenomorph. - var/mob/living/carbon/xenomorph/buff_owner +/datum/status_effect/mutation_upgrade/toxin + id = "mutation_upgrade_toxin" + alert_type = /atom/movable/screen/alert/status_effect/toxin + chamber_structure = MUTATION_STRUCTURE_VEIL /// The amount of toxins to inject. var/toxin_amount_per_chamber = 1 - /// The amount of times to multiply the toxin amount by. - var/chamber_scaling = 0 /// Currently selected reagent to inject. var/datum/reagent/toxin/selected_reagent = /datum/reagent/toxin/xeno_neurotoxin -/datum/status_effect/upgrade_toxin/on_apply() - if(!isxeno(owner)) +/datum/status_effect/mutation_upgrade/toxin/on_apply() + if(!..()) return FALSE - buff_owner = owner - chamber_scaling = length(buff_owner.hive.veil_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_slash)) return TRUE -/datum/status_effect/upgrade_toxin/on_remove() +/datum/status_effect/mutation_upgrade/toxin/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING) return ..() /// Sets the chamber_scaling to the amount of active veil chambers. -/datum/status_effect/upgrade_toxin/proc/update_buff() +/datum/status_effect/mutation_upgrade/toxin/proc/update_buff() SIGNAL_HANDLER - chamber_scaling = length(buff_owner.hive.veil_chambers) + update_chamber_scaling() /// Injects the human target with a variable amount of the selected reagent. -/datum/status_effect/upgrade_toxin/proc/on_slash(datum/source, mob/living/target) +/datum/status_effect/mutation_upgrade/toxin/proc/on_slash(datum/source, mob/living/target) SIGNAL_HANDLER if(!chamber_scaling || target.stat == DEAD || !ishuman(target) || !target.can_sting()) return @@ -1230,13 +1209,13 @@ // *************************************** // *************************************** // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_pheromones +/atom/movable/screen/alert/status_effect/pheromones name = "Pheromones" desc = "Allows to emit pheromones. Click to change pheromones." icon_state = "xenobuff_phero" -/atom/movable/screen/alert/status_effect/upgrade_pheromones/Click() - var/datum/status_effect/upgrade_pheromones/status_effect = attached_effect +/atom/movable/screen/alert/status_effect/pheromones/Click() + var/datum/status_effect/mutation_upgrade/pheromones/status_effect = attached_effect var/phero_choice = show_radial_menu(status_effect.buff_owner, status_effect.buff_owner, GLOB.pheromone_images_list, radius = 35, require_near = TRUE) if(!phero_choice) return @@ -1244,13 +1223,10 @@ status_effect.emitted_aura = phero_choice status_effect.create_aura() -/datum/status_effect/upgrade_pheromones - id = "upgrade_pheromones" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_pheromones - /// Owner typed as an xenomorph. - var/mob/living/carbon/xenomorph/buff_owner +/datum/status_effect/mutation_upgrade/pheromones + id = "mutation_upgrade_pheromones" + alert_type = /atom/movable/screen/alert/status_effect/pheromones + chamber_structure = MUTATION_STRUCTURE_VEIL /// The aura. var/datum/aura_bearer/current_aura /// The aura to emit. @@ -1259,46 +1235,42 @@ var/aura_power_base = 1 /// The phero power to increase by. var/aura_power_per_chamber = 1 - /// The amount of times to multiply the aura power by. - var/chamber_scaling = 0 -/datum/status_effect/upgrade_pheromones/on_apply() - if(!isxeno(owner)) +/datum/status_effect/mutation_upgrade/pheromones/on_apply() + if(!..()) return FALSE - buff_owner = owner - chamber_scaling = length(buff_owner.hive.veil_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) create_aura() return TRUE -/datum/status_effect/upgrade_pheromones/on_remove() +/datum/status_effect/mutation_upgrade/pheromones/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) if(current_aura) current_aura.stop_emitting() return ..() /// (Re)creates the aura. -/datum/status_effect/upgrade_pheromones/proc/create_aura() +/datum/status_effect/mutation_upgrade/pheromones/proc/create_aura() if(current_aura) QDEL_NULL(current_aura) current_aura = SSaura.add_emitter(buff_owner, emitted_aura, 6 + aura_power_per_chamber * chamber_scaling * 2, aura_power_base + aura_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) /// Sets the chamber_scaling to the amount of active veil chambers and recreates the aura. -/datum/status_effect/upgrade_pheromones/proc/update_buff() +/datum/status_effect/mutation_upgrade/pheromones/proc/update_buff() SIGNAL_HANDLER - chamber_scaling = length(buff_owner.hive.veil_chambers) + update_chamber_scaling() create_aura() // *************************************** // *************************************** // *************************************** -/atom/movable/screen/alert/status_effect/upgrade_trail +/atom/movable/screen/alert/status_effect/trail name = "Trail" desc = "We leave an acid trail behind. Click to change trail." icon_state = "xenobuff_generic" -/atom/movable/screen/alert/status_effect/upgrade_trail/Click() - var/datum/status_effect/upgrade_trail/effect = attached_effect +/atom/movable/screen/alert/status_effect/trail/Click() + var/datum/status_effect/mutation_upgrade/trail/effect = attached_effect if(effect.buff_owner.incapacitated(TRUE)) to_chat(usr, span_warning("Cant do that right now!")) return @@ -1309,19 +1281,14 @@ effect.selected_trail = effect.selectable_trails[i+1] effect.buff_owner.balloon_alert(effect.buff_owner, "[effect.selected_trail.name]") -/datum/status_effect/upgrade_trail - id = "upgrade_trail" - duration = -1 - status_type = STATUS_EFFECT_UNIQUE - alert_type = /atom/movable/screen/alert/status_effect/upgrade_trail - /// Owner typed as an xenomorph. - var/mob/living/carbon/xenomorph/buff_owner +/datum/status_effect/mutation_upgrade/trail + id = "mutation_upgrade_trail" + alert_type = /atom/movable/screen/alert/status_effect/trail + chamber_structure = MUTATION_STRUCTURE_VEIL /// The initial odds of the trail spawning. var/base_chance = 25 /// The additional chance of the trail starting. var/chance_per_chamber = 25 - /// The amount of times to increase the additional chance of trail spawning by. - var/chamber_scaling = 0 /// The selected trail that will spawn upon moving. var/obj/selected_trail = /obj/effect/xenomorph/spray /// A list of trails that can be selected @@ -1330,27 +1297,25 @@ /obj/alien/resin/sticky/thin ) -/datum/status_effect/upgrade_trail/on_apply() - if(!isxeno(owner)) +/datum/status_effect/mutation_upgrade/trail/on_apply() + if(!..()) return FALSE - buff_owner = owner - chamber_scaling = length(buff_owner.hive.veil_chambers) RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_MOVABLE_MOVED, PROC_REF(create_trail)) return TRUE -/datum/status_effect/upgrade_trail/on_remove() +/datum/status_effect/mutation_upgrade/trail/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) UnregisterSignal(buff_owner, COMSIG_MOVABLE_MOVED) return ..() /// Sets the chamber_scaling to the amount of active veil chambers. -/datum/status_effect/upgrade_trail/proc/update_buff() +/datum/status_effect/mutation_upgrade/trail/proc/update_buff() SIGNAL_HANDLER - chamber_scaling = length(buff_owner.hive.veil_chambers) + update_chamber_scaling() /// Rolls the dice and creates the selected trail if the dice is right. -/datum/status_effect/upgrade_trail/proc/create_trail() +/datum/status_effect/mutation_upgrade/trail/proc/create_trail() SIGNAL_HANDLER if(buff_owner.incapacitated() || buff_owner.lying_angle || buff_owner.resting) return diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 99b258571babd..368fd6f34262c 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -1,13 +1,3 @@ -GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) - -#define MUTATION_CATEGORY_SURVIVAL "Survival" -#define MUTATION_CATEGORY_ATTACK "Attack" -#define MUTATION_CATEGORY_UTILITY "Utility" - -#define MUTATION_STRUCTURE_CHAMBER "shell" -#define MUTATION_STRUCTURE_SPUR "spur" -#define MUTATION_STRUCTURE_VEIL "veil" - /datum/mutation_datum interaction_flags = INTERACT_UI_INTERACT @@ -93,14 +83,8 @@ GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) to_chat(usr, span_warning("You don't have enough biomass!")) return - var/list/excluded_mutation_base_upgrades = list( - /datum/mutation_upgrade/survival, - /datum/mutation_upgrade/attack, - /datum/mutation_upgrade/utility - ) - var/datum/mutation_upgrade/chosen_mutation_upgrade - for(var/datum/mutation_upgrade/subtype_mutation AS in subtypesof(/datum/mutation_upgrade) - excluded_mutation_base_upgrades) + for(var/datum/mutation_upgrade/subtype_mutation AS in GLOB.mutation_upgrades_buyable) if(subtype_mutation.name == upgrade_name) chosen_mutation_upgrade = subtype_mutation break @@ -128,7 +112,7 @@ GLOBAL_DATUM_INIT(mutation_selector, /datum/mutation_datum, new) return var/list/mutation_status_effects_to_remove = list() - for(var/datum/mutation_upgrade/subtype_mutation AS in subtypesof(/datum/mutation_upgrade) - excluded_mutation_base_upgrades) + for(var/datum/mutation_upgrade/subtype_mutation AS in GLOB.mutation_upgrades_buyable) if(chosen_mutation_upgrade.category == subtype_mutation.category) mutation_status_effects_to_remove += subtype_mutation.status_effect From c52be9c5487f047f69286cf5170f8e0eaaa27b8f Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Wed, 30 Oct 2024 02:18:20 -0700 Subject: [PATCH 060/106] typo comment --- code/datums/status_effects/xeno_buffs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index c2cbc80468ecd..db3210a838836 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -895,7 +895,7 @@ update_chamber_scaling() return TRUE -/// Sets the chamber_scaling based on the amount of chambers in the xeno's hiver. +/// Sets the chamber_scaling based on the amount of chambers in the xeno's hive. /datum/status_effect/mutation_upgrade/proc/update_chamber_scaling() switch(chamber_structure) if(MUTATION_STRUCTURE_CHAMBER) From 69a768ed18ec9c06e8606cea951897b90d737997 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Wed, 30 Oct 2024 02:23:39 -0700 Subject: [PATCH 061/106] sorting --- code/datums/status_effects/xeno_buffs.dm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index db3210a838836..9bd45ab68bbb1 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -873,13 +873,8 @@ return ..() // *************************************** -// *********** Upgrade Chambers Buffs - Survival +// *********** Upgrade Chambers Buffs // *************************************** -/atom/movable/screen/alert/status_effect/carapace - name = "Carapace" - desc = "Armor increased." - icon_state = "xenobuff_carapace" - /datum/status_effect/mutation_upgrade /// Owner typed as an xenomorph. var/mob/living/carbon/xenomorph/buff_owner @@ -905,6 +900,14 @@ if(MUTATION_STRUCTURE_VEIL) chamber_scaling = length(buff_owner.hive?.veil_chambers) +// *************************************** +// *********** Upgrade Chambers Buffs - Survival +// *************************************** +/atom/movable/screen/alert/status_effect/carapace + name = "Carapace" + desc = "Armor increased." + icon_state = "xenobuff_carapace" + /datum/status_effect/mutation_upgrade/carapace id = "mutation_upgrade_carapace" alert_type = /atom/movable/screen/alert/status_effect/carapace From 236d1fca866612ea15a53a097227740689026992 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Wed, 30 Oct 2024 02:24:35 -0700 Subject: [PATCH 062/106] unwanted TRUE --- code/datums/status_effects/xeno_buffs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 9bd45ab68bbb1..34b471add958d 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1274,7 +1274,7 @@ /atom/movable/screen/alert/status_effect/trail/Click() var/datum/status_effect/mutation_upgrade/trail/effect = attached_effect - if(effect.buff_owner.incapacitated(TRUE)) + if(effect.buff_owner.incapacitated()) to_chat(usr, span_warning("Cant do that right now!")) return var/i = effect.selectable_trails.Find(effect.selected_trail) From f75896e20b72f1f7f547917688104e3c63156922 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Fri, 1 Nov 2024 23:14:13 -0700 Subject: [PATCH 063/106] halve regeneration & vamp --- code/datums/status_effects/xeno_buffs.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 34b471add958d..b08d876a0858e 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -947,7 +947,7 @@ alert_type = /atom/movable/screen/alert/status_effect/regeneration chamber_structure = MUTATION_STRUCTURE_CHAMBER /// The amount of max health to be regenerated everytime the proc 'heal_wounds' is called. - var/health_regen_per_chamber = 0.015 // 1.5% + var/health_regen_per_chamber = 0.008 // 0.8% /// The amount of sunder to be regenerated everytime the proc 'heal_wounds' is called. var/sunder_regen_per_chamber = 0.166 @@ -992,7 +992,7 @@ alert_type = /atom/movable/screen/alert/status_effect/vampirism chamber_structure = MUTATION_STRUCTURE_CHAMBER /// The amount of max health to be regenerated the owner hits an alive human. - var/leech_buff_per_chamber = 0.033 + var/leech_buff_per_chamber = 0.016 /datum/status_effect/mutation_upgrade/vampirism/on_apply() if(!..()) From 692e09203f8d86ca7293e2a41dabd60bcb07131a Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 2 Nov 2024 16:08:28 -0700 Subject: [PATCH 064/106] nerf celerity in half for test merge --- code/datums/status_effects/xeno_buffs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index b08d876a0858e..d4b3b57dfafd7 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1038,7 +1038,7 @@ alert_type = /atom/movable/screen/alert/status_effect/celerity chamber_structure = MUTATION_STRUCTURE_SPUR /// The amount of movement speed the owner get. - var/speed_buff_per_chamber = 0.1 + var/speed_buff_per_chamber = 0.05 /datum/status_effect/mutation_upgrade/celerity/on_apply() if(!..()) From 81928b1b12f788ace6cb6434630535cb26a2786a Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 2 Nov 2024 16:17:23 -0700 Subject: [PATCH 065/106] autodoc pt. 1 of 2 --- code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm index ad6ba7cdc2f16..285665df9b3e2 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm @@ -267,6 +267,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( /datum/hive_upgrade/building/upgrade_chamber gamemode_flags = ABILITY_NUCLEARWAR building_loc = 0 + /// The maximum amount of buildings that can exist before being disallowed from buying more. var/max_chambers = 3 /datum/hive_upgrade/building/upgrade_chamber/shell From 3735d5fa38e0ec729d8f5f7cc8bc0abc77f8983a Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 2 Nov 2024 16:24:42 -0700 Subject: [PATCH 066/106] autodoc pt. 2 of 2 --- code/modules/mob/living/carbon/xenomorph/mutation_datum.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 368fd6f34262c..eea39af3996c0 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -124,10 +124,15 @@ xeno_purchaser.apply_status_effect(chosen_mutation_upgrade.status_effect) /datum/mutation_upgrade + /// The name that is displayed in the TGUI. var/name + /// The description that is displayed in the TGUI. var/desc + /// The category slot that this upgrade takes. Upgrades that conflict with this category slot will be removed/replaced. var/category + /// The structure that needs to exist for a successful purchase. var/required_structure + /// The status effect given upon successful purchase. var/datum/status_effect/status_effect /datum/mutation_upgrade/survival From 75b569672b4b8b41f1fd375aea69842ef2f79b83 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 2 Nov 2024 16:49:28 -0700 Subject: [PATCH 067/106] autodoc pt. 3 of 2 :) --- code/modules/mob/living/carbon/xenomorph/xenoprocs.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index b69406ad740b5..29ecaa1dde579 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -581,6 +581,7 @@ /mob/living/carbon/xenomorph/on_eord(turf/destination) revive(TRUE) +/// Opens the mutation selector UI. /mob/living/carbon/xenomorph/verb/upgrade_menu() set name = "Mutations Menu" set desc = "See current Upgrade Chambers and get mutations for yourself" From 63dba11e149d763d919ad84284db3d1a72479a9f Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 3 Nov 2024 09:32:27 -0800 Subject: [PATCH 068/106] ui_static_data --- .../modules/mob/living/carbon/xenomorph/mutation_datum.dm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index eea39af3996c0..06a36b014bfb3 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -17,6 +17,12 @@ data["spur_chambers"] = length(xeno_user.hive?.spur_chambers) data["veil_chambers"] = length(xeno_user.hive?.veil_chambers) data["biomass"] = xeno_user.biomass + return data + +/datum/mutation_datum/ui_static_data(mob/living/carbon/xenomorph/xeno_user) + var/list/data = list() + + // Cost is not expected to change as switching castes closes the UI. switch(xeno_user.xeno_caste.tier) if(XENO_TIER_ONE) data["cost"] = XENO_UPGRADE_BIOMASS_COST_T1 @@ -29,7 +35,7 @@ data["survival_mutations"] = list() for(var/datum/mutation_upgrade/survival/subtype_survival_mutation AS in subtypesof(/datum/mutation_upgrade/survival)) - data["survival_mutations"] += list(list( // Double listing doesn't look like it makes sense, but it works. + data["survival_mutations"] += list(list( // Double listing is how it needs to work. "name" = subtype_survival_mutation.name, "desc" = subtype_survival_mutation.desc )) From 2d83b78339b53d6918f74ec9680f2ffd8ef7db85 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 3 Nov 2024 10:35:39 -0800 Subject: [PATCH 069/106] remove verb, add button to hive status --- .../mob/living/carbon/xenomorph/hive_datum.dm | 4 +++ .../mob/living/carbon/xenomorph/xenoprocs.dm | 8 ------ tgui/packages/tgui/interfaces/HiveStatus.tsx | 26 +++++++++++++++---- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm index a7c424e2e877e..febaf5a85c8c0 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm @@ -276,6 +276,10 @@ if(!isxeno(usr)) return SEND_SIGNAL(usr, COMSIG_XENOABILITY_BLESSINGSMENU) + if("Mutations") + if(!isxeno(usr)) + return + GLOB.mutation_selector.interact(usr) if("Compass") var/atom/target = locate(params["target"]) if(isobserver(usr)) diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index 29ecaa1dde579..5a790ef032798 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -581,14 +581,6 @@ /mob/living/carbon/xenomorph/on_eord(turf/destination) revive(TRUE) -/// Opens the mutation selector UI. -/mob/living/carbon/xenomorph/verb/upgrade_menu() - set name = "Mutations Menu" - set desc = "See current Upgrade Chambers and get mutations for yourself" - set category = "Alien" - - GLOB.mutation_selector.interact(src) - /mob/living/carbon/xenomorph/proc/use_biomass(value) biomass = clamp(biomass - value, 0, 100) diff --git a/tgui/packages/tgui/interfaces/HiveStatus.tsx b/tgui/packages/tgui/interfaces/HiveStatus.tsx index 5f89779d85c8e..75a7417765881 100644 --- a/tgui/packages/tgui/interfaces/HiveStatus.tsx +++ b/tgui/packages/tgui/interfaces/HiveStatus.tsx @@ -190,15 +190,12 @@ const BlessingsButton = (_props: any) => { const { act, data } = useBackend(); const { user_purchase_perms, user_ref } = data; - if (!user_purchase_perms) { - return ; - } - return ( @@ -206,6 +203,22 @@ const BlessingsButton = (_props: any) => { ); }; +const MutationsButton = (_props: any) => { + const { act, data } = useBackend(); + const { user_ref } = data; + + return ( + + + + ); +}; + const GeneralInfo = (_props: any) => { const { data } = useBackend(); const { @@ -253,7 +266,10 @@ const GeneralInfo = (_props: any) => { {' ' + hive_larva_burrowed} - + + + + From c62e052d24e679e5de7a870dfcb4a1160d7d8c4f Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 3 Nov 2024 10:37:03 -0800 Subject: [PATCH 070/106] update desc --- code/modules/mob/living/carbon/xenomorph/mutation_datum.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 06a36b014bfb3..812a44fcd3907 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -152,12 +152,12 @@ /datum/mutation_upgrade/survival/regeneration name = "Regeneration" - desc = "When regenerating health on weeds, regenerate 1.5% max health and 0.167 sunder per Shell Chamber." + desc = "When regenerating health on weeds, regenerate 0.8% max health and 0.167 sunder per Shell Chamber." status_effect = STATUS_EFFECT_UPGRADE_REGENERATION /datum/mutation_upgrade/survival/vampirism name = "Vampirism" - desc = "When slashing living humans, heal 3.33% max health per Shell Chamber. Ravagers get half the bonus instead." + desc = "When slashing living humans, heal 1.67% max health per Shell Chamber. Ravagers get half the bonus instead." status_effect = STATUS_EFFECT_UPGRADE_VAMPIRISM /datum/mutation_upgrade/attack From c5736fc12d37603c7ebfd2ac4244e1aafe42d0d4 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:14:40 -0800 Subject: [PATCH 071/106] updated tgui appearance --- .../tgui/interfaces/MutationSelector.tsx | 187 +++++++++++++----- 1 file changed, 133 insertions(+), 54 deletions(-) diff --git a/tgui/packages/tgui/interfaces/MutationSelector.tsx b/tgui/packages/tgui/interfaces/MutationSelector.tsx index fc7e48f056c59..33bd5206780d7 100644 --- a/tgui/packages/tgui/interfaces/MutationSelector.tsx +++ b/tgui/packages/tgui/interfaces/MutationSelector.tsx @@ -1,7 +1,16 @@ import { useBackend } from '../backend'; -import { Box, Button, Flex, Section } from '../components'; +import { + Box, + Button, + Flex, + ProgressBar, + Section, + Tooltip, +} from '../components'; import { Window } from '../layouts'; +const bar_text_width = 10.25; + type Upgrade = { name: string; desc: string; @@ -18,6 +27,32 @@ type MutationData = { utility_mutations: Upgrade[]; }; +type BiomassData = { + biomass: number; + cost: number; +}; + +type SurvivalMutationData = { + survival_mutations: Upgrade[]; + shell_chambers: number; + biomass: number; + cost: number; +}; + +type AttackMutationData = { + attack_mutations: Upgrade[]; + spur_chambers: number; + biomass: number; + cost: number; +}; + +type UtilityMutationData = { + utility_mutations: Upgrade[]; + veil_chambers: number; + biomass: number; + cost: number; +}; + export const MutationSelector = (props) => { const { act, data } = useBackend(); const { @@ -32,63 +67,107 @@ export const MutationSelector = (props) => { } = data; return ( - + -
- - Shell Chambers: {shell_chambers} +
+ +
+ + + + + + ); +}; + +const BiomassBar = (_props: any) => { + const { data } = useBackend(); + const { biomass, cost } = data; + + return ( + + + + + {`${biomass} / 100 `} + + + + + ); +}; + +const SurvivalMutationSection = (_props: any) => { + const { act, data } = useBackend(); + const { survival_mutations, shell_chambers, cost, biomass } = data; + + return ( +
+ {survival_mutations.map((mutation) => ( + +
+ ); +}; + +const AttackMutationSection = (_props: any) => { + const { act, data } = useBackend(); + const { attack_mutations, spur_chambers, cost, biomass } = data; + + return ( +
+ {attack_mutations.map((mutation) => ( + +
+ ); +}; + +const UtilityMutationSection = (_props: any) => { + const { act, data } = useBackend(); + const { utility_mutations, veil_chambers, cost, biomass } = data; - - Veil Chambers: {veil_chambers} + return ( +
+ {utility_mutations.map((mutation) => ( + +
-
- {survival_mutations.map((mutation) => ( - -
-
- {attack_mutations.map((mutation) => ( - -
-
- {utility_mutations.map((mutation) => ( - -
- - + + ))} +
); }; From 7166d04c7311787a32eacc11c676972d5bf2c5fd Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:20:02 -0800 Subject: [PATCH 072/106] unneeded vars + theme --- .../tgui/interfaces/MutationSelector.tsx | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tgui/packages/tgui/interfaces/MutationSelector.tsx b/tgui/packages/tgui/interfaces/MutationSelector.tsx index 33bd5206780d7..adba48601a847 100644 --- a/tgui/packages/tgui/interfaces/MutationSelector.tsx +++ b/tgui/packages/tgui/interfaces/MutationSelector.tsx @@ -9,8 +9,6 @@ import { } from '../components'; import { Window } from '../layouts'; -const bar_text_width = 10.25; - type Upgrade = { name: string; desc: string; @@ -54,20 +52,8 @@ type UtilityMutationData = { }; export const MutationSelector = (props) => { - const { act, data } = useBackend(); - const { - shell_chambers, - spur_chambers, - veil_chambers, - biomass, - cost, - survival_mutations, - attack_mutations, - utility_mutations, - } = data; - return ( - +
From 15b3fc9b066479fb577dc6ff72317be948290fc8 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:40:31 -0800 Subject: [PATCH 073/106] sectioned + smaller width height --- .../tgui/interfaces/MutationSelector.tsx | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/tgui/packages/tgui/interfaces/MutationSelector.tsx b/tgui/packages/tgui/interfaces/MutationSelector.tsx index adba48601a847..31e1edba8fc9f 100644 --- a/tgui/packages/tgui/interfaces/MutationSelector.tsx +++ b/tgui/packages/tgui/interfaces/MutationSelector.tsx @@ -1,12 +1,5 @@ import { useBackend } from '../backend'; -import { - Box, - Button, - Flex, - ProgressBar, - Section, - Tooltip, -} from '../components'; +import { Button, Flex, ProgressBar, Section, Tooltip } from '../components'; import { Window } from '../layouts'; type Upgrade = { @@ -14,17 +7,6 @@ type Upgrade = { desc: string; }; -type MutationData = { - shell_chambers: number; - spur_chambers: number; - veil_chambers: number; - biomass: number; - cost: number; - survival_mutations: Upgrade[]; - attack_mutations: Upgrade[]; - utility_mutations: Upgrade[]; -}; - type BiomassData = { biomass: number; cost: number; @@ -51,10 +33,10 @@ type UtilityMutationData = { cost: number; }; -export const MutationSelector = (props) => { +export const MutationSelector = (_props: any) => { return ( - - + +
@@ -93,17 +75,23 @@ const SurvivalMutationSection = (_props: any) => { key="Survival" > {survival_mutations.map((mutation) => ( - -
); @@ -116,17 +104,23 @@ const AttackMutationSection = (_props: any) => { return (
{attack_mutations.map((mutation) => ( - -
); @@ -142,17 +136,23 @@ const UtilityMutationSection = (_props: any) => { key="Utility" > {utility_mutations.map((mutation) => ( - -
); From 6a9bc3a2bf21877cbda1577b6947d7c9981e02c2 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:57:58 -0800 Subject: [PATCH 074/106] dropdown menus + enabled if already owned --- .../living/carbon/xenomorph/mutation_datum.dm | 9 +- .../tgui/interfaces/MutationSelector.tsx | 135 ++++++++++-------- 2 files changed, 82 insertions(+), 62 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 812a44fcd3907..3e02ab982fee1 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -37,21 +37,24 @@ for(var/datum/mutation_upgrade/survival/subtype_survival_mutation AS in subtypesof(/datum/mutation_upgrade/survival)) data["survival_mutations"] += list(list( // Double listing is how it needs to work. "name" = subtype_survival_mutation.name, - "desc" = subtype_survival_mutation.desc + "desc" = subtype_survival_mutation.desc, + "owned" = locate(subtype_survival_mutation.status_effect) in xeno_user.status_effects )) data["attack_mutations"] = list() for(var/datum/mutation_upgrade/attack/subtype_attack_mutation AS in subtypesof(/datum/mutation_upgrade/attack)) data["attack_mutations"] += list(list( "name" = subtype_attack_mutation.name, - "desc" = subtype_attack_mutation.desc + "desc" = subtype_attack_mutation.desc, + "owned" = locate(subtype_attack_mutation.status_effect) in xeno_user.status_effects )) data["utility_mutations"] = list() for(var/datum/mutation_upgrade/utility/subtype_utility_mutation AS in subtypesof(/datum/mutation_upgrade/utility)) data["utility_mutations"] += list(list( "name" = subtype_utility_mutation.name, - "desc" = subtype_utility_mutation.desc + "desc" = subtype_utility_mutation.desc, + "owned" = locate(subtype_utility_mutation.status_effect) in xeno_user.status_effects )) return data diff --git a/tgui/packages/tgui/interfaces/MutationSelector.tsx b/tgui/packages/tgui/interfaces/MutationSelector.tsx index 31e1edba8fc9f..fd1d6c2a5764f 100644 --- a/tgui/packages/tgui/interfaces/MutationSelector.tsx +++ b/tgui/packages/tgui/interfaces/MutationSelector.tsx @@ -1,10 +1,18 @@ import { useBackend } from '../backend'; -import { Button, Flex, ProgressBar, Section, Tooltip } from '../components'; +import { + Button, + Collapsible, + Flex, + ProgressBar, + Section, + Tooltip, +} from '../components'; import { Window } from '../layouts'; type Upgrade = { name: string; desc: string; + owned: boolean; }; type BiomassData = { @@ -35,7 +43,7 @@ type UtilityMutationData = { export const MutationSelector = (_props: any) => { return ( - +
@@ -74,25 +82,28 @@ const SurvivalMutationSection = (_props: any) => { title={`Survival | Shell Chambers: ${shell_chambers}/3`} key="Survival" > - {survival_mutations.map((mutation) => ( -
act('purchase', { upgrade_name: mutation.name })} - disabled={cost > biomass || shell_chambers === 0} - /> - } - > - - {mutation.desc} - -
- ))} + + {survival_mutations.map((mutation) => ( +
act('purchase', { upgrade_name: mutation.name })} + disabled={cost > biomass || shell_chambers === 0} + selected={mutation.owned} + /> + } + > + + {mutation.desc} + +
+ ))} +
); }; @@ -103,25 +114,28 @@ const AttackMutationSection = (_props: any) => { return (
- {attack_mutations.map((mutation) => ( -
act('purchase', { upgrade_name: mutation.name })} - disabled={cost > biomass || spur_chambers === 0} - /> - } - > - - {mutation.desc} - -
- ))} + + {attack_mutations.map((mutation) => ( +
act('purchase', { upgrade_name: mutation.name })} + disabled={cost > biomass || spur_chambers === 0} + selected={mutation.owned} + /> + } + > + + {mutation.desc} + +
+ ))} +
); }; @@ -135,25 +149,28 @@ const UtilityMutationSection = (_props: any) => { title={`Utility | Veil Chambers: ${veil_chambers}/3`} key="Utility" > - {utility_mutations.map((mutation) => ( -
act('purchase', { upgrade_name: mutation.name })} - disabled={cost > biomass || veil_chambers === 0} - /> - } - > - - {mutation.desc} - -
- ))} + + {utility_mutations.map((mutation) => ( +
act('purchase', { upgrade_name: mutation.name })} + disabled={cost > biomass || veil_chambers === 0} + selected={mutation.owned} + /> + } + > + + {mutation.desc} + +
+ ))} +
); }; From fe495186995fa1403231abe48de580b54b56a3ec Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 3 Nov 2024 15:34:21 -0800 Subject: [PATCH 075/106] section name -> collapsible name --- .../tgui/interfaces/MutationSelector.tsx | 144 +++++++++--------- 1 file changed, 68 insertions(+), 76 deletions(-) diff --git a/tgui/packages/tgui/interfaces/MutationSelector.tsx b/tgui/packages/tgui/interfaces/MutationSelector.tsx index fd1d6c2a5764f..2dbc586dc4892 100644 --- a/tgui/packages/tgui/interfaces/MutationSelector.tsx +++ b/tgui/packages/tgui/interfaces/MutationSelector.tsx @@ -78,33 +78,30 @@ const SurvivalMutationSection = (_props: any) => { const { survival_mutations, shell_chambers, cost, biomass } = data; return ( -
- - {survival_mutations.map((mutation) => ( -
act('purchase', { upgrade_name: mutation.name })} - disabled={cost > biomass || shell_chambers === 0} - selected={mutation.owned} - /> - } - > - - {mutation.desc} - -
- ))} -
-
+ {survival_mutations.map((mutation) => ( +
act('purchase', { upgrade_name: mutation.name })} + disabled={cost > biomass || shell_chambers === 0} + selected={mutation.owned} + /> + } + > + + {mutation.desc} + +
+ ))} + ); }; @@ -113,30 +110,28 @@ const AttackMutationSection = (_props: any) => { const { attack_mutations, spur_chambers, cost, biomass } = data; return ( -
- - {attack_mutations.map((mutation) => ( -
act('purchase', { upgrade_name: mutation.name })} - disabled={cost > biomass || spur_chambers === 0} - selected={mutation.owned} - /> - } - > - - {mutation.desc} - -
- ))} -
-
+ + {attack_mutations.map((mutation) => ( +
act('purchase', { upgrade_name: mutation.name })} + disabled={cost > biomass || spur_chambers === 0} + selected={mutation.owned} + /> + } + > + + {mutation.desc} + +
+ ))} +
); }; @@ -145,32 +140,29 @@ const UtilityMutationSection = (_props: any) => { const { utility_mutations, veil_chambers, cost, biomass } = data; return ( -
- - {utility_mutations.map((mutation) => ( -
act('purchase', { upgrade_name: mutation.name })} - disabled={cost > biomass || veil_chambers === 0} - selected={mutation.owned} - /> - } - > - - {mutation.desc} - -
- ))} -
-
+ {utility_mutations.map((mutation) => ( +
act('purchase', { upgrade_name: mutation.name })} + disabled={cost > biomass || veil_chambers === 0} + selected={mutation.owned} + /> + } + > + + {mutation.desc} + +
+ ))} + ); }; From f166bfc057da138c73a73d329ab72b435ada39f1 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 9 Nov 2024 18:08:51 -0800 Subject: [PATCH 076/106] no phero if no chambers --- code/datums/status_effects/xeno_buffs.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index d4b3b57dfafd7..ebb3a4be6794d 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1256,7 +1256,8 @@ /datum/status_effect/mutation_upgrade/pheromones/proc/create_aura() if(current_aura) QDEL_NULL(current_aura) - current_aura = SSaura.add_emitter(buff_owner, emitted_aura, 6 + aura_power_per_chamber * chamber_scaling * 2, aura_power_base + aura_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) + if(chamber_scaling) + current_aura = SSaura.add_emitter(buff_owner, emitted_aura, 6 + aura_power_per_chamber * chamber_scaling * 2, aura_power_base + aura_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) /// Sets the chamber_scaling to the amount of active veil chambers and recreates the aura. /datum/status_effect/mutation_upgrade/pheromones/proc/update_buff() From 7d153799041e99b764fdfa9d5a3e04ce77857c5e Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 9 Nov 2024 18:22:19 -0800 Subject: [PATCH 077/106] cocoon: 10 initial shared, 6 overtime to all, 2.5 complete to all --- code/game/objects/items/cocoon.dm | 21 +++++++++++++++++++ .../mob/living/carbon/xenomorph/abilities.dm | 11 +++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/cocoon.dm b/code/game/objects/items/cocoon.dm index 1073e7361a96c..82054d0646ed7 100644 --- a/code/game/objects/items/cocoon.dm +++ b/code/game/objects/items/cocoon.dm @@ -47,6 +47,17 @@ //Gives marine cloneloss for a total of 30. victim.adjustCloneLoss(0.5) + // Slowly give biomass over time up to 6 biomass (assuming the time based on comment above is correct). + for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) + if(xeno.hivenumber != hivenumber) + continue + // Prevents Hivemind and Minions from getting biomass. + var/datum/action/ability/activable/xeno/cocoon/cocoon_ability = xeno.actions_by_path[/datum/action/ability/activable/xeno/cocoon] + if(!cocoon_ability) + continue + xeno.gain_biomass(0.1) + + /obj/structure/cocoon/take_damage(damage_amount, damage_type = BRUTE, armor_type = null, effects = TRUE, attack_dir, armour_penetration = 0, mob/living/blame_mob) . = ..() if(anchored && obj_integrity < max_integrity / 2) @@ -71,6 +82,16 @@ var/datum/hive_status/hive_status = GLOB.hive_datums[hivenumber] hive_status.update_tier_limits() GLOB.round_statistics.larva_from_cocoon += larva_point_reward / xeno_job.job_points_needed + // 5 biomass to all xenomorphs. + for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) + if(xeno.hivenumber != hivenumber) + continue + // Prevents Hivemind and Minions from getting biomass. + var/datum/action/ability/activable/xeno/cocoon/cocoon_ability = xeno.actions_by_path[/datum/action/ability/activable/xeno/cocoon] + if(!cocoon_ability) + continue + xeno.gain_biomass(2.5) + release_victim() update_icon() diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index 05a56666f4ee3..9630f490f94b2 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -1404,6 +1404,10 @@ // Intentionally includes the owner. if(!X.issamexenohive(nearby_xeno)) continue + // Prevents Hivemind and Minions from getting biomass. + var/datum/action/ability/activable/xeno/psydrain/cocoon_ability = nearby_xeno.actions_by_path[/datum/action/ability/activable/xeno/psydrain] + if(!cocoon_ability) + continue nearby_friendly_xenos += nearby_xeno // Split the reward amongst every xeno nearby, including themselves. @@ -1527,13 +1531,18 @@ // Intentionally includes the owner. if(!X.issamexenohive(nearby_xeno)) continue + // Prevents Hivemind and Minions from getting biomass. + var/datum/action/ability/activable/xeno/cocoon/cocoon_ability = nearby_xeno.actions_by_path[/datum/action/ability/activable/xeno/cocoon] + if(!cocoon_ability) + continue nearby_friendly_xenos += nearby_xeno // Split the reward amongst every xeno nearby, including themselves. - var/biomass_per_xeno = round(15/length(nearby_friendly_xenos), 0.1) + var/biomass_per_xeno = round(10/length(nearby_friendly_xenos), 0.1) for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) nearby_friendly_xeno.gain_biomass(biomass_per_xeno) + if(owner.client) var/datum/personal_statistics/personal_statistics = GLOB.personal_statistics_list[owner.ckey] personal_statistics.cocooned++ From 392ecebbff16da62973538e2ac8c9183ef651737 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 9 Nov 2024 18:24:56 -0800 Subject: [PATCH 078/106] comment --- code/game/objects/items/cocoon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/cocoon.dm b/code/game/objects/items/cocoon.dm index 82054d0646ed7..e7ab1d5a2fff9 100644 --- a/code/game/objects/items/cocoon.dm +++ b/code/game/objects/items/cocoon.dm @@ -82,7 +82,7 @@ var/datum/hive_status/hive_status = GLOB.hive_datums[hivenumber] hive_status.update_tier_limits() GLOB.round_statistics.larva_from_cocoon += larva_point_reward / xeno_job.job_points_needed - // 5 biomass to all xenomorphs. + // 2.5 biomass to all xenomorphs. for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) if(xeno.hivenumber != hivenumber) continue From 73606d371c729ccb7312d29b5d72aa8ee90fc088 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 9 Nov 2024 20:43:12 -0800 Subject: [PATCH 079/106] 0 initial, 9 overtime to all, 3.5 completion --- code/game/objects/items/cocoon.dm | 8 ++++---- .../mob/living/carbon/xenomorph/abilities.dm | 17 ----------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/code/game/objects/items/cocoon.dm b/code/game/objects/items/cocoon.dm index e7ab1d5a2fff9..66d7f50bc8935 100644 --- a/code/game/objects/items/cocoon.dm +++ b/code/game/objects/items/cocoon.dm @@ -47,7 +47,7 @@ //Gives marine cloneloss for a total of 30. victim.adjustCloneLoss(0.5) - // Slowly give biomass over time up to 6 biomass (assuming the time based on comment above is correct). + // Slowly give biomass over time up to 9 biomass (assuming the time based on comment above is correct). for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) if(xeno.hivenumber != hivenumber) continue @@ -55,7 +55,7 @@ var/datum/action/ability/activable/xeno/cocoon/cocoon_ability = xeno.actions_by_path[/datum/action/ability/activable/xeno/cocoon] if(!cocoon_ability) continue - xeno.gain_biomass(0.1) + xeno.gain_biomass(0.15) /obj/structure/cocoon/take_damage(damage_amount, damage_type = BRUTE, armor_type = null, effects = TRUE, attack_dir, armour_penetration = 0, mob/living/blame_mob) @@ -82,7 +82,7 @@ var/datum/hive_status/hive_status = GLOB.hive_datums[hivenumber] hive_status.update_tier_limits() GLOB.round_statistics.larva_from_cocoon += larva_point_reward / xeno_job.job_points_needed - // 2.5 biomass to all xenomorphs. + // 3.5 biomass to all xenomorphs. for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) if(xeno.hivenumber != hivenumber) continue @@ -90,7 +90,7 @@ var/datum/action/ability/activable/xeno/cocoon/cocoon_ability = xeno.actions_by_path[/datum/action/ability/activable/xeno/cocoon] if(!cocoon_ability) continue - xeno.gain_biomass(2.5) + xeno.gain_biomass(3.5) release_victim() update_icon() diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index 9630f490f94b2..f7b835262728d 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -1526,23 +1526,6 @@ ADD_TRAIT(victim, TRAIT_STASIS, TRAIT_STASIS) X.eject_victim(TRUE, starting_turf) - var/list/mob/living/carbon/xenomorph/nearby_friendly_xenos = list() - for(var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(X, 7)) - // Intentionally includes the owner. - if(!X.issamexenohive(nearby_xeno)) - continue - // Prevents Hivemind and Minions from getting biomass. - var/datum/action/ability/activable/xeno/cocoon/cocoon_ability = nearby_xeno.actions_by_path[/datum/action/ability/activable/xeno/cocoon] - if(!cocoon_ability) - continue - nearby_friendly_xenos += nearby_xeno - - // Split the reward amongst every xeno nearby, including themselves. - var/biomass_per_xeno = round(10/length(nearby_friendly_xenos), 0.1) - for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) - nearby_friendly_xeno.gain_biomass(biomass_per_xeno) - - if(owner.client) var/datum/personal_statistics/personal_statistics = GLOB.personal_statistics_list[owner.ckey] personal_statistics.cocooned++ From 4f45621cee03c58b7c04c548632136ebd7d1df24 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 9 Nov 2024 21:50:52 -0800 Subject: [PATCH 080/106] extra space --- code/game/objects/items/cocoon.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/game/objects/items/cocoon.dm b/code/game/objects/items/cocoon.dm index 66d7f50bc8935..1bc442674fd31 100644 --- a/code/game/objects/items/cocoon.dm +++ b/code/game/objects/items/cocoon.dm @@ -57,7 +57,6 @@ continue xeno.gain_biomass(0.15) - /obj/structure/cocoon/take_damage(damage_amount, damage_type = BRUTE, armor_type = null, effects = TRUE, attack_dir, armour_penetration = 0, mob/living/blame_mob) . = ..() if(anchored && obj_integrity < max_integrity / 2) From 2ea49640304383c94e4ce96845e97dc041a38bb0 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 10 Nov 2024 08:28:38 -0800 Subject: [PATCH 081/106] 100 biomass for Valhalla/Fallen xenos --- code/modules/mob/dead/observer/observer.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 10c85e8c91ba9..a07f2a37e304e 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -902,6 +902,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) log_game("[key_name(usr)] has joined Valhalla as a Xenomorph.") var/mob/living/carbon/xenomorph/new_xeno = new xeno_choice(pick(GLOB.spawns_by_job[/datum/job/fallen/xenomorph])) new_xeno.transfer_to_hive(XENO_HIVE_FALLEN) + new_xeno.gain_biomass(100) // So they can test it out here. ADD_TRAIT(new_xeno, TRAIT_VALHALLA_XENO, VALHALLA_TRAIT) var/datum/job/xallhala_job = SSjob.GetJobType(/datum/job/fallen/xenomorph) new_xeno.apply_assigned_role_to_spawn(xallhala_job) From e8a7ad6b59b35b274894a5b8eac96cc42a328bf7 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 10 Nov 2024 11:33:04 -0800 Subject: [PATCH 082/106] trail now buyable :) --- code/__DEFINES/xeno.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 00e2b35274ff1..b2138bf600d50 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -231,7 +231,7 @@ GLOBAL_LIST_INIT(mutation_upgrades_buyable, list( /datum/mutation_upgrade/attack/crush, /datum/mutation_upgrade/utility/toxin, /datum/mutation_upgrade/utility/pheromones, - /datum/mutation_upgrade/utility/toxin + /datum/mutation_upgrade/utility/trail )) #define MUTATION_CATEGORY_SURVIVAL "Survival" From 68bc531ec1a1f1a530fd347aed99299aaa0edb85 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 11 Nov 2024 21:55:50 -0800 Subject: [PATCH 083/106] nerfs(?) Toxin upgrade --- code/datums/status_effects/xeno_buffs.dm | 7 ++++--- code/modules/mob/living/carbon/xenomorph/mutation_datum.dm | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index ebb3a4be6794d..cbf21315687eb 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1179,8 +1179,6 @@ id = "mutation_upgrade_toxin" alert_type = /atom/movable/screen/alert/status_effect/toxin chamber_structure = MUTATION_STRUCTURE_VEIL - /// The amount of toxins to inject. - var/toxin_amount_per_chamber = 1 /// Currently selected reagent to inject. var/datum/reagent/toxin/selected_reagent = /datum/reagent/toxin/xeno_neurotoxin @@ -1206,8 +1204,11 @@ SIGNAL_HANDLER if(!chamber_scaling || target.stat == DEAD || !ishuman(target) || !target.can_sting()) return + var/datum/reagent/glob_reagent = GLOB.chemical_reagents_list[selected_reagent] + if(!glob_reagent) + return var/mob/living/carbon/human/human_target = target - human_target.reagents.add_reagent(selected_reagent, toxin_amount_per_chamber * chamber_scaling) + human_target.reagents.add_reagent(selected_reagent, glob_reagent.custom_metabolism * chamber_scaling) // *************************************** // *************************************** diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 3e02ab982fee1..9ce6dc58ad347 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -190,7 +190,7 @@ /datum/mutation_upgrade/utility/toxin name = "Toxin" - desc = "When slashing living humans, inject 1u of a chosen toxin into them per Veil Chamber." + desc = "When slashing living humans, inject a variable amount of a chosen toxin into them. The amount depends on the toxin and Spur Chamber count." status_effect = STATUS_EFFECT_UPGRADE_TOXIN /datum/mutation_upgrade/utility/pheromones From afef995b9135efca5aa7ccc9ab9c1561124d198f Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:07:37 -0800 Subject: [PATCH 084/106] temporary sticky thin resin --- code/datums/status_effects/xeno_buffs.dm | 4 ++-- code/game/objects/structures/xeno.dm | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index cbf21315687eb..4cc163bb902e2 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1271,7 +1271,7 @@ // *************************************** /atom/movable/screen/alert/status_effect/trail name = "Trail" - desc = "We leave an acid trail behind. Click to change trail." + desc = "We leave a trail behind. Click to change trail." icon_state = "xenobuff_generic" /atom/movable/screen/alert/status_effect/trail/Click() @@ -1299,7 +1299,7 @@ /// A list of trails that can be selected var/list/selectable_trails = list( /obj/effect/xenomorph/spray, - /obj/alien/resin/sticky/thin + /obj/alien/resin/sticky/thin/temporary ) /datum/status_effect/mutation_upgrade/trail/on_apply() diff --git a/code/game/objects/structures/xeno.dm b/code/game/objects/structures/xeno.dm index 1d6f768981852..7a582b6a70fda 100644 --- a/code/game/objects/structures/xeno.dm +++ b/code/game/objects/structures/xeno.dm @@ -145,6 +145,10 @@ ignore_weed_destruction = FALSE refundable = FALSE +/obj/alien/resin/sticky/thin/temporary/Initialize(mapload) + . = ..() + addtimer(CALLBACK(src, PROC_REF(obj_destruction), MELEE), 3 SECONDS) + //Resin Doors /obj/structure/mineral_door/resin name = RESIN_DOOR From fc202da671df6abe4db5b333f476f7d9891f4d64 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:43:51 -0800 Subject: [PATCH 085/106] caste_flag for no biomass gain instead of doing by ability ownership --- code/__DEFINES/mobs.dm | 9 +++++---- code/game/objects/items/cocoon.dm | 4 +--- .../mob/living/carbon/xenomorph/abilities.dm | 13 ++++++------- .../castes/baneling/castedatum_baneling.dm | 2 +- .../xenomorph/castes/beetle/castedatum_beetle.dm | 2 +- .../castes/hivemind/castedatum_hivemind.dm | 2 +- .../xenomorph/castes/mantis/castedatum_mantis.dm | 2 +- .../xenomorph/castes/nymph/castedatum_nymph.dm | 2 +- .../xenomorph/castes/puppet/castedatum_puppet.dm | 2 +- .../castes/scorpion/castedatum_scorpion.dm | 2 +- .../castes/spiderling/castedatum_spiderling.dm | 2 +- 11 files changed, 20 insertions(+), 22 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 0cd074464345b..187fbc071615f 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -589,12 +589,13 @@ GLOBAL_LIST_INIT(layers_to_offset, list( #define CASTE_STAGGER_RESISTANT (1<<15) //Resistant to some forms of stagger, such as projectiles #define CASTE_HAS_WOUND_MASK (1<<16) //uses an alpha mask for wounded states #define CASTE_EXCLUDE_STRAINS (1<<17) // denotes castes/basetypes that should be excluded from being evoable as a strain +#define CASTE_NO_BIOMASS (1<<18) // Xenos are excluded from getting any biomass // Xeno defines that affect evolution, considering making a new var for these -#define CASTE_LEADER_TYPE (1<<16) //Whether we are a leader type caste, such as the queen, shrike or ?king?, and is affected by queen ban and playtime restrictions -#define CASTE_CANNOT_EVOLVE_IN_CAPTIVITY (1<<17) //Whether we cannot evolve in the research lab -#define CASTE_REQUIRES_FREE_TILE (1<<18) //Whether we require a free tile to evolve -#define CASTE_INSTANT_EVOLUTION (1<<19) //Whether we require no evolution progress to evolve to this caste +#define CASTE_LEADER_TYPE (1<<19) //Whether we are a leader type caste, such as the queen, shrike or ?king?, and is affected by queen ban and playtime restrictions +#define CASTE_CANNOT_EVOLVE_IN_CAPTIVITY (1<<20) //Whether we cannot evolve in the research lab +#define CASTE_REQUIRES_FREE_TILE (1<<21) //Whether we require a free tile to evolve +#define CASTE_INSTANT_EVOLUTION (1<<22) //Whether we require no evolution progress to evolve to this caste #define CASTE_CAN_HOLD_FACEHUGGERS (1<<0) #define CASTE_CAN_BE_QUEEN_HEALED (1<<1) diff --git a/code/game/objects/items/cocoon.dm b/code/game/objects/items/cocoon.dm index 1bc442674fd31..e012382caabab 100644 --- a/code/game/objects/items/cocoon.dm +++ b/code/game/objects/items/cocoon.dm @@ -85,9 +85,7 @@ for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) if(xeno.hivenumber != hivenumber) continue - // Prevents Hivemind and Minions from getting biomass. - var/datum/action/ability/activable/xeno/cocoon/cocoon_ability = xeno.actions_by_path[/datum/action/ability/activable/xeno/cocoon] - if(!cocoon_ability) + if(xeno.xeno_caste.caste_flags & CASTE_NO_BIOMASS) continue xeno.gain_biomass(3.5) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index f7b835262728d..f4e60943a99ee 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -1404,16 +1404,15 @@ // Intentionally includes the owner. if(!X.issamexenohive(nearby_xeno)) continue - // Prevents Hivemind and Minions from getting biomass. - var/datum/action/ability/activable/xeno/psydrain/cocoon_ability = nearby_xeno.actions_by_path[/datum/action/ability/activable/xeno/psydrain] - if(!cocoon_ability) + if(nearby_xeno.xeno_caste.caste_flags & CASTE_NO_BIOMASS) continue nearby_friendly_xenos += nearby_xeno - // Split the reward amongst every xeno nearby, including themselves. - var/biomass_per_xeno = round(15/length(nearby_friendly_xenos), 0.1) - for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) - nearby_friendly_xeno.gain_biomass(biomass_per_xeno) + if(length(nearby_friendly_xenos)) + // Split the reward amongst every xeno nearby, including themselves. + var/biomass_per_xeno = round(15/length(nearby_friendly_xenos), 0.1) + for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) + nearby_friendly_xeno.gain_biomass(biomass_per_xeno) ADD_TRAIT(victim, TRAIT_PSY_DRAINED, TRAIT_PSY_DRAINED) if(HAS_TRAIT(victim, TRAIT_UNDEFIBBABLE)) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/baneling/castedatum_baneling.dm b/code/modules/mob/living/carbon/xenomorph/castes/baneling/castedatum_baneling.dm index 705d0a4fc4850..6791f5c3ebc2c 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/baneling/castedatum_baneling.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/baneling/castedatum_baneling.dm @@ -24,7 +24,7 @@ max_health = 100 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_BIOMASS can_flags = CASTE_CAN_BE_QUEEN_HEALED caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/beetle/castedatum_beetle.dm b/code/modules/mob/living/carbon/xenomorph/castes/beetle/castedatum_beetle.dm index 94dc092dc0630..7e2524b3cdb30 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/beetle/castedatum_beetle.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/beetle/castedatum_beetle.dm @@ -24,7 +24,7 @@ max_health = 260 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_BIOMASS can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_RIDE_CRUSHER caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm b/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm index 32fff1412c34f..0bfe11a00de6c 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm @@ -22,7 +22,7 @@ maximum_active_caste = 1 // *** Flags *** // - caste_flags = CASTE_INNATE_PLASMA_REGEN|CASTE_FIRE_IMMUNE|CASTE_IS_BUILDER|CASTE_DO_NOT_ALERT_LOW_LIFE + caste_flags = CASTE_INNATE_PLASMA_REGEN|CASTE_FIRE_IMMUNE|CASTE_IS_BUILDER|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_NO_BIOMASS can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_GIVEN_PLASMA caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/mantis/castedatum_mantis.dm b/code/modules/mob/living/carbon/xenomorph/castes/mantis/castedatum_mantis.dm index 190fa40955b4b..bff0c53574e43 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/mantis/castedatum_mantis.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/mantis/castedatum_mantis.dm @@ -25,7 +25,7 @@ max_health = 150 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_BIOMASS can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_GIVEN_PLASMA|CASTE_CAN_RIDE_CRUSHER caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/nymph/castedatum_nymph.dm b/code/modules/mob/living/carbon/xenomorph/castes/nymph/castedatum_nymph.dm index ad381f39c107f..de97402bcd3a8 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/nymph/castedatum_nymph.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/nymph/castedatum_nymph.dm @@ -24,7 +24,7 @@ max_health = 120 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_IS_BUILDER + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_IS_BUILDER|CASTE_NO_BIOMASS can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_GIVEN_PLASMA // *** Defense *** // diff --git a/code/modules/mob/living/carbon/xenomorph/castes/puppet/castedatum_puppet.dm b/code/modules/mob/living/carbon/xenomorph/castes/puppet/castedatum_puppet.dm index 6840b7fb279cd..afa3aace7a811 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/puppet/castedatum_puppet.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/puppet/castedatum_puppet.dm @@ -15,7 +15,7 @@ plasma_max = 2 plasma_gain = 0 max_health = 250 - caste_flags = CASTE_NOT_IN_BIOSCAN|CASTE_DO_NOT_ANNOUNCE_DEATH|CASTE_DO_NOT_ALERT_LOW_LIFE + caste_flags = CASTE_NOT_IN_BIOSCAN|CASTE_DO_NOT_ANNOUNCE_DEATH|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_NO_BIOMASS minimap_icon = "puppet" soft_armor = list(MELEE = 14, BULLET = 3, LASER = 5, ENERGY = 3, BOMB = 0, BIO = 0, FIRE = 0, ACID = 0) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/scorpion/castedatum_scorpion.dm b/code/modules/mob/living/carbon/xenomorph/castes/scorpion/castedatum_scorpion.dm index 42102310c5e56..66ef28d226b42 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/scorpion/castedatum_scorpion.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/scorpion/castedatum_scorpion.dm @@ -24,7 +24,7 @@ max_health = 130 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_BIOMASS can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_GIVEN_PLASMA|CASTE_CAN_RIDE_CRUSHER caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/spiderling/castedatum_spiderling.dm b/code/modules/mob/living/carbon/xenomorph/castes/spiderling/castedatum_spiderling.dm index 45a9b323f78d3..fb786ef7ebe0c 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/spiderling/castedatum_spiderling.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/spiderling/castedatum_spiderling.dm @@ -25,7 +25,7 @@ max_health = 125 // *** Flags *** // - caste_flags = CASTE_NOT_IN_BIOSCAN|CASTE_DO_NOT_ANNOUNCE_DEATH|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_BUILDER + caste_flags = CASTE_NOT_IN_BIOSCAN|CASTE_DO_NOT_ANNOUNCE_DEATH|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_BUILDER|CASTE_NO_BIOMASS // *** Minimap Icon *** // minimap_icon = "spiderling" From a7564719d13bb4b3f092bbc2c24d7bada63ac66b Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:51:23 -0800 Subject: [PATCH 086/106] Biomass in status tab --- code/modules/mob/living/carbon/xenomorph/xenoprocs.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index 5a790ef032798..557c99ecd5140 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -126,6 +126,10 @@ else //Upgrade process finished or impossible . += "Upgrade Progress: (FINISHED)" + if(!(xeno_caste.caste_flags & CASTE_NO_BIOMASS)) + . += "Biomass: [biomass]/100" + + . += "Health: [health]/[maxHealth][overheal ? " + [overheal]": ""]" //Changes with balance scalar, can't just use the caste if(xeno_caste.plasma_max > 0) From b70f27246c3439c0c7af757db55b9cbeee653104 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:51:38 -0800 Subject: [PATCH 087/106] forgot this for CASTE_NO_BIOMASS --- code/game/objects/items/cocoon.dm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/game/objects/items/cocoon.dm b/code/game/objects/items/cocoon.dm index e012382caabab..0e655ae04fa7a 100644 --- a/code/game/objects/items/cocoon.dm +++ b/code/game/objects/items/cocoon.dm @@ -51,9 +51,7 @@ for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) if(xeno.hivenumber != hivenumber) continue - // Prevents Hivemind and Minions from getting biomass. - var/datum/action/ability/activable/xeno/cocoon/cocoon_ability = xeno.actions_by_path[/datum/action/ability/activable/xeno/cocoon] - if(!cocoon_ability) + if(xeno.xeno_caste.caste_flags & CASTE_NO_BIOMASS) continue xeno.gain_biomass(0.15) From 8cd05a26866194774245cdbd8962a51eb03a1c4c Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:59:17 -0800 Subject: [PATCH 088/106] 6 overtime, 4 completion --- code/game/objects/items/cocoon.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/cocoon.dm b/code/game/objects/items/cocoon.dm index 0e655ae04fa7a..4246dda1c0e7c 100644 --- a/code/game/objects/items/cocoon.dm +++ b/code/game/objects/items/cocoon.dm @@ -53,7 +53,7 @@ continue if(xeno.xeno_caste.caste_flags & CASTE_NO_BIOMASS) continue - xeno.gain_biomass(0.15) + xeno.gain_biomass(0.1) /obj/structure/cocoon/take_damage(damage_amount, damage_type = BRUTE, armor_type = null, effects = TRUE, attack_dir, armour_penetration = 0, mob/living/blame_mob) . = ..() @@ -85,7 +85,7 @@ continue if(xeno.xeno_caste.caste_flags & CASTE_NO_BIOMASS) continue - xeno.gain_biomass(3.5) + xeno.gain_biomass(4) release_victim() update_icon() From 0c9156fd5569ec2f4e28a8328b0bfd10d87244a8 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:43:53 -0800 Subject: [PATCH 089/106] no trail if no chambers --- code/datums/status_effects/xeno_buffs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 4cc163bb902e2..5232216ef5c1b 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1322,7 +1322,7 @@ /// Rolls the dice and creates the selected trail if the dice is right. /datum/status_effect/mutation_upgrade/trail/proc/create_trail() SIGNAL_HANDLER - if(buff_owner.incapacitated() || buff_owner.lying_angle || buff_owner.resting) + if(buff_owner.incapacitated() || buff_owner.lying_angle || buff_owner.resting || !chamber_scaling) return if(prob(base_chance + (chance_per_chamber * chamber_scaling))) var/turf/T = get_turf(buff_owner) From f246691666124c3b1223c67b99772e43486c801b Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 16 Nov 2024 12:35:59 -0800 Subject: [PATCH 090/106] hivemind_manifestation CASTE_NO_BIOMASS --- .../carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm b/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm index 0bfe11a00de6c..a7ecb339d8001 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm @@ -74,7 +74,7 @@ upgrade = XENO_UPGRADE_MANIFESTATION // *** Flags *** // - caste_flags = CASTE_IS_BUILDER|CASTE_FIRE_IMMUNE + caste_flags = CASTE_IS_BUILDER|CASTE_FIRE_IMMUNE|CASTE_NO_BIOMASS aura_strength = 4 //Good pheros From d9bc4175e9721c11d541848e3c920210270f9a51 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Thu, 21 Nov 2024 19:32:48 -0800 Subject: [PATCH 091/106] swap around psypoint costs --- code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm index 285665df9b3e2..065e0624f164e 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_upgrades.dm @@ -274,7 +274,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( name = "Shell Upgrade Chamber" desc = "Constructs a chamber that allows xenos to buy survival mutations. Build up to 3 structures to increase mutation power." icon = "shell" - psypoint_cost = 300 + psypoint_cost = 250 building_type = /obj/structure/xeno/upgrade_chamber/shell /datum/hive_upgrade/building/upgrade_chamber/shell/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) @@ -287,7 +287,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( name = "Spur Upgrade Chamber" desc = "Constructs a chamber that allows xenos to buy attack mutations. Build up to 3 structures to increase mutation power." icon = "spur" - psypoint_cost = 250 + psypoint_cost = 200 building_type = /obj/structure/xeno/upgrade_chamber/spur /datum/hive_upgrade/building/upgrade_chamber/spur/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) @@ -300,7 +300,7 @@ GLOBAL_LIST_INIT(tier_to_primo_upgrade, list( name = "Veil Upgrade Chamber" desc = "Constructs a chamber that allows xenos to buy utility mutations. Build up to 3 structures to increase mutation power." icon = "veil" - psypoint_cost = 200 + psypoint_cost = 300 building_type = /obj/structure/xeno/upgrade_chamber/veil /datum/hive_upgrade/building/upgrade_chamber/veil/can_buy(mob/living/carbon/xenomorph/buyer, silent = TRUE) From 86fe23cb555bc9cd153214fb54793380a3f40cf3 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:05:59 -0800 Subject: [PATCH 092/106] pheromones now boost pre-existing pheros, nerf scaling --- code/datums/status_effects/xeno_buffs.dm | 33 ++++++++++++++++--- .../mob/living/carbon/xenomorph/abilities.dm | 5 ++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 5232216ef5c1b..f2db334a99be4 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1231,14 +1231,14 @@ id = "mutation_upgrade_pheromones" alert_type = /atom/movable/screen/alert/status_effect/pheromones chamber_structure = MUTATION_STRUCTURE_VEIL - /// The aura. + /// The aura if it is not using the xeno's aura from pheromones ability. var/datum/aura_bearer/current_aura /// The aura to emit. var/emitted_aura = AURA_XENO_RECOVERY /// The initial value of the aura's power. var/aura_power_base = 1 /// The phero power to increase by. - var/aura_power_per_chamber = 1 + var/aura_power_per_chamber = 0.75 /datum/status_effect/mutation_upgrade/pheromones/on_apply() if(!..()) @@ -1253,12 +1253,35 @@ current_aura.stop_emitting() return ..() -/// (Re)creates the aura. +/// Boosts the current aura (if they have pheromones already) or creates a aura. /datum/status_effect/mutation_upgrade/pheromones/proc/create_aura() if(current_aura) QDEL_NULL(current_aura) - if(chamber_scaling) - current_aura = SSaura.add_emitter(buff_owner, emitted_aura, 6 + aura_power_per_chamber * chamber_scaling * 2, aura_power_base + aura_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) + switch(emitted_aura) + if(AURA_XENO_RECOVERY) + var/datum/action/ability/xeno_action/pheromones/emit_recovery/recovery_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_recovery] + if(recovery_pheromones) + recovery_pheromones.bonus_aura_strength = aura_power_per_chamber * chamber_scaling + QDEL_NULL(buff_owner.current_aura) + recovery_pheromones.apply_pheros(AURA_XENO_RECOVERY) + return + if(AURA_XENO_WARDING) + var/datum/action/ability/xeno_action/pheromones/emit_warding/warding_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_warding] + if(warding_pheromones) + warding_pheromones.bonus_aura_strength = aura_power_per_chamber * chamber_scaling + QDEL_NULL(buff_owner.current_aura) + warding_pheromones.apply_pheros(AURA_XENO_WARDING) + return + if(AURA_XENO_FRENZY) + var/datum/action/ability/xeno_action/pheromones/emit_frenzy/frenzy_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_frenzy] + if(frenzy_pheromones) + frenzy_pheromones.bonus_aura_strength = aura_power_per_chamber * chamber_scaling + QDEL_NULL(buff_owner.current_aura) + frenzy_pheromones.apply_pheros(AURA_XENO_FRENZY) + return + if(!chamber_scaling) + return + current_aura = SSaura.add_emitter(buff_owner, emitted_aura, 6 + aura_power_per_chamber * chamber_scaling * 2, aura_power_base + aura_power_per_chamber * chamber_scaling, -1, FACTION_XENO, buff_owner.hivenumber) /// Sets the chamber_scaling to the amount of active veil chambers and recreates the aura. /datum/status_effect/mutation_upgrade/pheromones/proc/update_buff() diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index f4e60943a99ee..00c9789ad0527 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -633,6 +633,8 @@ ability_cost = 30 desc = "Opens your pheromone options." use_state_flags = ABILITY_USE_STAGGERED|ABILITY_USE_NOTTURF|ABILITY_USE_BUSY|ABILITY_USE_LYING + /// Additional aura strength which will be added to the caste's aura strength. + var/bonus_aura_strength = 0 /datum/action/ability/xeno_action/pheromones/proc/apply_pheros(phero_choice) var/mob/living/carbon/xenomorph/X = owner @@ -645,7 +647,8 @@ X.hud_set_pheromone() return fail_activate() QDEL_NULL(X.current_aura) - X.current_aura = SSaura.add_emitter(X, phero_choice, 6 + X.xeno_caste.aura_strength * 2, X.xeno_caste.aura_strength, -1, X.faction, X.hivenumber) + var/aura_strength = X.xeno_caste.aura_strength + bonus_aura_strength + X.current_aura = SSaura.add_emitter(X, phero_choice, 6 + aura_strength * 2, aura_strength, -1, X.faction, X.hivenumber) X.balloon_alert(X, "[phero_choice]") playsound(X.loc, SFX_ALIEN_DROOL, 25) From de6db0fc1a6f2d8010c4a92aa95e8e9bf67e123c Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:09:09 -0800 Subject: [PATCH 093/106] unneeded update_health() --- code/datums/status_effects/xeno_buffs.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index f2db334a99be4..e1192b7712a48 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -977,7 +977,6 @@ var/sunder_amount = -sunder_regen_per_chamber * chamber_scaling HEAL_XENO_DAMAGE(buff_owner, health_amount, FALSE) buff_owner.adjust_sunder(sunder_amount) - buff_owner.updatehealth() // *************************************** // *************************************** @@ -1023,7 +1022,6 @@ return var/health_amount = buff_owner.maxHealth * leech_buff_per_chamber * chamber_scaling HEAL_XENO_DAMAGE(buff_owner, health_amount, FALSE) - buff_owner.updatehealth() // *************************************** // *********** Upgrade Chambers Buffs - Attack From 35d5ad50f11e84c2cf008c0ba14a4b38b12641cb Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:51:13 -0800 Subject: [PATCH 094/106] do not give plasma over adjusted --- code/datums/status_effects/xeno_buffs.dm | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 46ab927f97281..6791abc07d7ef 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1070,7 +1070,7 @@ /// The amount of plasma to regenerate based on their caste's plasma regeneration. var/plasma_regen_buff_per_chamber = 0.1 // 10% /// The amount of plasma to regenerate based on their caste's maximum plasma. - var/plasma_percentage_buff_per_chamber = 0.01 // 1% + var/plasma_maximum_buff_per_chamber = 0.01 // 1% /datum/status_effect/mutation_upgrade/adrenaline/on_apply() if(!..()) @@ -1089,18 +1089,18 @@ SIGNAL_HANDLER update_chamber_scaling() -/// Gives the xenomorph more plasma (according to their plasma regeneration and adjusted maximum) everytime they are suppose to regen plasma. +/// Gives the xenomorph more plasma (according to their plasma regeneration and adjusted maximum) everytime they are suppose to regen plasma up to their adjusted maximum. /datum/status_effect/mutation_upgrade/adrenaline/proc/on_plasma_regen(mob/living/carbon/xenomorph/source_xenomorph, plasma_mod, seconds_per_tick) SIGNAL_HANDLER if(!chamber_scaling) return - var/adjusted_plasma_max = buff_owner.xeno_caste.plasma_max * buff_owner.xeno_caste.plasma_regen_limit - var/plasma_regen_amount = buff_owner.xeno_caste.plasma_gain * plasma_regen_buff_per_chamber * chamber_scaling - var/plasma_max_amount = adjusted_plasma_max * plasma_percentage_buff_per_chamber * chamber_scaling - var/plasma_to_give = plasma_regen_amount + plasma_max_amount * ((buff_owner.resting || buff_owner.lying_angle) ? 2 : 1) - var/plasma_stored_predicted = (buff_owner.plasma_stored + plasma_to_give) - // Give only enough plasma to reach the adjusted amount (for castes like Hivelord). - buff_owner.gain_plasma(plasma_stored_predicted > adjusted_plasma_max ? plasma_stored_predicted - adjusted_plasma_max : plasma_to_give) + + var/adjusted_plasma_maximum = buff_owner.xeno_caste.plasma_max * buff_owner.xeno_caste.plasma_regen_limit + var/plasma_from_regeneration = buff_owner.xeno_caste.plasma_gain * plasma_regen_buff_per_chamber * chamber_scaling + var/plasma_from_maximum = adjusted_plasma_maximum * plasma_maximum_buff_per_chamber * chamber_scaling + var/plasma_to_give = (plasma_from_regeneration + plasma_from_maximum) * ((buff_owner.resting || buff_owner.lying_angle) ? 2 : 1) + plasma_to_give = clamp(plasma_to_give, 0, adjusted_plasma_maximum - buff_owner.plasma_stored) + buff_owner.gain_plasma(plasma_to_give) // *************************************** // *************************************** From a315cbde713585a406197ae1f87d064cddca9466 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 7 Dec 2024 13:26:12 -0800 Subject: [PATCH 095/106] trail nerf for 1/2 veil --- code/datums/status_effects/xeno_buffs.dm | 6 ++---- code/modules/mob/living/carbon/xenomorph/mutation_datum.dm | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 6791abc07d7ef..06940e7d86232 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1310,10 +1310,8 @@ id = "mutation_upgrade_trail" alert_type = /atom/movable/screen/alert/status_effect/trail chamber_structure = MUTATION_STRUCTURE_VEIL - /// The initial odds of the trail spawning. - var/base_chance = 25 /// The additional chance of the trail starting. - var/chance_per_chamber = 25 + var/chance_per_chamber = 33.33 /// The selected trail that will spawn upon moving. var/obj/selected_trail = /obj/effect/xenomorph/spray /// A list of trails that can be selected @@ -1344,7 +1342,7 @@ SIGNAL_HANDLER if(buff_owner.incapacitated() || buff_owner.lying_angle || buff_owner.resting || !chamber_scaling) return - if(prob(base_chance + (chance_per_chamber * chamber_scaling))) + if(prob(chance_per_chamber * chamber_scaling)) var/turf/T = get_turf(buff_owner) if(T.density || isspaceturf(T)) return diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 9ce6dc58ad347..ed1c0b8fa1854 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -200,5 +200,5 @@ /datum/mutation_upgrade/utility/trail name = "Trail" - desc = "When moving, randomly leave a chosen trail underneath you at a 25% chance and an additional 25% per Veil Chamber." + desc = "When moving, randomly leave a chosen trail underneath you at a 33% chance for every Veil Chamber." status_effect = STATUS_EFFECT_UPGRADE_TRAIL From 05e895084eba72af05b902c407c80ca9aa20aeff Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sat, 7 Dec 2024 18:51:25 -0800 Subject: [PATCH 096/106] queen main found the meta --- code/datums/status_effects/xeno_buffs.dm | 2 +- code/modules/mob/living/carbon/xenomorph/mutation_datum.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 06940e7d86232..bf2915c6fe1a8 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1235,7 +1235,7 @@ /// The initial value of the aura's power. var/aura_power_base = 1 /// The phero power to increase by. - var/aura_power_per_chamber = 0.75 + var/aura_power_per_chamber = 0.5 /datum/status_effect/mutation_upgrade/pheromones/on_apply() if(!..()) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index ed1c0b8fa1854..99c4d9599b798 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -195,7 +195,7 @@ /datum/mutation_upgrade/utility/pheromones name = "Pheromones" - desc = "Allows you to emit a chosen pheromone starting at a power of 1 and an additional 1 per Veil Chamber." + desc = "Allows you to emit a chosen pheromone starting at a power of 1 and an additional 0.5 per Veil Chamber." status_effect = STATUS_EFFECT_UPGRADE_PHERO /datum/mutation_upgrade/utility/trail From 7d40ce5f980b1fb5b44842ccfa13c3c4c4fe12b1 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 12:43:24 -0800 Subject: [PATCH 097/106] ok lets start with mutation nerfs first --- code/datums/status_effects/xeno_buffs.dm | 26 +++++++++---------- .../living/carbon/xenomorph/mutation_datum.dm | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index bf2915c6fe1a8..bcd9d262a3564 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -911,25 +911,25 @@ id = "mutation_upgrade_carapace" alert_type = /atom/movable/screen/alert/status_effect/carapace chamber_structure = MUTATION_STRUCTURE_CHAMBER - /// The amount of soft armor given. - var/armor_buff_per_chamber = 2.5 + /// The amount of hard armor given. + var/armor_buff_per_chamber = 1 /datum/status_effect/mutation_upgrade/carapace/on_apply() if(!..()) return FALSE RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) - buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(armor_buff_per_chamber * chamber_scaling) + buff_owner.hard_armor = buff_owner.hard_armor.modifyAllRatings(armor_buff_per_chamber * chamber_scaling) return TRUE /datum/status_effect/mutation_upgrade/carapace/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) - buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(-armor_buff_per_chamber * chamber_scaling) + buff_owner.hard_armor = buff_owner.hard_armor.modifyAllRatings(-armor_buff_per_chamber * chamber_scaling) return ..() /// Sets the chamber_scaling to the amount of active survival chambers and adjusts soft armor accordingly. /datum/status_effect/mutation_upgrade/carapace/proc/update_buff() SIGNAL_HANDLER - buff_owner.soft_armor = buff_owner.soft_armor.modifyAllRatings(armor_buff_per_chamber * (length(buff_owner.hive.shell_chambers) - chamber_scaling)) + buff_owner.hard_armor = buff_owner.hard_armor.modifyAllRatings(armor_buff_per_chamber * (length(buff_owner.hive.shell_chambers) - chamber_scaling)) update_chamber_scaling() @@ -989,8 +989,8 @@ id = "mutation_upgrade_vampirism" alert_type = /atom/movable/screen/alert/status_effect/vampirism chamber_structure = MUTATION_STRUCTURE_CHAMBER - /// The amount of max health to be regenerated the owner hits an alive human. - var/leech_buff_per_chamber = 0.016 + /// The percentage of damage dealt to be healed after hitting an alive human. + var/leech_buff_per_chamber = 0.1 /datum/status_effect/mutation_upgrade/vampirism/on_apply() if(!..()) @@ -999,12 +999,12 @@ if(isxenoravager(buff_owner)) chamber_scaling /= 2 RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) - RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_slash)) + RegisterSignal(buff_owner, COMSIG_XENOMORPH_POSTATTACK_LIVING, PROC_REF(on_postattack)) return TRUE /datum/status_effect/mutation_upgrade/vampirism/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL) - UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING) + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_POSTATTACK_LIVING) return ..() /// Sets the chamber_scaling to the amount of active survival chambers. @@ -1015,11 +1015,11 @@ chamber_scaling /= 2 /// Heals the xenomorph for hitting a non-dead human by a percentage of their max health. -/datum/status_effect/mutation_upgrade/vampirism/proc/on_slash(datum/source, mob/living/target) +/datum/status_effect/mutation_upgrade/vampirism/proc/on_postattack(datum/source, mob/living/target, damage_done) SIGNAL_HANDLER if(target.stat == DEAD || !ishuman(target)) return - var/health_amount = buff_owner.maxHealth * leech_buff_per_chamber * chamber_scaling + var/health_amount = damage_done * leech_buff_per_chamber * chamber_scaling HEAL_XENO_DAMAGE(buff_owner, health_amount, FALSE) // *************************************** @@ -1235,7 +1235,7 @@ /// The initial value of the aura's power. var/aura_power_base = 1 /// The phero power to increase by. - var/aura_power_per_chamber = 0.5 + var/aura_power_per_chamber = 0.25 /datum/status_effect/mutation_upgrade/pheromones/on_apply() if(!..()) @@ -1311,7 +1311,7 @@ alert_type = /atom/movable/screen/alert/status_effect/trail chamber_structure = MUTATION_STRUCTURE_VEIL /// The additional chance of the trail starting. - var/chance_per_chamber = 33.33 + var/chance_per_chamber = 10 /// The selected trail that will spawn upon moving. var/obj/selected_trail = /obj/effect/xenomorph/spray /// A list of trails that can be selected diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 99c4d9599b798..ff448c068ab9d 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -195,10 +195,10 @@ /datum/mutation_upgrade/utility/pheromones name = "Pheromones" - desc = "Allows you to emit a chosen pheromone starting at a power of 1 and an additional 0.5 per Veil Chamber." + desc = "Allows you to emit a chosen pheromone starting at a power of 1 and an additional 0.25 per Veil Chamber." status_effect = STATUS_EFFECT_UPGRADE_PHERO /datum/mutation_upgrade/utility/trail name = "Trail" - desc = "When moving, randomly leave a chosen trail underneath you at a 33% chance for every Veil Chamber." + desc = "When moving, randomly leave a chosen trail underneath you at a 10% chance for every Veil Chamber." status_effect = STATUS_EFFECT_UPGRADE_TRAIL From b85927019b65e6657f3ef862a8ae6f306add40f8 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 12:53:11 -0800 Subject: [PATCH 098/106] replaces mutation Toxin with mutation Focus --- code/__DEFINES/status_effects.dm | 2 +- code/__DEFINES/xeno.dm | 2 +- code/datums/status_effects/xeno_buffs.dm | 51 ++++++------------- .../living/carbon/xenomorph/mutation_datum.dm | 8 +-- 4 files changed, 21 insertions(+), 42 deletions(-) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index dead66ff61e43..2dd834e648d7c 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -51,7 +51,7 @@ #define STATUS_EFFECT_UPGRADE_CRUSH /datum/status_effect/mutation_upgrade/crush -#define STATUS_EFFECT_UPGRADE_TOXIN /datum/status_effect/mutation_upgrade/toxin +#define STATUS_EFFECT_UPGRADE_FOCUS /datum/status_effect/mutation_upgrade/focus #define STATUS_EFFECT_UPGRADE_PHERO /datum/status_effect/mutation_upgrade/pheromones diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index b2138bf600d50..e52690f0b50e4 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -229,7 +229,7 @@ GLOBAL_LIST_INIT(mutation_upgrades_buyable, list( /datum/mutation_upgrade/attack/celerity, /datum/mutation_upgrade/attack/adrenaline, /datum/mutation_upgrade/attack/crush, - /datum/mutation_upgrade/utility/toxin, + /datum/mutation_upgrade/utility/focus, /datum/mutation_upgrade/utility/pheromones, /datum/mutation_upgrade/utility/trail )) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index bcd9d262a3564..9df8c77a9dd71 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1155,57 +1155,36 @@ // *************************************** // *********** Upgrade Chambers Buffs - Utility // *************************************** -/atom/movable/screen/alert/status_effect/toxin - name = "Toxin" - desc = "Inject toxin on attack. Click to change toxin." +/atom/movable/screen/alert/status_effect/focus + name = "Focus" + desc = "Increases attack damage." icon_state = "xenobuff_generic" -/atom/movable/screen/alert/status_effect/toxin/Click() - var/datum/status_effect/mutation_upgrade/toxin/status_effect = attached_effect - var/datum/reagent/toxin/toxin_choice = show_radial_menu(status_effect.buff_owner, status_effect.buff_owner, GLOB.defiler_toxin_images_list, radius = 35, require_near = TRUE) - if(!toxin_choice) - return - for(var/defiler_toxin in GLOB.defiler_toxin_type_list) - var/datum/reagent/reagent = GLOB.chemical_reagents_list[defiler_toxin] - if(reagent.name == toxin_choice) - status_effect.selected_reagent = reagent.type - break - status_effect.buff_owner.balloon_alert(status_effect.buff_owner, "[toxin_choice]") - -/datum/status_effect/mutation_upgrade/toxin - id = "mutation_upgrade_toxin" - alert_type = /atom/movable/screen/alert/status_effect/toxin +/datum/status_effect/mutation_upgrade/focus + id = "mutation_upgrade_focus" + alert_type = /atom/movable/screen/alert/status_effect/focus chamber_structure = MUTATION_STRUCTURE_VEIL - /// Currently selected reagent to inject. - var/datum/reagent/toxin/selected_reagent = /datum/reagent/toxin/xeno_neurotoxin + /// The bonus melee damage for each chamber. + var/damage_buff_per_chamber = 1 -/datum/status_effect/mutation_upgrade/toxin/on_apply() +/datum/status_effect/mutation_upgrade/focus/on_apply() if(!..()) return FALSE RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) - RegisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING, PROC_REF(on_slash)) + buff_owner.xeno_caste.melee_damage += damage_buff_per_chamber * chamber_scaling return TRUE -/datum/status_effect/mutation_upgrade/toxin/on_remove() +/datum/status_effect/mutation_upgrade/focus/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) - UnregisterSignal(buff_owner, COMSIG_XENOMORPH_ATTACK_LIVING) + buff_owner.xeno_caste.melee_damage -= damage_buff_per_chamber * chamber_scaling return ..() /// Sets the chamber_scaling to the amount of active veil chambers. -/datum/status_effect/mutation_upgrade/toxin/proc/update_buff() +/datum/status_effect/mutation_upgrade/focus/proc/update_buff() SIGNAL_HANDLER + buff_owner.xeno_caste.melee_damage -= damage_buff_per_chamber * chamber_scaling update_chamber_scaling() - -/// Injects the human target with a variable amount of the selected reagent. -/datum/status_effect/mutation_upgrade/toxin/proc/on_slash(datum/source, mob/living/target) - SIGNAL_HANDLER - if(!chamber_scaling || target.stat == DEAD || !ishuman(target) || !target.can_sting()) - return - var/datum/reagent/glob_reagent = GLOB.chemical_reagents_list[selected_reagent] - if(!glob_reagent) - return - var/mob/living/carbon/human/human_target = target - human_target.reagents.add_reagent(selected_reagent, glob_reagent.custom_metabolism * chamber_scaling) + buff_owner.xeno_caste.melee_damage += damage_buff_per_chamber * chamber_scaling // *************************************** // *************************************** diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index ff448c068ab9d..99d6afce3326a 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -188,10 +188,10 @@ category = MUTATION_CATEGORY_UTILITY required_structure = MUTATION_STRUCTURE_VEIL -/datum/mutation_upgrade/utility/toxin - name = "Toxin" - desc = "When slashing living humans, inject a variable amount of a chosen toxin into them. The amount depends on the toxin and Spur Chamber count." - status_effect = STATUS_EFFECT_UPGRADE_TOXIN +/datum/mutation_upgrade/utility/focus + name = "Focus" + desc = "Deal 1 additional melee damage for every Veil Chamber." + status_effect = STATUS_EFFECT_UPGRADE_FOCUS /datum/mutation_upgrade/utility/pheromones name = "Pheromones" From e8ff2734dd968d8e2b5792b314b1407798089b50 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 15:20:51 -0800 Subject: [PATCH 099/106] biomass is now a group resource instead of individual resource --- code/__DEFINES/mobs.dm | 2 +- code/__DEFINES/mode.dm | 1 + code/controllers/subsystem/points.dm | 9 +++++++++ code/datums/gamemodes/nuclear_war.dm | 2 +- code/game/objects/items/cocoon.dm | 20 ++++--------------- code/modules/mob/dead/observer/observer.dm | 2 +- .../mob/living/carbon/xenomorph/abilities.dm | 16 +-------------- .../castes/baneling/castedatum_baneling.dm | 2 +- .../castes/beetle/castedatum_beetle.dm | 2 +- .../castes/hivemind/castedatum_hivemind.dm | 4 ++-- .../castes/mantis/castedatum_mantis.dm | 2 +- .../castes/nymph/castedatum_nymph.dm | 2 +- .../castes/puppet/castedatum_puppet.dm | 2 +- .../castes/scorpion/castedatum_scorpion.dm | 2 +- .../spiderling/castedatum_spiderling.dm | 2 +- .../mob/living/carbon/xenomorph/evolution.dm | 3 --- .../mob/living/carbon/xenomorph/hive_datum.dm | 7 ++++++- .../living/carbon/xenomorph/mutation_datum.dm | 19 ++++++++++-------- .../living/carbon/xenomorph/xeno_defines.dm | 2 -- .../mob/living/carbon/xenomorph/xenoprocs.dm | 11 ++-------- tgui/packages/tgui/interfaces/HiveStatus.tsx | 4 +++- .../tgui/interfaces/MutationSelector.tsx | 4 ++-- 22 files changed, 51 insertions(+), 69 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 187fbc071615f..38fb91e269d6e 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -589,7 +589,7 @@ GLOBAL_LIST_INIT(layers_to_offset, list( #define CASTE_STAGGER_RESISTANT (1<<15) //Resistant to some forms of stagger, such as projectiles #define CASTE_HAS_WOUND_MASK (1<<16) //uses an alpha mask for wounded states #define CASTE_EXCLUDE_STRAINS (1<<17) // denotes castes/basetypes that should be excluded from being evoable as a strain -#define CASTE_NO_BIOMASS (1<<18) // Xenos are excluded from getting any biomass +#define CASTE_NO_MUTATION (1<<18) // Xenos are excluded from getting any mutations. // Xeno defines that affect evolution, considering making a new var for these #define CASTE_LEADER_TYPE (1<<19) //Whether we are a leader type caste, such as the queen, shrike or ?king?, and is affected by queen ban and playtime restrictions diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm index ac92848b50f90..7b7c4bea09346 100644 --- a/code/__DEFINES/mode.dm +++ b/code/__DEFINES/mode.dm @@ -50,6 +50,7 @@ #define MODE_ALLOW_XENO_QUICKBUILD (1<<14) #define MODE_DISALLOW_RAILGUN (1<<15) #define MODE_FORCE_CUSTOMSQUAD_UI (1<<16) +#define MODE_BIOMASS_POINTS (1<<17) #define MODE_INFESTATION_X_MAJOR "Xenomorph Major Victory" #define MODE_INFESTATION_M_MAJOR "Marine Major Victory" diff --git a/code/controllers/subsystem/points.dm b/code/controllers/subsystem/points.dm index a5b4bb0903c8e..3f50c567b5e93 100644 --- a/code/controllers/subsystem/points.dm +++ b/code/controllers/subsystem/points.dm @@ -16,6 +16,8 @@ SUBSYSTEM_DEF(points) var/list/xeno_strategic_points_by_hive = list() ///Assoc list of xeno tactical points: xeno_tactical_points_by_hive["hivenum"] var/list/xeno_tactical_points_by_hive = list() + ///Assoc list of xeno biomass points: xeno_biomass_points_by_hive["hivenum"] + var/list/xeno_biomass_points_by_hive = list() var/ordernum = 1 //order number given to next order @@ -92,6 +94,13 @@ SUBSYSTEM_DEF(points) return xeno_tactical_points_by_hive[hivenumber] += amount + +///Add amount of tactical psy points to the selected hive only if the gamemode support biomass +/datum/controller/subsystem/points/proc/add_biomass_points(hivenumber, amount) + if(!CHECK_BITFIELD(SSticker.mode.round_type_flags, MODE_BIOMASS_POINTS)) + return + xeno_biomass_points_by_hive[hivenumber] = clamp(xeno_biomass_points_by_hive[hivenumber] + amount, 0, 500) + /datum/controller/subsystem/points/proc/approve_request(datum/supply_order/O, mob/living/user) var/cost = 0 for(var/i in O.pack) diff --git a/code/datums/gamemodes/nuclear_war.dm b/code/datums/gamemodes/nuclear_war.dm index 2ddbee953f332..f69493f783728 100644 --- a/code/datums/gamemodes/nuclear_war.dm +++ b/code/datums/gamemodes/nuclear_war.dm @@ -2,7 +2,7 @@ name = "Nuclear War" config_tag = "Nuclear War" silo_scaling = 2 - round_type_flags = MODE_INFESTATION|MODE_LATE_OPENING_SHUTTER_TIMER|MODE_XENO_RULER|MODE_PSY_POINTS|MODE_PSY_POINTS_ADVANCED|MODE_DEAD_GRAB_FORBIDDEN|MODE_HIJACK_POSSIBLE|MODE_SILO_RESPAWN|MODE_SILOS_SPAWN_MINIONS|MODE_ALLOW_XENO_QUICKBUILD|MODE_FORCE_CUSTOMSQUAD_UI + round_type_flags = MODE_INFESTATION|MODE_LATE_OPENING_SHUTTER_TIMER|MODE_XENO_RULER|MODE_PSY_POINTS|MODE_PSY_POINTS_ADVANCED|MODE_DEAD_GRAB_FORBIDDEN|MODE_HIJACK_POSSIBLE|MODE_SILO_RESPAWN|MODE_SILOS_SPAWN_MINIONS|MODE_ALLOW_XENO_QUICKBUILD|MODE_FORCE_CUSTOMSQUAD_UI|MODE_BIOMASS_POINTS xeno_abilities_flags = ABILITY_NUCLEARWAR valid_job_types = list( /datum/job/terragov/command/captain = 1, diff --git a/code/game/objects/items/cocoon.dm b/code/game/objects/items/cocoon.dm index 4246dda1c0e7c..9265b61242297 100644 --- a/code/game/objects/items/cocoon.dm +++ b/code/game/objects/items/cocoon.dm @@ -44,16 +44,10 @@ psych_points_output = clamp(psych_points_output, COCOON_PSY_POINTS_REWARD_MIN, COCOON_PSY_POINTS_REWARD_MAX) SSpoints.add_strategic_psy_points(hivenumber, psych_points_output) SSpoints.add_tactical_psy_points(hivenumber, psych_points_output*0.25) - //Gives marine cloneloss for a total of 30. + // Gives marine cloneloss for a total of 30. victim.adjustCloneLoss(0.5) - - // Slowly give biomass over time up to 9 biomass (assuming the time based on comment above is correct). - for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) - if(xeno.hivenumber != hivenumber) - continue - if(xeno.xeno_caste.caste_flags & CASTE_NO_BIOMASS) - continue - xeno.gain_biomass(0.1) + // Slowly give biomass over time up to 18 biomass (assuming the time based on comment above is correct). + SSpoints.add_biomass_points(hivenumber, 0.3) /obj/structure/cocoon/take_damage(damage_amount, damage_type = BRUTE, armor_type = null, effects = TRUE, attack_dir, armour_penetration = 0, mob/living/blame_mob) . = ..() @@ -79,13 +73,7 @@ var/datum/hive_status/hive_status = GLOB.hive_datums[hivenumber] hive_status.update_tier_limits() GLOB.round_statistics.larva_from_cocoon += larva_point_reward / xeno_job.job_points_needed - // 3.5 biomass to all xenomorphs. - for(var/mob/living/carbon/xenomorph/xeno in GLOB.alive_xeno_list) - if(xeno.hivenumber != hivenumber) - continue - if(xeno.xeno_caste.caste_flags & CASTE_NO_BIOMASS) - continue - xeno.gain_biomass(4) + SSpoints.add_biomass_points(hivenumber, 12) release_victim() update_icon() diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index a07f2a37e304e..57b555009f7ba 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -902,12 +902,12 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) log_game("[key_name(usr)] has joined Valhalla as a Xenomorph.") var/mob/living/carbon/xenomorph/new_xeno = new xeno_choice(pick(GLOB.spawns_by_job[/datum/job/fallen/xenomorph])) new_xeno.transfer_to_hive(XENO_HIVE_FALLEN) - new_xeno.gain_biomass(100) // So they can test it out here. ADD_TRAIT(new_xeno, TRAIT_VALHALLA_XENO, VALHALLA_TRAIT) var/datum/job/xallhala_job = SSjob.GetJobType(/datum/job/fallen/xenomorph) new_xeno.apply_assigned_role_to_spawn(xallhala_job) SSpoints.xeno_strategic_points_by_hive[XENO_HIVE_FALLEN] = 10000 SSpoints.xeno_tactical_points_by_hive[XENO_HIVE_FALLEN] = 10000 + SSpoints.xeno_biomass_points_by_hive[XENO_HIVE_FALLEN] = 500 mind.transfer_to(new_xeno, TRUE) xallhala_job.after_spawn(new_xeno) return diff --git a/code/modules/mob/living/carbon/xenomorph/abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities.dm index 00c9789ad0527..22a82282e6661 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities.dm @@ -1401,21 +1401,7 @@ victim.do_jitter_animation(2) victim.adjustCloneLoss(20) - - var/list/mob/living/carbon/xenomorph/nearby_friendly_xenos = list() - for(var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(X, 7)) - // Intentionally includes the owner. - if(!X.issamexenohive(nearby_xeno)) - continue - if(nearby_xeno.xeno_caste.caste_flags & CASTE_NO_BIOMASS) - continue - nearby_friendly_xenos += nearby_xeno - - if(length(nearby_friendly_xenos)) - // Split the reward amongst every xeno nearby, including themselves. - var/biomass_per_xeno = round(15/length(nearby_friendly_xenos), 0.1) - for(var/mob/living/carbon/xenomorph/nearby_friendly_xeno AS in nearby_friendly_xenos) - nearby_friendly_xeno.gain_biomass(biomass_per_xeno) + SSpoints.add_biomass_points(X.hivenumber, 15) ADD_TRAIT(victim, TRAIT_PSY_DRAINED, TRAIT_PSY_DRAINED) if(HAS_TRAIT(victim, TRAIT_UNDEFIBBABLE)) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/baneling/castedatum_baneling.dm b/code/modules/mob/living/carbon/xenomorph/castes/baneling/castedatum_baneling.dm index 6791f5c3ebc2c..f3356533ed536 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/baneling/castedatum_baneling.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/baneling/castedatum_baneling.dm @@ -24,7 +24,7 @@ max_health = 100 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_BIOMASS + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_MUTATION can_flags = CASTE_CAN_BE_QUEEN_HEALED caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/beetle/castedatum_beetle.dm b/code/modules/mob/living/carbon/xenomorph/castes/beetle/castedatum_beetle.dm index 7e2524b3cdb30..21c46d7720a3a 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/beetle/castedatum_beetle.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/beetle/castedatum_beetle.dm @@ -24,7 +24,7 @@ max_health = 260 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_BIOMASS + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_MUTATION can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_RIDE_CRUSHER caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm b/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm index a7ecb339d8001..a0512db0764b4 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/hivemind/castedatum_hivemind.dm @@ -22,7 +22,7 @@ maximum_active_caste = 1 // *** Flags *** // - caste_flags = CASTE_INNATE_PLASMA_REGEN|CASTE_FIRE_IMMUNE|CASTE_IS_BUILDER|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_NO_BIOMASS + caste_flags = CASTE_INNATE_PLASMA_REGEN|CASTE_FIRE_IMMUNE|CASTE_IS_BUILDER|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_NO_MUTATION can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_GIVEN_PLASMA caste_traits = null @@ -74,7 +74,7 @@ upgrade = XENO_UPGRADE_MANIFESTATION // *** Flags *** // - caste_flags = CASTE_IS_BUILDER|CASTE_FIRE_IMMUNE|CASTE_NO_BIOMASS + caste_flags = CASTE_IS_BUILDER|CASTE_FIRE_IMMUNE|CASTE_NO_MUTATION aura_strength = 4 //Good pheros diff --git a/code/modules/mob/living/carbon/xenomorph/castes/mantis/castedatum_mantis.dm b/code/modules/mob/living/carbon/xenomorph/castes/mantis/castedatum_mantis.dm index bff0c53574e43..9b71d0df965fd 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/mantis/castedatum_mantis.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/mantis/castedatum_mantis.dm @@ -25,7 +25,7 @@ max_health = 150 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_BIOMASS + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_MUTATION can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_GIVEN_PLASMA|CASTE_CAN_RIDE_CRUSHER caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/nymph/castedatum_nymph.dm b/code/modules/mob/living/carbon/xenomorph/castes/nymph/castedatum_nymph.dm index de97402bcd3a8..f897a8ccfffc6 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/nymph/castedatum_nymph.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/nymph/castedatum_nymph.dm @@ -24,7 +24,7 @@ max_health = 120 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_IS_BUILDER|CASTE_NO_BIOMASS + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_IS_BUILDER|CASTE_NO_MUTATION can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_GIVEN_PLASMA // *** Defense *** // diff --git a/code/modules/mob/living/carbon/xenomorph/castes/puppet/castedatum_puppet.dm b/code/modules/mob/living/carbon/xenomorph/castes/puppet/castedatum_puppet.dm index afa3aace7a811..82f8fa4d00b5e 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/puppet/castedatum_puppet.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/puppet/castedatum_puppet.dm @@ -15,7 +15,7 @@ plasma_max = 2 plasma_gain = 0 max_health = 250 - caste_flags = CASTE_NOT_IN_BIOSCAN|CASTE_DO_NOT_ANNOUNCE_DEATH|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_NO_BIOMASS + caste_flags = CASTE_NOT_IN_BIOSCAN|CASTE_DO_NOT_ANNOUNCE_DEATH|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_NO_MUTATION minimap_icon = "puppet" soft_armor = list(MELEE = 14, BULLET = 3, LASER = 5, ENERGY = 3, BOMB = 0, BIO = 0, FIRE = 0, ACID = 0) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/scorpion/castedatum_scorpion.dm b/code/modules/mob/living/carbon/xenomorph/castes/scorpion/castedatum_scorpion.dm index 66ef28d226b42..6dc30aa83fcfd 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/scorpion/castedatum_scorpion.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/scorpion/castedatum_scorpion.dm @@ -24,7 +24,7 @@ max_health = 130 // *** Flags *** // - caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_BIOMASS + caste_flags = CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_A_MINION|CASTE_NO_MUTATION can_flags = CASTE_CAN_BE_QUEEN_HEALED|CASTE_CAN_BE_GIVEN_PLASMA|CASTE_CAN_RIDE_CRUSHER caste_traits = null diff --git a/code/modules/mob/living/carbon/xenomorph/castes/spiderling/castedatum_spiderling.dm b/code/modules/mob/living/carbon/xenomorph/castes/spiderling/castedatum_spiderling.dm index fb786ef7ebe0c..e9c7964f079ff 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/spiderling/castedatum_spiderling.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/spiderling/castedatum_spiderling.dm @@ -25,7 +25,7 @@ max_health = 125 // *** Flags *** // - caste_flags = CASTE_NOT_IN_BIOSCAN|CASTE_DO_NOT_ANNOUNCE_DEATH|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_BUILDER|CASTE_NO_BIOMASS + caste_flags = CASTE_NOT_IN_BIOSCAN|CASTE_DO_NOT_ANNOUNCE_DEATH|CASTE_DO_NOT_ALERT_LOW_LIFE|CASTE_IS_BUILDER|CASTE_NO_MUTATION // *** Minimap Icon *** // minimap_icon = "spiderling" diff --git a/code/modules/mob/living/carbon/xenomorph/evolution.dm b/code/modules/mob/living/carbon/xenomorph/evolution.dm index 06b4f9a38a7af..6cfccda4b9fb6 100644 --- a/code/modules/mob/living/carbon/xenomorph/evolution.dm +++ b/code/modules/mob/living/carbon/xenomorph/evolution.dm @@ -173,9 +173,6 @@ new_xeno.hive?.update_ruler() // Since ruler wasn't set during initialization, update ruler now. transfer_observers_to(new_xeno) - // Carry over the biomass - new_xeno.biomass = biomass - if(new_xeno.health - getBruteLoss(src) - getFireLoss(src) > 0) //Cmon, don't kill the new one! Shouldnt be possible though new_xeno.bruteloss = bruteloss //Transfers the damage over. new_xeno.fireloss = fireloss //Transfers the damage over. diff --git a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm index febaf5a85c8c0..36f621f1e5735 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_datum.dm @@ -42,6 +42,9 @@ var/datum/hive_purchases/purchases = new /// The nuke HUD timer datum, shown on each xeno's screen var/atom/movable/screen/text/screen_timer/nuke_hud_timer + /// The amount of biomass stored. + var/biomass = 0 + // *************************************** // *********** Init @@ -159,6 +162,7 @@ "is_leader" = xeno.xeno_flags & XENO_LEADER, "is_ssd" = !xeno.client, "index" = GLOB.hive_ui_caste_index[caste.caste_type_path], + "mutation_disabled" = caste.caste_flags & CASTE_NO_MUTATION )) var/mob/living/carbon/xenomorph/xeno_user @@ -177,7 +181,7 @@ .["user_maturity"] = isxeno(user) ? xeno_user.upgrade_stored : 0 .["user_next_mat_level"] = isxeno(user) && xeno_user.upgrade_possible() ? xeno_user.xeno_caste.upgrade_threshold : 0 .["user_tracked"] = isxeno(user) && !isnull(xeno_user.tracked) ? REF(xeno_user.tracked) : "" - + .["user_can_mutate"] = !isxeno(user) || (xeno_user.xeno_caste.caste_flags & CASTE_NO_MUTATION) .["user_show_empty"] = !!(user.client.prefs.status_toggle_flags & HIVE_STATUS_SHOW_EMPTY) .["user_show_compact"] = !!(user.client.prefs.status_toggle_flags & HIVE_STATUS_COMPACT_MODE) .["user_show_general"] = !!(user.client.prefs.status_toggle_flags & HIVE_STATUS_SHOW_GENERAL) @@ -1607,3 +1611,4 @@ to_chat will check for valid clients itself already so no need to double check f if(faction == FACTION_ZOMBIE) return FACTION_ZOMBIE return FALSE + diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index 99d6afce3326a..fdb0cbcb57269 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -16,7 +16,7 @@ data["shell_chambers"] = length(xeno_user.hive?.shell_chambers) data["spur_chambers"] = length(xeno_user.hive?.spur_chambers) data["veil_chambers"] = length(xeno_user.hive?.veil_chambers) - data["biomass"] = xeno_user.biomass + data["biomass"] = !isnull(SSpoints.xeno_biomass_points_by_hive[xeno_user.hivenumber]) ? SSpoints.xeno_biomass_points_by_hive[xeno_user.hivenumber] : 0 return data /datum/mutation_datum/ui_static_data(mob/living/carbon/xenomorph/xeno_user) @@ -74,7 +74,9 @@ /// Tries to purchase a mutation. Denies if possible. Otherwise, removes conflicting mutations and gives the purchased mutation. /datum/mutation_datum/proc/try_purchase_mutation(mob/living/carbon/xenomorph/xeno_purchaser, upgrade_name) - if(!upgrade_name) + if(!xeno_purchaser.hive || !upgrade_name) + return + if((xeno_purchaser.xeno_caste.caste_flags & CASTE_NO_MUTATION)) return var/upgrade_price @@ -88,8 +90,9 @@ else upgrade_price = XENO_UPGRADE_BIOMASS_COST_T4 - if(xeno_purchaser.biomass < upgrade_price) - to_chat(usr, span_warning("You don't have enough biomass!")) + var/current_biomass = !isnull(SSpoints.xeno_biomass_points_by_hive[xeno_purchaser.hivenumber]) ? SSpoints.xeno_biomass_points_by_hive[xeno_purchaser.hivenumber] : 0 + if(current_biomass < upgrade_price) + to_chat(usr, span_warning("The hive does not have enough biomass!")) return var/datum/mutation_upgrade/chosen_mutation_upgrade @@ -103,15 +106,15 @@ switch(chosen_mutation_upgrade.required_structure) if(MUTATION_STRUCTURE_CHAMBER) - if(!length(xeno_purchaser.hive?.shell_chambers)) + if(!length(xeno_purchaser.hive.shell_chambers)) to_chat(usr, span_xenonotice("This mutation requires a shell chamber to exist!")) return if(MUTATION_STRUCTURE_SPUR) - if(!length(xeno_purchaser.hive?.spur_chambers)) + if(!length(xeno_purchaser.hive.spur_chambers)) to_chat(usr, span_xenonotice("This mutation requires a spur chamber to exist!")) return if(MUTATION_STRUCTURE_VEIL) - if(!length(xeno_purchaser.hive?.veil_chambers)) + if(!length(xeno_purchaser.hive.veil_chambers)) to_chat(usr, span_xenonotice("This mutation requires a veil chamber to exist!")) return @@ -125,7 +128,7 @@ if(chosen_mutation_upgrade.category == subtype_mutation.category) mutation_status_effects_to_remove += subtype_mutation.status_effect - xeno_purchaser.use_biomass(upgrade_price) + SSpoints.xeno_biomass_points_by_hive[xeno_purchaser.hivenumber] -= upgrade_price to_chat(xeno_purchaser, span_xenonotice("Mutation gained.")) for(var/datum/status_effect/removed_status_effect AS in mutation_status_effects_to_remove) xeno_purchaser.remove_status_effect(removed_status_effect) diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index 03f81d4326ae8..624a032f869d3 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -347,8 +347,6 @@ GLOBAL_LIST_INIT(strain_list, init_glob_strain_list()) ///Will increase by 10 every decisecond if under 0. ///Increases by xeno_caste.regen_ramp_amount every decisecond. If you want to balance this, look at the xeno_caste defines mentioned above. var/regen_power = 0 - /// The amount of biomass stored. Used for Chamber Upgrades. - var/biomass = 0 var/zoom_turf = null diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index 557c99ecd5140..6e76d3f095111 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -126,9 +126,8 @@ else //Upgrade process finished or impossible . += "Upgrade Progress: (FINISHED)" - if(!(xeno_caste.caste_flags & CASTE_NO_BIOMASS)) - . += "Biomass: [biomass]/100" - + if(!(xeno_caste.caste_flags & CASTE_NO_MUTATION)) + . += "Biomass: [!isnull(SSpoints.xeno_biomass_points_by_hive[xeno_user.hivenumber]) ? SSpoints.xeno_biomass_points_by_hive[xeno_user.hivenumber] : 0]/500" . += "Health: [health]/[maxHealth][overheal ? " + [overheal]": ""]" //Changes with balance scalar, can't just use the caste @@ -584,9 +583,3 @@ /mob/living/carbon/xenomorph/on_eord(turf/destination) revive(TRUE) - -/mob/living/carbon/xenomorph/proc/use_biomass(value) - biomass = clamp(biomass - value, 0, 100) - -/mob/living/carbon/xenomorph/proc/gain_biomass(value) - biomass = clamp(biomass + value, 0, 100) diff --git a/tgui/packages/tgui/interfaces/HiveStatus.tsx b/tgui/packages/tgui/interfaces/HiveStatus.tsx index 75a7417765881..f7cae197cb00f 100644 --- a/tgui/packages/tgui/interfaces/HiveStatus.tsx +++ b/tgui/packages/tgui/interfaces/HiveStatus.tsx @@ -44,6 +44,7 @@ type InputPack = { user_evolution: number; user_purchase_perms: boolean; user_maturity: number; + user_can_mutate: boolean; user_next_mat_level: number; user_tracked: string; user_show_compact: boolean; @@ -205,13 +206,14 @@ const BlessingsButton = (_props: any) => { const MutationsButton = (_props: any) => { const { act, data } = useBackend(); - const { user_ref } = data; + const { user_ref, user_can_mutate } = data; return ( diff --git a/tgui/packages/tgui/interfaces/MutationSelector.tsx b/tgui/packages/tgui/interfaces/MutationSelector.tsx index 2dbc586dc4892..03321ae94ba37 100644 --- a/tgui/packages/tgui/interfaces/MutationSelector.tsx +++ b/tgui/packages/tgui/interfaces/MutationSelector.tsx @@ -64,8 +64,8 @@ const BiomassBar = (_props: any) => { - - {`${biomass} / 100 `} + + {`${biomass} / 500 `} From f80b11ada373af487dd2893a463cf28c20fdeef1 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 15:28:29 -0800 Subject: [PATCH 100/106] whoops --- code/modules/mob/living/carbon/xenomorph/xenoprocs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm index 6e76d3f095111..737f1bfe8d58a 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenoprocs.dm @@ -127,7 +127,7 @@ . += "Upgrade Progress: (FINISHED)" if(!(xeno_caste.caste_flags & CASTE_NO_MUTATION)) - . += "Biomass: [!isnull(SSpoints.xeno_biomass_points_by_hive[xeno_user.hivenumber]) ? SSpoints.xeno_biomass_points_by_hive[xeno_user.hivenumber] : 0]/500" + . += "Biomass: [!isnull(SSpoints.xeno_biomass_points_by_hive[hivenumber]) ? SSpoints.xeno_biomass_points_by_hive[hivenumber] : 0]/500" . += "Health: [health]/[maxHealth][overheal ? " + [overheal]": ""]" //Changes with balance scalar, can't just use the caste From c8cacf5a8221ab5b5421fe5d8497b9f1253f05a7 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 15:33:03 -0800 Subject: [PATCH 101/106] prevent bonus_area_strength holdover --- code/datums/status_effects/xeno_buffs.dm | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 9df8c77a9dd71..530d57623b465 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1227,32 +1227,45 @@ UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) if(current_aura) current_aura.stop_emitting() + switch(emitted_aura) + if(AURA_XENO_RECOVERY) + var/datum/action/ability/xeno_action/pheromones/emit_recovery/recovery_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_recovery] + if(recovery_pheromones) + recovery_pheromones.bonus_aura_strength = initial(recovery_pheromones.bonus_aura_strength) + recovery_pheromones.apply_pheros(AURA_XENO_RECOVERY) + if(AURA_XENO_WARDING) + var/datum/action/ability/xeno_action/pheromones/emit_warding/warding_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_warding] + if(warding_pheromones) + warding_pheromones.bonus_aura_strength = initial(warding_pheromones.bonus_aura_strength) + warding_pheromones.apply_pheros(AURA_XENO_WARDING) + if(AURA_XENO_FRENZY) + var/datum/action/ability/xeno_action/pheromones/emit_frenzy/frenzy_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_frenzy] + if(frenzy_pheromones) + frenzy_pheromones.bonus_aura_strength = initial(frenzy_pheromones.bonus_aura_strength) + frenzy_pheromones.apply_pheros(AURA_XENO_FRENZY) return ..() /// Boosts the current aura (if they have pheromones already) or creates a aura. /datum/status_effect/mutation_upgrade/pheromones/proc/create_aura() if(current_aura) - QDEL_NULL(current_aura) + current_aura.stop_emitting() switch(emitted_aura) if(AURA_XENO_RECOVERY) var/datum/action/ability/xeno_action/pheromones/emit_recovery/recovery_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_recovery] if(recovery_pheromones) recovery_pheromones.bonus_aura_strength = aura_power_per_chamber * chamber_scaling - QDEL_NULL(buff_owner.current_aura) recovery_pheromones.apply_pheros(AURA_XENO_RECOVERY) return if(AURA_XENO_WARDING) var/datum/action/ability/xeno_action/pheromones/emit_warding/warding_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_warding] if(warding_pheromones) warding_pheromones.bonus_aura_strength = aura_power_per_chamber * chamber_scaling - QDEL_NULL(buff_owner.current_aura) warding_pheromones.apply_pheros(AURA_XENO_WARDING) return if(AURA_XENO_FRENZY) var/datum/action/ability/xeno_action/pheromones/emit_frenzy/frenzy_pheromones = buff_owner.actions_by_path[/datum/action/ability/xeno_action/pheromones/emit_frenzy] if(frenzy_pheromones) frenzy_pheromones.bonus_aura_strength = aura_power_per_chamber * chamber_scaling - QDEL_NULL(buff_owner.current_aura) frenzy_pheromones.apply_pheros(AURA_XENO_FRENZY) return if(!chamber_scaling) From 58be8c858ef27755292cb9229bfc38627179b098 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 15:34:16 -0800 Subject: [PATCH 102/106] desc changes --- code/datums/status_effects/xeno_buffs.dm | 3 --- code/modules/mob/living/carbon/xenomorph/mutation_datum.dm | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 530d57623b465..853665dde02c7 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -995,9 +995,6 @@ /datum/status_effect/mutation_upgrade/vampirism/on_apply() if(!..()) return FALSE - // Ravagers gets half of the effect since they eventually get their own version of vampirism. - if(isxenoravager(buff_owner)) - chamber_scaling /= 2 RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_SURVIVAL, PROC_REF(update_buff)) RegisterSignal(buff_owner, COMSIG_XENOMORPH_POSTATTACK_LIVING, PROC_REF(on_postattack)) return TRUE diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index fdb0cbcb57269..f45144e4d1138 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -153,7 +153,7 @@ /datum/mutation_upgrade/survival/carapace name = "Carapace" - desc = "Increases our soft armor by 2.5 per Shell Chamber." + desc = "Increases our hard armor by 1 per Shell Chamber." status_effect = STATUS_EFFECT_UPGRADE_CARAPACE /datum/mutation_upgrade/survival/regeneration @@ -163,7 +163,7 @@ /datum/mutation_upgrade/survival/vampirism name = "Vampirism" - desc = "When slashing living humans, heal 1.67% max health per Shell Chamber. Ravagers get half the bonus instead." + desc = "When slashing living humans, heal 10% for damage dealt per Shell Chamber." status_effect = STATUS_EFFECT_UPGRADE_VAMPIRISM /datum/mutation_upgrade/attack From 7e4ee0fcf894b1aaf7f5124f721d0222227b844c Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 16:31:47 -0800 Subject: [PATCH 103/106] xeno_message for those who buy mutations --- code/modules/mob/living/carbon/xenomorph/mutation_datum.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index f45144e4d1138..ff87e7e1c589e 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -134,6 +134,7 @@ xeno_purchaser.remove_status_effect(removed_status_effect) xeno_purchaser.do_jitter_animation(500) xeno_purchaser.apply_status_effect(chosen_mutation_upgrade.status_effect) + xeno_message("[xeno_purchaser] has purchased [chosen_mutation_upgrade.name] Mutation.", "xenoannounce", 5, xeno_purchaser.hivenumber) /datum/mutation_upgrade /// The name that is displayed in the TGUI. From 9251c2e8a00b4878564cd369ec093ae4f9491c01 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 16:56:35 -0800 Subject: [PATCH 104/106] eh this is probably fine to remove --- code/datums/status_effects/xeno_buffs.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 853665dde02c7..639276bad3719 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1008,8 +1008,6 @@ /datum/status_effect/mutation_upgrade/vampirism/proc/update_buff() SIGNAL_HANDLER update_chamber_scaling() - if(isxenoravager(buff_owner)) - chamber_scaling /= 2 /// Heals the xenomorph for hitting a non-dead human by a percentage of their max health. /datum/status_effect/mutation_upgrade/vampirism/proc/on_postattack(datum/source, mob/living/target, damage_done) From 83b6aa5c0eacc698c3f5b8cf10ed9ae6e20eee1a Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Sun, 8 Dec 2024 23:46:14 -0800 Subject: [PATCH 105/106] todo stuff later --- code/__DEFINES/traits.dm | 1 + code/datums/status_effects/xeno_buffs.dm | 39 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 856b0b64d65fc..5aabb1bd66d03 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -80,6 +80,7 @@ #define SPECIES_TRAIT "species" // /datum/species innate trait #define CRYOPOD_TRAIT "cryopod" #define XENO_TRAIT "xeno" +#define XENO_BUFF_TRAIT "xenobuff" #define ARMOR_TRAIT "armor" #define STAT_TRAIT "stat" #define NECKGRAB_TRAIT "neckgrab" diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index 639276bad3719..f1b18c5c0a53c 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1181,6 +1181,45 @@ update_chamber_scaling() buff_owner.xeno_caste.melee_damage += damage_buff_per_chamber * chamber_scaling +// *************************************** +// *************************************** +// *************************************** +// TODO: Replace Trail with this. +/atom/movable/screen/alert/status_effect/camouflage + name = "Camouflage" + desc = "Increases your capabilities of stealth." + icon_state = "xenobuff_generic" + +/datum/status_effect/mutation_upgrade/camouflage + id = "mutation_upgrade_camouflage" + alert_type = /atom/movable/screen/alert/status_effect/camouflage + chamber_structure = MUTATION_STRUCTURE_VEIL + +/datum/status_effect/mutation_upgrade/camouflage/on_apply() + if(!..()) + return FALSE + RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) + ADD_TRAIT(src, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) + // TODO: Waiting on motion sensor component PR to merge first. + if(chamber_scaling >= 3) + buff_owner.alpha = 64 + return TRUE + +/datum/status_effect/mutation_upgrade/camouflage/on_remove() + UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) + REMOVE_TRAIT(src, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) + if(chamber_scaling >= 3) + buff_owner.alpha = initial(buff_owner.alpha) + return ..() + +/// Sets the chamber_scaling to the amount of active veil chambers. +/datum/status_effect/mutation_upgrade/camouflage/proc/update_buff() + SIGNAL_HANDLER + update_chamber_scaling() + ADD_TRAIT(src, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) + if(chamber_scaling >= 3) + buff_owner.alpha = 64 + // *************************************** // *************************************** // *************************************** From 9fbdb415b8dc38466e72e65a45533c152c453585 Mon Sep 17 00:00:00 2001 From: Rune Knight <30399783+Runian@users.noreply.github.com> Date: Mon, 9 Dec 2024 02:46:55 -0800 Subject: [PATCH 106/106] kills trail and replace it with camouflage --- code/__DEFINES/status_effects.dm | 2 +- code/__DEFINES/traits.dm | 3 +- code/__DEFINES/xeno.dm | 2 +- code/datums/status_effects/xeno_buffs.dm | 129 +++++++----------- code/game/objects/items/motion_detector.dm | 4 +- .../living/carbon/xenomorph/mutation_datum.dm | 8 +- 6 files changed, 61 insertions(+), 87 deletions(-) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 2dd834e648d7c..961f191cfc0c6 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -55,7 +55,7 @@ #define STATUS_EFFECT_UPGRADE_PHERO /datum/status_effect/mutation_upgrade/pheromones -#define STATUS_EFFECT_UPGRADE_TRAIL /datum/status_effect/mutation_upgrade/trail +#define STATUS_EFFECT_UPGRADE_CAMOUFLAGE /datum/status_effect/mutation_upgrade/camouflage #define STATUS_EFFECT_MINDMEND /datum/status_effect/mindmeld diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 5aabb1bd66d03..817045e3e490f 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -188,7 +188,8 @@ #define TRAIT_TANK_DESANT "tank_desant" ///Builds things better #define TRAIT_SUPERIOR_BUILDER "superior_builder" - +/// Does not ping tactical sensor +#define TRAIT_TACTICAL_SENSOR_IMMUNE "tactical_sensor_immune" /// Prevents usage of manipulation appendages (picking, holding or using items, manipulating storage). #define TRAIT_HANDS_BLOCKED "handsblocked" diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index e52690f0b50e4..458b0f832203c 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -231,7 +231,7 @@ GLOBAL_LIST_INIT(mutation_upgrades_buyable, list( /datum/mutation_upgrade/attack/crush, /datum/mutation_upgrade/utility/focus, /datum/mutation_upgrade/utility/pheromones, - /datum/mutation_upgrade/utility/trail + /datum/mutation_upgrade/utility/camouflage )) #define MUTATION_CATEGORY_SURVIVAL "Survival" diff --git a/code/datums/status_effects/xeno_buffs.dm b/code/datums/status_effects/xeno_buffs.dm index f1b18c5c0a53c..3490750cb1dbc 100644 --- a/code/datums/status_effects/xeno_buffs.dm +++ b/code/datums/status_effects/xeno_buffs.dm @@ -1184,7 +1184,6 @@ // *************************************** // *************************************** // *************************************** -// TODO: Replace Trail with this. /atom/movable/screen/alert/status_effect/camouflage name = "Camouflage" desc = "Increases your capabilities of stealth." @@ -1194,31 +1193,73 @@ id = "mutation_upgrade_camouflage" alert_type = /atom/movable/screen/alert/status_effect/camouflage chamber_structure = MUTATION_STRUCTURE_VEIL + var/actively_cloaked = FALSE /datum/status_effect/mutation_upgrade/camouflage/on_apply() if(!..()) return FALSE RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) - ADD_TRAIT(src, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) - // TODO: Waiting on motion sensor component PR to merge first. + ADD_TRAIT(buff_owner, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) + if(chamber_scaling >= 2) + ADD_TRAIT(buff_owner, TRAIT_TACTICAL_SENSOR_IMMUNE, XENO_BUFF_TRAIT) if(chamber_scaling >= 3) - buff_owner.alpha = 64 + RegisterSignal(buff_owner, COMSIG_XENOMORPH_HEALTH_REGEN, PROC_REF(give_camouflage)) return TRUE /datum/status_effect/mutation_upgrade/camouflage/on_remove() UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) - REMOVE_TRAIT(src, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) + REMOVE_TRAIT(buff_owner, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) + if(chamber_scaling >= 2) + REMOVE_TRAIT(buff_owner, TRAIT_TACTICAL_SENSOR_IMMUNE, XENO_BUFF_TRAIT) if(chamber_scaling >= 3) - buff_owner.alpha = initial(buff_owner.alpha) + remove_camouflage() + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_HEALTH_REGEN, PROC_REF(give_camouflage)) return ..() /// Sets the chamber_scaling to the amount of active veil chambers. /datum/status_effect/mutation_upgrade/camouflage/proc/update_buff() SIGNAL_HANDLER + var/previous_chamber_scale = chamber_scaling update_chamber_scaling() - ADD_TRAIT(src, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) - if(chamber_scaling >= 3) - buff_owner.alpha = 64 + // No change at all. + if(previous_chamber_scale == chamber_scaling) + return + // Scaling down. + if(previous_chamber_scale > chamber_scaling) + // Removes things based on the difference. + for(var/i = (chamber_scaling + 1) to previous_chamber_scale) + switch(i) + if(1) + REMOVE_TRAIT(buff_owner, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) + if(2) + REMOVE_TRAIT(buff_owner, TRAIT_TACTICAL_SENSOR_IMMUNE, XENO_BUFF_TRAIT) + if(3) + remove_camouflage() + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_HEALTH_REGEN) + return + // Scaling up. + for(var/i = (previous_chamber_scale + 1) to chamber_scaling) + switch(i) + if(1) + ADD_TRAIT(buff_owner, TRAIT_SILENT_FOOTSTEPS, XENO_BUFF_TRAIT) + if(2) + ADD_TRAIT(buff_owner, TRAIT_TACTICAL_SENSOR_IMMUNE, XENO_BUFF_TRAIT) + if(3) + give_camouflage() + RegisterSignal(buff_owner, COMSIG_XENOMORPH_HEALTH_REGEN, PROC_REF(give_camouflage)) + +/// Sets the alpha of the owner to normal. +/datum/status_effect/mutation_upgrade/camouflage/proc/remove_camouflage() + buff_owner.alpha = initial(buff_owner.alpha) + UnregisterSignal(buff_owner, COMSIG_XENOMORPH_TAKING_DAMAGE) + +/// Sets the alpha of the owner if their alpha is normal. +/datum/status_effect/mutation_upgrade/camouflage/proc/give_camouflage() + // No giving camouflage if they already got it or getting their alpha set by something else. + if(buff_owner.alpha != 255) + return + buff_owner.alpha = 64 + RegisterSignal(buff_owner, COMSIG_XENOMORPH_TAKING_DAMAGE, PROC_REF(remove_camouflage)) // *************************************** // *************************************** @@ -1311,73 +1352,3 @@ SIGNAL_HANDLER update_chamber_scaling() create_aura() - -// *************************************** -// *************************************** -// *************************************** -/atom/movable/screen/alert/status_effect/trail - name = "Trail" - desc = "We leave a trail behind. Click to change trail." - icon_state = "xenobuff_generic" - -/atom/movable/screen/alert/status_effect/trail/Click() - var/datum/status_effect/mutation_upgrade/trail/effect = attached_effect - if(effect.buff_owner.incapacitated()) - to_chat(usr, span_warning("Cant do that right now!")) - return - var/i = effect.selectable_trails.Find(effect.selected_trail) - if(length(effect.selectable_trails) == i) - effect.selected_trail = effect.selectable_trails[1] - else - effect.selected_trail = effect.selectable_trails[i+1] - effect.buff_owner.balloon_alert(effect.buff_owner, "[effect.selected_trail.name]") - -/datum/status_effect/mutation_upgrade/trail - id = "mutation_upgrade_trail" - alert_type = /atom/movable/screen/alert/status_effect/trail - chamber_structure = MUTATION_STRUCTURE_VEIL - /// The additional chance of the trail starting. - var/chance_per_chamber = 10 - /// The selected trail that will spawn upon moving. - var/obj/selected_trail = /obj/effect/xenomorph/spray - /// A list of trails that can be selected - var/list/selectable_trails = list( - /obj/effect/xenomorph/spray, - /obj/alien/resin/sticky/thin/temporary - ) - -/datum/status_effect/mutation_upgrade/trail/on_apply() - if(!..()) - return FALSE - RegisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY, PROC_REF(update_buff)) - RegisterSignal(buff_owner, COMSIG_MOVABLE_MOVED, PROC_REF(create_trail)) - return TRUE - -/datum/status_effect/mutation_upgrade/trail/on_remove() - UnregisterSignal(SSdcs, COMSIG_UPGRADE_CHAMBER_UTILITY) - UnregisterSignal(buff_owner, COMSIG_MOVABLE_MOVED) - return ..() - -/// Sets the chamber_scaling to the amount of active veil chambers. -/datum/status_effect/mutation_upgrade/trail/proc/update_buff() - SIGNAL_HANDLER - update_chamber_scaling() - -/// Rolls the dice and creates the selected trail if the dice is right. -/datum/status_effect/mutation_upgrade/trail/proc/create_trail() - SIGNAL_HANDLER - if(buff_owner.incapacitated() || buff_owner.lying_angle || buff_owner.resting || !chamber_scaling) - return - if(prob(chance_per_chamber * chamber_scaling)) - var/turf/T = get_turf(buff_owner) - if(T.density || isspaceturf(T)) - return - for(var/obj/O in T.contents) - if(is_type_in_typecache(O, GLOB.no_sticky_resin)) - return - if(selected_trail == /obj/effect/xenomorph/spray) - new selected_trail(T, rand(2 SECONDS, 5 SECONDS)) - for(var/obj/O in T) - O.acid_spray_act(buff_owner) - else - new selected_trail(T) diff --git a/code/game/objects/items/motion_detector.dm b/code/game/objects/items/motion_detector.dm index 1f0bce3d96a6a..2cc15c41c6473 100644 --- a/code/game/objects/items/motion_detector.dm +++ b/code/game/objects/items/motion_detector.dm @@ -136,7 +136,9 @@ continue prepare_blip(nearby_human, nearby_human.wear_id?.iff_signal & operator.wear_id.iff_signal ? MOTION_DETECTOR_FRIENDLY : MOTION_DETECTOR_HOSTILE) for (var/mob/living/carbon/xenomorph/nearby_xeno AS in cheap_get_xenos_near(operator, range)) - if(nearby_xeno.last_move_time + move_sensitivity < world.time ) + if(nearby_xeno.last_move_time + move_sensitivity < world.time) + continue + if(HAS_TRAIT(nearby_xeno, TRAIT_TACTICAL_SENSOR_IMMUNE)) continue prepare_blip(nearby_xeno, MOTION_DETECTOR_HOSTILE) if(hostile_detected) diff --git a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm index ff87e7e1c589e..c517e9c4ea12e 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutation_datum.dm @@ -202,7 +202,7 @@ desc = "Allows you to emit a chosen pheromone starting at a power of 1 and an additional 0.25 per Veil Chamber." status_effect = STATUS_EFFECT_UPGRADE_PHERO -/datum/mutation_upgrade/utility/trail - name = "Trail" - desc = "When moving, randomly leave a chosen trail underneath you at a 10% chance for every Veil Chamber." - status_effect = STATUS_EFFECT_UPGRADE_TRAIL +/datum/mutation_upgrade/utility/camouflage + name = "Camouflage" + desc = "Grants various stealth effects based on the amount of Veil Chambers: slient step (1), immunity to tactical sensor detection (2), and stealth that is broken when taking damage & regained when healing (3)." + status_effect = STATUS_EFFECT_UPGRADE_CAMOUFLAGE