Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modsuit prep: Replace CTF Hardsuits #10992

Merged
merged 4 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading