[MIRROR] Removes bug room objective, Reworks primary objective and steal objectives. [MDB IGNORE] (#19819)

* Removes bug room objective, Reworks primary objective and steal objectives.

* ???

* fix

* Delete bug_room.dm

---------

Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-03-15 00:47:07 +00:00
committed by GitHub
co-authored by Watermelon914 Gandalf
parent 30bdf00da2
commit f7e6ea19e1
13 changed files with 303 additions and 456 deletions
+19 -4
View File
@@ -252,6 +252,21 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list(
// Progression traitor defines
/// Chance that the traitor could roll hijack if the pop limit is met.
#define HIJACK_PROB 10
/// Hijack is unavailable as a random objective below this player count.
#define HIJACK_MIN_PLAYERS 30
/// Chance the traitor gets a martyr objective instead of having to escape alive, as long as all the objectives are martyr compatible.
#define MARTYR_PROB 20
/// Chance the traitor gets a kill objective. If this prob fails, they will get a steal objective instead.
#define KILL_PROB 50
/// If a kill objective is rolled, chance that it is to destroy the AI.
#define DESTROY_AI_PROB(denominator) (100 / denominator)
/// If the destroy AI objective doesn't roll, chance that we'll get a maroon instead. If this prob fails, they will get a generic assassinate objective instead.
#define MAROON_PROB 30
/// How many telecrystals a normal traitor starts with
#define TELECRYSTALS_DEFAULT 20
/// How many telecrystals mapper/admin only "precharged" uplink implant
@@ -280,11 +295,11 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list(
#define OBJECTIVE_STATE_INVALID 5
/// Weights for traitor objective categories
#define OBJECTIVE_WEIGHT_TINY 5
#define OBJECTIVE_WEIGHT_SMALL 7
#define OBJECTIVE_WEIGHT_VERY_UNLIKELY 2
#define OBJECTIVE_WEIGHT_UNLIKELY 5
#define OBJECTIVE_WEIGHT_DEFAULT 10
#define OBJECTIVE_WEIGHT_BIG 15
#define OBJECTIVE_WEIGHT_HUGE 20
#define OBJECTIVE_WEIGHT_LIKELY 15
#define OBJECTIVE_WEIGHT_VERY_LIKELY 20
#define REVENANT_NAME_FILE "revenant_names.json"
+91 -32
View File
@@ -1,4 +1,6 @@
#define ADD_STEAL_ITEM(Source, Type) GLOB.steal_item_handler.objectives_by_path[Type] += Source
/proc/add_item_to_steal(source, type)
GLOB.steal_item_handler.objectives_by_path[type] += source
return type
//Contains the target item datums for Steal objectives.
/datum/objective_item
@@ -60,11 +62,11 @@
return ..()
// Low risk steal objectives
/datum/objective_item/steal/low_risk
/datum/objective_item/steal/traitor
objective_type = OBJECTIVE_ITEM_TYPE_TRAITOR
// Unique-ish low risk objectives
/datum/objective_item/steal/low_risk/bartender_shotgun
/datum/objective_item/steal/traitor/bartender_shotgun
name = "the bartender's shotgun"
targetitem = /obj/item/gun/ballistic/shotgun/doublebarrel
excludefromjob = list(JOB_BARTENDER)
@@ -72,10 +74,9 @@
exists_on_map = TRUE
/obj/item/gun/ballistic/shotgun/doublebarrel/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/gun/ballistic/shotgun/doublebarrel)
return add_item_to_steal(src, /obj/item/gun/ballistic/shotgun/doublebarrel)
// No item owner, list would be so long as to be functionally useless and they're in two very disparate locations on most maps
/datum/objective_item/steal/low_risk/fireaxe
/datum/objective_item/steal/traitor/fireaxe
name = "a fire axe"
targetitem = /obj/item/fireaxe
excludefromjob = list(
@@ -92,9 +93,9 @@
exists_on_map = TRUE
/obj/item/fireaxe/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/fireaxe)
return add_item_to_steal(src, /obj/item/fireaxe)
/datum/objective_item/steal/low_risk/big_crowbar
/datum/objective_item/steal/traitor/big_crowbar
name = "a mech removal tool"
targetitem = /obj/item/crowbar/mechremoval
excludefromjob = list(
@@ -106,9 +107,9 @@
exists_on_map = TRUE
/obj/item/crowbar/mechremoval/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/crowbar/mechremoval)
return add_item_to_steal(src, /obj/item/crowbar/mechremoval)
/datum/objective_item/steal/low_risk/nullrod
/datum/objective_item/steal/traitor/nullrod
name = "the chaplain's null rod"
targetitem = /obj/item/nullrod
excludefromjob = list(JOB_CHAPLAIN)
@@ -116,15 +117,49 @@
exists_on_map = TRUE
/obj/item/nullrod/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/nullrod)
return add_item_to_steal(src, /obj/item/nullrod)
/datum/objective_item/steal/low_risk/clown_shoes
/datum/objective_item/steal/traitor/clown_shoes
name = "the clown's shoes"
targetitem = /obj/item/clothing/shoes/clown_shoes
excludefromjob = list(JOB_CLOWN, JOB_CARGO_TECHNICIAN, JOB_QUARTERMASTER)
item_owner = list(JOB_CLOWN)
/datum/objective_item/steal/low_risk/cargo_budget
/datum/objective_item/steal/traitor/det_revolver
name = "detective's revolver"
targetitem = /obj/item/gun/ballistic/revolver/c38/detective
excludefromjob = list(JOB_DETECTIVE)
exists_on_map = TRUE
/obj/item/gun/ballistic/revolver/c38/detective/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/gun/ballistic/revolver/c38/detective)
/datum/objective_item/steal/traitor/chief_engineer_belt
name = "the chief engineer's belt"
targetitem = /obj/item/storage/belt/utility/chief
excludefromjob = list(JOB_CHIEF_ENGINEER)
exists_on_map = TRUE
/obj/item/storage/belt/utility/chief/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/storage/belt/utility/chief)
/datum/objective_item/steal/traitor/telebaton
name = "a head of staff's telescopic baton"
targetitem = /obj/item/melee/baton/telescopic
excludefromjob = list(
JOB_RESEARCH_DIRECTOR,
JOB_CAPTAIN,
JOB_HEAD_OF_SECURITY,
JOB_HEAD_OF_PERSONNEL,
JOB_CHIEF_ENGINEER,
JOB_CHIEF_MEDICAL_OFFICER
)
exists_on_map = TRUE
/obj/item/melee/baton/telescopic/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/melee/baton/telescopic)
/datum/objective_item/steal/traitor/cargo_budget
name = "cargo's departmental budget"
targetitem = /obj/item/card/id/departmental_budget/car
excludefromjob = list(JOB_QUARTERMASTER, JOB_CARGO_TECHNICIAN)
@@ -132,7 +167,32 @@
exists_on_map = TRUE
/obj/item/card/id/departmental_budget/car/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/card/id/departmental_budget/car)
return add_item_to_steal(src, /obj/item/card/id/departmental_budget/car)
/datum/objective_item/steal/traitor/captain_modsuit
name = "the captain's magnate MOD control unit"
targetitem = /obj/item/mod/control/pre_equipped/magnate
excludefromjob = list(JOB_CAPTAIN)
exists_on_map = TRUE
/obj/item/mod/control/pre_equipped/magnate/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/mod/control/pre_equipped/magnate)
/datum/objective_item/steal/traitor/captain_spare
name = "the captain's spare ID"
targetitem = /obj/item/card/id/advanced/gold/captains_spare
excludefromjob = list(
JOB_RESEARCH_DIRECTOR,
JOB_CAPTAIN,
JOB_HEAD_OF_SECURITY,
JOB_HEAD_OF_PERSONNEL,
JOB_CHIEF_ENGINEER,
JOB_CHIEF_MEDICAL_OFFICER
)
exists_on_map = TRUE
/obj/item/card/id/advanced/gold/captains_spare/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/card/id/advanced/gold/captains_spare)
// High risk steal objectives
@@ -144,7 +204,7 @@
exists_on_map = TRUE
/obj/item/gun/energy/laser/captain/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/gun/energy/laser/captain)
return add_item_to_steal(src, /obj/item/gun/energy/laser/captain)
/datum/objective_item/steal/hoslaser
name = "the head of security's personal laser gun"
@@ -154,7 +214,7 @@
exists_on_map = TRUE
/obj/item/gun/energy/e_gun/hos/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/gun/energy/e_gun/hos)
return add_item_to_steal(src, /obj/item/gun/energy/e_gun/hos)
/datum/objective_item/steal/handtele
name = "a hand teleporter"
@@ -164,7 +224,7 @@
exists_on_map = TRUE
/obj/item/hand_tele/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/hand_tele)
return add_item_to_steal(src, /obj/item/hand_tele)
/datum/objective_item/steal/jetpack
name = "the Captain's jetpack"
@@ -174,7 +234,7 @@
exists_on_map = TRUE
/obj/item/tank/jetpack/oxygen/captain/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/tank/jetpack/oxygen/captain)
return add_item_to_steal(src, /obj/item/tank/jetpack/oxygen/captain)
/datum/objective_item/steal/magboots
name = "the chief engineer's advanced magnetic boots"
@@ -184,7 +244,7 @@
exists_on_map = TRUE
/obj/item/clothing/shoes/magboots/advance/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/clothing/shoes/magboots/advance)
return add_item_to_steal(src, /obj/item/clothing/shoes/magboots/advance)
/datum/objective_item/steal/capmedal
name = "the medal of captaincy"
@@ -194,7 +254,7 @@
exists_on_map = TRUE
/obj/item/clothing/accessory/medal/gold/captain/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/clothing/accessory/medal/gold/captain)
return add_item_to_steal(src, /obj/item/clothing/accessory/medal/gold/captain)
/datum/objective_item/steal/hypo
//name = "the hypospray" // ORIGINAL
@@ -205,16 +265,17 @@
item_owner = list(JOB_CHIEF_MEDICAL_OFFICER)
exists_on_map = TRUE
///obj/item/reagent_containers/hypospray/cmo/add_stealing_item_objective() // ORIGINAL
/obj/item/hypospray/mkii/cmo/add_stealing_item_objective() // SKYRAT EDIT CHANGE
//ADD_STEAL_ITEM(src, /obj/item/reagent_containers/hypospray/cmo) // ORIGINAL
ADD_STEAL_ITEM(src, /obj/item/hypospray/mkii/cmo) // SKYRAT EDIT CHANGE
return add_item_to_steal(src, /obj/item/hypospray/mkii/cmo) // SKYRAT EDIT CHANGE
/datum/objective_item/steal/nukedisc
name = "the nuclear authentication disk"
targetitem = /obj/item/disk/nuclear
excludefromjob = list(JOB_CAPTAIN)
/obj/item/disk/nuclear/add_stealing_item_objective()
return add_item_to_steal(src, /obj/item/disk/nuclear)
/datum/objective_item/steal/nukedisc/check_special_completion(obj/item/disk/nuclear/N)
return !N.fake
@@ -226,7 +287,7 @@
exists_on_map = TRUE
/obj/item/clothing/suit/hooded/ablative/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/clothing/suit/hooded/ablative)
return add_item_to_steal(src, /obj/item/clothing/suit/hooded/ablative)
/datum/objective_item/steal/reactive
name = "the reactive teleport armor"
@@ -236,7 +297,7 @@
exists_on_map = TRUE
/obj/item/clothing/suit/armor/reactive/teleport/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/clothing/suit/armor/reactive/teleport)
return add_item_to_steal(src, /obj/item/clothing/suit/armor/reactive/teleport)
/datum/objective_item/steal/documents
name = "any set of secret documents of any organization"
@@ -244,7 +305,7 @@
exists_on_map = TRUE
/obj/item/documents/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/documents) //Any set of secret documents. Doesn't have to be NT's
return add_item_to_steal(src, /obj/item/documents) //Any set of secret documents. Doesn't have to be NT's
/datum/objective_item/steal/nuke_core
name = "the heavily radioactive plutonium core from the onboard self-destruct"
@@ -253,7 +314,7 @@
exists_on_map = TRUE
/obj/item/nuke_core/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/nuke_core)
return add_item_to_steal(src, /obj/item/nuke_core)
/datum/objective_item/steal/nuke_core/New()
special_equipment += /obj/item/storage/box/syndie_kit/nuke
@@ -267,7 +328,7 @@
exists_on_map = TRUE
/obj/item/computer_disk/hdd_theft/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/computer_disk/hdd_theft)
return add_item_to_steal(src, /obj/item/computer_disk/hdd_theft)
/datum/objective_item/steal/hdd_extraction/New()
special_equipment += /obj/item/paper/guides/antag/hdd_extraction
@@ -324,7 +385,7 @@
exists_on_map = TRUE
/obj/item/areaeditor/blueprints/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/areaeditor/blueprints)
return add_item_to_steal(src, /obj/item/areaeditor/blueprints)
/datum/objective_item/steal/blueprints/check_special_completion(obj/item/I)
if(istype(I, /obj/item/areaeditor/blueprints))
@@ -342,6 +403,4 @@
exists_on_map = TRUE
/obj/item/blackbox/add_stealing_item_objective()
ADD_STEAL_ITEM(src, /obj/item/blackbox)
#undef ADD_STEAL_ITEM
return add_item_to_steal(src, /obj/item/blackbox)
+1 -3
View File
@@ -254,8 +254,6 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_ITEM, src)
if(LAZYLEN(embedding))
updateEmbedding()
if(mapload && !GLOB.steal_item_handler.generated_items)
add_stealing_item_objective()
/obj/item/Destroy(force)
// This var exists as a weird proxy "owner" ref
@@ -313,7 +311,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
LAZYREMOVE(actions, action)
qdel(action)
/// Called if this item is supposed to be a steal objective item objective. Only done at mapload
/// Called if this item is supposed to be a steal objective item objective.
/obj/item/proc/add_stealing_item_objective()
return
@@ -35,6 +35,9 @@
var/uplink_sale_count = 3
///the final objective the traitor has to accomplish, be it escaping, hijacking, or just martyrdom.
var/datum/objective/ending_objective
/datum/antagonist/traitor/New(give_objectives = TRUE)
. = ..()
src.give_objectives = give_objectives
@@ -53,10 +56,10 @@
else
uplink_handler = uplink.uplink_handler
uplink_handler.primary_objectives = objectives
uplink_handler.has_progression = progression_enabled
uplink_handler.has_progression = TRUE
SStraitor.register_uplink_handler(uplink_handler)
uplink_handler.has_objectives = progression_enabled //SKYRAT EDIT
uplink_handler.has_objectives = TRUE
uplink_handler.generate_objectives()
if(uplink_handler.progression_points < SStraitor.current_global_progression)
@@ -72,8 +75,10 @@
uplink_items += item
continue
uplink_handler.extra_purchasable += create_uplink_sales(uplink_sale_count, /datum/uplink_category/discounts, 1, uplink_items)
if(give_objectives && progression_enabled) //SKYRAT EDIT - progression_enabled
if(give_objectives)
forge_traitor_objectives()
forge_ending_objective()
pick_employer()
@@ -144,6 +149,11 @@
possible_employers.Add(GLOB.syndicate_employers, GLOB.nanotrasen_employers)
if(istype(ending_objective, /datum/objective/hijack))
possible_employers -= GLOB.normal_employers
else //escape or martyrdom
possible_employers -= GLOB.hijack_employers
switch(faction)
if(FLAVOR_FACTION_SYNDICATE)
possible_employers -= GLOB.nanotrasen_employers
@@ -152,33 +162,74 @@
employer = pick(possible_employers)
traitor_flavor = strings(TRAITOR_FLAVOR_FILE, employer)
/// Generates a complete set of traitor objectives up to the traitor objective limit, including non-generic objectives such as martyr and hijack.
/datum/antagonist/traitor/proc/forge_traitor_objectives()
objectives.Cut()
var/objective_count = 0
if((GLOB.joined_player_list.len >= HIJACK_MIN_PLAYERS) && prob(HIJACK_PROB))
is_hijacker = TRUE
objective_count++
var/list/kill_targets = list() //for blacklisting already-set targets
var/objective_limit = CONFIG_GET(number/traitor_objectives_amount)
for(var/i in 1 to objective_limit)
var/list/ai_targets = active_ais(z = 2) //For multiZ stations, this proc will include AIs on all station levels if the provided arg is 2.
ai_targets -= kill_targets
if(ai_targets.len)
var/diceroll = rand(1, (living_player_count() - 1)) //AI kill and crew kill objectives are different, but I want a rough equal chance for AIs to be targets. Maybe I'll refractor this someday
if(diceroll <= ai_targets.len)
var/datum/objective/task = new /datum/objective/destroy()
task.owner = owner
task.find_target(blacklist = kill_targets)
kill_targets += task.target
objectives += task
continue
var/datum/objective/task = new /datum/objective/assassinate()
task.owner = owner
task.find_target(blacklist = kill_targets)
kill_targets += task.target
objectives += task
// for(in...to) loops iterate inclusively, so to reach objective_limit we need to loop to objective_limit - 1
// This does not give them 1 fewer objectives than intended.
for(var/i in objective_count to objective_limit - 1)
objectives += forge_single_generic_objective()
var/datum/objective/escape/bye = new /datum/objective/escape()
objectives += bye
bye.owner = owner
/**
* ## forge_ending_objective
*
* Forges the endgame objective and adds it to this datum's objective list.
*/
/datum/antagonist/traitor/proc/forge_ending_objective()
if(is_hijacker)
ending_objective = new /datum/objective/hijack
ending_objective.owner = owner
return
var/martyr_compatibility = TRUE
for(var/datum/objective/traitor_objective in objectives)
if(!traitor_objective.martyr_compatible)
martyr_compatibility = FALSE
break
if(martyr_compatibility && prob(MARTYR_PROB))
ending_objective = new /datum/objective/martyr
ending_objective.owner = owner
objectives += ending_objective
return
ending_objective = new /datum/objective/escape
ending_objective.owner = owner
objectives += ending_objective
/datum/antagonist/traitor/proc/forge_single_generic_objective()
if(prob(KILL_PROB))
var/list/active_ais = active_ais()
if(active_ais.len && prob(DESTROY_AI_PROB(GLOB.joined_player_list.len)))
var/datum/objective/destroy/destroy_objective = new()
destroy_objective.owner = owner
destroy_objective.find_target()
return destroy_objective
if(prob(MAROON_PROB))
var/datum/objective/maroon/maroon_objective = new()
maroon_objective.owner = owner
maroon_objective.find_target()
return maroon_objective
var/datum/objective/assassinate/kill_objective = new()
kill_objective.owner = owner
kill_objective.find_target()
return kill_objective
var/datum/objective/steal/steal_objective = new()
steal_objective.owner = owner
steal_objective.find_target()
return steal_objective
/datum/antagonist/traitor/apply_innate_effects(mob/living/mob_override)
. = ..()
@@ -240,16 +291,11 @@
if(objectives.len) //If the traitor had no objectives, don't need to process this.
var/count = 1
for(var/datum/objective/objective in objectives)
// SKYRAT EDIT START - No greentext
/*
if(objective.check_completion())
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_greentext("Success!")]"
else
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_redtext("Fail.")]"
traitor_won = FALSE
*/
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text]"
// SKYRAT EDIT END - No greentext
count++
if(uplink_handler.final_objective)
objectives_text += "<br>[span_greentext("[traitor_won ? "Additionally" : "However"], the final objective \"[uplink_handler.final_objective]\" was completed!")]"
@@ -267,15 +313,8 @@
result += objectives_text
if(uplink_handler)
var/completed_objectives_text = "Completed Uplink Objectives: "
for(var/datum/traitor_objective/objective as anything in uplink_handler.completed_objectives)
if(objective.objective_state == OBJECTIVE_STATE_COMPLETED)
completed_objectives_text += "<br><B>[objective.name]</B> - ([objective.telecrystal_reward] TC, [DISPLAY_PROGRESSION(objective.progression_reward)] Reputation)"
result += completed_objectives_text
result += "<br>The traitor had a total of [DISPLAY_PROGRESSION(uplink_handler.progression_points)] Reputation and [uplink_handler.telecrystals] Unused Telecrystals."
// SKYRAT EDIT REMOVAL
/*
var/special_role_text = lowertext(name)
if(traitor_won)
@@ -283,7 +322,6 @@
else
result += span_redtext("The [special_role_text] has failed!")
SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg')
*/
return result.Join("<br>")
@@ -1,210 +0,0 @@
/datum/traitor_objective_category/bug_room
name = "Bug Room"
objectives = list(
/datum/traitor_objective/bug_room = 1,
/datum/traitor_objective/bug_room/risky = 1,
/datum/traitor_objective/bug_room/super_risky = 1,
)
/datum/traitor_objective/bug_room
name = "Bug the %DEPARTMENT HEAD%'s office"
description = "Use the button below to materialize the bug within your hand, \
where you'll then be able to place it down in the %DEPARTMENT HEAD%'s office. \
If it gets destroyed before you are able to plant it, this objective will fail. \
Remember, planting the bug may leave behind fibers and fingerprints - \
be sure to clean it off with soap (or similar) to be safe!"
progression_reward = list(2 MINUTES, 8 MINUTES)
telecrystal_reward = list(0, 1)
progression_minimum = 0 MINUTES
progression_maximum = 30 MINUTES
var/list/applicable_heads = list(
JOB_RESEARCH_DIRECTOR = /area/station/command/heads_quarters/rd,
JOB_CHIEF_MEDICAL_OFFICER = /area/station/command/heads_quarters/cmo,
JOB_CHIEF_ENGINEER = /area/station/command/heads_quarters/ce,
JOB_HEAD_OF_PERSONNEL = /area/station/command/heads_quarters/hop,
JOB_CAPTAIN = /area/station/command/heads_quarters/captain, // For head roles so that they can still get this objective.
JOB_QUARTERMASTER = /area/station/command/heads_quarters/qm,
)
var/datum/job/target_office
var/requires_head_as_supervisor = TRUE
var/obj/item/traitor_bug/bug
/datum/traitor_objective/bug_room/risky
progression_minimum = 10 MINUTES
progression_maximum = 40 MINUTES
applicable_heads = list(
JOB_CAPTAIN = /area/station/command/heads_quarters/captain,
)
progression_reward = list(5 MINUTES, 10 MINUTES)
telecrystal_reward = list(1, 2)
requires_head_as_supervisor = FALSE
/datum/traitor_objective/bug_room/super_risky
progression_minimum = 20 MINUTES
progression_maximum = 60 MINUTES
applicable_heads = list(
JOB_HEAD_OF_SECURITY = /area/station/command/heads_quarters/hos,
)
progression_reward = list(10 MINUTES, 15 MINUTES)
telecrystal_reward = list(2, 3)
requires_head_as_supervisor = FALSE
/datum/traitor_objective/bug_room/super_risky/generate_objective(datum/mind/generating_for, list/possible_duplicates)
if(!handler.get_completion_count(/datum/traitor_objective/bug_room/risky))
// Locked if they don't have any of the risky bug room objective completed
return FALSE
return ..()
/datum/traitor_objective/bug_room/generate_ui_buttons(mob/user)
var/list/buttons = list()
if(!bug)
buttons += add_ui_button("", "Pressing this will materialize a bug in your hand, which you can place at the target office", "wifi", "summon_gear")
return buttons
/datum/traitor_objective/bug_room/ui_perform_action(mob/living/user, action)
. = ..()
switch(action)
if("summon_gear")
if(bug)
return
bug = new(user.drop_location())
user.put_in_hands(bug)
bug.balloon_alert(user, "the bug materializes in your hand")
bug.target_area_type = applicable_heads[target_office.title]
AddComponent(/datum/component/traitor_objective_register, bug, \
succeed_signals = list(COMSIG_TRAITOR_BUG_PLANTED_GROUND), \
fail_signals = list(COMSIG_PARENT_QDELETING), \
penalty = TRUE)
/datum/traitor_objective/bug_room/generate_objective(datum/mind/generating_for, list/possible_duplicates)
var/datum/job/role = generating_for.assigned_role
var/list/possible_heads
if(requires_head_as_supervisor)
possible_heads = applicable_heads & role.department_head
else
possible_heads = applicable_heads
for(var/datum/traitor_objective/bug_room/room as anything in possible_duplicates)
possible_heads -= room.target_office.title
if(!length(possible_heads))
return FALSE
var/target_head = pick(possible_heads)
target_office = SSjob.name_occupations[target_head]
replace_in_name("%DEPARTMENT HEAD%", target_head)
return TRUE
/datum/traitor_objective/bug_room/ungenerate_objective()
bug = null
/obj/item/traitor_bug
name = "suspicious device"
desc = "It looks dangerous."
item_flags = EXAMINE_SKIP
icon = 'icons/obj/weapons/items_and_weapons.dmi'
icon_state = "bug"
/// The area at which this bug can be planted at. Has to be a type.
var/area/target_area_type
/// The object on which this bug can be planted on. Has to be a type.
var/obj/target_object_type
/// The object this bug is currently planted on.
var/obj/planted_on
/// The time it takes to place this bug.
var/deploy_time = 10 SECONDS
/obj/item/traitor_bug/examine(mob/user)
. = ..()
if(planted_on)
return
if(user.mind?.has_antag_datum(/datum/antagonist/traitor))
if(target_area_type)
. += span_notice("This device must be placed by <b>using it in hand</b> inside the <b>[initial(target_area_type.name)]</b>.")
else if(target_object_type)
. += span_notice("This device must be placed by <b>clicking on the [initial(target_object_type.name)]</b> with it.")
. += span_notice("Remember, you may leave behind fingerprints or fibers on the device. Use <b>soap</b> or similar to scrub it clean to be safe!")
/obj/item/traitor_bug/interact(mob/user)
. = ..()
if(!target_area_type)
return
var/turf/location = drop_location()
if(!location)
return
var/area/current_area = get_area(location)
if(!istype(current_area, target_area_type))
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)
transfer_fingerprints_to(new_bug)
transfer_fibers_to(new_bug)
SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PLANTED_GROUND, location)
qdel(src)
/obj/item/traitor_bug/afterattack(atom/movable/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!target_object_type)
return
if(!user.Adjacent(target))
return
. |= AFTERATTACK_PROCESSED_ITEM
var/result = SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PRE_PLANTED_OBJECT, target)
if(!(result & COMPONENT_FORCE_PLACEMENT))
if(result & COMPONENT_FORCE_FAIL_PLACEMENT || !istype(target, target_object_type))
balloon_alert(user, "you can't attach this onto here!")
return
if(!do_after(user, deploy_time, src))
return
if(planted_on)
return
forceMove(target)
target.vis_contents += src
vis_flags |= VIS_INHERIT_PLANE
planted_on = target
RegisterSignal(planted_on, COMSIG_PARENT_QDELETING, PROC_REF(handle_planted_on_deletion))
SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PLANTED_OBJECT, target)
/obj/item/traitor_bug/proc/handle_planted_on_deletion()
planted_on = null
/obj/item/traitor_bug/Destroy()
if(planted_on)
vis_flags &= ~VIS_INHERIT_PLANE
planted_on.vis_contents -= src
return ..()
/obj/item/traitor_bug/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
. = ..()
if(planted_on)
vis_flags &= ~VIS_INHERIT_PLANE
planted_on.vis_contents -= src
anchored = FALSE
UnregisterSignal(planted_on, COMSIG_PARENT_QDELETING)
planted_on = null
/obj/structure/traitor_bug
name = "suspicious device"
desc = "It looks dangerous. Best you leave this alone."
anchored = TRUE
icon = 'icons/obj/weapons/items_and_weapons.dmi'
icon_state = "bug-animated"
/obj/structure/traitor_bug/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(fade_out), 10 SECONDS), 3 MINUTES)
/obj/structure/traitor_bug/proc/fade_out(seconds)
animate(src, alpha = 30, time = seconds)
/obj/structure/traitor_bug/deconstruct(disassembled)
explosion(src, light_impact_range = 2, flame_range = 5, explosion_cause = src) // Pretty god damn dangerous
return ..()
@@ -8,7 +8,7 @@
/datum/traitor_objective/demoralise/poster = 2,
/datum/traitor_objective/demoralise/graffiti = 1,
)
weight = OBJECTIVE_WEIGHT_TINY
weight = OBJECTIVE_WEIGHT_UNLIKELY
/datum/traitor_objective/demoralise
name = "Debug your code."
@@ -19,10 +19,10 @@
telecrystal_reward = 1
possible_items = list(
/datum/objective_item/steal/low_risk/bartender_shotgun,
/datum/objective_item/steal/low_risk/fireaxe,
/datum/objective_item/steal/low_risk/big_crowbar,
/datum/objective_item/steal/low_risk/nullrod,
/datum/objective_item/steal/traitor/bartender_shotgun,
/datum/objective_item/steal/traitor/fireaxe,
/datum/objective_item/steal/traitor/nullrod,
/datum/objective_item/steal/traitor/big_crowbar,
)
/datum/traitor_objective/destroy_item/very_risky
@@ -4,7 +4,7 @@
/datum/traitor_objective/eyesnatching = 1,
/datum/traitor_objective/eyesnatching/heads = 1,
)
weight = OBJECTIVE_WEIGHT_TINY
weight = OBJECTIVE_WEIGHT_UNLIKELY
/datum/traitor_objective/eyesnatching
name = "Steal the eyes of %TARGET% the %JOB TITLE%"
@@ -3,7 +3,7 @@
objectives = list(
/datum/traitor_objective/locate_weakpoint = 1,
)
weight = OBJECTIVE_WEIGHT_TINY
weight = OBJECTIVE_WEIGHT_UNLIKELY
/datum/traitor_objective/locate_weakpoint
name = "Triangulate station's structural weakpoint and detonate an explosive charge nearby."
@@ -8,16 +8,15 @@
/datum/traitor_objective/steal_item/somewhat_risky = 1,
list(
/datum/traitor_objective/destroy_item/very_risky = 1,
/datum/traitor_objective/steal_item/risky = 1,
/datum/traitor_objective/steal_item/very_risky = 1,
) = 1,
/datum/traitor_objective/steal_item/very_risky = 1,
/datum/traitor_objective/steal_item/most_risky = 1
)
GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
/datum/objective_item_handler
var/list/objectives_by_path
var/list/list/objectives_by_path
var/generated_items = FALSE
/datum/objective_item_handler/New()
@@ -26,25 +25,42 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
for(var/datum/objective_item/item as anything in subtypesof(/datum/objective_item))
objectives_by_path[initial(item.targetitem)] = list()
RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(save_items))
RegisterSignal(SSdcs, COMSIG_GLOB_NEW_ITEM, PROC_REF(new_item_created))
/datum/objective_item_handler/proc/new_item_created(datum/source, obj/item/item)
SIGNAL_HANDLER
if(!generated_items)
item.add_stealing_item_objective()
return
var/typepath = item.add_stealing_item_objective()
if(typepath != null)
register_item(item, typepath)
/// Registers all items that are potentially stealable and removes ones that aren't.
/// We still need to do things this way because on mapload, items may not be on the station until everything has finished loading.
/datum/objective_item_handler/proc/save_items()
SIGNAL_HANDLER
for(var/obj/item/typepath as anything in objectives_by_path)
for(var/obj/item/object as anything in objectives_by_path[typepath])
var/turf/place = get_turf(object)
if(!place || !is_station_level(place.z))
objectives_by_path[typepath] -= object
continue
RegisterSignal(object, COMSIG_PARENT_QDELETING, PROC_REF(remove_item))
var/list/obj_by_path_cache = objectives_by_path[typepath].Copy()
for(var/obj/item/object as anything in obj_by_path_cache)
register_item(object, typepath)
generated_items = TRUE
/datum/objective_item_handler/proc/register_item(atom/object, typepath)
var/turf/place = get_turf(object)
if(!place || !is_station_level(place.z))
objectives_by_path[typepath] -= object
return
RegisterSignal(object, COMSIG_PARENT_QDELETING, PROC_REF(remove_item))
/datum/objective_item_handler/proc/remove_item(atom/source)
SIGNAL_HANDLER
for(var/typepath in objectives_by_path)
objectives_by_path[typepath] -= source
/datum/traitor_objective/steal_item
name = "Steal %ITEM% and place a bug on it."
description = "Use the button below to materialize the bug within your hand, where you'll then be able to place it on the item. Additionally, you can keep it near you for %TIME% minutes, and you will be rewarded with %PROGRESSION% reputation and %TC% telecrystals."
name = "Steal %ITEM% and place a schematics scanner on it."
description = "Use the button below to materialize the schematic scanner within your hand, where you'll then be able to place it on the item. Additionally, you can keep it near you and let it scan for %TIME% minutes, and you will be rewarded with %PROGRESSION% reputation and %TC% telecrystals."
progression_minimum = 20 MINUTES
@@ -79,54 +95,37 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
minutes_per_telecrystal = 6
possible_items = list(
/datum/objective_item/steal/low_risk/cargo_budget,
/datum/objective_item/steal/low_risk/clown_shoes,
/datum/objective_item/steal/traitor/cargo_budget,
/datum/objective_item/steal/traitor/clown_shoes,
)
/datum/traitor_objective/steal_item/somewhat_risky
progression_minimum = 20 MINUTES
progression_reward = 5 MINUTES
telecrystal_reward = 1
possible_items = list(
/datum/objective_item/steal/magboots,
/datum/objective_item/steal/hypo,
/datum/objective_item/steal/reactive,
/datum/objective_item/steal/handtele,
/datum/objective_item/steal/blueprints,
)
/datum/traitor_objective/steal_item/risky
progression_minimum = 30 MINUTES
progression_reward = 13 MINUTES
progression_maximum = 50 MINUTES
progression_reward = 10 MINUTES
telecrystal_reward = 2
possible_items = list(
/datum/objective_item/steal/reflector,
/datum/objective_item/steal/capmedal,
/datum/objective_item/steal/hdd_extraction,
/datum/objective_item/steal/documents,
/datum/objective_item/steal/traitor/chief_engineer_belt
)
/datum/traitor_objective/steal_item/very_risky
progression_minimum = 40 MINUTES
progression_reward = 17 MINUTES
progression_minimum = 30 MINUTES
progression_reward = 15 MINUTES
telecrystal_reward = 3
possible_items = list(
/datum/objective_item/steal/hoslaser,
/datum/objective_item/steal/caplaser,
/datum/objective_item/steal/nuke_core,
/datum/objective_item/steal/supermatter,
/datum/objective_item/steal/traitor/det_revolver,
)
/datum/traitor_objective/steal_item/most_risky
progression_minimum = 50 MINUTES
progression_reward = 25 MINUTES
progression_reward = 20 MINUTES
telecrystal_reward = 5
possible_items = list(
/datum/objective_item/steal/nukedisc,
/datum/objective_item/steal/traitor/captain_modsuit,
/datum/objective_item/steal/traitor/captain_spare,
)
/datum/traitor_objective/steal_item/most_risky/generate_objective(datum/mind/generating_for, list/possible_duplicates)
@@ -169,9 +168,9 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
if(special_equipment)
buttons += add_ui_button("", "Pressing this will summon any extra special equipment you may need for the mission.", "tools", "summon_gear")
if(!bug)
buttons += add_ui_button("", "Pressing this will materialize a bug in your hand, which you can place on the target item", "wifi", "summon_bug")
buttons += add_ui_button("", "Pressing this will materialize a scanner in your hand, which you can place on the target item", "wifi", "summon_bug")
else if(bug.planted_on)
buttons += add_ui_button("[DisplayTimeText(time_fulfilled)]", "This tells you how much time you have spent around the target item after the bug has been planted.", "clock", "none")
buttons += add_ui_button("[DisplayTimeText(time_fulfilled)]", "This tells you how much time you have spent around the target item after the scanner has been planted.", "clock", "none")
buttons += add_ui_button("Skip Time", "Pressing this will succeed the mission. You will not get the extra TC and progression.", "forward", "cash_out")
return buttons
@@ -183,7 +182,7 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
return
bug = new(user.drop_location())
user.put_in_hands(bug)
bug.balloon_alert(user, "the bug materializes in your hand")
bug.balloon_alert(user, "the scanner materializes in your hand")
bug.target_object_type = target_item.targetitem
AddComponent(/datum/component/traitor_objective_register, bug, \
fail_signals = list(COMSIG_PARENT_QDELETING), \
@@ -245,3 +244,72 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
SIGNAL_HANDLER
if(objective_state == OBJECTIVE_STATE_ACTIVE)
START_PROCESSING(SSprocessing, src)
/obj/item/traitor_bug
name = "suspicious device"
desc = "It looks dangerous."
item_flags = EXAMINE_SKIP
icon = 'icons/obj/weapons/items_and_weapons.dmi'
icon_state = "bug"
/// The object on which this bug can be planted on. Has to be a type.
var/obj/target_object_type
/// The object this bug is currently planted on.
var/obj/planted_on
/// The time it takes to place this bug.
var/deploy_time = 10 SECONDS
/obj/item/traitor_bug/examine(mob/user)
. = ..()
if(planted_on)
return
if(user.mind?.has_antag_datum(/datum/antagonist/traitor))
if(target_object_type)
. += span_notice("This device must be placed by <b>clicking on the [initial(target_object_type.name)]</b> with it.")
. += span_notice("Remember, you may leave behind fingerprints or fibers on the device. Use <b>soap</b> or similar to scrub it clean to be safe!")
/obj/item/traitor_bug/afterattack(atom/movable/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!target_object_type)
return
if(!user.Adjacent(target))
return
. |= AFTERATTACK_PROCESSED_ITEM
var/result = SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PRE_PLANTED_OBJECT, target)
if(!(result & COMPONENT_FORCE_PLACEMENT))
if(result & COMPONENT_FORCE_FAIL_PLACEMENT || !istype(target, target_object_type))
balloon_alert(user, "you can't attach this onto here!")
return
if(!do_after(user, deploy_time, src))
return
if(planted_on)
return
forceMove(target)
target.vis_contents += src
vis_flags |= VIS_INHERIT_PLANE
planted_on = target
RegisterSignal(planted_on, COMSIG_PARENT_QDELETING, PROC_REF(handle_planted_on_deletion))
SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PLANTED_OBJECT, target)
/obj/item/traitor_bug/proc/handle_planted_on_deletion()
planted_on = null
/obj/item/traitor_bug/Destroy()
if(planted_on)
vis_flags &= ~VIS_INHERIT_PLANE
planted_on.vis_contents -= src
return ..()
/obj/item/traitor_bug/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
. = ..()
if(planted_on)
vis_flags &= ~VIS_INHERIT_PLANE
planted_on.vis_contents -= src
anchored = FALSE
UnregisterSignal(planted_on, COMSIG_PARENT_QDELETING)
planted_on = null
/obj/item/traitor_bug/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user)
return !istype(storage_holder, target_object_type)
@@ -1,106 +0,0 @@
/// Chance that the traitor could roll hijack if the pop limit is met.
#define HIJACK_PROB 10
/// Hijack is unavailable as a random objective below this player count.
#define HIJACK_MIN_PLAYERS 50
/// Chance the traitor gets a martyr objective instead of having to escape alive, as long as all the objectives are martyr compatible.
#define MARTYR_PROB 20
/// Chance the traitor gets a kill objective. If this prob fails, they will get a steal objective instead.
#define KILL_PROB 50
/// If a kill objective is rolled, chance that it is to destroy the AI.
#define DESTROY_AI_PROB(denominator) (100 / denominator)
/// Generates a complete set of traitor objectives up to the traitor objective limit, including non-generic objectives such as martyr and hijack.
/datum/antagonist/traitor/forge_traitor_objectives()
objectives.Cut()
var/objective_count = 0
if((length(GLOB.joined_player_list) >= HIJACK_MIN_PLAYERS) && prob(HIJACK_PROB))
is_hijacker = TRUE
objective_count++
var/objective_limit = CONFIG_GET(number/traitor_objectives_amount)
// for(in...to) loops iterate inclusively, so to reach objective_limit we need to loop to objective_limit - 1
// This does not give them 1 fewer objectives than intended.
for(var/i in objective_count to objective_limit - 1)
objectives += forge_single_generic_objective()
/// Adds a generic kill or steal objective to this datum's objective list.
/datum/antagonist/traitor/proc/forge_single_generic_objective()
if(prob(KILL_PROB))
var/list/active_ais = active_ais()
if(length(active_ais) && prob(DESTROY_AI_PROB(length(GLOB.joined_player_list))))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = owner
destroy_objective.find_target()
return destroy_objective
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
return kill_objective
var/datum/objective/steal/steal_objective = new
steal_objective.owner = owner
steal_objective.find_target()
return steal_objective
/**
* ## forge_ending_objective
*
* Forges the endgame objective and adds it to this datum's objective list.
*/
/datum/antagonist/traitor/proc/forge_ending_objective()
if(is_hijacker)
ending_objective = new /datum/objective/hijack
ending_objective.owner = owner
objectives += ending_objective
return
var/martyr_compatibility = TRUE
for(var/datum/objective/traitor_objective in objectives)
if(!traitor_objective.martyr_compatible)
martyr_compatibility = FALSE
break
if(martyr_compatibility && prob(MARTYR_PROB))
ending_objective = new /datum/objective/martyr
ending_objective.owner = owner
objectives += ending_objective
return
ending_objective = new /datum/objective/escape
ending_objective.owner = owner
objectives += ending_objective
/// Forges a single escape objective and adds it to this datum's objective list.
/datum/antagonist/traitor/proc/forge_escape_objective()
var/is_martyr = prob(MARTYR_PROB)
var/martyr_compatibility = TRUE
for(var/datum/objective/traitor_objective in objectives)
if(!traitor_objective.martyr_compatible)
martyr_compatibility = FALSE
break
if(martyr_compatibility && is_martyr)
var/datum/objective/martyr/martyr_objective = new
martyr_objective.owner = owner
objectives += martyr_objective
return
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
objectives += escape_objective
#undef HIJACK_PROB
#undef HIJACK_MIN_PLAYERS
#undef MARTYR_PROB
#undef KILL_PROB
#undef DESTROY_AI_PROB
@@ -1,12 +0,0 @@
/// Progresionless traitor
/datum/antagonist/traitor
/// If the traitor should have progression enabled or not on their uplink
var/progression_enabled = FALSE
/// The final objective the traitor has to accomplish, be it escaping, hijacking, or just martyrdom.
var/datum/objective/ending_objective
/datum/antagonist/traitor/on_gain()
if(give_objectives)
forge_traitor_objectives()
forge_ending_objective()
return ..()
-3
View File
@@ -2686,7 +2686,6 @@
#include "code\modules\antagonists\traitor\components\traitor_objective_limit_per_time.dm"
#include "code\modules\antagonists\traitor\components\traitor_objective_mind_tracker.dm"
#include "code\modules\antagonists\traitor\objectives\assassination.dm"
#include "code\modules\antagonists\traitor\objectives\bug_room.dm"
#include "code\modules\antagonists\traitor\objectives\demoralise_crew.dm"
#include "code\modules\antagonists\traitor\objectives\demoralise_graffiti.dm"
#include "code\modules\antagonists\traitor\objectives\demoralise_poster.dm"
@@ -5252,10 +5251,8 @@
#include "modular_skyrat\master_files\code\game\turfs\open\space\space.dm"
#include "modular_skyrat\master_files\code\modules\admin\admin.dm"
#include "modular_skyrat\master_files\code\modules\antagonists\_common\antag_datum.dm"
#include "modular_skyrat\master_files\code\modules\antagonists\_common\objectives.dm"
#include "modular_skyrat\master_files\code\modules\antagonists\ashwalker\ashwalker.dm"
#include "modular_skyrat\master_files\code\modules\antagonists\ert\ert.dm"
#include "modular_skyrat\master_files\code\modules\antagonists\traitor\datums\datum_traitor.dm"
#include "modular_skyrat\master_files\code\modules\antagonists\traitor\objectives\kill_pet.dm"
#include "modular_skyrat\master_files\code\modules\antagonists\traitor\objectives\smuggling.dm"
#include "modular_skyrat\master_files\code\modules\bandana\bandanafix.dm"