Skip to content

Commit

Permalink
Modsuit prep: Replace CTF Hardsuits (#10992)
Browse files Browse the repository at this point in the history
* Replace CTF Hardsuits

* 515
  • Loading branch information
Tsar-Salat authored Jul 30, 2024
1 parent 0c01333 commit 4f6e312
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 95 deletions.
2 changes: 2 additions & 0 deletions code/__DEFINES/colors.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#define COLOR_DARK_RED "#A50824"
#define COLOR_RED_LIGHT "#FF3333"
#define COLOR_MAROON "#800000"
#define COLOR_SECURITY_RED "#CB0000"
#define COLOR_VIVID_RED "#FF3232"

#define COLOR_YELLOW "#FFFF00"
#define COLOR_VIVID_YELLOW "#FBFF23"
Expand Down
59 changes: 36 additions & 23 deletions code/datums/components/shielded.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,32 @@
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
/// How many charges we recover on each charge increment
var/charge_recovery = 1
/// 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
/// Should the shield lose charges equal to the damage dealt by a hit?
var/lose_multiple_charges = 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)
/datum/component/shielded/Initialize(max_charges = 3, recharge_start_delay = 20 SECONDS, charge_increment_delay = 1 SECONDS, charge_recovery = 1, lose_multiple_charges = FALSE, 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.charge_recovery = charge_recovery
src.lose_multiple_charges = lose_multiple_charges
src.shield_icon_file = shield_icon_file
src.shield_icon = shield_icon
src.shield_inhand = shield_inhand
Expand All @@ -46,7 +52,7 @@
if(wearer)
shield_icon = "broken"
UnregisterSignal(wearer, COMSIG_ATOM_UPDATE_OVERLAYS)
wearer.update_icon()
wearer.update_appearance(UPDATE_ICON)
wearer = null
QDEL_NULL(on_hit_effects)
return ..()
Expand All @@ -55,7 +61,7 @@
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped))
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(lost_wearer))
RegisterSignal(parent, COMSIG_ITEM_HIT_REACT, PROC_REF(on_hit_react))
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(check_recharge_item))
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(check_recharge_rune))

/datum/component/shielded/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_ITEM_HIT_REACT, COMSIG_PARENT_ATTACKBY))
Expand All @@ -73,13 +79,16 @@

var/obj/item/item_parent = parent
COOLDOWN_START(src, charge_add_cd, charge_increment_delay)
current_charges++
if(wearer && current_charges == 1)
wearer.update_icon()
adjust_charge(charge_recovery) // set the number of charges to current + recovery per increment, clamped from zero to max_charges
playsound(item_parent, 'sound/magic/charge.ogg', 50, TRUE)
if(current_charges == max_charges)
playsound(item_parent, 'sound/machines/ding.ogg', 50, TRUE)

/datum/component/shielded/proc/adjust_charge(change)
current_charges = clamp(current_charges + change, 0, max_charges)
if(wearer)
wearer.update_appearance(UPDATE_ICON)

/// 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
Expand All @@ -92,15 +101,15 @@
RegisterSignal(wearer, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
RegisterSignal(wearer, COMSIG_PARENT_QDELETING, PROC_REF(lost_wearer))
if(current_charges)
wearer.update_icon()
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_icon()
wearer.update_appearance(UPDATE_ICON)
wearer = null

/// Used to draw the shield overlay on the wearer
Expand All @@ -113,15 +122,21 @@
* 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, damage, attack_type)
/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)

var/charge_loss = 1 // how many charges do we lose

if(lose_multiple_charges) // if the shield has health like damage we'll lose charges equal to the damage of the hit
charge_loss = damage

adjust_charge(-charge_loss)

INVOKE_ASYNC(src, PROC_REF(actually_run_hit_callback), owner, attack_text, current_charges)

Expand All @@ -130,8 +145,6 @@
qdel(src)
return

if(!current_charges)
wearer.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
Expand All @@ -141,20 +154,20 @@
/// 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>")
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_item(datum/source, obj/item/item, mob/living/user)
/datum/component/shielded/proc/check_recharge_rune(datum/source, obj/item/wizard_armour_charge/recharge_rune, mob/living/user)
SIGNAL_HANDLER

if(istype(item, /obj/item/wizard_armour_charge))
. = COMPONENT_NO_AFTERATTACK
var/obj/item/wizard_armour_charge/recharge_rune = item
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
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>")
qdel(recharge_rune)
current_charges += recharge_rune.restored_charges
to_chat(user, "<span class='notice'>You charge \the [parent]. It can now absorb [current_charges] hits.</span>")
qdel(recharge_rune)
20 changes: 20 additions & 0 deletions code/datums/greyscale/greyscale_configs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,23 @@
name = "Plushie Space Lizard"
icon_file = 'icons/obj/plushes.dmi'
json_config = 'code/datums/greyscale/json_configs/plushie_spacelizard.json'

/datum/greyscale_config/ctf_standard
name = "CTF Standard Vest"
icon_file = 'icons/obj/clothing/suits/ctf.dmi'
json_config = 'code/datums/greyscale/json_configs/ctf_standard.json'

/datum/greyscale_config/ctf_standard_worn
name = "Worn CTF Standard Vest"
icon_file = 'icons/mob/clothing/suits/ctf.dmi'
json_config = 'code/datums/greyscale/json_configs/ctf_standard_worn.json'

/datum/greyscale_config/ctf_light
name = "CTF Light Vest"
icon_file = 'icons/obj/clothing/suits/ctf.dmi'
json_config = 'code/datums/greyscale/json_configs/ctf_light.json'

/datum/greyscale_config/ctf_light_worn
name = "Worn CTF Light Vest"
icon_file = 'icons/mob/clothing/suits/ctf.dmi'
json_config = 'code/datums/greyscale/json_configs/ctf_light_worn.json'
15 changes: 15 additions & 0 deletions code/datums/greyscale/json_configs/ctf_light.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"light": [
{
"type": "icon_state",
"icon_state": "light",
"blend_mode": "overlay"
},
{
"type": "icon_state",
"icon_state": "light_colours",
"blend_mode": "overlay",
"color_ids": [ 1 ]
}
]
}
15 changes: 15 additions & 0 deletions code/datums/greyscale/json_configs/ctf_light_worn.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"light": [
{
"type": "icon_state",
"icon_state": "light",
"blend_mode": "overlay"
},
{
"type": "icon_state",
"icon_state": "light_colours",
"blend_mode": "overlay",
"color_ids": [ 1 ]
}
]
}
15 changes: 15 additions & 0 deletions code/datums/greyscale/json_configs/ctf_standard.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"standard": [
{
"type": "icon_state",
"icon_state": "standard",
"blend_mode": "overlay"
},
{
"type": "icon_state",
"icon_state": "standard_colours",
"blend_mode": "overlay",
"color_ids": [ 1 ]
}
]
}
15 changes: 15 additions & 0 deletions code/datums/greyscale/json_configs/ctf_standard_worn.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"standard": [
{
"type": "icon_state",
"icon_state": "standard",
"blend_mode": "overlay"
},
{
"type": "icon_state",
"icon_state": "standard_colours",
"blend_mode": "overlay",
"color_ids": [ 1 ]
}
]
}
6 changes: 2 additions & 4 deletions code/modules/antagonists/cult/cult_items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,8 @@ Striking a noncultist, however, will tear their flesh."}
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/anyone
allow_any = TRUE

/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_REF(shield_damaged)))
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/setup_shielding()
AddComponent(/datum/component/shielded, recharge_start_delay = 0 SECONDS, shield_icon_file = 'icons/effects/cult_effects.dmi', shield_icon = "shield-cult", run_hit_callback = CALLBACK(src, PROC_REF(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)
Expand Down
6 changes: 3 additions & 3 deletions code/modules/awaymissions/capture_the_flag.dm
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@
name = "CTF"
ears = /obj/item/radio/headset
uniform = /obj/item/clothing/under/syndicate
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf
suit = /obj/item/clothing/suit/armor/vest/ctf
toggle_helmet = FALSE // see the whites of their eyes
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
Expand Down Expand Up @@ -601,7 +601,7 @@
shoes = /obj/item/clothing/shoes/jackboots/fast

/datum/outfit/ctf/red
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/red
suit = /obj/item/clothing/suit/armor/vest/ctf/red
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/red
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/red
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/red
Expand All @@ -611,7 +611,7 @@
shoes = /obj/item/clothing/shoes/jackboots/fast

/datum/outfit/ctf/blue
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/blue
suit = /obj/item/clothing/suit/armor/vest/ctf/blue
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/blue
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/blue
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/blue
Expand Down
Loading

0 comments on commit 4f6e312

Please sign in to comment.