Skip to content

Commit 8c42446

Browse files
authored
Reworks infiltrators and converts them into a midround antagonist (yogstation13#22802)
* A start * 10 TC * Fixes PDAs and gives them the rest of the chameleon kit * Fixes chameleon hardsuits and them unduly calling their own proc hundreds of times * Helmet light respects sprites * Surgery dufflebag * Fixes the infiltrator cutter's bolt airlocks button * Puts it back to the old preview * Escape disguised objective * Chameleon copying * Revert "Chameleon copying" This reverts commit 5d2d248. * Do not go to the base to end the round * Back to chameleon copying, I guess * Actually make it do something * This is why I need to think sometimes * Even more of a mess * Semi working but still not working * Back to atoms I guess * Just to confirm it isn't this * Finally works * Chameleon working, but badly * Might be more reasonable * Moves it to 10 seconds instead * Keeps chameleon copy to one proc * Refinements * Adds chameleon copy sprite * Gives them break machinery * Makes bad hardsuit list static * Prevents chameleon copy duplicating * Okay, maybe I should have checked the typepath * Temporary event minimum lowering * Fixing conflicts with psionics * Fix break machinery not actually giving you the proper objective to break machinery * May have forgotten that infiltrators are a team * Okay there, I referenced you properly
1 parent 74e8e75 commit 8c42446

File tree

13 files changed

+249
-26
lines changed

13 files changed

+249
-26
lines changed

_maps/shuttles/infiltrator_cutter.dmm

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
dir = 2
88
},
99
/obj/machinery/door/airlock/external{
10-
id_tag = "syndicatecutter_bolt_port"
10+
id_tag = "bolt_port"
1111
},
1212
/obj/docking_port/mobile{
1313
callTime = 150;
@@ -69,7 +69,7 @@
6969
dir = 1
7070
},
7171
/obj/machinery/door/airlock/external{
72-
id_tag = "syndicatecutter_bolt_port"
72+
id_tag = "bolt_port"
7373
},
7474
/obj/effect/mapping_helpers/airlock/access/all/syndicate/general,
7575
/turf/open/floor/plating,
@@ -204,13 +204,6 @@
204204
/area/shuttle/yogs/stealthcruiser)
205205
"aC" = (
206206
/obj/structure/table,
207-
/obj/item/circular_saw,
208-
/obj/item/scalpel{
209-
pixel_y = 12
210-
},
211-
/obj/item/cautery{
212-
pixel_x = 4
213-
},
214207
/obj/machinery/light/small{
215208
dir = 8
216209
},
@@ -312,8 +305,7 @@
312305
/area/shuttle/yogs/stealthcruiser)
313306
"aN" = (
314307
/obj/structure/table,
315-
/obj/item/retractor,
316-
/obj/item/hemostat,
308+
/obj/item/storage/backpack/duffelbag/med/surgery,
317309
/obj/effect/decal/cleanable/dirt,
318310
/turf/open/floor/plasteel,
319311
/area/shuttle/yogs/stealthcruiser)
@@ -757,7 +749,7 @@
757749
},
758750
/obj/effect/mapping_helpers/airlock/locked,
759751
/obj/machinery/door/airlock/external{
760-
id_tag = "syndicatecutter_bolt_starboard"
752+
id_tag = "bolt_starboard"
761753
},
762754
/obj/effect/mapping_helpers/airlock/access/all/syndicate/general,
763755
/turf/open/floor/plating,
@@ -780,7 +772,7 @@
780772
},
781773
/obj/effect/mapping_helpers/airlock/locked,
782774
/obj/machinery/door/airlock/external{
783-
id_tag = "syndicatecutter_bolt_starboard"
775+
id_tag = "bolt_starboard"
784776
},
785777
/obj/effect/mapping_helpers/airlock/access/all/syndicate/general,
786778
/turf/open/floor/plating,

code/modules/clothing/chameleon.dm

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,89 @@
143143
return TRUE
144144

145145

146+
/datum/action/cooldown/chameleon_copy
147+
name = "Copy person"
148+
button_icon = 'yogstation/icons/mob/actions.dmi'
149+
button_icon_state = "chameleon_copy"
150+
var/target_range = 3
151+
var/syndicate = FALSE
152+
var/active = FALSE
153+
var/copying = FALSE
154+
var/in_use = FALSE
155+
156+
/datum/action/cooldown/chameleon_copy/InterceptClickOn(mob/living/caller, params, atom/target)
157+
click_with_power(target)
158+
159+
/datum/action/cooldown/chameleon_copy/Grant(mob/M)
160+
if(syndicate)
161+
owner_has_control = is_syndicate(M)
162+
. = ..()
163+
164+
/datum/action/cooldown/chameleon_copy/proc/toggle_button()
165+
if(active)
166+
active = FALSE
167+
background_icon_state = "bg_default"
168+
build_all_button_icons()
169+
unset_click_ability(owner)
170+
return FALSE
171+
active = TRUE
172+
background_icon_state = "bg_default_on"
173+
build_all_button_icons()
174+
set_click_ability(owner)
175+
176+
/datum/action/cooldown/chameleon_copy/Trigger(trigger_flags, atom/target)
177+
if(active)
178+
toggle_button()
179+
else
180+
to_chat(owner, span_announce("Whom shall your chameleon kit copy?")) //Bad wording, need to improve it
181+
toggle_button()
182+
183+
184+
/datum/action/cooldown/chameleon_copy/proc/CheckValidTarget(atom/target)
185+
if(target == owner)
186+
return FALSE
187+
if(!ishuman(target))
188+
return FALSE
189+
return TRUE
190+
191+
/datum/action/cooldown/chameleon_copy/proc/click_with_power(atom/target_atom)
192+
if(in_use || !CheckValidTarget(target_atom))
193+
return FALSE
194+
in_use = TRUE
195+
FireTargetedPower(target_atom)
196+
in_use = FALSE
197+
return TRUE
198+
199+
/datum/action/cooldown/chameleon_copy/proc/FireTargetedPower(atom/target_atom)
200+
var/mob/living/carbon/human/T = target_atom
201+
var/datum/outfit/O = new()
202+
to_chat(owner, span_notice("Attempting to copy [T]..."))
203+
if(!do_after(owner, 10 SECONDS, target_atom))
204+
return
205+
O.uniform = T.w_uniform
206+
O.suit = T.wear_suit
207+
O.head = T.head
208+
O.shoes = T.shoes
209+
O.gloves = T.gloves
210+
O.ears = T.ears
211+
O.glasses = T.glasses
212+
O.mask = T.wear_mask
213+
O.back = T.back
214+
var/list/types = O.get_chameleon_disguise_info()
215+
for(var/Y in types)
216+
for(var/V in owner.chameleon_item_actions)
217+
var/datum/action/item_action/chameleon/change/A = V
218+
var/obj/item/I = Y
219+
if(A.chameleon_blacklist[Y] || (initial(I.item_flags) & ABSTRACT || !initial(I.icon_state)))
220+
continue
221+
if(istype(Y, A.chameleon_type)) //Need to make sure it's the right type, wouldn't want to wear an armour vest on your head.
222+
A.update_look(owner, Y)
223+
A.copying = TRUE
224+
A.copy_target = T
225+
to_chat(owner, span_notice("Successfully copied [T]!"))
226+
toggle_button()
227+
228+
146229
/datum/action/item_action/chameleon/change
147230
name = "Chameleon Change"
148231
var/list/chameleon_blacklist = list() //This is a typecache
@@ -152,6 +235,8 @@
152235
var/emp_timer
153236
var/current_disguise = null
154237
var/syndicate = FALSE
238+
var/copying = FALSE
239+
var/mob/living/copy_target
155240

156241
/datum/action/item_action/chameleon/change/Grant(mob/M)
157242
if(M && (owner != M))
@@ -160,6 +245,9 @@
160245
var/datum/action/chameleon_outfit/O = new /datum/action/chameleon_outfit()
161246
O.syndicate = syndicate
162247
O.Grant(M)
248+
var/datum/action/cooldown/chameleon_copy/C = new /datum/action/cooldown/chameleon_copy()
249+
C.syndicate = syndicate
250+
C.Grant(M)
163251
else
164252
M.chameleon_item_actions |= src
165253
if(syndicate)
@@ -172,6 +260,8 @@
172260
if(!LAZYLEN(M.chameleon_item_actions))
173261
var/datum/action/chameleon_outfit/O = locate(/datum/action/chameleon_outfit) in M.actions
174262
qdel(O)
263+
var/datum/action/cooldown/chameleon_copy/C = locate(/datum/action/cooldown/chameleon_copy) in M.actions
264+
qdel(C)
175265
return ..()
176266

177267
/datum/action/item_action/chameleon/change/proc/initialize_disguises()
@@ -195,6 +285,7 @@
195285
if(!picked_item)
196286
return
197287
update_look(user, picked_item)
288+
copying = FALSE
198289

199290
/datum/action/item_action/chameleon/change/proc/random_look(mob/user)
200291
var/picked_name = pick(chameleon_list)
@@ -275,10 +366,16 @@
275366
if(istype(atom_target, /obj/item/clothing/suit/space/hardsuit/infiltration)) //YOGS START
276367
var/obj/item/clothing/suit/space/hardsuit/infiltration/I = target
277368
var/obj/item/clothing/suit/space/hardsuit/HS = picked_item
278-
var/obj/item/clothing/head/helmet/helmet = initial(HS.helmettype)
369+
var/obj/item/clothing/head/helmet/space/hardsuit/helmet = initial(HS.helmettype)
279370
I.head_piece.initial_state = initial(helmet.icon_state)
280-
update_item(helmet, I.head_piece)
281371
I.head_piece.update_appearance(UPDATE_ICON)
372+
I.head_piece.current_disguise = picked_item
373+
I.head_piece.new_type = helmet.hardsuit_type
374+
var/datum/action/A
375+
for(var/X in I.actions)
376+
A = X
377+
A.build_all_button_icons()
378+
282379
qdel(helmet)
283380
//YOGS END
284381

@@ -616,6 +713,8 @@
616713
chameleon_action.emp_randomise(INFINITY)
617714

618715
/obj/item/clothing/mask/chameleon/attack_self(mob/user)
716+
if(!is_syndicate(user)) //Wouldn't want someone to randomly find a switch on a mask, would we?
717+
return
619718
vchange = !vchange
620719
to_chat(user, span_notice("The voice changer is now [vchange ? "on" : "off"]!"))
621720
if(vchange)

code/modules/modular_computers/computers/item/pda/pda_presets.dm

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,17 @@
233233
)
234234
return ..()
235235

236-
//for inside one of the nukie lockers
236+
//for inside one of the nukie lockers and the ones infiltrators spawn with
237237
/obj/item/modular_computer/tablet/pda/preset/syndicate
238238
desc = "Based off Nanotrasen's PDAs, this one has been reverse-engineered and loaded with illegal software provided by the Syndicate."
239239
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
240240
greyscale_colors = "#A80001#5C070F#000000"
241+
starting_components = list( /obj/item/computer_hardware/processor_unit/small,
242+
/obj/item/stock_parts/cell/computer,
243+
/obj/item/computer_hardware/hard_drive/small/syndicate,
244+
/obj/item/computer_hardware/network_card/advanced,
245+
/obj/item/computer_hardware/card_slot,
246+
/obj/item/computer_hardware/printer/mini)
241247

242248
/obj/item/modular_computer/tablet/pda/preset/syndicate/Initialize(mapload)
243249
obj_flags |= EMAGGED //starts emagged

code/modules/modular_computers/computers/item/tablet/tablet_presets.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
starting_components = list( /obj/item/computer_hardware/processor_unit/small,
7070
/obj/item/stock_parts/cell/computer,
7171
/obj/item/computer_hardware/hard_drive/small/nukeops,
72-
/obj/item/computer_hardware/network_card)
72+
/obj/item/computer_hardware/network_card/advanced)
7373

7474
starting_files = list(new /datum/computer_file/program/radar/fission360)
7575
initial_program = /datum/computer_file/program/radar/fission360

tgui/packages/tgui/interfaces/PreferencesMenu/antagonists/antagonists/infiltrator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const Infiltrator: Antagonist = {
1919
`,
2020
INFILTRATOR_MECHANICAL_DESCRIPTION,
2121
],
22-
category: Category.Roundstart,
22+
category: Category.Midround,
2323
priority: -1,
2424
};
2525

yogstation/code/game/objects/items/implants/implant_infiltrator.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
. = ..()
1010
ADD_TRAIT(src, TRAIT_EMPPROOF_SELF, "innate_empproof")
1111
ADD_TRAIT(src, TRAIT_EMPPROOF_CONTENTS, "innate_empproof")
12-
var/datum/component/uplink/uplink = AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, 20)
12+
var/datum/component/uplink/uplink = AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, 10)
1313
uplink.set_antagonist(ROLE_INFILTRATOR)
1414
alert_radio = new(src)
1515
alert_radio.make_syndie()

yogstation/code/modules/antagonists/infiltrator/infiltrator.dm

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team.
1111
var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint.
1212
var/dress_up = TRUE
13-
preview_outfit = /datum/outfit/infiltrator
13+
preview_outfit = /datum/outfit/infiltrator_preview
1414

1515
/datum/antagonist/infiltrator/apply_innate_effects(mob/living/mob_override)
1616
var/mob/living/M = mob_override || owner.current
@@ -24,7 +24,6 @@
2424
to_chat(owner, span_notice("You also have an internal radio, for communicating with your team-mates at all times."))
2525
to_chat(owner, span_notice("You have a dusting implant, to ensure that Nanotrasen does not get their hands on Syndicate gear. Only activate it, if you are compromised."))
2626
to_chat(owner, span_boldnotice(span_italics("Do NOT kill or destroy needlessly, as this defeats the purpose of an 'infiltration'!")))
27-
to_chat(owner, span_boldnotice("Once your objectives are complete, return to base, with all living infiltrators, to end the round."))
2827
owner.announce_objectives()
2928

3029
/datum/antagonist/infiltrator/on_gain()

yogstation/code/modules/antagonists/infiltrator/items/hardsuit.dm

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,48 @@
44
item_state = "eng_helm"
55
armor = list(MELEE = 35, BULLET = 15, LASER = 30,ENERGY = 10, BOMB = 10, BIO = 100, RAD = 50, FIRE = 75, ACID = 75)
66
syndicate = TRUE
7+
var/current_disguise = /obj/item/clothing/suit/space/hardsuit/infiltration
8+
var/new_type = "engineering"
9+
var/static/list/bad_hardsuits = list(
10+
/obj/item/clothing/suit/space/hardsuit/darktemplar,
11+
/obj/item/clothing/suit/space/hardsuit/darktemplar/chap,
12+
/obj/item/clothing/suit/space/hardsuit/cult,
13+
/obj/item/clothing/suit/space/hardsuit/syndi,
14+
/obj/item/clothing/suit/space/hardsuit/syndi/elite,
15+
/obj/item/clothing/suit/space/hardsuit/syndi/owl,
16+
/obj/item/clothing/suit/space/hardsuit/syndi/debug,
17+
/obj/item/clothing/suit/space/hardsuit/carp,
18+
/obj/item/clothing/suit/space/hardsuit/carp/dragon,
19+
/obj/item/clothing/suit/space/hardsuit/swat,
20+
/obj/item/clothing/suit/space/hardsuit/swat/captain,
21+
/obj/item/clothing/suit/space/hardsuit/ert/paranormal,
22+
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor,
23+
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker,
24+
/obj/item/clothing/suit/space/hardsuit/shielded/swat,
25+
/obj/item/clothing/suit/space/hardsuit/shielded/swat/honk,
26+
/obj/item/clothing/suit/space/hardsuit/deathsquad
27+
)
728

829
/obj/item/clothing/head/helmet/space/hardsuit/infiltration/Initialize(mapload)
930
. = ..()
1031
if(istype(loc, /obj/item/clothing/suit/space/hardsuit/infiltration))
1132
var/obj/item/clothing/suit/space/hardsuit/infiltration/I = loc
1233
I.head_piece = src
1334

35+
/obj/item/clothing/head/helmet/space/hardsuit/infiltration/attack_self(mob/user)
36+
if(bad_hardsuits.Find(current_disguise))
37+
to_chat(user, span_warning("You can't use the hardsuit's helmet light with this current disguise, change to another one!"))
38+
else //Copied from original hardsuit attack_self and modified slightly
39+
on = !on
40+
icon_state = "[basestate][on]-[new_type]"
41+
user.update_inv_head() //so our mob-overlays update
42+
43+
set_light_on(on)
44+
45+
for(var/X in actions)
46+
var/datum/action/A = X
47+
A.build_all_button_icons()
48+
1449
/obj/item/clothing/suit/space/hardsuit/infiltration
1550
name = "engineering hardsuit"
1651
icon_state = "hardsuit-engineering"

yogstation/code/modules/antagonists/infiltrator/objectives.dm

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,72 @@ GLOBAL_LIST_INIT(infiltrator_kidnap_areas, typecacheof(list(/area/shuttle/yogs/s
113113
/datum/objective/infiltrator/kidnap/check_completion()
114114
var/target_area = get_area(target.current)
115115
return QDELETED(target) || (target.current && (!target.current.ckey || target.current.suiciding)) || (considered_alive(target) && is_type_in_typecache(target_area, GLOB.infiltrator_kidnap_areas))
116+
117+
/datum/objective/infiltrator/escape_disguised //Sort of based on the escape with identity objective for changelings, most of the code is from that with modifications
118+
explanation_text = "Have one member of your team disguise as a crewmember using your chameleon kit, and escape on the shuttle while wearing their identification card."
119+
var/target_real_name
120+
var/target_missing_id
121+
122+
/datum/objective/infiltrator/escape_disguised/proc/potential_targets()
123+
var/list/possible_targets = list()
124+
for(var/datum/mind/M in SSticker.minds)
125+
if(!M || !considered_alive(M) || considered_afk(M) || !M.current || !M.current.client || !ishuman(M.current) || M.quiet_round)
126+
continue
127+
if(M.has_antag_datum(/datum/antagonist/infiltrator) || M.has_antag_datum(/datum/antagonist/traitor) || M.has_antag_datum(/datum/antagonist/nukeop))
128+
continue
129+
if(M.assigned_role in GLOB.command_positions)
130+
possible_targets[M] = 25
131+
else //Either command or crew, stealing IDs from security officers and then having to impersonate them on shuttle simply doesn't work well
132+
possible_targets[M] = 5
133+
return possible_targets
134+
135+
/datum/objective/infiltrator/escape_disguised/is_possible()
136+
return LAZYLEN(potential_targets())
137+
138+
/datum/objective/infiltrator/escape_disguised/find_target(dupe_search_range, blacklist)
139+
target = pickweight(potential_targets())
140+
update_explanation_text()
141+
return target
142+
143+
/datum/objective/infiltrator/escape_disguised/update_explanation_text()
144+
if(target && target.current)
145+
target_real_name = target.current.real_name
146+
explanation_text = "Have one member of your team disguise as [target.name], the [target.assigned_role] using your chameleon kit, and escape on the shuttle or an escape pod"
147+
var/mob/living/carbon/human/H
148+
if(ishuman(target.current))
149+
H = target.current
150+
if(H && H.get_id_name() != target_real_name)
151+
target_missing_id = 1
152+
else
153+
explanation_text += " while wearing their identification card"
154+
explanation_text += "."
155+
else
156+
explanation_text = "Free Objective"
157+
158+
/datum/objective/infiltrator/escape_disguised/check_completion()
159+
. = ..()
160+
if(completed)
161+
return TRUE
162+
if(!target || !target_real_name)
163+
return TRUE
164+
var/list/infiltrators = get_antag_minds(/datum/antagonist/infiltrator, TRUE)
165+
for(var/datum/mind/M in infiltrators)
166+
if(!considered_escaped(M))
167+
continue
168+
var/mob/living/carbon/human/H = M.current
169+
var/mob/living/carbon/human/T = target.current
170+
var/clothing = H.chameleon_item_actions.len //8 possible clothes: Head, suit, ears, glasses, uniform, shoes, gloves, backpack
171+
var/copied = TRUE
172+
for(var/datum/action/item_action/chameleon/change/V in H.chameleon_item_actions)
173+
if(!V.copying)
174+
clothing -= 1
175+
if(V.copy_target != T)
176+
clothing -= 1
177+
if(clothing<3) //Some leniency if you don't have the required clothes or your target isn't wearing many, but not complete leniency
178+
copied = FALSE
179+
break
180+
if(!copied)
181+
continue
182+
if(H.get_id_name() == target_real_name || target_missing_id)
183+
return TRUE
184+
return FALSE

0 commit comments

Comments
 (0)