From 4ef3b9ec88bebe3e3b77c59aa1353f35e2229d32 Mon Sep 17 00:00:00 2001 From: forest2001 <41653574+realforest2001@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:05:17 +0100 Subject: [PATCH] Yautja Bracer Charging Rework (#3456) # About the pull request Changes how bracers recharge, requiring drain from APC in the field. Change made as atomisation from #3271 as part of an ongoing project to make Yautja a more balanced role for what it is. # Explain why it's good for the game Balances out power usage and makes things more dynamic. Will tie in with cloak not using power but being more vulnerable to the methods to force decloak. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: add: Yautja bracers can now be recharged from APCs. remove: Yautja bracers no longer naturally recharge on the colony. /:cl: --------- Co-authored-by: harryob --- code/__DEFINES/misc.dm | 2 + code/modules/cm_preds/yaut_bracers.dm | 29 ++++++- code/modules/power/apc.dm | 120 ++++++++++++++++++-------- 3 files changed, 110 insertions(+), 41 deletions(-) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index bed2ceeced7d..4464a0b16a1d 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -284,6 +284,8 @@ #define COOLDOWN_COMM_CENTRAL 30 SECONDS #define COOLDOWN_COMM_DESTRUCT 5 MINUTES +///Cooldown for pred recharge +#define COOLDOWN_BRACER_CHARGE 3 MINUTES // magic value to use for indicating a proc slept #define PROC_RETURN_SLEEP -1 diff --git a/code/modules/cm_preds/yaut_bracers.dm b/code/modules/cm_preds/yaut_bracers.dm index b526e11d99bb..9642b4b9f5a5 100644 --- a/code/modules/cm_preds/yaut_bracers.dm +++ b/code/modules/cm_preds/yaut_bracers.dm @@ -31,6 +31,10 @@ var/notification_sound = TRUE // Whether the bracer pings when a message comes or not var/charge = 1500 var/charge_max = 1500 + /// The amount charged per process + var/charge_rate = 30 + /// Cooldown on draining power from APC + var/charge_cooldown = COOLDOWN_BRACER_CHARGE var/cloaked = 0 var/cloak_timer = 0 var/cloak_malfunction = 0 @@ -41,6 +45,7 @@ var/mob/living/carbon/human/owner //Pred spawned on, or thrall given to. var/obj/item/clothing/gloves/yautja/linked_bracer //Bracer linked to this one (thrall or mentor). + COOLDOWN_DECLARE(bracer_recharge) /obj/item/clothing/gloves/yautja/equipped(mob/user, slot) . = ..() @@ -75,11 +80,27 @@ if(!ishuman(loc)) STOP_PROCESSING(SSobj, src) return - var/mob/living/carbon/human/H = loc + var/mob/living/carbon/human/human_holder = loc - charge = min(charge + 30, charge_max) - var/perc_charge = (charge / charge_max * 100) - H.update_power_display(perc_charge) + if(charge < charge_max) + var/charge_increase = charge_rate + if(is_ground_level(human_holder.z)) + charge_increase = charge_rate / 6 + else if(is_mainship_level(human_holder.z)) + charge_increase = charge_rate / 3 + + charge = min(charge + charge_increase, charge_max) + var/perc_charge = (charge / charge_max * 100) + human_holder.update_power_display(perc_charge) + + //Non-Yautja have a chance to get stunned with each power drain + if(!cloaked) + return + if(human_holder.stat == DEAD) + decloak(human_holder, TRUE) + if(!HAS_TRAIT(human_holder, TRAIT_YAUTJA_TECH) && !human_holder.hunter_data.thralled && prob(15)) + decloak(human_holder) + shock_user(human_holder) /// handles decloaking only on HUNTER gloves /obj/item/clothing/gloves/yautja/proc/decloak() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 7247e9b87b16..e7a160095705 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -676,9 +676,9 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( var/turf/T = get_turf(src) var/obj/structure/cable/N = T.get_cable_node() if(prob(50) && electrocute_mob(usr, N, N)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(5, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new /datum/effect_system/spark_spread + spark.set_up(5, 1, src) + spark.start() return if(C.use(10)) user.visible_message(SPAN_NOTICE("[user] wires [src]'s frame."), @@ -700,9 +700,9 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( to_chat(user, SPAN_WARNING("\The [src] lacks a terminal to remove.")) return if (prob(50) && electrocute_mob(user, terminal.powernet, terminal)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(5, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new /datum/effect_system/spark_spread + spark.set_up(5, 1, src) + spark.start() return new /obj/item/stack/cable_coil(loc,10) user.visible_message(SPAN_NOTICE("[user] removes [src]'s wiring and terminal."), @@ -798,41 +798,87 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( //Human mob special interaction goes here. if(ishuman(user)) - var/mob/living/carbon/human/H = user + var/mob/living/carbon/human/grabber = user - if(H.species.flags & IS_SYNTHETIC && H.a_intent == INTENT_GRAB) - if(H.action_busy) - return - - if(!do_after(H, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC)) - return + if(grabber.a_intent == INTENT_GRAB) - playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + //Synthpack recharge + if((grabber.species.flags & IS_SYNTHETIC) && istype(grabber.back, /obj/item/storage/backpack/marine/smartpack)) + var/obj/item/storage/backpack/marine/smartpack/s_pack = grabber.back + if(grabber.action_busy) + return - if(stat & BROKEN) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(3, 1, src) - s.start() - to_chat(H, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!")) - H.apply_damage(10,0, BURN) - else if(cell && cell.charge > 0) - if(!istype(H.back, /obj/item/storage/backpack/marine/smartpack)) + if(!do_after(grabber, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC)) return - var/obj/item/storage/backpack/marine/smartpack/S = H.back - if(S.battery_charge < SMARTPACK_MAX_POWER_STORED) - var/charge_to_use = min(cell.charge, SMARTPACK_MAX_POWER_STORED - S.battery_charge) - if(!(cell.use(charge_to_use))) + playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + + if(stat & BROKEN) + var/datum/effect_system/spark_spread/spark = new() + spark.set_up(3, 1, src) + spark.start() + to_chat(grabber, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!")) + grabber.apply_damage(10,0, BURN) + else if(cell && cell.charge > 0) + if(!istype(s_pack)) return - S.battery_charge += charge_to_use - to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. [S.name] now has [S.battery_charge]/[SMARTPACK_MAX_POWER_STORED]")) - charging = APC_CHARGING + + if(s_pack.battery_charge < SMARTPACK_MAX_POWER_STORED) + var/charge_to_use = min(cell.charge, SMARTPACK_MAX_POWER_STORED - s_pack.battery_charge) + if(!(cell.use(charge_to_use))) + return + s_pack.battery_charge += charge_to_use + to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. [s_pack.name] now has [s_pack.battery_charge]/[SMARTPACK_MAX_POWER_STORED]")) + charging = APC_CHARGING + else + to_chat(user, SPAN_WARNING("[s_pack.name] is already fully charged.")) else - to_chat(user, SPAN_WARNING("[S.name] is already fully charged.")) - else - to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) - return - else if(H.species.can_shred(H)) + to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) + return + + // Yautja Bracer Recharge + var/obj/item/clothing/gloves/yautja/bracer = grabber.gloves + if(istype(bracer)) + if(grabber.action_busy) + return FALSE + if(!COOLDOWN_FINISHED(bracer, bracer_recharge)) + to_chat(user, SPAN_WARNING("It is too soon for [bracer.name] to siphon power again. Wait [COOLDOWN_SECONDSLEFT(bracer, bracer_recharge)] seconds.")) + return FALSE + to_chat(user, SPAN_NOTICE("You rest your bracer against the APC interface and begin to siphon off some of the stored energy.")) + if(!do_after(grabber, 20, INTERRUPT_ALL, BUSY_ICON_HOSTILE)) + return FALSE + + if(stat & BROKEN) + var/datum/effect_system/spark_spread/spark = new() + spark.set_up(3, 1, src) + spark.start() + to_chat(grabber, SPAN_DANGER("The APC's power currents surge eratically, super-heating your bracer!")) + playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + grabber.apply_damage(10,0, BURN) + return FALSE + if(!cell || cell.charge <= 0) + to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) + return FALSE + + if(bracer.charge_max <= bracer.charge) + to_chat(user, SPAN_WARNING("[bracer.name] is already fully charged.")) + return FALSE + + var/charge_to_use = min(cell.charge, bracer.charge_max - bracer.charge) + if(!(cell.use(charge_to_use))) + return FALSE + playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + bracer.charge += charge_to_use + COOLDOWN_START(bracer, bracer_recharge, bracer.charge_cooldown) + to_chat(grabber, SPAN_YAUTJABOLD("[icon2html(bracer)] \The [bracer] beep: Power siphon complete. Charge at [bracer.charge]/[bracer.charge_max].")) + if(bracer.notification_sound) + playsound(bracer.loc, 'sound/items/pred_bracer.ogg', 75, 1) + charging = APC_CHARGING + set_broken() // Breaks the APC + + return TRUE + + else if(grabber.species.can_shred(grabber)) var/allcut = TRUE for(var/wire = 1; wire < length(get_wire_descriptions()); wire++) if(!isWireCut(wire)) @@ -1011,9 +1057,9 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( smoke.set_up(1, 0, loc) smoke.attach(src) smoke.start() - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(1, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new() + spark.set_up(1, 1, src) + spark.start() visible_message(SPAN_WARNING("[src] suddenly lets out a blast of smoke and some sparks!")) /obj/structure/machinery/power/apc/surplus()