Skip to content

Commit

Permalink
More Tot Secondary Objective Stuff
Browse files Browse the repository at this point in the history
Some sabotage machinery tweaks, re-adds the sleeper protocol objection, and ports monkiestation's "Tide Bug Department" objective.
  • Loading branch information
hyperjll committed Feb 28, 2025
1 parent 822328d commit d5584a3
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 4 deletions.
11 changes: 11 additions & 0 deletions code/__DEFINES/antagonists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,14 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list(
#define INFILTRATOR_FACTION_CORPORATE_CLIMBER "Corporate Climber"
#define INFILTRATOR_FACTION_ANIMAL_RIGHTS_CONSORTIUM "Animal Rights Consortium"
#define INFILTRATOR_FACTION_GORLEX_MARAUDERS "Gorlex Marauders"

/// For the tide bug secondary tot objective
#define TRAITOR_OBJECTIVE_BLACKLISTED_AREAS list(/area/station/engineering/hallway, \
/area/station/engineering/lobby, \
/area/station/engineering/storage, \
/area/station/science/lobby, \
/area/station/science/ordnance/bomb, \
/area/station/science/ordnance/freezerchamber, \
/area/station/science/ordnance/burnchamber, \
/area/station/security/prison, \
)
3 changes: 3 additions & 0 deletions code/__DEFINES/dcs/signals/signals_event.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@

/// Signal sent by round event controls when they create round event datums before calling setup() on them: (datum/round_event_control/source_event_control, datum/round_event/created_event)
#define COMSIG_CREATED_ROUND_EVENT "creating_round_event"

/// Sent when a T1de bug activates
#define COMSIG_GLOBAL_GREY_TIDE_TRAITOR "grey_tide_traitor"
8 changes: 6 additions & 2 deletions code/game/machinery/doors/airlock.dm
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,9 @@
RegisterSignal(src, COMSIG_MACHINERY_BROKEN, PROC_REF(on_break))

RegisterSignal(SSdcs, COMSIG_GLOB_GREY_TIDE, PROC_REF(grey_tide))
RegisterSignal(SSdcs, COMSIG_GLOBAL_GREY_TIDE_TRAITOR, PROC_REF(grey_tide)) // for tot objectives

/obj/machinery/door/airlock/proc/grey_tide(datum/source, list/grey_tide_areas)
/obj/machinery/door/airlock/proc/grey_tide(datum/source, list/grey_tide_areas, traitor_bug = FALSE)
SIGNAL_HANDLER

if(!is_station_level(z) || critical_machine)
Expand All @@ -198,7 +199,10 @@
for(var/area_type in grey_tide_areas)
if(!istype(get_area(src), area_type))
continue
INVOKE_ASYNC(src, PROC_REF(prison_open)) //Sleep gets called further down in open(), so we have to invoke async
if(traitor_bug)
INVOKE_ASYNC(src, PROC_REF(traitor_bug_tide))
else
INVOKE_ASYNC(src, PROC_REF(prison_open)) //Sleep gets called further down in open(), so we have to invoke async

/obj/machinery/door/airlock/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
if(id_tag)
Expand Down
14 changes: 12 additions & 2 deletions code/modules/antagonists/traitor/objectives/sabotage_machinery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ GLOBAL_DATUM_INIT(objective_machine_handler, /datum/objective_target_machine_han
/datum/traitor_objective_category/sabotage_machinery
name = "Sabotage Worksite"
objectives = list(
/datum/traitor_objective/sabotage_machinery/trap = 1,
/datum/traitor_objective/sabotage_machinery/destroy = 1,
/datum/traitor_objective/sabotage_machinery/trap = 3,
/datum/traitor_objective/sabotage_machinery/destroy = 3,
/datum/traitor_objective/sabotage_machinery/trap/rare = 1,
)
weight = OBJECTIVE_WEIGHT_DEFAULT

/datum/traitor_objective/sabotage_machinery
name = "Sabotage the %MACHINE%"
Expand Down Expand Up @@ -70,6 +72,14 @@ GLOBAL_DATUM_INIT(objective_machine_handler, /datum/objective_target_machine_han
applicable_jobs = list(
JOB_STATION_ENGINEER = /obj/machinery/telecomms/hub,
JOB_SCIENTIST = /obj/machinery/rnd/server,
JOB_ROBOTICIST = /obj/machinery/mecha_part_fabricator,
JOB_HEAD_OF_PERSONNEL = /obj/machinery/modular_computer/preset/id,
JOB_RESEARCH_DIRECTOR = /obj/machinery/computer/gateway_control,
JOB_CAPTAIN = /obj/machinery/teleport/station,
JOB_SECURITY_OFFICER = /obj/machinery/gulag_teleporter,
JOB_WARDEN = /obj/machinery/computer/security/labor,
JOB_QUARTERMASTER = /obj/machinery/computer/security/qm,
JOB_CHIEF_ENGINEER = /obj/machinery/computer/telecomms/monitor,
)

// Rig machines which are in public locations to explode when interacted with
Expand Down
2 changes: 2 additions & 0 deletions hypermods/_SIGNALS/traitor.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// Sent when a bug activates
#define COMSIG_TRAITOR_BUG_ACTIVATED "traitor_bug_activated"
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
name = "Sabotage the %MACHINE%"
description = "Destroy the %MACHINE% to cause disarray and disrupt the operations of the %JOB%'s department. If you can get another crew member to destroy the machine using the provided booby trap, you will be rewarded with an additional %PROGRESSION% reputation and %TC% telecrystals."

abstract_type = /datum/traitor_objective/sabotage_machinery/trap/rare
duplicate_type = /datum/traitor_objective/sabotage_machinery

progression_reward = list(5 MINUTES, 8 MINUTES)
telecrystal_reward = 2 // A reward, for tresspassing into hard-to-breach areas

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/datum/traitor_objective_category/sleeper_protocol
name = "Sleeper Protocol"
objectives = list(
/datum/traitor_objective/sleeper_protocol = 1,
/datum/traitor_objective/sleeper_protocol/everybody = 1,
)
weight = OBJECTIVE_WEIGHT_UNLIKELY

/datum/traitor_objective/sleeper_protocol
name = "Perform the sleeper protocol on a crewmember"
description = "Use the button below to materialize a surgery disk in your hand, where you'll then be able to perform the sleeper protocol on a crewmember. If the disk gets destroyed, the objective will fail. This will only work on living and sentient crewmembers."

progression_minimum = 0 MINUTES

progression_reward = list(8 MINUTES, 15 MINUTES)
telecrystal_reward = list(2, 3)

abstract_type = /datum/traitor_objective/sleeper_protocol

var/list/limited_to = list(
JOB_CHIEF_MEDICAL_OFFICER,
JOB_MEDICAL_DOCTOR,
JOB_PARAMEDIC,
JOB_ROBOTICIST,
)

var/obj/item/disk/surgery/sleeper_protocol/disk

var/mob/living/current_registered_mob

var/inverted_limitation = FALSE

/datum/traitor_objective/sleeper_protocol/generate_ui_buttons(mob/user)
var/list/buttons = list()
if(!disk)
buttons += add_ui_button("", "Clicking this will materialize the sleeper protocol surgery in your hand", "save", "summon_disk")
return buttons

/datum/traitor_objective/sleeper_protocol/ui_perform_action(mob/living/user, action)
switch(action)
if("summon_disk")
if(disk)
return
disk = new(user.drop_location())
user.put_in_hands(disk)
AddComponent(/datum/component/traitor_objective_register, disk, \
fail_signals = list(COMSIG_QDELETING))

/datum/traitor_objective/sleeper_protocol/proc/on_surgery_success(datum/source, datum/surgery_step/step, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results)
SIGNAL_HANDLER
if(istype(step, /datum/surgery_step/brainwash/sleeper_agent))
succeed_objective()

/datum/traitor_objective/sleeper_protocol/can_generate_objective(datum/mind/generating_for, list/possible_duplicates)
var/datum/job/job = generating_for.assigned_role
if(!(job.title in limited_to) && !inverted_limitation)
return FALSE
if((job.title in limited_to) && inverted_limitation)
return FALSE
if(length(possible_duplicates) > 0)
return FALSE
return TRUE

/datum/traitor_objective/sleeper_protocol/generate_objective(datum/mind/generating_for, list/possible_duplicates)
AddComponent(/datum/component/traitor_objective_mind_tracker, generating_for, \
signals = list(COMSIG_MOB_SURGERY_STEP_SUCCESS = PROC_REF(on_surgery_success)))
return TRUE

/datum/traitor_objective/sleeper_protocol/ungenerate_objective()
disk = null
/obj/item/disk/surgery/sleeper_protocol
name = "Suspicious Surgery Disk"
desc = "The disk provides instructions on how to turn someone into a sleeper agent for the Syndicate."
surgeries = list(/datum/surgery/advanced/brainwashing_sleeper)

/datum/traitor_objective/sleeper_protocol/everybody //Much harder for non-med and non-robo
progression_minimum = 30 MINUTES
progression_reward = list(8 MINUTES, 15 MINUTES)
telecrystal_reward = list(3, 5)

inverted_limitation = TRUE
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
/datum/traitor_objective_category/tide_bug_department
name = "Tide Bug Department"
objectives = list(
/datum/traitor_objective/tide_bug_department = 2,
/datum/traitor_objective/tide_bug_department/high_risk_department = 1,
)
weight = OBJECTIVE_WEIGHT_UNLIKELY

/datum/traitor_objective/tide_bug_department
name = "Disrupt the operations of %DEPARTMENT% by placing a T1de virus bug in %AREA%."
description = "Use the button below to materialize the T1de virus bug within your hand, where you'll then be able to place it in %AREA%. \
One minute after the bug is placed it will randomly open, bolt, and or electrify all airlocks in the department, \
if the bug is destroyed before this, the objective will fail."
progression_minimum = 10 MINUTES
progression_reward = list(5 MINUTES, 10 MINUTES)
telecrystal_reward = list(2, 3)

abstract_type = /datum/traitor_objective/tide_bug_department

///What departments can we pick from mapped to their base area type
var/list/valid_departments = list(/datum/job_department/cargo = /area/station/cargo,
/datum/job_department/medical = /area/station/medical,
/datum/job_department/science = /area/station/science,
/datum/job_department/engineering = /area/station/engineering) //service is too low security for them to be worth anything(sorry clown)
///The department chosen for this objective to target
var/datum/job_department/targeted_department
///The area chosen for this objective to target
var/area/targeted_area
///Have we sent them the bug yet
var/bug_sent = FALSE
///The areas affected by this bug
var/list/affected_areas

/datum/traitor_objective/tide_bug_department/high_risk_department
progression_minimum = 30 MINUTES
progression_reward = list(15 MINUTES, 20 MINUTES)
telecrystal_reward = list(3, 4)
valid_departments = list(/datum/job_department/command = /area/station/command,
/datum/job_department/security = /area/station/security)

/datum/traitor_objective/tide_bug_department/can_generate_objective(datum/mind/generating_for, list/possible_duplicates)
if(length(possible_duplicates))
return FALSE
return TRUE

/datum/traitor_objective/tide_bug_department/generate_objective(datum/mind/generating_for, list/possible_duplicates)
var/datum/job/role = generating_for.assigned_role
for(var/datum/traitor_objective/tide_bug_department/objective as anything in possible_duplicates)
valid_departments -= objective.targeted_department
for(var/datum/job_department/department as anything in role.departments_list) //breaking into your own department should not be an objective
valid_departments -= department

if(!length(valid_departments))
return FALSE

targeted_department = SSjob.joinable_departments_by_type[pick(valid_departments)]

var/list/valid_areas = typecacheof(valid_departments[targeted_department.type])
var/list/blacklisted_areas = typecacheof(TRAITOR_OBJECTIVE_BLACKLISTED_AREAS + /area/station/security/checkpoint) //sec checkpoint is fine for weakpoints but not tide bugs
affected_areas = GLOB.the_station_areas.Copy()
for(var/area/possible_area as anything in affected_areas)
if(is_type_in_typecache(possible_area, blacklisted_areas) || !is_type_in_typecache(possible_area, valid_areas) || initial(possible_area.outdoors))
affected_areas -= possible_area

if(!length(affected_areas))
return FALSE

targeted_area = pick(affected_areas)

replace_in_name("%DEPARTMENT%", targeted_department.department_name)
replace_in_name("%AREA%", initial(targeted_area.name))
return TRUE

/datum/traitor_objective/tide_bug_department/generate_ui_buttons(mob/user)
var/list/buttons = list()
if(!bug_sent)
buttons += add_ui_button("", "Pressing this will materialize a T1de virus bug in your hand.", "globe", "bug")
return buttons

/datum/traitor_objective/tide_bug_department/ui_perform_action(mob/user, action)
. = ..()
if(action == "bug")
if(bug_sent)
return
bug_sent = TRUE
var/obj/item/traitor_bug/bug = new(user.drop_location(), src)
user.put_in_hands(bug)
bug.balloon_alert(user, "The Tide virus bug materializes in your hand.")
AddComponent(/datum/component/traitor_objective_register, bug, \
succeed_signals = list(COMSIG_TRAITOR_BUG_ACTIVATED), \
fail_signals = list(COMSIG_QDELETING), \
penalty = telecrystal_penalty)
bug.objective_weakref = WEAKREF(src)

/obj/item/traitor_bug
///Weakref to our objective
var/datum/weakref/objective_weakref

/obj/item/traitor_bug/interact(mob/user)
. = ..()
var/datum/traitor_objective/tide_bug_department/resolved_objective = objective_weakref?.resolve()
if(!resolved_objective?.targeted_area)
return

var/turf/location = drop_location()
if(!location)
return

var/area/current_area = get_area(location)
if(!istype(current_area, resolved_objective.targeted_area))
balloon_alert(user, "you can't deploy this here!")
return

if(!do_after(user, deploy_time, src))
return

var/obj/structure/traitor_bug/new_bug = new(location)
new_bug.bug_item_ref = src
transfer_fingerprints_to(new_bug)
transfer_fibers_to(new_bug)
moveToNullspace() //this used to be handled by the objective completing as soon as this was planted, but due to needing to check for things after that its just easier to do it this way

/obj/structure/traitor_bug
name = "suspicious device"
desc = "It looks dangerous. Best you leave this alone."

anchored = TRUE

icon = 'hypermods/icons/obj/devices/syndie_gadget.dmi'
icon_state = "bug-animated"
/// Ref to our bug item
var/obj/item/traitor_bug/bug_item_ref

/obj/structure/traitor_bug/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(tide_department)), 60 SECONDS)

/obj/structure/traitor_bug/deconstruct(disassembled)
QDEL_NULL(bug_item_ref)
return ..()

/obj/structure/traitor_bug/proc/tide_department()
if(QDELETED(bug_item_ref))
return

SEND_SIGNAL(bug_item_ref, COMSIG_TRAITOR_BUG_ACTIVATED)

var/datum/traitor_objective/tide_bug_department/resolved_objective = bug_item_ref.objective_weakref?.resolve()
if(!resolved_objective?.affected_areas)
return

SEND_GLOBAL_SIGNAL(COMSIG_GLOBAL_GREY_TIDE_TRAITOR, resolved_objective.affected_areas, TRUE)

#define TIME_TO_UNBOLT 3 MINUTES
/obj/machinery/door/airlock/proc/traitor_bug_tide()
if((obj_flags & EMAGGED) || is_probably_external_airlock())
return

unbolt()
open()

//its random if it gets bolted or electrifried or not
if(prob(70))
bolt()

if(prob(30))
set_electrified(MACHINE_ELECTRIFIED_PERMANENT)

addtimer(CALLBACK(src, PROC_REF(unbolt)), TIME_TO_UNBOLT, TIMER_DELETE_ME) //unbolt the airlocks in 3 minutes

#undef TIME_TO_UNBOLT

/// Checks to see if the airlock, or any airlocks linked to it, are adjacent to
/// any tiles that have likely unsafe atmospheric conditions.
/obj/machinery/door/airlock/proc/is_probably_external_airlock()
. = FALSE
if(leads_to_space() || closeOther?.leads_to_space() || cyclelinkedairlock?.leads_to_space())
return TRUE
for(var/obj/machinery/door/airlock/other_door in close_others)
if(other_door.leads_to_space())
return TRUE

/// Checks to see if the door is adjacent to any tiles that have likely unsafe atmospheric conditions.
/obj/machinery/door/airlock/proc/leads_to_space()
var/turf/our_turf = get_turf(src)
if(QDELETED(our_turf))
return TRUE
for(var/turf/open/turf as anything in RANGE_TURFS(1, our_turf))
if(!istype(turf) || QDELING(turf) || turf.is_blocked_turf(exclude_mobs = TRUE, source_atom = src))
continue
if(isgroundlessturf(turf))
return TRUE
var/pressure = turf.return_air()?.return_pressure()
if(!pressure || !ISINRANGE_EX(pressure, HAZARD_LOW_PRESSURE, HAZARD_HIGH_PRESSURE))
return TRUE
return FALSE
Binary file modified hypermods/icons/obj/devices/syndie_gadget.dmi
Binary file not shown.
3 changes: 3 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -6564,6 +6564,7 @@
#include "hypermods\_DEFINES\mobs.dm"
#include "hypermods\_DEFINES\nanites.dm"
#include "hypermods\_SIGNALS\nanites.dm"
#include "hypermods\_SIGNALS\traitor.dm"
#include "hypermods\code\controllers\subsystem\dynamic\dynamic_rulesets_latejoin.dm"
#include "hypermods\code\controllers\subsystem\dynamic\dynamic_rulesets_midround.dm"
#include "hypermods\code\controllers\subsystem\dynamic\dynamic_rulesets_roundstart.dm"
Expand Down Expand Up @@ -6762,6 +6763,8 @@
#include "hypermods\code\modules\antagonists\ninja\energy_net_nets.dm"
#include "hypermods\code\modules\antagonists\traitor\final_objective\cyborg_rift.dm"
#include "hypermods\code\modules\antagonists\traitor\objectives\sabotage_machinery.dm"
#include "hypermods\code\modules\antagonists\traitor\objectives\sleeper_protocol.dm"
#include "hypermods\code\modules\antagonists\traitor\objectives\tide_bug_department.dm"
#include "hypermods\code\modules\antagonists\werewolf\bodyparts.dm"
#include "hypermods\code\modules\antagonists\werewolf\organs.dm"
#include "hypermods\code\modules\antagonists\werewolf\species.dm"
Expand Down

0 comments on commit d5584a3

Please sign in to comment.