diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 84a256a78a8..fea07054b5c 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -931,6 +931,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
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 5ace6d01a99..dec2891b2cb 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -398,6 +398,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
diff --git a/code/datums/components/shielded.dm b/code/datums/components/shielded.dm
index 2920bfe34b5..7450c92295e 100644
--- a/code/datums/components/shielded.dm
+++ b/code/datums/components/shielded.dm
@@ -13,12 +13,16 @@
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
@@ -26,13 +30,15 @@
/// 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
@@ -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
@@ -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)
@@ -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
diff --git a/code/datums/elements/delete_on_drop.dm b/code/datums/elements/delete_on_drop.dm
new file mode 100644
index 00000000000..bc4d0fdccf7
--- /dev/null
+++ b/code/datums/elements/delete_on_drop.dm
@@ -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)
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/impact.dm b/code/game/objects/effects/temporary_visuals/projectiles/impact.dm
index 379923bd7f0..c504bb4f7b2 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/impact.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/impact.dm
@@ -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"
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm b/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm
index 35d57e17be8..a26141d80a8 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm
@@ -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"
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
index ab669ca20f6..c0fa093a2fe 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
@@ -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"
diff --git a/code/modules/capture_the_flag/ctf_classes.dm b/code/modules/capture_the_flag/ctf_classes.dm
new file mode 100644
index 00000000000..52ad1af5315
--- /dev/null
+++ b/code/modules/capture_the_flag/ctf_classes.dm
@@ -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
diff --git a/code/modules/capture_the_flag/ctf_equipment.dm b/code/modules/capture_the_flag/ctf_equipment.dm
new file mode 100644
index 00000000000..5cf4ce17846
--- /dev/null
+++ b/code/modules/capture_the_flag/ctf_equipment.dm
@@ -0,0 +1,605 @@
+
+// GENERIC PROJECTILE
+
+/obj/projectile/beam/ctf
+ damage = 0
+ icon_state = "omnilaser"
+
+/obj/projectile/beam/ctf/prehit_pierce(atom/target)
+ if(!is_ctf_target(target))
+ damage = 0
+ return PROJECTILE_PIERCE_NONE /// hey uhhh don't hit anyone behind them
+ . = ..()
+
+/obj/projectile/beam/ctf/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ if(is_ctf_target(target) && blocked == FALSE)
+ if(iscarbon(target))
+ var/mob/living/carbon/target_mob = target
+ target_mob.adjustBruteLoss(150, 0)
+ return BULLET_ACT_HIT
+
+/obj/item/ammo_box/magazine/recharge/ctf
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf
+
+/obj/item/ammo_box/magazine/recharge/ctf/Initialize()
+ . = ..()
+ AddElement(/datum/element/delete_on_drop)
+
+
+/obj/item/ammo_casing/caseless/laser/ctf
+ projectile_type = /obj/projectile/beam/ctf/
+
+/obj/item/ammo_casing/caseless/laser/ctf/Initialize()
+ . = ..()
+ AddElement(/datum/element/delete_on_drop)
+
+// LASER RIFLE
+
+/obj/item/gun/ballistic/automatic/laser/ctf
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/rifle
+ desc = "This looks like it could really hurt in melee."
+ force = 50
+ weapon_weight = WEAPON_HEAVY
+ slot_flags = null
+
+/obj/item/gun/ballistic/automatic/laser/ctf/Initialize()
+ . = ..()
+ AddElement(/datum/element/delete_on_drop)
+
+
+/obj/item/ammo_box/magazine/recharge/ctf/rifle
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/rifle
+
+
+/obj/item/ammo_casing/caseless/laser/ctf/rifle
+ projectile_type = /obj/projectile/beam/ctf/rifle
+
+
+/obj/projectile/beam/ctf/rifle
+ damage = 45
+ light_color = LIGHT_COLOR_BLUE
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+
+// LASER SHOTGUN
+
+/obj/item/gun/ballistic/shotgun/ctf
+ name = "laser shotgun"
+ desc = "This looks like it could really hurt in melee."
+ icon_state = "ctfshotgun"
+ inhand_icon_state = "shotgun_combat"
+ worn_icon_state = "gun"
+ slot_flags = null
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/shotgun
+ empty_indicator = TRUE
+ fire_sound = 'sound/weapons/gun/shotgun/shot_alt.ogg'
+ semi_auto = TRUE
+ internal_magazine = FALSE
+ tac_reloads = TRUE
+
+/obj/item/gun/ballistic/shotgun/ctf/Initialize()
+ . = ..()
+ AddElement(/datum/element/delete_on_drop)
+
+/obj/item/ammo_box/magazine/recharge/ctf/shotgun
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/shotgun
+ max_ammo = 6
+
+
+/obj/item/ammo_casing/caseless/laser/ctf/shotgun
+ projectile_type = /obj/projectile/beam/ctf/shotgun
+ pellets = 6
+ variance = 25
+
+
+/obj/projectile/beam/ctf/shotgun
+ damage = 15
+ light_color = LIGHT_COLOR_BLUE
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+
+// MARKSMAN RIFLE
+
+/obj/item/gun/ballistic/automatic/laser/ctf/marksman
+ name = "designated marksman rifle"
+ icon_state = "ctfmarksman"
+ inhand_icon_state = "ctfmarksman"
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/marksman
+ fire_delay = 1 SECONDS
+
+/obj/item/ammo_box/magazine/recharge/ctf/marksman
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/marksman
+ max_ammo = 10
+
+/obj/item/ammo_casing/caseless/laser/ctf/marksman
+ projectile_type = /obj/projectile/beam/ctf/marksman
+
+/obj/projectile/beam/ctf/marksman
+ damage = 30
+ hitscan = TRUE
+ tracer_type = /obj/effect/projectile/tracer/laser/blue
+ muzzle_type = /obj/effect/projectile/muzzle/laser/blue
+ impact_type = /obj/effect/projectile/impact/laser/blue
+
+// DESERT EAGLE
+
+/obj/item/gun/ballistic/automatic/pistol/deagle/ctf
+ desc = "This looks like it could really hurt in melee."
+ force = 75
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/deagle
+
+/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/Initialize()
+ . = ..()
+ AddElement(/datum/element/delete_on_drop)
+
+
+/obj/item/ammo_box/magazine/recharge/ctf/deagle
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/deagle
+ max_ammo = 7
+
+
+/obj/item/ammo_casing/caseless/laser/ctf/deagle
+ projectile_type = /obj/projectile/beam/ctf/deagle
+
+
+/obj/projectile/beam/ctf/deagle
+ icon_state = "bullet"
+ damage = 60
+ light_color = COLOR_WHITE
+ impact_effect_type = /obj/effect/temp_visual/impact_effect
+
+// INSTAKILL RIFLE
+
+/obj/item/gun/energy/laser/instakill
+ name = "instakill rifle"
+ icon_state = "instagib"
+ inhand_icon_state = "instagib"
+ desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit."
+ w_class = WEIGHT_CLASS_BULKY
+ ammo_type = list(/obj/item/ammo_casing/energy/instakill)
+ force = 60
+ slot_flags = null
+ charge_sections = 5
+ ammo_x_offset = 2
+ shaded_charge = FALSE
+
+/obj/item/gun/energy/laser/instakill/Initialize()
+ . = ..()
+ AddElement(/datum/element/delete_on_drop)
+
+/obj/item/gun/energy/laser/instakill/emp_act() //implying you could stop the instagib
+ return
+
+/obj/item/ammo_casing/energy/instakill
+ projectile_type = /obj/projectile/beam/instakill
+ e_cost = 0
+ select_name = "DESTROY"
+
+/obj/projectile/beam/instakill
+ name = "instagib laser"
+ icon_state = "purple_laser"
+ damage = 200
+ damage_type = BURN
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
+ light_color = LIGHT_COLOR_PURPLE
+
+/obj/projectile/beam/instakill/on_hit(atom/target)
+ . = ..()
+ if(iscarbon(target))
+ var/mob/living/carbon/target_mob = target
+ target_mob.visible_message(span_danger("[target_mob] explodes into a shower of gibs!"))
+ target_mob.gib()
+
+// SHIELDED HARDSUIT
+
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf
+ name = "white shielded hardsuit"
+ desc = "Standard issue hardsuit for playing capture the flag."
+ icon_state = "ert_medical"
+ inhand_icon_state = "ert_medical"
+ hardsuit_type = "ert_medical"
+ // Adding TRAIT_NODROP is done when the CTF spawner equips people
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf
+ armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0) // CTF gear gives no protection outside of the shield
+ allowed = null
+ slowdown = 0
+ max_charges = 150
+ recharge_amount = 30
+ lose_multiple_charges = TRUE
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf
+ name = "shielded hardsuit helmet"
+ desc = "Standard issue hardsuit helmet for playing capture the flag."
+ icon_state = "hardsuit0-ert_medical"
+ inhand_icon_state = "hardsuit0-ert_medical"
+ hardsuit_type = "ert_medical"
+ armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0)
+
+// LIGHT SHIELDED HARDSUIT
+
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/light
+ name = "light white shielded hardsuit"
+ desc = "Lightweight hardsuit for playing capture the flag."
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light
+ max_charges = 30
+ slowdown = -0.25
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light
+ name = "light shielded hardsuit helmet"
+ desc = "Lightweight hardsuit helmet for playing capture the flag."
+
+// RED TEAM GUNS
+
+// Rifle
+/obj/item/gun/ballistic/automatic/laser/ctf/red
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/rifle/red
+
+/obj/item/ammo_box/magazine/recharge/ctf/rifle/red
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/rifle/red
+
+/obj/item/ammo_casing/caseless/laser/ctf/rifle/red
+ projectile_type = /obj/projectile/beam/ctf/rifle/red
+
+/obj/projectile/beam/ctf/rifle/red
+ icon_state = "laser"
+ light_color = COLOR_SOFT_RED
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
+
+
+// Shotgun
+/obj/item/gun/ballistic/shotgun/ctf/red
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/red
+
+/obj/item/ammo_box/magazine/recharge/ctf/shotgun/red
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/shotgun/red
+
+/obj/item/ammo_casing/caseless/laser/ctf/shotgun/red
+ projectile_type = /obj/projectile/beam/ctf/shotgun/red
+
+/obj/projectile/beam/ctf/shotgun/red
+ icon_state = "laser"
+ light_color = COLOR_SOFT_RED
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
+
+
+// DMR
+/obj/item/gun/ballistic/automatic/laser/ctf/marksman/red
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/marksman/red
+
+/obj/item/ammo_box/magazine/recharge/ctf/marksman/red
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/marksman/red
+
+/obj/item/ammo_casing/caseless/laser/ctf/marksman/red
+ projectile_type = /obj/projectile/beam/ctf/marksman/red
+
+/obj/projectile/beam/ctf/marksman/red
+ icon_state = "laser"
+ tracer_type = /obj/effect/projectile/tracer/laser
+ muzzle_type = /obj/effect/projectile/muzzle/laser
+ impact_type = /obj/effect/projectile/impact/laser
+
+
+// Instakill
+/obj/item/gun/energy/laser/instakill/red
+ desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a red design."
+ icon_state = "instagibred"
+ inhand_icon_state = "instagibred"
+ ammo_type = list(/obj/item/ammo_casing/energy/instakill/red)
+
+/obj/item/ammo_casing/energy/instakill/red
+ projectile_type = /obj/projectile/beam/instakill/red
+
+/obj/projectile/beam/instakill/red
+ icon_state = "red_laser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
+ light_color = COLOR_SOFT_RED
+
+// BLUE TEAM GUNS
+
+// Rifle
+/obj/item/gun/ballistic/automatic/laser/ctf/blue
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/rifle/blue
+
+/obj/item/ammo_box/magazine/recharge/ctf/rifle/blue
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/rifle/blue
+
+/obj/item/ammo_casing/caseless/laser/ctf/rifle/blue
+ projectile_type = /obj/projectile/beam/ctf/rifle/blue
+
+/obj/projectile/beam/ctf/rifle/blue
+ icon_state = "bluelaser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+
+// Shotgun
+/obj/item/gun/ballistic/shotgun/ctf/blue
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/blue
+
+/obj/item/ammo_box/magazine/recharge/ctf/shotgun/blue
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/shotgun/blue
+
+/obj/item/ammo_casing/caseless/laser/ctf/shotgun/blue
+ projectile_type = /obj/projectile/beam/ctf/shotgun/blue
+
+/obj/projectile/beam/ctf/shotgun/blue
+ icon_state = "bluelaser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+
+
+// DMR
+/obj/item/gun/ballistic/automatic/laser/ctf/marksman/blue
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/marksman/blue
+
+/obj/item/ammo_box/magazine/recharge/ctf/marksman/blue
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/marksman/blue
+
+/obj/item/ammo_casing/caseless/laser/ctf/marksman/blue
+ projectile_type = /obj/projectile/beam/ctf/marksman/blue
+
+/obj/projectile/beam/ctf/marksman/blue
+
+
+// Instakill
+/obj/item/gun/energy/laser/instakill/blue
+ desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a blue design."
+ icon_state = "instagibblue"
+ inhand_icon_state = "instagibblue"
+ ammo_type = list(/obj/item/ammo_casing/energy/instakill/blue)
+
+/obj/item/ammo_casing/energy/instakill/blue
+ projectile_type = /obj/projectile/beam/instakill/blue
+
+/obj/projectile/beam/instakill/blue
+ icon_state = "blue_laser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+ light_color = LIGHT_COLOR_BLUE
+
+// GREEN TEAM GUNS
+
+// Rifle
+/obj/item/gun/ballistic/automatic/laser/ctf/green
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/rifle/green
+
+/obj/item/ammo_box/magazine/recharge/ctf/rifle/green
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/rifle/green
+
+/obj/item/ammo_casing/caseless/laser/ctf/rifle/green
+ projectile_type = /obj/projectile/beam/ctf/rifle/green
+
+/obj/projectile/beam/ctf/rifle/green
+ icon_state = "xray"
+ light_color = COLOR_VERY_PALE_LIME_GREEN
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
+
+
+// Shotgun
+/obj/item/gun/ballistic/shotgun/ctf/green
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/green
+
+/obj/item/ammo_box/magazine/recharge/ctf/shotgun/green
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/shotgun/green
+
+/obj/item/ammo_casing/caseless/laser/ctf/shotgun/green
+ projectile_type = /obj/projectile/beam/ctf/shotgun/green
+
+/obj/projectile/beam/ctf/shotgun/green
+ icon_state = "xray"
+ light_color = COLOR_VERY_PALE_LIME_GREEN
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
+
+
+// DMR
+/obj/item/gun/ballistic/automatic/laser/ctf/marksman/green
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/marksman/green
+
+/obj/item/ammo_box/magazine/recharge/ctf/marksman/green
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/marksman/green
+
+/obj/item/ammo_casing/caseless/laser/ctf/marksman/green
+ projectile_type = /obj/projectile/beam/ctf/marksman/green
+
+/obj/projectile/beam/ctf/marksman/green
+ icon_state = "xray"
+ tracer_type = /obj/effect/projectile/tracer/xray
+ muzzle_type = /obj/effect/projectile/muzzle/xray
+ impact_type = /obj/effect/projectile/impact/xray
+
+
+// Instakill
+/obj/item/gun/energy/laser/instakill/green
+ desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a green design."
+ icon_state = "instagibgreen"
+ inhand_icon_state = "instagibgreen"
+ ammo_type = list(/obj/item/ammo_casing/energy/instakill/green)
+
+/obj/item/ammo_casing/energy/instakill/green
+ projectile_type = /obj/projectile/beam/instakill/green
+
+/obj/projectile/beam/instakill/green
+ icon_state = "green_laser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
+ light_color = COLOR_VERY_PALE_LIME_GREEN
+
+// YELLOW TEAM GUNS
+
+// Rifle
+/obj/item/gun/ballistic/automatic/laser/ctf/yellow
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/rifle/yellow
+
+/obj/item/ammo_box/magazine/recharge/ctf/rifle/yellow
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/rifle/yellow
+
+/obj/item/ammo_casing/caseless/laser/ctf/rifle/yellow
+ projectile_type = /obj/projectile/beam/ctf/rifle/yellow
+
+/obj/projectile/beam/ctf/rifle/yellow
+ icon_state = "gaussstrong"
+ light_color = COLOR_VERY_SOFT_YELLOW
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/yellow_laser
+
+
+// Shotgun
+/obj/item/gun/ballistic/shotgun/ctf/yellow
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/shotgun/yellow
+
+/obj/item/ammo_box/magazine/recharge/ctf/shotgun/yellow
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/shotgun/yellow
+
+/obj/item/ammo_casing/caseless/laser/ctf/shotgun/yellow
+ projectile_type = /obj/projectile/beam/ctf/shotgun/yellow
+
+/obj/projectile/beam/ctf/shotgun/yellow
+ icon_state = "gaussstrong"
+ light_color = COLOR_VERY_SOFT_YELLOW
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/yellow_laser
+
+
+// DMR
+/obj/item/gun/ballistic/automatic/laser/ctf/marksman/yellow
+ mag_type = /obj/item/ammo_box/magazine/recharge/ctf/marksman/yellow
+
+/obj/item/ammo_box/magazine/recharge/ctf/marksman/yellow
+ ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/marksman/yellow
+
+/obj/item/ammo_casing/caseless/laser/ctf/marksman/yellow
+ projectile_type = /obj/projectile/beam/ctf/marksman/yellow
+
+/obj/projectile/beam/ctf/marksman/yellow
+ icon_state = "gaussstrong"
+ tracer_type = /obj/effect/projectile/tracer/solar
+ muzzle_type = /obj/effect/projectile/muzzle/solar
+ impact_type = /obj/effect/projectile/impact/solar
+
+
+// Instakill
+/obj/item/gun/energy/laser/instakill/yellow
+ desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a yellow design."
+ icon_state = "instagibyellow"
+ inhand_icon_state = "instagibyellow"
+ ammo_type = list(/obj/item/ammo_casing/energy/instakill/yellow)
+
+/obj/item/ammo_casing/energy/instakill/yellow
+ projectile_type = /obj/projectile/beam/instakill/yellow
+
+/obj/projectile/beam/instakill/yellow
+ icon_state = "yellow_laser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/yellow_laser
+ light_color = COLOR_VERY_SOFT_YELLOW
+
+// RED TEAM SUITS
+
+// Regular
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/red
+ name = "red shielded hardsuit"
+ icon_state = "ert_security"
+ inhand_icon_state = "ert_security"
+ hardsuit_type = "ert_security"
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red
+ shield_icon = "shield-red"
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red
+ icon_state = "hardsuit0-ert_security"
+ inhand_icon_state = "hardsuit0-ert_security"
+ hardsuit_type = "ert_security"
+
+// Light
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/light/red
+ name = "light red shielded hardsuit"
+ icon_state = "ert_security"
+ inhand_icon_state = "ert_security"
+ hardsuit_type = "ert_security"
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light/red
+ shield_icon = "shield-red"
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light/red
+ icon_state = "hardsuit0-ert_security"
+ inhand_icon_state = "hardsuit0-ert_security"
+ hardsuit_type = "ert_security"
+
+// BLUE TEAM SUITS
+
+// Regular
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/blue
+ name = "blue shielded hardsuit"
+ icon_state = "ert_command"
+ inhand_icon_state = "ert_command"
+ hardsuit_type = "ert_commander"
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/blue
+ shield_icon = "shield-old"
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/blue
+ icon_state = "hardsuit0-ert_commander"
+ inhand_icon_state = "hardsuit0-ert_commander"
+ hardsuit_type = "ert_commander"
+
+// Light
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/light/blue
+ name = "light blue shielded hardsuit"
+ icon_state = "ert_command"
+ inhand_icon_state = "ert_command"
+ hardsuit_type = "ert_commander"
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light/blue
+ shield_icon = "shield-old"
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light/blue
+ icon_state = "hardsuit0-ert_commander"
+ inhand_icon_state = "hardsuit0-ert_commander"
+ hardsuit_type = "ert_commander"
+
+// GREEN TEAM SUITS
+
+// Regular
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/green
+ name = "green shielded hardsuit"
+ icon_state = "ert_green"
+ inhand_icon_state = "ert_green"
+ hardsuit_type = "ert_green"
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/green
+ shield_icon = "shield-green"
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/green
+ icon_state = "hardsuit0-ert_green"
+ inhand_icon_state = "hardsuit0-ert_green"
+ hardsuit_type = "ert_green"
+
+// Light
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/light/green
+ name = "light green shielded hardsuit"
+ icon_state = "ert_green"
+ inhand_icon_state = "ert_green"
+ hardsuit_type = "ert_green"
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light/green
+ shield_icon = "shield-green"
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light/green
+ icon_state = "hardsuit0-ert_green"
+ inhand_icon_state = "hardsuit0-ert_green"
+ hardsuit_type = "ert_green"
+
+// YELLOW TEAM SUITS
+
+// Regular
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/yellow
+ name = "yellow shielded hardsuit"
+ icon_state = "ert_engineer"
+ inhand_icon_state = "ert_engineer"
+ hardsuit_type = "ert_engineer"
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/yellow
+ shield_icon = "shield-yellow"
+
+// Light
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/yellow
+ icon_state = "hardsuit0-ert_engineer"
+ inhand_icon_state = "hardsuit0-ert_engineer"
+ hardsuit_type = "ert_engineer"
+
+/obj/item/clothing/suit/space/hardsuit/shielded/ctf/light/yellow
+ name = "light yellow shielded hardsuit"
+ icon_state = "ert_engineer"
+ inhand_icon_state = "ert_engineer"
+ hardsuit_type = "ert_engineer"
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light/yellow
+ shield_icon = "shield-yellow"
+
+/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/light/yellow
+ icon_state = "hardsuit0-ert_engineer"
+ inhand_icon_state = "hardsuit0-ert_engineer"
+ hardsuit_type = "ert_engineer"
diff --git a/code/modules/capture_the_flag/capture_the_flag.dm b/code/modules/capture_the_flag/ctf_game.dm
similarity index 68%
rename from code/modules/capture_the_flag/capture_the_flag.dm
rename to code/modules/capture_the_flag/ctf_game.dm
index 9bd0ad23eba..efe67ff08dd 100644
--- a/code/modules/capture_the_flag/capture_the_flag.dm
+++ b/code/modules/capture_the_flag/ctf_game.dm
@@ -43,10 +43,6 @@
reset.flag = src
RegisterSignal(src, COMSIG_PARENT_PREQDELETED, .proc/reset_flag) //just in case CTF has some map hazards (read: chasms).
-/obj/item/ctf/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/two_handed, require_twohands = TRUE)
-
/obj/item/ctf/process()
if(is_ctf_target(loc)) //pickup code calls temporary drops to test things out, we need to make sure the flag doesn't reset from
return PROCESS_KILL
@@ -223,7 +219,7 @@
var/list/recently_dead_ckeys = list()
var/ctf_enabled = FALSE
///assoc list for classes. If there's only one, it'll just equip. Otherwise, it lets you pick which outfit!
- var/list/ctf_gear = list("white" = /datum/outfit/ctf)
+ var/list/ctf_gear = list("Rifleman" = /datum/outfit/ctf, "Assaulter" = /datum/outfit/ctf/assault, "Marksman" = /datum/outfit/ctf/marksman)
var/instagib_gear = /datum/outfit/ctf/instagib
var/ammo_type = /obj/effect/powerup/ammo/ctf
// Fast paced gameplay, no real time for burn infections.
@@ -246,7 +242,7 @@
continue
// Anyone in crit, automatically reap
var/mob/living/living_participant = i
- if(HAS_TRAIT(living_participant, TRAIT_CRITICAL_CONDITION) || living_participant.stat == DEAD)
+ if(HAS_TRAIT(living_participant, TRAIT_CRITICAL_CONDITION) || living_participant.stat == DEAD || !living_participant.client) // If they're critted, dead or no longer in their body, dust them
ctf_dust_old(living_participant)
else
// The changes that you've been hit with no shield but not
@@ -259,7 +255,7 @@
icon_state = "syndbeacon"
team = RED_TEAM
team_span = "redteamradio"
- ctf_gear = list("red" = /datum/outfit/ctf/red)
+ ctf_gear = list("Rifleman" = /datum/outfit/ctf/red, "Assaulter" = /datum/outfit/ctf/assault/red, "Marksman" = /datum/outfit/ctf/marksman/red)
instagib_gear = /datum/outfit/ctf/red/instagib
/obj/machinery/capture_the_flag/blue
@@ -267,7 +263,7 @@
icon_state = "bluebeacon"
team = BLUE_TEAM
team_span = "blueteamradio"
- ctf_gear = list("blue" = /datum/outfit/ctf/blue)
+ ctf_gear = list("Rifleman" = /datum/outfit/ctf/blue, "Assaulter" = /datum/outfit/ctf/assault/blue, "Marksman" = /datum/outfit/ctf/marksman/blue)
instagib_gear = /datum/outfit/ctf/blue/instagib
/obj/machinery/capture_the_flag/green
@@ -275,7 +271,7 @@
icon_state = "greenbeacon"
team = GREEN_TEAM
team_span = "greenteamradio"
- ctf_gear = list("green" = /datum/outfit/ctf/green)
+ ctf_gear = list("Rifleman" = /datum/outfit/ctf/green, "Assaulter" = /datum/outfit/ctf/assault/green, "Marksman" = /datum/outfit/ctf/marksman/green)
instagib_gear = /datum/outfit/ctf/green/instagib
/obj/machinery/capture_the_flag/yellow
@@ -283,7 +279,7 @@
icon_state = "yellowbeacon"
team = YELLOW_TEAM
team_span = "yellowteamradio"
- ctf_gear = list("yellow" = /datum/outfit/ctf/yellow)
+ ctf_gear = list("Rifleman" = /datum/outfit/ctf/yellow, "Assaulter" = /datum/outfit/ctf/assault/yellow, "Marksman" = /datum/outfit/ctf/marksman/yellow)
instagib_gear = /datum/outfit/ctf/yellow/instagib
//ATTACK GHOST IGNORING PARENT RETURN VALUE
@@ -335,11 +331,13 @@
if(CTF.team_members.len < src.team_members.len)
to_chat(user, span_warning("[src.team] has more team members than [CTF.team]! Try joining [CTF.team] team to even things up."))
return
+
var/client/new_team_member = user.client
- if(user.mind && user.mind.current)
- ctf_dust_old(user.mind.current)
+ team_members |= new_team_member.ckey
+ to_chat(user, "You are now a member of [src.team]. Get the enemy flag and bring it back to your team's controller!")
spawn_team_member(new_team_member)
+
//does not add to recently dead, because it dusts and that triggers ctf_qdelled_player
/obj/machinery/capture_the_flag/proc/ctf_dust_old(mob/living/body)
if(isliving(body) && (team in body.faction))
@@ -360,21 +358,28 @@
/obj/machinery/capture_the_flag/proc/spawn_team_member(client/new_team_member)
var/datum/outfit/chosen_class
+
if(ctf_gear.len == 1) //no choices to make
for(var/key in ctf_gear)
chosen_class = ctf_gear[key]
- else if(ctf_gear.len > 3) //a lot of choices, so much that we can't use a basic alert
- var/result = input(new_team_member, "Select a class.", "CTF") as null|anything in sortList(ctf_gear)
- if(!result || !(GLOB.ghost_role_flags & GHOSTROLE_MINIGAME) || (new_team_member.ckey in recently_dead_ckeys) || !isobserver(new_team_member.mob))
- return //picked nothing, admin disabled it, cheating to respawn faster, cheating to respawn... while in game?
- chosen_class = ctf_gear[result]
- else //2-3 choices
- var/list/names_only = assoc_list_strip_value(ctf_gear)
- names_only.len += 1 //create a new null entry so if it's a 2-sized list, names_only[3] is null instead of out of bounds
- var/result = tgui_alert(new_team_member, "Select a class.", "CTF", list(names_only[1], names_only[2], names_only[3]))
- if(!result || !(GLOB.ghost_role_flags & GHOSTROLE_MINIGAME) || (new_team_member.ckey in recently_dead_ckeys) || !isobserver(new_team_member.mob))
- return //picked nothing, admin disabled it, cheating to respawn faster, cheating to respawn... while in game?
- chosen_class = ctf_gear[result]
+
+ else //there's a choice to make, present a radial menu
+ var/list/display_classes = list()
+
+ for(var/key in ctf_gear)
+ var/datum/outfit/ctf/class = ctf_gear[key]
+ var/datum/radial_menu_choice/option = new
+ option.image = image(icon = initial(class.icon), icon_state = initial(class.icon_state))
+ option.info = "[initial(class.class_description)]"
+ display_classes[key] = option
+
+ sortList(display_classes)
+ var/choice = show_radial_menu(new_team_member.mob, src, display_classes, radius = 38)
+ if(!choice || !(GLOB.ghost_role_flags & GHOSTROLE_MINIGAME) || (new_team_member.ckey in recently_dead_ckeys) || !isobserver(new_team_member.mob) || src.ctf_enabled == FALSE || !(new_team_member.ckey in src.team_members))
+ return //picked nothing, admin disabled it, cheating to respawn faster, cheating to respawn... while in game?,
+ //there isn't a game going on any more, you are no longer a member of this team (perhaps a new match already started?)
+ chosen_class = ctf_gear[choice]
+
var/mob/living/carbon/human/M = new /mob/living/carbon/human(get_turf(src))
new_team_member.prefs.copy_to(M)
M.set_species(/datum/species/synth)
@@ -385,7 +390,6 @@
for(var/trait in player_traits)
ADD_TRAIT(M, trait, CAPTURE_THE_FLAG_TRAIT)
spawned_mobs[M] = chosen_class
- team_members |= new_team_member.ckey
return M //used in medisim.dm
/obj/machinery/capture_the_flag/Topic(href, href_list)
@@ -446,7 +450,7 @@
dead_barricades.Cut()
- notify_ghosts("[name] has been activated!", enter_link="(Click to join the [team] team!) or click on the controller directly!", source = src, action=NOTIFY_ATTACK, header = "CTF has been activated")
+ notify_ghosts("[name] has been activated!", source = src, action=NOTIFY_ORBIT, header = "CTF has been activated")
if(!arena_reset)
reset_the_arena()
@@ -497,256 +501,6 @@
CTF.ctf_gear = initial(ctf_gear)
CTF.respawn_cooldown = DEFAULT_RESPAWN
-/obj/item/gun/ballistic/automatic/pistol/deagle/ctf
- desc = "This looks like it could really hurt in melee."
- force = 75
- mag_type = /obj/item/ammo_box/magazine/m50/ctf
-
-/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/dropped()
- . = ..()
- addtimer(CALLBACK(src, .proc/floor_vanish), 1)
-
-/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/proc/floor_vanish()
- if(isturf(loc))
- qdel(src)
-
-/obj/item/ammo_box/magazine/m50/ctf
- ammo_type = /obj/item/ammo_casing/a50/ctf
-
-/obj/item/ammo_casing/a50/ctf
- projectile_type = /obj/projectile/bullet/ctf
-
-/obj/projectile/bullet/ctf
- damage = 0
-
-/obj/projectile/bullet/ctf/prehit_pierce(atom/target)
- if(is_ctf_target(target))
- damage = 60
- return PROJECTILE_PIERCE_NONE /// hey uhh don't hit anyone behind them
- . = ..()
-
-/obj/item/gun/ballistic/automatic/laser/ctf
- mag_type = /obj/item/ammo_box/magazine/recharge/ctf
- desc = "This looks like it could really hurt in melee."
- force = 50
-
-/obj/item/gun/ballistic/automatic/laser/ctf/dropped()
- . = ..()
- addtimer(CALLBACK(src, .proc/floor_vanish), 1)
-
-/obj/item/gun/ballistic/automatic/laser/ctf/proc/floor_vanish()
- if(isturf(loc))
- qdel(src)
-
-/obj/item/ammo_box/magazine/recharge/ctf
- ammo_type = /obj/item/ammo_casing/caseless/laser/ctf
-
-/obj/item/ammo_box/magazine/recharge/ctf/dropped()
- . = ..()
- addtimer(CALLBACK(src, .proc/floor_vanish), 1)
-
-/obj/item/ammo_box/magazine/recharge/ctf/proc/floor_vanish()
- if(isturf(loc))
- qdel(src)
-
-/obj/item/ammo_casing/caseless/laser/ctf
- projectile_type = /obj/projectile/beam/ctf
-
-/obj/projectile/beam/ctf
- damage = 0
- icon_state = "omnilaser"
-
-/obj/projectile/beam/ctf/prehit_pierce(atom/target)
- if(is_ctf_target(target))
- damage = 150
- return PROJECTILE_PIERCE_NONE /// hey uhhh don't hit anyone behind them
- . = ..()
-
-/proc/is_ctf_target(atom/target)
- . = FALSE
- if(istype(target, /obj/structure/barricade/security/ctf))
- . = TRUE
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- for(var/obj/machinery/capture_the_flag/CTF in GLOB.machines)
- if(H in CTF.spawned_mobs)
- . = TRUE
- break
-
-// RED TEAM GUNS
-
-/obj/item/gun/ballistic/automatic/laser/ctf/red
- mag_type = /obj/item/ammo_box/magazine/recharge/ctf/red
-
-/obj/item/ammo_box/magazine/recharge/ctf/red
- ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/red
-
-/obj/item/ammo_casing/caseless/laser/ctf/red
- projectile_type = /obj/projectile/beam/ctf/red
-
-/obj/projectile/beam/ctf/red
- icon_state = "laser"
- impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
-
-// BLUE TEAM GUNS
-
-/obj/item/gun/ballistic/automatic/laser/ctf/blue
- mag_type = /obj/item/ammo_box/magazine/recharge/ctf/blue
-
-/obj/item/ammo_box/magazine/recharge/ctf/blue
- ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/blue
-
-/obj/item/ammo_casing/caseless/laser/ctf/blue
- projectile_type = /obj/projectile/beam/ctf/blue
-
-/obj/projectile/beam/ctf/blue
- icon_state = "bluelaser"
- impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
-
-// GREEN TEAM GUNS
-
-/obj/item/gun/ballistic/automatic/laser/ctf/green
- mag_type = /obj/item/ammo_box/magazine/recharge/ctf/green
-
-/obj/item/ammo_box/magazine/recharge/ctf/green
- ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/green
-
-/obj/item/ammo_casing/caseless/laser/ctf/green
- projectile_type = /obj/projectile/beam/ctf/green
-
-/obj/projectile/beam/ctf/green
- icon_state = "xray"
- impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
-
-// YELLOW TEAM GUNS
-
-/obj/item/gun/ballistic/automatic/laser/ctf/yellow
- mag_type = /obj/item/ammo_box/magazine/recharge/ctf/yellow
-
-/obj/item/ammo_box/magazine/recharge/ctf/yellow
- ammo_type = /obj/item/ammo_casing/caseless/laser/ctf/yellow
-
-/obj/item/ammo_casing/caseless/laser/ctf/yellow
- projectile_type = /obj/projectile/beam/ctf/yellow
-
-/obj/projectile/beam/ctf/yellow
- icon_state = "gaussstrong"
- impact_effect_type = /obj/effect/temp_visual/impact_effect/yellow_laser
-
-/datum/outfit/ctf
- name = "CTF"
- 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
-
-/datum/outfit/ctf/post_equip(mob/living/carbon/human/H, visualsOnly=FALSE)
- if(visualsOnly)
- return
- var/list/no_drops = list()
- var/obj/item/card/id/W = H.wear_id
- no_drops += W
- W.registered_name = H.real_name
- W.update_label()
- W.update_icon()
-
- no_drops += H.get_item_by_slot(ITEM_SLOT_OCLOTHING)
- no_drops += H.get_item_by_slot(ITEM_SLOT_GLOVES)
- no_drops += H.get_item_by_slot(ITEM_SLOT_FEET)
- no_drops += H.get_item_by_slot(ITEM_SLOT_ICLOTHING)
- no_drops += H.get_item_by_slot(ITEM_SLOT_EARS)
- for(var/i in no_drops)
- var/obj/item/I = i
- ADD_TRAIT(I, TRAIT_NODROP, CAPTURE_THE_FLAG_TRAIT)
-
-/datum/outfit/ctf/instagib
- r_hand = /obj/item/gun/energy/laser/instakill
- shoes = /obj/item/clothing/shoes/jackboots/fast
-
-/datum/outfit/ctf/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/red
- r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/red
- id = /obj/item/card/id/red //it's red
-
-/datum/outfit/ctf/red/instagib
- r_hand = /obj/item/gun/energy/laser/instakill/red
- shoes = /obj/item/clothing/shoes/jackboots/fast
-
-/datum/outfit/ctf/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/blue
- r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/blue
- id = /obj/item/card/id/blue //it's blue
-
-/datum/outfit/ctf/blue/instagib
- r_hand = /obj/item/gun/energy/laser/instakill/blue
- shoes = /obj/item/clothing/shoes/jackboots/fast
-
-/datum/outfit/ctf/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/green
- r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/green
- id = /obj/item/card/id/green //it's green
-
-/datum/outfit/ctf/green/instagib
- r_hand = /obj/item/gun/energy/laser/instakill/green
- shoes = /obj/item/clothing/shoes/jackboots/fast
-
-/datum/outfit/ctf/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/yellow
- r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/yellow
- id = /obj/item/card/id/yellow //it's yellow
-
-/datum/outfit/ctf/yellow/instagib
- r_hand = /obj/item/gun/energy/laser/instakill/yellow
- shoes = /obj/item/clothing/shoes/jackboots/fast
-
-/datum/outfit/ctf/red/post_equip(mob/living/carbon/human/H)
- ..()
- var/obj/item/radio/R = H.ears
- R.set_frequency(FREQ_CTF_RED)
- R.freqlock = TRUE
- R.independent = TRUE
- H.dna.species.stunmod = 0
-
-/datum/outfit/ctf/blue/post_equip(mob/living/carbon/human/H)
- ..()
- var/obj/item/radio/R = H.ears
- R.set_frequency(FREQ_CTF_BLUE)
- R.freqlock = TRUE
- R.independent = TRUE
- H.dna.species.stunmod = 0
-
-/datum/outfit/ctf/green/post_equip(mob/living/carbon/human/H)
- ..()
- var/obj/item/radio/R = H.ears
- R.set_frequency(FREQ_CTF_GREEN)
- R.freqlock = TRUE
- R.independent = TRUE
- H.dna.species.stunmod = 0
-
-/datum/outfit/ctf/yellow/post_equip(mob/living/carbon/human/H)
- ..()
- var/obj/item/radio/R = H.ears
- R.set_frequency(FREQ_CTF_YELLOW)
- R.freqlock = TRUE
- R.independent = TRUE
- H.dna.species.stunmod = 0
-
-
/obj/structure/trap/ctf
name = "Spawn protection"
desc = "Stay outta the enemy spawn!"
@@ -869,6 +623,17 @@
to_chat(M, span_userdanger("[user.real_name] has captured \the [src], claiming it for [CTF.team]! Go take it back!"))
break
+/proc/is_ctf_target(atom/target)
+ . = FALSE
+ if(istype(target, /obj/structure/barricade/security/ctf))
+ . = TRUE
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ for(var/obj/machinery/capture_the_flag/CTF in GLOB.machines)
+ if(H in CTF.spawned_mobs)
+ . = TRUE
+ break
+
#undef WHITE_TEAM
#undef RED_TEAM
#undef BLUE_TEAM
diff --git a/code/modules/capture_the_flag/map_loading.dm b/code/modules/capture_the_flag/ctf_map_loading.dm
similarity index 100%
rename from code/modules/capture_the_flag/map_loading.dm
rename to code/modules/capture_the_flag/ctf_map_loading.dm
diff --git a/code/modules/capture_the_flag/medieval_sim/medisim_classes.dm b/code/modules/capture_the_flag/medieval_sim/medisim_classes.dm
new file mode 100644
index 00000000000..3361b2e0626
--- /dev/null
+++ b/code/modules/capture_the_flag/medieval_sim/medisim_classes.dm
@@ -0,0 +1,50 @@
+/datum/outfit/ctf/medisim
+ name = "Redfield Castle Knight"
+ icon_state = "medisim_knight"
+
+ uniform = /obj/item/clothing/under/color/red
+ shoes = /obj/item/clothing/shoes/plate/red
+ suit = /obj/item/clothing/suit/armor/riot/knight/red
+ gloves = /obj/item/clothing/gloves/plate/red
+ head = /obj/item/clothing/head/helmet/knight/red
+ r_hand = /obj/item/claymore
+
+ ears = null
+ id = null
+ belt = null
+ l_pocket = null
+ r_pocket = null
+
+ has_radio = FALSE
+ has_card = FALSE
+
+ nodrop_slots = list(ITEM_SLOT_OCLOTHING, ITEM_SLOT_GLOVES, ITEM_SLOT_FEET, ITEM_SLOT_ICLOTHING, ITEM_SLOT_EARS, ITEM_SLOT_BELT, ITEM_SLOT_HEAD)
+
+ class_description = "Melee class. Armed with a claymore."
+
+/datum/outfit/ctf/medisim/archer
+ name = "Redfield Castle Archer"
+ icon_state = "medisim_archer"
+
+ belt = /obj/item/storage/bag/quiver
+ suit = /obj/item/clothing/suit/armor/vest/cuirass
+ r_hand = /obj/item/gun/ballistic/bow
+
+ class_description = "Ranged class. Armed with a bow and arrows."
+
+/datum/outfit/ctf/medisim/blue
+ name = "Bluesworth Hold Knight"
+
+ uniform = /obj/item/clothing/under/color/blue
+ shoes = /obj/item/clothing/shoes/plate/blue
+ suit = /obj/item/clothing/suit/armor/riot/knight/blue
+ gloves = /obj/item/clothing/gloves/plate/blue
+ head = /obj/item/clothing/head/helmet/knight/blue
+
+/datum/outfit/ctf/medisim/archer/blue
+ name = "Bluesworth Hold Archer"
+
+ uniform = /obj/item/clothing/under/color/blue
+ shoes = /obj/item/clothing/shoes/plate/blue
+ gloves = /obj/item/clothing/gloves/plate/blue
+ head = /obj/item/clothing/head/helmet/knight/blue
diff --git a/code/modules/capture_the_flag/medieval_sim/medisim_game.dm b/code/modules/capture_the_flag/medieval_sim/medisim_game.dm
new file mode 100644
index 00000000000..8b9215dd8b6
--- /dev/null
+++ b/code/modules/capture_the_flag/medieval_sim/medisim_game.dm
@@ -0,0 +1,74 @@
+///These are for the medisim shuttle
+
+#define REDFIELD_TEAM "Red"
+#define BLUESWORTH_TEAM "Blue"
+
+/obj/machinery/capture_the_flag/medisim
+ game_id = "medieval"
+ game_area = /area/shuttle/escape/simulation
+ ammo_type = null //no guns, no need
+ victory_rejoin_text = "Teams have been cleared. The next game is starting automatically. Rejoin a team if you wish!"
+ player_traits = list()
+
+/obj/machinery/capture_the_flag/medisim/Initialize(mapload)
+ . = ..()
+ start_ctf() //both machines initialize, so both will call start_ctf instead of toggle_id_ctf calling it for both, twice.
+
+/obj/machinery/capture_the_flag/medisim/victory()
+ . = ..()
+ toggle_id_ctf(null, game_id, automated = TRUE)//only one machine runs the victory proc, start_ctf proc would break the other machine
+
+/obj/machinery/capture_the_flag/medisim/spawn_team_member(client/new_team_member)
+ . = ..()
+ if(!.)
+ return
+ var/mob/living/carbon/human/human_knight = .
+ randomize_human(human_knight)
+ human_knight.dna.update_dna_identity()
+ human_knight.dna.add_mutation(MEDIEVAL, MUT_OTHER)
+ var/oldname = human_knight.name
+ var/title = "error"
+ switch (human_knight.gender)
+ if (MALE)
+ title = pick(list("Sir", "Lord"))
+ if (FEMALE)
+ title = pick(list("Dame", "Lady"))
+ else
+ title = "Noble"
+ human_knight.real_name = "[title] [oldname]"
+ human_knight.name = human_knight.real_name
+
+/obj/machinery/capture_the_flag/medisim/red
+ name = "\improper Redfield Data Realizer"
+ icon_state = "syndbeacon"
+ team = REDFIELD_TEAM
+ team_span = "redteamradio"
+ ctf_gear = list("knight" = /datum/outfit/ctf/medisim, "archer" = /datum/outfit/ctf/medisim/archer)
+
+/obj/machinery/capture_the_flag/medisim/blue
+ name = "\improper Bluesworth Data Realizer"
+ icon_state = "bluebeacon"
+ team = BLUESWORTH_TEAM
+ team_span = "blueteamradio"
+ ctf_gear = list("knight" = /datum/outfit/ctf/medisim/blue, "archer" = /datum/outfit/ctf/medisim/archer/blue)
+
+/obj/item/ctf/red/medisim
+ name = "\improper Redfield Castle Fair Maiden"
+ desc = "Protect your maiden, and capture theirs!"
+ icon = 'icons/obj/plushes.dmi'
+ icon_state = "plushie_nuke"
+ force = 0
+ game_area = /area/shuttle/escape
+ movement_type = FLOATING //there are chasms, and resetting when they fall in is really lame so lets minimize that
+
+/obj/item/ctf/blue/medisim
+ name = "\improper Bluesworth Hold Fair Maiden"
+ desc = "Protect your maiden, and capture theirs!"
+ icon = 'icons/obj/plushes.dmi'
+ icon_state = "plushie_slime"
+ force = 0
+ game_area = /area/shuttle/escape
+ movement_type = FLOATING //there are chasms, and resetting when they fall in is really lame so lets minimize that
+
+#undef REDFIELD_TEAM
+#undef BLUESWORTH_TEAM
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 022812aaefc..1357f6fcf7d 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -784,6 +784,10 @@
var/recharge_delay = 20 SECONDS
/// How quickly the shield recharges each charge once it starts charging
var/recharge_rate = 1 SECONDS
+ /// How many charges are recovered on each recharge
+ var/recharge_amount = 1
+ /// Should the shield lose charges equal to the damage dealt by a hit?
+ var/lose_multiple_charges = FALSE
/// The icon for the shield
var/shield_icon = "shield-old"
@@ -791,92 +795,12 @@
. = ..()
if(!allowed)
allowed = GLOB.advanced_hardsuit_allowed
- AddComponent(/datum/component/shielded, max_charges = max_charges, recharge_start_delay = recharge_delay, charge_increment_delay = recharge_rate, shield_icon = shield_icon)
+ AddComponent(/datum/component/shielded, max_charges = max_charges, recharge_start_delay = recharge_delay, charge_increment_delay = recharge_rate, charge_recovery = recharge_amount, lose_multiple_charges = lose_multiple_charges, shield_icon = shield_icon)
/obj/item/clothing/head/helmet/space/hardsuit/shielded
resistance_flags = FIRE_PROOF | ACID_PROOF
-///////////////Capture the Flag////////////////////
-
-/obj/item/clothing/suit/space/hardsuit/shielded/ctf
- name = "white shielded hardsuit"
- desc = "Standard issue hardsuit for playing capture the flag."
- icon_state = "ert_medical"
- inhand_icon_state = "ert_medical"
- hardsuit_type = "ert_medical"
- // Adding TRAIT_NODROP is done when the CTF spawner equips people
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf
- armor = list(MELEE = 0, BULLET = 30, LASER = 30, ENERGY = 40, BOMB = 50, BIO = 100, RAD = 100, FIRE = 95, ACID = 95)
- slowdown = 0
- max_charges = 5
-
-/obj/item/clothing/suit/space/hardsuit/shielded/ctf/red
- name = "red shielded hardsuit"
- icon_state = "ert_security"
- inhand_icon_state = "ert_security"
- hardsuit_type = "ert_security"
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red
- shield_icon = "shield-red"
-
-/obj/item/clothing/suit/space/hardsuit/shielded/ctf/blue
- name = "blue shielded hardsuit"
- desc = "Standard issue hardsuit for playing capture the flag."
- icon_state = "ert_command"
- inhand_icon_state = "ert_command"
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/blue
-
-/obj/item/clothing/suit/space/hardsuit/shielded/ctf/green
- name = "green shielded hardsuit"
- icon_state = "ert_green"
- inhand_icon_state = "ert_green"
- hardsuit_type = "ert_green"
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/green
- shield_icon = "shield-green"
-
-/obj/item/clothing/suit/space/hardsuit/shielded/ctf/yellow
- name = "yellow shielded hardsuit"
- icon_state = "ert_engineer"
- inhand_icon_state = "ert_engineer"
- hardsuit_type = "ert_engineer"
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/yellow
- shield_icon = "shield-yellow"
-
-
-/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf
- name = "shielded hardsuit helmet"
- desc = "Standard issue hardsuit helmet for playing capture the flag."
- icon_state = "hardsuit0-ert_medical"
- inhand_icon_state = "hardsuit0-ert_medical"
- hardsuit_type = "ert_medical"
- armor = list(MELEE = 0, BULLET = 30, LASER = 30, ENERGY = 40, BOMB = 50, BIO = 100, RAD = 100, FIRE = 95, ACID = 95)
-
-
-/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red
- icon_state = "hardsuit0-ert_security"
- inhand_icon_state = "hardsuit0-ert_security"
- hardsuit_type = "ert_security"
-
-/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/blue
- name = "shielded hardsuit helmet"
- desc = "Standard issue hardsuit helmet for playing capture the flag."
- icon_state = "hardsuit0-ert_commander"
- inhand_icon_state = "hardsuit0-ert_commander"
- hardsuit_type = "ert_commander"
-
-/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/green
- icon_state = "hardsuit0-ert_green"
- inhand_icon_state = "hardsuit0-ert_green"
- hardsuit_type = "ert_green"
-
-/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/yellow
- icon_state = "hardsuit0-ert_engineer"
- inhand_icon_state = "hardsuit0-ert_engineer"
- hardsuit_type = "ert_engineer"
-
-
-
//////Syndicate Version
-
/obj/item/clothing/suit/space/hardsuit/shielded/syndi
name = "blood-red hardsuit"
desc = "An advanced hardsuit with built in energy shielding."
diff --git a/code/modules/projectiles/ammunition/energy/special.dm b/code/modules/projectiles/ammunition/energy/special.dm
index 908ff5cbc75..6f3ddb5fd86 100644
--- a/code/modules/projectiles/ammunition/energy/special.dm
+++ b/code/modules/projectiles/ammunition/energy/special.dm
@@ -58,23 +58,6 @@
select_name = "snare"
harmful = FALSE
-/obj/item/ammo_casing/energy/instakill
- projectile_type = /obj/projectile/beam/instakill
- e_cost = 0
- select_name = "DESTROY"
-
-/obj/item/ammo_casing/energy/instakill/blue
- projectile_type = /obj/projectile/beam/instakill/blue
-
-/obj/item/ammo_casing/energy/instakill/red
- projectile_type = /obj/projectile/beam/instakill/red
-
-/obj/item/ammo_casing/energy/instakill/green
- projectile_type = /obj/projectile/beam/instakill/green
-
-/obj/item/ammo_casing/energy/instakill/yellow
- projectile_type = /obj/projectile/beam/instakill/yellow
-
/obj/item/ammo_casing/energy/tesla_cannon
fire_sound = 'sound/magic/lightningshock.ogg'
e_cost = 30
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index 163e39a0cbc..3ca48f81890 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -218,6 +218,7 @@
if(casing_ejector || !from_firing)
AC.forceMove(drop_location()) //Eject casing onto ground.
AC.bounce_away(TRUE)
+ SEND_SIGNAL(AC, COMSIG_CASING_EJECTED)
chambered = null
else if(empty_chamber)
chambered = null
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index 51a0f40ca8c..be8700dda0e 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -395,6 +395,7 @@
w_class = WEIGHT_CLASS_BULKY
inhand_icon_state = "arg"
mag_type = /obj/item/ammo_box/magazine/recharge
+ empty_indicator = TRUE
fire_delay = 2
can_suppress = FALSE
burst_size = 0
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index 54a411e7a5d..1a0a3efc2f3 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -323,45 +323,6 @@
desc = "A weapon that can only be used to its full potential by the truly robust."
pin = /obj/item/firing_pin
-/obj/item/gun/energy/laser/instakill
- name = "instakill rifle"
- icon_state = "instagib"
- inhand_icon_state = "instagib"
- desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit."
- w_class = WEIGHT_CLASS_BULKY
- ammo_type = list(/obj/item/ammo_casing/energy/instakill)
- force = 60
- charge_sections = 5
- ammo_x_offset = 2
- shaded_charge = FALSE
-
-/obj/item/gun/energy/laser/instakill/red
- desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a red design."
- icon_state = "instagibred"
- inhand_icon_state = "instagibred"
- ammo_type = list(/obj/item/ammo_casing/energy/instakill/red)
-
-/obj/item/gun/energy/laser/instakill/blue
- desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a blue design."
- icon_state = "instagibblue"
- inhand_icon_state = "instagibblue"
- ammo_type = list(/obj/item/ammo_casing/energy/instakill/blue)
-
-/obj/item/gun/energy/laser/instakill/green
- desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a green design."
- icon_state = "instagibgreen"
- inhand_icon_state = "instagibgreen"
- ammo_type = list(/obj/item/ammo_casing/energy/instakill/green)
-
-/obj/item/gun/energy/laser/instakill/yellow
- desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a yellow design."
- icon_state = "instagibyellow"
- inhand_icon_state = "instagibyellow"
- ammo_type = list(/obj/item/ammo_casing/energy/instakill/yellow)
-
-/obj/item/gun/energy/laser/instakill/emp_act() //implying you could stop the instagib
- return
-
/obj/item/gun/energy/gravity_gun
name = "one-point gravitational manipulator"
desc = "An experimental, multi-mode device that fires bolts of Zero-Point Energy, causing local distortions in gravity. Requires a gravitational anomaly core to function."
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index d846833a5da..e60cc243bd3 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -202,41 +202,6 @@
/obj/projectile/beam/lasertag/bluetag/hitscan
hitscan = TRUE
-/obj/projectile/beam/instakill
- name = "instagib laser"
- icon_state = "purple_laser"
- damage = 200
- damage_type = BURN
- impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
- light_color = LIGHT_COLOR_PURPLE
-
-/obj/projectile/beam/instakill/blue
- icon_state = "blue_laser"
- impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
- light_color = LIGHT_COLOR_BLUE
-
-/obj/projectile/beam/instakill/red
- icon_state = "red_laser"
- impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
- light_color = COLOR_SOFT_RED
-
-/obj/projectile/beam/instakill/green
- icon_state = "green_laser"
- impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
- light_color = COLOR_VERY_PALE_LIME_GREEN
-
-/obj/projectile/beam/instakill/yellow
- icon_state = "yellow_laser"
- impact_effect_type = /obj/effect/temp_visual/impact_effect/yellow_laser
- light_color = COLOR_VERY_SOFT_YELLOW
-
-/obj/projectile/beam/instakill/on_hit(atom/target)
- . = ..()
- if(iscarbon(target))
- var/mob/living/carbon/M = target
- M.visible_message(span_danger("[M] explodes into a shower of gibs!"))
- M.gib()
-
//a shrink ray that shrinks stuff, which grows back after a short while.
/obj/projectile/beam/shrink
name = "shrink ray"
diff --git a/code/modules/shuttle/medisim.dm b/code/modules/shuttle/medisim.dm
index d51297a786d..77cbf52a9af 100644
--- a/code/modules/shuttle/medisim.dm
+++ b/code/modules/shuttle/medisim.dm
@@ -1,132 +1,5 @@
///These are for the medisim shuttle
-#define REDFIELD_TEAM "Red"
-#define BLUESWORTH_TEAM "Blue"
-
-/obj/machinery/capture_the_flag/medisim
- game_id = "medieval"
- game_area = /area/shuttle/escape/simulation
- ammo_type = null //no guns, no need
- victory_rejoin_text = "Teams have been cleared. The next game is starting automatically. Rejoin a team if you wish!"
-
-/obj/machinery/capture_the_flag/medisim/Initialize(mapload)
- . = ..()
- // Ensure that the historical simulation is extra bloody.
- player_traits -= TRAIT_NEVER_WOUNDED
-
- start_ctf() //both machines initialize, so both will call start_ctf instead of toggle_id_ctf calling it for both, twice.
-
-/obj/machinery/capture_the_flag/medisim/victory()
- . = ..()
- toggle_id_ctf(null, game_id, automated = TRUE)//only one machine runs the victory proc, start_ctf proc would break the other machine
-
-/obj/machinery/capture_the_flag/medisim/spawn_team_member(client/new_team_member)
- . = ..()
- if(!.)
- return
- var/mob/living/carbon/human/human_knight = .
- randomize_human(human_knight)
- human_knight.dna.update_dna_identity()
- human_knight.dna.add_mutation(MEDIEVAL, MUT_OTHER)
- var/oldname = human_knight.name
- var/title = "error"
- switch (human_knight.gender)
- if (MALE)
- title = pick(list("Sir", "Lord"))
- if (FEMALE)
- title = pick(list("Dame", "Lady"))
- else
- title = "Noble"
- human_knight.real_name = "[title] [oldname]"
- human_knight.name = human_knight.real_name
-
-/obj/machinery/capture_the_flag/medisim/red
- name = "\improper Redfield Data Realizer"
- icon_state = "syndbeacon"
- team = REDFIELD_TEAM
- team_span = "redteamradio"
- ctf_gear = list("knight" = /datum/outfit/medisim/red_knight, "archer" = /datum/outfit/medisim/red_archer)
-
-/obj/machinery/capture_the_flag/medisim/blue
- name = "\improper Bluesworth Data Realizer"
- icon_state = "bluebeacon"
- team = BLUESWORTH_TEAM
- team_span = "blueteamradio"
- ctf_gear = list("knight" = /datum/outfit/medisim/blue_knight, "archer" = /datum/outfit/medisim/blue_archer)
-
-/obj/item/ctf/red/medisim
- name = "\improper Redfield Castle Fair Maiden"
- desc = "Protect your maiden, and capture theirs!"
- icon = 'icons/obj/plushes.dmi'
- icon_state = "plushie_nuke"
- game_area = /area/shuttle/escape
- movement_type = FLOATING //there are chasms, and resetting when they fall in is really lame so lets minimize that
-
-/obj/item/ctf/blue/medisim
- name = "\improper Bluesworth Hold Fair Maiden"
- desc = "Protect your maiden, and capture theirs!"
- icon = 'icons/obj/plushes.dmi'
- icon_state = "plushie_slime"
- game_area = /area/shuttle/escape
- movement_type = FLOATING //there are chasms, and resetting when they fall in is really lame so lets minimize that
-
-//everything except arrows
-/datum/outfit/medisim/post_equip(mob/living/carbon/human/H, visualsOnly)
- var/list/no_drops = list()
- no_drops += H.get_item_by_slot(ITEM_SLOT_FEET)
- no_drops += H.get_item_by_slot(ITEM_SLOT_BELT)
- no_drops += H.get_item_by_slot(ITEM_SLOT_ICLOTHING)
- no_drops += H.get_item_by_slot(ITEM_SLOT_OCLOTHING)
- no_drops += H.get_item_by_slot(ITEM_SLOT_HEAD)
- no_drops += H.get_item_by_slot(ITEM_SLOT_HANDS)
- no_drops += H.get_item_by_slot(ITEM_SLOT_GLOVES)
- listclearnulls(no_drops) //any slots we didn't have
- for(var/_outfit_item in no_drops)
- var/obj/item/outfit_item = _outfit_item
- outfit_item.item_flags |= DROPDEL//so this all stays clean :)
-
-/datum/outfit/medisim/red_knight
- name = "Redfield Castle Knight"
-
- uniform = /obj/item/clothing/under/color/red
- shoes = /obj/item/clothing/shoes/plate/red
- suit = /obj/item/clothing/suit/armor/riot/knight/red
- gloves = /obj/item/clothing/gloves/plate/red
- head = /obj/item/clothing/head/helmet/knight/red
- r_hand = /obj/item/claymore
-
-/datum/outfit/medisim/blue_knight
- name = "Bluesworth Hold Knight"
-
- uniform = /obj/item/clothing/under/color/blue
- shoes = /obj/item/clothing/shoes/plate/blue
- suit = /obj/item/clothing/suit/armor/riot/knight/blue
- gloves = /obj/item/clothing/gloves/plate/blue
- head = /obj/item/clothing/head/helmet/knight/blue
- r_hand = /obj/item/claymore
-
-/datum/outfit/medisim/red_archer
- name = "Redfield Castle Archer"
-
- uniform = /obj/item/clothing/under/color/red
- belt = /obj/item/storage/bag/quiver
- shoes = /obj/item/clothing/shoes/plate/red
- suit = /obj/item/clothing/suit/armor/vest/cuirass
- gloves = /obj/item/clothing/gloves/plate/red
- head = /obj/item/clothing/head/helmet/knight/red
- r_hand = /obj/item/gun/ballistic/bow
-
-/datum/outfit/medisim/blue_archer
- name = "Bluesworth Hold Archer"
-
- uniform = /obj/item/clothing/under/color/blue
- belt = /obj/item/storage/bag/quiver
- shoes = /obj/item/clothing/shoes/plate/blue
- suit = /obj/item/clothing/suit/armor/vest/cuirass
- gloves = /obj/item/clothing/gloves/plate/blue
- head = /obj/item/clothing/head/helmet/knight/blue
- r_hand = /obj/item/gun/ballistic/bow
-
/obj/machinery/computer/reality_simulation
name = "reality simulation computer"
desc = "A computer calculating the medieval times. Uh, wow. Is this bad boy quantum?"
@@ -143,6 +16,3 @@
the rest of the page is filled with various doodles of people fighting with swords."}
-
-#undef REDFIELD_TEAM
-#undef BLUESWORTH_TEAM
diff --git a/icons/hud/radial_ctf.dmi b/icons/hud/radial_ctf.dmi
new file mode 100644
index 00000000000..9fd9a741a56
Binary files /dev/null and b/icons/hud/radial_ctf.dmi differ
diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi
index 34611cbeb16..98316b40a46 100644
Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi
index 98313a39d28..02c03f721bc 100644
Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ
diff --git a/icons/obj/guns/ballistic.dmi b/icons/obj/guns/ballistic.dmi
index 3cfad7ed030..62479e6c25b 100644
Binary files a/icons/obj/guns/ballistic.dmi and b/icons/obj/guns/ballistic.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index c417e55417f..80b850bbe30 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -741,6 +741,7 @@
#include "code\datums\elements\curse_announcement.dm"
#include "code\datums\elements\cursed.dm"
#include "code\datums\elements\deferred_aquarium_content.dm"
+#include "code\datums\elements\delete_on_drop.dm"
#include "code\datums\elements\digitalcamo.dm"
#include "code\datums\elements\drag_pickup.dm"
#include "code\datums\elements\dryable.dm"
@@ -1981,8 +1982,12 @@
#include "code\modules\buildmode\submodes\smite.dm"
#include "code\modules\buildmode\submodes\throwing.dm"
#include "code\modules\buildmode\submodes\variable_edit.dm"
-#include "code\modules\capture_the_flag\capture_the_flag.dm"
-#include "code\modules\capture_the_flag\map_loading.dm"
+#include "code\modules\capture_the_flag\ctf_classes.dm"
+#include "code\modules\capture_the_flag\ctf_equipment.dm"
+#include "code\modules\capture_the_flag\ctf_game.dm"
+#include "code\modules\capture_the_flag\ctf_map_loading.dm"
+#include "code\modules\capture_the_flag\medieval_sim\medisim_classes.dm"
+#include "code\modules\capture_the_flag\medieval_sim\medisim_game.dm"
#include "code\modules\cargo\bounty.dm"
#include "code\modules\cargo\centcom_podlauncher.dm"
#include "code\modules\cargo\coupon.dm"