Skip to content

Commit d903539

Browse files
mudzbeTiviPlusLumipharon
authored
Fully implement Zombie Crash Gamemode [port] (#18276)
Co-authored-by: TiviPlus <57223640+TiviPlus@users.noreply.github.com> Co-authored-by: Lumipharon <amadeusrandom@gmail.com>
1 parent 8c5fbc7 commit d903539

File tree

47 files changed

+949
-195
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+949
-195
lines changed

_maps/map_files/generic/Admin_Level.dmm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@
12041204
},
12051205
/area/centcom/valhalla)
12061206
"bsY" = (
1207-
/obj/effect/landmark/corpsespawner/colonist,
1207+
/obj/effect/landmark/corpsespawner/colonist/valhalla,
12081208
/turf/open/floor/plating/ground/mars/random/cave,
12091209
/area/centcom/valhalla/xenocave)
12101210
"bur" = (
@@ -3507,7 +3507,7 @@
35073507
/area/centcom/valhalla)
35083508
"eAt" = (
35093509
/obj/effect/turf_decal/sandytile/sandyplating,
3510-
/obj/effect/landmark/corpsespawner/pmc,
3510+
/obj/effect/landmark/corpsespawner/PMC/valhalla,
35113511
/turf/open/floor/plating,
35123512
/area/centcom/valhalla)
35133513
"eAE" = (

code/__DEFINES/ai.dm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,5 @@ GLOBAL_LIST_INIT(ai_squad_presets, list(
351351
/datum/job/terragov/squad/smartgunner/npc,
352352
),
353353
))
354+
355+
GLOBAL_LIST_EMPTY(zombie_spawners)

code/__DEFINES/conflict.dm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
#define AMMO_SOUND_PITCH (1<<16)
7777
///Is this projectile considered sniper ammo, used for the anti sniper stacking status effect
7878
#define AMMO_SNIPER (1<<17)
79+
///Ammo type entirely ignores xenos
80+
#define AMMO_SKIPS_ZOMBIE (1<<18)
7981

8082
//Gun defines for gun related thing. More in the projectile folder.
8183
//gun_features_flags

code/__DEFINES/dcs/signals/signals.dm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
#define COMSIG_GLOB_AI_MINION_RALLY "!ai_minion_rally"
6565
#define COMSIG_GLOB_HIVE_TARGET_DRAINED "!hive_target_drained"
6666

67+
///from proc/global_rally_zombies()
68+
#define COMSIG_GLOB_AI_ZOMBIE_RALLY "!ai_zombie_rally"
69+
6770
/// Sent when a marine dropship enters transit level
6871
#define COMSIG_GLOB_DROPSHIP_TRANSIT "!dropship_transit"
6972
///Sent when xenos launch a hijacked dropship
@@ -156,6 +159,8 @@
156159
///from /datum/action/ability/activable/build_designator/indicate_target()
157160
#define COMSIG_GLOB_DESIGNATED_TARGET_SET "!designated_target_set"
158161

162+
#define COMSIG_GLOB_ZOMBIE_TUNNEL_DESTROYED "!ZOMBIE_TUNNEL_DESTROYED"
163+
159164
//////////////////////////////////////////////////////////////////
160165
// /datum/component signals
161166
#define COMSIG_AUTOFIRE_ONMOUSEDOWN "autofire_onmousedown"

code/__DEFINES/is_helpers.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ GLOBAL_LIST_INIT(turfs_openspace, typecacheof(list(
335335

336336
//Gamemode
337337
#define iscrashgamemode(O) (istype(O, /datum/game_mode/infestation/crash))
338+
#define iszombiecrashgamemode(O) (istype(O, /datum/game_mode/infestation/crash/zombie))
338339
#define isinfestationgamemode(O) (istype(O, /datum/game_mode/infestation))
339340
#define iscombatpatrolgamemode(O) (istype(O, /datum/game_mode/hvh/combat_patrol))
340341
#define issensorcapturegamemode(O) (istype(O, /datum/game_mode/hvh/combat_patrol/sensor_capture))

code/__DEFINES/mode.dm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@
7575
#define MODE_INFESTATION_M_MAJOR "Marine Major Victory"
7676
#define MODE_INFESTATION_X_MINOR "Xenomorph Minor Victory"
7777
#define MODE_INFESTATION_M_MINOR "Marine Minor Victory"
78+
79+
#define MODE_ZOMBIE_Z_MAJOR "Zombie Major Victory"
80+
#define MODE_ZOMBIE_Z_MINOR "Zombie Minor Victory"
81+
7882
#define MODE_INFESTATION_DRAW_DEATH "DRAW: Mutual Annihilation"
7983

8084
#define MODE_GENERIC_DRAW_NUKE "DRAW: Nuclear Explosion"

code/__DEFINES/zombie.dm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
///How frequently the proximity alert can go off
2+
#define ZOMBIE_STRUCTURE_DETECTION_COOLDOWN 1 MINUTES
3+
///How frequently defenders can be spawned in response to a proximity alarm
4+
#define ZOMBIE_STRUCTURE_DEFENDER_COOLDOWN 5 MINUTES
5+
///Proxy detection radius
6+
#define ZOMBIE_STRUCTURE_DETECTION_RANGE 15
7+
///Defender spawn amount
8+
#define ZOMBIE_DEFENDER_AMOUNT 13

code/controllers/subsystem/minimap/minimap_action_subtypes.dm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
minimap_flags = MINIMAP_FLAG_MARINE_SOM
2828
marker_flags = MINIMAP_FLAG_MARINE_SOM
2929

30+
/datum/action/minimap/lone
31+
minimap_flags = MINIMAP_FLAG_LONE
32+
3033
/datum/action/minimap/observer
3134
minimap_flags = MINIMAP_FLAG_XENO|MINIMAP_FLAG_MARINE|MINIMAP_FLAG_MARINE_SOM|MINIMAP_FLAG_EXCAVATION_ZONE
3235
marker_flags = NONE

code/controllers/subsystem/spawning.dm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
#define MAXIMUM_DEFAULT_SPAWN 120
2+
#define MAXIMUM_DEFAULT_SPAWN 400
33

44
SUBSYSTEM_DEF(spawning)
55
name = "Spawning"
@@ -81,7 +81,7 @@ SUBSYSTEM_DEF(spawning)
8181
for(var/b = 0 to spawnerdata[spawner].spawnamount)
8282
if(length(spawnerdata[spawner].spawnedmobs) >= spawnerdata[spawner].max_allowed_mobs)
8383
break
84-
var/spawntype = pick(spawnerdata[spawner].spawntypes)
84+
var/spawntype = pickweight(spawnerdata[spawner].spawntypes)
8585
var/mob/newmob = new spawntype(spawnpoint)
8686

8787
var/datum/callback/deathcb = CALLBACK(src, PROC_REF(decrement_spawnedmobs), newmob, spawner)
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
// ***************************************
2+
// *********** Emit Gas
3+
// ***************************************
4+
/datum/action/ability/emit_gas
5+
name = "Emit Gas"
6+
action_icon_state = "emit_neurogas"
7+
action_icon = 'icons/Xeno/actions/defiler.dmi'
8+
desc = "Use to emit a cloud of blinding smoke."
9+
cooldown_duration = 30 SECONDS
10+
keybind_flags = ABILITY_KEYBIND_USE_ABILITY|ABILITY_IGNORE_SELECTED_ABILITY
11+
keybinding_signals = list(
12+
KEYBINDING_NORMAL = COMSIG_XENOABILITY_EMIT_NEUROGAS,
13+
)
14+
/// Used for particles. Holds the particles instead of the mob. See particle_holder for documentation.
15+
var/obj/effect/abstract/particle_holder/particle_holder
16+
/// smoke type created when the grenade is primed
17+
var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/bad
18+
///radius this smoke grenade will encompass
19+
var/smokeradius = 4
20+
///The duration of the smoke in 2 second ticks
21+
var/smoke_duration = 5
22+
23+
/datum/action/ability/emit_gas/on_cooldown_finish()
24+
playsound(owner.loc, 'sound/effects/alien/new_larva.ogg', 50, 0)
25+
to_chat(owner, span_xenodanger("We feel our smoke filling us once more. We can emit gas again."))
26+
toggle_particles(TRUE)
27+
return ..()
28+
29+
/datum/action/ability/emit_gas/action_activate()
30+
var/datum/effect_system/smoke_spread/smoke = new smoketype()
31+
var/turf/owner_turf = get_turf(owner)
32+
playsound(owner_turf, 'sound/effects/smoke_bomb.ogg', 25, TRUE)
33+
smoke.set_up(smokeradius, owner_turf, smoke_duration)
34+
smoke.start()
35+
toggle_particles(FALSE)
36+
37+
add_cooldown()
38+
succeed_activate()
39+
40+
owner.record_war_crime()
41+
42+
/datum/action/ability/emit_gas/ai_should_start_consider()
43+
return TRUE
44+
45+
/datum/action/ability/emit_gas/ai_should_use(atom/target)
46+
if(!iscarbon(target))
47+
return FALSE
48+
var/mob/living/carbon/carbon_target = target
49+
if(carbon_target.faction == owner.faction)
50+
return FALSE
51+
if(get_dist(carbon_target, owner) > 2)
52+
return FALSE
53+
if(!can_use_action(override_flags = ABILITY_IGNORE_SELECTED_ABILITY))
54+
return FALSE
55+
if(!line_of_sight(owner, carbon_target))
56+
return FALSE
57+
return TRUE
58+
59+
/// Toggles particles on or off
60+
/datum/action/ability/emit_gas/proc/toggle_particles(activate)
61+
if(!activate)
62+
QDEL_NULL(particle_holder)
63+
return
64+
65+
particle_holder = new(owner, /particles/smoker_zombie)
66+
particle_holder.pixel_y = 6
67+
68+
/datum/action/ability/emit_gas/give_action(mob/living/L)
69+
. = ..()
70+
toggle_particles(TRUE)
71+
72+
/datum/action/ability/emit_gas/remove_action(mob/living/L)
73+
. = ..()
74+
QDEL_NULL(particle_holder)
75+
76+
/datum/action/ability/emit_gas/Destroy()
77+
. = ..()
78+
QDEL_NULL(particle_holder)
79+
80+
81+
/datum/action/ability/activable/pounce
82+
name = "Pounce"
83+
desc = "Leap at your target, tackling and disarming them."
84+
action_icon_state = "pounce"
85+
action_icon = 'icons/Xeno/actions/runner.dmi'
86+
cooldown_duration = 10 SECONDS
87+
keybinding_signals = list(
88+
KEYBINDING_NORMAL = COMSIG_XENOABILITY_HUNTER_POUNCE,
89+
)
90+
use_state_flags = ABILITY_USE_BUCKLED
91+
/// The range of this ability.
92+
var/pounce_range = 4
93+
/// The stun duration (inflicted to mob) on successful tackle.
94+
var/stun_duration = 2 SECONDS
95+
/// The immobilize duration (inflicted to self) on successful tackle.
96+
var/self_immobilize_duration = 1 SECONDS
97+
98+
/datum/action/ability/activable/pounce/on_cooldown_finish()
99+
owner.balloon_alert(owner, "pounce ready")
100+
owner.playsound_local(owner, 'sound/effects/alien/new_larva.ogg', 25, 0, 1)
101+
return ..()
102+
103+
/datum/action/ability/activable/pounce/can_use_ability(atom/A, silent = FALSE, override_flags)
104+
if(!A)
105+
return FALSE
106+
return ..()
107+
108+
/datum/action/ability/activable/pounce/ai_should_start_consider()
109+
return TRUE
110+
111+
/datum/action/ability/activable/pounce/ai_should_use(atom/target)
112+
if(!iscarbon(target))
113+
return FALSE
114+
var/mob/living/carbon/carbon_target = target
115+
if(carbon_target.faction == owner.faction)
116+
return FALSE
117+
if(!line_of_sight(owner, target, pounce_range))
118+
return FALSE
119+
if(!can_use_ability(target, override_flags = ABILITY_IGNORE_SELECTED_ABILITY))
120+
return FALSE
121+
return TRUE
122+
123+
/datum/action/ability/activable/pounce/use_ability(atom/A)
124+
if(owner.buckled)
125+
owner.buckled.unbuckle_mob(owner)
126+
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(movement_fx))
127+
RegisterSignal(owner, COMSIG_MOVABLE_POST_THROW, PROC_REF(pounce_complete))
128+
RegisterSignal(owner, COMSIG_MOVABLE_PREBUMP_MOVABLE, PROC_REF(mob_hit))
129+
owner.throw_at(A, pounce_range, 2, owner)
130+
succeed_activate()
131+
add_cooldown()
132+
133+
if(!owner.throwing) //if we instantly run into something, the throw is already over
134+
pounce_complete()
135+
return
136+
owner.remove_pass_flags(PASS_MOB, THROW_TRAIT) //we explicitly want to hit people
137+
138+
///Visual mid pounce
139+
/datum/action/ability/activable/pounce/proc/movement_fx()
140+
SIGNAL_HANDLER
141+
new /obj/effect/temp_visual/after_image(get_turf(owner), owner)
142+
143+
///Impact checks mid pounce
144+
/datum/action/ability/activable/pounce/proc/mob_hit(datum/source, mob/living/living_target)
145+
SIGNAL_HANDLER
146+
if(!istype(living_target))
147+
return
148+
149+
. = TRUE
150+
151+
if(living_target.faction == owner.faction) //we leap past friendlies
152+
return
153+
154+
if(ishuman(living_target) && (angle_to_dir(Get_Angle(owner.throw_source, living_target)) in reverse_nearby_direction(living_target.dir)))
155+
var/mob/living/carbon/human/human_target = living_target
156+
if(!human_target.check_shields(COMBAT_TOUCH_ATTACK, 30, "melee"))
157+
var/mob/living/living_owner = owner
158+
living_owner.Paralyze(stun_duration)
159+
living_owner.set_throwing(FALSE)
160+
return
161+
trigger_pounce_effect(living_target)
162+
pounce_complete()
163+
164+
///Triggers the effect of a successful pounce on the target
165+
/datum/action/ability/activable/pounce/proc/trigger_pounce_effect(mob/living/living_target)
166+
var/mob/living/living_owner = owner
167+
playsound(get_turf(living_target), 'sound/voice/alien/pounce.ogg', 25, TRUE)
168+
living_owner.Immobilize(self_immobilize_duration)
169+
living_owner.forceMove(get_turf(living_target))
170+
living_target.Knockdown(stun_duration)
171+
GLOB.round_statistics.runner_pounce_victims++
172+
SSblackbox.record_feedback("tally", "round_statistics", 1, "runner_pounce_victims")
173+
174+
///Cleans up after pounce is complete
175+
/datum/action/ability/activable/pounce/proc/pounce_complete()
176+
SIGNAL_HANDLER
177+
UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_PREBUMP_MOVABLE, COMSIG_MOVABLE_POST_THROW))
178+
179+
// ***************************************
180+
// *********** Boomer Explode
181+
// ***************************************
182+
/datum/action/ability/boomer_explode
183+
name = "Boomer Explode"
184+
action_icon_state = "baneling_explode"
185+
action_icon = 'icons/Xeno/actions/baneling.dmi'
186+
desc = "Explode and spread dangerous toxins to hinder or kill your foes. You die."
187+
keybinding_signals = list(
188+
KEYBINDING_NORMAL = COMSIG_XENOABILITY_BANELING_EXPLODE,
189+
)
190+
191+
/datum/action/ability/boomer_explode/give_action(mob/living/L)
192+
. = ..()
193+
RegisterSignal(L, COMSIG_MOB_PRE_DEATH, PROC_REF(handle_smoke))
194+
195+
/datum/action/ability/boomer_explode/remove_action(mob/living/L)
196+
. = ..()
197+
UnregisterSignal(L, COMSIG_MOB_PRE_DEATH)
198+
199+
/datum/action/ability/boomer_explode/action_activate()
200+
. = ..()
201+
owner.record_tactical_unalive()
202+
handle_smoke()
203+
204+
/// This proc defines, and sets up and then lastly starts the smoke, if ability is false we divide range by 4.
205+
/datum/action/ability/boomer_explode/proc/handle_smoke(datum/source)
206+
SIGNAL_HANDLER
207+
UnregisterSignal(owner, COMSIG_MOB_PRE_DEATH)
208+
var/turf/own_turf = get_turf(owner)
209+
var/datum/effect_system/smoke_spread/smoke = new /datum/effect_system/smoke_spread/xeno/neuro(own_turf)
210+
smoke.set_up(3, own_turf, 4)
211+
playsound(own_turf, 'sound/effects/blobattack.ogg', 25)
212+
smoke.start()
213+
214+
owner.record_war_crime()
215+
INVOKE_NEXT_TICK(owner, TYPE_PROC_REF(/mob/living, death), TRUE)
216+
217+
/datum/action/ability/boomer_explode/ai_should_start_consider()
218+
return TRUE
219+
220+
/datum/action/ability/boomer_explode/ai_should_use(atom/target)
221+
if(!iscarbon(target))
222+
return FALSE
223+
var/mob/living/living_owner = owner
224+
if(living_owner.health > (living_owner.maxHealth * 0.3))
225+
return FALSE
226+
var/mob/living/carbon/carbon_target = target
227+
if(carbon_target.faction == owner.faction)
228+
return FALSE
229+
if(get_dist(target, owner) > 1)
230+
return FALSE
231+
if(!line_of_sight(owner, target))
232+
return FALSE
233+
return TRUE
234+
235+
// ***************************************
236+
// *********** Bile spit
237+
// ***************************************
238+
/datum/action/ability/activable/bile_spit
239+
name = "Bile spit"
240+
action_icon_state = "spray_acid"
241+
action_icon = 'icons/Xeno/actions/boiler.dmi'
242+
desc = "Hurl a glob of bile at your foes."
243+
cooldown_duration = 6 SECONDS
244+
keybinding_signals = list(
245+
KEYBINDING_NORMAL = COMSIG_XENOABILITY_PSYCHIC_BLAST,
246+
)
247+
///Ammo type to fire
248+
var/spit_type = /datum/ammo/bile_spit
249+
250+
/datum/action/ability/activable/bile_spit/on_cooldown_finish()
251+
owner.balloon_alert(owner, "Bile ready")
252+
playsound(owner, 'sound/effects/refill.ogg', 50, 1)
253+
return ..()
254+
255+
/datum/action/ability/activable/bile_spit/use_ability(atom/A)
256+
owner.do_jitter_animation(1000)
257+
if(!do_after(owner, 1 SECONDS, IGNORE_TARGET_LOC_CHANGE, A, BUSY_ICON_DANGER) || !can_use_ability(A, FALSE, ABILITY_IGNORE_SELECTED_ABILITY) || !(A in range(get_screen_size(TRUE), owner)))
258+
fail_activate()
259+
return
260+
261+
succeed_activate()
262+
add_cooldown()
263+
264+
var/atom/movable/projectile/projectile = new /atom/movable/projectile(owner.loc)
265+
projectile.generate_bullet(spit_type)
266+
projectile.fire_at(A, owner, owner, projectile.ammo.max_range, projectile.ammo.shell_speed)
267+
playsound(owner, 'sound/effects/blobattack.ogg', 40, 1)
268+
269+
/datum/action/ability/activable/bile_spit/ai_should_start_consider()
270+
return TRUE
271+
272+
/datum/action/ability/activable/bile_spit/ai_should_use(atom/target)
273+
if(!iscarbon(target))
274+
return FALSE
275+
var/mob/living/carbon/carbon_target = target
276+
if(carbon_target.faction == owner.faction)
277+
return FALSE
278+
if(!line_of_sight(owner, target, 8))
279+
return FALSE
280+
if(check_path(owner, target, PASS_PROJECTILE|PASS_MOB) != get_turf(target))
281+
return
282+
if(!can_use_ability(target, override_flags = ABILITY_IGNORE_SELECTED_ABILITY))
283+
return FALSE
284+
return TRUE

0 commit comments

Comments
 (0)