diff --git a/_maps/map_files/generic/z2.dmm b/_maps/map_files/generic/z2.dmm
index bb23d7a2261..cb662517f47 100644
--- a/_maps/map_files/generic/z2.dmm
+++ b/_maps/map_files/generic/z2.dmm
@@ -4258,7 +4258,7 @@
/turf/open/floor/engine/cult,
/area/wizard_station)
"nd" = (
-/obj/structure/barricade/security,
+/obj/structure/barricade/security/ctf,
/turf/open/floor/plasteel/circuit,
/area/ctf)
"ne" = (
@@ -4739,7 +4739,7 @@
/turf/open/floor/plasteel/cafeteria,
/area/centcom/holding)
"oE" = (
-/obj/structure/barricade/security,
+/obj/structure/barricade/security/ctf,
/turf/open/floor/plasteel/bluespace,
/area/ctf)
"oF" = (
@@ -5108,7 +5108,7 @@
},
/area/ctf)
"pT" = (
-/obj/structure/barricade/security,
+/obj/structure/barricade/security/ctf,
/turf/open/floor/plasteel/circuit/rcircuit,
/area/ctf)
"pU" = (
@@ -5400,7 +5400,7 @@
},
/area/ctf)
"qP" = (
-/obj/structure/barricade/security,
+/obj/structure/barricade/security/ctf,
/turf/open/floor/plasteel/circuit/gcircuit/off,
/area/ctf)
"qQ" = (
@@ -5408,8 +5408,7 @@
/turf/open/floor/plasteel/red,
/area/ctf)
"qR" = (
-/obj/structure/barricade/security,
-/obj/structure/barricade/security,
+/obj/structure/barricade/security/ctf,
/turf/open/floor/plasteel/circuit/rcircuit,
/area/ctf)
"qS" = (
diff --git a/code/game/gamemodes/handofgod/traps.dm b/code/game/gamemodes/handofgod/traps.dm
index 61eabc661cf..b39475f0ce1 100644
--- a/code/game/gamemodes/handofgod/traps.dm
+++ b/code/game/gamemodes/handofgod/traps.dm
@@ -16,13 +16,13 @@
/obj/structure/divine/trap/Crossed(atom/movable/AM)
if(last_trigger + time_between_triggers > world.time)
return
- alpha = 30
+ alpha = initial(alpha)
if(isliving(AM))
var/mob/living/L = AM
last_trigger = world.time
alpha = 200
trap_effect(L)
- animate(src, alpha = 30, time = time_between_triggers)
+ animate(src, alpha = initial(alpha), time = time_between_triggers)
/obj/structure/divine/trap/examine(mob/user)
@@ -31,7 +31,7 @@
return
user << "You reveal a trap!"
alpha = 200
- animate(src, alpha = 30, time = time_between_triggers)
+ animate(src, alpha = initial(alpha), time = time_between_triggers)
/obj/structure/divine/trap/proc/trap_effect(mob/living/L)
@@ -106,6 +106,4 @@
/obj/structure/divine/trap/ward/New()
..()
- spawn(time_between_triggers)
- if(src)
- qdel(src)
+ QDEL_IN(src, time_between_triggers)
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index e8370cec19d..e3388b227f0 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -36,10 +36,11 @@
damage = 0
health -= damage
if(health <= 0)
- if(debris_type)
- new debris_type(get_turf(src), 3)
+ make_debris()
qdel(src)
+/obj/structure/barricade/proc/make_debris()
+ return
/obj/structure/barricade/attack_animal(mob/living/simple_animal/M)
M.changeNext_move(CLICK_CD_MELEE)
@@ -109,7 +110,9 @@
icon = 'icons/obj/structures.dmi'
icon_state = "woodenbarricade"
material = WOOD
- debris_type = /obj/item/stack/sheet/mineral/wood
+
+/obj/structure/barricade/wooden/make_debris()
+ new /obj/item/stack/sheet/mineral/wood(get_turf(src), 3)
/obj/structure/barricade/sandbags
@@ -121,7 +124,7 @@
maxhealth = 280
proj_pass_rate = 20
pass_flags = LETPASSTHROW
- material = null
+ material = SAND
climbable = TRUE
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/barricade/sandbags, /turf/closed/wall, /turf/closed/wall/r_wall, /obj/structure/falsewall, /obj/structure/falsewall/reinforced, /turf/closed/wall/rust, /turf/closed/wall/r_wall/rust, /obj/structure/barricade/security)
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index a16815225cd..d3f42f00d59 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -4,11 +4,11 @@
icon_state = "x2"
anchored = 1
unacidable = 1
+ invisibility = INVISIBILITY_ABSTRACT
/obj/effect/landmark/New()
..()
tag = text("landmark*[]", name)
- invisibility = INVISIBILITY_ABSTRACT
landmarks_list += src
switch(name) //some of these are probably obsolete
@@ -77,7 +77,6 @@
/obj/effect/landmark/start/New()
..()
tag = "start*[name]"
- invisibility = INVISIBILITY_ABSTRACT
start_landmarks_list += src
return 1
@@ -286,4 +285,4 @@
/obj/effect/landmark/ruin/Destroy()
ruin_landmarks -= src
ruin_template = null
- . = ..()
\ No newline at end of file
+ . = ..()
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index 8335f1258ca..26a284fa0c1 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -568,11 +568,9 @@
if("ctfbutton")
if(!check_rights(R_ADMIN))
return
- var/ctf_enabled = 0
+ var/ctf_enabled = FALSE
for(var/obj/machinery/capture_the_flag/CTF in machines)
- ctf_enabled = !CTF.ctf_enabled
- CTF.ctf_enabled = !CTF.ctf_enabled
- CTF.TellGhost()
+ ctf_enabled = CTF.toggle_ctf()
message_admins("[key_name_admin(usr)] has [ctf_enabled? "enabled" : "disabled"] CTF!")
notify_ghosts("CTF has been [ctf_enabled? "enabled" : "disabled"]!",'sound/effects/ghost2.ogg')
if("masspurrbation")
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index c49caf7c78b..4f5ae87e849 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -22,27 +22,35 @@
flags = HANDSLOW
var/team = WHITE_TEAM
var/reset_cooldown = 0
- var/obj/effect/landmark/reset
+ var/obj/effect/ctf/flag_reset/reset
+ var/reset_path = /obj/effect/ctf/flag_reset
/obj/item/weapon/twohanded/required/ctf/New()
if(!reset)
- reset = new /obj/effect/landmark(get_turf(src))
+ reset = new reset_path(get_turf(src))
+
+/obj/item/weapon/twohanded/required/ctf/Destroy()
+ if(reset)
+ qdel(reset)
+ reset = null
+ . = ..()
/obj/item/weapon/twohanded/required/ctf/initialize()
if(!reset)
- reset = new /obj/effect/landmark(get_turf(src))
+ reset = new reset_path(get_turf(src))
/obj/item/weapon/twohanded/required/ctf/process()
if(world.time > reset_cooldown)
- src.loc = get_turf(src.reset)
+ forceMove(get_turf(src.reset))
for(var/mob/M in player_list)
var/area/mob_area = get_area(M)
if(istype(mob_area, /area/ctf))
- M << "\The [src] has been returned to base!"
+ M << "\The [src] has been returned \
+ to base!"
STOP_PROCESSING(SSobj, src)
/obj/item/weapon/twohanded/required/ctf/attack_hand(mob/living/user)
- if (!user)
+ if(!user)
return
if(team in user.faction)
user << "You can't move your own flag!"
@@ -78,6 +86,7 @@
item_state = "banner-red"
desc = "A red banner, used to play capture the flag."
team = RED_TEAM
+ reset_path = /obj/effect/ctf/flag_reset/red
/obj/item/weapon/twohanded/required/ctf/blue
@@ -86,8 +95,26 @@
item_state = "banner-blue"
desc = "A blue banner, used to play capture the flag."
team = BLUE_TEAM
+ reset_path = /obj/effect/ctf/flag_reset/blue
+/obj/effect/ctf/flag_reset
+ name = "banner landmark"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "banner"
+ desc = "This is where a banner with Nanotrasen's logo on it would go."
+ layer = LOW_ITEM_LAYER
+/obj/effect/ctf/flag_reset/red
+ name = "red flag landmark"
+ icon_state = "banner-red"
+ desc = "This is where a red banner, used to play capture the flag \
+ would go."
+
+/obj/effect/ctf/flag_reset/blue
+ name = "blue flag landmark"
+ icon_state = "banner-blue"
+ desc = "This is where a blue banner, used to play capture the flag \
+ would go."
/obj/machinery/capture_the_flag
name = "CTF Controller"
@@ -107,9 +134,23 @@
var/ctf_enabled = FALSE
var/ctf_gear = /datum/outfit/ctf
var/instagib_gear = /datum/outfit/ctf/instagib
+ var/list/dead_barricades = list()
+
+ var/static/ctf_object_typecache
+ var/static/arena_cleared = FALSE
/obj/machinery/capture_the_flag/New()
..()
+ if(!ctf_object_typecache)
+ ctf_object_typecache = typecacheof(list(
+ /turf,
+ /mob,
+ /area,
+ /obj/machinery,
+ /obj/structure,
+ /obj/effect/ctf,
+ /obj/item/weapon/twohanded/required/ctf
+ ))
poi_list |= src
/obj/machinery/capture_the_flag/Destroy()
@@ -172,10 +213,6 @@
M.faction += team
M.equipOutfit(ctf_gear)
-/obj/machinery/capture_the_flag/proc/TellGhost()
- if(ctf_enabled)
- 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)
-
/obj/machinery/capture_the_flag/Topic(href, href_list)
if(href_list["join"])
var/mob/dead/observer/ghost = usr
@@ -214,9 +251,41 @@
CTF.control_points = 0
CTF.ctf_enabled = FALSE
CTF.team_members = list()
- spawn(300)
- CTF.ctf_enabled = TRUE
+ CTF.arena_cleared = FALSE
+ addtimer(CTF, "start_ctf", 300)
+/obj/machinery/capture_the_flag/proc/toggle_ctf()
+ if(!ctf_enabled)
+ start_ctf()
+ . = TRUE
+ else
+ stop_ctf()
+ . = FALSE
+
+/obj/machinery/capture_the_flag/proc/start_ctf()
+ ctf_enabled = TRUE
+ for(var/obj/effect/ctf/dead_barricade/ded in dead_barricades)
+ ded.respawn()
+ 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)
+
+ if(!arena_cleared)
+ clear_the_arena()
+ arena_cleared = TRUE
+
+/obj/machinery/capture_the_flag/proc/clear_the_arena()
+ var/area/A = get_area(src)
+ for(var/atm in A)
+ if(!is_type_in_typecache(atm, ctf_object_typecache))
+ qdel(atm)
+
+/obj/machinery/capture_the_flag/proc/stop_ctf()
+ ctf_enabled = FALSE
+ var/area/A = get_area(src)
+ for(var/mob/M in mob_list)
+ if((get_area(A) == A) && M.ckey in team_members)
+ M.dust()
+ team_members.Cut()
/obj/machinery/capture_the_flag/proc/instagib_mode()
for(var/obj/machinery/capture_the_flag/CTF in machines)
@@ -243,11 +312,35 @@
ammo_type = /obj/item/ammo_casing/caseless/laser/ctf
/obj/item/ammo_casing/caseless/laser/ctf
- projectile_type = /obj/item/projectile/beam/ctf
+ projectile_type = /obj/item/projectile/beam/ctf
/obj/item/projectile/beam/ctf
damage = 150
+/obj/item/weapon/gun/projectile/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/item/projectile/beam/ctf/red
+
+/obj/item/projectile/beam/ctf/red
+ icon_state = "laser"
+
+/obj/item/weapon/gun/projectile/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/item/projectile/beam/ctf/blue
+
+/obj/item/projectile/beam/ctf/blue
+ icon_state = "bluelaser"
+
/datum/outfit/ctf
name = "CTF"
/obj/item/device/radio/headset
@@ -268,6 +361,7 @@
/datum/outfit/ctf/red
ears = /obj/item/device/radio/headset/syndicate/alt
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/red
+ r_hand = /obj/item/weapon/gun/projectile/automatic/laser/ctf/red
/datum/outfit/ctf/red/instagib
r_hand = /obj/item/weapon/gun/energy/laser/instakill/red
@@ -276,6 +370,7 @@
/datum/outfit/ctf/blue
ears = /obj/item/device/radio/headset/headset_cent/commander
suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf/blue
+ r_hand = /obj/item/weapon/gun/projectile/automatic/laser/ctf/blue
/datum/outfit/ctf/blue/instagib
r_hand = /obj/item/weapon/gun/energy/laser/instakill/blue
@@ -321,8 +416,31 @@
team = BLUE_TEAM
icon_state = "trap-frost"
-/obj/structure/barricade/security/CTF
- health = INFINITY
+/obj/structure/barricade/security/ctf
+ name = "barrier"
+ desc = "A barrier. Provides cover in fire fights."
+
+/obj/structure/barricade/security/ctf/make_debris()
+ new /obj/effect/ctf/dead_barricade(get_turf(src))
+
+/obj/effect/ctf
+ density = FALSE
+ anchored = TRUE
+ invisibility = INVISIBILITY_OBSERVER
+ alpha = 100
+
+/obj/effect/ctf/dead_barricade
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "barrier0"
+
+/obj/effect/ctf/dead_barricade/New()
+ for(var/obj/machinery/capture_the_flag/CTF in machines)
+ CTF.dead_barricades += src
+
+/obj/effect/ctf/dead_barricade/proc/respawn()
+ if(!qdeleted(src))
+ new /obj/structure/barricade/security/ctf(get_turf(src))
+ qdel(src)
//Areas