Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New traitor objective as well as a rework to the bomb of the locate weakpoint objective, also replaces the become dragon final objective #236

Merged
merged 22 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions code/__DEFINES/~monkestation/antagonists.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
/// List of areas blacklisted from area based traitor objectives
#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, \
)

// Clock cultist
#define IS_CLOCK(mob) ((FACTION_CLOCK in mob.faction) || mob?.mind?.has_antag_datum(/datum/antagonist/clock_cultist))
/// maximum amount of cogscarabs the clock cult can have
Expand Down
4 changes: 4 additions & 0 deletions code/__DEFINES/~monkestation/dcs/signals/signals_traitor.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Sent when a bug activates
#define COMSIG_TRAITOR_BUG_ACTIVATED "traitor_bug_activated"
/// Sent when a T1de bug activates
#define COMSIG_GLOBAL_GREY_TIDE_TRAITOR "grey_tide_traitor"
10 changes: 8 additions & 2 deletions code/game/machinery/airlock_control.dm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/obj/machinery/door/airlock/Initialize(mapload)
. = ..()
RegisterSignal(SSdcs, COMSIG_GLOB_GREY_TIDE, PROC_REF(grey_tide))
RegisterSignal(SSdcs, COMSIG_GLOBAL_GREY_TIDE_TRAITOR, PROC_REF(grey_tide)) //monkestation edit

/// Forces the airlock to unbolt and open
/obj/machinery/door/airlock/proc/secure_open()
Expand All @@ -35,7 +36,7 @@
locked = FALSE
return ..()

/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) //monkestation edit: adds traitor_bug
SIGNAL_HANDLER

if(!is_station_level(z) || critical_machine)
Expand All @@ -44,7 +45,12 @@
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
//monkestation edit start
if(traitor_bug)
INVOKE_ASYNC(src, PROC_REF(traitor_bug_tide))
else
//monkestation edit end
INVOKE_ASYNC(src, PROC_REF(prison_open)) //Sleep gets called further down in open(), so we have to invoke async

/obj/machinery/airlock_sensor
icon = 'icons/obj/airlock_machines.dmi'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
try_draw_new_rune(user, target)
return COMPONENT_CANCEL_ATTACK_CHAIN

if (istype(target, /obj/effect/decal/cleanable/traitor_rune))
if (istype(target, /obj/effect/decal/cleanable/traitor_rune) && multi_stage) //monkestation edit: adds multi_stage check
try_complete_rune(user, target)
return COMPONENT_CANCEL_ATTACK_CHAIN

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
objectives = list(
/datum/traitor_objective/ultimate/romerol = 1,
/datum/traitor_objective/ultimate/battlecruiser = 1,
/datum/traitor_objective/ultimate/space_dragon = 1,
// /datum/traitor_objective/ultimate/space_dragon = 1, //monkestation removal
/datum/traitor_objective/ultimate/supermatter_cascade = 1,
/datum/traitor_objective/ultimate/infect_ai = 1,
/datum/traitor_objective/ultimate/dark_matteor = 1,
/datum/traitor_objective/ultimate/wizard = 1, //monkestation edit
)
weight = 100

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//MONKESTATION FILE REMOVAL: REPLACED WITH THE /datum/traitor_objective/ultimate/wizard OBJECTIVE
/*
/datum/traitor_objective/ultimate/space_dragon
name = "Find a Space Carp and mutate their DNA with your own using a DNA harvester we will drop pod at %AREA%"
description = "Go to %AREA%, and recieve the Carp DNA scanner. Use it on any Space Carp to harvest its DNA. \
Expand Down Expand Up @@ -47,4 +49,4 @@
"target" = get_turf(user),
"style" = STYLE_SYNDICATE,
"spawn" = /obj/item/storage/box/syndie_kit/space_dragon,
))
))*/
39 changes: 34 additions & 5 deletions code/modules/antagonists/traitor/objectives/locate_weakpoint.dm
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,16 @@
/area/station/security,
))

var/list/blacklisted_areas = typecacheof(list(/area/station/engineering/hallway,
//monkestation removal start
/* var/list/blacklisted_areas = typecacheof(list(/area/station/engineering/hallway,
/area/station/engineering/lobby,
/area/station/engineering/storage,
/area/station/science/lobby,
/area/station/science/ordnance/bomb,
/area/station/security/prison,
))
))*/
//monkestation removal end
var/list/blacklisted_areas = typecacheof(TRAITOR_OBJECTIVE_BLACKLISTED_AREAS) //monkestation edit

var/list/possible_areas = GLOB.the_station_areas.Copy()
for(var/area/possible_area as anything in possible_areas)
Expand Down Expand Up @@ -119,10 +122,36 @@
/datum/traitor_objective/locate_weakpoint/proc/create_shockwave(center_x, center_y, center_z)
var/turf/epicenter = locate(center_x, center_y, center_z)
var/lowpop = (length(GLOB.clients) <= CONFIG_GET(number/minimal_access_threshold))
if(lowpop)
//monkestation removal start
/* if(lowpop)
explosion(epicenter, devastation_range = 2, heavy_impact_range = 4, light_impact_range = 6, explosion_cause = src)
else
explosion(epicenter, devastation_range = 3, heavy_impact_range = 6, light_impact_range = 9, explosion_cause = src)
explosion(epicenter, devastation_range = 3, heavy_impact_range = 6, light_impact_range = 9, explosion_cause = src)*/
//monkestation removal end
//monkestation edit start: now creates radiating(one explosion in each ring) light explosions
var/greatest_dist = 0
var/list/turfs_to_collapse = list()
for(var/turf/collapsed_turf as anything in GLOB.station_turfs)
if(istype(get_area(collapsed_turf), /area/station/ai_monitored)) //remote bombing of these areas would be bad
continue

var/dist = get_dist(epicenter, collapsed_turf)
if(dist > greatest_dist)
greatest_dist = dist

if(!turfs_to_collapse["[dist]"])
turfs_to_collapse["[dist]"] = list()
turfs_to_collapse["[dist]"] += collapsed_turf

for(var/iterator in 1 to greatest_dist)
if(!turfs_to_collapse["[iterator]"])
continue
for(var/i in 1 to (lowpop ? 1 : 2)) //if lowpop then only do one collapse per ring, otherwise do two
addtimer(CALLBACK(pick_n_take(turfs_to_collapse["[iterator]"]), TYPE_PROC_REF(/turf, structural_collapse), 6 SECONDS, list(0, 0, 3), list('sound/effects/creak1.ogg', \
'sound/effects/creak2.ogg', \
'sound/effects/creak3.ogg')), \
2 SECONDS * iterator)
//monkestation edit end
priority_announce(
"Attention crew, it appears that a high-power explosive charge has been detonated in your station's weakpoint, causing severe structural damage.",
"[command_name()] High-Priority Update"
Expand Down Expand Up @@ -228,7 +257,7 @@
inhand_icon_state = "plasticx4"
worn_icon_state = "x4"

boom_sizes = list(3, 6, 9)
boom_sizes = list(1, 2, 3) //monkestation edit: from list(3, 6, 9), now creates a bunch of light explosions across the station

/// Weakref to user's objective
var/datum/weakref/objective_weakref
Expand Down
13 changes: 10 additions & 3 deletions code/modules/antagonists/traitor/objectives/steal.dm
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,12 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
/datum/objective_item/steal/traitor/captain_spare,
)

/datum/traitor_objective/steal_item/most_risky/generate_objective(datum/mind/generating_for, list/possible_duplicates)
//monkestation removal start, this was added with biddle traitor and then was just never removed when steal got reworked
/*/datum/traitor_objective/steal_item/most_risky/generate_objective(datum/mind/generating_for, list/possible_duplicates)
if(!handler.get_completion_count(/datum/traitor_objective/steal_item/very_risky))
return FALSE
return ..()
return ..()*/
//monkestation removal end

/datum/traitor_objective/steal_item/generate_objective(datum/mind/generating_for, list/possible_duplicates)
for(var/datum/traitor_objective/steal_item/objective as anything in possible_duplicates)
Expand Down Expand Up @@ -266,7 +268,12 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new())
return

if(IS_TRAITOR(user))
if(target_object_type)
//monkestation edit start
var/datum/traitor_objective/tide_bug_department/resolved_objective = objective_weakref?.resolve()
if(resolved_objective)
. += span_notice("This device must be placed by <b>using it in hand</b> inside the <b>[initial(resolved_objective.targeted_area?.name)]</b>.")
//monkestation edit end
else if(target_object_type) //monkestation edit: makes this an else if
. += 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!")

Expand Down
23 changes: 16 additions & 7 deletions code/modules/antagonists/wizard/grand_ritual/grand_rune.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// Number of times you need to cast on the rune to complete it
#define GRAND_RUNE_INVOKES_TO_COMPLETE 3
//#define GRAND_RUNE_INVOKES_TO_COMPLETE 3 //monkestation removal
/// Base time to take to invoke one stage of the rune. This is done three times to complete the rune.
#define BASE_INVOKE_TIME 7 SECONDS
/// Time to add on to each step every time a previous rune is completed.
Expand Down Expand Up @@ -90,22 +90,31 @@

/obj/effect/grand_rune/examine(mob/user)
. = ..()
if (times_invoked >= GRAND_RUNE_INVOKES_TO_COMPLETE)
if (times_invoked >= invokes_needed) //monkestation edit: replaced GRAND_RUNE_INVOKES_TO_COMPLETE with invokes_needed
. += span_notice("Its power seems to have been expended.")
return
if(!IS_WIZARD(user))
return
. += span_notice("Invoke this rune [GRAND_RUNE_INVOKES_TO_COMPLETE - times_invoked] more times to complete the ritual.")
. += span_notice("Invoke this rune [invokes_needed - times_invoked] more times to complete the ritual.")//monkestation edit: replaced GRAND_RUNE_INVOKES_TO_COMPLETE with invokes_needed

/obj/effect/grand_rune/can_interact(mob/living/user)
. = ..()
if(!.)
return
if(!IS_WIZARD(user))
//monkestation edit start
if(!owning_mind && !IS_WIZARD(user))
return FALSE

else if(owning_mind && !(user.mind == owning_mind?.resolve()))
return FALSE
//monkestation edit end
//monkestation removal start
/*if(!IS_WIZARD(user))
return FALSE*/
//monkestation removal end
if(is_in_use)
return FALSE
if (times_invoked >= GRAND_RUNE_INVOKES_TO_COMPLETE)
if (times_invoked >= invokes_needed) //monkestation edit: replaced GRAND_RUNE_INVOKES_TO_COMPLETE with invokes_needed
return FALSE
return TRUE

Expand Down Expand Up @@ -157,7 +166,7 @@
for(var/obj/machinery/light/light in orange(4, src.loc))
light.flicker()

if(times_invoked >= GRAND_RUNE_INVOKES_TO_COMPLETE)
if(times_invoked >= invokes_needed) //monkestation edit: replaced GRAND_RUNE_INVOKES_TO_COMPLETE with invokes_needed
on_invocation_complete(user)
return
flick("[icon_state]_flash", src)
Expand Down Expand Up @@ -264,7 +273,7 @@
new_influence.after_drain()
created++

#undef GRAND_RUNE_INVOKES_TO_COMPLETE
//#undef GRAND_RUNE_INVOKES_TO_COMPLETE //monkestation removal

#undef BASE_INVOKE_TIME
#undef ADD_INVOKE_TIME
Expand Down
14 changes: 14 additions & 0 deletions monkestation/code/__HELPERS/turfs.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**Shake() and then explode a turf based on the passed vars
* shake_duration: how long to shake the turf for before calling explosion()
* explosion_stats: a list of what stats to give the called explosion()
* sound: if passed then what sound to play at the start of the shaking, if a list is passed then it will pick() from that list
**/
/turf/proc/structural_collapse(shake_duration = 1 SECONDS, explosion_stats = list(1, 2, 3), sound/played_sound)
if(QDELETED(src))
return

if(played_sound)
playsound(src, (islist(played_sound) ? pick(played_sound) : played_sound), 60)
visible_message(span_userdanger("\The [src] looks like its about to collapse!"))
Shake(0.2, 0.2, shake_duration)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(explosion), src, explosion_stats[1], explosion_stats[2], explosion_stats[3]), shake_duration)
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/datum/traitor_objective/ultimate/wizard
name = "Go to %AREA% and invoke a rune of power."
description = "Go to %AREA% and draw a rune of power with the provided impliment. Then, invoke the rune to gain great magical power."

///Area where the rune must be drawn
var/area/area_of_power
///Have we sent our spraycan yet
var/spraycan_sent = FALSE

/datum/traitor_objective/ultimate/wizard/generate_objective(datum/mind/generating_for, list/possible_duplicates)
var/list/possible_areas = GLOB.the_station_areas.Copy()
var/list/extra_blacklisted_areas = list(/area/station/hallway, /area/station/security, /area/station/ai_monitored)
for(var/area/possible_area as anything in possible_areas)
if(is_type_in_list(possible_area, (TRAITOR_OBJECTIVE_BLACKLISTED_AREAS + extra_blacklisted_areas)) || initial(possible_area.outdoors))
possible_areas -= possible_area

if(!length(possible_areas))
return FALSE

area_of_power = pick(possible_areas)
replace_in_name("%AREA%", initial(area_of_power.name))
return TRUE

/datum/traitor_objective/ultimate/wizard/generate_ui_buttons(mob/user)
var/list/buttons = list()
if(!spraycan_sent)
buttons += add_ui_button("", "Pressing this will materialize an enchanted spraycan in your hand.", "wifi", "spraycan")
return buttons

/datum/traitor_objective/ultimate/wizard/ui_perform_action(mob/living/user, action)
. = ..()
switch(action)
if("spraycan")
if(spraycan_sent)
return

spraycan_sent = TRUE
var/obj/item/traitor_spraycan/enchanted/spray = new(user.drop_location())
spray.owning_mind = WEAKREF(user.mind)
user.put_in_hands(spray)
spray.balloon_alert(user, "\The [spray] materializes in your hand.")

//the spraycan

/obj/item/traitor_spraycan
///Is our rune multi stage
var/multi_stage = TRUE

/obj/item/traitor_spraycan/enchanted
name = "enchanted seditious spraycan"
desc = "An enchanted spraycan able to draw a single rune of power."
multi_stage = FALSE
///Weakref to the mind that owns this spraycan, used for transfer to the rune
var/datum/weakref/owning_mind

/obj/item/traitor_spraycan/enchanted/try_draw_new_rune(mob/living/user, turf/target_turf)
for(var/turf/nearby_turf as anything in RANGE_TURFS(1, target_turf))
if(isindestructiblewall(nearby_turf) || is_type_in_typecache(nearby_turf, no_draw_turfs))
user.balloon_alert(user, "Invalid floor!")
return

draw_rune(user, target_turf)

/obj/item/traitor_spraycan/enchanted/draw_rune(mob/living/user, turf/target_turf)
drawing_rune = TRUE
target_turf.balloon_alert(user, "Drawing rune...")
var/obj/effect/temp_visual/wizard_rune/traitor_drawing/draw_effect = new(target_turf)
if(!do_after(user, 4 SECONDS, target_turf))
target_turf.balloon_alert(user, "Interrupted!")
drawing_rune = FALSE
qdel(draw_effect)
new /obj/effect/temp_visual/wizard_rune/failed(target_turf)
return

var/evaporated_obstacles = FALSE
for(var/atom/possible_obstacle in range(1, target_turf))
if(!possible_obstacle.density)
continue
evaporated_obstacles = TRUE
new /obj/effect/temp_visual/emp/pulse(possible_obstacle)

if(iswallturf(possible_obstacle))
var/turf/closed/wall/wall = possible_obstacle
wall.dismantle_wall(devastated = TRUE)
continue
possible_obstacle.atom_destruction("magic")

if(evaporated_obstacles)
playsound(target_turf, 'sound/magic/blind.ogg', 100, TRUE)

target_turf.balloon_alert(user, "Rune created.")
var/obj/effect/grand_rune/traitor/new_rune = new(target_turf)
new_rune.owning_mind = WEAKREF(owning_mind?.resolve())
expended = TRUE
desc = "A very suspicious looking spraycan, it's empty."
drawing_rune = FALSE
//the rune

#define TRAITOR_RUNE_INVOKE_TIME 30 SECONDS //you just have to invoke it once but it takes a while to channel
#define TRAITOR_GRAND_RUNE_INVOKES_TO_COMPLETE 1

/obj/effect/grand_rune/traitor
name = "suspicious rune"
desc = "A flowing circle of shapes and runes is etched into the floor, it has an odd red tint."
icon = 'monkestation/icons/effects/96x96.dmi'
icon_state = "traitor_wizard_rune"
spell_colour = "#780000"
invoke_time = TRAITOR_RUNE_INVOKE_TIME
invokes_needed = TRAITOR_GRAND_RUNE_INVOKES_TO_COMPLETE

/obj/effect/grand_rune/traitor/get_invoke_time()
return invoke_time

/obj/effect/grand_rune/traitor/on_invocation_complete(mob/living/user)
is_in_use = FALSE
playsound(src,'sound/magic/staff_change.ogg', 75, TRUE)
user.mind?.make_wizard()
trigger_side_effects()
tear_reality()
icon = 'icons/effects/96x96.dmi'
flick("activate", src)
addtimer(CALLBACK(src, PROC_REF(remove_rune)), 6)

#undef TRAITOR_RUNE_INVOKE_TIME
#undef TRAITOR_GRAND_RUNE_INVOKES_TO_COMPLETE

//the temp visual for drawing the rune

/obj/effect/temp_visual/wizard_rune/traitor_drawing
icon = 'monkestation/icons/effects/96x96.dmi'
icon_state = "traitor_wizard_rune_draw"
duration = 4 SECONDS
Loading