mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-28 15:47:15 +01:00
[MIRROR] Dynamic now plays a part in controlling random event antagonists (#3685)
* Dynamic now plays a part in controlling random event antagonists * Update _event.dm * Update spider_infestation.dm Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> Co-authored-by: KathrinBailey <53862927+KathrinBailey@users.noreply.github.com>
This commit is contained in:
co-authored by
Mothblocks
KathrinBailey
parent
5372145671
commit
70fe7d1f86
@@ -27,6 +27,11 @@
|
||||
#define COMSIG_GLOB_JOB_AFTER_SPAWN "!job_after_spawn"
|
||||
/// crewmember joined the game (mob/living, rank)
|
||||
#define COMSIG_GLOB_CREWMEMBER_JOINED "!crewmember_joined"
|
||||
/// Random event is trying to roll. (/datum/round_event_control/random_event)
|
||||
/// Called by (/datum/round_event_control/preRunEvent).
|
||||
#define COMSIG_GLOB_PRE_RANDOM_EVENT "!pre_random_event"
|
||||
/// Do not allow this random event to continue.
|
||||
#define CANCEL_PRE_RANDOM_EVENT (1<<0)
|
||||
|
||||
/// signals from globally accessible objects
|
||||
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
/// This is the only ruleset that should be picked this round, used by admins and should not be on rulesets in code.
|
||||
#define ONLY_RULESET 1
|
||||
#define ONLY_RULESET (1 << 0)
|
||||
|
||||
/// Only one ruleset with this flag will be picked.
|
||||
#define HIGH_IMPACT_RULESET 2
|
||||
#define HIGH_IMPACT_RULESET (1 << 1)
|
||||
|
||||
/// This ruleset can only be picked once. Anything that does not have a scaling_cost MUST have this.
|
||||
#define LONE_RULESET 4
|
||||
#define LONE_RULESET (1 << 2)
|
||||
|
||||
/// No round event was hijacked this cycle
|
||||
#define HIJACKED_NOTHING "HIJACKED_NOTHING"
|
||||
|
||||
/// This cycle, a round event was hijacked when the last midround event was too recent.
|
||||
#define HIJACKED_TOO_RECENT "HIJACKED_TOO_RECENT"
|
||||
|
||||
/// This cycle, a round event was hijacked when the next midround event is too soon.
|
||||
#define HIJACKED_TOO_SOON "HIJACKED_TOO_SOON"
|
||||
|
||||
@@ -129,9 +129,24 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
/// lower value rounds closer to the average.
|
||||
var/roundstart_split_curve_width = 1.8
|
||||
|
||||
/// The minimum amount of time for antag random events to be hijacked.
|
||||
var/random_event_hijack_minimum = 10 MINUTES
|
||||
|
||||
/// The maximum amount of time for antag random events to be hijacked.
|
||||
var/random_event_hijack_maximum = 18 MINUTES
|
||||
|
||||
/// A list of recorded "snapshots" of the round, stored in the dynamic.json log
|
||||
var/list/datum/dynamic_snapshot/snapshots
|
||||
|
||||
/// The time when the last midround injection was attempted, whether or not it was successful
|
||||
var/last_midround_injection_attempt = 0
|
||||
|
||||
/// The amount to inject when a round event is hijacked
|
||||
var/hijacked_random_event_injection_chance = 50
|
||||
|
||||
/// Whether or not a random event has been hijacked this midround cycle
|
||||
var/random_event_hijacked = HIJACKED_NOTHING
|
||||
|
||||
/datum/game_mode/dynamic/admin_panel()
|
||||
var/list/dat = list("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>Game Mode Panel</title></head><body><h1><B>Game Mode Panel</B></h1>")
|
||||
dat += "Dynamic Mode <a href='?_src_=vars;[HrefToken()];Vars=[REF(src)]'>\[VV\]</a> <a href='?src=\ref[src];[HrefToken()]'>\[Refresh\]</a><BR>"
|
||||
@@ -159,7 +174,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
dat += "[DR.ruletype] - <b>[DR.name]</b><br>"
|
||||
else
|
||||
dat += "none.<br>"
|
||||
dat += "<br>Injection Timers: (<b>[get_injection_chance(TRUE)]%</b> chance)<BR>"
|
||||
dat += "<br>Injection Timers: (<b>[get_injection_chance(dry_run = TRUE)]%</b> latejoin chance, <b>[get_midround_injection_chance(dry_run = TRUE)]%</b> midround chance)<BR>"
|
||||
dat += "Latejoin: [(latejoin_injection_cooldown-world.time)>60*10 ? "[round((latejoin_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(latejoin_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];injectlate=1'>\[Now!\]</a><BR>"
|
||||
dat += "Midround: [(midround_injection_cooldown-world.time)>60*10 ? "[round((midround_injection_cooldown-world.time)/60/10,0.1)] minutes" : "[(midround_injection_cooldown-world.time)] seconds"] <a href='?src=\ref[src];[HrefToken()];injectmid=1'>\[Now!\]</a><BR>"
|
||||
usr << browse(dat.Join(), "window=gamemode_panel;size=500x500")
|
||||
@@ -359,6 +374,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
vars[variable] = configuration["Dynamic"][variable]
|
||||
|
||||
setup_parameters()
|
||||
setup_hijacking()
|
||||
|
||||
var/valid_roundstart_ruleset = 0
|
||||
for (var/rule in subtypesof(/datum/dynamic_ruleset))
|
||||
@@ -647,7 +663,9 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
message_admins("DYNAMIC: Checking for midround injection.")
|
||||
log_game("DYNAMIC: Checking for midround injection.")
|
||||
|
||||
if (prob(get_injection_chance()))
|
||||
last_midround_injection_attempt = world.time
|
||||
|
||||
if (prob(get_midround_injection_chance()))
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/midround/rule in midround_rules)
|
||||
if (!rule.weight)
|
||||
@@ -661,8 +679,17 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
drafted_rules[rule] = rule.get_weight()
|
||||
if (drafted_rules.len > 0)
|
||||
picking_midround_latejoin_rule(drafted_rules)
|
||||
else if (random_event_hijacked == HIJACKED_TOO_SOON)
|
||||
log_game("DYNAMIC: Midround injection failed when random event was hijacked. Spawning another random event in its place.")
|
||||
|
||||
/// Gets the chance for latejoin and midround injection, the dry_run argument is only used for forced injection.
|
||||
// A random event antag would have rolled had this injection check passed.
|
||||
// As a refund, spawn a non-ghost-role random event.
|
||||
SSevents.spawnEvent()
|
||||
SSevents.reschedule()
|
||||
|
||||
random_event_hijacked = HIJACKED_NOTHING
|
||||
|
||||
/// Gets the chance for latejoin injection, the dry_run argument is only used for forced injection.
|
||||
/datum/game_mode/dynamic/proc/get_injection_chance(dry_run = FALSE)
|
||||
if(forced_injection)
|
||||
forced_injection = !dry_run
|
||||
@@ -685,6 +712,16 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
chance -= lower_injection_chance
|
||||
return round(max(0,chance))
|
||||
|
||||
/// Gets the chance for midround injection, the dry_run argument is only used for forced injection.
|
||||
/// Usually defers to the latejoin injection chance.
|
||||
/datum/game_mode/dynamic/proc/get_midround_injection_chance(dry_run)
|
||||
var/chance = get_injection_chance(dry_run)
|
||||
|
||||
if (random_event_hijacked != HIJACKED_NOTHING)
|
||||
chance += hijacked_random_event_injection_chance
|
||||
|
||||
return chance
|
||||
|
||||
/// Removes type from the list
|
||||
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
|
||||
for(var/I in type_list)
|
||||
@@ -801,6 +838,11 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
if (20 to INFINITY)
|
||||
return rand(90, 100)
|
||||
|
||||
/// Log to messages and to the game
|
||||
/datum/game_mode/dynamic/proc/dynamic_log(text)
|
||||
message_admins("DYNAMIC: [text]")
|
||||
log_game("DYNAMIC: [text]")
|
||||
|
||||
#undef FAKE_REPORT_CHANCE
|
||||
#undef REPORT_NEG_DIVERGENCE
|
||||
#undef REPORT_POS_DIVERGENCE
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/datum/game_mode/dynamic/proc/setup_hijacking()
|
||||
RegisterSignal(SSdcs, COMSIG_GLOB_PRE_RANDOM_EVENT, .proc/on_pre_random_event)
|
||||
|
||||
/datum/game_mode/dynamic/proc/on_pre_random_event(datum/source, datum/round_event_control/round_event_control)
|
||||
if (!round_event_control.dynamic_should_hijack)
|
||||
return
|
||||
|
||||
if (random_event_hijacked != HIJACKED_NOTHING)
|
||||
dynamic_log("Random event [round_event_control.name] tried to roll, but Dynamic vetoed it (random event has already ran).")
|
||||
SSevents.spawnEvent()
|
||||
SSevents.reschedule()
|
||||
return CANCEL_PRE_RANDOM_EVENT
|
||||
|
||||
var/time_range = rand(random_event_hijack_minimum, random_event_hijack_maximum)
|
||||
|
||||
if (world.time - last_midround_injection_attempt < time_range)
|
||||
random_event_hijacked = HIJACKED_TOO_RECENT
|
||||
dynamic_log("Random event [round_event_control.name] tried to roll, but the last midround injection \
|
||||
was too recent. Injection chance has been raised to [get_midround_injection_chance(dry_run = TRUE)]%.")
|
||||
return CANCEL_PRE_RANDOM_EVENT
|
||||
|
||||
if (midround_injection_cooldown - world.time < time_range)
|
||||
random_event_hijacked = HIJACKED_TOO_SOON
|
||||
dynamic_log("Random event [round_event_control.name] tried to roll, but the next midround injection \
|
||||
is too soon. Injection chance has been raised to [get_midround_injection_chance(dry_run = TRUE)]%.")
|
||||
return CANCEL_PRE_RANDOM_EVENT
|
||||
@@ -168,3 +168,17 @@ The "Dynamic" key has the following configurable values:
|
||||
- `threat_curve_width` - A number between 0.5 and 4. Higher value will favour extreme rounds and lower value rounds closer to the average.
|
||||
- `roundstart_split_curve_centre` - A number between -5 and +5. Equivalent to threat_curve_centre, but for the budget split. A negative value will weigh towards midround rulesets, and a positive value will weight towards roundstart ones.
|
||||
- `roundstart_split_curve_width` - A number between 0.5 and 4. Equivalent to threat_curve_width, but for the budget split. Higher value will favour more variance in splits and lower value rounds closer to the average.
|
||||
- `random_event_hijack_minimum` - The minimum amount of time for antag random events to be hijacked. (See [Random Event Hijacking](#random-event-hijacking))
|
||||
- `random_event_hijack_maximum` - The maximum amount of time for antag random events to be hijacked. (See [Random Event Hijacking](#random-event-hijacking))
|
||||
- `hijacked_random_event_injection_chance` - The amount of injection chance to give to Dynamic when a random event is hijacked. (See [Random Event Hijacking](#random-event-hijacking))
|
||||
|
||||
## Random Event "Hijacking"
|
||||
Random events have the potential to be hijacked by Dynamic to keep the pace of midround injections, while also allowing greenshifts to contain some antagonists.
|
||||
|
||||
`/datum/round_event_control/dynamic_should_hijack` is a variable to random events to allow Dynamic to hijack them, and defaults to FALSE. This is set to TRUE for random events that spawn antagonists.
|
||||
|
||||
In `/datum/game_mode/dynamic/on_pre_random_event` (in `dynamic_hijacking.dm`), Dynamic hooks to random events. If the `dynamic_should_hijack` variable is TRUE, the following sequence of events occurs:
|
||||
|
||||

|
||||
|
||||
`n` is a random value between `random_event_hijack_minimum` and `random_event_hijack_maximum`. Injection chance, should it need to be raised, is increased by `hijacked_random_event_injection_chance`.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
weight = 7
|
||||
max_occurrences = 1
|
||||
min_players = 5
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
|
||||
/datum/round_event/ghost_role/revenant
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
max_occurrences = 1
|
||||
earliest_start = 1 HOURS
|
||||
min_players = 20
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define RANDOM_EVENT_ADMIN_INTERVENTION_TIME 60 // SKYRAT EDIT: Original value (10)
|
||||
|
||||
//this singleton datum is used by the events controller to dictate how it selects events
|
||||
/datum/round_event_control
|
||||
var/name //The human-readable name of the event
|
||||
@@ -26,6 +28,9 @@
|
||||
|
||||
var/triggering //admin cancellation
|
||||
|
||||
/// Whether or not dynamic should hijack this event
|
||||
var/dynamic_should_hijack = FALSE
|
||||
|
||||
/datum/round_event_control/New()
|
||||
if(config && !wizardevent) // Magic is unaffected by configs
|
||||
earliest_start = CEILING(earliest_start * CONFIG_GET(number/events_min_time_mul), 1)
|
||||
@@ -55,18 +60,24 @@
|
||||
return FALSE
|
||||
if(ispath(typepath, /datum/round_event/ghost_role) && !(GLOB.ghost_role_flags & GHOSTROLE_MIDROUND_EVENT))
|
||||
return FALSE
|
||||
|
||||
var/datum/game_mode/dynamic/dynamic = SSticker.mode
|
||||
if (istype(dynamic) && dynamic_should_hijack && dynamic.random_event_hijacked != HIJACKED_NOTHING)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/round_event_control/proc/preRunEvent()
|
||||
if(!ispath(typepath, /datum/round_event))
|
||||
return EVENT_CANT_RUN
|
||||
|
||||
if (SEND_GLOBAL_SIGNAL(COMSIG_GLOB_PRE_RANDOM_EVENT, src) & CANCEL_PRE_RANDOM_EVENT)
|
||||
return EVENT_INTERRUPTED
|
||||
|
||||
triggering = TRUE
|
||||
if (alert_observers)
|
||||
//message_admins("Random Event triggering in 10 seconds: [name] (<a href='?src=[REF(src)];cancel=1'>CANCEL</a>)") //ORIGINAL
|
||||
//sleep(100) //ORIGINAL
|
||||
message_admins("Random Event triggering in 60 seconds: [name] (<a href='?src=[REF(src)];cancel=1'>CANCEL</a>)") //SKYRAT EDIT CHANGE - EVENTS
|
||||
sleep(600) //SKYRAT EDIT CHANGE - EVENTS
|
||||
message_admins("Random Event triggering in [RANDOM_EVENT_ADMIN_INTERVENTION_TIME] seconds: [name] (<a href='?src=[REF(src)];cancel=1'>CANCEL</a>)")
|
||||
sleep(RANDOM_EVENT_ADMIN_INTERVENTION_TIME SECONDS)
|
||||
var/gamemode = SSticker.mode.config_tag
|
||||
var/players_amt = get_active_player_count(alive_check = TRUE, afk_check = TRUE, human_check = TRUE)
|
||||
if(!canSpawnEvent(players_amt, gamemode))
|
||||
@@ -217,3 +228,5 @@
|
||||
processing = my_processing
|
||||
SSevents.running += src
|
||||
return ..()
|
||||
|
||||
#undef RANDOM_EVENT_ADMIN_INTERVENTION_TIME
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
weight = 10
|
||||
max_occurrences = 1
|
||||
min_players = 20
|
||||
dynamic_should_hijack = TRUE
|
||||
gamemode_blacklist = list("nuclear","wizard","revolution")
|
||||
|
||||
/datum/round_event/ghost_role/abductor
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
min_players = 10
|
||||
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
/datum/round_event_control/alien_infestation/canSpawnEvent()
|
||||
. = ..()
|
||||
if(!.)
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
// min_players = 20 // SKYRAT EDIT -- Original
|
||||
min_players = 60 // SKYRAT EDIT CHANGE -- Requires 60 alive non-afk players for blob
|
||||
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
gamemode_blacklist = list("blob") //Just in case a blob survives that long
|
||||
|
||||
/datum/round_event_control/blob/canSpawnEvent(players, gamemode)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
typepath = /datum/round_event/ghost_role/nightmare
|
||||
max_occurrences = 1
|
||||
min_players = 20
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
/datum/round_event/ghost_role/nightmare
|
||||
minimum_required = 1
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
typepath = /datum/round_event/ghost_role/operative
|
||||
weight = 0 //Admin only
|
||||
max_occurrences = 1
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
/datum/round_event/ghost_role/operative
|
||||
minimum_required = 1
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
max_occurrences = 1
|
||||
min_players = 10
|
||||
earliest_start = 30 MINUTES
|
||||
dynamic_should_hijack = TRUE
|
||||
gamemode_blacklist = list("nuclear")
|
||||
|
||||
#define PIRATES_ROGUES "Rogues"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
weight = 10
|
||||
max_occurrences = 1
|
||||
min_players = 20
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
/datum/round_event/ghost_role/space_dragon
|
||||
minimum_required = 1
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
weight = 10
|
||||
earliest_start = 20 MINUTES
|
||||
min_players = 20
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
/datum/round_event/ghost_role/space_ninja
|
||||
minimum_required = 1
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//max_occurrences = 1 //ORIGINAL
|
||||
max_occurrences = 0 //SKYRAT EDIT CHANGE
|
||||
//min_players = 20 - SKYRAT EDIT - moved to modular_skyrat/master_files
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
/datum/round_event/spider_infestation
|
||||
announceWhen = 400
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
weight = 3 //SKYRAT EDIT CHANGE - EVENTS - same as the dynamic ruleset
|
||||
max_occurrences = 1 //Only once okay fam
|
||||
min_players = 20
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
/datum/round_event/spawn_swarmer/announce(fake)
|
||||
priority_announce("Our long-range sensors have detected that your station's defenses have been breached by some sort of alien device. We suggest searching for and destroying it as soon as possible.", "[command_name()] High-Priority Update")
|
||||
|
||||
@@ -840,6 +840,7 @@
|
||||
#include "code\game\gamemodes\clown_ops\clown_weapons.dm"
|
||||
#include "code\game\gamemodes\cult\cult.dm"
|
||||
#include "code\game\gamemodes\dynamic\dynamic.dm"
|
||||
#include "code\game\gamemodes\dynamic\dynamic_hijacking.dm"
|
||||
#include "code\game\gamemodes\dynamic\dynamic_logging.dm"
|
||||
#include "code\game\gamemodes\dynamic\dynamic_rulesets.dm"
|
||||
#include "code\game\gamemodes\dynamic\dynamic_rulesets_latejoin.dm"
|
||||
|
||||
Reference in New Issue
Block a user