Capture The Flag: Skill Issue (#72960)

## About The Pull Request

QoL update for CTF to make the experience better and smoother.

## Why It's Good For The Game

The CTF experience is a bit unpolished in some areas such as important
information (shield charge, control point score) being obscured,
mandatory hand switching on spawning, and players messing with their
team by blocking the controller.

## Changelog
🆑
qol: CTF guns spawn in the default active hand
qol: CTF shields become transparent as they lose charge
qol: CTF King of the Hill scores are visible to players in-game
qol: CTF controllers can no longer be blocked by players standing on
them
/🆑
This commit is contained in:
Thunder12345
2023-02-07 15:41:44 -08:00
committed by GitHub
parent d8077e6b11
commit c87cc44e04
10 changed files with 83 additions and 50 deletions
+3
View File
@@ -21,6 +21,9 @@
/// Simply removes the < and > characters, and limits the length of the message.
#define STRIP_HTML_SIMPLE(text, limit) (GLOB.angular_brackets.Replace(copytext(text, 1, limit), ""))
/// Removes everything enclose in < and > inclusive of the bracket, and limits the length of the message.
#define STRIP_HTML_FULL(text, limit) (GLOB.html_tags.Replace(copytext(text, 1, limit), ""))
/// Folder directory for strings
#define STRING_DIRECTORY "strings"
+5
View File
@@ -44,6 +44,11 @@
return sanitize(STRIP_HTML_SIMPLE(text, limit))
/// Runs STRIP_HTML_FULL and sanitize.
/proc/strip_html_full(text, limit = MAX_MESSAGE_LEN)
return sanitize(STRIP_HTML_FULL(text, limit))
/// Runs STRIP_HTML_SIMPLE and byond's sanitization proc.
/proc/adminscrub(text, limit = MAX_MESSAGE_LEN)
return html_encode(STRIP_HTML_SIMPLE(text, limit))
+3
View File
@@ -13,6 +13,9 @@ GLOBAL_DATUM_INIT(has_discord_embeddable_links, /regex, regex("(https?://\[^\\s|
//All < and > characters
GLOBAL_DATUM_INIT(angular_brackets, /regex, regex(@"[<>]", "g"))
//All characters between < a > inclusive of the bracket
GLOBAL_DATUM_INIT(html_tags, /regex, regex(@"<.*?>", "g"))
//All characters forbidden by filenames: ", \, \n, \t, /, ?, %, *, :, |, <, >, ..
GLOBAL_DATUM_INIT(filename_forbidden_chars, /regex, regex(@{""|[\\\n\t/?%*:|<>]|\.\."}, "g"))
GLOBAL_PROTECT(filename_forbidden_chars)
+8 -2
View File
@@ -23,6 +23,8 @@
var/shield_inhand = FALSE
/// Should the shield lose charges equal to the damage dealt by a hit?
var/lose_multiple_charges = FALSE
/// Should the shield's alpha change to show its remaining charge
var/show_charge_as_alpha = FALSE
/// The item we use for recharging
var/recharge_path
/// The cooldown tracking when we were last hit
@@ -32,7 +34,7 @@
/// 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, charge_recovery = 1, lose_multiple_charges = FALSE, recharge_path = null, starting_charges = null, 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, show_charge_as_alpha = FALSE, recharge_path = null, starting_charges = null, 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
@@ -41,6 +43,7 @@
src.charge_increment_delay = charge_increment_delay
src.charge_recovery = charge_recovery
src.lose_multiple_charges = lose_multiple_charges
src.show_charge_as_alpha = show_charge_as_alpha
src.recharge_path = recharge_path
src.shield_icon_file = shield_icon_file
src.shield_icon = shield_icon
@@ -132,7 +135,10 @@
/datum/component/shielded/proc/on_update_overlays(atom/parent_atom, list/overlays)
SIGNAL_HANDLER
overlays += mutable_appearance(shield_icon_file, (current_charges > 0 ? shield_icon : "broken"), MOB_SHIELD_LAYER)
var/mutable_appearance/shield_appearance = mutable_appearance(shield_icon_file, (current_charges > 0 ? shield_icon : "broken"), MOB_SHIELD_LAYER)
if(show_charge_as_alpha)
shield_appearance.alpha = (current_charges/max_charges)*255
overlays += shield_appearance
/**
* This proc fires when we're hit, and is responsible for checking if we're charged, then deducting one + returning that we're blocking if so.
+5 -9
View File
@@ -54,16 +54,12 @@
viewer_client?.images += balloon_alert
var/duration_mult = 1
var/duration_length = length(text) - BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN
if(duration_length > 0)
duration_mult += duration_length*BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT
var/length_mult = 1 + max(0, length(strip_html_full(text)) - BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN) * BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT
animate(
balloon_alert,
pixel_y = world.icon_size * 1.2,
time = BALLOON_TEXT_TOTAL_LIFETIME(1),
time = BALLOON_TEXT_TOTAL_LIFETIME(length_mult),
easing = SINE_EASING | EASE_OUT,
)
@@ -76,7 +72,7 @@
animate(
alpha = 0,
time = BALLOON_TEXT_FULLY_VISIBLE_TIME*duration_mult,
time = BALLOON_TEXT_FULLY_VISIBLE_TIME * length_mult,
easing = CUBIC_EASING | EASE_IN,
)
@@ -84,8 +80,8 @@
// These two timers are not the same
// One manages the relation to the atom that spawned us, the other to the client we're displaying to
// We could lose our loc, and still need to talk to our client, so they are done seperately
addtimer(CALLBACK(balloon_alert.loc, PROC_REF(forget_balloon_alert), balloon_alert), BALLOON_TEXT_TOTAL_LIFETIME(duration_mult))
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(remove_image_from_client), balloon_alert, viewer_client), BALLOON_TEXT_TOTAL_LIFETIME(duration_mult))
addtimer(CALLBACK(balloon_alert.loc, PROC_REF(forget_balloon_alert), balloon_alert), BALLOON_TEXT_TOTAL_LIFETIME(length_mult))
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(remove_image_from_client), balloon_alert, viewer_client), BALLOON_TEXT_TOTAL_LIFETIME(length_mult))
/atom/proc/forget_balloon_alert(image/balloon_alert)
LAZYREMOVE(update_on_z, balloon_alert)
+20 -20
View File
@@ -11,7 +11,7 @@
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
l_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."
@@ -60,7 +60,7 @@
/datum/outfit/ctf/instagib
name = "CTF Instagib (Solo)"
r_hand = /obj/item/gun/energy/laser/instakill/ctf
l_hand = /obj/item/gun/energy/laser/instakill/ctf
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."
@@ -68,7 +68,7 @@
/datum/outfit/ctf/assault
name = "CTF Assaulter (Solo)"
suit = /obj/item/clothing/suit/armor/vest/ctf/light
r_hand = /obj/item/gun/ballistic/shotgun/ctf
l_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
@@ -78,7 +78,7 @@
/datum/outfit/ctf/marksman
name = "CTF Marksman (Solo)"
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman
l_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
@@ -90,7 +90,7 @@
/datum/outfit/ctf/red
name = "CTF Rifleman (Red)"
suit = /obj/item/clothing/suit/armor/vest/ctf/red
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/red
l_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
@@ -98,14 +98,14 @@
/datum/outfit/ctf/red/instagib
name = "CTF Instagib (Red)"
r_hand = /obj/item/gun/energy/laser/instakill/ctf/red
l_hand = /obj/item/gun/energy/laser/instakill/ctf/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/armor/vest/ctf/light/red
r_hand = /obj/item/gun/ballistic/shotgun/ctf/red
l_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
@@ -114,7 +114,7 @@
/datum/outfit/ctf/marksman/red
name = "CTF Marksman (Red)"
suit = /obj/item/clothing/suit/armor/vest/ctf/red
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman/red
l_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
@@ -125,7 +125,7 @@
/datum/outfit/ctf/blue
name = "CTF Rifleman (Blue)"
suit = /obj/item/clothing/suit/armor/vest/ctf/blue
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/blue
l_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
@@ -133,14 +133,14 @@
/datum/outfit/ctf/blue/instagib
name = "CTF Instagib (Blue)"
r_hand = /obj/item/gun/energy/laser/instakill/ctf/blue
l_hand = /obj/item/gun/energy/laser/instakill/ctf/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/armor/vest/ctf/light/blue
r_hand = /obj/item/gun/ballistic/shotgun/ctf/blue
l_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
@@ -149,7 +149,7 @@
/datum/outfit/ctf/marksman/blue
name = "CTF Marksman (Blue)"
suit = /obj/item/clothing/suit/armor/vest/ctf/blue
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman/blue
l_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
@@ -160,7 +160,7 @@
/datum/outfit/ctf/green
name = "CTF Rifleman (Green)"
suit = /obj/item/clothing/suit/armor/vest/ctf/green
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/green
l_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
@@ -168,14 +168,14 @@
/datum/outfit/ctf/green/instagib
name = "CTF Instagib (Green)"
r_hand = /obj/item/gun/energy/laser/instakill/ctf/green
l_hand = /obj/item/gun/energy/laser/instakill/ctf/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/armor/vest/ctf/light/green
r_hand = /obj/item/gun/ballistic/shotgun/ctf/green
l_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
@@ -184,7 +184,7 @@
/datum/outfit/ctf/marksman/green
name = "CTF Marksman (Green)"
suit = /obj/item/clothing/suit/armor/vest/ctf/green
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman/green
l_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
@@ -195,7 +195,7 @@
/datum/outfit/ctf/yellow
name = "CTF Rifleman (Yellow)"
suit = /obj/item/clothing/suit/armor/vest/ctf/yellow
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/yellow
l_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
@@ -203,14 +203,14 @@
/datum/outfit/ctf/yellow/instagib
name = "CTF Instagib (Yellow)"
r_hand = /obj/item/gun/energy/laser/instakill/ctf/yellow
l_hand = /obj/item/gun/energy/laser/instakill/ctf/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/armor/vest/ctf/light/yellow
r_hand = /obj/item/gun/ballistic/shotgun/ctf/yellow
l_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
@@ -219,7 +219,7 @@
/datum/outfit/ctf/marksman/yellow
name = "CTF Marksman (Yellow)"
suit = /obj/item/clothing/suit/armor/vest/ctf/yellow
r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/marksman/yellow
l_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
+13 -4
View File
@@ -206,9 +206,19 @@
///Icon state to be fed into the shielded component
var/team_shield_icon = "shield-old"
var/max_charges = 150
var/recharge_start_delay = 20 SECONDS
var/charge_increment_delay = 1 SECONDS
var/charge_recovery = 30
var/lose_multiple_charges = TRUE
var/show_charge_as_alpha = TRUE
/obj/item/clothing/suit/armor/vest/ctf/setup_shielding()
AddComponent(/datum/component/shielded, max_charges = 150, recharge_start_delay = 20 SECONDS, charge_increment_delay = 1 SECONDS, charge_recovery = 30, lose_multiple_charges = TRUE, shield_icon = team_shield_icon)
/obj/item/clothing/suit/armor/vest/ctf/equipped(mob/user, slot)
. = ..()
if(!slot || slot & ITEM_SLOT_HANDS)
return
AddComponent(/datum/component/shielded, max_charges = max_charges, recharge_start_delay = recharge_start_delay, charge_increment_delay = charge_increment_delay, \
charge_recovery = charge_recovery, lose_multiple_charges = lose_multiple_charges, show_charge_as_alpha = show_charge_as_alpha, shield_icon = team_shield_icon)
// LIGHT SHIELDED VEST
@@ -220,8 +230,7 @@
greyscale_config_worn = /datum/greyscale_config/ctf_light_worn
slowdown = -0.25
/obj/item/clothing/suit/armor/vest/ctf/light/setup_shielding()
AddComponent(/datum/component/shielded, max_charges = 30, recharge_start_delay = 20 SECONDS, charge_increment_delay = 1 SECONDS, charge_recovery = 30, lose_multiple_charges = TRUE, shield_icon = team_shield_icon)
max_charges = 30
// RED TEAM GUNS
+18 -7
View File
@@ -240,6 +240,7 @@
desc = "Used for running friendly games of capture the flag."
icon = 'icons/obj/device.dmi'
icon_state = "syndbeacon"
density = TRUE
resistance_flags = INDESTRUCTIBLE
var/game_id = CTF_GHOST_CTF_GAME_ID
@@ -377,7 +378,7 @@
var/client/new_team_member = user.client
team_members |= new_team_member.ckey
to_chat(user, "<span class='warning'>You are now a member of [src.team]. Get the enemy flag and bring it back to your team's controller!</span>")
to_chat(user, "<span class='userdanger'>You are now a member of [src.team]. Get the enemy flag and bring it back to your team's controller!</span>")
spawn_team_member(new_team_member)
@@ -423,7 +424,8 @@
//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))
var/turf/spawn_point = pick(get_adjacent_open_turfs(get_turf(src)))
var/mob/living/carbon/human/M = new /mob/living/carbon/human(spawn_point)
new_team_member.prefs.safe_transfer_prefs_to(M, is_antag = TRUE)
if(M.dna.species.outfit_important_for_life)
M.set_species(/datum/species/human)
@@ -640,6 +642,15 @@
if(controlling.control_points >= controlling.control_points_to_win)
controlling.victory()
var/scores
for(var/obj/machinery/capture_the_flag/team as anything in GLOB.ctf_panel.ctf_machines)
if (!team.ctf_enabled)
continue
scores += UNLINT("<span style='color: [team.team]'>[team.team] - [team.control_points]/[team.control_points_to_win]</span>\n")
balloon_alert_to_viewers(scores)
/obj/machinery/control_point/attackby(mob/user, params)
capture(user)
@@ -651,14 +662,14 @@
/obj/machinery/control_point/proc/capture(mob/user)
if(do_after(user, 30, target = src))
for(var/obj/machinery/capture_the_flag/CTF as anything in GLOB.ctf_panel.ctf_machines)
if(CTF.ctf_enabled && (user.ckey in CTF.team_members))
controlling = CTF
icon_state = "dominator-[CTF.team]"
for(var/obj/machinery/capture_the_flag/team as anything in GLOB.ctf_panel.ctf_machines)
if(team.ctf_enabled && (user.ckey in team.team_members))
controlling = team
icon_state = "dominator-[team.team]"
for(var/mob/M in GLOB.player_list)
var/area/mob_area = get_area(M)
if(istype(mob_area, game_area))
to_chat(M, span_userdanger("[user.real_name] has captured \the [src], claiming it for [CTF.team]! Go take it back!"))
to_chat(M, "<span class='userdanger [team.team_span]'>[user.real_name] has captured \the [src], claiming it for [team.team]! Go take it back!</span>")
break
/proc/is_ctf_target(atom/target)
@@ -371,19 +371,19 @@ em {
}
.redteamradio {
color: #ff4444;
color: #ff4444 !important;
}
.blueteamradio {
color: #3434fd;
color: #3434fd !important;
}
.greenteamradio {
color: #34fd34;
color: #34fd34 !important;
}
.yellowteamradio {
color: #fdfd34;
color: #fdfd34 !important;
}
.yell {
@@ -388,19 +388,19 @@ em {
}
.redteamradio {
color: #ff0000;
color: #ff0000 !important;
}
.blueteamradio {
color: #0000ff;
color: #0000ff !important;
}
.greenteamradio {
color: #00ff00;
color: #00ff00 !important;
}
.yellowteamradio {
color: #d1ba22;
color: #d1ba22 !important;
}
.yell {