Files
Batrachophreno 3c2bd9bb45 Overmap hazard rebalance (#21571)
# Summary

This PR rebalances the spawn count and radius of overmap hazard
clusters, as well as adjusts some of their overmap movement behavior.

## Justification

Mining trips to exoplanets distant to the Horizon can force miners to
spend large portions of a given round just trying to navigate around
overmap hazards; in the worst cases, the sheer number of dead ends and
blind spots can result in their effective removal from the first 60-90
minutes of a round, and the worst delays can obviate the need for their
materials in the first place. While reducing these hazards would also
benefit the Horizon and offships, the primary motivation was to reduce
mining's "dead time" in any given round.

## Details

Most overmap hazard types have had their 'count' (the number of clusters
spawned) and radius reduced, to open up more navigable space on the
overmap. This has been compensated for by modifying movement
probabilities, speeds, and behaviors of overmap hazards.

The intervals between overmap hazards moving (their effective speeds)
has been made variable; different clusters of movable hazards will no
longer always proc movement at the same time.

Carp continue to have a random chance to move in a random direction
every interval. Space dust and meteors now also have a chance to spawn
in as movable hazards, but they will only ever move in one direction.
While more dangerous to passing shuttles and ships than carp, they are
also much more predictable.

The current numbers were based on observation of several randomly
generated maps during testing, but will likely need adjustment as it
faces actual miners and we accumulate their feedback. I erred on the
side of 'less difficult' to avoid overtuned rocks from smashing crew to
pieces every round.
2025-11-13 18:42:06 +00:00

138 lines
4.6 KiB
Plaintext

/datum/event/meteor_wave
startWhen = 86
endWhen = 9999//safety value, will be set during ticks
has_skybox_image = TRUE
var/next_meteor = 40
var/waves = 1
var/start_side
var/next_meteor_lower = 10
var/next_meteor_upper = 20
ic_name = "a meteor storm"
/datum/event/meteor_wave/get_skybox_image()
var/image/res = overlay_image('icons/skybox/rockbox.dmi', "rockbox", COLOR_ASTEROID_ROCK, RESET_COLOR)
res.blend_mode = BLEND_OVERLAY
return res
/datum/event/meteor_wave/setup()
waves = 0
for(var/n in 1 to severity)
waves += rand(5,15)
start_side = pick(GLOB.cardinals)
endWhen = worst_case_end()
/datum/event/meteor_wave/announce()
command_announcement.Announce(SSatlas.current_map.meteors_detected_message, "Meteor Alert", new_sound = 'sound/AI/meteors_detected_message.ogg', zlevels = affecting_z)
/datum/event/meteor_wave/announce_start()
if(announce_to_sensor_console)
send_sensor_message("Entering [ic_name].")
return FALSE
else
command_announcement.Announce(SSatlas.current_map.meteor_contact_message, "Meteor Alert", zlevels = affecting_z)
/datum/event/meteor_wave/announce_end(var/faked)
if(faked)
return
if(announce_to_sensor_console)
send_sensor_message("Exiting [ic_name].")
return FALSE
else
spawn(100)//We give 10 seconds before announcing, for the last wave of meteors to hit the station
command_announcement.Announce(SSatlas.current_map.meteor_end_message, "Meteor Alert", zlevels = affecting_z)
/datum/event/meteor_wave/tick()
if(waves && activeFor >= next_meteor)
send_wave()
/datum/event/meteor_wave/proc/worst_case_end()
return activeFor + ((30 / severity) * waves) + 30
/datum/event/meteor_wave/proc/send_wave()
var/pick_side = prob(80) ? start_side : (prob(50) ? turn(start_side, 90) : turn(start_side, -90))
spawn() spawn_meteors(get_wave_size(), get_meteors(), pick_side, pick(affecting_z))
next_meteor += rand(next_meteor_lower, next_meteor_upper) / severity
waves--
endWhen = worst_case_end()
/datum/event/meteor_wave/proc/get_wave_size()
return severity * rand(2,4)
/datum/event/meteor_wave/proc/get_meteors()
switch(severity)
if(EVENT_LEVEL_MAJOR)
return SSatlas.current_sector.meteors_major
if(EVENT_LEVEL_MODERATE)
return SSatlas.current_sector.meteors_moderate
else
return SSatlas.current_sector.meteors_minor
/datum/event/meteor_wave/downed_ship
ic_name = "a downed vessel"
no_fake = TRUE
/datum/event/meteor_wave/downed_ship/get_meteors()
return SSatlas.current_sector.downed_ship_meteors
/datum/event/meteor_wave/downed_ship/announce()
command_announcement.Announce(SSatlas.current_map.ship_meteor_end_message, "Ship Debris Alert", new_sound = 'sound/AI/meteor_end_message.ogg', zlevels = affecting_z)
/datum/event/meteor_wave/downed_ship/announce_start()
. = ..()
if(.)
command_announcement.Announce(SSatlas.current_map.ship_meteor_contact_message, "Ship Debris Alert", new_sound = 'sound/AI/meteor_contact_message.ogg', zlevels = affecting_z)
/datum/event/meteor_wave/downed_ship/announce_end(var/faked)
if(faked)
return
. = ..()
if(.)
spawn(100)//We give 10 seconds before announcing, for the last wave of meteors to hit the station
command_announcement.Announce(SSatlas.current_map.ship_meteor_end_message, "Ship Debris Alert", new_sound = 'sound/AI/meteor_end_message.ogg', zlevels = affecting_z)
/datum/event/meteor_wave/overmap
next_meteor_lower = 5
next_meteor_upper = 10
next_meteor = 0
/datum/event/meteor_wave/overmap/announce()
return
/datum/event/meteor_wave/dust
ic_name = "a dust belt"
/datum/event/meteor_wave/dust/announce()
command_announcement.Announce(SSatlas.current_map.dust_detected_message, "Dust Belt Alert", new_sound = 'sound/AI/dust_detected_message.ogg', zlevels = affecting_z)
/datum/event/meteor_wave/dust/announce_start()
if(announce_to_sensor_console)
send_sensor_message("Entering [ic_name].")
return FALSE
else
command_announcement.Announce(SSatlas.current_map.dust_contact_message, "Dust Belt Alert", new_sound = 'sound/AI/dust_contact_message.ogg', zlevels = affecting_z)
/datum/event/meteor_wave/dust/announce_end(var/faked)
if(faked)
return
if(announce_to_sensor_console)
send_sensor_message("Exiting [ic_name].")
return FALSE
else
spawn(100)//We give 10 seconds before announcing, for the last wave of meteors to hit the station
command_announcement.Announce(SSatlas.current_map.dust_end_message, "Dust Belt Alert", new_sound = 'sound/AI/dust_end_message.ogg', zlevels = affecting_z)
/datum/event/meteor_wave/dust/get_meteors()
return SSatlas.current_sector.meteors_dust
/datum/event/meteor_wave/dust/overmap
next_meteor_lower = 5
next_meteor_upper = 10
next_meteor = 0
/datum/event/meteor_wave/dust/overmap/announce()
return