forked from Sea-of-Lost-Souls/Tannhauser-Gate
-
Notifications
You must be signed in to change notification settings - Fork 1
/
earthquake.dm
180 lines (153 loc) · 7.84 KB
/
earthquake.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
///Earthquake random event.
///Draws a curve of turfs between a high and low point. These turfs will shake and eventually "collapse", forming a cut in the station that drops to the z-level below.
///Much of the actual structural damage is done through the explosions subsystem. Objects, machines, and especially people
///that aren't moved out of the epicenter area (indicated by the wobbly tiles) will not just be thrown down a z-level, but also be destroyed/maimed in the process.
/datum/round_event_control/earthquake
name = "Chasmic Earthquake"
description = "Causes an earthquake, demolishing anything caught in the fault."
typepath = /datum/round_event/earthquake
category = EVENT_CATEGORY_ENGINEERING
min_players = 20
max_occurrences = 3
earliest_start = 35 MINUTES
weight = 7
min_wizard_trigger_potency = 3
max_wizard_trigger_potency = 7
map_flags = EVENT_PLANETARY_ONLY
/datum/round_event_control/earthquake/can_spawn_event(players_amt, allow_magic)
. = ..()
if(!.)
return .
if(!length(GLOB.generic_event_spawns))
return FALSE
/datum/round_event/earthquake
start_when = 1
announce_when = 3
end_when = 25
announce_chance = 25
///The chosen location and center of our earthquake.
var/turf/epicenter
///A list of turfs that will be damaged by this event.
var/list/turfs_to_shred
///A list of turfs directly under turfs_to_shred, for creating a proper chasm to the floor below.
var/list/underbelly = list()
///The edges of our fault line, to receive light damage.
var/list/edges = list()
/datum/round_event/earthquake/setup()
epicenter = get_turf(pick(GLOB.generic_event_spawns))
if(!epicenter)
message_admins("Earthquake event failed to find a turf! generic_event_spawn landmarks may be absent or bugged. Aborting...")
return
// Give a bit of variance so our epicenter isn't always on the landmark.
epicenter = locate(epicenter.x + rand(-10, 10), epicenter.y + rand(-10, 10), epicenter.z)
message_admins("An earthquake event is about to strike the [get_area_name(epicenter)][ADMIN_JMP(epicenter)].")
// Picks two points generally opposite from each other
var/turf/fracture_point_high = locate(epicenter.x + rand(4, 10), epicenter.y + rand(4, 8), epicenter.z)
var/turf/fracture_point_low = locate(epicenter.x - rand(4, 10), epicenter.y - rand(4, 8), epicenter.z)
turfs_to_shred = block(fracture_point_high, fracture_point_low)
// Now, we filter out some of the points that are a certain distance away from a rough approximation of the fault line.
// This should create a pattern more akin to a fracture in the ground, rather than a rectangle-shaped crater of destroyed ground.
var/turf/high_midpoint = TURF_MIDPOINT(fracture_point_high, epicenter)
var/turf/low_midpoint = TURF_MIDPOINT(fracture_point_low, epicenter)
// We populate a list with the midpoints and midpoints of midpoints to create a rough line of turfs to compare distances against.
var/list/turfs_to_compare = list(
fracture_point_high,
fracture_point_low,
high_midpoint,
low_midpoint,
TURF_MIDPOINT(fracture_point_high, high_midpoint),
TURF_MIDPOINT(fracture_point_low, low_midpoint),
TURF_MIDPOINT(high_midpoint, epicenter),
TURF_MIDPOINT(low_midpoint, epicenter),
)
// Find the shortest distance between each turf in the list and the rough fault line we've just established
for(var/turf/turf_to_check in turfs_to_shred)
var/nearest_distance = get_dist(turf_to_check, epicenter)
for(var/turf/turf_to_compare in turfs_to_compare)
nearest_distance = min(get_dist(turf_to_check, turf_to_compare), nearest_distance)
// If the turf is too far from any point on our fault line estimate, we remove it. If it's on the edge, we lightly damage it
if(nearest_distance > 2)
if(nearest_distance == 3)
edges += turf_to_check
turfs_to_shred -= turf_to_check
// Grab a list of turfs below the ones we're going to destroy.
// If we're at the bottom layer, it will just tear up the flooring a bunch (exposing it to LAVA).
for(var/turf/turf_to_quake in turfs_to_shred)
underbelly += GET_TURF_BELOW(turf_to_quake)
/datum/round_event/earthquake/announce(fake)
priority_announce("Planetary monitoring systems indicate a devastating seismic event in the near future.", "Seismic Report")
/datum/round_event/earthquake/start()
notify_ghosts(
"The earthquake's epicenter has been located: [get_area_name(epicenter)]!",
source = epicenter,
header = "Rumble Rumble Rumble!",
)
/datum/round_event/earthquake/tick()
if(ISMULTIPLE(activeFor, 5))
for(var/turf/turf_to_quake in turfs_to_shred)
turf_to_quake.Shake(pixelshiftx = 0.1, pixelshifty = 0.1, duration = 1 SECONDS)
if(ISMULTIPLE(activeFor, 10))
for(var/mob/earthquake_witness as anything in GLOB.player_list)
if(!is_station_level(earthquake_witness.z))
continue
shake_camera(earthquake_witness, 1 SECONDS, 1 + (activeFor % 10))
earthquake_witness.playsound_local(
earthquake_witness,
pick(
'sound/misc/earth_rumble_distant1.ogg',
'sound/misc/earth_rumble_distant2.ogg',
'sound/misc/earth_rumble_distant3.ogg',
'sound/misc/earth_rumble_distant4.ogg',
),
75,
)
for(var/turf/turf_to_quake in underbelly)
turf_to_quake.Shake(pixelshiftx = 0.1, pixelshifty = 0.1, duration = 1 SECONDS)
if(activeFor == end_when - 2)
for(var/turf/turf_to_quake in turfs_to_shred)
turf_to_quake.Shake(pixelshiftx = 0.5, pixelshifty = 0.5, duration = 1 SECONDS)
for(var/mob/living/quake_victim in turf_to_quake)
quake_victim.Knockdown(7 SECONDS)
quake_victim.Paralyze(5 SECONDS)
to_chat(quake_victim, span_warning("The ground quakes violently beneath you, throwing you off your feet!"))
for(var/turf/turf_to_quake in underbelly)
turf_to_quake.Shake(pixelshiftx = 0.5, pixelshifty = 0.5, duration = 1 SECONDS)
for(var/mob/living/carbon/quake_victim in turf_to_quake)
to_chat(quake_victim, span_warning("Damn, I wonder what that rumbling noise is?")) ///You're about to find out
// Step one of the destruction, which clears natural tiles out from the underbelly and does a bit of initial damage to the topside.
if(activeFor == end_when - 1)
for(var/turf/turf_to_shred in turfs_to_shred)
if(prob(90))
SSexplosions.lowturf += turf_to_shred
for(var/turf/turf_to_clear in underbelly)
if(ismineralturf(turf_to_clear))
var/turf/closed/mineral/rock_to_clear = turf_to_clear
rock_to_clear.gets_drilled(give_exp = FALSE)
for(var/turf/turf_to_quake in edges)
turf_to_quake.Shake(pixelshiftx = 0.5, pixelshifty = 0.5, duration = 1 SECONDS)
playsound(epicenter, 'sound/misc/metal_creak.ogg', 125, TRUE)
/datum/round_event/earthquake/end()
playsound(epicenter, 'sound/misc/earth_rumble.ogg', 125)
for(var/mob/earthquake_witness as anything in GLOB.player_list)
if(!is_station_level(earthquake_witness.z) || !is_mining_level(earthquake_witness.z))
continue
shake_camera(earthquake_witness, 2 SECONDS, 4)
earthquake_witness.playsound_local(earthquake_witness, 'sound/effects/explosionfar.ogg', 75)
// Step two of the destruction, which detonates the turfs in the earthquake zone. There is no actual explosion, meaning stuff around the earthquake zone is perfectly safe.
// All turfs, and everything else that IS in the earthquake zone, however, will behave as if it were bombed.
// If you are caught in the earthquake zone, you will not only die but probably be torn apart in the process.
for(var/turf/turf_to_shred in turfs_to_shred)
if(prob(10))
SSexplosions.medturf += turf_to_shred
else
SSexplosions.highturf += turf_to_shred
if(isasteroidturf(turf_to_shred) && prob(95))
turf_to_shred.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
for(var/mob/living/carbon/quake_victim in turf_to_shred)
if(quake_victim.client)
quake_victim.client.give_award(/datum/award/achievement/misc/earthquake_victim, quake_victim)
for(var/turf/edge_to_damage in edges)
if(prob(25))
SSexplosions.medturf += edge_to_damage
else
SSexplosions.lowturf += edge_to_damage