mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Continues work on new Event System
Ports and adds some more events, including dust, meteors, carp, etc. Tweaks meteors, now has a 10 minute warning beforehand and meteors only approach from one direction now.
This commit is contained in:
@@ -5,12 +5,9 @@
|
||||
var/chaotic = 0 // A number showing how chaotic the action may be. If danger is high, the GM will avoid it.
|
||||
var/reusable = FALSE // If true, the event does not become disabled upon being used. Should be used sparingly.
|
||||
var/observers_used = FALSE // Determines if the GM should check if ghosts are available before using this.
|
||||
var/length = 0 // Determines how long the event lasts, until end() is called.
|
||||
var/datum/game_master/gm = null
|
||||
|
||||
/datum/gm_action/New(var/datum/game_master/new_gm)
|
||||
..()
|
||||
gm = new_gm
|
||||
|
||||
/datum/gm_action/proc/set_up()
|
||||
return
|
||||
|
||||
|
||||
65
code/modules/gamemaster/actions/carp_migration.dm
Normal file
65
code/modules/gamemaster/actions/carp_migration.dm
Normal file
@@ -0,0 +1,65 @@
|
||||
//carp_migration
|
||||
/datum/gm_action/carp_migration
|
||||
name = "carp migration"
|
||||
departments = list(ROLE_SECURITY, ROLE_EVERYONE)
|
||||
chaotic = 50
|
||||
var/list/spawned_carp = list()
|
||||
var/carp_amount = 0
|
||||
length = 20 MINUTES
|
||||
|
||||
/datum/gm_action/carp_migration/get_weight()
|
||||
var/people_in_space = 0
|
||||
for(var/mob/living/L in player_list)
|
||||
if(!(L.z in config.station_levels))
|
||||
continue // Not on the right z-level.
|
||||
var/turf/T = get_turf(L)
|
||||
if(istype(T, /turf/space) && istype(T.loc,/area/space))
|
||||
people_in_space++
|
||||
return 50 + (metric.count_people_in_department(ROLE_SECURITY) * 10) + (people_in_space * 20)
|
||||
|
||||
/datum/gm_action/carp_migration/announce()
|
||||
var/announcement = "Unknown biological entities have been detected near [station_name()], please stand-by."
|
||||
command_announcement.Announce(announcement, "Lifesign Alert")
|
||||
|
||||
/datum/gm_action/carp_migration/set_up()
|
||||
// Higher filled roles means more groups of fish.
|
||||
var/station_strength = 0
|
||||
station_strength += (metric.count_people_in_department(ROLE_SECURITY) * 3)
|
||||
station_strength += (metric.count_people_in_department(ROLE_ENGINEERING) * 2)
|
||||
station_strength += metric.count_people_in_department(ROLE_MEDICAL)
|
||||
|
||||
// Less active emergency response departments tones the event down.
|
||||
var/activeness = ((metric.assess_department(ROLE_SECURITY) + metric.assess_department(ROLE_ENGINEERING) + metric.assess_department(ROLE_MEDICAL)) / 3)
|
||||
activeness = max(activeness, 20)
|
||||
|
||||
carp_amount = Ceiling(station_strength * (activeness / 100) + 1)
|
||||
|
||||
/datum/gm_action/carp_migration/start()
|
||||
..()
|
||||
var/list/spawn_locations = list()
|
||||
|
||||
var/group_size_min = 3
|
||||
var/group_size_max = 5
|
||||
|
||||
for(var/obj/effect/landmark/C in landmarks_list)
|
||||
if(C.name == "carpspawn")
|
||||
spawn_locations.Add(C.loc)
|
||||
|
||||
spawn_locations = shuffle(spawn_locations)
|
||||
carp_amount = min(carp_amount, spawn_locations.len)
|
||||
|
||||
var/i = 1
|
||||
while (i <= carp_amount)
|
||||
var/group_size = rand(group_size_min, group_size_max)
|
||||
for (var/j = 1, j <= group_size, j++)
|
||||
spawned_carp.Add(new /mob/living/simple_animal/hostile/carp(spawn_locations[i]))
|
||||
i++
|
||||
message_admins("[spawned_carp.len] carp spawned by event.")
|
||||
|
||||
/datum/gm_action/carp_migration/end()
|
||||
for(var/mob/living/simple_animal/hostile/carp/C in spawned_carp)
|
||||
if(!C.stat)
|
||||
var/turf/T = get_turf(C)
|
||||
if(istype(T, /turf/space))
|
||||
if(!prob(25))
|
||||
qdel(C)
|
||||
@@ -1,9 +1,21 @@
|
||||
// Comms blackout is, just like grid check, mostly the same as always, yet engineering has an option to get it back sooner.
|
||||
|
||||
/datum/gm_action/comms_blackout
|
||||
name = "communications blackout"
|
||||
departments = list(ROLE_ENGINEERING, ROLE_EVERYONE)
|
||||
chaotic = 35
|
||||
|
||||
/datum/gm_action/comms_blackout/get_weight()
|
||||
return 50 + (metric.count_people_in_department(ROLE_ENGINEERING) * 40)
|
||||
return 50 + (metric.count_people_in_department(ROLE_ENGINEERING) * 40)
|
||||
|
||||
/datum/gm_action/comms_blackout/announce()
|
||||
if(prob(33))
|
||||
command_announcement.Announce("Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you-BZZT", new_sound = 'sound/misc/interference.ogg')
|
||||
// AIs will always know if there's a comm blackout, rogue AIs could then lie about comm blackouts in the future while they shutdown comms
|
||||
for(var/mob/living/silicon/ai/A in player_list)
|
||||
A << "<br>"
|
||||
A << "<span class='warning'><b>Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you-BZZT</b></span>"
|
||||
A << "<br>"
|
||||
|
||||
/datum/gm_action/comms_blackout/start()
|
||||
..()
|
||||
for(var/obj/machinery/telecomms/T in telecomms_list)
|
||||
T.emp_act(1)
|
||||
|
||||
17
code/modules/gamemaster/actions/dust.dm
Normal file
17
code/modules/gamemaster/actions/dust.dm
Normal file
@@ -0,0 +1,17 @@
|
||||
/datum/gm_action/dust
|
||||
name = "dust"
|
||||
departments = list(ROLE_ENGINEERING)
|
||||
chaotic = 10
|
||||
reusable = TRUE
|
||||
|
||||
/datum/gm_action/dust/announce()
|
||||
command_announcement.Announce("Debris resulting from activity on another nearby asteroid is approaching your colony.", "Dust Alert")
|
||||
|
||||
/datum/gm_action/dust/get_weight()
|
||||
var/engineers = metric.count_people_in_department(ROLE_ENGINEERING)
|
||||
var/weight = 30 + (engineers * 25)
|
||||
return weight
|
||||
|
||||
/datum/gm_action/dust/start()
|
||||
..()
|
||||
dust_swarm("norm")
|
||||
@@ -13,6 +13,7 @@
|
||||
return 50 + (metric.count_people_in_department(ROLE_ENGINEERING) * 30)
|
||||
|
||||
/datum/gm_action/grid_check/start()
|
||||
..()
|
||||
// This sets off a chain of events that lead to the actual grid check (or perhaps worse).
|
||||
// First, the Supermatter engine makes a power spike.
|
||||
for(var/obj/machinery/power/generator/engine in machines)
|
||||
|
||||
51
code/modules/gamemaster/actions/meteor_defense.dm
Normal file
51
code/modules/gamemaster/actions/meteor_defense.dm
Normal file
@@ -0,0 +1,51 @@
|
||||
// This event gives the station an advance warning about meteors, so that they can prepare in various ways.
|
||||
|
||||
/datum/gm_action/meteor_defense
|
||||
name = "meteor defense"
|
||||
departments = list(ROLE_ENGINEERING)
|
||||
chaotic = 50
|
||||
var/direction = null
|
||||
var/dir_text = null
|
||||
var/waves = 0
|
||||
|
||||
/datum/gm_action/meteor_defense/get_weight()
|
||||
var/engineers = metric.count_people_in_department(ROLE_ENGINEERING)
|
||||
var/weight = (max(engineers - 1, 0) * 25) // If only one engineer exists, no meteors for now.
|
||||
return weight
|
||||
|
||||
/datum/gm_action/meteor_defense/set_up()
|
||||
direction = pick(cardinal) // alldirs doesn't work with current meteor code unfortunately.
|
||||
waves = rand(5, 8)
|
||||
switch(direction)
|
||||
if(NORTH)
|
||||
dir_text = "aft" // For some reason this is needed.
|
||||
if(SOUTH)
|
||||
dir_text = "fore"
|
||||
if(EAST)
|
||||
dir_text = "port"
|
||||
if(WEST)
|
||||
dir_text = "starboard"
|
||||
|
||||
/datum/gm_action/meteor_defense/announce()
|
||||
var/announcement = "Alert! Two other asteroids have collided near [station_name()]. Chunks of it are expected to approach from the [dir_text] side. ETA to arrival is \
|
||||
approximately 10 minutes."
|
||||
command_announcement.Announce(announcement, "Meteor Alert", new_sound = 'sound/AI/meteors.ogg')
|
||||
|
||||
/datum/gm_action/meteor_defense/start()
|
||||
..()
|
||||
spawn(0)
|
||||
// sleep(5 MINUTES)
|
||||
var/announcement = "The incoming debris are expected to approach from the [dir_text] side. ETA to arrival is approximately 5 minutes."
|
||||
command_announcement.Announce(announcement, "Meteor Alert - Update")
|
||||
// sleep(5 MINUTES)
|
||||
announcement = "Incoming debris approaches from the [dir_text] side!"
|
||||
command_announcement.Announce(announcement, "Meteor Alert - Update")
|
||||
while(waves)
|
||||
message_admins("[waves] more wave\s of meteors remain.")
|
||||
spawn(1) // Dir is reversed because the direction describes where meteors are going, not what side it's gonna hit.
|
||||
spawn_meteors(rand(8, 12), meteors_threatening, reverse_dir[direction])
|
||||
waves--
|
||||
sleep(30 SECONDS)
|
||||
announcement = "The colony has cleared the incoming debris."
|
||||
command_announcement.Announce(announcement, "Meteor Alert - Update")
|
||||
message_admins("Meteor defense event has ended.")
|
||||
17
code/modules/gamemaster/actions/shipping_error.dm
Normal file
17
code/modules/gamemaster/actions/shipping_error.dm
Normal file
@@ -0,0 +1,17 @@
|
||||
/datum/gm_action/shipping_error
|
||||
name = "shipping error"
|
||||
departments = list(ROLE_CARGO)
|
||||
reusable = TRUE
|
||||
|
||||
/datum/gm_action/shipping_error/get_weight()
|
||||
var/cargo = metric.count_people_in_department(ROLE_CARGO)
|
||||
var/weight = (cargo * 40)
|
||||
return weight
|
||||
|
||||
/datum/gm_action/shipping_error/start()
|
||||
..()
|
||||
var/datum/supply_order/O = new /datum/supply_order()
|
||||
O.ordernum = supply_controller.ordernum
|
||||
O.object = supply_controller.supply_packs[pick(supply_controller.supply_packs)]
|
||||
O.orderedby = random_name(pick(MALE,FEMALE), species = "Human")
|
||||
supply_controller.shoppinglist += O
|
||||
53
code/modules/gamemaster/actions/surprise_carp_attack.dm
Normal file
53
code/modules/gamemaster/actions/surprise_carp_attack.dm
Normal file
@@ -0,0 +1,53 @@
|
||||
// This event sends a few carp after someone in space.
|
||||
|
||||
/datum/gm_action/surprise_carp_attack
|
||||
name = "surprise carp attack"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
reusable = TRUE
|
||||
chaotic = 10
|
||||
var/mob/living/victim = null
|
||||
|
||||
/datum/gm_action/surprise_carp_attack/get_weight()
|
||||
var/people_in_space = 0
|
||||
for(var/mob/living/L in player_list)
|
||||
if(!(L.z in config.station_levels))
|
||||
continue // Not on the right z-level.
|
||||
var/turf/T = get_turf(L)
|
||||
if(istype(T, /turf/space) && istype(T.loc,/area/space))
|
||||
people_in_space++
|
||||
return people_in_space * 50
|
||||
|
||||
/datum/gm_action/surprise_carp_attack/set_up()
|
||||
var/list/potential_victims = list()
|
||||
victim = null
|
||||
for(var/mob/living/L in player_list)
|
||||
if(!(L.z in config.station_levels))
|
||||
continue // Not on the right z-level.
|
||||
if(L.stat)
|
||||
continue // Don't want dead people.
|
||||
var/turf/T = get_turf(L)
|
||||
if(istype(T, /turf/space) && istype(T.loc,/area/space))
|
||||
potential_victims.Add(L)
|
||||
victim = pick(potential_victims)
|
||||
|
||||
|
||||
/datum/gm_action/surprise_carp_attack/start()
|
||||
..()
|
||||
if(!victim)
|
||||
message_admins("Surprise carp attack failed to find a target.")
|
||||
return
|
||||
var/number_of_carp = rand(1, 2)
|
||||
message_admins("Sending [number_of_carp] carp\s after [victim].")
|
||||
while(number_of_carp)
|
||||
var/turf/spawning_turf = null
|
||||
var/list/nearby_things = oview(10, victim)
|
||||
for(var/turf/space/space in nearby_things)
|
||||
if(get_dist(space, victim) <= 7)
|
||||
continue
|
||||
spawning_turf = space
|
||||
break
|
||||
if(spawning_turf)
|
||||
var/mob/living/simple_animal/hostile/carp/C = new(spawning_turf)
|
||||
C.target_mob = victim
|
||||
C.stance = STANCE_ATTACK
|
||||
number_of_carp--
|
||||
17
code/modules/gamemaster/actions/surprise_meteor.dm
Normal file
17
code/modules/gamemaster/actions/surprise_meteor.dm
Normal file
@@ -0,0 +1,17 @@
|
||||
// This event sends one wave of meteors unannounced.
|
||||
|
||||
/datum/gm_action/surprise_meteors
|
||||
name = "surprise meteors"
|
||||
departments = list(ROLE_ENGINEERING)
|
||||
chaotic = 25
|
||||
|
||||
/datum/gm_action/surprise_meteors/get_weight()
|
||||
var/engineers = metric.count_people_in_department(ROLE_ENGINEERING)
|
||||
var/weight = (max(engineers - 1, 0) * 25) // If only one engineer exists, no meteors for now.
|
||||
return weight
|
||||
|
||||
/datum/gm_action/surprise_meteors/start()
|
||||
..()
|
||||
spawn(1)
|
||||
spawn_meteors(rand(4, 8), meteors_normal, pick(cardinal))
|
||||
message_admins("Surprise meteors event has ended.")
|
||||
@@ -24,7 +24,7 @@
|
||||
for(var/datum/gm_action/action in available_actions)
|
||||
if(action.enabled == FALSE)
|
||||
continue
|
||||
HTML += "[action.name] ([english_list(action.departments)]) (weight: [action.get_weight()])<br>"
|
||||
HTML += "[action.name] ([english_list(action.departments)]) (weight: [action.get_weight()]) <a href='?src=\ref[action];force=1'>\[Force\]</a> <br>"
|
||||
|
||||
HTML += "<br>"
|
||||
HTML += "All living mobs activity: [metric.assess_all_living_mobs()]%<br>"
|
||||
@@ -77,4 +77,16 @@
|
||||
adjust_danger(amount)
|
||||
message_admins("GM danger was adjusted by [amount] by [usr.key].")
|
||||
|
||||
interact(usr) // To refresh the UI.
|
||||
interact(usr) // To refresh the UI.
|
||||
|
||||
/datum/gm_action/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!is_admin(usr))
|
||||
message_admins("[usr] has attempted to force an event without being an admin.")
|
||||
return
|
||||
|
||||
if(href_list["force"])
|
||||
gm.run_action(src)
|
||||
message_admins("GM event [name] was forced by [usr.key].")
|
||||
@@ -19,6 +19,8 @@
|
||||
/datum/game_master/New()
|
||||
..()
|
||||
available_actions = init_subtypes(/datum/gm_action)
|
||||
for(var/datum/gm_action/action in available_actions)
|
||||
action.gm = src
|
||||
|
||||
/datum/game_master/proc/process()
|
||||
if(ticker && ticker.current_state == GAME_STATE_PLAYING && !suspended)
|
||||
@@ -68,17 +70,26 @@
|
||||
if(best_actions && best_actions.len)
|
||||
var/list/weighted_actions = list()
|
||||
for(var/datum/gm_action/action in best_actions)
|
||||
if(action.chaotic > danger)
|
||||
continue // We skip dangerous events when bad stuff is already occuring.
|
||||
weighted_actions[action] = action.get_weight()
|
||||
|
||||
var/datum/gm_action/choice = pickweight(weighted_actions)
|
||||
if(choice)
|
||||
log_debug("[choice.name] was chosen by the Game Master, and is now being ran.")
|
||||
choice.set_up()
|
||||
choice.start()
|
||||
next_action = world.time + rand(15 MINUTES, 30 MINUTES)
|
||||
last_department_used = choice.departments[1]
|
||||
|
||||
run_action(choice)
|
||||
|
||||
/datum/game_master/proc/run_action(var/datum/gm_action/action)
|
||||
action.set_up()
|
||||
action.start()
|
||||
action.announce()
|
||||
if(action.chaotic)
|
||||
danger += action.chaotic
|
||||
if(action.length)
|
||||
spawn(action.length)
|
||||
action.end()
|
||||
next_action = world.time + rand(15 MINUTES, 30 MINUTES)
|
||||
last_department_used = action.departments[1]
|
||||
|
||||
|
||||
/datum/game_master/proc/decide_best_action(var/list/most_active_departments)
|
||||
|
||||
@@ -1357,8 +1357,14 @@
|
||||
#include "code\modules\gamemaster\game_master.dm"
|
||||
#include "code\modules\gamemaster\helpers.dm"
|
||||
#include "code\modules\gamemaster\actions\action.dm"
|
||||
#include "code\modules\gamemaster\actions\carp_migration.dm"
|
||||
#include "code\modules\gamemaster\actions\comms_blackout.dm"
|
||||
#include "code\modules\gamemaster\actions\dust.dm"
|
||||
#include "code\modules\gamemaster\actions\grid_check.dm"
|
||||
#include "code\modules\gamemaster\actions\meteor_defense.dm"
|
||||
#include "code\modules\gamemaster\actions\shipping_error.dm"
|
||||
#include "code\modules\gamemaster\actions\surprise_carp_attack.dm"
|
||||
#include "code\modules\gamemaster\actions\surprise_meteor.dm"
|
||||
#include "code\modules\gamemaster\actions\waste_disposal.dm"
|
||||
#include "code\modules\games\cah.dm"
|
||||
#include "code\modules\games\cah_black_cards.dm"
|
||||
|
||||
Reference in New Issue
Block a user