Newmap - SMC, Openturf, Arrivals Controller, and Mine Turf Improvements (#1958)

* Replace SSingulo with SScalamity; processing cleanup
- SScalamity now handles blobs as well as singularity-types.
- Processing subtypes have been simplified to not require a stop_processing definition.

* this is probably important

* Remove cascade disabling SSgarbage

* Fixed a bug where dust() did not qdel the target mob

* Misc fixes

* Fix decals surviving break-to-plating

* Subsystem flag tweaks

* Apparently subsystems are new'd before config is.

* Fix paper icons

* Speculative fix for insane lag

* Better machinery stat

* Make organs not use SSoverlay

* Misc bugfixes & tweaks

* Nightmode fixes

* Changelog for SMC

* Port /tg/'s improved MC crash handling

* Add some more SS Recover() procs

* supply_controller -> SScargo

* More New() -> Initialize()

* pAI and robot construction overlays

* Fix cargo unit tests

* Merge the DMM Suite's atom/New() into atoms_init

* Lighting pre-baking

* Lighting initialization logging

* Fix some bad SS init orders

* Fix SSlighting logging; rename Processes to MC

* Speculative fix for insane GC lag

* Prebaked openturf/icon_smooth & fix lighting prebake

* SS init status; SSatoms LATEQDEL

* Fix bug with MC init stat panel

* Fix parallax

* Misc

* Ignore SS_NO_DISPLAY during init

* apparently this is important

* REEEEEE

* Image GC fixes; broadcaster radio-new sanity

* RCON Cleanup

* Move pAI recruiter into subsystem

* Move global solars list into sun subsystem

* Make chickens not use a global

* Demote SSdisposals to SS_BACKGROUND; garbage-debug cleanup

* Speed up space init a little

* Fix bad timer flags on floor drying

* Subsystem panic-restart verb for mins

* Explosion speedup

* Minor subsystem & MC logging tweaks

* SSopenturf improvements

* Make pipenet actually initialize (whoops)

* Minor tweaks

* Implement lighting rounding

* comments are hard okay

* Minor lattice tweaks

* Fix some timer issues & better closet init

* Timer sanity

* Request console tweaks + Storage init sanity

* Minor SSmachiner RCON improvements

* Further reduce world-start timer count

* Standardize subsystem logging

* Garbage hard delete profiling from /tg/

* Timer hang detection & recovery

* Log machines that sleep in process() and fuck up SSmachinery

* Fix an issue with external airlocks sleeping in process()

* Failsafe logging

* Minor tweaks

* Revert "Request console tweaks + Storage init sanity"

This reverts commit 98d3579e35.

* Re-implement RC changes

* Fix SQL FT saving

* Fix SSmachinery sleep in disposals

* Minor SS tweaks

* Paper fixes

* Blood drying fixes

* Merge gameticker and SSticker

* Minor global list init cleanup

* Lagcheck biogenerator & bags

* Tweak SScargo init order; RIG Initialize()

* Caching tweaks

* Remove rogue comma

* Initialize fixes

* Lighting destroy cleanup

* Fix emagging airlocks

* Initial SSicon implementation

* Tweaks & Fixes

* Fire + Air alarm queued icon updates

* Overlays + Queued icon cleanup

* Runtime & background fixes

* Kill some meaningless set statements

* Kill some image qdels

* Bump up lighting rounding val

* Fix adv. scanner destroy runtimes

* Remove unneeded icon update limiting

* Move icon smoothing into helpers

* Show a warning if DM 510 compiles without memory leak hack enabled

* Re-organize subsystems & MC defines a little

* Airlock SFX

* Log of Changes

* Make SSicon_update disable itself when not doing anything

* Fix respawn verb runtime when used early in server-init

* Add more information to MC's stat_entry()

* Replace direct refernces to gcDestroyed with QDEL* macros

* plant_controller -> SSplants

* More plant tweaks

* Add more humor to changelog

* Move parallax globals into SSparallax

* Lighting responsiveness tweaks

* Fix parallax init order & better MC init panel stat

* Make mobs GC

* More overlays + Remove intercom spawn()

* SSfast_process; make pinpointers not use spawn-recursion to process
Also made the SM Cascade beach process with SSprocessing instead of a spawn loop.

* Update changelog

* Mob GC tweaks

* Del() cleanup

* Fix insomniac ZAS connection edges

* Minor pAI cleanup

* Convert more things to SSoverlay; fix duplicated overlay in field gens

* SM Bluespace turf tweaks

* Update SSgarbage debug globals list

* Human-type qdel tweaks

* Subsystem suspension; stat_entry improvements

* SQL Statistics cleanup

* Fix runtimes with ambrosia

* More disable() -> suspend(); fix nightmode again

* Human qdel fix; minor tweaks

* Update turbolift to work with StonedMC

* Make lifts use timers instead of a subsystem

* Make SSassets start earlier

* Convert the radio controller into a subsystem

* Fix some missing CHECK_TICKs in asteroid generation

* MC stat tweaks; make shouldnt_see a typecache

* Kill some redundant debug-controller entries

* radio_controller -> SSradio

* Better SSgarbage hard-del logging from /tg/ upstream

* Logging tweaks + GELF

* Misc client caching improvements

* Slime SSoverlay

* Oven icon fixes

* Implant fixes
- Death implants will no longer spam Common on death of user.
- Death implants should handle a deleted user better.

* Holder tweaks + Welding tool Initialize()

* Fix some bad subsystem logging

* Fix suit cooling units spawning without cells

* Starlight tweaks

* Gibber infinite gib fix

* More SSoverlay stuff

* Make crates use CUT_OVERLAY_IN

* Make SSarrivals suspend instead of disable

* Make openturf use split/phased tick checks

* Speculative fix for unwet timer runtimes

* Blood overlay tweaks/fixes

* Update crusher to play nice with SMC + SSoverlay

* Openturf improvements and fixes

* Minor turbolift tweaks

* Lighting performance improvements + ChangeTurf tweaks

* this is probably important

* Fix wall weld noises on changeturf

* More ChangeTurf tweaks

* Explosion tweaks

* Pre-game lobby tweaks

* Openturf tweaks

* Prevent admins from starting the game before init finishes

* Fix Travis

* Kill an unused var

* Fix ChangeTurf runtimes on openturfs

* Fixes

* Browser datum fixes, asset caching

* Update changelog

* Changelog

* Lobby tweaks

* Ticker tweaks; kill ticker var

* Further lobby tweaks

* Cascade tweaks

* air_master -> SSair

* Reduce overhead from radio autosay

* alarm_manager -> SSalarm

* bomb_processor -> SSexplosives

* corp_regs -> SSlaw

* ZAS overlay fixes

* Small wall icon optimization

* Fix effects master

* Assembly tweaks

* Megavend fixes

* Shuttle fixes

* Camera alert performance improvements

* Fix some world.log spam from lighting overlays

* Fix some Initialize() procs

* Openspace responsiveness tweaks

* Make HE pipes animate through openturfs

* Kill a spawn
This commit is contained in:
Lohikar
2017-05-02 13:40:40 -05:00
committed by LordFowl
parent 9dbf27a0f4
commit f6dc33a465
872 changed files with 17767 additions and 13417 deletions
@@ -0,0 +1,157 @@
/var/datum/controller/subsystem/processing/airflow/SSairflow
#define CLEAR_OBJECT(TARGET) \
processing -= TARGET; \
TARGET.airflow_dest = null; \
TARGET.airflow_speed = 0; \
TARGET.airflow_time = 0; \
TARGET.airflow_skip_speedcheck = FALSE; \
if (TARGET.airflow_od) { \
TARGET.density = 0; \
}
/datum/controller/subsystem/processing/airflow
name = "Airflow"
wait = 1
flags = SS_NO_INIT
priority = SS_PRIORITY_AIRFLOW
/datum/controller/subsystem/processing/airflow/New()
NEW_SS_GLOBAL(SSairflow)
/datum/controller/subsystem/processing/airflow/fire(resumed = FALSE)
if (!resumed)
currentrun = processing.Copy() // Defined in parent.
var/list/curr = currentrun // Defined in parent.
while (curr.len)
var/atom/movable/target = curr[curr.len]
curr.len--
if (target.airflow_speed <= 0)
CLEAR_OBJECT(target)
if (MC_TICK_CHECK)
return
continue
if (target.airflow_process_delay > 0)
target.airflow_process_delay -= 1
if (MC_TICK_CHECK)
return
continue
else if (target.airflow_process_delay)
target.airflow_process_delay = 0
target.airflow_speed = min(target.airflow_speed, 15)
target.airflow_speed -= vsc.airflow_speed_decay
if (!target.airflow_skip_speedcheck)
if (target.airflow_speed > 7)
if (target.airflow_time++ >= target.airflow_speed - 7)
if (target.airflow_od)
target.density = 0
target.airflow_skip_speedcheck = TRUE
if (MC_TICK_CHECK)
return
continue
else
if (target.airflow_od)
target.density = 0
target.airflow_process_delay = max(1, 10 - (target.airflow_speed + 3))
target.airflow_skip_speedcheck = TRUE
if (MC_TICK_CHECK)
return
continue
target.airflow_skip_speedcheck = FALSE
if (target.airflow_od)
target.density = 1
if (!target.airflow_dest || target.loc == target.airflow_dest)
target.airflow_dest = locate(min(max(target.x + target.airflow_xo, 1), world.maxx), min(max(target.y + target.airflow_yo, 1), world.maxy), target.z)
if ((target.x == 1) || (target.x == world.maxx) || (target.y == 1) || (target.y == world.maxy))
CLEAR_OBJECT(target)
if (MC_TICK_CHECK)
return
continue
if (!isturf(target.loc))
CLEAR_OBJECT(target)
if (MC_TICK_CHECK)
return
continue
step_towards(target, target.airflow_dest)
if (ismob(target) && target:client)
target:setMoveCooldown(vsc.airflow_mob_slowdown)
if (MC_TICK_CHECK)
return
#undef CLEAR_OBJECT
/atom/movable
var/tmp/airflow_xo
var/tmp/airflow_yo
var/tmp/airflow_od
var/tmp/airflow_process_delay
var/tmp/airflow_skip_speedcheck
/atom/movable/proc/prepare_airflow(n)
if (!airflow_dest || airflow_speed < 0 || last_airflow > world.time - vsc.airflow_delay)
return FALSE
if (airflow_speed)
airflow_speed = n / max(get_dist(src, airflow_dest), 1)
return FALSE
if (airflow_dest == loc)
step_away(src, loc)
if (!src.AirflowCanMove(n))
return FALSE
if (ismob(src))
src << span("danger", "You are pushed away by airflow!")
last_airflow = world.time
var/airflow_falloff = 9 - sqrt((x - airflow_dest.x) ** 2 + (y - airflow_dest.y) ** 2)
if (airflow_falloff < 1)
airflow_dest = null
return FALSE
airflow_speed = min(max(n * (9 / airflow_falloff), 1), 9)
airflow_od = 0
if (!density)
density = 1
airflow_od = 1
return TRUE
/atom/movable/proc/GotoAirflowDest(n)
if (!prepare_airflow(n))
return
airflow_xo = airflow_dest.x - src.x
airflow_yo = airflow_dest.y - src.y
airflow_dest = null
SSairflow.processing += src
/atom/movable/proc/RepelAirflowDest(n)
if (!prepare_airflow(n))
return
airflow_xo = -(airflow_dest.x - src.x)
airflow_yo = -(airflow_dest.y - src.y)
airflow_dest = null
SSairflow.processing += src
@@ -0,0 +1,10 @@
// This is a separate processor so the MC can schedule singuloth/tesla/Nar-sie independent from other objects.
var/datum/controller/subsystem/processing/SScalamity
/datum/controller/subsystem/processing/calamity
name = "Calamity"
flags = SS_NO_INIT | SS_POST_FIRE_TIMING
priority = SS_PRIORITY_CALAMITY
/datum/controller/subsystem/processing/calamity/New()
NEW_SS_GLOBAL(SScalamity)
@@ -0,0 +1,9 @@
var/datum/controller/subsystem/processing/disease/SSdisease
/datum/controller/subsystem/processing/disease
name = "Diseases"
flags = SS_KEEP_TIMING | SS_NO_INIT
priority = SS_PRIORITY_DISEASE
/datum/controller/subsystem/processing/disease/New()
NEW_SS_GLOBAL(SSdisease)
@@ -0,0 +1,14 @@
/var/datum/controller/subsystem/processing/disposals/SSdisposals
/datum/controller/subsystem/processing/disposals
name = "Disposals"
wait = 1 // deciseconds
flags = SS_NO_INIT | SS_BACKGROUND
priority = SS_PRIORITY_DISPOSALS
// Reference list for disposal sort junctions. Filled by sorting junctions' initialize().
var/list/tagger_locations
/datum/controller/subsystem/processing/disposals/New()
NEW_SS_GLOBAL(SSdisposals)
LAZYINITLIST(tagger_locations)
@@ -0,0 +1,10 @@
/var/datum/controller/subsystem/processing/fast/SSfast_process
// Not really much to it, literally just a faster-ticking SSprocessing.
/datum/controller/subsystem/processing/fast
name = "Processing (Fast)"
wait = 5
/datum/controller/subsystem/processing/fast/New()
NEW_SS_GLOBAL(SSfast_process)
@@ -0,0 +1,9 @@
var/datum/controller/subsystem/processing/modifiers/SSmodifiers
/datum/controller/subsystem/processing/modifiers
name = "Modifiers"
wait = 1 SECOND
flags = SS_NO_INIT
priority = SS_PRIORITY_MODIFIER
/datum/controller/subsystem/processing/modifiers/New()
NEW_SS_GLOBAL(SSmodifiers)
@@ -0,0 +1,209 @@
var/datum/controller/subsystem/processing/overlays/SSoverlays
/datum/controller/subsystem/processing/overlays
name = "Overlay"
flags = SS_TICKER|SS_FIRE_IN_LOBBY
wait = 1
priority = SS_PRIORITY_OVERLAY
init_order = SS_INIT_OVERLAY
stat_tag = "Ov"
currentrun = null
var/list/overlay_icon_state_caches
var/list/overlay_icon_cache
var/initialized = FALSE
/datum/controller/subsystem/processing/overlays/New()
NEW_SS_GLOBAL(SSoverlays)
LAZYINITLIST(overlay_icon_state_caches)
LAZYINITLIST(overlay_icon_cache)
/datum/controller/subsystem/processing/overlays/Initialize()
initialized = TRUE
Flush()
..()
/datum/controller/subsystem/processing/overlays/Recover()
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
overlay_icon_cache = SSoverlays.overlay_icon_cache
processing = SSoverlays.processing
/datum/controller/subsystem/processing/overlays/fire(resumed = FALSE, mc_check = TRUE)
while(processing.len)
var/atom/thing = processing[processing.len]
processing.len--
if(thing)
thing.compile_overlays(FALSE)
if(mc_check)
if(MC_TICK_CHECK)
break
else
CHECK_TICK
/datum/controller/subsystem/processing/overlays/proc/Flush()
if(processing.len)
log_ss("overlays", "Flushing [processing.len] overlays.")
fire(mc_check = FALSE) //pair this thread up with the MC to get extra compile time
/atom/proc/compile_overlays()
if(LAZYLEN(priority_overlays) && LAZYLEN(our_overlays))
overlays = our_overlays + priority_overlays
else if(LAZYLEN(our_overlays))
overlays = our_overlays
else if(LAZYLEN(priority_overlays))
overlays = priority_overlays
else
overlays.Cut()
overlay_queued = FALSE
/atom/movable/compile_overlays()
..()
UPDATE_OO_IF_PRESENT
/turf/compile_overlays()
..()
if (istype(above))
above.update_icon()
/proc/iconstate2appearance(icon, iconstate)
var/static/image/stringbro = new()
var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
var/list/cached_icon = icon_states_cache[icon]
if (cached_icon)
var/cached_appearance = cached_icon["[iconstate]"]
if (cached_appearance)
return cached_appearance
stringbro.icon = icon
stringbro.icon_state = iconstate
if (!cached_icon) //not using the macro to save an associated lookup
cached_icon = list()
icon_states_cache[icon] = cached_icon
var/cached_appearance = stringbro.appearance
cached_icon["[iconstate]"] = cached_appearance
return cached_appearance
/proc/icon2appearance(icon)
var/static/image/iconbro = new()
var/list/icon_cache = SSoverlays.overlay_icon_cache
. = icon_cache[icon]
if (!.)
iconbro.icon = icon
. = iconbro.appearance
icon_cache[icon] = .
/atom/proc/build_appearance_list(new_overlays)
var/static/image/appearance_bro = new()
if (!islist(new_overlays))
new_overlays = list(new_overlays)
else
listclearnulls(new_overlays)
for (var/i in 1 to length(new_overlays))
var/image/cached_overlay = new_overlays[i]
if (istext(cached_overlay))
new_overlays[i] = iconstate2appearance(icon, cached_overlay)
else if(isicon(cached_overlay))
new_overlays[i] = icon2appearance(cached_overlay)
else //image probable
appearance_bro.appearance = cached_overlay
if(!ispath(cached_overlay))
appearance_bro.dir = cached_overlay.dir
new_overlays[i] = appearance_bro.appearance
return new_overlays
#define NOT_QUEUED_ALREADY (!(overlay_queued))
#define QUEUE_FOR_COMPILE overlay_queued = TRUE; SSoverlays.processing += src;
/atom/proc/cut_overlays(priority = FALSE)
var/list/cached_overlays = our_overlays
var/list/cached_priority = priority_overlays
var/need_compile = FALSE
if(LAZYLEN(cached_overlays)) //don't queue empty lists, don't cut priority overlays
cached_overlays.Cut() //clear regular overlays
need_compile = TRUE
if(priority && LAZYLEN(cached_priority))
cached_priority.Cut()
need_compile = TRUE
if(NOT_QUEUED_ALREADY && need_compile)
QUEUE_FOR_COMPILE
/atom/proc/cut_overlay(list/overlays, priority)
if(!overlays)
return
overlays = build_appearance_list(overlays)
var/list/cached_overlays = our_overlays //sanic
var/list/cached_priority = priority_overlays
var/init_o_len = LAZYLEN(cached_overlays)
var/init_p_len = LAZYLEN(cached_priority) //starter pokemon
LAZYREMOVE(cached_overlays, overlays)
if(priority)
LAZYREMOVE(cached_priority, overlays)
if(NOT_QUEUED_ALREADY && ((init_o_len != LAZYLEN(cached_priority)) || (init_p_len != LAZYLEN(cached_overlays))))
QUEUE_FOR_COMPILE
/atom/proc/add_overlay(list/overlays, priority = FALSE)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(our_overlays) //always initialized after this point
LAZYINITLIST(priority_overlays)
var/list/cached_overlays = our_overlays //sanic
var/list/cached_priority = priority_overlays
var/init_o_len = cached_overlays.len
var/init_p_len = cached_priority.len //starter pokemon
var/need_compile
if(priority)
cached_priority += overlays //or in the image. Can we use [image] = image?
need_compile = init_p_len != cached_priority.len
else
cached_overlays += overlays
need_compile = init_o_len != cached_overlays.len
if(NOT_QUEUED_ALREADY && need_compile) //have we caught more pokemon?
QUEUE_FOR_COMPILE
/atom/proc/copy_overlays(atom/other, cut_old = FALSE) //copys our_overlays from another atom
if(!other)
if(cut_old)
cut_overlays()
return
var/list/cached_other = other.our_overlays
if(cached_other)
if(cut_old)
our_overlays = cached_other.Copy()
else
our_overlays |= cached_other
if(NOT_QUEUED_ALREADY)
QUEUE_FOR_COMPILE
else if(cut_old)
cut_overlays()
#undef NOT_QUEUED_ALREADY
#undef QUEUE_FOR_COMPILE
//TODO: Better solution for these?
/image/proc/add_overlay(x)
overlays += x
/image/proc/cut_overlay(x)
overlays -= x
/image/proc/cut_overlays(x)
overlays.Cut()
/atom
var/tmp/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate
var/tmp/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
var/tmp/overlay_queued
@@ -0,0 +1,16 @@
var/datum/controller/subsystem/processing/pipenet/SSpipenet
/datum/controller/subsystem/processing/pipenet
name = "Pipenet"
init_order = SS_INIT_PIPENET
priority = SS_PRIORITY_MACHINERY
flags = 0
/datum/controller/subsystem/processing/pipenet/New()
NEW_SS_GLOBAL(SSpipenet)
/datum/controller/subsystem/processing/pipenet/Initialize(timeofday)
for (var/obj/machinery/atmospherics/machine in machines)
machine.build_network()
CHECK_TICK
..()
@@ -0,0 +1,116 @@
/var/datum/controller/subsystem/processing/plants/SSplants
/datum/controller/subsystem/processing/plants
name = "Seeds & Plants"
flags = 0 // Override parent's flags.
wait = 75
init_order = SS_INIT_SEEDS
priority = SS_PRIORITY_PLANTS
var/list/product_descs = list() // Stores generated fruit descs.
var/list/seeds = list() // All seed data stored here.
var/list/gene_tag_masks = list() // Gene obfuscation for delicious trial and error goodness.
var/list/plant_icon_cache = list() // Stores images of growth, fruits and seeds.
var/list/plant_sprites = list() // List of all harvested product sprites.
var/list/plant_product_sprites = list() // List of all growth sprites plus number of growth stages.
/datum/controller/subsystem/processing/plants/New()
NEW_SS_GLOBAL(SSplants)
/datum/controller/subsystem/processing/plants/Initialize(timeofday)
// Build the icon lists.
for(var/icostate in icon_states('icons/obj/hydroponics_growing.dmi'))
var/split = findtext(icostate,"-")
if(!split)
// invalid icon_state
continue
var/ikey = copytext(icostate,(split+1))
if(ikey == "dead")
// don't count dead icons
continue
ikey = text2num(ikey)
var/base = copytext(icostate,1,split)
if(!(plant_sprites[base]) || (plant_sprites[base]<ikey))
plant_sprites[base] = ikey
for(var/icostate in icon_states('icons/obj/hydroponics_products.dmi'))
var/split = findtext(icostate,"-")
if(split)
plant_product_sprites |= copytext(icostate,1,split)
// Populate the global seed datum list.
for(var/type in typesof(/datum/seed)-/datum/seed)
var/datum/seed/S = new type
seeds[S.name] = S
S.uid = "[seeds.len]"
S.roundstart = 1
// Make sure any seed packets that were mapped in are updated
// correctly (since the seed datums did not exist a tick ago).
for(var/obj/item/seeds/S in world)
S.update_seed()
//Might as well mask the gene types while we're at it.
var/list/used_masks = list()
var/list/plant_traits = ALL_GENES
while(plant_traits && plant_traits.len)
var/gene_tag = pick(plant_traits)
var/gene_mask = "[uppertext(num2hex(rand(0,255)))]"
while(gene_mask in used_masks)
gene_mask = "[uppertext(num2hex(rand(0,255)))]"
used_masks += gene_mask
plant_traits -= gene_tag
gene_tag_masks[gene_tag] = gene_mask
..()
/datum/controller/subsystem/processing/plants/Recover()
if (istype(SSplants))
src.product_descs = SSplants.product_descs
src.seeds = SSplants.seeds
src.gene_tag_masks = SSplants.gene_tag_masks
src.plant_icon_cache = SSplants.plant_icon_cache
src.plant_sprites = SSplants.plant_sprites
src.plant_product_sprites = SSplants.plant_product_sprites
// Proc for creating a random seed type.
/datum/controller/subsystem/processing/plants/proc/create_random_seed(var/survive_on_station)
var/datum/seed/seed = new()
seed.randomize()
seed.uid = seeds.len + 1
seed.name = "[seed.uid]"
seeds[seed.name] = seed
if(survive_on_station)
if(seed.consume_gasses)
seed.consume_gasses["phoron"] = null
seed.consume_gasses["carbon_dioxide"] = null
if(seed.chems && !isnull(seed.chems["pacid"]))
seed.chems["pacid"] = null // Eating through the hull will make these plants completely inviable, albeit very dangerous.
seed.chems -= null // Setting to null does not actually remove the entry, which is weird.
seed.set_trait(TRAIT_IDEAL_HEAT,293)
seed.set_trait(TRAIT_HEAT_TOLERANCE,20)
seed.set_trait(TRAIT_IDEAL_LIGHT,8)
seed.set_trait(TRAIT_LIGHT_TOLERANCE,5)
seed.set_trait(TRAIT_LOWKPA_TOLERANCE,25)
seed.set_trait(TRAIT_HIGHKPA_TOLERANCE,200)
return seed
// Debug for testing seed genes.
/client/proc/show_plant_genes()
set category = "Debug"
set name = "Show Plant Genes"
set desc = "Prints the round's plant gene masks."
if(!holder) return
if(!SSplants || !SSplants.gene_tag_masks)
usr << "Gene masks not set."
return
for(var/mask in SSplants.gene_tag_masks)
usr << "[mask]: [SSplants.gene_tag_masks[mask]]"
@@ -0,0 +1,42 @@
//Used to process objects. Fires once every two seconds.
var/datum/controller/subsystem/processing/SSprocessing
/datum/controller/subsystem/processing
name = "Processing"
priority = SS_PRIORITY_PROCESSING
flags = SS_BACKGROUND|SS_POST_FIRE_TIMING|SS_NO_INIT
var/stat_tag = "P" //Used for logging
var/list/processing = list()
var/list/currentrun = list()
/datum/controller/subsystem/processing/New()
NEW_SS_GLOBAL(SSprocessing)
/datum/controller/subsystem/processing/stat_entry()
..("[stat_tag]:[processing.len]")
/datum/controller/subsystem/processing/fire(resumed = 0)
if (!resumed)
currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/current_run = currentrun
while(current_run.len)
var/datum/thing = current_run[current_run.len]
current_run.len--
if(thing)
if (thing.process() == PROCESS_KILL)
stop_processing(thing)
else
processing -= thing
if (MC_TICK_CHECK)
return
// Helper so PROCESS_KILL works.
/datum/controller/subsystem/processing/proc/stop_processing(datum/D)
STOP_PROCESSING(src, D)
/datum/var/isprocessing = 0
/datum/proc/process()
return PROCESS_KILL
@@ -0,0 +1,256 @@
var/datum/controller/subsystem/processing/shuttle/shuttle_controller
/datum/controller/subsystem/processing/shuttle
name = "Shuttles"
init_order = SS_INIT_SHUTTLE
priority = SS_PRIORITY_SHUTTLE
flags = 0 // Override parent.
var/list/shuttles
/datum/controller/subsystem/processing/shuttle/New()
NEW_SS_GLOBAL(shuttle_controller)
shuttles = list()
/datum/controller/subsystem/processing/shuttle/Recover()
src.shuttles = shuttle_controller.shuttles
/datum/controller/subsystem/processing/shuttle/proc/setup_shuttle_docks()
for(var/shuttle_tag in shuttles)
var/datum/shuttle/shuttle = shuttles[shuttle_tag]
shuttle.init_docking_controllers()
shuttle.dock() //makes all shuttles docked to something at round start go into the docked state
for(var/obj/machinery/embedded_controller/C in machines)
if(istype(C.program, /datum/computer/file/embedded_program/docking))
C.program.tag = null //clear the tags, 'cause we don't need 'em anymore
/datum/controller/subsystem/processing/shuttle/Initialize(timeofday)
var/datum/shuttle/ferry/shuttle
// Escape shuttle and pods
shuttle = new/datum/shuttle/ferry/emergency()
shuttle.location = 1
shuttle.warmup_time = 10
shuttle.area_offsite = locate(/area/shuttle/escape/centcom)
shuttle.area_station = locate(/area/shuttle/escape/station)
shuttle.area_transition = locate(/area/shuttle/escape/transit)
shuttle.docking_controller_tag = "escape_shuttle"
shuttle.dock_target_station = "escape_dock"
shuttle.dock_target_offsite = "centcom_dock"
shuttle.transit_direction = NORTH
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN
//shuttle.docking_controller_tag = "supply_shuttle"
//shuttle.dock_target_station = "cargo_bay"
shuttles["Escape"] = shuttle
START_PROCESSING(shuttle_controller, shuttle)
log_debug("Escape shuttle [shuttle ? "exists." : "DOES NOT EXIST!"]")
shuttle = new/datum/shuttle/ferry/escape_pod()
shuttle.location = 0
shuttle.warmup_time = 0
shuttle.area_station = locate(/area/shuttle/escape_pod1/station)
shuttle.area_offsite = locate(/area/shuttle/escape_pod1/centcom)
shuttle.area_transition = locate(/area/shuttle/escape_pod1/transit)
shuttle.docking_controller_tag = "escape_pod_1"
shuttle.dock_target_station = "escape_pod_1_berth"
//shuttle.dock_target_offsite = "escape_pod_1_recovery"
shuttle.transit_direction = NORTH
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN + rand(-30, 60) //randomize this so it seems like the pods are being picked up one by one
shuttles["Escape Pod 1"] = shuttle
START_PROCESSING(shuttle_controller, shuttle)
shuttle = new/datum/shuttle/ferry/escape_pod()
shuttle.location = 0
shuttle.warmup_time = 0
shuttle.area_station = locate(/area/shuttle/escape_pod2/station)
shuttle.area_offsite = locate(/area/shuttle/escape_pod2/centcom)
shuttle.area_transition = locate(/area/shuttle/escape_pod2/transit)
shuttle.docking_controller_tag = "escape_pod_2"
shuttle.dock_target_station = "escape_pod_2_berth"
//shuttle.dock_target_offsite = "escape_pod_2_recovery"
shuttle.transit_direction = NORTH
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN + rand(-30, 60) //randomize this so it seems like the pods are being picked up one by one
shuttles["Escape Pod 2"] = shuttle
START_PROCESSING(shuttle_controller, shuttle)
shuttle = new/datum/shuttle/ferry/escape_pod()
shuttle.location = 0
shuttle.warmup_time = 0
shuttle.area_station = locate(/area/shuttle/escape_pod3/station)
shuttle.area_offsite = locate(/area/shuttle/escape_pod3/centcom)
shuttle.area_transition = locate(/area/shuttle/escape_pod3/transit)
shuttle.docking_controller_tag = "escape_pod_3"
shuttle.dock_target_station = "escape_pod_3_berth"
//shuttle.dock_target_offsite = "escape_pod_3_recovery"
shuttle.transit_direction = EAST
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN + rand(-30, 60) //randomize this so it seems like the pods are being picked up one by one
shuttles["Escape Pod 3"] = shuttle
START_PROCESSING(shuttle_controller, shuttle)
//There is no pod 4, apparently.
/*shuttle = new/datum/shuttle/ferry/escape_pod()
shuttle.location = 0
shuttle.warmup_time = 0
shuttle.area_station = locate(/area/shuttle/escape_pod5/station)
shuttle.area_offsite = locate(/area/shuttle/escape_pod5/centcom)
shuttle.area_transition = locate(/area/shuttle/escape_pod5/transit)
shuttle.docking_controller_tag = "escape_pod_5"
shuttle.dock_target_station = "escape_pod_5_berth"
shuttle.dock_target_offsite = "escape_pod_5_recovery"
shuttle.transit_direction = EAST //should this be WEST? I have no idea.
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN + rand(-30, 60) //randomize this so it seems like the pods are being picked up one by one
process_shuttles += shuttle
shuttles["Escape Pod 5"] = shuttle*/
//give the emergency shuttle controller it's shuttles
emergency_shuttle.shuttle = shuttles["Escape"]
emergency_shuttle.escape_pods = list(
shuttles["Escape Pod 1"],
shuttles["Escape Pod 2"],
shuttles["Escape Pod 3"]
)
// Supply shuttle
shuttle = new/datum/shuttle/ferry/supply()
shuttle.location = 1
shuttle.warmup_time = 10
shuttle.area_offsite = locate(/area/supply/dock)
shuttle.area_station = locate(/area/supply/station)
shuttle.docking_controller_tag = "supply_shuttle"
shuttle.dock_target_station = "cargo_bay"
shuttles["Supply"] = shuttle
START_PROCESSING(shuttle_controller, shuttle)
SScargo.shuttle = shuttle
shuttle = new/datum/shuttle/ferry/arrival()
shuttle.location = 1
shuttle.warmup_time = 5
shuttle.area_station = locate(/area/shuttle/arrival/station)
shuttle.area_offsite = locate(/area/shuttle/arrival/centcom)
shuttle.area_transition = locate(/area/shuttle/arrival/transit)
shuttle.docking_controller_tag = "arrival_shuttle"
shuttle.dock_target_station = "arrival_dock"
shuttle.dock_target_offsite = "centcom_setup"
shuttle.transit_direction = EAST
shuttle.move_time = 60
shuttles["Arrival"] = shuttle
START_PROCESSING(shuttle_controller, shuttle)
SSarrivals.shuttle = shuttle
// Admin shuttles.
shuttle = new()
shuttle.location = 1
shuttle.warmup_time = 10
shuttle.area_offsite = locate(/area/shuttle/transport1/centcom)
shuttle.area_station = locate(/area/shuttle/transport1/station)
shuttle.docking_controller_tag = "centcom_shuttle"
shuttle.dock_target_station = "centcom_shuttle_dock_airlock"
shuttle.dock_target_offsite = "centcom_shuttle_bay"
shuttles["Centcom"] = shuttle
START_PROCESSING(shuttle_controller, shuttle)
shuttle = new()
shuttle.location = 1
shuttle.warmup_time = 10 //want some warmup time so people can cancel.
shuttle.area_offsite = locate(/area/shuttle/administration/centcom)
shuttle.area_station = locate(/area/shuttle/administration/station)
shuttle.docking_controller_tag = "admin_shuttle"
shuttle.dock_target_station = "admin_shuttle_dock_airlock"
shuttle.dock_target_offsite = "admin_shuttle_bay"
shuttles["Administration"] = shuttle
START_PROCESSING(shuttle_controller, shuttle)
/*// Public shuttles
shuttle = new()
shuttle.warmup_time = 10
shuttle.area_offsite = locate(/area/shuttle/constructionsite/site)
shuttle.area_station = locate(/area/shuttle/constructionsite/station)
shuttle.docking_controller_tag = "engineering_shuttle"
shuttle.dock_target_station = "engineering_dock_airlock"
shuttle.dock_target_offsite = "edock_airlock"
shuttles["Engineering"] = shuttle
process_shuttles += shuttle
shuttle = new()
shuttle.warmup_time = 10
shuttle.area_offsite = locate(/area/shuttle/mining/outpost)
shuttle.area_station = locate(/area/shuttle/mining/station)
shuttle.docking_controller_tag = "mining_shuttle"
shuttle.dock_target_station = "mining_dock_airlock"
shuttle.dock_target_offsite = "mining_outpost_airlock"
shuttles["Mining"] = shuttle
process_shuttles += shuttle
shuttle = new()
shuttle.warmup_time = 10
shuttle.area_offsite = locate(/area/shuttle/research/outpost)
shuttle.area_station = locate(/area/shuttle/research/station)
shuttle.docking_controller_tag = "research_shuttle"
shuttle.dock_target_station = "research_dock_airlock"
shuttle.dock_target_offsite = "research_outpost_dock"
shuttles["Research"] = shuttle
process_shuttles += shuttle*/
// ERT Shuttle
var/datum/shuttle/ferry/multidock/specops/ERT = new()
ERT.location = 0
ERT.warmup_time = 10
ERT.area_offsite = locate(/area/shuttle/specops/station) //centcom is the home station, the Exodus is offsite
ERT.area_station = locate(/area/shuttle/specops/centcom)
ERT.docking_controller_tag = "specops_shuttle_port"
ERT.docking_controller_tag_station = "specops_shuttle_port"
ERT.docking_controller_tag_offsite = "specops_shuttle_fore"
ERT.dock_target_station = "specops_centcom_dock"
ERT.dock_target_offsite = "specops_dock_airlock"
shuttles["Special Operations"] = ERT
START_PROCESSING(shuttle_controller, ERT)
//Skipjack.
var/datum/shuttle/multi_shuttle/VS = new/datum/shuttle/multi_shuttle()
VS.origin = locate(/area/skipjack_station/start)
VS.destinations = list(
"Surface of the station" = locate(/area/skipjack_station/surface),
"Under the station" = locate(/area/skipjack_station/above),
"Above the station" = locate(/area/skipjack_station/under),
"Mining caverns" = locate(/area/skipjack_station/cavern)
)
VS.announcer = "NDV Icarus"
VS.arrival_message = "Attention, [station_short], we just tracked a small target bypassing our defensive perimeter. Can't fire on it without hitting the station - you've got incoming visitors, like it or not."
VS.departure_message = "Your guests are pulling away, [station_short] - moving too fast for us to draw a bead on them. Looks like they're heading out of the system at a rapid clip."
VS.interim = locate(/area/skipjack_station/transit)
VS.warmup_time = 0
shuttles["Skipjack"] = VS
//Nuke Ops shuttle.
var/datum/shuttle/multi_shuttle/MS = new/datum/shuttle/multi_shuttle()
MS.origin = locate(/area/syndicate_station/start)
MS.start_location = "Mercenary Base"
MS.destinations = list(
"Surface of the station" = locate(/area/syndicate_station/surface),
"Above the station" = locate(/area/syndicate_station/above),
"Under the station" = locate(/area/syndicate_station/under),
"Mining caverns" = locate(/area/syndicate_station/caverns)
)
MS.docking_controller_tag = "merc_shuttle"
MS.destination_dock_targets = list(
"Mercenary Base" = "merc_base",
"Arrivals dock" = "nuke_shuttle_dock_airlock"
)
MS.announcer = "NDV Icarus"
MS.arrival_message = "Attention, [station_short], you have a large signature approaching the station - looks unarmed to surface scans. We're too far out to intercept - brace for visitors."
MS.departure_message = "Your visitors are on their way out of the system, [station_short], burning delta-v like it's nothing. Good riddance."
MS.interim = locate(/area/syndicate_station/transit)
MS.warmup_time = 0
shuttles["Mercenary"] = MS
..()