Ports overmap events from Baystation12

- Move overmap defines to _defines folder.  Rename old file to turfs.dm since that is what it contains.
- Definition of overmap event objects and the overmap event handler.
- Upgrades to SSevents and SSskybox to tie in the overmap events.
- Enhancement to /datum/event itself to support affecting_z and victim ship.
- Upgrade to the five event types used on the overmap to support new vars.
- Upgrade to dust and meteor spawning code to support targeting z-levels.
This commit is contained in:
Leshana
2020-03-18 13:28:37 -04:00
committed by Aronai Sieyes
parent 15273a356c
commit f2a582569b
22 changed files with 795 additions and 347 deletions

View File

@@ -14,4 +14,6 @@
#define COLOR_ASSEMBLY_LBLUE "#5D99BE" #define COLOR_ASSEMBLY_LBLUE "#5D99BE"
#define COLOR_ASSEMBLY_BLUE "#38559E" #define COLOR_ASSEMBLY_BLUE "#38559E"
#define COLOR_ASSEMBLY_PURPLE "#6F6192" #define COLOR_ASSEMBLY_PURPLE "#6F6192"
#define COLOR_ASSEMBLY_HOT_PINK "#FF69B4" #define COLOR_ASSEMBLY_HOT_PINK "#FF69B4"
#define COLOR_ASTEROID_ROCK "#735555"

16
code/__defines/overmap.dm Normal file
View File

@@ -0,0 +1,16 @@
//How far from the edge of overmap zlevel could randomly placed objects spawn
#define OVERMAP_EDGE 2
#define SHIP_SIZE_TINY 1
#define SHIP_SIZE_SMALL 2
#define SHIP_SIZE_LARGE 3
//multipliers for max_speed to find 'slow' and 'fast' speeds for the ship
#define SHIP_SPEED_SLOW 1/(40 SECONDS)
#define SHIP_SPEED_FAST 3/(20 SECONDS)// 15 speed
#define OVERMAP_WEAKNESS_NONE 0
#define OVERMAP_WEAKNESS_FIRE 1
#define OVERMAP_WEAKNESS_EMP 2
#define OVERMAP_WEAKNESS_MINING 4
#define OVERMAP_WEAKNESS_EXPLOSIVE 8

View File

@@ -26,6 +26,15 @@
max_z = max(z, max_z) max_z = max(z, max_z)
return max_z return max_z
/proc/living_observers_present(var/list/zlevels)
if(LAZYLEN(zlevels))
for(var/mob/M in player_list) //if a tree ticks on the empty zlevel does it really tick
if(M.stat != DEAD) //(no it doesn't)
var/turf/T = get_turf(M)
if(T && (T.z in zlevels))
return TRUE
return FALSE
/proc/get_area(atom/A) /proc/get_area(atom/A)
if(isarea(A)) if(isarea(A))
return A return A

View File

@@ -33,6 +33,20 @@
available_turfs = start_turfs available_turfs = start_turfs
return pick(available_turfs) return pick(available_turfs)
// Picks a turf that is clearance tiles away from the map edge given by dir, on z-level Z
/proc/pick_random_edge_turf(var/dir, var/Z, var/clearance = TRANSITIONEDGE + 1)
if(!dir)
return
switch(dir)
if(NORTH)
return locate(rand(clearance, world.maxx - clearance), world.maxy - clearance, Z)
if(SOUTH)
return locate(rand(clearance, world.maxx - clearance), clearance, Z)
if(EAST)
return locate(world.maxx - clearance, rand(clearance, world.maxy - clearance), Z)
if(WEST)
return locate(clearance, rand(clearance, world.maxy - clearance), Z)
/proc/is_below_sound_pressure(var/turf/T) /proc/is_below_sound_pressure(var/turf/T)
var/datum/gas_mixture/environment = T ? T.return_air() : null var/datum/gas_mixture/environment = T ? T.return_air() : null
var/pressure = environment ? environment.return_pressure() : 0 var/pressure = environment ? environment.return_pressure() : 0

View File

@@ -1,6 +1,8 @@
SUBSYSTEM_DEF(events) SUBSYSTEM_DEF(events)
name = "Events" name = "Events"
wait = 20 wait = 2 SECONDS
var/tmp/list/currentrun = null
var/list/datum/event/active_events = list() var/list/datum/event/active_events = list()
var/list/datum/event/finished_events = list() var/list/datum/event/finished_events = list()
@@ -11,23 +13,37 @@ SUBSYSTEM_DEF(events)
var/datum/event_meta/new_event = new var/datum/event_meta/new_event = new
/datum/controller/subsystem/events/Initialize() /datum/controller/subsystem/events/Initialize()
allEvents = typesof(/datum/event) - /datum/event
event_containers = list( event_containers = list(
EVENT_LEVEL_MUNDANE = new/datum/event_container/mundane, EVENT_LEVEL_MUNDANE = new/datum/event_container/mundane,
EVENT_LEVEL_MODERATE = new/datum/event_container/moderate, EVENT_LEVEL_MODERATE = new/datum/event_container/moderate,
EVENT_LEVEL_MAJOR = new/datum/event_container/major EVENT_LEVEL_MAJOR = new/datum/event_container/major
) )
allEvents = typesof(/datum/event) - /datum/event if(global.using_map.use_overmap)
GLOB.overmap_event_handler.create_events(global.using_map.overmap_z, global.using_map.overmap_size, global.using_map.overmap_event_areas)
return ..() return ..()
/datum/controller/subsystem/events/fire(resumed) /datum/controller/subsystem/events/fire(resumed)
for(var/datum/event/E in active_events) if (!resumed)
src.currentrun = active_events.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while (currentrun.len)
var/datum/event/E = currentrun[currentrun.len]
currentrun.len--
if(E.processing_active) if(E.processing_active)
E.process() E.process()
if (MC_TICK_CHECK)
return
for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR) for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR)
var/list/datum/event_container/EC = event_containers[i] var/list/datum/event_container/EC = event_containers[i]
EC.process() EC.process()
/datum/controller/subsystem/events/stat_entry()
..("E:[active_events.len]")
/datum/controller/subsystem/events/Recover() /datum/controller/subsystem/events/Recover()
if(SSevents.active_events) if(SSevents.active_events)
active_events |= SSevents.active_events active_events |= SSevents.active_events
@@ -35,6 +51,8 @@ SUBSYSTEM_DEF(events)
finished_events |= SSevents.finished_events finished_events |= SSevents.finished_events
/datum/controller/subsystem/events/proc/event_complete(var/datum/event/E) /datum/controller/subsystem/events/proc/event_complete(var/datum/event/E)
active_events -= E
if(!E.event_meta || !E.severity) // datum/event is used here and there for random reasons, maintaining "backwards compatibility" if(!E.event_meta || !E.severity) // datum/event is used here and there for random reasons, maintaining "backwards compatibility"
log_debug("Event of '[E.type]' with missing meta-data has completed.") log_debug("Event of '[E.type]' with missing meta-data has completed.")
return return
@@ -50,7 +68,7 @@ SUBSYSTEM_DEF(events)
log_debug("Event '[EM.name]' has completed at [stationtime2text()].") log_debug("Event '[EM.name]' has completed at [stationtime2text()].")
/datum/controller/subsystem/events/proc/delay_events(var/severity, var/delay) /datum/controller/subsystem/events/proc/delay_events(var/severity, var/delay)
var/list/datum/event_container/EC = event_containers[severity] var/datum/event_container/EC = event_containers[severity]
EC.next_event_time += delay EC.next_event_time += delay
/datum/controller/subsystem/events/proc/RoundEnd() /datum/controller/subsystem/events/proc/RoundEnd()

View File

@@ -81,10 +81,10 @@ SUBSYSTEM_DEF(skybox)
overmap.appearance_flags = RESET_COLOR overmap.appearance_flags = RESET_COLOR
res.overlays += overmap res.overlays += overmap
// TODO - Allow events to apply custom overlays to skybox! (Awesome!) // Allow events to apply custom overlays to skybox! (Awesome!)
//for(var/datum/event/E in SSevent.active_events) for(var/datum/event/E in SSevents.active_events)
// if(E.has_skybox_image && E.isRunning && (z in E.affecting_z)) if(E.has_skybox_image && E.isRunning && (z in E.affecting_z))
// res.overlays += E.get_skybox_image() res.overlays += E.get_skybox_image()
return res return res

View File

@@ -7,27 +7,57 @@ No command report on the common version of this event.
The "dust" will damage the hull of the station causin minor hull breaches. The "dust" will damage the hull of the station causin minor hull breaches.
*/ */
/proc/dust_swarm(var/strength = "weak") /proc/dust_swarm(var/strength = "weak", var/list/affecting_z)
var/numbers = 1 var/numbers = 1
var/dust_type = /obj/effect/space_dust
switch(strength) switch(strength)
if("weak") if("weak")
numbers = rand(2,4) numbers = rand(2,4)
for(var/i = 0 to numbers) dust_type = /obj/effect/space_dust/weak
new/obj/effect/space_dust/weak()
if("norm") if("norm")
numbers = rand(5,10) numbers = rand(5,10)
for(var/i = 0 to numbers) dust_type = /obj/effect/space_dust
new/obj/effect/space_dust()
if("strong") if("strong")
numbers = rand(10,15) numbers = rand(10,15)
for(var/i = 0 to numbers) dust_type = /obj/effect/space_dust/strong
new/obj/effect/space_dust/strong()
if("super") if("super")
numbers = rand(15,25) numbers = rand(15,25)
for(var/i = 0 to numbers) dust_type = /obj/effect/space_dust/super
new/obj/effect/space_dust/super()
return
var/startside = pick(cardinal)
for(var/i = 0 to numbers)
var/startx = 0
var/starty = 0
var/endy = 0
var/endx = 0
switch(startside)
if(NORTH)
starty = world.maxy-TRANSITIONEDGE-1
startx = rand(TRANSITIONEDGE+1, world.maxx-TRANSITIONEDGE-1)
endy = TRANSITIONEDGE
endx = rand(TRANSITIONEDGE+1, world.maxx-TRANSITIONEDGE-1)
if(EAST)
starty = rand(TRANSITIONEDGE+1, world.maxy-TRANSITIONEDGE-1)
startx = world.maxx-TRANSITIONEDGE-1
endy = rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE)
endx = TRANSITIONEDGE
if(SOUTH)
starty = TRANSITIONEDGE+1
startx = rand(TRANSITIONEDGE+1, world.maxx-TRANSITIONEDGE-1)
endy = world.maxy-TRANSITIONEDGE
endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE)
if(WEST)
starty = rand(TRANSITIONEDGE+1, world.maxy-TRANSITIONEDGE-1)
startx = TRANSITIONEDGE+1
endy = rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE)
endx = world.maxx-TRANSITIONEDGE
var/randomz = pick(affecting_z)
var/turf/startloc = locate(startx, starty, randomz)
var/turf/endloc = locate(endx, endy, randomz)
var/obj/effect/space_dust/D = new dust_type(startloc)
D.set_dir(GLOB.reverse_dir[startside])
walk_towards(D, endloc, 1)
/obj/effect/space_dust /obj/effect/space_dust
name = "Space Dust" name = "Space Dust"
@@ -39,96 +69,51 @@ The "dust" will damage the hull of the station causin minor hull breaches.
var/strength = 2 //ex_act severity number var/strength = 2 //ex_act severity number
var/life = 2 //how many things we hit before qdel(src) var/life = 2 //how many things we hit before qdel(src)
weak /obj/effect/space_dust/weak
strength = 3 strength = 3
life = 1 life = 1
strong /obj/effect/space_dust/strong
strength = 1 strength = 1
life = 6 life = 6
super /obj/effect/space_dust/super
strength = 1 strength = 1
life = 40 life = 40
/obj/effect/space_dust/Destroy()
walk(src, 0) // Because we might have called walk_towards, we must stop the walk loop or BYOND keeps an internal reference to us forever.
return ..()
/obj/effect/space_dust/touch_map_edge()
qdel(src)
/obj/effect/space_dust/Bump(atom/A)
spawn(0)
if(prob(50))
for(var/mob/M in range(10, src))
if(!M.stat && !istype(M, /mob/living/silicon/ai))
shake_camera(M, 3, 1)
if (A)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
if(ismob(A))
A.ex_act(strength)//This should work for now I guess
else if(!istype(A,/obj/machinery/power/emitter) && !istype(A,/obj/machinery/field_generator)) //Protect the singularity from getting released every round!
A.ex_act(strength) //Changing emitter/field gen ex_act would make it immune to bombs and C4
life--
if(life <= 0)
walk(src,0)
qdel(src)
return 0
return
New() /obj/effect/space_dust/Bumped(atom/A)
..() Bump(A)
var/startx = 0 return
var/starty = 0
var/endy = 0
var/endx = 0
var/startside = pick(cardinal)
switch(startside) /obj/effect/space_dust/ex_act(severity)
if(NORTH) qdel(src)
starty = world.maxy-(TRANSITIONEDGE+1) return
startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
endy = TRANSITIONEDGE
endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE)
if(EAST)
starty = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1))
startx = world.maxx-(TRANSITIONEDGE+1)
endy = rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE)
endx = TRANSITIONEDGE
if(SOUTH)
starty = (TRANSITIONEDGE+1)
startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
endy = world.maxy-TRANSITIONEDGE
endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE)
if(WEST)
starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1))
startx = (TRANSITIONEDGE+1)
endy = rand(TRANSITIONEDGE,world.maxy-TRANSITIONEDGE)
endx = world.maxx-TRANSITIONEDGE
//VOREStation Edit - No space dust outside of space
var/list/z_levels = using_map.station_levels.Copy()
for(var/datum/planet/P in SSplanets.planets)
z_levels.Remove(P.expected_z_levels)
var/z_level = pick(z_levels)
//VOREStation Edit End
var/goal = locate(endx, endy, z_level)
src.x = startx
src.y = starty
src.z = z_level
spawn(0)
walk_towards(src, goal, 1)
return
Destroy()
walk(src, 0) // Because we might have called walk_towards, we must stop the walk loop or BYOND keeps an internal reference to us forever.
return ..()
touch_map_edge()
qdel(src)
Bump(atom/A)
spawn(0)
if(prob(50))
for(var/mob/M in range(10, src))
if(!M.stat && !istype(M, /mob/living/silicon/ai))
shake_camera(M, 3, 1)
if (A)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
if(ismob(A))
A.ex_act(strength)//This should work for now I guess
else if(!istype(A,/obj/machinery/power/emitter) && !istype(A,/obj/machinery/field_generator)) //Protect the singularity from getting released every round!
A.ex_act(strength) //Changing emitter/field gen ex_act would make it immune to bombs and C4
life--
if(life <= 0)
walk(src,0)
qdel(src)
return 0
return
Bumped(atom/A)
Bump(A)
return
ex_act(severity)
qdel(src)
return

View File

@@ -18,21 +18,18 @@
//Meteor spawning global procs //Meteor spawning global procs
/////////////////////////////// ///////////////////////////////
/proc/pick_meteor_start(var/startSide = pick(cardinal)) /proc/spawn_meteors(var/number = 10, var/list/meteortypes, var/startSide, var/zlevel)
var/startLevel = pick(using_map.station_levels - using_map.sealed_levels) log_debug("Spawning [number] meteors on the [dir2text(startSide)] of [zlevel]")
var/pickedstart = spaceDebrisStartLoc(startSide, startLevel)
return list(startLevel, pickedstart)
/proc/spawn_meteors(var/number = 10, var/list/meteortypes, var/startSide)
for(var/i = 0; i < number; i++) for(var/i = 0; i < number; i++)
spawn_meteor(meteortypes, startSide) spawn_meteor(meteortypes, startSide, zlevel)
/proc/spawn_meteor(var/list/meteortypes, var/startSide) /proc/spawn_meteor(var/list/meteortypes, var/startSide, var/startLevel)
var/start = pick_meteor_start(startSide) if(isnull(startSide))
startSide = pick(cardinal)
if(isnull(startLevel))
startLevel = pick(using_map.station_levels - using_map.sealed_levels)
var/startLevel = start[1] var/turf/pickedstart = spaceDebrisStartLoc(startSide, startLevel)
var/turf/pickedstart = start[2]
var/turf/pickedgoal = spaceDebrisFinishLoc(startSide, startLevel) var/turf/pickedgoal = spaceDebrisFinishLoc(startSide, startLevel)
var/Me = pickweight(meteortypes) var/Me = pickweight(meteortypes)

View File

@@ -269,20 +269,23 @@ var/const/enterloopsanity = 100
for(var/obj/O in src) for(var/obj/O in src)
O.hide(O.hides_under_flooring() && !is_plating()) O.hide(O.hides_under_flooring() && !is_plating())
/turf/proc/AdjacentTurfs() /turf/proc/AdjacentTurfs(var/check_blockage = TRUE)
var/L[] = new() . = list()
for(var/turf/simulated/t in oview(src,1)) for(var/t in (trange(1,src) - src))
if(!t.density) var/turf/T = t
if(!LinkBlocked(src, t) && !TurfBlockedNonWindow(t)) if(check_blockage)
L.Add(t) if(!T.density)
return L if(!LinkBlocked(src, T) && !TurfBlockedNonWindow(T))
. += t
else
. += t
/turf/proc/CardinalTurfs() /turf/proc/CardinalTurfs(var/check_blockage = TRUE)
var/L[] = new() . = list()
for(var/turf/simulated/T in AdjacentTurfs()) for(var/ad in AdjacentTurfs(check_blockage))
var/turf/T = ad
if(T.x == src.x || T.y == src.y) if(T.x == src.x || T.y == src.y)
L.Add(T) . += T
return L
/turf/proc/Distance(turf/t) /turf/proc/Distance(turf/t)
if(get_dist(src,t) == 1) if(get_dist(src,t) == 1)

View File

@@ -1,51 +1,75 @@
/datum/event/carp_migration /datum/event/carp_migration
announceWhen = 50 startWhen = 0 // Start immediately
endWhen = 900 announceWhen = 45 // Adjusted by setup
endWhen = 75 // Adjusted by setup
var/carp_cap = 10
var/list/spawned_carp = list() var/list/spawned_carp = list()
/datum/event/carp_migration/setup() /datum/event/carp_migration/setup()
announceWhen = rand(40, 60) announceWhen = rand(30, 60) // 1 to 2 minutes
endWhen = rand(600,1200) endWhen += severity * 25
carp_cap = 2 + 3 ** severity // No more than this many at once regardless of waves. (5, 11, 29)
/datum/event/carp_migration/announce() /datum/event/carp_migration/announce()
var/announcement = "" var/announcement = ""
if(severity == EVENT_LEVEL_MAJOR) if(severity == EVENT_LEVEL_MAJOR)
announcement = "Massive migration of unknown biological entities has been detected near [station_name()], please stand-by." announcement = "Massive migration of unknown biological entities has been detected near [location_name()], please stand-by."
else else
announcement = "Unknown biological [spawned_carp.len == 1 ? "entity has" : "entities have"] been detected near [station_name()], please stand-by." announcement = "Unknown biological [spawned_carp.len == 1 ? "entity has" : "entities have"] been detected near [location_name()], please stand-by."
command_announcement.Announce(announcement, "Lifesign Alert") command_announcement.Announce(announcement, "Lifesign Alert")
/datum/event/carp_migration/start() /datum/event/carp_migration/tick()
if(severity == EVENT_LEVEL_MAJOR) if(activeFor % 4 != 0)
spawn_fish(landmarks_list.len) return // Only process every 8 seconds.
else if(severity == EVENT_LEVEL_MODERATE) if(count_spawned_carps() < carp_cap && living_observers_present(affecting_z))
spawn_fish(rand(4, 6)) //12 to 30 carp, in small groups spawn_fish(rand(1, severity * 2) - 1, severity, severity * 2)
else
spawn_fish(rand(1, 3), 1, 2) //1 to 6 carp, alone or in pairs
/datum/event/carp_migration/proc/spawn_fish(var/num_groups, var/group_size_min=3, var/group_size_max=5) /datum/event/carp_migration/proc/spawn_fish(var/num_groups, var/group_size_min, var/group_size_max, var/dir)
var/list/spawn_locations = list() if(isnull(dir))
dir = (victim && prob(80)) ? victim.fore_dir : pick(GLOB.cardinal)
for(var/obj/effect/landmark/C in landmarks_list)
if(C.name == "carpspawn")
spawn_locations.Add(C.loc)
spawn_locations = shuffle(spawn_locations)
num_groups = min(num_groups, spawn_locations.len)
var/i = 1 var/i = 1
while (i <= num_groups) while (i <= num_groups)
var/Z = pick(affecting_z)
var/group_size = rand(group_size_min, group_size_max) var/group_size = rand(group_size_min, group_size_max)
for (var/j = 1, j <= group_size, j++) var/turf/map_center = locate(round(world.maxx/2), round(world.maxy/2), Z)
spawned_carp.Add(new /mob/living/simple_mob/animal/space/carp/event(spawn_locations[i])) var/turf/group_center = pick_random_edge_turf(dir, Z, TRANSITIONEDGE + 2)
var/list/turfs = getcircle(group_center, 2)
for (var/j = 0, j < group_size, j++)
var/mob/living/simple_mob/animal/M = new /mob/living/simple_mob/animal/space/carp/event(turfs[(i % turfs.len) + 1])
GLOB.destroyed_event.register(M, src, .proc/on_carp_destruction)
spawned_carp.Add(M)
M.ai_holder?.give_destination(map_center) // Ask carp to swim towards the middle of the map
// TODO - Our throwing systems don't support callbacks. If it ever does, we can throw first to simulate ship speed.
i++ i++
// Counts living carp spawned by this event.
/datum/event/carp_migration/proc/count_spawned_carps()
. = 0
for(var/I in spawned_carp)
var/mob/living/simple_mob/animal/M = I
if(!QDELETED(M) && M.stat != DEAD)
. += 1
// If carp is bomphed, remove it from the list.
/datum/event/carp_migration/proc/on_carp_destruction(var/mob/M)
spawned_carp -= M
GLOB.destroyed_event.unregister(M, src, .proc/on_carp_destruction)
/datum/event/carp_migration/end() /datum/event/carp_migration/end()
. = ..()
// Clean up carp that died in space for some reason.
spawn(0) spawn(0)
for(var/mob/living/simple_mob/SM in spawned_carp) for(var/mob/living/simple_mob/SM in spawned_carp)
if(!SM.stat) if(SM.stat == DEAD)
var/turf/T = get_turf(SM) var/turf/T = get_turf(SM)
if(istype(T, /turf/space)) if(istype(T, /turf/space))
if(prob(75)) if(prob(75))
qdel(SM) qdel(SM)
sleep(1) CHECK_TICK
//
// Overmap version of the event!
//
/datum/event/carp_migration/overmap
announceWhen = 1 // Announce much faster!

View File

@@ -3,13 +3,17 @@
endWhen = 30 endWhen = 30
/datum/event/dust/announce() /datum/event/dust/announce()
command_announcement.Announce("Debris resulting from activity on another nearby asteroid is approaching \the [station_name()]", "Dust Alert") if(victim)
command_announcement.Announce("The [location_name()] is now passing through a belt of space dust.", "[location_name()] Sensor Array")
else
command_announcement.Announce("Debris resulting from activity on another nearby asteroid is approaching \the [location_name()]", "Dust Alert")
/datum/event/dust/start() /datum/event/dust/tick()
dust_swarm(get_severity()) if(prob(10))
dust_swarm(severity, affecting_z)
/datum/event/dust/end() /datum/event/dust/end()
command_announcement.Announce("\The [station_name()] is no longer in danger of impact from space debris.", "Dust Notice") command_announcement.Announce("\The [location_name()] is no longer in danger of impact from space debris.", "Dust Notice")
/datum/event/dust/proc/get_severity() /datum/event/dust/proc/get_severity()
switch(severity) switch(severity)

View File

@@ -1,28 +1,61 @@
/datum/event/electrical_storm /datum/event/electrical_storm
var/lightsoutAmount = 1 announceWhen = 0 // Warn them shortly before it begins.
var/lightsoutRange = 25 startWhen = 30 // 1 minute
endWhen = 60 // Set in setup()
has_skybox_image = TRUE
var/tmp/lightning_color
var/tmp/list/valid_apcs // List of valid APCs.
/datum/event/electrical_storm/get_skybox_image()
if(!lightning_color)
lightning_color = pick("#ffd98c", "#ebc7ff", "#bdfcff", "#bdd2ff", "#b0ffca", "#ff8178", "#ad74cc")
var/image/res = image('icons/skybox/electrobox.dmi', "lightning")
res.color = lightning_color
res.appearance_flags = RESET_COLOR
res.blend_mode = BLEND_ADD
return res
/datum/event/electrical_storm/announce() /datum/event/electrical_storm/announce()
command_announcement.Announce("An electrical issue has been detected in your area, please repair potential electronic overloads.", "Electrical Alert") ..()
switch(severity)
if(EVENT_LEVEL_MUNDANE)
command_announcement.Announce("A minor electrical storm has been detected near the [location_name()]. Please watch out for possible electrical discharges.", "[location_name()] Sensor Array")
if(EVENT_LEVEL_MODERATE)
command_announcement.Announce("The [location_name()] is about to pass through an electrical storm. Please secure sensitive electrical equipment until the storm passes.", "[location_name()] Sensor Array")
if(EVENT_LEVEL_MAJOR)
command_announcement.Announce("Alert. A strong electrical storm has been detected in proximity of the [location_name()]. It is recommended to immediately secure sensitive electrical equipment until the storm passes.", "[location_name()] Sensor Array")
/datum/event/electrical_storm/start() /datum/event/electrical_storm/start()
var/list/epicentreList = list() ..()
valid_apcs = list()
for(var/obj/machinery/power/apc/A in global.machines)
if(A.z in affecting_z)
valid_apcs.Add(A)
endWhen = (severity * 60) + startWhen
for(var/i=1, i <= lightsoutAmount, i++) /datum/event/electrical_storm/tick()
var/list/possibleEpicentres = list() ..()
for(var/obj/effect/landmark/newEpicentre in landmarks_list) // See if shields can stop it first (It would be nice to port baystation's cooler shield gens perhaps)
if(newEpicentre.name == "lightsout" && !(newEpicentre in epicentreList)) // TODO - We need a better shield generator system to handle this properly.
possibleEpicentres += newEpicentre if(!valid_apcs.len)
if(possibleEpicentres.len) log_debug("No valid APCs found for electrical storm event ship=[victim]!")
epicentreList += pick(possibleEpicentres) return
else var/list/picked_apcs = list()
break for(var/i=0, i< severity * 2, i++) // up to 2/4/6 APCs per tick depending on severity
picked_apcs |= pick(valid_apcs)
for(var/obj/machinery/power/apc/T in picked_apcs)
affect_apc(T)
if(!epicentreList.len) /datum/event/electrical_storm/proc/affect_apc(var/obj/machinery/power/apc/T)
// Main breaker is turned off. Consider this APC protected.
if(!T.operating)
return return
for(var/obj/effect/landmark/epicentre in epicentreList) // Decent chance to overload lighting circuit.
for(var/obj/machinery/power/apc/apc in range(epicentre,lightsoutRange)) if(prob(3 * severity))
apc.overload_lighting() T.overload_lighting()
// Relatively small chance to emag the apc as apc_damage event does.
if(prob(0.2 * severity))
T.emagged = 1
T.update_icon()

View File

@@ -1,3 +1,4 @@
// Event Meta instances represent choices for the event manager to choose for random events.
/datum/event_meta /datum/event_meta
var/name = "" var/name = ""
var/enabled = 1 // Whether or not the event is available for random selection at all var/enabled = 1 // Whether or not the event is available for random selection at all
@@ -39,6 +40,10 @@
return total_weight return total_weight
/datum/event_meta/no_overmap/get_weight() //these events have overmap equivalents, and shouldn't fire randomly if overmap is used
return global.using_map.use_overmap ? 0 : ..()
// Event datums define and execute the actual events themselves.
/datum/event //NOTE: Times are measured in master controller ticks! /datum/event //NOTE: Times are measured in master controller ticks!
var/startWhen = 0 //When in the lifetime to call start(). var/startWhen = 0 //When in the lifetime to call start().
var/announceWhen = 0 //When in the lifetime to call announce(). var/announceWhen = 0 //When in the lifetime to call announce().
@@ -51,6 +56,9 @@
var/endedAt = 0 //When this event ended. var/endedAt = 0 //When this event ended.
var/processing_active = TRUE var/processing_active = TRUE
var/datum/event_meta/event_meta = null var/datum/event_meta/event_meta = null
var/list/affecting_z = null // List of z-levels to affect, null lets the event choose (usally station_levels)
var/has_skybox_image = FALSE // True if SSskybox should query this event for an image to put in the skybox.
var/obj/effect/overmap/visitable/ship/victim = null // Ship that triggered this event on itself. Some messages might be different etc.
/datum/event/nothing /datum/event/nothing
@@ -65,6 +73,8 @@
//Allows you to start before announcing or vice versa. //Allows you to start before announcing or vice versa.
//Only called once. //Only called once.
/datum/event/proc/start() /datum/event/proc/start()
if(has_skybox_image)
SSskybox.rebuild_skyboxes(affecting_z)
return return
//Called when the tick is equal to the announceWhen variable. //Called when the tick is equal to the announceWhen variable.
@@ -87,6 +97,8 @@
//For example: if(activeFor == myOwnVariable + 30) doStuff() //For example: if(activeFor == myOwnVariable + 30) doStuff()
//Only called once. //Only called once.
/datum/event/proc/end() /datum/event/proc/end()
if(has_skybox_image)
SSskybox.rebuild_skyboxes(affecting_z)
return return
//Returns the latest point of event processing. //Returns the latest point of event processing.
@@ -132,9 +144,12 @@
end() end()
endedAt = world.time endedAt = world.time
SSevents.active_events -= src
SSevents.event_complete(src) SSevents.event_complete(src)
//Called during building of skybox to get overlays
/datum/event/proc/get_skybox_image()
return
/datum/event/New(var/datum/event_meta/EM) /datum/event/New(var/datum/event_meta/EM)
// event needs to be responsible for this, as stuff like APLUs currently make their own events for curious reasons // event needs to be responsible for this, as stuff like APLUs currently make their own events for curious reasons
SSevents.active_events += src SSevents.active_events += src
@@ -146,5 +161,17 @@
startedAt = world.time startedAt = world.time
if(!affecting_z)
affecting_z = using_map.station_levels
setup() setup()
..() ..()
/datum/event/Destroy()
victim = null
. = ..()
/datum/event/proc/location_name()
if(victim)
return victim.name
return station_name()

View File

@@ -1,20 +1,51 @@
//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:04 //This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:04
/datum/event/ionstorm /datum/event/ionstorm
has_skybox_image = TRUE
var/botEmagChance = 0 //VOREStation Edit var/botEmagChance = 0 //VOREStation Edit
var/cloud_hueshift
var/list/players = list() var/list/players = list()
/datum/event/ionstorm/announce() /datum/event/ionstorm/get_skybox_image()
if(!cloud_hueshift)
cloud_hueshift = color_rotation(rand(-3, 3) * 15)
var/image/res = image('icons/skybox/ionbox.dmi', "ions")
res.color = cloud_hueshift
res.appearance_flags = RESET_COLOR
res.blend_mode = BLEND_ADD
return res
/datum/event/ionstorm/setup()
endWhen = rand(500, 1500) endWhen = rand(500, 1500)
// Interestingly enough, announce() actually *DOES* this event for some reason.
/datum/event/ionstorm/announce()
// command_alert("The station has entered an ion storm. Monitor all electronic equipment for malfunctions", "Anomaly Alert") // command_alert("The station has entered an ion storm. Monitor all electronic equipment for malfunctions", "Anomaly Alert")
for (var/mob/living/carbon/human/player in player_list) for (var/mob/living/carbon/human/player in player_list)
if( !player.mind || player_is_antag(player.mind, only_offstation_roles = 1) || player.client.inactivity > MinutesToTicks(10)) if( !player.mind || player_is_antag(player.mind, only_offstation_roles = 1) || player.client.inactivity > MinutesToTicks(10))
continue continue
players += player.real_name players += player.real_name
// Flomph synthetics
for(var/mob/living/carbon/S in living_mob_list)
if (!S.isSynthetic())
continue
if(!(S.z in affecting_z))
continue
var/area/A = get_area(S)
if(!A || A.flags & RAD_SHIELDED) // Rad shielding will protect from ions too
continue
to_chat(S, "<span class='warning'>Your integrated sensors detect an ionospheric anomaly. Your systems will be impacted as you begin a partial restart.</span>")
var/ionbug = rand(3, 9)
S.confused += ionbug
S.eye_blurry += (ionbug - 1)
// Ionize silicon mobs
for (var/mob/living/silicon/ai/target in silicon_mob_list) for (var/mob/living/silicon/ai/target in silicon_mob_list)
if(!(target.z in affecting_z))
continue
var/law = target.generate_ion_law() var/law = target.generate_ion_law()
to_chat(target, "<font color='red'><b>You have detected a change in your laws information:</b></font>") to_chat(target, "<span class='danger'>You have detected a change in your laws information:</span>")
to_chat(target, law) to_chat(target, law)
target.add_ion_law(law) target.add_ion_law(law)
target.show_laws() target.show_laws()
@@ -31,13 +62,15 @@
/datum/event/ionstorm/tick() /datum/event/ionstorm/tick()
if(botEmagChance) if(botEmagChance)
for(var/mob/living/bot/bot in mob_list) for(var/mob/living/bot/bot in mob_list)
if(!(bot.z in affecting_z))
continue
if(prob(botEmagChance)) if(prob(botEmagChance))
bot.emag_act(1) bot.emag_act(1)
/datum/event/ionstorm/end() /datum/event/ionstorm/end()
spawn(rand(5000,8000)) if(prob(50))
if(prob(50)) spawn(rand(5000,8000))
ion_storm_announcement() command_announcement.Announce("It has come to our attention that \the [location_name()] passed through an ion storm. Please monitor all electronic equipment for malfunctions.", "Anomaly Alert")
/* /*
/proc/IonStorm(botEmagChance = 10) /proc/IonStorm(botEmagChance = 10)

View File

@@ -1,30 +1,45 @@
/datum/event/meteor_wave /datum/event/meteor_wave
startWhen = 5 startWhen = 30 // About one minute early warning
endWhen = 7 endWhen = 60 // Adjusted automatically in tick()
has_skybox_image = TRUE
var/next_meteor = 6 var/next_meteor = 6
var/waves = 1 var/waves = 1
var/start_side var/start_side
var/next_meteor_lower = 10
var/next_meteor_upper = 20
/datum/event/meteor_wave/get_skybox_image()
var/image/res = image('icons/skybox/rockbox.dmi', "rockbox")
res.color = COLOR_ASTEROID_ROCK
res.appearance_flags = RESET_COLOR
return res
/datum/event/meteor_wave/setup() /datum/event/meteor_wave/setup()
waves = 2 + rand(1, severity) //EVENT_LEVEL_MAJOR is 3-5 waves waves = (2 + rand(1, severity)) * severity
start_side = pick(cardinal) start_side = pick(cardinal)
endWhen = worst_case_end() endWhen = worst_case_end()
/datum/event/meteor_wave/announce() /datum/event/meteor_wave/announce()
switch(severity) switch(severity)
if(EVENT_LEVEL_MAJOR) if(EVENT_LEVEL_MAJOR)
command_announcement.Announce("Meteors have been detected on collision course with \the [station_name()].", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg') command_announcement.Announce("Meteors have been detected on collision course with \the [location_name()].", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg')
else else
command_announcement.Announce("\The [station_name()] is now in a meteor shower.", "Meteor Alert") command_announcement.Announce("\The [location_name()] is now in a meteor shower.", "Meteor Alert")
/datum/event/meteor_wave/tick() /datum/event/meteor_wave/tick()
if(waves && activeFor >= next_meteor) if(waves && activeFor >= next_meteor)
var/pick_side = prob(80) ? start_side : (prob(50) ? turn(start_side, 90) : turn(start_side, -90)) send_wave()
spawn() spawn_meteors(severity * rand(1,2), get_meteors(), pick_side) /datum/event/meteor_wave/proc/send_wave()
next_meteor += rand(15, 30) / severity var/pick_side = prob(80) ? start_side : (prob(50) ? turn(start_side, 90) : turn(start_side, -90))
waves--
endWhen = worst_case_end() 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, 3)
/datum/event/meteor_wave/proc/worst_case_end() /datum/event/meteor_wave/proc/worst_case_end()
return activeFor + ((30 / severity) * waves) + 10 return activeFor + ((30 / severity) * waves) + 10
@@ -32,9 +47,9 @@
/datum/event/meteor_wave/end() /datum/event/meteor_wave/end()
switch(severity) switch(severity)
if(EVENT_LEVEL_MAJOR) if(EVENT_LEVEL_MAJOR)
command_announcement.Announce("\The [station_name()] has cleared the meteor storm.", "Meteor Alert") command_announcement.Announce("\The [location_name()] has cleared the meteor storm.", "Meteor Alert")
else else
command_announcement.Announce("\The [station_name()] has cleared the meteor shower", "Meteor Alert") command_announcement.Announce("\The [location_name()] has cleared the meteor shower", "Meteor Alert")
/datum/event/meteor_wave/proc/get_meteors() /datum/event/meteor_wave/proc/get_meteors()
if(EVENT_LEVEL_MAJOR) if(EVENT_LEVEL_MAJOR)
@@ -44,3 +59,41 @@
return meteors_threatening return meteors_threatening
else else
return meteors_normal return meteors_normal
/datum/event/meteor_wave/overmap
next_meteor_lower = 5
next_meteor_upper = 10
next_meteor = 0
/datum/event/meteor_wave/overmap/tick()
if(victim && !victim.is_still()) // Meteors mostly fly in your face
start_side = prob(90) ? victim.fore_dir : pick(GLOB.cardinal)
else //Unless you're standing still
start_side = pick(GLOB.cardinal)
..()
/datum/event/meteor_wave/overmap/get_wave_size()
. = ..()
if(!victim)
return
var/skill = victim.get_helm_skill()
var/speed = victim.get_speed()
if(skill >= SKILL_PROF)
. = round(. * 0.5)
if(victim.is_still()) //Standing still means less shit flies your way
. = round(. * 0.1)
if(speed < SHIP_SPEED_SLOW) //Slow and steady
. = round(. * 0.5)
if(speed > SHIP_SPEED_FAST) //Sanic stahp
. *= 2
//Smol ship evasion
if(victim.vessel_size < SHIP_SIZE_LARGE && speed < SHIP_SPEED_FAST)
var/skill_needed = SKILL_PROF
if(speed < SHIP_SPEED_SLOW)
skill_needed = SKILL_ADEPT
if(victim.vessel_size < SHIP_SIZE_SMALL)
skill_needed = skill_needed - 1
if(skill >= max(skill_needed, victim.skill_needed))
. = round(. * 0.5)

View File

@@ -3,6 +3,7 @@ var/global/const
SKILL_BASIC = 1 SKILL_BASIC = 1
SKILL_ADEPT = 2 SKILL_ADEPT = 2
SKILL_EXPERT = 3 SKILL_EXPERT = 3
SKILL_PROF = 4
/datum/skill/var /datum/skill/var
ID = "none" // ID of the skill, used in code ID = "none" // ID of the skill, used in code

View File

@@ -1,145 +0,0 @@
//How far from the edge of overmap zlevel could randomly placed objects spawn
#define OVERMAP_EDGE 2
#define SHIP_SIZE_TINY 1
#define SHIP_SIZE_SMALL 2
#define SHIP_SIZE_LARGE 3
//multipliers for max_speed to find 'slow' and 'fast' speeds for the ship
#define SHIP_SPEED_SLOW 1/(40 SECONDS)
#define SHIP_SPEED_FAST 3/(20 SECONDS)// 15 speed
#define OVERMAP_WEAKNESS_NONE 0
#define OVERMAP_WEAKNESS_FIRE 1
#define OVERMAP_WEAKNESS_EMP 2
#define OVERMAP_WEAKNESS_MINING 4
#define OVERMAP_WEAKNESS_EXPLOSIVE 8
//Dimension of overmap (squares 4 lyfe)
var/global/list/map_sectors = list()
/area/overmap/
name = "System Map"
icon_state = "start"
requires_power = 0
base_turf = /turf/unsimulated/map
/turf/unsimulated/map
icon = 'icons/turf/space.dmi'
icon_state = "map"
initialized = FALSE // TODO - Fix unsimulated turf initialization so this override is not necessary!
/turf/unsimulated/map/edge
opacity = 1
density = 1
/turf/unsimulated/map/Initialize()
. = ..()
name = "[x]-[y]"
var/list/numbers = list()
if(x == 1 || x == global.using_map.overmap_size)
numbers += list("[round(y/10)]","[round(y%10)]")
if(y == 1 || y == global.using_map.overmap_size)
numbers += "-"
if(y == 1 || y == global.using_map.overmap_size)
numbers += list("[round(x/10)]","[round(x%10)]")
for(var/i = 1 to numbers.len)
var/image/I = image('icons/effects/numbers.dmi',numbers[i])
I.pixel_x = 5*i - 2
I.pixel_y = world.icon_size/2 - 3
if(y == 1)
I.pixel_y = 3
I.pixel_x = 5*i + 4
if(y == global.using_map.overmap_size)
I.pixel_y = world.icon_size - 9
I.pixel_x = 5*i + 4
if(x == 1)
I.pixel_x = 5*i - 2
if(x == global.using_map.overmap_size)
I.pixel_x = 5*i + 2
add_overlay(I)
//list used to track which zlevels are being 'moved' by the proc below
var/list/moving_levels = list()
//Proc to 'move' stars in spess
//yes it looks ugly, but it should only fire when state actually change.
//null direction stops movement
proc/toggle_move_stars(zlevel, direction)
if(!zlevel)
return
if (moving_levels["[zlevel]"] != direction)
moving_levels["[zlevel]"] = direction
var/list/spaceturfs = block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel))
for(var/turf/space/T in spaceturfs)
T.toggle_transit(direction)
CHECK_TICK
/*
//list used to cache empty zlevels to avoid nedless map bloat
var/list/cached_space = list()
proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A)
var/obj/effect/map/M = map_sectors["[T.z]"]
if (!M)
return
var/mapx = M.x
var/mapy = M.y
var/nx = 1
var/ny = 1
var/nz = M.map_z
if(T.x <= TRANSITIONEDGE)
nx = world.maxx - TRANSITIONEDGE - 2
ny = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
mapx = max(1, mapx-1)
else if (A.x >= (world.maxx - TRANSITIONEDGE - 1))
nx = TRANSITIONEDGE + 2
ny = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
mapx = min(world.maxx, mapx+1)
else if (T.y <= TRANSITIONEDGE)
ny = world.maxy - TRANSITIONEDGE -2
nx = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
mapy = max(1, mapy-1)
else if (A.y >= (world.maxy - TRANSITIONEDGE - 1))
ny = TRANSITIONEDGE + 2
nx = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
mapy = min(world.maxy, mapy+1)
testing("[A] moving from [M] ([M.x], [M.y]) to ([mapx],[mapy]).")
var/turf/map = locate(mapx,mapy,OVERMAP_ZLEVEL)
var/obj/effect/map/TM = locate() in map
if(TM)
nz = TM.map_z
testing("Destination: [TM]")
else
if(cached_space.len)
var/obj/effect/map/sector/temporary/cache = cached_space[cached_space.len]
cached_space -= cache
nz = cache.map_z
cache.x = mapx
cache.y = mapy
testing("Destination: *cached* [TM]")
else
world.maxz++
nz = world.maxz
TM = new /obj/effect/map/sector/temporary(mapx, mapy, nz)
testing("Destination: *new* [TM]")
var/turf/dest = locate(nx,ny,nz)
if(dest)
A.loc = dest
if(istype(M, /obj/effect/map/sector/temporary))
var/obj/effect/map/sector/temporary/source = M
if (source.can_die())
testing("Catching [M] for future use")
source.loc = null
cached_space += source
*/

View File

@@ -0,0 +1,163 @@
GLOBAL_DATUM_INIT(overmap_event_handler, /decl/overmap_event_handler, new)
/decl/overmap_event_handler
var/list/hazard_by_turf
var/list/ship_events
/decl/overmap_event_handler/New()
..()
hazard_by_turf = list()
ship_events = list()
// Populates overmap with random events! Should be called once at startup at some point.
/decl/overmap_event_handler/proc/create_events(var/z_level, var/overmap_size, var/number_of_events)
// Acquire the list of not-yet utilized overmap turfs on this Z-level
var/list/overmap_turfs = block(locate(OVERMAP_EDGE, OVERMAP_EDGE, z_level), locate(overmap_size - OVERMAP_EDGE, overmap_size - OVERMAP_EDGE, z_level))
var/list/candidate_turfs = list()
for(var/Trf in overmap_turfs)
var/turf/T = Trf
if(!(locate(/obj/effect/overmap/visitable) in T))
candidate_turfs += T
for(var/i = 1 to number_of_events)
if(!candidate_turfs.len)
break
var/overmap_event_type = pick(subtypesof(/datum/overmap_event))
var/datum/overmap_event/datum_spawn = new overmap_event_type
log_debug("Generating cloud of [datum_spawn.count] [datum_spawn] overmap event hazards")
var/list/event_turfs = acquire_event_turfs(datum_spawn.count, datum_spawn.radius, candidate_turfs, datum_spawn.continuous)
candidate_turfs -= event_turfs
for(var/event_turf in event_turfs)
var/type = pick(datum_spawn.hazards)
new type(event_turf)
qdel(datum_spawn)//idk help how do I do this better?
/decl/overmap_event_handler/proc/acquire_event_turfs(var/number_of_turfs, var/distance_from_origin, var/list/candidate_turfs, var/continuous = TRUE)
number_of_turfs = min(number_of_turfs, candidate_turfs.len)
candidate_turfs = candidate_turfs.Copy() // Not this proc's responsibility to adjust the given lists
var/origin_turf = pick(candidate_turfs)
var/list/selected_turfs = list(origin_turf)
var/list/selection_turfs = list(origin_turf)
candidate_turfs -= origin_turf
while(selection_turfs.len && selected_turfs.len < number_of_turfs)
var/selection_turf = pick(selection_turfs)
var/random_neighbour = get_random_neighbour(selection_turf, candidate_turfs, continuous, distance_from_origin)
if(random_neighbour)
candidate_turfs -= random_neighbour
selected_turfs += random_neighbour
if(get_dist(origin_turf, random_neighbour) < distance_from_origin)
selection_turfs += random_neighbour
else
selection_turfs -= selection_turf
return selected_turfs
/decl/overmap_event_handler/proc/get_random_neighbour(var/turf/origin_turf, var/list/candidate_turfs, var/continuous = TRUE, var/range)
var/fitting_turfs
if(continuous)
fitting_turfs = origin_turf.CardinalTurfs(FALSE)
else
fitting_turfs = trange(range, origin_turf)
fitting_turfs = shuffle(fitting_turfs)
for(var/turf/T in fitting_turfs)
if(T in candidate_turfs)
return T
/decl/overmap_event_handler/proc/start_hazard(var/obj/effect/overmap/visitable/ship/ship, var/obj/effect/overmap/event/hazard)//make these accept both hazards or events
if(!(ship in ship_events))
ship_events += ship
for(var/event_type in hazard.events)
if(is_event_active(ship, event_type, hazard.difficulty))//event's already active, don't bother
continue
var/datum/event_meta/EM = new(hazard.difficulty, "Overmap event - [hazard.name]", event_type, add_to_queue = FALSE, is_one_shot = TRUE)
var/datum/event/E = new event_type(EM)
E.startWhen = 0
E.endWhen = INFINITY
// TODO - Leshana - Note: event.setup() is called before these are set!
E.affecting_z = ship.map_z
E.victim = ship
LAZYADD(ship_events[ship], E)
/decl/overmap_event_handler/proc/stop_hazard(var/obj/effect/overmap/visitable/ship/ship, var/obj/effect/overmap/event/hazard)
for(var/event_type in hazard.events)
var/datum/event/E = is_event_active(ship, event_type, hazard.difficulty)
if(E)
E.kill()
LAZYREMOVE(ship_events[ship], E)
/decl/overmap_event_handler/proc/is_event_active(var/ship, var/event_type, var/severity)
if(!ship_events[ship]) return
for(var/datum/event/E in ship_events[ship])
if(E.type == event_type && E.severity == severity)
return E
/decl/overmap_event_handler/proc/on_turf_entered(var/turf/new_loc, var/obj/effect/overmap/visitable/ship/ship, var/old_loc)
if(!istype(ship))
return
if(new_loc == old_loc)
return
for(var/obj/effect/overmap/event/E in hazard_by_turf[new_loc])
start_hazard(ship, E)
/decl/overmap_event_handler/proc/on_turf_exited(var/turf/old_loc, var/obj/effect/overmap/visitable/ship/ship, var/new_loc)
if(!istype(ship))
return
if(new_loc == old_loc)
return
for(var/obj/effect/overmap/event/E in hazard_by_turf[old_loc])
if(is_event_included(hazard_by_turf[new_loc], E))
continue // If new turf has the same event as well... keep it going!
stop_hazard(ship, E)
/decl/overmap_event_handler/proc/update_hazards(var/turf/T)//catch all updater
if(!istype(T))
return
var/list/active_hazards = list()
for(var/obj/effect/overmap/event/E in T)
if(is_event_included(active_hazards, E, TRUE))
continue
active_hazards += E
if(!active_hazards.len)
hazard_by_turf -= T
else
hazard_by_turf |= T
hazard_by_turf[T] = active_hazards
for(var/obj/effect/overmap/visitable/ship/ship in T)
for(var/datum/event/E in ship_events[ship])
if(is_event_in_turf(E, T))
continue
E.kill()
LAZYREMOVE(ship_events[ship], E)
for(var/obj/effect/overmap/event/E in active_hazards)
start_hazard(ship, E)
/decl/overmap_event_handler/proc/is_event_in_turf(var/datum/event/E, var/turf/T)
for(var/obj/effect/overmap/event/hazard in hazard_by_turf[T])
if(E in hazard.events && E.severity == hazard.difficulty)
return TRUE
/decl/overmap_event_handler/proc/is_event_included(var/list/hazards, var/obj/effect/overmap/event/E, var/equal_or_better)//this proc is only used so it can break out of 2 loops cleanly
for(var/obj/effect/overmap/event/A in hazards)
if(istype(A, E.type) || istype(E, A.type))
if(same_entries(A.events, E.events))
if(equal_or_better)
if(A.difficulty >= E.difficulty)
return TRUE
else
hazards -= A // TODO - Improve this SPAGHETTI CODE! Done only when called from update_hazards. ~Leshana
else
if(A.difficulty == E.difficulty)
return TRUE

View File

@@ -0,0 +1,49 @@
/*
** /datum/overmap_event - Descriptors of how/what to spawn during overmap event generation
*/
//These now are basically only used to spawn hazards. Will be useful when we need to spawn group of moving hazards
/datum/overmap_event
var/name = "map event"
var/radius = 2 // Radius of the spawn circle around chosen epicenter
var/count = 6 // How many hazards to spawn
var/hazards // List (or single) typepath of hazard to spawn
var/continuous = TRUE //if it should form continous blob, or can have gaps
/datum/overmap_event/meteor
name = "asteroid field"
count = 15
radius = 4
continuous = FALSE
hazards = /obj/effect/overmap/event/meteor
/datum/overmap_event/electric
name = "electrical storm"
count = 11
radius = 3
hazards = /obj/effect/overmap/event/electric
/datum/overmap_event/dust
name = "dust cloud"
count = 16
radius = 4
hazards = /obj/effect/overmap/event/dust
/datum/overmap_event/ion
name = "ion cloud"
count = 8
radius = 3
hazards = /obj/effect/overmap/event/ion
/datum/overmap_event/carp
name = "carp shoal"
count = 8
radius = 3
continuous = FALSE
hazards = /obj/effect/overmap/event/carp
/datum/overmap_event/carp/major
name = "carp school"
count = 5
radius = 4
hazards = /obj/effect/overmap/event/carp/major

View File

@@ -0,0 +1,86 @@
/*
** /obj/effect/overmap/event - Actual instances of event hazards on the overmap map
*/
// We don't subtype /obj/effect/overmap/visitable because that'll create sections one can travel to
// And with them "existing" on the overmap Z-level things quickly get odd.
/obj/effect/overmap/event
name = "event"
icon = 'icons/obj/overmap.dmi'
icon_state = "event"
opacity = 1
var/list/events // List of event datum paths
var/list/event_icon_states // Randomly picked from
var/difficulty = EVENT_LEVEL_MODERATE
var/weaknesses //if the BSA can destroy them and with what
var/list/victims //basically cached events on which Z level
/obj/effect/overmap/event/Initialize()
. = ..()
icon_state = pick(event_icon_states)
GLOB.overmap_event_handler.update_hazards(loc)
/obj/effect/overmap/event/Move()
var/turf/old_loc = loc
. = ..()
if(.)
GLOB.overmap_event_handler.update_hazards(old_loc)
GLOB.overmap_event_handler.update_hazards(loc)
/obj/effect/overmap/event/forceMove(atom/destination)
var/old_loc = loc
. = ..()
if(.)
GLOB.overmap_event_handler.update_hazards(old_loc)
GLOB.overmap_event_handler.update_hazards(loc)
/obj/effect/overmap/event/Destroy()//takes a look at this one as well, make sure everything is A-OK
var/turf/T = loc
. = ..()
GLOB.overmap_event_handler.update_hazards(T)
//
// Definitions for specific types!
//
/obj/effect/overmap/event/meteor
name = "asteroid field"
events = list(/datum/event/meteor_wave/overmap)
event_icon_states = list("meteor1", "meteor2", "meteor3", "meteor4")
difficulty = EVENT_LEVEL_MAJOR
weaknesses = OVERMAP_WEAKNESS_MINING | OVERMAP_WEAKNESS_EXPLOSIVE
/obj/effect/overmap/event/electric
name = "electrical storm"
events = list(/datum/event/electrical_storm)
opacity = 0
event_icon_states = list("electrical1", "electrical2", "electrical3", "electrical4")
difficulty = EVENT_LEVEL_MAJOR
weaknesses = OVERMAP_WEAKNESS_EMP
/obj/effect/overmap/event/dust
name = "dust cloud"
events = list(/datum/event/dust)
event_icon_states = list("dust1", "dust2", "dust3", "dust4")
weaknesses = OVERMAP_WEAKNESS_MINING | OVERMAP_WEAKNESS_EXPLOSIVE | OVERMAP_WEAKNESS_FIRE
/obj/effect/overmap/event/ion
name = "ion cloud"
events = list(/datum/event/ionstorm)
opacity = 0
event_icon_states = list("ion1", "ion2", "ion3", "ion4")
difficulty = EVENT_LEVEL_MAJOR
weaknesses = OVERMAP_WEAKNESS_EMP
/obj/effect/overmap/event/carp
name = "carp shoal"
events = list(/datum/event/carp_migration/overmap)
opacity = 0
difficulty = EVENT_LEVEL_MODERATE
event_icon_states = list("carp1", "carp2")
weaknesses = OVERMAP_WEAKNESS_EXPLOSIVE | OVERMAP_WEAKNESS_FIRE
/obj/effect/overmap/event/carp/major
name = "carp school"
difficulty = EVENT_LEVEL_MAJOR
event_icon_states = list("carp3", "carp4")

View File

@@ -0,0 +1,72 @@
//Dimension of overmap (squares 4 lyfe)
var/global/list/map_sectors = list()
/area/overmap/
name = "System Map"
icon_state = "start"
requires_power = 0
base_turf = /turf/unsimulated/map
/turf/unsimulated/map
icon = 'icons/turf/space.dmi'
icon_state = "map"
initialized = FALSE // TODO - Fix unsimulated turf initialization so this override is not necessary!
/turf/unsimulated/map/edge
opacity = 1
density = 1
/turf/unsimulated/map/Initialize()
. = ..()
name = "[x]-[y]"
var/list/numbers = list()
if(x == 1 || x == global.using_map.overmap_size)
numbers += list("[round(y/10)]","[round(y%10)]")
if(y == 1 || y == global.using_map.overmap_size)
numbers += "-"
if(y == 1 || y == global.using_map.overmap_size)
numbers += list("[round(x/10)]","[round(x%10)]")
for(var/i = 1 to numbers.len)
var/image/I = image('icons/effects/numbers.dmi',numbers[i])
I.pixel_x = 5*i - 2
I.pixel_y = world.icon_size/2 - 3
if(y == 1)
I.pixel_y = 3
I.pixel_x = 5*i + 4
if(y == global.using_map.overmap_size)
I.pixel_y = world.icon_size - 9
I.pixel_x = 5*i + 4
if(x == 1)
I.pixel_x = 5*i - 2
if(x == global.using_map.overmap_size)
I.pixel_x = 5*i + 2
add_overlay(I)
/turf/unsimulated/map/Entered(var/atom/movable/O, var/atom/oldloc)
..()
if(istype(O, /obj/effect/overmap/visitable/ship))
GLOB.overmap_event_handler.on_turf_entered(src, O, oldloc)
/turf/unsimulated/map/Exited(var/atom/movable/O, var/atom/newloc)
..()
if(istype(O, /obj/effect/overmap/visitable/ship))
GLOB.overmap_event_handler.on_turf_exited(src, O, newloc)
//list used to track which zlevels are being 'moved' by the proc below
var/list/moving_levels = list()
//Proc to 'move' stars in spess
//yes it looks ugly, but it should only fire when state actually change.
//null direction stops movement
proc/toggle_move_stars(zlevel, direction)
if(!zlevel)
return
if (moving_levels["[zlevel]"] != direction)
moving_levels["[zlevel]"] = direction
var/list/spaceturfs = block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel))
for(var/turf/space/T in spaceturfs)
T.toggle_transit(direction)
CHECK_TICK

View File

@@ -62,6 +62,7 @@
#include "code\__defines\mobs_vr.dm" #include "code\__defines\mobs_vr.dm"
#include "code\__defines\nifsoft.dm" #include "code\__defines\nifsoft.dm"
#include "code\__defines\objects.dm" #include "code\__defines\objects.dm"
#include "code\__defines\overmap.dm"
#include "code\__defines\planets.dm" #include "code\__defines\planets.dm"
#include "code\__defines\process_scheduler.dm" #include "code\__defines\process_scheduler.dm"
#include "code\__defines\qdel.dm" #include "code\__defines\qdel.dm"
@@ -2872,11 +2873,14 @@
#include "code\modules\organs\subtypes\vox.dm" #include "code\modules\organs\subtypes\vox.dm"
#include "code\modules\organs\subtypes\vox_vr.dm" #include "code\modules\organs\subtypes\vox_vr.dm"
#include "code\modules\organs\subtypes\xenos.dm" #include "code\modules\organs\subtypes\xenos.dm"
#include "code\modules\overmap\_defines.dm"
#include "code\modules\overmap\overmap_object.dm" #include "code\modules\overmap\overmap_object.dm"
#include "code\modules\overmap\overmap_shuttle.dm" #include "code\modules\overmap\overmap_shuttle.dm"
#include "code\modules\overmap\sectors.dm" #include "code\modules\overmap\sectors.dm"
#include "code\modules\overmap\spacetravel.dm" #include "code\modules\overmap\spacetravel.dm"
#include "code\modules\overmap\turfs.dm"
#include "code\modules\overmap\events\event_handler.dm"
#include "code\modules\overmap\events\generation.dm"
#include "code\modules\overmap\events\overmap_event.dm"
#include "code\modules\overmap\ships\landable.dm" #include "code\modules\overmap\ships\landable.dm"
#include "code\modules\overmap\ships\ship.dm" #include "code\modules\overmap\ships\ship.dm"
#include "code\modules\overmap\ships\computers\computer_shims.dm" #include "code\modules\overmap\ships\computers\computer_shims.dm"