[MIRROR] Crystal Event: flavor texts, signaler, balancing and mob differentiation (#623)

* Crystal Event: flavor texts, signaler, balancing and mob differentiation

* Update crystal_event.dm

Co-authored-by: Ghilker <42839747+Ghilker@users.noreply.github.com>
Co-authored-by: Azarak <azarak10@gmail.com>
This commit is contained in:
SkyratBot
2020-09-02 03:50:57 +02:00
committed by GitHub
parent 7a526ae9c1
commit 540b6dcdc3
4 changed files with 280 additions and 55 deletions
@@ -18,6 +18,16 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/destabilized_crystal
mid_sounds = list('sound/machines/sm/loops/delamming.ogg' = 1)
mid_length = 60
volume = 55
extra_range = 15
falloff = 5
vary = TRUE
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/looping_sound/generator
start_sound = 'sound/machines/generator/generator_start.ogg'
start_length = 4
+4
View File
@@ -161,6 +161,10 @@
var/shockdamage = 20
var/explosive = TRUE
/obj/effect/anomaly/flux/Initialize(mapload, new_lifespan, drops_core = TRUE, _explosive = TRUE)
. = ..()
explosive = _explosive
/obj/effect/anomaly/flux/anomalyEffect()
..()
canshock = TRUE
+3
View File
@@ -179,6 +179,9 @@
/obj/item/assembly/signaler/anomaly/attack_self()
return
/obj/item/assembly/signaler/crystal_anomaly/attack_self()
return
/obj/item/assembly/signaler/cyborg
/obj/item/assembly/signaler/cyborg/attackby(obj/item/W, mob/user, params)
+263 -55
View File
@@ -35,9 +35,9 @@ This section is for the event controller
earliest_start = 25 MINUTES
/datum/round_event/crystal_invasion
startWhen = 10
startWhen = 5
announceWhen = 1
endWhen = 25 MINUTES
endWhen = 460
///Is the name of the wave, used to check wich wave will be generated
var/wave_name
///Max number of portals that can spawn per type of wave
@@ -95,7 +95,7 @@ This section is for the event controller
anomaly from a portal by using the anomaly neutralizer, place it inside a crystal stabilizer, and inject it into your Supermatter to stop a ZK-Lambda-Class Cosmic Fragmentation Scenario from occurring.", "Alert")
sound_to_playing_players('sound/misc/notice1.ogg')
addtimer(CALLBACK(src, .proc/spawn_portals), 10 SECONDS)
addtimer(CALLBACK(src, .proc/spawn_portals), 3 SECONDS)
///Pick a location from the generic_event_spawns list that are present on the maps and call the spawn anomaly and portal procs
/datum/round_event/crystal_invasion/proc/spawn_portals()
@@ -109,14 +109,26 @@ This section is for the event controller
for(var/i in 1 to 6)
spawn_anomaly(spawners)
addtimer(CALLBACK(src, .proc/more_portals, GLOB.crystal_invasion_waves[wave_name]), 15 MINUTES)
var/list/crystal_spawner_turfs = list()
for(var/range_turf in RANGE_TURFS(6, dest_crystal.loc))
if(!isopenturf(range_turf) || isspaceturf(range_turf))
continue
crystal_spawner_turfs += range_turf
for(var/i in 1 to 6)
if(!length(crystal_spawner_turfs))
break
var/pick_portal = pickweight(GLOB.crystal_invasion_waves["big wave"])
var/turf/crystal_spawner_turf = pick_n_take(crystal_spawner_turfs)
new pick_portal(crystal_spawner_turf)
addtimer(CALLBACK(src, .proc/more_portals, GLOB.crystal_invasion_waves[wave_name]), 10 MINUTES)
///Spawn an anomaly randomly in a different location than spawn_portal()
/datum/round_event/crystal_invasion/proc/spawn_anomaly(list/spawners)
if(!spawners.len)
CRASH("No landmarks on the station map, aborting")
var/obj/spawner = pick(spawners)
new/obj/effect/anomaly/flux(spawner.loc)
new/obj/effect/anomaly/flux(spawner.loc, 30 SECONDS, FALSE, FALSE)
///Spawn one portal in a random location choosen from the generic_event_spawns list
/datum/round_event/crystal_invasion/proc/spawn_portal(list/wave_type, list/spawners)
@@ -129,7 +141,7 @@ This section is for the event controller
///If after 10 minutes the crystal is not stabilized more portals are spawned and the event progress further
/datum/round_event/crystal_invasion/proc/more_portals()
priority_announce("WARNING - Detected another spike from the destabilized crystal. More portals are spawning all around the station, the next spike could \
cause a \[REDACTED] class event we assume you have 10 more minutes before total crystal annihilation", "Alert")
cause a \[REDACTED] class event we assume you have five more minutes before total crystal annihilation", "Alert")
sound_to_playing_players('sound/misc/notice1.ogg')
var/list/spawners = list()
for(var/es in GLOB.generic_event_spawns)
@@ -140,18 +152,17 @@ This section is for the event controller
spawn_portal(GLOB.crystal_invasion_waves["small wave"], spawners)
/datum/round_event/crystal_invasion/tick()
if(dest_crystal == null)
processing = FALSE
message_admins("Deleted Destabilized crystal, aborting")
kill()
if(dest_crystal.is_stabilized == TRUE)
processing = FALSE
is_zk_scenario = FALSE
end()
/datum/round_event/crystal_invasion/end()
if(is_zk_scenario == TRUE)
finish_event()
if(activeFor == endWhen - 10)
processing = FALSE
finish_event()
///Handles wich end the event shall have
/datum/round_event/crystal_invasion/proc/finish_event()
if(is_zk_scenario == TRUE)
zk_event_announcement()
else
restore()
@@ -193,6 +204,7 @@ This section is for the event controller
/datum/round_event/crystal_invasion/proc/on_dest_crystal_qdel()
UnregisterSignal(dest_crystal, COMSIG_PARENT_QDELETING)
processing = FALSE
message_admins("Deleted Destabilized crystal, aborting")
dest_crystal = null
kill()
@@ -213,12 +225,26 @@ This section is for the destabilized SM
var/active = TRUE
///Check if the crew managed to stop the ZK-class event by stabilizing the crystal
var/is_stabilized = FALSE
///Our sound loop
var/datum/looping_sound/destabilized_crystal/soundloop
/obj/machinery/destabilized_crystal/Initialize()
. = ..()
soundloop = new(list(src), TRUE)
/obj/machinery/destabilized_crystal/Destroy()
QDEL_NULL(soundloop)
return ..()
/obj/machinery/destabilized_crystal/process()
if(!active)
return
if(prob(75))
radiation_pulse(src, 250, 6)
if(prob(30))
playsound(loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10)
if(prob(15))
fire_nuclear_particle()
var/turf/loc_turf = loc
var/datum/gas_mixture/env = loc_turf.return_air()
var/datum/gas_mixture/removed
@@ -256,6 +282,36 @@ This section is for the destabilized SM
active = FALSE
is_stabilized = TRUE
/obj/machinery/destabilized_crystal/examine(mob/user)
. = ..()
. += "<span class='notice'>The Crystal appears to be heavily destabilized. Maybe it can be fixed by injecting it with something from another world.</span>"
/obj/machinery/destabilized_crystal/Bumped(atom/movable/movable_atom)
if(!isliving(movable_atom))
return
var/mob/living/user = movable_atom
if(isnull(user.mind))
return
movable_atom.visible_message("<span class='danger'>\The [movable_atom] slams into \the [src] inducing a resonance... [movable_atom.p_their()] body starts to glow and burst into flames before flashing into dust!</span>",\
"<span class='userdanger'>You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"</span>",\
"<span class='hear'>You hear an unearthly noise as a wave of heat washes over you.</span>")
playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE)
consume(movable_atom)
/obj/machinery/destabilized_crystal/proc/consume(atom/movable/movable_atom)
if(isliving(movable_atom))
var/mob/living/user = movable_atom
if(user.status_flags & GODMODE || isnull(user.mind))
return
message_admins("[src] has consumed [key_name_admin(user)] [ADMIN_JMP(src)].")
investigate_log("has consumed [key_name(user)].", INVESTIGATE_SUPERMATTER)
user.dust(force = TRUE)
for(var/find_portal in GLOB.crystal_portals)
var/obj/structure/crystal_portal/portal = find_portal
portal.modify_component()
priority_announce("The sacrifice of a member of the station (we hope was the clown) has weakened the portals and the monsters generation is slowing down!")
sound_to_playing_players('sound/misc/notice2.ogg')
/*
This section is for the crystal stabilizer item and the crystal from the closed portals
*/
@@ -271,6 +327,7 @@ This section is for the crystal stabilizer item and the crystal from the closed
/obj/item/crystal_stabilizer/examine(user)
. = ..()
. += "<span class='notice'>There is a compartment for something small... like a crystal...</span>"
if(!filled)
. += "<span class='notice'>The [src] is empty.</span>"
else
@@ -295,6 +352,27 @@ This section is for the crystal stabilizer item and the crystal from the closed
icon = 'icons/obj/stack_objects.dmi'
material_type = /datum/material/otherworld_crystal
/*
This section is for the signaler part of the crystal portals
*/
/obj/item/assembly/signaler/crystal_anomaly
name = "Nothing here"
desc = "Nothing to see here."
///Link to the crystal
var/anomaly_type = /obj/structure/crystal_portal
/obj/item/assembly/signaler/crystal_anomaly/receive_signal(datum/signal/signal)
if(!signal)
return FALSE
if(signal.data["code"] != code)
return FALSE
if(suicider)
manual_suicide(suicider)
for(var/obj/structure/crystal_portal/portal in get_turf(src))
portal.closed = TRUE
qdel(portal)
return TRUE
/*
This section is for the crystal portals variations
*/
@@ -305,11 +383,12 @@ This section is for the crystal portals variations
icon_state = "anom"
color = COLOR_SILVER
anchored = TRUE
light_range = 3
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
///Max amount of mobs that a portal can spawn in any given time
var/max_mobs = 5
///Spawn time between each mobs
var/spawn_time = 1000
var/spawn_time = 0
///Type of mob that the portal will spawn, if more than one type in the list will choose randomly
var/mob_types = list(/mob/living/simple_animal/hostile/carp)
///Fluff text for each mob spawned
@@ -320,6 +399,8 @@ This section is for the crystal portals variations
var/spawner_type = /datum/component/spawner
///This var check if the portal has been closed by a player with a neutralizer
var/closed = FALSE
///Link to the signaler object for signaling uses
var/obj/item/assembly/signaler/crystal_anomaly/a_signal = /obj/item/assembly/signaler/crystal_anomaly
/obj/structure/crystal_portal/Initialize()
. = ..()
@@ -327,9 +408,18 @@ This section is for the crystal portals variations
GLOB.crystal_portals += src
mob_types = typelist("crystal_portal mob_types", mob_types)
faction = typelist("crystal_portal faction", faction)
a_signal = new a_signal(src)
a_signal.code = rand(1,100)
a_signal.anomaly_type = type
var/frequency = rand(MIN_FREE_FREQ, MAX_FREE_FREQ)
if(ISMULTIPLE(frequency, 2))//signaller frequencies are always uneven!
frequency++
a_signal.set_frequency(frequency)
/obj/structure/crystal_portal/Destroy()
GLOB.crystal_portals -= src
if(a_signal)
QDEL_NULL(a_signal)
if(!closed)
switch(name)
if("Small Portal")
@@ -343,6 +433,10 @@ This section is for the crystal portals variations
new/obj/item/stack/sheet/otherworld_crystal(loc)
return ..()
/obj/structure/crystal_portal/examine(user)
. = ..()
. += "<span class='notice'>The [src] seems to be releasing some sort or high frequency wavelength, maybe it could be closed if another signal is sent back or if an equivalent device is used on it.</span>"
/obj/structure/crystal_portal/attack_animal(mob/living/simple_animal/M)
if(faction_check(faction, M.faction, FALSE) && !M.client)
return ..()
@@ -356,13 +450,19 @@ This section is for the crystal portals variations
to_chat(user, "<span class='notice'>You successfully close \the [src]!</span>")
closed = TRUE
qdel(src)
if(W.tool_behaviour == TOOL_ANALYZER)
to_chat(user, "<span class='notice'>Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(a_signal.frequency)], code [a_signal.code].</span>")
/obj/structure/crystal_portal/proc/modify_component()
spawn_time += 5
AddComponent(spawner_type, mob_types, spawn_time, faction, spawn_text, max_mobs)
/obj/structure/crystal_portal/small
name = "Small Portal"
desc = "A small portal to an unkown dimension!"
color = COLOR_BRIGHT_BLUE
max_mobs = 3
spawn_time = 200
spawn_time = 5 SECONDS
mob_types = list(
/mob/living/simple_animal/hostile/crystal_monster/minion,
/mob/living/simple_animal/hostile/crystal_monster/thug
@@ -372,8 +472,8 @@ This section is for the crystal portals variations
name = "Medium Portal"
desc = "A medium portal to an unkown dimension!"
color = COLOR_GREEN
max_mobs = 5
spawn_time = 180
max_mobs = 4
spawn_time = 10 SECONDS
mob_types = list(
/mob/living/simple_animal/hostile/crystal_monster/minion,
/mob/living/simple_animal/hostile/crystal_monster/thug,
@@ -384,8 +484,8 @@ This section is for the crystal portals variations
name = "Big Portal"
desc = "A big portal to an unkown dimension!"
color = COLOR_RED
max_mobs = 8
spawn_time = 160
max_mobs = 5
spawn_time = 10 SECONDS
mob_types = list(
/mob/living/simple_animal/hostile/crystal_monster/minion,
/mob/living/simple_animal/hostile/crystal_monster/thug,
@@ -397,8 +497,8 @@ This section is for the crystal portals variations
name = "Huge Portal"
desc = "A huge portal to an unkown dimension!"
color = COLOR_BLACK
max_mobs = 12
spawn_time = 140
max_mobs = 6
spawn_time = 15 SECONDS
mob_types = list(
/mob/living/simple_animal/hostile/crystal_monster/minion,
/mob/living/simple_animal/hostile/crystal_monster/thug,
@@ -419,16 +519,10 @@ This section is for the crystal monsters variations
icon_dead = "crystal_minion"
gender = NEUTER
mob_biotypes = MOB_MINERAL|MOB_HUMANOID
turns_per_move = 5
turns_per_move = 1
speak_emote = list("resonates")
emote_see = list("resonates")
a_intent = INTENT_HARM
maxHealth = 25
health = 25
speed = 1.2
harm_intent_damage = 2.5
melee_damage_lower = 5
melee_damage_upper = 5
minbodytemp = 0
maxbodytemp = 1500
healable = 0 //they're crystals how would bruise packs help them??
@@ -438,13 +532,16 @@ This section is for the crystal monsters variations
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 10
robust_searching = 1
stat_attack = UNCONSCIOUS
stat_attack = HARD_CRIT
faction = list("crystal")
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
deathmessage = "collapses into dust!"
del_on_death = 1
footstep_type = FOOTSTEP_MOB_SHOE
stop_automated_movement = FALSE
stop_automated_movement_when_pulled = FALSE
wander = TRUE
/mob/living/simple_animal/hostile/crystal_monster/minion
name = "crystal minion"
@@ -453,12 +550,26 @@ This section is for the crystal monsters variations
icon_state = "crystal_minion"
icon_living = "crystal_minion"
icon_dead = "crystal_minion"
maxHealth = 40
health = 40
speed = 1.5
harm_intent_damage = 5
melee_damage_lower = 5
melee_damage_upper = 10
maxHealth = 20
health = 20
speed = 0.8
harm_intent_damage = 11
melee_damage_lower = 20
melee_damage_upper = 35
move_force = MOVE_FORCE_WEAK
move_resist = MOVE_FORCE_WEAK
pull_force = MOVE_FORCE_WEAK
var/death_cloud_size = 2
/mob/living/simple_animal/hostile/crystal_monster/minion/Destroy()
if(isturf(loc))
var/datum/effect_system/smoke_spread/chem/S = new
create_reagents(3)
reagents.add_reagent(/datum/reagent/toxin/lexorin, 4)
S.attach(loc)
S.set_up(reagents, death_cloud_size, loc, silent = TRUE)
S.start()
return ..()
/mob/living/simple_animal/hostile/crystal_monster/thug
name = "crystal thug"
@@ -467,12 +578,30 @@ This section is for the crystal monsters variations
icon_state = "crystal_thug"
icon_living = "crystal_thug"
icon_dead = "crystal_thug"
maxHealth = 50
health = 50
speed = 1.3
harm_intent_damage = 9
melee_damage_lower = 15
melee_damage_upper = 20
maxHealth = 20
health = 20
speed = 0.9
harm_intent_damage = 11
melee_damage_lower = 20
melee_damage_upper = 35
move_force = MOVE_FORCE_NORMAL
move_resist = MOVE_FORCE_NORMAL
pull_force = MOVE_FORCE_NORMAL
dodging = TRUE
dodge_prob = 25
/mob/living/simple_animal/hostile/crystal_monster/thug/attackby(obj/item/O, mob/user, params)
if(prob(30))
var/list/temp_turfs = list()
for(var/turf/around_turfs in view(7, src))
if(!isopenturf(around_turfs) || isspaceturf(around_turfs))
continue
temp_turfs += around_turfs
if(length(temp_turfs))
var/turf/open/choosen_turf = pick(temp_turfs)
do_teleport(src, choosen_turf)
return
return ..()
/mob/living/simple_animal/hostile/crystal_monster/recruit
name = "crystal recruit"
@@ -481,12 +610,24 @@ This section is for the crystal monsters variations
icon_state = "crystal_recruit"
icon_living = "crystal_recruit"
icon_dead = "crystal_recruit"
maxHealth = 65
health = 65
maxHealth = 20
health = 20
speed = 1.2
harm_intent_damage = 11
melee_damage_lower = 20
melee_damage_upper = 35
move_force = MOVE_FORCE_STRONG
move_resist = MOVE_FORCE_STRONG
pull_force = MOVE_FORCE_STRONG
obj_damage = 100
environment_smash = ENVIRONMENT_SMASH_WALLS
/mob/living/simple_animal/hostile/crystal_monster/recruit/Bump(atom/clong)
. = ..()
if(isturf(clong))
var/turf/turf_bump = clong
turf_bump.Melt()
playsound(get_turf(src), 'sound/effects/supermatter.ogg', 35, TRUE)
/mob/living/simple_animal/hostile/crystal_monster/killer
name = "crystal killer"
@@ -495,12 +636,40 @@ This section is for the crystal monsters variations
icon_state = "crystal_killer"
icon_living = "crystal_killer"
icon_dead = "crystal_killer"
maxHealth = 80
health = 80
speed = 1.2
harm_intent_damage = 13
melee_damage_lower = 30
maxHealth = 35
health = 35
speed = 0.75
harm_intent_damage = 20
melee_damage_lower = 25
melee_damage_upper = 45
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
dodging = TRUE
dodge_prob = 35
environment_smash = ENVIRONMENT_SMASH_RWALLS
projectiletype = /obj/projectile/temp/basilisk
projectilesound = 'sound/weapons/pierce.ogg'
ranged = 1
ranged_message = "throws"
ranged_cooldown_time = 25
/obj/projectile/temp/crystal_killer
name = "freezing blast"
icon_state = "ice_2"
color = COLOR_YELLOW
damage = 0
damage_type = BURN
nodamage = TRUE
flag = ENERGY
temperature = -75
/mob/living/simple_animal/hostile/crystal_monster/killer/Bump(atom/clong)
. = ..()
if(isturf(clong))
var/turf/turf_bump = clong
turf_bump.Melt()
playsound(get_turf(src), 'sound/effects/supermatter.ogg', 35, TRUE)
/mob/living/simple_animal/hostile/crystal_monster/boss
name = "crystal boss"
@@ -509,9 +678,48 @@ This section is for the crystal monsters variations
icon_state = "crystal_boss"
icon_living = "crystal_boss"
icon_dead = "crystal_boss"
maxHealth = 150
health = 150
speed = 1
harm_intent_damage = 15
melee_damage_lower = 45
melee_damage_upper = 65
maxHealth = 300
health = 30
speed = 1.3
harm_intent_damage = 11
melee_damage_lower = 20
melee_damage_upper = 35
move_force = MOVE_FORCE_EXTREMELY_STRONG
move_resist = MOVE_FORCE_EXTREMELY_STRONG
pull_force = MOVE_FORCE_EXTREMELY_STRONG
environment_smash = ENVIRONMENT_SMASH_RWALLS
projectiletype = /obj/projectile/magic/aoe/lightning
projectilesound = 'sound/weapons/pierce.ogg'
ranged = 1
ranged_message = "throws"
ranged_cooldown_time = 45
/mob/living/simple_animal/hostile/crystal_monster/boss/Bump(atom/clong)
. = ..()
if(isliving(clong))
var/mob/living/mob = clong
if(mob.stat >= HARD_CRIT)
mob.dust()
health += 35
else if(isturf(clong))
var/turf/turf_bump = clong
turf_bump.Melt()
playsound(get_turf(src), 'sound/effects/supermatter.ogg', 35, TRUE)
/mob/living/simple_animal/hostile/crystal_monster/boss/AttackingTarget()
. = ..()
if(isliving(target))
var/mob/living/mob = target
if(mob.stat >= HARD_CRIT)
mob.dust()
health += 35
else
var/obj/item/bodypart/body_part = mob.get_bodypart(pick(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
if(body_part)
body_part.drop_limb(FALSE, TRUE)
else if(isturf(target))
var/turf/turf_bump = target
turf_bump.Melt()
playsound(get_turf(src), 'sound/effects/supermatter.ogg', 35, TRUE)