Skip to content

Commit

Permalink
Merge pull request #236 from wraith-54321/traitor-stuff
Browse files Browse the repository at this point in the history
New traitor objective as well as a rework to the bomb of the locate weakpoint objective, also replaces the become dragon final objective
  • Loading branch information
dwasint authored Oct 16, 2023
2 parents 242c577 + fb79216 commit 2e4d942
Show file tree
Hide file tree
Showing 15 changed files with 415 additions and 20 deletions.
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

0 comments on commit 2e4d942

Please sign in to comment.