Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ab16fdc
Automatic changelog compile [ci skip]
cmss13-ci[bot] Feb 11, 2026
9e1296d
Fixes being unable to apply Eschar or Severe Burns through the limb s…
Puckaboo2 Feb 12, 2026
79a9b5d
Automatic changelog for PR #11450 [ci skip]
cmss13-ci[bot] Feb 12, 2026
5b3ebbc
big xenos can no longer be buckled into office chairs (#11675)
ori-disillusion-mirnov Feb 12, 2026
d88803e
Automatic changelog for PR #11675 [ci skip]
cmss13-ci[bot] Feb 12, 2026
c2b6a99
Automatic changelog compile [ci skip]
cmss13-ci[bot] Feb 12, 2026
dc6a44f
Shell/bullet ejection stacking to hand, moving while attaching weapon…
Nihisohel Feb 12, 2026
2c4f27f
Automatic changelog for PR #11323 [ci skip]
cmss13-ci[bot] Feb 12, 2026
93ec14d
general revoler holster rig > general revolver holster rig + revolver…
neeshacark Feb 12, 2026
1f56b68
Automatic changelog for PR #11619 [ci skip]
cmss13-ci[bot] Feb 12, 2026
5a6a871
Automatic changelog compile [ci skip]
cmss13-ci[bot] Feb 13, 2026
2fb6150
Fixes evolving from a larva into a t1 with a dead queen (#11678)
AmazingDragon353 Feb 15, 2026
f920fe3
Automatic changelog for PR #11678 [ci skip]
cmss13-ci[bot] Feb 15, 2026
2bb4f40
Fix hydrotrays ignoring bullet damage (#11672)
timothymtorres Feb 15, 2026
c20a471
Automatic changelog for PR #11672 [ci skip]
cmss13-ci[bot] Feb 15, 2026
e0f9b75
build and release
hry-gh Feb 15, 2026
53e140f
slim down the build some more
hry-gh Feb 15, 2026
76df713
include tgui folder
hry-gh Feb 15, 2026
771bf4a
Automatic changelog compile [ci skip]
cmss13-ci[bot] Feb 16, 2026
49ffdd4
Revert "Queens can rest again" (Ovi) (#11718)
Drulikar Feb 17, 2026
3a4756f
Automatic changelog for PR #11718 [ci skip]
cmss13-ci[bot] Feb 17, 2026
65ba4ca
Automatic changelog compile [ci skip]
cmss13-ci[bot] Feb 17, 2026
c9eb051
Rust_g 6.0.0 (#11653)
Drulikar Feb 17, 2026
4577fa7
Automatic changelog for PR #11653 [ci skip]
cmss13-ci[bot] Feb 17, 2026
75bcd95
Moderators (+ trial) now get full STUI + logs + fixes (#11714)
Drulikar Feb 17, 2026
1096a23
Automatic changelog for PR #11714 [ci skip]
cmss13-ci[bot] Feb 17, 2026
0e4fbb3
Fix: Cades stacking on top of each other. (#11636)
MistChristmas Feb 17, 2026
7369f7b
Automatic changelog for PR #11636 [ci skip]
cmss13-ci[bot] Feb 17, 2026
efccafb
Desert Moon - Hunting Grounds Map (#10935)
Unknownity Feb 17, 2026
b6ecc14
Automatic changelog for PR #10935 [ci skip]
cmss13-ci[bot] Feb 17, 2026
3567bb5
multitile vehicle hvh stuff (#9120)
BOBAMAx Feb 17, 2026
a57fac0
Automatic changelog for PR #9120 [ci skip]
cmss13-ci[bot] Feb 17, 2026
1877870
Tyrargo Rift - Ground Map (#8846)
Steelpoint Feb 17, 2026
bb50fba
Automatic changelog for PR #8846 [ci skip]
cmss13-ci[bot] Feb 17, 2026
7cd1009
[QOL] New option for admins to remove mindless mobs during ERT spawn.…
PhantornRU Feb 17, 2026
208e09e
Automatic changelog for PR #9402 [ci skip]
cmss13-ci[bot] Feb 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Build and Release

on:
push:
branches:
- master

concurrency:
group: build-and-release
cancel-in-progress: true

jobs:
build_and_release:
name: Build and Release
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v5

- name: Setup Bun
uses: ./.github/actions/setup_bun

- name: Restore BYOND from Cache
uses: ./.github/actions/restore_or_install_byond

- name: Install curl
run: |
sudo dpkg --add-architecture i386
sudo apt update || true
sudo apt install -o APT::Immediate-Configure=false curl:i386

- name: Build
run: |
source $HOME/BYOND/byond/bin/byondsetup
tools/build/build.sh

- name: Install zstd
run: sudo apt install -y zstd

- name: Create compressed archive
run: |
tar --exclude='./icons' --exclude='./sound' --exclude='./.git' --exclude='node_modules' --exclude='./code' --exclude='./tools' -cvf - . | zstd -19 -T0 -o colonialmarines-build.tar.zst

- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: build-${{ github.sha }}
name: Build ${{ github.sha }}
body: Automated build from commit ${{ github.sha }}
files: |
colonialmarines-build.tar.zst
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 4 additions & 0 deletions code/__DEFINES/__game.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define MAP_LV522_CHANCES_CLAIM "LV-522 Chance's Claim"
#define MAP_LV759_HYBRISA_PROSPERA "LV-759 Hybrisa Prospera" // Highpop Only
#define MAP_NEW_VARADERO "New Varadero"//ice colony underground but as its own map
#define MAP_TYRARGO_RIFT "Tyrargo Rift"
#define MAP_CHINOOK "Chinook 91 GSO" //admin level
#define MAP_ROSTOCK "SSV Rostock" //UPP Warship

Expand Down Expand Up @@ -389,6 +390,9 @@
#define WALL_STRATA_ICE "strata_ice"
#define WALL_STRATA_ICE_DIRTY "strata_ice_dirty"
#define WALL_JUNGLE_UPDATED "jungle_veg"
#define WALL_FOREST "forest_veg"
#define WALL_FOREST_ROCK "rock_forest"
#define WALL_FOREST_ROCK_DIRTY "rock_forest_dirty"
#define WALL_STRATA_OUTPOST_RIBBED "strata_ribbed_outpost_"
#define WALL_STRATA_OUTPOST_BARE "strata_bare_outpost_"
#define WALL_SHIVA_ICE "shiva_ice"
Expand Down
55 changes: 52 additions & 3 deletions code/__DEFINES/__rust_g.dm
Original file line number Diff line number Diff line change
Expand Up @@ -203,21 +203,70 @@

#define rustg_hash_string(algorithm, text) RUSTG_CALL(RUST_G, "hash_string")(algorithm, text)
#define rustg_hash_file(algorithm, fname) RUSTG_CALL(RUST_G, "hash_file")(algorithm, fname)
#define rustg_hash_generate_totp(seed) RUSTG_CALL(RUST_G, "generate_totp")(seed)
#define rustg_hash_generate_totp_tolerance(seed, tolerance) RUSTG_CALL(RUST_G, "generate_totp_tolerance")(seed, tolerance)

/// Supported algorithms: RUSTG_HASH_SHA1, RUSTG_HASH_SHA256, RUSTG_HASH_SHA512
/// Seed must be between 10 bytes to 64 bytes (padded or unpadded) of base32. 20 bytes is recommended. Use a CSPRNG.
/// Refresh rate is fixed at 30sec and digit count is fixed at 6
#define rustg_hash_generate_totp(algorithm, seed) RUSTG_CALL(RUST_G, "generate_totp")(algorithm, seed)
/// Supported algorithms: RUSTG_HASH_SHA1, RUSTG_HASH_SHA256, RUSTG_HASH_SHA512
/// Seed must be between 10 bytes to 64 bytes (padded or unpadded) of base32. 20 bytes is recommended. Use a CSPRNG.
/// Refresh rate is fixed at 30sec and digit count is fixed at 6
/// Tolerance is the number of codes +-30sec from the current one that are allowed.
#define rustg_hash_generate_totp_tolerance(algorithm, seed, tolerance) RUSTG_CALL(RUST_G, "generate_totp_tolerance")(algorithm, seed, tolerance)

/// Creates a cryptographically-secure pseudorandom number generator using the OS-level PRNG as a seed
/// n_bytes is the number of bytes provided to the RNG, the length of the string output varies by format
/// The output string length and characters contained in each format is as follows:
/// RUSTG_RNG_FORMAT_HEX: n_bytes * 2, [a-z0-9]
/// RUSTG_RNG_FORMAT_ALPHANUMERIC: n_bytes, [A-Za-z0-9]
/// RUSTG_RNG_FORMAT_BASE32: ceil(n_bytes / 5 * 8) [A-Z2-7]
/// RUSTG_RNG_FORMAT_BASE32_PADDED: ceil(n_bytes / 5) * 8 [A-Z2-7=]
/// RUSTG_RNG_FORMAT_BASE64: 4 * ceil(n_bytes/3), [A-Za-z0-9+/=]
/// Outputs "ERROR: [reason]" if the format string provided is invalid, or n_bytes is not a positive non-zero integer
#define rustg_csprng_chacha20(format, n_bytes) RUSTG_CALL(RUST_G, "csprng_chacha20")(format, "[n_bytes]")

/// Creates a seeded pseudorandom number generator using the SHA256 hash output bytes of the seed string
/// Note that this function is NOT suitable for use in cryptography and is intended for high-quality **predictable** RNG
/// Use rustg_csprng_chacha20 for a cryptographically-secure PRNG.
/// n_bytes is the number of bytes provided to the RNG, the length of the string output varies by format
/// The output string length and characters contained in each format is as follows:
/// RUSTG_RNG_FORMAT_HEX: n_bytes * 2, [a-z0-9]
/// RUSTG_RNG_FORMAT_ALPHANUMERIC: n_bytes, [A-Za-z0-9]
/// RUSTG_RNG_FORMAT_BASE32: ceil(n_bytes / 5 * 8) [A-Z2-7]
/// RUSTG_RNG_FORMAT_BASE32_PADDED: ceil(n_bytes / 5) * 8 [A-Z2-7=]
/// RUSTG_RNG_FORMAT_BASE64: 4 * ceil(n_bytes/3), [A-Za-z0-9+/=]
/// Outputs "ERROR: [reason]" if the format string provided is invalid, or n_bytes is not a positive non-zero integer
#define rustg_prng_chacha20_seeded(format, n_bytes, seed) RUSTG_CALL(RUST_G, "prng_chacha20_seeded")(format, "[n_bytes]", seed)

#define RUSTG_RNG_FORMAT_HEX "hex"
#define RUSTG_RNG_FORMAT_ALPHANUMERIC "alphanumeric"
#define RUSTG_RNG_FORMAT_BASE32 "base32_rfc4648"
#define RUSTG_RNG_FORMAT_BASE32_PADDED "base32_rfc4648_pad"
#define RUSTG_RNG_FORMAT_BASE64 "base64"

#define RUSTG_HASH_MD5 "md5"
#define RUSTG_HASH_SHA1 "sha1"
#define RUSTG_HASH_SHA256 "sha256"
#define RUSTG_HASH_SHA512 "sha512"
#define RUSTG_HASH_XXH64 "xxh64"
#define RUSTG_HASH_BASE32 "base32_rfc4648"
#define RUSTG_HASH_BASE32_PADDED "base32_rfc4648_pad"
#define RUSTG_HASH_BASE64 "base64"

/// Encode a given string into base64
#define rustg_encode_base64(str) rustg_hash_string(RUSTG_HASH_BASE64, str)
/// Decode a given base64 string
/// Decode a given base64 string. This expects padding.
/// Returns a blank string if the string is not valid base64.
#define rustg_decode_base64(str) RUSTG_CALL(RUST_G, "decode_base64")(str)

/// Encode a given string into base32 (RFC4648)
/// If padding set to FALSE, will not output padding characters.
#define rustg_encode_base32(str, padding) rustg_hash_string(padding ? RUSTG_HASH_BASE32_PADDED : RUSTG_HASH_BASE32, str)
/// Decode a given base32 (RFC4648) string
/// If padding set to FALSE, decoding will not support padding characters.
/// Returns a blank string if the string is not valid base32.
#define rustg_decode_base32(str, padding) RUSTG_CALL(RUST_G, "decode_base32")(str, "[padding ? 1 : 0]")

#ifdef RUSTG_OVERRIDE_BUILTINS
#define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing))
#endif
Expand Down
16 changes: 16 additions & 0 deletions code/__DEFINES/job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define SQUAD_CBRN "CBRN"
#define SQUAD_FORECON "FORECON"
#define SQUAD_SOLAR "Solar Devils"
#define SQUAD_ARMY "US Army"

// Job name defines
#define JOB_SQUAD_MARINE "Rifleman"
Expand Down Expand Up @@ -354,6 +355,21 @@ GLOBAL_LIST_INIT(job_command_roles, JOB_COMMAND_ROLES_LIST)

#define JOB_FORECON_LIST list(JOB_FORECON_CO, JOB_FORECON_SL, JOB_FORECON_SYN, JOB_FORECON_SNIPER, JOB_FORECON_MARKSMAN, JOB_FORECON_SUPPORT, JOB_FORECON_RIFLEMAN, JOB_FORECON_SMARTGUNNER)

//-------- US ARMY --------//

#define JOB_ARMY_TROOPER "US Army Trooper"
#define JOB_ARMY_ENGI "US Army Combat Engineering Technician"
#define JOB_ARMY_MEDIC "US Army Combat Medical Technician"
#define JOB_ARMY_MARKSMAN "US Army Marksman"
#define JOB_ARMY_SMARTGUNNER "US Army Heavy Gunner"
#define JOB_ARMY_SNCO "US Army Squad Leader"
#define JOB_ARMY_CO "US Army Commander"
#define JOB_ARMY_SYN "US Army Synthetic"


#define JOB_ARMY_LIST list(JOB_ARMY_TROOPER, JOB_ARMY_ENGI, JOB_ARMY_MEDIC, JOB_ARMY_MARKSMAN, JOB_ARMY_SMARTGUNNER, JOB_ARMY_SNCO, JOB_ARMY_CO, JOB_ARMY_SYN)


//-------- UPP --------//
#define JOB_UPP "UPP Ryadovoy"
#define JOB_UPP_CONSCRIPT "UPP Conscript"
Expand Down
1 change: 1 addition & 0 deletions code/__DEFINES/minimap.dm
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ GLOBAL_LIST_INIT(all_minimap_flags, bitfield2list(MINIMAP_FLAG_ALL))
#define MINIMAP_SQUAD_ECHO "#00b043"
#define MINIMAP_SQUAD_FOXTROT "#fe7b2e"
#define MINIMAP_SQUAD_SOF "#400000"
#define MINIMAP_SQUAD_ARMY "#349c30"
#define MINIMAP_SQUAD_INTEL "#053818"

//Prison
Expand Down
8 changes: 8 additions & 0 deletions code/__DEFINES/sounds.dm
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,11 @@
#define SCAPE_PL_LV759_DEEPCAVES list('sound/soundscape/lv759/outdoors/deepcave1.ogg','sound/soundscape/lv759/outdoors/deepcave2.ogg')
#define SCAPE_PL_LV759_CAVES list('sound/soundscape/lv759/outdoors/windy_caverns_1.ogg','sound/soundscape/lv759/outdoors/windy_caverns_2.ogg','sound/soundscape/lv759/outdoors/windy_caverns_3.ogg',)
#define SCAPE_PL_LV759_PLATEAU_OUTDOORS list('sound/soundscape/lv759/outdoors/derelict_plateau_1.ogg','sound/soundscape/lv759/outdoors/derelict_plateau_2.ogg',)

// Tyrargo Soundscapes

#define AMBIENCE_TYRARGO_CITY 'sound/ambience/tyrargo_city_ambience.ogg'
#define AMBIENCE_TYRARGO_SEWER_CITY 'sound/ambience/tyrargo_sewer_ambience.ogg'

#define SCAPE_PL_TYRARGO_SEWER list('sound/ambience/tyrargo_underground_1.ogg','sound/ambience/tyrargo_underground_2.ogg','sound/ambience/tyrargo_underground_3.ogg','sound/ambience/tyrargo_underground_4.ogg')
#define SCAPE_PL_TYRARGO_ALERT list('sound/ambience/tyrargo_alert_1.ogg', 'sound/ambience/tyrargo_alert_2.ogg', 'sound/ambience/tyrargo_alert_3.ogg', 'sound/ambience/tyrargo_alert_4.ogg', 'sound/ambience/tyrargo_alert_5.ogg', 'sound/ambience/tyrargo_alert_6.ogg')
10 changes: 9 additions & 1 deletion code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ GLOBAL_DATUM(action_purple_power_up, /image)
* numticks: If a value is given, denotes how often the timed action checks for interrupting actions. By default, there are 5 checks every delay/5 deciseconds.
* Note: 'delay' should be divisible by numticks in order for the timing to work as intended. numticks should also be a whole number.
*/
/proc/do_after(mob/user, delay, user_flags = INTERRUPT_ALL, show_busy_icon, atom/movable/target, target_flags = INTERRUPT_MOVED, show_target_icon, max_dist = 1, \
/proc/do_after(mob/user, delay, user_flags = INTERRUPT_ALL, show_busy_icon, atom/movable/target, target_flags = INTERRUPT_MOVED, show_target_icon, max_dist = 1, status_effect = null, \
show_remaining_time = FALSE, numticks = DA_DEFAULT_NUM_TICKS) // These args should primarily be named args, since you only modify them in niche situations
if(!istype(user) || delay < 0)
return FALSE
Expand Down Expand Up @@ -802,6 +802,10 @@ GLOBAL_DATUM(action_purple_power_up, /image)
if(user_flags & BEHAVIOR_IMMOBILE)
busy_user.status_flags |= IMMOBILE_ACTION

// if we wanna apply a status effect to a user
if(status_effect && busy_user)
busy_user.adjust_effect(delay, status_effect)

busy_user.action_busy++ // target is not tethered by action, the action is tethered by target though
busy_user.resisting = FALSE
busy_user.clicked_something = list()
Expand Down Expand Up @@ -950,6 +954,10 @@ GLOBAL_DATUM(action_purple_power_up, /image)
T.resisting = FALSE
busy_user.status_flags &= ~IMMOBILE_ACTION

// remove the effect once we finish
if(status_effect && busy_user)
busy_user.adjust_effect(-delay, status_effect)

if (show_remaining_time)
return (. ? 0 : time_remaining/expected_total_time) // If action was not interrupted, return 0 for no time left, otherwise return ratio of time remaining

Expand Down
2 changes: 2 additions & 0 deletions code/_globalvars/bitfields.dm
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ DEFINE_BITFIELD(status, list(
"LIMB_ROBOT" = LIMB_ROBOT,
"LIMB_SYNTHSKIN" = LIMB_SYNTHSKIN,
"LIMB_BROKEN" = LIMB_BROKEN,
"LIMB_ESCHAR" = LIMB_ESCHAR,
"LIMB_THIRD_DEGREE_BURNS" = LIMB_THIRD_DEGREE_BURNS,
"LIMB_DESTROYED" = LIMB_DESTROYED,
"LIMB_SPLINTED" = LIMB_SPLINTED,
"LIMB_MUTATED" = LIMB_MUTATED,
Expand Down
3 changes: 3 additions & 0 deletions code/controllers/subsystem/communications.dm
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency
#define PVST_FREQ 1473
#define CBRN_FREQ 1474
#define FORECON_FREQ 1475
#define ARMY_FREQ 1476

//Ship department channels
#define SENTRY_FREQ 1480
Expand Down Expand Up @@ -192,6 +193,7 @@ GLOBAL_LIST_INIT(radiochannels, list(
SQUAD_CBRN = CBRN_FREQ,
SQUAD_FORECON = FORECON_FREQ,
SQUAD_SOLAR = SOF_FREQ,
SQUAD_ARMY = ARMY_FREQ,

RADIO_CHANNEL_ALAMO = DS1_FREQ,
RADIO_CHANNEL_NORMANDY = DS2_FREQ,
Expand Down Expand Up @@ -322,6 +324,7 @@ SUBSYSTEM_DEF(radio)
"[ECHO_FREQ]" = "echoradio",
"[CRYO_FREQ]" = "cryoradio",
"[CBRN_FREQ]" = "hcradio",
"[ARMY_FREQ]" = "hcradio",
"[FORECON_FREQ]" = "hcradio",
"[SOF_FREQ]" = "hcradio",
"[HC_FREQ]" = "hcradio",
Expand Down
2 changes: 1 addition & 1 deletion code/controllers/subsystem/who.dm
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ SUBSYSTEM_DEF(who)
listings["Maintainers"] = list(R_PROFILER, list())
listings["Administrators"] = list(R_ADMIN, list())
if(CONFIG_GET(flag/show_mods))
listings["Moderators"] = list(R_MOD|R_BAN, list())
listings["Moderators"] = list(R_MOD, list())
if(CONFIG_GET(flag/show_mentors))
listings["Mentors"] = list(R_MENTOR, list())

Expand Down
7 changes: 7 additions & 0 deletions code/datums/ammo/bullet/pistol.dm
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,13 @@
BULLET_TRAIT_ENTRY(/datum/element/bullet_trait_incendiary)
))

/datum/ammo/bullet/pistol/squash/heap
name = "high-explosive armor-piercing pistol bullet"

headshot_state = HEADSHOT_OVERLAY_HEAVY
damage = 50
penetration = ARMOR_PENETRATION_TIER_10

/datum/ammo/bullet/pistol/squash/rubber
name = "rubber squash-head pistol bullet"
damage_type = BURN
Expand Down
21 changes: 20 additions & 1 deletion code/datums/emergency_calls/custom.dm
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,27 @@

return

/datum/emergency_call/custom/spawn_candidates(announce, override_spawn_loc)
/datum/emergency_call/custom/spawn_candidates(announce, override_spawn_loc, delete_mindless_mobs = FALSE)
. = ..()
if(delete_mindless_mobs)
delete_mindless_mobs()
else
offer_mobs_for_ghosts()

/datum/emergency_call/custom/proc/offer_mobs_for_ghosts()
if(owner)
for(var/mob/living/carbon/human/H in players_to_offer)
owner.free_for_ghosts(H)

/datum/emergency_call/custom/proc/delete_mindless_mobs()
var/count_mob_deleted = 0
for(var/player in players_to_offer)
if(!ismob(player))
continue
var/mob/spawned_mob = player
if(spawned_mob.mind)
continue
qdel(spawned_mob)
count_mob_deleted++

message_admins("After ERT spawn as [name], [count_mob_deleted] out of [mob_max] mindless mobs were removed.")
55 changes: 55 additions & 0 deletions code/datums/emergency_calls/us_army.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

/datum/emergency_call/us_army
name = "US Army (32nd Armor)"
home_base = /datum/lazy_template/ert/uscm_station
mob_min = 1
mob_max = 14
probability = 0
shuttle_id = ""
chance_hidden = 0
name_of_spawn = /obj/effect/landmark/ert_spawns/groundside_army

max_heavies = 2
max_medics = 2
max_smartgunners = 2

/datum/emergency_call/us_army/New()
..()
arrival_message = "Break, break. This is USS Victory, local Army elements confirm your sector is free of hostile tangos. Be advised, the 32nd Armour is en-route, forward elements should be entering your AO shortly to assist in mop-up. You may have just saved a lot of lives today Falling Falcons. Over and out."
objectives = "Assist the Marines in securing the area of operations."

/datum/emergency_call/us_army/create_member(datum/mind/new_mind, turf/override_spawn_loc)
var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point()

if(!istype(spawn_loc))
return //Didn't find a useable spawn point.

var/mob/living/carbon/human/mob = new(spawn_loc)
new_mind.transfer_to(mob, TRUE)

if(!leader && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(mob.client, JOB_SQUAD_LEADER, time_required_for_job))
leader = mob
arm_equipment(mob, /datum/equipment_preset/us_army/sl, TRUE, TRUE)
to_chat(mob, SPAN_ROLE_HEADER("You are the US Army Squad Leader!"))

else if(heavies < max_heavies && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_HEAVY) && check_timelock(mob.client, JOB_SQUAD_SPECIALIST))
heavies++
to_chat(mob, SPAN_ROLE_HEADER("You are a US Army Tank Crewman!"))
arm_equipment(mob, /datum/equipment_preset/us_army/tank, TRUE, TRUE)

else if(medics < max_medics && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_MEDIC) && check_timelock(mob.client, JOB_SQUAD_MEDIC, time_required_for_job))
medics++
arm_equipment(mob, /datum/equipment_preset/us_army/medic, TRUE, TRUE)
to_chat(mob, SPAN_ROLE_HEADER("You are the US Army Medic!"))

else if(smartgunners < max_smartgunners && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_SMARTGUNNER) && check_timelock(mob.client, JOB_SQUAD_SMARTGUN))
smartgunners++
to_chat(mob, SPAN_ROLE_HEADER("You are a US Army Gunner!"))
arm_equipment(mob, /datum/equipment_preset/us_army/gunner, TRUE, TRUE)

else
arm_equipment(mob, /datum/equipment_preset/us_army/standard, TRUE, TRUE)
to_chat(mob, SPAN_ROLE_HEADER("You are a US Army Trooper!"))

to_chat(mob, SPAN_ROLE_BODY("You are a member of the US Army 32nd Armored Division. You and your division have been held in reserve until the Falling Falcons could secure a beachhead. Now that this is true, you are being sent in to help secure the breach!"))
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)
Loading