Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 30ea933

Browse files
authored
[ADMIN] NT uplinks for ERT (#15355)
* ERT uplink init * add oxy tank to ert backpack * add ds hardsuits & fix m1911 mag * set to just "Commander" * adds eshield, teleshield, and ds mask to uplink * add medbeam gun, remove duplicate * restrict discounts & limit stock * fix wt dupe * makes the tommygun wildly inaccurate * tommy cheaper cause inaccurate also desc * lets you have two tommy guns miss me with that ‘weapon accuracy’ shit. im shooting everything. im laying down cover fire. im shooting the walls. im shooting my teammates. im shooting myself. my accuracy is 100% yall just dont know what im aiming at * makes toolbelt 1 wc * makes tommy actually inaccurate * poke turdis * fixes * adds ap and incen saber ammo * add laser rifle, cap eguns * ds get a little more * reduce industrial RCD price to 5WC * reduce RCD to 2 and combat RCD to 4 * reduce medbeam by 1 and limit stock * ERT leader gets 5 extra WC * leader gets fancy hat * Update ert.dm * fix laser rifle overwriting tac eguns * set default uplink type * add mini e gun * add nt mantis blades * fix nt mantis * efficiency or something * actually mini * lower mantis to 7 * add armors * update teleshield desc * add bowman * fix paths * add poster box * Update uplink_items.dm * lower recharger cost to 2 WC * add exclusivity to ert commander hardsuit * fixes stupid tommygun code * Update smg.dm
1 parent 2d546bb commit 30ea933

16 files changed

Lines changed: 790 additions & 7 deletions

File tree

code/datums/components/uplink.dm

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ GLOBAL_LIST_EMPTY(uplinks)
1212
/datum/component/uplink
1313
dupe_mode = COMPONENT_DUPE_UNIQUE
1414
var/name = "syndicate uplink"
15+
var/js_ui = "Uplink"
16+
var/obj/item/stack/currency = /obj/item/stack/telecrystal
1517
var/active = FALSE
1618
var/lockable = TRUE
1719
var/locked = TRUE
@@ -56,7 +58,7 @@ GLOBAL_LIST_EMPTY(uplinks)
5658
RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation)
5759

5860
GLOB.uplinks += src
59-
uplink_items = get_uplink_items(_gamemode, TRUE, allow_restricted)
61+
uplink_items = get_uplink_items(_gamemode, TRUE, allow_restricted, js_ui)
6062

6163
if(_owner)
6264
owner = _owner
@@ -90,7 +92,7 @@ GLOBAL_LIST_EMPTY(uplinks)
9092
purchase_log = null
9193
return ..()
9294

93-
/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE)
95+
/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/TC, silent = FALSE)
9496
if(!silent)
9597
to_chat(user, span_notice("You slot [TC] into [parent] and charge its internal uplink."))
9698
var/amt = TC.amount
@@ -99,12 +101,12 @@ GLOBAL_LIST_EMPTY(uplinks)
99101

100102
/datum/component/uplink/proc/set_gamemode(_gamemode)
101103
gamemode = _gamemode
102-
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted)
104+
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted, js_ui)
103105

104106
/datum/component/uplink/proc/OnAttackBy(datum/source, obj/item/I, mob/user)
105107
if(!active)
106108
return //no hitting everyone/everything just to try to slot tcs in!
107-
if(istype(I, /obj/item/stack/telecrystal))
109+
if(istype(I, currency))
108110
LoadTC(user, I)
109111
return
110112
var/datum/component/refundable/R = I.GetComponent(/datum/component/refundable)
@@ -132,7 +134,7 @@ GLOBAL_LIST_EMPTY(uplinks)
132134
active = TRUE
133135
ui = SStgui.try_update_ui(user, src, ui)
134136
if(!ui)
135-
ui = new(user, src, "Uplink", name)
137+
ui = new(user, src, js_ui, name)
136138
// This UI is only ever opened by one person,
137139
// and never is updated outside of user input.
138140
ui.set_autoupdate(FALSE)
@@ -345,3 +347,10 @@ GLOBAL_LIST_EMPTY(uplinks)
345347
return
346348
explosion(T,1,2,3)
347349
qdel(parent) //Alternatively could brick the uplink.
350+
351+
352+
/// NT Uplink
353+
/datum/component/uplink/nanotrasen
354+
name = "nanotrasen uplink"
355+
js_ui = "NTUplink"
356+
currency = /obj/item/stack/ore/bluespace_crystal/refined/nt

code/datums/ert.dm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
var/teamsize = 5
1313
var/polldesc
1414

15+
// this can be safely set as default because it doesnt do anything unless specifically making uplinked ERT
16+
var/obj/item/uplinktype = /obj/item/ntuplink/official
17+
1518
/datum/ert/New()
1619
if (!polldesc)
1720
polldesc = "a Code [code] Nanotrasen Emergency Response Team"
@@ -109,6 +112,12 @@
109112
rename_team = "CentCom Grand Admirals"
110113
polldesc = "a CentCom Grand Admiral"
111114

115+
/datum/ert/uplinked
116+
leader_role = /datum/antagonist/ert/common/leader
117+
roles = list(/datum/antagonist/ert/common)
118+
rename_team = "Uplinked Emergency Response Team"
119+
polldesc = "an Uplink-Equipped ERT"
120+
112121
/datum/ert/inquisition
113122
roles = list(/datum/antagonist/ert/chaplain/inquisitor, /datum/antagonist/ert/security/inquisitor, /datum/antagonist/ert/medic/inquisitor)
114123
leader_role = /datum/antagonist/ert/commander/inquisitor

code/game/objects/items/devices/radio/headset.dm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,16 @@ GLOBAL_LIST_INIT(channel_tokens, list(
260260
/obj/item/radio/headset/headset_cent/alt
261261
keyslot = new /obj/item/encryptionkey/heads/captain
262262

263+
/obj/item/radio/headset/headset_cent/bowman // No captain key
264+
name = "\improper CentCom bowman headset"
265+
desc = "A headset especially for emergency response personnel. Protects ears from flashbangs."
266+
icon_state = "cent_headset_alt"
267+
item_state = "cent_headset_alt"
268+
269+
/obj/item/radio/headset/headset_cent/bowman/ComponentInitialize()
270+
. = ..()
271+
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
272+
263273
/obj/item/radio/headset/headset_cent/commander
264274
name = "\improper CentCom bowman headset"
265275
desc = "A headset especially for emergency response personnel. Protects ears from flashbangs."

code/game/objects/items/stacks/bscrystal.dm

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,45 @@
1818
points = 0
1919
refined_type = null
2020

21+
/obj/item/stack/ore/bluespace_crystal/refined/nt // NT's telecrystal
22+
name = "warpcrystal"
23+
desc = "The culmination of Nanotrasen's sacrifices in pursuing technological advancement. Highly top-secret."
24+
materials = list(/datum/material/bluespace=MINERAL_MATERIAL_AMOUNT*2.5) // more potent
25+
26+
/obj/item/stack/ore/bluespace_crystal/refined/nt/five
27+
amount = 5
28+
29+
/obj/item/stack/ore/bluespace_crystal/refined/nt/twenty
30+
amount = 20
31+
32+
/obj/item/stack/ore/bluespace_crystal/refined/nt/attack_self(mob/user)
33+
if(!isliving(user))
34+
return
35+
36+
var/mob/living/L = user
37+
38+
var/turf/destination = get_teleport_loc(loc, L, rand(3,6)) // Gets 3-6 tiles in the user's direction
39+
40+
if(!istype(destination))
41+
return
42+
43+
L.visible_message(span_warning("[L] crushes [src]!"), span_danger("You crush [src]!"))
44+
new /obj/effect/particle_effect/sparks(loc)
45+
playsound(loc, "sparks", 50, 1)
46+
47+
if(!do_teleport(L, destination, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE))
48+
L.visible_message(span_warning("[src] refuses to be crushed by [L]! There must be something interfering!"), span_danger("[src] suddenly hardens in your hand! There must be something interfering!"))
49+
return
50+
51+
// Throws you one additional tile, giving it that cool "exit portal" effect and also throwing people very far if they are in space
52+
L.throw_at(get_edge_target_turf(L, L.dir), 1, 3, spin = FALSE, diagonals_first = TRUE)
53+
if(iscarbon(L))
54+
var/mob/living/carbon/C = L
55+
// Half as debilitating than a bluespace crystal, as this is a precious resource you're using
56+
C.adjust_disgust(15)
57+
58+
use(1)
59+
2160
/obj/item/stack/ore/bluespace_crystal/Initialize()
2261
. = ..()
2362
pixel_x = rand(-5, 5)

code/game/objects/items/storage/briefcase.dm

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,12 @@
5353
/obj/item/storage/briefcase/syndie_mantis/PopulateContents()
5454
..()
5555
new /obj/item/autosurgeon/organ/syndicate/syndie_mantis(src)
56-
new /obj/item/autosurgeon/organ/syndicate/syndie_mantis/l(src)
56+
new /obj/item/autosurgeon/organ/syndicate/syndie_mantis/l(src)
57+
58+
/obj/item/storage/briefcase/nt_mantis
59+
desc = "A sleek briefcase. It has the letters H.E.P.H.A.E.S.T.U.S. on it"
60+
61+
/obj/item/storage/briefcase/nt_mantis/PopulateContents()
62+
..()
63+
new /obj/item/autosurgeon/nt_mantis(src)
64+
new /obj/item/autosurgeon/nt_mantis/l(src)

code/game/objects/items/storage/uplink_kits.dm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,3 +634,11 @@
634634
/obj/item/storage/box/syndie_kit/bee_grenades/PopulateContents()
635635
for(var/i in 1 to 3)
636636
new /obj/item/grenade/spawnergrenade/buzzkill(src)
637+
638+
/obj/item/storage/box/official_posters
639+
name = "poster box"
640+
desc = "A box filled with posters."
641+
642+
/obj/item/storage/box/official_posters/PopulateContents()
643+
for(var/i in 1 to 7)
644+
new /obj/item/poster/random_official(src)

code/modules/admin/topic.dm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@
175175
else
176176
message_admins("[key_name_admin(usr)] tried to create a CentCom response team. Unfortunately, there were not enough candidates available.")
177177
log_admin("[key_name(usr)] failed to create a CentCom response team.")
178+
if("centcom_custom")
179+
message_admins("[key_name(usr)] is creating a Uplinked CentCom response team...")
180+
if(src.makeUplinkEmergencyResponseTeam())
181+
message_admins("[key_name(usr)] created a Uplinked CentCom response team.")
182+
log_admin("[key_name(usr)] created a Uplinked CentCom response team.")
183+
else
184+
message_admins("[key_name_admin(usr)] tried to create a Uplinked CentCom response team. Unfortunately, there were not enough candidates available.")
185+
log_admin("[key_name(usr)] failed to create a Uplinked CentCom response team.")
178186
if("abductors")
179187
message_admins("[key_name(usr)] is creating an abductor team...")
180188
if(src.makeAbductorTeam())

code/modules/admin/verbs/one_click_antag.dm

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<a href='?src=[REF(src)];[HrefToken()];makeAntag=blob'>Make Blob</a><br>
2121
<a href='?src=[REF(src)];[HrefToken()];makeAntag=wizard'>Make Wizard (Requires Ghosts)</a><br>
2222
<a href='?src=[REF(src)];[HrefToken()];makeAntag=nukeops'>Make Nuke Team (Requires Ghosts)</a><br>
23+
<a href='?src=[REF(src)];[HrefToken()];makeAntag=centcom_custom'>Make Uplink CentCom Response Team (Requires Ghosts)</a><br>
2324
<a href='?src=[REF(src)];[HrefToken()];makeAntag=centcom'>Make CentCom Response Team (Requires Ghosts)</a><br>
2425
<a href='?src=[REF(src)];[HrefToken()];makeAntag=abductors'>Make Abductor Team (Requires Ghosts)</a><br>
2526
<a href='?src=[REF(src)];[HrefToken()];makeAntag=revenant'>Make Revenant (Requires Ghost)</a><br>
@@ -491,6 +492,120 @@
491492

492493
return
493494

495+
// Uplink-equipped Centcom Response Team
496+
/datum/admins/proc/makeUplinkEmergencyResponseTeam(var/datum/ert/ertemplate = null)
497+
if (ertemplate)
498+
ertemplate = new ertemplate
499+
else
500+
ertemplate = new /datum/ert/uplinked
501+
502+
var/list/settings = list(
503+
"preview_callback" = CALLBACK(src, .proc/makeERTPreviewIcon),
504+
"mainsettings" = list(
505+
"template" = list("desc" = "Template", "type" = "datum", "path" = "/datum/ert/uplinked", "value" = "/datum/ert/uplinked"),
506+
"uplink" = list("desc" = "Uplink Type", "type" = "datum", "path" = "/obj/item/ntuplink", "subtypesonly" = TRUE, "value" = ertemplate.uplinktype),
507+
"teamsize" = list("desc" = "Team Size", "type" = "number", "value" = ertemplate.teamsize),
508+
"mission" = list("desc" = "Mission", "type" = "string", "value" = ertemplate.mission),
509+
"polldesc" = list("desc" = "Ghost poll description", "type" = "string", "value" = ertemplate.polldesc),
510+
"enforce_human" = list("desc" = "Enforce human authority", "type" = "boolean", "value" = "[(CONFIG_GET(flag/enforce_human_authority) ? "Yes" : "No")]"),
511+
"open_armory" = list("desc" = "Open armory doors", "type" = "boolean", "value" = "[(ertemplate.opendoors ? "Yes" : "No")]"),
512+
"open_mechbay" = list("desc" = "Open Mech Bay", "type" = "boolean", "value" = "[(ertemplate.openmech ? "Yes" : "No")]"),
513+
)
514+
)
515+
516+
var/list/prefreturn = presentpreflikepicker(usr,"Customize ERT", "Customize ERT", Button1="Ok", width = 600, StealFocus = 1,Timeout = 0, settings=settings)
517+
518+
if (isnull(prefreturn))
519+
return FALSE
520+
521+
if (prefreturn["button"] == 1)
522+
var/list/prefs = settings["mainsettings"]
523+
524+
ertemplate.uplinktype = prefs["uplink"]["value"]
525+
ertemplate.teamsize = prefs["teamsize"]["value"]
526+
ertemplate.mission = prefs["mission"]["value"]
527+
ertemplate.polldesc = prefs["polldesc"]["value"]
528+
ertemplate.enforce_human = prefs["enforce_human"]["value"] == "Yes" ? TRUE : FALSE
529+
ertemplate.opendoors = prefs["open_armory"]["value"] == "Yes" ? TRUE : FALSE
530+
ertemplate.openmech = prefs["open_mechbay"]["value"] == "Yes" ? TRUE : FALSE
531+
532+
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for [ertemplate.polldesc] ?", "deathsquad", null)
533+
var/teamSpawned = FALSE
534+
535+
if(candidates.len > 0)
536+
//Pick the (un)lucky players
537+
var/numagents = min(ertemplate.teamsize,candidates.len)
538+
539+
//Create team
540+
var/datum/team/ert/ert_team = new ertemplate.team
541+
if(ertemplate.rename_team)
542+
ert_team.name = ertemplate.rename_team
543+
544+
//Asign team objective
545+
var/datum/objective/missionobj = new
546+
missionobj.team = ert_team
547+
missionobj.explanation_text = ertemplate.mission
548+
missionobj.completed = TRUE
549+
ert_team.objectives += missionobj
550+
ert_team.mission = missionobj
551+
552+
var/list/spawnpoints = GLOB.emergencyresponseteamspawn
553+
while(numagents && candidates.len)
554+
if (numagents > spawnpoints.len)
555+
numagents--
556+
continue // This guy's unlucky, not enough spawn points, we skip him.
557+
var/spawnloc = spawnpoints[numagents]
558+
var/mob/dead/observer/chosen_candidate = pick(candidates)
559+
candidates -= chosen_candidate
560+
if(!chosen_candidate.key)
561+
continue
562+
563+
//Spawn the body
564+
var/mob/living/carbon/human/ERTOperative = new ertemplate.mobtype(spawnloc)
565+
chosen_candidate.client.prefs.copy_to(ERTOperative)
566+
ERTOperative.key = chosen_candidate.key
567+
568+
if(ertemplate.enforce_human || !(ERTOperative.dna.species.changesource_flags & ERT_SPAWN)) // Don't want any exploding plasmemes
569+
ERTOperative.set_species(/datum/species/human)
570+
571+
//Give antag datum
572+
var/datum/antagonist/ert/ert_antag
573+
574+
if(numagents == 1)
575+
ert_antag = new ertemplate.leader_role
576+
else
577+
ert_antag = ertemplate.roles[WRAP(numagents,1,length(ertemplate.roles) + 1)]
578+
ert_antag = new ert_antag
579+
580+
ERTOperative.mind.add_antag_datum(ert_antag,ert_team)
581+
ERTOperative.mind.assigned_role = ert_antag.name
582+
583+
// Equip uplink
584+
var/obj/item/upl = new ertemplate.uplinktype
585+
if(istype(upl))
586+
ERTOperative.equip_to_slot_or_del(upl, SLOT_IN_BACKPACK)
587+
588+
//Logging and cleanup
589+
//log_game("[key_name(ERTOperative)] has been selected as an [ert_antag.name]") | yogs - redundant
590+
numagents--
591+
teamSpawned++
592+
593+
if (teamSpawned)
594+
message_admins("[ertemplate.polldesc] has spawned with the mission: [ertemplate.mission]")
595+
596+
//Open the Armory doors
597+
if(ertemplate.opendoors)
598+
for(var/obj/machinery/door/poddoor/ert/door in GLOB.airlocks)
599+
INVOKE_ASYNC(door, /obj/machinery/door/poddoor.proc/open)
600+
601+
//Open the Mech Bay
602+
if(ertemplate.openmech)
603+
for(var/obj/machinery/door/poddoor/deathsquad/door in GLOB.airlocks)
604+
INVOKE_ASYNC(door, /obj/machinery/door/poddoor.proc/open)
605+
return TRUE
606+
607+
return FALSE
608+
494609
//Abductors
495610
/datum/admins/proc/makeAbductorTeam()
496611
new /datum/round_event/ghost_role/abductor

code/modules/antagonists/ert/ert.dm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@
6464
/datum/antagonist/ert/medic/red
6565
outfit = /datum/outfit/ert/medic/alert
6666

67+
/datum/antagonist/ert/common
68+
outfit = /datum/outfit/ert
69+
70+
/datum/antagonist/ert/common/leader
71+
name = "Emergency Response Commander"
72+
role = "Commander"
73+
outfit = /datum/outfit/ert/commonleader
74+
6775
/datum/antagonist/ert/commander
6876
role = "Commander"
6977
outfit = /datum/outfit/ert/commander

code/modules/clothing/outfits/ert.dm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,27 @@
11
/datum/outfit/ert
22
name = "ERT Common"
33

4+
id = /obj/item/card/id/ert
5+
back = /obj/item/storage/backpack
46
uniform = /obj/item/clothing/under/rank/centcom_officer
57
shoes = /obj/item/clothing/shoes/combat/swat
68
gloves = /obj/item/clothing/gloves/combat
79
ears = /obj/item/radio/headset/headset_cent/alt
810
implants = list(/obj/item/implant/mindshield)
11+
backpack_contents = list(
12+
/obj/item/clothing/mask/gas/sechailer/swat=1,
13+
/obj/item/tank/internals/oxygen/tactical=1,
14+
/obj/item/tank/internals/emergency_oxygen/double=1,
15+
)
916

17+
/datum/outfit/ert/commonleader
18+
head = /obj/item/clothing/head/beret/sec
19+
backpack_contents = list(
20+
/obj/item/clothing/mask/gas/sechailer/swat=1,
21+
/obj/item/tank/internals/oxygen/tactical=1,
22+
/obj/item/tank/internals/emergency_oxygen/double=1,
23+
/obj/item/stack/ore/bluespace_crystal/refined/nt/five=1
24+
)
1025

1126
/datum/outfit/ert/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
1227
if(visualsOnly)

0 commit comments

Comments
 (0)