Skip to content

Commit

Permalink
Capture The Flag: Class Warfare (tgstation#59629)
Browse files Browse the repository at this point in the history
Co-authored-by: Thunder12345 <stewart@critar.demon.co.uk>
  • Loading branch information
2 people authored and Bytube committed Jul 26, 2021
1 parent d0d3c2f commit ff8fba1
Show file tree
Hide file tree
Showing 25 changed files with 1,066 additions and 587 deletions.
2 changes: 2 additions & 0 deletions code/__DEFINES/dcs/signals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,8 @@
#define COMSIG_MOB_FIRED_GUN "mob_fired_gun"
///called in /obj/item/gun/process_fire (user, target, params, zone_override)
#define COMSIG_GUN_FIRED "gun_fired"
///called in /obj/item/gun/ballistic/process_chamber (casing)
#define COMSIG_CASING_EJECTED "casing_ejected"

// /obj/effect/proc_holder/spell signals

Expand Down
1 change: 1 addition & 0 deletions code/__DEFINES/misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE)))
#define DUMMY_HUMAN_SLOT_PREFERENCES "dummy_preference_preview"
#define DUMMY_HUMAN_SLOT_ADMIN "admintools"
#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
#define DUMMY_HUMAN_SLOT_CTF "dummy_ctf_preview_generation"

#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
//This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
Expand Down
27 changes: 20 additions & 7 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 Down Expand Up @@ -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_appearance(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 Down Expand Up @@ -121,7 +130,13 @@
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/actually_run_hit_callback, owner, attack_text, current_charges)

Expand All @@ -130,8 +145,6 @@
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
Expand Down
21 changes: 21 additions & 0 deletions code/datums/elements/delete_on_drop.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Attaches to an item, if that item is dropped on the floor delete it
*/
/datum/element/delete_on_drop
element_flags = ELEMENT_DETACH
var/list/myvar = list()

/datum/element/delete_on_drop/Attach(datum/target)
. = ..()
if(!isitem(target))
return COMPONENT_INCOMPATIBLE
RegisterSignal(target, list(COMSIG_ITEM_DROPPED, COMSIG_CASING_EJECTED), .proc/del_on_drop)

/datum/element/delete_on_drop/Detach(datum/source)
. = ..()
UnregisterSignal(source, list(COMSIG_ITEM_DROPPED, COMSIG_CASING_EJECTED))

/datum/element/delete_on_drop/proc/del_on_drop(atom/source)
SIGNAL_HANDLER
if(isturf(source.loc))
qdel(source)
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@
/obj/effect/projectile/impact/laser/emitter
name = "emitter impact"
icon_state = "impact_emitter"

/obj/effect/projectile/impact/solar
name = "solar impact"
icon_state = "impact_solar"
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@
/obj/effect/projectile/muzzle/laser/emitter
name = "emitter flash"
icon_state = "muzzle_emitter"

/obj/effect/projectile/muzzle/solar
icon_state = "muzzle_solar"
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
name = "heavy laser"
icon_state = "beam_heavy"

/obj/effect/projectile/tracer/solar
name = "solar beam"
icon_state = "solar"

//BEAM RIFLE
/obj/effect/projectile/tracer/tracer/beam_rifle
icon_state = "tracer_beam"
Expand Down
227 changes: 227 additions & 0 deletions code/modules/capture_the_flag/ctf_classes.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
// GENERIC CLASSES

/datum/outfit/ctf
name = "CTF Rifleman (Solo)"
ears = /obj/item/radio/headset
uniform = /obj/item/clothing/under/syndicate
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf
toggle_helmet = FALSE // see the whites of their eyes
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
id = /obj/item/card/id/away
belt = /obj/item/gun/ballistic/automatic/pistol/deagle/ctf
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf

///Description to be shown in the class selection menu
var/class_description = "General purpose combat class. Armed with a laser rifle and backup pistol."
///Radio frequency to assign players with this outfit
var/team_radio_freq = FREQ_COMMON // they won't be able to use this on the centcom z-level, so ffa players cannot use radio
///Icon file for the class radial menu icons
var/icon = 'icons/hud/radial_ctf.dmi'
///Icon state for this class
var/icon_state = "ctf_rifleman"
///Do they get a headset?
var/has_radio = TRUE
///Do they get an ID?
var/has_card = TRUE
///Which slots to apply TRAIT_NODROP to the items in
var/list/nodrop_slots = list(ITEM_SLOT_OCLOTHING, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_ICLOTHING, ITEM_SLOT_EARS)

/datum/outfit/ctf/post_equip(mob/living/carbon/human/human_to_equip, visualsOnly=FALSE)
if(visualsOnly)
return
var/list/no_drops = list()

if(has_card)
var/obj/item/card/id/idcard = human_to_equip.wear_id
no_drops += idcard
idcard.registered_name = human_to_equip.real_name
idcard.update_label()
idcard.update_icon()

// Make clothing in the specified slots NODROP
for(var/slot in nodrop_slots)
no_drops += human_to_equip.get_item_by_slot(slot)
// Make items in the hands NODROP
for(var/obj/item/held_item in human_to_equip.held_items)
no_drops += held_item
listclearnulls(no_drops) // For any slots we didn't have filled
// Apply TRAIT_NODROP to everything
for(var/obj/item/item_to_nodrop as anything in no_drops)
ADD_TRAIT(item_to_nodrop, TRAIT_NODROP, CAPTURE_THE_FLAG_TRAIT)

if(has_radio)
var/obj/item/radio/headset = human_to_equip.ears
headset.set_frequency(team_radio_freq)
headset.freqlock = TRUE
headset.independent = TRUE
human_to_equip.dna.species.stunmod = 0

/datum/outfit/ctf/instagib
name = "CTF Instagib (Solo)"
r_hand = /obj/item/gun/energy/laser/instakill
shoes = /obj/item/clothing/shoes/jackboots/fast
icon_state = "ctf_instakill"
class_description = "General purpose combat class. Armed with a laser rifle and backup pistol."

/datum/outfit/ctf/assault
name = "CTF Assaulter (Solo)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/light
r_hand = /obj/item/gun/ballistic/shotgun/ctf
gloves = /obj/item/clothing/gloves/tackler/rocket
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun
belt = null
icon_state = "ctf_assaulter"
class_description = "Close combat class. Armed with a shotgun and rocket gloves."

/datum/outfit/ctf/marksman
name = "CTF Marksman (Solo)"
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman
belt = null
icon_state = "ctf_marksman"
class_description = "Long range class. Armed with a hitscan laser rifle."

// RED TEAM CLASSES

/datum/outfit/ctf/red
name = "CTF Rifleman (Red)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/red
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/red
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/rifle/red
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/rifle/red
id = /obj/item/card/id/red //it's red
team_radio_freq = FREQ_CTF_RED

/datum/outfit/ctf/red/instagib
name = "CTF Instagib (Red)"
r_hand = /obj/item/gun/energy/laser/instakill/red
shoes = /obj/item/clothing/shoes/jackboots/fast
team_radio_freq = FREQ_CTF_RED

/datum/outfit/ctf/assault/red
name = "CTF Assaulter (Red)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/light/red
r_hand = /obj/item/gun/ballistic/shotgun/ctf/red
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/red
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/red
id = /obj/item/card/id/red
team_radio_freq = FREQ_CTF_RED

/datum/outfit/ctf/marksman/red
name = "CTF Marksman (Red)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/red
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman/red
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman/red
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman/red
id = /obj/item/card/id/red
team_radio_freq = FREQ_CTF_RED

// BLUE TEAM CLASSES

/datum/outfit/ctf/blue
name = "CTF Rifleman (Blue)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/blue
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/blue
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/rifle/blue
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/rifle/blue
id = /obj/item/card/id/blue //it's blue
team_radio_freq = FREQ_CTF_BLUE

/datum/outfit/ctf/blue/instagib
name = "CTF Instagib (Blue)"
r_hand = /obj/item/gun/energy/laser/instakill/blue
shoes = /obj/item/clothing/shoes/jackboots/fast
team_radio_freq = FREQ_CTF_BLUE

/datum/outfit/ctf/assault/blue
name = "CTF Assaulter (Blue)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/light/blue
r_hand = /obj/item/gun/ballistic/shotgun/ctf/blue
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/blue
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/blue
id = /obj/item/card/id/blue
team_radio_freq = FREQ_CTF_BLUE

/datum/outfit/ctf/marksman/blue
name = "CTF Marksman (Blue)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/blue
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman/blue
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman/blue
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman/blue
id = /obj/item/card/id/blue
team_radio_freq = FREQ_CTF_BLUE

// GREEN TEAM CLASSES

/datum/outfit/ctf/green
name = "CTF Rifleman (Green)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/green
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/green
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/rifle/green
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/rifle/green
id = /obj/item/card/id/green //it's green
team_radio_freq = FREQ_CTF_GREEN

/datum/outfit/ctf/green/instagib
name = "CTF Instagib (Green)"
r_hand = /obj/item/gun/energy/laser/instakill/green
shoes = /obj/item/clothing/shoes/jackboots/fast
team_radio_freq = FREQ_CTF_GREEN

/datum/outfit/ctf/assault/green
name = "CTF Assaulter (Green)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/light/green
r_hand = /obj/item/gun/ballistic/shotgun/ctf/green
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/green
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/green
id = /obj/item/card/id/green
team_radio_freq = FREQ_CTF_GREEN

/datum/outfit/ctf/marksman/green
name = "CTF Marksman (Blue)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/green
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman/green
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman/green
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman/green
id = /obj/item/card/id/green
team_radio_freq = FREQ_CTF_GREEN

// YELLOW TEAM CLASSES

/datum/outfit/ctf/yellow
name = "CTF Rifleman (Yellow)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/yellow
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/yellow
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/rifle/yellow
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/rifle/yellow
id = /obj/item/card/id/yellow //it's yellow
team_radio_freq = FREQ_CTF_YELLOW

/datum/outfit/ctf/yellow/instagib
name = "CTF Instagib (Yellow)"
r_hand = /obj/item/gun/energy/laser/instakill/yellow
shoes = /obj/item/clothing/shoes/jackboots/fast
team_radio_freq = FREQ_CTF_YELLOW

/datum/outfit/ctf/assault/yellow
name = "CTF Assaulter (Yellow)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/light/yellow
r_hand = /obj/item/gun/ballistic/shotgun/ctf/yellow
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/yellow
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/yellow
id = /obj/item/card/id/yellow
team_radio_freq = FREQ_CTF_YELLOW

/datum/outfit/ctf/marksman/yellow
name = "CTF Marksman (Blue)"
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/yellow
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman/yellow
l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman/yellow
r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/marksman/yellow
id = /obj/item/card/id/yellow
team_radio_freq = FREQ_CTF_YELLOW
Loading

0 comments on commit ff8fba1

Please sign in to comment.