Refactors shielded hardsuits into a component, fixes kisses consuming shield charges (#57797)

Shielded hardsuits (like the syndie ones) and shielded cult robes, despite functioning very similarly, were actually implemented twice in their own pockets of clothing code. This merges them into one component that lets you block a certain number of attacks while your suit has charges, and have the suit recharge itself after going so long without being hit (optional, cult robes still don't regain lost charges).

This PR also fixes harmless kiss projectiles consuming charges on shielded suits, I'm sure to much disappointment. They'll now pass directly through though, so you can still try your luck to see if love truly conquers all (it probably won't).

One casualty of this is that you can no longer toggle the shield color of syndie hardsuits with a multitool since that it was annoying to componentize, not something that affected gameplay, and probably something noone knew you could do anyway.

Fixes: #57723
This commit is contained in:
Ryll Ryll
2021-04-05 12:50:12 -04:00
committed by GitHub
parent f4a3033e00
commit a54b528dfa
10 changed files with 247 additions and 132 deletions
+1
View File
@@ -709,6 +709,7 @@
#define COMPONENT_BLOCK_MARK_RETRIEVAL (1<<0)
///from base of obj/item/hit_reaction(): (list/args)
#define COMSIG_ITEM_HIT_REACT "item_hit_react"
#define COMPONENT_HIT_REACTION_BLOCK (1<<0)
///called on item when microwaved (): (obj/machinery/microwave/M)
#define COMSIG_ITEM_MICROWAVE_ACT "microwave_act"
#define COMPONENT_SUCCESFUL_MICROWAVE (1<<0)
+1
View File
@@ -78,6 +78,7 @@
#define BELOW_MOB_LAYER 3.7
#define LYING_MOB_LAYER 3.8
//#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define
#define MOB_SHIELD_LAYER 4.01
#define ABOVE_MOB_LAYER 4.1
#define WALL_OBJ_LAYER 4.25
#define EDGED_TURF_LAYER 4.3
+159
View File
@@ -0,0 +1,159 @@
/**
* The shielded component causes the parent item to nullify a certain number of attacks against the wearer, see: shielded hardsuits.
*/
/datum/component/shielded
/// The person currently wearing us
var/mob/living/wearer
/// How many charges we can have max, and how many we start with
var/max_charges
/// How many charges we currently have
var/current_charges
/// How long we have to avoid being hit to replenish charges. If set to 0, we never recharge lost charges
var/recharge_start_delay = 20 SECONDS
/// Once we go unhit long enough to recharge, we replenish charges this often. The floor is effectively 1 second, AKA how often SSdcs processes
var/charge_increment_delay = 1 SECONDS
/// What .dmi we're pulling the shield icon from
var/shield_icon_file = 'icons/effects/effects.dmi'
/// What icon is used when someone has a functional shield up
var/shield_icon = "shield-old"
/// Do we still shield if we're being held in-hand? If FALSE, it needs to be equipped to a slot to work
var/shield_inhand = FALSE
/// The cooldown tracking when we were last hit
COOLDOWN_DECLARE(recently_hit_cd)
/// The cooldown tracking when we last replenished a charge
COOLDOWN_DECLARE(charge_add_cd)
/// A callback for the sparks/message that play when a charge is used, see [/datum/component/shielded/proc/default_run_hit_callback]
var/datum/callback/on_hit_effects
/datum/component/shielded/Initialize(max_charges = 3, recharge_start_delay = 20 SECONDS, charge_increment_delay = 1 SECONDS, shield_icon_file = 'icons/effects/effects.dmi', shield_icon = "shield-old", shield_inhand = FALSE, run_hit_callback)
if(!isitem(parent) || max_charges <= 0)
return COMPONENT_INCOMPATIBLE
src.max_charges = max_charges
src.recharge_start_delay = recharge_start_delay
src.charge_increment_delay = charge_increment_delay
src.shield_icon_file = shield_icon_file
src.shield_icon = shield_icon
src.shield_inhand = shield_inhand
src.on_hit_effects = run_hit_callback || CALLBACK(src, .proc/default_run_hit_callback)
current_charges = max_charges
if(recharge_start_delay)
START_PROCESSING(SSdcs, src)
/datum/component/shielded/Destroy(force, silent)
if(wearer)
shield_icon = "broken"
UnregisterSignal(wearer, COMSIG_ATOM_UPDATE_OVERLAYS)
wearer.update_appearance(UPDATE_ICON)
wearer = null
QDEL_NULL(on_hit_effects)
return ..()
/datum/component/shielded/RegisterWithParent()
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equipped)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/lost_wearer)
RegisterSignal(parent, COMSIG_ITEM_HIT_REACT, .proc/on_hit_react)
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/check_recharge_rune)
/datum/component/shielded/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_ITEM_HIT_REACT, COMSIG_PARENT_ATTACKBY))
// Handle recharging, if we want to
/datum/component/shielded/process(delta_time)
if(current_charges >= max_charges)
STOP_PROCESSING(SSdcs, src)
return
if(!COOLDOWN_FINISHED(src, recently_hit_cd))
return
if(!COOLDOWN_FINISHED(src, charge_add_cd))
return
var/obj/item/item_parent = parent
COOLDOWN_START(src, charge_add_cd, charge_increment_delay)
current_charges++
if(wearer && current_charges == 1)
wearer.update_appearance(UPDATE_ICON)
playsound(item_parent, 'sound/magic/charge.ogg', 50, TRUE)
if(current_charges == max_charges)
playsound(item_parent, 'sound/machines/ding.ogg', 50, TRUE)
/// Check if we've been equipped to a valid slot to shield
/datum/component/shielded/proc/on_equipped(datum/source, mob/user, slot)
SIGNAL_HANDLER
if(slot == ITEM_SLOT_HANDS && !shield_inhand)
lost_wearer(source, user)
return
wearer = user
RegisterSignal(wearer, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/on_update_overlays)
RegisterSignal(wearer, COMSIG_PARENT_QDELETING, .proc/lost_wearer)
if(current_charges)
wearer.update_appearance(UPDATE_ICON)
/// Either we've been dropped or our wearer has been QDEL'd. Either way, they're no longer our problem
/datum/component/shielded/proc/lost_wearer(datum/source, mob/user)
SIGNAL_HANDLER
if(wearer)
UnregisterSignal(wearer, list(COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_PARENT_QDELETING))
wearer.update_appearance(UPDATE_ICON)
wearer = null
/// Used to draw the shield overlay on the wearer
/datum/component/shielded/proc/on_update_overlays(atom/parent_atom, list/overlays)
SIGNAL_HANDLER
overlays += mutable_appearance(shield_icon_file, (current_charges > 0 ? shield_icon : "broken"), MOB_SHIELD_LAYER)
/**
* This proc fires when we're hit, and is responsible for checking if we're charged, then deducting one + returning that we're blocking if so.
* It then runs the callback in [/datum/component/shielded/var/on_hit_effects] which handles the messages/sparks (so the visuals)
*/
/datum/component/shielded/proc/on_hit_react(datum/source, mob/living/carbon/human/owner, atom/movable/hitby, attack_text, final_block_chance, damage, attack_type)
SIGNAL_HANDLER
COOLDOWN_START(src, recently_hit_cd, recharge_start_delay)
if(current_charges <= 0)
return
. = COMPONENT_HIT_REACTION_BLOCK
current_charges = max(current_charges - 1, 0)
INVOKE_ASYNC(src, .proc/actually_run_hit_callback, owner, attack_text, current_charges)
if(!recharge_start_delay) // if recharge_start_delay is 0, we don't recharge
if(!current_charges) // obviously if someone ever adds a manual way to replenish charges, change this
qdel(src)
return
if(!current_charges)
wearer.update_appearance(UPDATE_ICON)
START_PROCESSING(SSdcs, src) // if we DO recharge, start processing so we can do that
/// The wrapper to invoke the on_hit callback, so we don't have to worry about blocking in the signal handler
/datum/component/shielded/proc/actually_run_hit_callback(mob/living/owner, attack_text, current_charges)
on_hit_effects.Invoke(owner, attack_text, current_charges)
/// Default on_hit proc, since cult robes are stupid and have different descriptions/sparks
/datum/component/shielded/proc/default_run_hit_callback(mob/living/owner, attack_text, current_charges)
do_sparks(2, TRUE, owner)
owner.visible_message("<span class='danger'>[owner]'s shields deflect [attack_text] in a shower of sparks!<span>")
if(current_charges <= 0)
owner.visible_message("<span class='warning'>[owner]'s shield overloads!</span>")
/datum/component/shielded/proc/check_recharge_rune(datum/source, obj/item/wizard_armour_charge/recharge_rune, mob/living/user)
SIGNAL_HANDLER
if(!istype(recharge_rune))
return
. = COMPONENT_NO_AFTERATTACK
if(!istype(parent, /obj/item/clothing/suit/space/hardsuit/shielded/wizard))
to_chat(user, "<span class='warning'>The rune can only be used on battlemage armour!</span>")
return
current_charges += recharge_rune.restored_charges
to_chat(user, "<span class='notice'>You charge \the [parent]. It can now absorb [current_charges] hits.</span>")
+4 -3
View File
@@ -451,11 +451,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
// afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, owner, hitby, attack_text, final_block_chance, damage, attack_type)
if(SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, owner, hitby, attack_text, final_block_chance, damage, attack_type) & COMPONENT_HIT_REACTION_BLOCK)
return TRUE
if(prob(final_block_chance))
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")
return 1
return 0
return TRUE
/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language, list/message_mods)
return ITALICS | REDUCE_RANGE
+48 -29
View File
@@ -306,38 +306,57 @@
name = "[name] blown by [firer]"
return ..()
/obj/projectile/kiss/Impact(atom/A)
if(!nodamage || !isliving(A)) // if we do damage or we hit a nonliving thing, we don't have to worry about a harmless hit because we can't wrongly do damage anyway
return ..()
harmless_on_hit(A)
qdel(src)
return FALSE
/**
* To get around shielded hardsuits & such being set off by kisses when they shouldn't, we take a page from hallucination projectiles
* and simply fake our on hit effects. This lets kisses remain incorporeal without having to make some new trait for this one niche situation.
* This fake hit only happens if we can deal damage and if we hit a living thing. Otherwise, we just do normal on hit effects.
*/
/obj/projectile/kiss/proc/harmless_on_hit(mob/living/living_target)
playsound(get_turf(living_target), hitsound, 100, TRUE)
living_target.visible_message("<span class='danger'>[living_target] is hit by \a [src].</span>", "<span class='userdanger'>You're hit by \a [src]!</span>", vision_distance=COMBAT_MESSAGE_RANGE)
try_fluster(living_target)
/obj/projectile/kiss/proc/try_fluster(mob/living/living_target)
// people with the social anxiety quirk can get flustered when hit by a kiss
if(!HAS_TRAIT(living_target, TRAIT_ANXIOUS) || (living_target.stat > SOFT_CRIT))
return
if(HAS_TRAIT(living_target, TRAIT_FEARLESS) || prob(50)) // 50% chance for it to apply, also immune while on meds
return
var/other_msg
var/self_msg
var/roll = rand(1, 3)
switch(roll)
if(1)
other_msg = "stumbles slightly, turning a bright red!"
self_msg = "You lose control of your limbs for a moment as your blood rushes to your face, turning it bright red!"
living_target.add_confusion(rand(5, 10))
if(2)
other_msg = "stammers softly for a moment before choking on something!"
self_msg = "You feel your tongue disappear down your throat as you fight to remember how to make words!"
addtimer(CALLBACK(living_target, /atom/movable.proc/say, pick("Uhhh...", "O-oh, uhm...", "I- uhhhhh??", "You too!!", "What?")), rand(0.5 SECONDS, 1.5 SECONDS))
living_target.stuttering += rand(5, 15)
if(3)
other_msg = "locks up with a stunned look on [living_target.p_their()] face, staring at [firer ? firer : "the ceiling"]!"
self_msg = "Your brain completely fails to process what just happened, leaving you rooted in place staring at [firer ? "[firer]" : "the ceiling"] for what feels like an eternity!"
living_target.face_atom(firer)
living_target.Stun(rand(3 SECONDS, 8 SECONDS))
living_target.visible_message("<b>[living_target]</b> [other_msg]", "<span class='userdanger'>Whoa! [self_msg]<span>")
/obj/projectile/kiss/on_hit(atom/target, blocked, pierce_hit)
def_zone = BODY_ZONE_HEAD // let's keep it PG, people
. = ..()
if(!ismob(target))
return
SEND_SIGNAL(target, COMSIG_ADD_MOOD_EVENT, "kiss", /datum/mood_event/kiss, firer)
var/mob/living/target_living = target
// people with the social anxiety quirk can get flustered when hit by a kiss
if(HAS_TRAIT(target_living, TRAIT_ANXIOUS) && (target_living.stat > SOFT_CRIT))
if(prob(50) || HAS_TRAIT(target_living, TRAIT_FEARLESS)) // 50% chance for it to apply, also immune while on meds
return
var/other_msg
var/self_msg
var/roll = rand(1, 3)
switch(roll)
if(1)
other_msg = "stumbles slightly, turning a bright red!"
self_msg = "You lose control of your limbs for a moment as your blood rushes to your face, turning it bright red!"
target_living.add_confusion(rand(5, 10))
if(2)
other_msg = "stammers softly for a moment before choking on something!"
self_msg = "You feel your tongue disappear down your throat as you fight to remember how to make words!"
addtimer(CALLBACK(target_living, /atom/movable.proc/say, pick("Uhhh...", "O-oh, uhm...", "I- uhhhhh??", "You too!!", "What?")), rand(0.5 SECONDS, 1.5 SECONDS))
target_living.stuttering += rand(5, 15)
if(3)
other_msg = "locks up with a stunned look on [target_living.p_their()] face, staring at [firer ? firer : "the ceiling"]!"
self_msg = "Your brain completely fails to process what just happened, leaving you rooted in place staring [firer ? "at [firer]" : "the ceiling"] for what feels like an eternity!"
target_living.face_atom(firer)
target_living.Stun(rand(3 SECONDS, 8 SECONDS))
target_living.visible_message("<b>[target_living]</b> [other_msg]", "<span class='userdanger'>Whoa! [self_msg]</span>")
if(isliving(target))
try_fluster(target)
/obj/projectile/kiss/death
name = "kiss of death"
+1 -1
View File
@@ -328,7 +328,7 @@
/obj/item/nullrod/staff/worn_overlays(isinhands)
. = list()
if(isinhands)
. += mutable_appearance('icons/effects/effects.dmi', shield_icon, MOB_LAYER + 0.01)
. += mutable_appearance('icons/effects/effects.dmi', shield_icon, MOB_SHIELD_LAYER)
/obj/item/nullrod/staff/blue
name = "blue holy staff"
+12 -17
View File
@@ -420,9 +420,20 @@
inhand_icon_state = "cult_armor"
w_class = WEIGHT_CLASS_BULKY
armor = list(MELEE = 50, BULLET = 40, LASER = 50,ENERGY = 50, BOMB = 50, BIO = 30, RAD = 30, FIRE = 50, ACID = 60)
var/current_charges = 3
hoodtype = /obj/item/clothing/head/hooded/cult_hoodie/cult_shield
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/Initialize()
. = ..()
// note that these charges don't regenerate
AddComponent(/datum/component/shielded, recharge_start_delay = 0, shield_icon_file = 'icons/effects/cult_effects.dmi', shield_icon = "shield-cult", run_hit_callback = CALLBACK(src, .proc/shield_damaged))
/// A proc for callback when the shield breaks, since cult robes are stupid and have different effects
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/proc/shield_damaged(mob/living/wearer, attack_text, new_current_charges)
wearer.visible_message("<span class='danger'>[wearer]'s robes neutralize [attack_text] in a burst of blood-red sparks!</span>")
new /obj/effect/temp_visual/cult/sparks(get_turf(wearer))
if(new_current_charges == 0)
wearer.visible_message("<span class='danger'>The runed shield around [wearer] suddenly disappears!</span>")
/obj/item/clothing/head/hooded/cult_hoodie/cult_shield
name = "empowered cultist helmet"
desc = "Empowered helmet which creates a powerful shield around the user."
@@ -438,22 +449,6 @@
user.Dizzy(30)
user.Paralyze(100)
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(current_charges)
owner.visible_message("<span class='danger'>\The [attack_text] is deflected in a burst of blood-red sparks!</span>")
current_charges--
new /obj/effect/temp_visual/cult/sparks(get_turf(owner))
if(!current_charges)
owner.visible_message("<span class='danger'>The runed shield around [owner] suddenly disappears!</span>")
owner.update_inv_wear_suit()
return TRUE
return FALSE
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/worn_overlays(isinhands)
. = list()
if(!isinhands && current_charges)
. += mutable_appearance('icons/effects/cult_effects.dmi', "shield-cult", MOB_LAYER + 0.01)
/obj/item/clothing/suit/hooded/cultrobes/berserker
name = "flagellant's robes"
desc = "Blood-soaked robes infused with dark magic; allows the user to move at inhuman speeds, but at the cost of increased damage."
+14 -66
View File
@@ -775,50 +775,20 @@
allowed = null
armor = list(MELEE = 30, BULLET = 15, LASER = 30, ENERGY = 40, BOMB = 10, BIO = 100, RAD = 50, FIRE = 100, ACID = 100, WOUND = 15)
resistance_flags = FIRE_PROOF | ACID_PROOF
var/current_charges = 3
var/max_charges = 3 //How many charges total the shielding has
var/recharge_delay = 200 //How long after we've been shot before we can start recharging. 20 seconds here
var/recharge_cooldown = 0 //Time since we've last been shot
var/recharge_rate = 1 //How quickly the shield recharges once it starts charging
var/shield_state = "shield-old"
var/shield_on = "shield-old"
/// How many charges total the shielding has
var/max_charges = 3
/// How long after we've been shot before we can start recharging.
var/recharge_delay = 20 SECONDS
/// How quickly the shield recharges each charge once it starts charging
var/recharge_rate = 1 SECONDS
/// The icon for the shield
var/shield_icon = "shield-old"
/obj/item/clothing/suit/space/hardsuit/shielded/Initialize()
. = ..()
if(!allowed)
allowed = GLOB.advanced_hardsuit_allowed
/obj/item/clothing/suit/space/hardsuit/shielded/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
recharge_cooldown = world.time + recharge_delay
if(current_charges > 0)
var/datum/effect_system/spark_spread/s = new
s.set_up(2, 1, src)
s.start()
owner.visible_message("<span class='danger'>[owner]'s shields deflect [attack_text] in a shower of sparks!</span>")
current_charges--
if(current_charges <= 0)
owner.visible_message("<span class='warning'>[owner]'s shield overloads!</span>")
shield_state = "broken"
owner.update_inv_wear_suit()
return TRUE
return FALSE
/obj/item/clothing/suit/space/hardsuit/shielded/process()
. = ..()
if(recharge_rate && world.time > recharge_cooldown && current_charges < max_charges)
current_charges = clamp((current_charges + recharge_rate), 0, max_charges)
playsound(loc, 'sound/magic/charge.ogg', 50, TRUE)
if(current_charges == max_charges)
playsound(loc, 'sound/machines/ding.ogg', 50, TRUE)
shield_state = "[shield_on]"
if(ishuman(loc))
var/mob/living/carbon/human/C = loc
C.update_inv_wear_suit()
/obj/item/clothing/suit/space/hardsuit/shielded/worn_overlays(isinhands)
. = list()
if(!isinhands)
. += mutable_appearance('icons/effects/effects.dmi', shield_state, MOB_LAYER + 0.01)
AddComponent(/datum/component/shielded, max_charges = max_charges, recharge_start_delay = recharge_delay, charge_increment_delay = recharge_rate, shield_icon = shield_icon)
/obj/item/clothing/head/helmet/space/hardsuit/shielded
resistance_flags = FIRE_PROOF | ACID_PROOF
@@ -843,8 +813,7 @@
inhand_icon_state = "ert_security"
hardsuit_type = "ert_security"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red
shield_state = "shield-red"
shield_on = "shield-red"
shield_icon = "shield-red"
/obj/item/clothing/suit/space/hardsuit/shielded/ctf/blue
name = "blue shielded hardsuit"
@@ -859,8 +828,7 @@
inhand_icon_state = "ert_green"
hardsuit_type = "ert_green"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/green
shield_state = "shield-green"
shield_on = "shield-green"
shield_icon = "shield-green"
/obj/item/clothing/suit/space/hardsuit/shielded/ctf/yellow
name = "yellow shielded hardsuit"
@@ -868,8 +836,7 @@
inhand_icon_state = "ert_engineer"
hardsuit_type = "ert_engineer"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/yellow
shield_state = "shield-yellow"
shield_on = "shield-yellow"
shield_icon = "shield-yellow"
/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf
@@ -917,25 +884,7 @@
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi
slowdown = 0
shield_state = "shield-red"
shield_on = "shield-red"
/obj/item/clothing/suit/space/hardsuit/shielded/syndi/multitool_act(mob/living/user, obj/item/I)
. = ..()
if(shield_state == "broken")
to_chat(user, "<span class='warning'>You can't interface with the hardsuit's software if the shield's broken!</span>")
return
if(shield_state == "shield-red")
shield_state = "shield-old"
shield_on = "shield-old"
to_chat(user, "<span class='warning'>You roll back the hardsuit's software, changing the shield's color!</span>")
else
shield_state = "shield-red"
shield_on = "shield-red"
to_chat(user, "<span class='warning'>You update the hardsuit's hardware, changing back the shield's color to red.</span>")
user.update_inv_wear_suit()
shield_icon = "shield-red"
/obj/item/clothing/suit/space/hardsuit/shielded/syndi/Initialize()
jetpack = new /obj/item/tank/jetpack/suit(src)
@@ -957,8 +906,7 @@
inhand_icon_state = "swat_suit"
hardsuit_type = "syndi"
max_charges = 4
current_charges = 4
recharge_delay = 15
recharge_delay = 1.5 SECONDS
armor = list(MELEE = 80, BULLET = 80, LASER = 50, ENERGY = 60, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100, WOUND = 30)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+6 -16
View File
@@ -187,11 +187,9 @@
desc = "Not all wizards are afraid of getting up close and personal."
icon_state = "battlemage"
inhand_icon_state = "battlemage"
recharge_rate = 0
current_charges = 15
recharge_cooldown = INFINITY
shield_state = "shield-red"
shield_on = "shield-red"
recharge_delay = 0 // no auto-recharge
max_charges = 15
shield_icon = "shield-red"
min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard
@@ -213,19 +211,11 @@
/obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard/attack_self(mob/user)
return
// The actual code for this is handled in the shielded component, see [/datum/component/shielded/proc/check_recharge_rune]
/obj/item/wizard_armour_charge
name = "battlemage shield charges"
desc = "A powerful rune that will increase the number of hits a suit of battlemage armour can take before failing.."
icon = 'icons/effects/effects.dmi'
icon_state = "electricity2"
/obj/item/wizard_armour_charge/afterattack(obj/item/clothing/suit/space/hardsuit/shielded/wizard/W, mob/user, proximity)
. = ..()
if(!proximity)
return
if(!istype(W))
to_chat(user, "<span class='warning'>The rune can only be used on battlemage armour!</span>")
return
W.current_charges += 8
to_chat(user, "<span class='notice'>You charge \the [W]. It can now absorb [W.current_charges] hits.</span>")
qdel(src)
/// How many charges get restored
var/restored_charges = 8
+1
View File
@@ -520,6 +520,7 @@
#include "code\datums\components\remote_materials.dm"
#include "code\datums\components\rot.dm"
#include "code\datums\components\rotation.dm"
#include "code\datums\components\shielded.dm"
#include "code\datums\components\shrink.dm"
#include "code\datums\components\singularity.dm"
#include "code\datums\components\sitcomlaughter.dm"