mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
Absolute paths for the files in the Controllers folder
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays
|
||||
#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha6.dmi' //Icon used for lighting shading effects
|
||||
|
||||
datum/light_source
|
||||
/datum/light_source
|
||||
var/atom/owner
|
||||
var/changed = 1
|
||||
var/list/effect = list()
|
||||
@@ -41,76 +41,76 @@ datum/light_source
|
||||
var/__y = 0 //y coordinate at last update
|
||||
|
||||
|
||||
New(atom/A)
|
||||
if(!istype(A))
|
||||
CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.")
|
||||
..()
|
||||
owner = A
|
||||
/datum/light_source/New(atom/A)
|
||||
if(!istype(A))
|
||||
CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.")
|
||||
..()
|
||||
owner = A
|
||||
__x = owner.x
|
||||
__y = owner.y
|
||||
// the lighting object maintains a list of all light sources
|
||||
lighting_controller.lights += src
|
||||
|
||||
|
||||
//Check a light to see if its effect needs reprocessing. If it does, remove any old effect and create a new one
|
||||
/datum/light_source/proc/check()
|
||||
if(!owner)
|
||||
remove_effect()
|
||||
return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it.
|
||||
|
||||
// check to see if we've moved since last update
|
||||
if(owner.x != __x || owner.y != __y)
|
||||
__x = owner.x
|
||||
__y = owner.y
|
||||
// the lighting object maintains a list of all light sources
|
||||
lighting_controller.lights += src
|
||||
changed = 1
|
||||
|
||||
if(changed)
|
||||
changed = 0
|
||||
remove_effect()
|
||||
return add_effect()
|
||||
return 0
|
||||
|
||||
|
||||
//Check a light to see if its effect needs reprocessing. If it does, remove any old effect and create a new one
|
||||
proc/check()
|
||||
if(!owner)
|
||||
remove_effect()
|
||||
return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it.
|
||||
/datum/light_source/proc/remove_effect()
|
||||
// before we apply the effect we remove the light's current effect.
|
||||
for(var/turf/T in effect) // negate the effect of this light source
|
||||
T.update_lumcount(-effect[T])
|
||||
effect.Cut() // clear the effect list
|
||||
|
||||
// check to see if we've moved since last update
|
||||
if(owner.x != __x || owner.y != __y)
|
||||
__x = owner.x
|
||||
__y = owner.y
|
||||
changed = 1
|
||||
/datum/light_source/proc/add_effect()
|
||||
// only do this if the light is turned on and is on the map
|
||||
if(owner.loc && owner.luminosity > 0)
|
||||
effect = list()
|
||||
for(var/turf/T in view(owner.get_light_range(),owner))
|
||||
var/delta_lumen = lum(T)
|
||||
if(delta_lumen > 0)
|
||||
effect[T] = delta_lumen
|
||||
T.update_lumcount(delta_lumen)
|
||||
|
||||
if(changed)
|
||||
changed = 0
|
||||
remove_effect()
|
||||
return add_effect()
|
||||
return 0
|
||||
else
|
||||
owner.light = null
|
||||
return 1 //cause the light to be removed from the lights list and garbage collected once it's no
|
||||
//longer referenced by the queue
|
||||
|
||||
|
||||
proc/remove_effect()
|
||||
// before we apply the effect we remove the light's current effect.
|
||||
for(var/turf/T in effect) // negate the effect of this light source
|
||||
T.update_lumcount(-effect[T])
|
||||
effect.Cut() // clear the effect list
|
||||
|
||||
proc/add_effect()
|
||||
// only do this if the light is turned on and is on the map
|
||||
if(owner.loc && owner.luminosity > 0)
|
||||
effect = list()
|
||||
for(var/turf/T in view(owner.get_light_range(),owner))
|
||||
var/delta_lumen = lum(T)
|
||||
if(delta_lumen > 0)
|
||||
effect[T] = delta_lumen
|
||||
T.update_lumcount(delta_lumen)
|
||||
|
||||
return 0
|
||||
else
|
||||
owner.light = null
|
||||
return 1 //cause the light to be removed from the lights list and garbage collected once it's no
|
||||
//longer referenced by the queue
|
||||
|
||||
proc/lum(turf/A)
|
||||
if (owner.trueLuminosity < 1)
|
||||
return 0
|
||||
var/dist
|
||||
if(!A)
|
||||
dist = 0
|
||||
else
|
||||
/datum/light_source/proc/lum(turf/A)
|
||||
if (owner.trueLuminosity < 1)
|
||||
return 0
|
||||
var/dist
|
||||
if(!A)
|
||||
dist = 0
|
||||
else
|
||||
#ifdef LIGHTING_CIRCULAR
|
||||
dist = cheap_hypotenuse(A.x, A.y, __x, __y)
|
||||
dist = cheap_hypotenuse(A.x, A.y, __x, __y)
|
||||
#else
|
||||
dist = max(abs(A.x - __x), abs(A.y - __y))
|
||||
dist = max(abs(A.x - __x), abs(A.y - __y))
|
||||
#endif
|
||||
if (owner.trueLuminosity > 100) // This will never happen... right?
|
||||
return sqrt(owner.trueLuminosity) - dist
|
||||
else
|
||||
return sqrtTable[owner.trueLuminosity] - dist
|
||||
if (owner.trueLuminosity > 100) // This will never happen... right?
|
||||
return sqrt(owner.trueLuminosity) - dist
|
||||
else
|
||||
return sqrtTable[owner.trueLuminosity] - dist
|
||||
|
||||
atom
|
||||
/atom
|
||||
var/datum/light_source/light
|
||||
var/trueLuminosity = 0 // Typically 'luminosity' squared. The builtin luminosity must remain linear.
|
||||
// We may read it, but NEVER set it directly.
|
||||
@@ -118,7 +118,7 @@ atom
|
||||
|
||||
//Turfs with opacity when they are constructed will trigger nearby lights to update
|
||||
//Turfs and atoms with luminosity when they are constructed will create a light_source automatically
|
||||
turf/New()
|
||||
/turf/New()
|
||||
..()
|
||||
if(luminosity)
|
||||
if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.")
|
||||
@@ -127,7 +127,7 @@ turf/New()
|
||||
|
||||
//Movable atoms with opacity when they are constructed will trigger nearby lights to update
|
||||
//Movable atoms with luminosity when they are constructed will create a light_source automatically
|
||||
atom/movable/New()
|
||||
/atom/movable/New()
|
||||
..()
|
||||
if(opacity)
|
||||
if(isturf(loc))
|
||||
@@ -139,7 +139,7 @@ atom/movable/New()
|
||||
light = new(src)
|
||||
|
||||
//Objects with opacity will trigger nearby lights to update at next lighting process.
|
||||
atom/movable/Destroy()
|
||||
/atom/movable/Destroy()
|
||||
if(opacity)
|
||||
if(isturf(loc))
|
||||
if(loc:lighting_lumcount > 1)
|
||||
@@ -151,7 +151,7 @@ atom/movable/Destroy()
|
||||
//If we are setting luminosity to 0 the light will be cleaned up by the controller and garbage collected once all its
|
||||
//queues are complete.
|
||||
//if we have a light already it is merely updated, rather than making a new one.
|
||||
atom/proc/SetLuminosity(new_luminosity, trueLum = FALSE)
|
||||
/atom/proc/SetLuminosity(new_luminosity, trueLum = FALSE)
|
||||
if(new_luminosity < 0)
|
||||
new_luminosity = 0
|
||||
if(!trueLum)
|
||||
@@ -170,19 +170,19 @@ atom/proc/SetLuminosity(new_luminosity, trueLum = FALSE)
|
||||
else
|
||||
luminosity = sqrt(trueLuminosity)
|
||||
|
||||
atom/proc/AddLuminosity(delta_luminosity)
|
||||
/atom/proc/AddLuminosity(delta_luminosity)
|
||||
if(delta_luminosity > 0)
|
||||
SetLuminosity(trueLuminosity + delta_luminosity*delta_luminosity, TRUE)
|
||||
else if(delta_luminosity < 0)
|
||||
SetLuminosity(trueLuminosity - delta_luminosity*delta_luminosity, TRUE)
|
||||
|
||||
area/SetLuminosity(new_luminosity) //we don't want dynamic lighting for areas
|
||||
/area/SetLuminosity(new_luminosity) //we don't want dynamic lighting for areas
|
||||
luminosity = !!new_luminosity
|
||||
trueLuminosity = luminosity
|
||||
|
||||
|
||||
//change our opacity (defaults to toggle), and then update all lights that affect us.
|
||||
atom/proc/SetOpacity(new_opacity)
|
||||
/atom/proc/SetOpacity(new_opacity)
|
||||
if(new_opacity == null)
|
||||
new_opacity = !opacity //default = toggle opacity
|
||||
else if(opacity == new_opacity)
|
||||
@@ -190,7 +190,7 @@ atom/proc/SetOpacity(new_opacity)
|
||||
opacity = new_opacity //update opacity, the below procs now call light updates.
|
||||
return 1
|
||||
|
||||
turf/SetOpacity(new_opacity)
|
||||
/turf/SetOpacity(new_opacity)
|
||||
if(..()==1) //only bother if opacity changed
|
||||
if(lighting_lumcount) //only bother with an update if our turf is currently affected by a light
|
||||
UpdateAffectingLights()
|
||||
@@ -203,24 +203,24 @@ turf/SetOpacity(new_opacity)
|
||||
UpdateAffectingLights()
|
||||
|
||||
|
||||
turf
|
||||
/turf
|
||||
var/lighting_lumcount = 0
|
||||
var/lighting_changed = 0
|
||||
|
||||
turf/space
|
||||
/turf/space
|
||||
lighting_lumcount = 4 //starlight
|
||||
|
||||
turf/proc/update_lumcount(amount)
|
||||
/turf/proc/update_lumcount(amount)
|
||||
lighting_lumcount += amount
|
||||
if(!lighting_changed)
|
||||
lighting_controller.changed_turfs += src
|
||||
lighting_changed = 1
|
||||
|
||||
turf/proc/lighting_tag(var/level)
|
||||
/turf/proc/lighting_tag(var/level)
|
||||
var/area/A = loc
|
||||
return A.tagbase + "sd_L[level]"
|
||||
|
||||
turf/proc/build_lighting_area(var/tag, var/level)
|
||||
/turf/proc/build_lighting_area(var/tag, var/level)
|
||||
var/area/Area = loc
|
||||
var/area/A = new Area.type() // create area if it wasn't found
|
||||
// replicate vars
|
||||
@@ -238,7 +238,7 @@ turf/proc/build_lighting_area(var/tag, var/level)
|
||||
Area.related += A
|
||||
return A
|
||||
|
||||
turf/proc/shift_to_subarea()
|
||||
/turf/proc/shift_to_subarea()
|
||||
lighting_changed = 0
|
||||
var/area/Area = loc
|
||||
|
||||
@@ -257,54 +257,54 @@ turf/proc/shift_to_subarea()
|
||||
// Dedicated lighting sublevel for space turfs
|
||||
// helps us depower things in space, remove space fire alarms,
|
||||
// and evens out space lighting
|
||||
turf/space/lighting_tag(var/level)
|
||||
/turf/space/lighting_tag(var/level)
|
||||
var/area/A = loc
|
||||
return A.tagbase + "sd_L_space"
|
||||
turf/space/build_lighting_area(var/tag,var/level)
|
||||
/turf/space/build_lighting_area(var/tag,var/level)
|
||||
var/area/A = ..(tag,4)
|
||||
A.lighting_space = 1
|
||||
A.SetLightLevel(4)
|
||||
A.icon_state = null
|
||||
return A
|
||||
|
||||
area
|
||||
/area
|
||||
var/lighting_use_dynamic = 1 //Turn this flag off to prevent sd_DynamicAreaLighting from affecting this area
|
||||
var/image/lighting_overlay //tracks the darkness image of the area for easy removal
|
||||
var/lighting_subarea = 0 //tracks whether we're a lighting sub-area
|
||||
var/lighting_space = 0 // true for space-only lighting subareas
|
||||
var/tagbase
|
||||
|
||||
proc/SetLightLevel(light)
|
||||
if(!src) return
|
||||
if(light <= 0)
|
||||
light = 0
|
||||
luminosity = 0
|
||||
else
|
||||
if(light > lighting_controller.lighting_states)
|
||||
light = lighting_controller.lighting_states
|
||||
luminosity = 1
|
||||
/area/proc/SetLightLevel(light)
|
||||
if(!src) return
|
||||
if(light <= 0)
|
||||
light = 0
|
||||
luminosity = 0
|
||||
else
|
||||
if(light > lighting_controller.lighting_states)
|
||||
light = lighting_controller.lighting_states
|
||||
luminosity = 1
|
||||
|
||||
if(lighting_overlay)
|
||||
overlays -= lighting_overlay
|
||||
lighting_overlay.icon_state = "[light]"
|
||||
else
|
||||
lighting_overlay = image(LIGHTING_ICON,,num2text(light),LIGHTING_LAYER)
|
||||
if(lighting_overlay)
|
||||
overlays -= lighting_overlay
|
||||
lighting_overlay.icon_state = "[light]"
|
||||
else
|
||||
lighting_overlay = image(LIGHTING_ICON,,num2text(light),LIGHTING_LAYER)
|
||||
|
||||
overlays += lighting_overlay
|
||||
overlays += lighting_overlay
|
||||
|
||||
proc/SetDynamicLighting()
|
||||
/area/proc/SetDynamicLighting()
|
||||
|
||||
src.lighting_use_dynamic = 1
|
||||
for(var/turf/T in src.contents)
|
||||
T.update_lumcount(0)
|
||||
src.lighting_use_dynamic = 1
|
||||
for(var/turf/T in src.contents)
|
||||
T.update_lumcount(0)
|
||||
|
||||
proc/InitializeLighting() //TODO: could probably improve this bit ~Carn
|
||||
tagbase = "[type]"
|
||||
if(!tag) tag = tagbase
|
||||
if(!lighting_use_dynamic)
|
||||
if(!lighting_subarea) // see if this is a lighting subarea already
|
||||
//show the dark overlay so areas, not yet in a lighting subarea, won't be bright as day and look silly.
|
||||
SetLightLevel(4)
|
||||
/area/proc/InitializeLighting() //TODO: could probably improve this bit ~Carn
|
||||
tagbase = "[type]"
|
||||
if(!tag) tag = tagbase
|
||||
if(!lighting_use_dynamic)
|
||||
if(!lighting_subarea) // see if this is a lighting subarea already
|
||||
//show the dark overlay so areas, not yet in a lighting subarea, won't be bright as day and look silly.
|
||||
SetLightLevel(4)
|
||||
|
||||
#undef LIGHTING_LAYER
|
||||
#undef LIGHTING_CIRCULAR
|
||||
@@ -316,24 +316,24 @@ area
|
||||
//set the changed status of all lights which could have possibly lit this atom.
|
||||
//We don't need to worry about lights which lit us but moved away, since they will have change status set already
|
||||
//This proc can cause lots of lights to be updated. :(
|
||||
atom/proc/UpdateAffectingLights()
|
||||
/atom/proc/UpdateAffectingLights()
|
||||
for(var/atom/A in oview(LIGHTING_MAX_LUMINOSITY_STATIC-1,src))
|
||||
if(A.light)
|
||||
A.light.changed = 1 //force it to update at next process()
|
||||
|
||||
//caps luminosity effects max-range based on what type the light's owner is.
|
||||
atom/proc/get_light_range()
|
||||
/atom/proc/get_light_range()
|
||||
return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC)
|
||||
|
||||
atom/movable/get_light_range()
|
||||
/atom/movable/get_light_range()
|
||||
return min(luminosity, LIGHTING_MAX_LUMINOSITY_MOBILE)
|
||||
|
||||
obj/machinery/light/get_light_range()
|
||||
/obj/machinery/light/get_light_range()
|
||||
return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC)
|
||||
|
||||
turf/get_light_range()
|
||||
/turf/get_light_range()
|
||||
return min(luminosity, LIGHTING_MAX_LUMINOSITY_TURF)
|
||||
|
||||
#undef LIGHTING_MAX_LUMINOSITY_STATIC
|
||||
#undef LIGHTING_MAX_LUMINOSITY_MOBILE
|
||||
#undef LIGHTING_MAX_LUMINOSITY_TURF
|
||||
#undef LIGHTING_MAX_LUMINOSITY_TURF
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var/datum/controller/lighting/lighting_controller = new ()
|
||||
|
||||
datum/controller/lighting
|
||||
/datum/controller/lighting
|
||||
var/processing = 0
|
||||
var/processing_interval = 5 //setting this too low will probably kill the server. Don't be silly with it!
|
||||
var/process_cost = 0
|
||||
@@ -17,7 +17,7 @@ datum/controller/lighting
|
||||
var/list/changed_turfs = list()
|
||||
var/changed_turfs_workload_max = 0
|
||||
|
||||
datum/controller/lighting/New()
|
||||
/datum/controller/lighting/New()
|
||||
lighting_states = max( 0, length(icon_states(LIGHTING_ICON))-1 )
|
||||
if(lighting_controller != src)
|
||||
if(istype(lighting_controller,/datum/controller/lighting))
|
||||
@@ -31,7 +31,7 @@ datum/controller/lighting/New()
|
||||
//All queue lists prune themselves, which will cause lights with no luminosity to be garbage collected (cheaper and safer
|
||||
//than deleting them). Processing interval should be roughly half a second for best results.
|
||||
//By using queues we are ensuring we don't perform more updates than are necessary
|
||||
datum/controller/lighting/proc/process()
|
||||
/datum/controller/lighting/proc/process()
|
||||
processing = 1
|
||||
spawn(0)
|
||||
set background = BACKGROUND_ENABLED
|
||||
@@ -65,7 +65,7 @@ datum/controller/lighting/proc/process()
|
||||
//Does not loop. Should be run prior to process() being called for the first time.
|
||||
//Note: if we get additional z-levels at runtime (e.g. if the gateway thin ever gets finished) we can initialize specific
|
||||
//z-levels with the z_level argument
|
||||
datum/controller/lighting/proc/Initialize(var/z_level)
|
||||
/datum/controller/lighting/proc/Initialize(var/z_level)
|
||||
processing = 0
|
||||
spawn(-1)
|
||||
set background = BACKGROUND_ENABLED
|
||||
@@ -95,7 +95,7 @@ datum/controller/lighting/proc/Initialize(var/z_level)
|
||||
//Used to strip valid information from an existing controller and transfer it to a replacement
|
||||
//It works by using spawn(-1) to transfer the data, if there is a runtime the data does not get transfered but the loop
|
||||
//does not crash
|
||||
datum/controller/lighting/proc/Recover()
|
||||
/datum/controller/lighting/proc/Recover()
|
||||
if(!istype(lighting_controller.changed_turfs,/list))
|
||||
lighting_controller.changed_turfs = list()
|
||||
if(!istype(lighting_controller.lights,/list))
|
||||
|
||||
@@ -11,7 +11,7 @@ var/global/last_tick_duration = 0
|
||||
var/global/air_processing_killed = 0
|
||||
var/global/pipe_processing_killed = 0
|
||||
|
||||
datum/controller/game_controller
|
||||
/datum/controller/game_controller
|
||||
var/processing = 0
|
||||
var/breather_ticks = 2 //a somewhat crude attempt to iron over the 'bumps' caused by high-cpu use by letting the MC have a breather for this many ticks after every loop
|
||||
var/minimum_ticks = 20 //The minimum length of time between MC ticks
|
||||
@@ -37,7 +37,7 @@ datum/controller/game_controller
|
||||
|
||||
var/last_thing_processed
|
||||
|
||||
datum/controller/game_controller/New()
|
||||
/datum/controller/game_controller/New()
|
||||
//There can be only one master_controller. Out with the old and in with the new.
|
||||
if(master_controller != src)
|
||||
if(istype(master_controller))
|
||||
@@ -69,7 +69,7 @@ datum/controller/game_controller/New()
|
||||
if(!emergency_shuttle) emergency_shuttle = new /datum/shuttle_controller/emergency_shuttle()
|
||||
if(!supply_shuttle) supply_shuttle = new /datum/controller/supply_shuttle()
|
||||
|
||||
datum/controller/game_controller/proc/setup()
|
||||
/datum/controller/game_controller/proc/setup()
|
||||
world.tick_lag = config.Ticklag
|
||||
|
||||
setup_objects()
|
||||
@@ -80,7 +80,7 @@ datum/controller/game_controller/proc/setup()
|
||||
if(ticker)
|
||||
ticker.pregame()
|
||||
|
||||
datum/controller/game_controller/proc/setup_objects()
|
||||
/datum/controller/game_controller/proc/setup_objects()
|
||||
world << "\red \b Initializing objects..."
|
||||
sleep(-1)
|
||||
for(var/atom/movable/object in world)
|
||||
@@ -110,7 +110,7 @@ datum/controller/game_controller/proc/setup_objects()
|
||||
sleep(-1)
|
||||
|
||||
|
||||
datum/controller/game_controller/proc/process()
|
||||
/datum/controller/game_controller/proc/process()
|
||||
processing = 1
|
||||
spawn(0)
|
||||
set background = BACKGROUND_ENABLED
|
||||
@@ -223,7 +223,7 @@ datum/controller/game_controller/proc/process()
|
||||
sleep(10)
|
||||
|
||||
/*
|
||||
datum/controller/game_controller/proc/process_liquid()
|
||||
/datum/controller/game_controller/proc/process_liquid()
|
||||
last_thing_processed = /datum/puddle
|
||||
var/i = 1
|
||||
while(i<=puddles.len)
|
||||
@@ -235,7 +235,7 @@ datum/controller/game_controller/proc/process_liquid()
|
||||
puddles.Cut(i,i+1)
|
||||
*/
|
||||
|
||||
datum/controller/game_controller/proc/process_mobs()
|
||||
/datum/controller/game_controller/proc/process_mobs()
|
||||
var/i = 1
|
||||
while(i<=mob_list.len)
|
||||
var/mob/M = mob_list[i]
|
||||
@@ -246,7 +246,7 @@ datum/controller/game_controller/proc/process_mobs()
|
||||
continue
|
||||
mob_list.Cut(i,i+1)
|
||||
|
||||
datum/controller/game_controller/proc/process_diseases()
|
||||
/datum/controller/game_controller/proc/process_diseases()
|
||||
var/i = 1
|
||||
while(i<=active_diseases.len)
|
||||
var/datum/disease/Disease = active_diseases[i]
|
||||
@@ -257,7 +257,7 @@ datum/controller/game_controller/proc/process_diseases()
|
||||
continue
|
||||
active_diseases.Cut(i,i+1)
|
||||
|
||||
datum/controller/game_controller/proc/process_machines()
|
||||
/datum/controller/game_controller/proc/process_machines()
|
||||
var/i = 1
|
||||
while(i<=machines.len)
|
||||
var/obj/machinery/Machine = machines[i]
|
||||
@@ -271,7 +271,7 @@ datum/controller/game_controller/proc/process_machines()
|
||||
continue
|
||||
machines.Cut(i,i+1)
|
||||
|
||||
datum/controller/game_controller/proc/process_objects()
|
||||
/datum/controller/game_controller/proc/process_objects()
|
||||
var/i = 1
|
||||
while(i<=processing_objects.len)
|
||||
var/obj/Object = processing_objects[i]
|
||||
@@ -282,7 +282,7 @@ datum/controller/game_controller/proc/process_objects()
|
||||
continue
|
||||
processing_objects.Cut(i,i+1)
|
||||
|
||||
datum/controller/game_controller/proc/process_pipenets()
|
||||
/datum/controller/game_controller/proc/process_pipenets()
|
||||
last_thing_processed = /datum/pipe_network
|
||||
var/i = 1
|
||||
while(i<=pipe_networks.len)
|
||||
@@ -293,7 +293,7 @@ datum/controller/game_controller/proc/process_pipenets()
|
||||
continue
|
||||
pipe_networks.Cut(i,i+1)
|
||||
|
||||
datum/controller/game_controller/proc/process_powernets()
|
||||
/datum/controller/game_controller/proc/process_powernets()
|
||||
last_thing_processed = /datum/powernet
|
||||
var/i = 1
|
||||
while(i<=powernets.len)
|
||||
@@ -304,7 +304,7 @@ datum/controller/game_controller/proc/process_powernets()
|
||||
continue
|
||||
powernets.Cut(i,i+1)
|
||||
|
||||
datum/controller/game_controller/proc/process_nano()
|
||||
/datum/controller/game_controller/proc/process_nano()
|
||||
var/i = 1
|
||||
while(i<=nanomanager.processing_uis.len)
|
||||
var/datum/nanoui/ui = nanomanager.processing_uis[i]
|
||||
@@ -314,7 +314,7 @@ datum/controller/game_controller/proc/process_nano()
|
||||
continue
|
||||
nanomanager.processing_uis.Cut(i,i+1)
|
||||
|
||||
datum/controller/game_controller/proc/Recover() //Mostly a placeholder for now.
|
||||
/datum/controller/game_controller/proc/Recover() //Mostly a placeholder for now.
|
||||
var/msg = "## DEBUG: [time2text(world.timeofday)] MC restarted. Reports:\n"
|
||||
for(var/varname in master_controller.vars)
|
||||
switch(varname)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
var/global/datum/shuttle_controller/emergency_shuttle/emergency_shuttle
|
||||
|
||||
datum/shuttle_controller
|
||||
/datum/shuttle_controller
|
||||
var/location = UNDOCKED //
|
||||
var/online = 0
|
||||
var/direction = 1 //-1 = going back to central command, 1 = going to SS13. Only important for recalling
|
||||
@@ -37,150 +37,149 @@ datum/shuttle_controller
|
||||
// call the shuttle
|
||||
// if not called before, set the endtime to T+600 seconds
|
||||
// otherwise if outgoing, switch to incoming
|
||||
proc/incall(coeff = 1, var/signal_origin)
|
||||
/datum/shuttle_controller/proc/incall(coeff = 1, var/signal_origin)
|
||||
|
||||
if(endtime)
|
||||
if(direction == -1)
|
||||
setdirection(1)
|
||||
if(endtime)
|
||||
if(direction == -1)
|
||||
setdirection(1)
|
||||
else
|
||||
if(signal_origin && prob(60)) //40% chance the signal tracing will fail
|
||||
last_call_loc = signal_origin
|
||||
else
|
||||
if(signal_origin && prob(60)) //40% chance the signal tracing will fail
|
||||
last_call_loc = signal_origin
|
||||
last_call_loc = null
|
||||
settimeleft(SHUTTLEARRIVETIME*coeff)
|
||||
online = 1
|
||||
if(always_fake_recall)
|
||||
|
||||
if ((seclevel2num(get_security_level()) == SEC_LEVEL_RED))
|
||||
fake_recall = rand(SHUTTLEARRIVETIME / 4, SHUTTLEARRIVETIME - 100 / 2)
|
||||
else
|
||||
last_call_loc = null
|
||||
settimeleft(SHUTTLEARRIVETIME*coeff)
|
||||
online = 1
|
||||
if(always_fake_recall)
|
||||
fake_recall = rand(SHUTTLEARRIVETIME / 2, SHUTTLEARRIVETIME - 100)
|
||||
|
||||
if ((seclevel2num(get_security_level()) == SEC_LEVEL_RED))
|
||||
fake_recall = rand(SHUTTLEARRIVETIME / 4, SHUTTLEARRIVETIME - 100 / 2)
|
||||
else
|
||||
fake_recall = rand(SHUTTLEARRIVETIME / 2, SHUTTLEARRIVETIME - 100)
|
||||
/datum/shuttle_controller/proc/recall(var/signal_origin)
|
||||
if(direction == 1)
|
||||
var/timeleft = timeleft()
|
||||
if(timeleft >= SHUTTLEARRIVETIME)
|
||||
online = 0
|
||||
direction = 1
|
||||
endtime = null
|
||||
return
|
||||
|
||||
proc/recall(var/signal_origin)
|
||||
recall_count ++
|
||||
|
||||
if(recall_count > 2 && signal_origin && prob(60)) //40% chance the signal tracing will fail
|
||||
last_call_loc = signal_origin
|
||||
else
|
||||
last_call_loc = null
|
||||
|
||||
if(recall_count == 2)
|
||||
priority_announce("The emergency shuttle has been recalled.\n\nExcessive number of emergency shuttle calls detected. We will attempt to trace all future calls and recalls to their source. Tracing results can be viewed on any communications console.", null, 'sound/AI/shuttlerecalled.ogg')
|
||||
else
|
||||
priority_announce("The emergency shuttle has been recalled.", null, 'sound/AI/shuttlerecalled.ogg', "Priority")
|
||||
setdirection(-1)
|
||||
online = 1
|
||||
|
||||
|
||||
// returns the time (in seconds) before shuttle arrival
|
||||
// note if direction = -1, gives a count-up to SHUTTLEARRIVETIME
|
||||
/datum/shuttle_controller/proc/timeleft()
|
||||
if(online)
|
||||
var/timeleft = round((endtime - world.timeofday)/10 ,1)
|
||||
if(timeleft > (MIDNIGHT_ROLLOVER/10)) // midnight rollover protection
|
||||
endtime -= MIDNIGHT_ROLLOVER // subtract 24 hours from endtime
|
||||
timeleft = round((endtime - world.timeofday)/10 ,1) // recalculate timeleft
|
||||
if(direction == 1)
|
||||
var/timeleft = timeleft()
|
||||
if(timeleft >= SHUTTLEARRIVETIME)
|
||||
return timeleft
|
||||
else
|
||||
return SHUTTLEARRIVETIME-timeleft
|
||||
else
|
||||
return SHUTTLEARRIVETIME
|
||||
|
||||
// sets the time left to a given delay (in seconds)
|
||||
/datum/shuttle_controller/proc/settimeleft(var/delay)
|
||||
endtime = world.timeofday + delay * 10
|
||||
timelimit = delay
|
||||
|
||||
// sets the shuttle direction
|
||||
// 1 = towards SS13, -1 = back to centcom
|
||||
/datum/shuttle_controller/proc/setdirection(var/dirn)
|
||||
if(direction == dirn)
|
||||
return
|
||||
direction = dirn
|
||||
// if changing direction, flip the timeleft by SHUTTLEARRIVETIME
|
||||
var/ticksleft = endtime - world.timeofday
|
||||
endtime = world.timeofday + (SHUTTLEARRIVETIME*10 - ticksleft)
|
||||
return
|
||||
|
||||
//calls the shuttle if there's no live active AI or powered non broken comms console,
|
||||
/datum/shuttle_controller/proc/autoshuttlecall()
|
||||
var/callshuttle = 1
|
||||
|
||||
for(var/SC in shuttle_caller_list)
|
||||
if(istype(SC,/mob/living/silicon/ai))
|
||||
var/mob/living/silicon/ai/AI = SC
|
||||
if(AI.stat || !AI.client)
|
||||
continue
|
||||
if(istype(SC,/obj/machinery/computer/communications))
|
||||
var/obj/machinery/computer/communications/C = SC
|
||||
if(C.stat & BROKEN)
|
||||
continue
|
||||
var/turf/T = get_turf(SC)
|
||||
if(T && T.z == 1)
|
||||
callshuttle = 0 //if there's an alive AI or a powered non broken communication console on the station z level, we don't call the shuttle
|
||||
break
|
||||
|
||||
if(callshuttle)
|
||||
if(!online && direction == 1) //we don't call the shuttle if it's already coming
|
||||
incall(SHUTTLEAUTOCALLTIMER) //X minutes! If they want to recall, they have X-(X-5) minutes to do so
|
||||
log_game("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.")
|
||||
message_admins("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.", 1)
|
||||
priority_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.", null, 'sound/AI/shuttlecalled.ogg', "Priority")
|
||||
|
||||
/datum/shuttle_controller/proc/move_shuttles()
|
||||
var/datum/shuttle_manager/s
|
||||
for(var/t in pods)
|
||||
s = shuttles[t]
|
||||
s.move_shuttle()
|
||||
|
||||
/datum/shuttle_controller/proc/process()
|
||||
|
||||
/datum/shuttle_controller/emergency_shuttle/process()
|
||||
if(!online)
|
||||
return
|
||||
var/timeleft = timeleft()
|
||||
if(location == UNDOCKED)
|
||||
if(direction == -1)
|
||||
if(timeleft >= timelimit) // Shuttle reaches CentCom after being recalled.
|
||||
online = 0
|
||||
direction = 1
|
||||
endtime = null
|
||||
return
|
||||
|
||||
recall_count ++
|
||||
|
||||
if(recall_count > 2 && signal_origin && prob(60)) //40% chance the signal tracing will fail
|
||||
last_call_loc = signal_origin
|
||||
else
|
||||
last_call_loc = null
|
||||
|
||||
if(recall_count == 2)
|
||||
priority_announce("The emergency shuttle has been recalled.\n\nExcessive number of emergency shuttle calls detected. We will attempt to trace all future calls and recalls to their source. Tracing results can be viewed on any communications console.", null, 'sound/AI/shuttlerecalled.ogg')
|
||||
else
|
||||
priority_announce("The emergency shuttle has been recalled.", null, 'sound/AI/shuttlerecalled.ogg', "Priority")
|
||||
setdirection(-1)
|
||||
online = 1
|
||||
|
||||
|
||||
// returns the time (in seconds) before shuttle arrival
|
||||
// note if direction = -1, gives a count-up to SHUTTLEARRIVETIME
|
||||
proc/timeleft()
|
||||
if(online)
|
||||
var/timeleft = round((endtime - world.timeofday)/10 ,1)
|
||||
if(timeleft > (MIDNIGHT_ROLLOVER/10)) // midnight rollover protection
|
||||
endtime -= MIDNIGHT_ROLLOVER // subtract 24 hours from endtime
|
||||
timeleft = round((endtime - world.timeofday)/10 ,1) // recalculate timeleft
|
||||
if(direction == 1)
|
||||
return timeleft
|
||||
else
|
||||
return SHUTTLEARRIVETIME-timeleft
|
||||
else
|
||||
return SHUTTLEARRIVETIME
|
||||
|
||||
// sets the time left to a given delay (in seconds)
|
||||
proc/settimeleft(var/delay)
|
||||
endtime = world.timeofday + delay * 10
|
||||
timelimit = delay
|
||||
|
||||
// sets the shuttle direction
|
||||
// 1 = towards SS13, -1 = back to centcom
|
||||
proc/setdirection(var/dirn)
|
||||
if(direction == dirn)
|
||||
return
|
||||
direction = dirn
|
||||
// if changing direction, flip the timeleft by SHUTTLEARRIVETIME
|
||||
var/ticksleft = endtime - world.timeofday
|
||||
endtime = world.timeofday + (SHUTTLEARRIVETIME*10 - ticksleft)
|
||||
return
|
||||
|
||||
//calls the shuttle if there's no live active AI or powered non broken comms console,
|
||||
proc/autoshuttlecall()
|
||||
var/callshuttle = 1
|
||||
|
||||
for(var/SC in shuttle_caller_list)
|
||||
if(istype(SC,/mob/living/silicon/ai))
|
||||
var/mob/living/silicon/ai/AI = SC
|
||||
if(AI.stat || !AI.client)
|
||||
continue
|
||||
if(istype(SC,/obj/machinery/computer/communications))
|
||||
var/obj/machinery/computer/communications/C = SC
|
||||
if(C.stat & BROKEN)
|
||||
continue
|
||||
var/turf/T = get_turf(SC)
|
||||
if(T && T.z == 1)
|
||||
callshuttle = 0 //if there's an alive AI or a powered non broken communication console on the station z level, we don't call the shuttle
|
||||
break
|
||||
|
||||
if(callshuttle)
|
||||
if(!online && direction == 1) //we don't call the shuttle if it's already coming
|
||||
incall(SHUTTLEAUTOCALLTIMER) //X minutes! If they want to recall, they have X-(X-5) minutes to do so
|
||||
log_game("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.")
|
||||
message_admins("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.", 1)
|
||||
priority_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.", null, 'sound/AI/shuttlecalled.ogg', "Priority")
|
||||
|
||||
proc/move_shuttles()
|
||||
var/datum/shuttle_manager/s
|
||||
for(var/t in pods)
|
||||
s = shuttles[t]
|
||||
s.move_shuttle()
|
||||
|
||||
proc/process()
|
||||
|
||||
emergency_shuttle
|
||||
process()
|
||||
if(!online)
|
||||
return
|
||||
var/timeleft = timeleft()
|
||||
if(location == UNDOCKED)
|
||||
if(direction == -1)
|
||||
if(timeleft >= timelimit) // Shuttle reaches CentCom after being recalled.
|
||||
online = 0
|
||||
direction = 1
|
||||
endtime = null
|
||||
return 0
|
||||
else if(fake_recall && (timeleft <= fake_recall))
|
||||
recall()
|
||||
fake_recall = 0
|
||||
return 0
|
||||
else if(timeleft <= 0)
|
||||
var/datum/shuttle_manager/s = shuttles["escape"]
|
||||
s.move_shuttle()
|
||||
location = DOCKED
|
||||
settimeleft(SHUTTLELEAVETIME)
|
||||
send2irc("Server", "The Emergency Shuttle has docked with the station.")
|
||||
priority_announce("The Emergency Shuttle has docked with the station. You have [round(timeleft()/60,1)] minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg', "Priority")
|
||||
else if(timeleft <= 0) //Nothing happens if time's not up and the ship's docked or later
|
||||
if(location == DOCKED)
|
||||
move_shuttles()
|
||||
location = TRANSIT
|
||||
settimeleft(SHUTTLETRANSITTIME)
|
||||
priority_announce("The Emergency Shuttle has left the station. Estimate [round(timeleft()/60,1)] minutes until the shuttle docks at Central Command.", null, null, "Priority")
|
||||
else if(location == TRANSIT)
|
||||
move_shuttles()
|
||||
//message_admins("Shuttles have attempted to move to Centcom")
|
||||
location = ENDGAME
|
||||
online = 0
|
||||
endtime = null
|
||||
return 1
|
||||
return 0
|
||||
else if(fake_recall && (timeleft <= fake_recall))
|
||||
recall()
|
||||
fake_recall = 0
|
||||
return 0
|
||||
else if(timeleft <= 0)
|
||||
var/datum/shuttle_manager/s = shuttles["escape"]
|
||||
s.move_shuttle()
|
||||
location = DOCKED
|
||||
settimeleft(SHUTTLELEAVETIME)
|
||||
send2irc("Server", "The Emergency Shuttle has docked with the station.")
|
||||
priority_announce("The Emergency Shuttle has docked with the station. You have [round(timeleft()/60,1)] minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg', "Priority")
|
||||
else if(timeleft <= 0) //Nothing happens if time's not up and the ship's docked or later
|
||||
if(location == DOCKED)
|
||||
move_shuttles()
|
||||
location = TRANSIT
|
||||
settimeleft(SHUTTLETRANSITTIME)
|
||||
priority_announce("The Emergency Shuttle has left the station. Estimate [round(timeleft()/60,1)] minutes until the shuttle docks at Central Command.", null, null, "Priority")
|
||||
else if(location == TRANSIT)
|
||||
move_shuttles()
|
||||
//message_admins("Shuttles have attempted to move to Centcom")
|
||||
location = ENDGAME
|
||||
online = 0
|
||||
endtime = null
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/*
|
||||
Some slapped-together star effects for maximum spess immershuns. Basically consists of a
|
||||
@@ -194,23 +193,23 @@ datum/shuttle_controller
|
||||
var/direction = SOUTH
|
||||
layer = 2 // TURF_LAYER
|
||||
|
||||
New()
|
||||
..()
|
||||
pixel_x += rand(-2,30)
|
||||
pixel_y += rand(-2,30)
|
||||
var/starnum = pick("1", "1", "1", "2", "3", "4")
|
||||
/obj/effect/bgstar/New()
|
||||
..()
|
||||
pixel_x += rand(-2,30)
|
||||
pixel_y += rand(-2,30)
|
||||
var/starnum = pick("1", "1", "1", "2", "3", "4")
|
||||
|
||||
icon_state = "star"+starnum
|
||||
icon_state = "star"+starnum
|
||||
|
||||
speed = rand(2, 5)
|
||||
speed = rand(2, 5)
|
||||
|
||||
proc/startmove()
|
||||
/obj/effect/bgstar/proc/startmove()
|
||||
|
||||
while(src)
|
||||
sleep(speed)
|
||||
step(src, direction)
|
||||
for(var/obj/effect/starender/E in loc)
|
||||
qdel(src)
|
||||
while(src)
|
||||
sleep(speed)
|
||||
step(src, direction)
|
||||
for(var/obj/effect/starender/E in loc)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/effect/starender
|
||||
@@ -221,17 +220,17 @@ datum/shuttle_controller
|
||||
var/spawndir = SOUTH
|
||||
var/spawning = 0
|
||||
|
||||
West
|
||||
spawndir = WEST
|
||||
/obj/effect/starspawner/West
|
||||
spawndir = WEST
|
||||
|
||||
proc/startspawn()
|
||||
spawning = 1
|
||||
while(spawning)
|
||||
sleep(rand(2, 30))
|
||||
var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z))
|
||||
S.direction = spawndir
|
||||
spawn()
|
||||
S.startmove()
|
||||
/obj/effect/starspawner/proc/startspawn()
|
||||
spawning = 1
|
||||
while(spawning)
|
||||
sleep(rand(2, 30))
|
||||
var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z))
|
||||
S.direction = spawndir
|
||||
spawn()
|
||||
S.startmove()
|
||||
|
||||
|
||||
/proc/push_mob_back(var/mob/living/L, var/dir)
|
||||
|
||||
+225
-225
@@ -61,18 +61,18 @@ var/global/datum/controller/supply_shuttle/supply_shuttle
|
||||
name = "airtight plastic flaps"
|
||||
desc = "Heavy duty, airtight, plastic flaps."
|
||||
|
||||
New() //set the turf below the flaps to block air
|
||||
var/turf/T = get_turf(loc)
|
||||
if(T)
|
||||
T.blocks_air = 1
|
||||
..()
|
||||
/obj/structure/plasticflaps/mining/New() //set the turf below the flaps to block air
|
||||
var/turf/T = get_turf(loc)
|
||||
if(T)
|
||||
T.blocks_air = 1
|
||||
..()
|
||||
|
||||
Destroy() //lazy hack to set the turf to allow air to pass if it's a simulated floor //wow this is terrible
|
||||
var/turf/T = get_turf(loc)
|
||||
if(T)
|
||||
if(istype(T, /turf/simulated/floor))
|
||||
T.blocks_air = 0
|
||||
..()
|
||||
/obj/structure/plasticflaps/mining/Destroy() //lazy hack to set the turf to allow air to pass if it's a simulated floor //wow this is terrible
|
||||
var/turf/T = get_turf(loc)
|
||||
if(T)
|
||||
if(istype(T, /turf/simulated/floor))
|
||||
T.blocks_air = 0
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/supplycomp
|
||||
name = "supply shuttle console"
|
||||
@@ -140,269 +140,269 @@ var/global/datum/controller/supply_shuttle/supply_shuttle
|
||||
//shuttle loan
|
||||
var/datum/round_event/shuttle_loan/shuttle_loan
|
||||
|
||||
New()
|
||||
ordernum = rand(1,9000)
|
||||
for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs))
|
||||
var/datum/supply_packs/P = new typepath()
|
||||
if(P.name == "HEADER") continue // To filter out group headers
|
||||
supply_packs[P.name] = P
|
||||
/datum/controller/supply_shuttle/New()
|
||||
ordernum = rand(1,9000)
|
||||
for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs))
|
||||
var/datum/supply_packs/P = new typepath()
|
||||
if(P.name == "HEADER") continue // To filter out group headers
|
||||
supply_packs[P.name] = P
|
||||
|
||||
//Supply shuttle ticker - handles supply point regenertion and shuttle travelling between centcom and the station
|
||||
proc/process()
|
||||
//Supply shuttle ticker - handles supply point regenertion and shuttle travelling between centcom and the station
|
||||
/datum/controller/supply_shuttle/proc/process()
|
||||
|
||||
spawn(0)
|
||||
set background = BACKGROUND_ENABLED
|
||||
while(1)
|
||||
if(processing)
|
||||
iteration++
|
||||
points += points_per_process
|
||||
spawn(0)
|
||||
set background = BACKGROUND_ENABLED
|
||||
while(1)
|
||||
if(processing)
|
||||
iteration++
|
||||
points += points_per_process
|
||||
|
||||
if(moving == 1)
|
||||
var/ticksleft = (eta_timeofday - world.timeofday)
|
||||
if(ticksleft > 0)
|
||||
eta = round(ticksleft/600,1)
|
||||
else
|
||||
eta = 0
|
||||
send()
|
||||
if(moving == 1)
|
||||
var/ticksleft = (eta_timeofday - world.timeofday)
|
||||
if(ticksleft > 0)
|
||||
eta = round(ticksleft/600,1)
|
||||
else
|
||||
eta = 0
|
||||
send()
|
||||
|
||||
|
||||
sleep(processing_interval)
|
||||
sleep(processing_interval)
|
||||
|
||||
proc/send()
|
||||
var/area/from
|
||||
var/area/dest
|
||||
switch(at_station)
|
||||
if(1)
|
||||
from = locate(SUPPLY_STATION_AREATYPE)
|
||||
dest = locate(SUPPLY_DOCK_AREATYPE)
|
||||
at_station = 0
|
||||
if(0)
|
||||
from = locate(SUPPLY_DOCK_AREATYPE)
|
||||
dest = locate(SUPPLY_STATION_AREATYPE)
|
||||
at_station = 1
|
||||
dest.clear_docking_area()
|
||||
moving = 0
|
||||
/datum/controller/supply_shuttle/proc/send()
|
||||
var/area/from
|
||||
var/area/dest
|
||||
switch(at_station)
|
||||
if(1)
|
||||
from = locate(SUPPLY_STATION_AREATYPE)
|
||||
dest = locate(SUPPLY_DOCK_AREATYPE)
|
||||
at_station = 0
|
||||
if(0)
|
||||
from = locate(SUPPLY_DOCK_AREATYPE)
|
||||
dest = locate(SUPPLY_STATION_AREATYPE)
|
||||
at_station = 1
|
||||
dest.clear_docking_area()
|
||||
moving = 0
|
||||
|
||||
from.move_contents_to(dest)
|
||||
from.move_contents_to(dest)
|
||||
|
||||
//Check whether the shuttle is allowed to move
|
||||
proc/can_move()
|
||||
if(moving) return 0
|
||||
//Check whether the shuttle is allowed to move
|
||||
/datum/controller/supply_shuttle/proc/can_move()
|
||||
if(moving) return 0
|
||||
|
||||
var/area/shuttle = locate(/area/supply/station)
|
||||
if(!shuttle) return 0
|
||||
var/area/shuttle = locate(/area/supply/station)
|
||||
if(!shuttle) return 0
|
||||
|
||||
if(forbidden_atoms_check(shuttle))
|
||||
return 0
|
||||
if(forbidden_atoms_check(shuttle))
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
//To stop things being sent to centcom which should not be sent to centcom Recursively checks for these types.
|
||||
/datum/controller/supply_shuttle/proc/forbidden_atoms_check(atom/A)
|
||||
if(istype(A,/mob/living))
|
||||
return 1
|
||||
if(istype(A,/obj/item/weapon/disk/nuclear))
|
||||
return 1
|
||||
if(istype(A,/obj/machinery/nuclearbomb))
|
||||
return 1
|
||||
if(istype(A,/obj/item/device/radio/beacon))
|
||||
return 1
|
||||
if(istype(A,/obj/effect/blob))
|
||||
return 1
|
||||
if(istype(A,/obj/effect/spider/spiderling))
|
||||
return 1
|
||||
|
||||
//To stop things being sent to centcom which should not be sent to centcom Recursively checks for these types.
|
||||
proc/forbidden_atoms_check(atom/A)
|
||||
if(istype(A,/mob/living))
|
||||
return 1
|
||||
if(istype(A,/obj/item/weapon/disk/nuclear))
|
||||
return 1
|
||||
if(istype(A,/obj/machinery/nuclearbomb))
|
||||
return 1
|
||||
if(istype(A,/obj/item/device/radio/beacon))
|
||||
return 1
|
||||
if(istype(A,/obj/effect/blob))
|
||||
return 1
|
||||
if(istype(A,/obj/effect/spider/spiderling))
|
||||
for(var/i=1, i<=A.contents.len, i++)
|
||||
var/atom/B = A.contents[i]
|
||||
if(.(B))
|
||||
return 1
|
||||
|
||||
for(var/i=1, i<=A.contents.len, i++)
|
||||
var/atom/B = A.contents[i]
|
||||
if(.(B))
|
||||
return 1
|
||||
//Sellin
|
||||
/datum/controller/supply_shuttle/proc/sell()
|
||||
var/shuttle_at
|
||||
if(at_station) shuttle_at = SUPPLY_STATION_AREATYPE
|
||||
else shuttle_at = SUPPLY_DOCK_AREATYPE
|
||||
|
||||
//Sellin
|
||||
proc/sell()
|
||||
var/shuttle_at
|
||||
if(at_station) shuttle_at = SUPPLY_STATION_AREATYPE
|
||||
else shuttle_at = SUPPLY_DOCK_AREATYPE
|
||||
var/area/shuttle = locate(shuttle_at)
|
||||
if(!shuttle) return
|
||||
|
||||
var/area/shuttle = locate(shuttle_at)
|
||||
if(!shuttle) return
|
||||
var/plasma_count = 0
|
||||
var/intel_count = 0
|
||||
var/crate_count = 0
|
||||
|
||||
var/plasma_count = 0
|
||||
var/intel_count = 0
|
||||
var/crate_count = 0
|
||||
centcom_message = ""
|
||||
|
||||
centcom_message = ""
|
||||
|
||||
for(var/atom/movable/MA in shuttle)
|
||||
if(MA.anchored) continue
|
||||
for(var/atom/movable/MA in shuttle)
|
||||
if(MA.anchored) continue
|
||||
|
||||
|
||||
// Must be in a crate (or a critter crate)!
|
||||
if(istype(MA,/obj/structure/closet/crate) || istype(MA,/obj/structure/closet/critter))
|
||||
crate_count++
|
||||
var/find_slip = 1
|
||||
// Must be in a crate (or a critter crate)!
|
||||
if(istype(MA,/obj/structure/closet/crate) || istype(MA,/obj/structure/closet/critter))
|
||||
crate_count++
|
||||
var/find_slip = 1
|
||||
|
||||
for(var/atom in MA)
|
||||
// Sell manifests
|
||||
var/atom/A = atom
|
||||
if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
|
||||
var/obj/item/weapon/paper/manifest/slip = A
|
||||
// TODO: Check for a signature, too.
|
||||
if(slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
|
||||
// Did they mark it as erroneous?
|
||||
var/denied = 0
|
||||
for(var/i=1,i<=slip.stamped.len,i++)
|
||||
if(slip.stamped[i] == /obj/item/weapon/stamp/denied)
|
||||
denied = 1
|
||||
if(slip.erroneous && denied) // Caught a mistake by Centcom (IDEA: maybe Centcom rarely gets offended by this)
|
||||
points += slip.points-points_per_crate // For now, give a full refund for paying attention (minus the crate cost)
|
||||
centcom_message += "<font color=green>+[slip.points-points_per_crate]</font>: Station correctly denied package [slip.ordernumber]: "
|
||||
for(var/atom in MA)
|
||||
// Sell manifests
|
||||
var/atom/A = atom
|
||||
if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
|
||||
var/obj/item/weapon/paper/manifest/slip = A
|
||||
// TODO: Check for a signature, too.
|
||||
if(slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
|
||||
// Did they mark it as erroneous?
|
||||
var/denied = 0
|
||||
for(var/i=1,i<=slip.stamped.len,i++)
|
||||
if(slip.stamped[i] == /obj/item/weapon/stamp/denied)
|
||||
denied = 1
|
||||
if(slip.erroneous && denied) // Caught a mistake by Centcom (IDEA: maybe Centcom rarely gets offended by this)
|
||||
points += slip.points-points_per_crate // For now, give a full refund for paying attention (minus the crate cost)
|
||||
centcom_message += "<font color=green>+[slip.points-points_per_crate]</font>: Station correctly denied package [slip.ordernumber]: "
|
||||
if(slip.erroneous & MANIFEST_ERROR_NAME)
|
||||
centcom_message += "Destination station incorrect. "
|
||||
else if(slip.erroneous & MANIFEST_ERROR_COUNT)
|
||||
centcom_message += "Packages incorrectly counted. "
|
||||
else if(slip.erroneous & MANIFEST_ERROR_ITEM)
|
||||
centcom_message += "Package incomplete. "
|
||||
centcom_message += "Points refunded.<BR>"
|
||||
else if(!slip.erroneous && !denied) // Approving a proper order awards the relatively tiny points_per_slip
|
||||
points += points_per_slip
|
||||
centcom_message += "<font color=green>+1</font>: Package [slip.ordernumber] accorded.<BR>"
|
||||
else // You done goofed.
|
||||
if(slip.erroneous)
|
||||
centcom_message += "<font color=red>+0</font>: Station approved package [slip.ordernumber] despite error: "
|
||||
if(slip.erroneous & MANIFEST_ERROR_NAME)
|
||||
centcom_message += "Destination station incorrect. "
|
||||
centcom_message += "Destination station incorrect."
|
||||
else if(slip.erroneous & MANIFEST_ERROR_COUNT)
|
||||
centcom_message += "Packages incorrectly counted. "
|
||||
centcom_message += "Packages incorrectly counted."
|
||||
else if(slip.erroneous & MANIFEST_ERROR_ITEM)
|
||||
centcom_message += "Package incomplete. "
|
||||
centcom_message += "Points refunded.<BR>"
|
||||
else if(!slip.erroneous && !denied) // Approving a proper order awards the relatively tiny points_per_slip
|
||||
points += points_per_slip
|
||||
centcom_message += "<font color=green>+1</font>: Package [slip.ordernumber] accorded.<BR>"
|
||||
else // You done goofed.
|
||||
if(slip.erroneous)
|
||||
centcom_message += "<font color=red>+0</font>: Station approved package [slip.ordernumber] despite error: "
|
||||
if(slip.erroneous & MANIFEST_ERROR_NAME)
|
||||
centcom_message += "Destination station incorrect."
|
||||
else if(slip.erroneous & MANIFEST_ERROR_COUNT)
|
||||
centcom_message += "Packages incorrectly counted."
|
||||
else if(slip.erroneous & MANIFEST_ERROR_ITEM)
|
||||
centcom_message += "We found unshipped items on our dock."
|
||||
centcom_message += " Be more vigilant.<BR>"
|
||||
else
|
||||
points -= slip.points-points_per_crate
|
||||
centcom_message += "<font color=red>-[slip.points-points_per_crate]</font>: Station denied package [slip.ordernumber]. Our records show no fault on our part.<BR>"
|
||||
find_slip = 0
|
||||
continue
|
||||
centcom_message += "We found unshipped items on our dock."
|
||||
centcom_message += " Be more vigilant.<BR>"
|
||||
else
|
||||
points -= slip.points-points_per_crate
|
||||
centcom_message += "<font color=red>-[slip.points-points_per_crate]</font>: Station denied package [slip.ordernumber]. Our records show no fault on our part.<BR>"
|
||||
find_slip = 0
|
||||
continue
|
||||
|
||||
// Sell plasma
|
||||
if(istype(A, /obj/item/stack/sheet/mineral/plasma))
|
||||
var/obj/item/stack/sheet/mineral/plasma/P = A
|
||||
plasma_count += P.amount
|
||||
// Sell plasma
|
||||
if(istype(A, /obj/item/stack/sheet/mineral/plasma))
|
||||
var/obj/item/stack/sheet/mineral/plasma/P = A
|
||||
plasma_count += P.amount
|
||||
|
||||
// Sell syndicate intel
|
||||
if(istype(A, /obj/item/documents/syndicate))
|
||||
intel_count += 1
|
||||
// Sell syndicate intel
|
||||
if(istype(A, /obj/item/documents/syndicate))
|
||||
intel_count += 1
|
||||
|
||||
if(istype(A, /obj/item/seeds))
|
||||
var/obj/item/seeds/S = A
|
||||
if(S.rarity == 0) // Mundane species
|
||||
centcom_message += "<font color=red>+0</font>: We don't need samples of mundane species \"[capitalize(S.species)]\".<BR>"
|
||||
else if(discoveredPlants[S.type]) // This species has already been sent to CentComm
|
||||
var/potDiff = S.potency - discoveredPlants[S.type] // Compare it to the previous best
|
||||
if(potDiff > 0) // This sample is better
|
||||
discoveredPlants[S.type] = S.potency
|
||||
centcom_message += "<font color=green>+[potDiff]</font>: New sample of \"[capitalize(S.species)]\" is superior. Good work.<BR>"
|
||||
points += potDiff
|
||||
else // This sample is worthless
|
||||
centcom_message += "<font color=red>+0</font>: New sample of \"[capitalize(S.species)]\" is not more potent than existing sample ([discoveredPlants[S.type]] potency).<BR>"
|
||||
else // This is a new discovery!
|
||||
if(istype(A, /obj/item/seeds))
|
||||
var/obj/item/seeds/S = A
|
||||
if(S.rarity == 0) // Mundane species
|
||||
centcom_message += "<font color=red>+0</font>: We don't need samples of mundane species \"[capitalize(S.species)]\".<BR>"
|
||||
else if(discoveredPlants[S.type]) // This species has already been sent to CentComm
|
||||
var/potDiff = S.potency - discoveredPlants[S.type] // Compare it to the previous best
|
||||
if(potDiff > 0) // This sample is better
|
||||
discoveredPlants[S.type] = S.potency
|
||||
centcom_message += "<font color=green>+[S.rarity]</font>: New species discovered: \"[capitalize(S.species)]\". Excellent work.<BR>"
|
||||
points += S.rarity // That's right, no bonus for potency. Send a crappy sample first to "show improvement" later
|
||||
qdel(MA)
|
||||
centcom_message += "<font color=green>+[potDiff]</font>: New sample of \"[capitalize(S.species)]\" is superior. Good work.<BR>"
|
||||
points += potDiff
|
||||
else // This sample is worthless
|
||||
centcom_message += "<font color=red>+0</font>: New sample of \"[capitalize(S.species)]\" is not more potent than existing sample ([discoveredPlants[S.type]] potency).<BR>"
|
||||
else // This is a new discovery!
|
||||
discoveredPlants[S.type] = S.potency
|
||||
centcom_message += "<font color=green>+[S.rarity]</font>: New species discovered: \"[capitalize(S.species)]\". Excellent work.<BR>"
|
||||
points += S.rarity // That's right, no bonus for potency. Send a crappy sample first to "show improvement" later
|
||||
qdel(MA)
|
||||
|
||||
if(plasma_count)
|
||||
centcom_message += "<font color=green>+[round(plasma_count/plasma_per_point)]</font>: Received [plasma_count] unit(s) of exotic material.<BR>"
|
||||
points += round(plasma_count / plasma_per_point)
|
||||
if(plasma_count)
|
||||
centcom_message += "<font color=green>+[round(plasma_count/plasma_per_point)]</font>: Received [plasma_count] unit(s) of exotic material.<BR>"
|
||||
points += round(plasma_count / plasma_per_point)
|
||||
|
||||
if(intel_count)
|
||||
centcom_message += "<font color=green>+[round(intel_count*points_per_intel)]</font>: Received [intel_count] article(s) of enemy intelligence.<BR>"
|
||||
points += round(intel_count*points_per_intel)
|
||||
if(intel_count)
|
||||
centcom_message += "<font color=green>+[round(intel_count*points_per_intel)]</font>: Received [intel_count] article(s) of enemy intelligence.<BR>"
|
||||
points += round(intel_count*points_per_intel)
|
||||
|
||||
if(crate_count)
|
||||
centcom_message += "<font color=green>+[round(crate_count*points_per_crate)]</font>: Received [crate_count] crate(s).<BR>"
|
||||
points += crate_count * points_per_crate
|
||||
if(crate_count)
|
||||
centcom_message += "<font color=green>+[round(crate_count*points_per_crate)]</font>: Received [crate_count] crate(s).<BR>"
|
||||
points += crate_count * points_per_crate
|
||||
|
||||
//Buyin
|
||||
proc/buy()
|
||||
if(!shoppinglist.len) return
|
||||
//Buyin
|
||||
/datum/controller/supply_shuttle/proc/buy()
|
||||
if(!shoppinglist.len) return
|
||||
|
||||
var/shuttle_at
|
||||
if(at_station) shuttle_at = SUPPLY_STATION_AREATYPE
|
||||
else shuttle_at = SUPPLY_DOCK_AREATYPE
|
||||
var/shuttle_at
|
||||
if(at_station) shuttle_at = SUPPLY_STATION_AREATYPE
|
||||
else shuttle_at = SUPPLY_DOCK_AREATYPE
|
||||
|
||||
var/area/shuttle = locate(shuttle_at)
|
||||
if(!shuttle) return
|
||||
var/area/shuttle = locate(shuttle_at)
|
||||
if(!shuttle) return
|
||||
|
||||
var/list/clear_turfs = list()
|
||||
var/list/clear_turfs = list()
|
||||
|
||||
for(var/turf/T in shuttle)
|
||||
if(T.density || T.contents.len) continue
|
||||
clear_turfs += T
|
||||
for(var/turf/T in shuttle)
|
||||
if(T.density || T.contents.len) continue
|
||||
clear_turfs += T
|
||||
|
||||
for(var/S in shoppinglist)
|
||||
if(!clear_turfs.len) break
|
||||
var/i = rand(1,clear_turfs.len)
|
||||
var/turf/pickedloc = clear_turfs[i]
|
||||
clear_turfs.Cut(i,i+1)
|
||||
for(var/S in shoppinglist)
|
||||
if(!clear_turfs.len) break
|
||||
var/i = rand(1,clear_turfs.len)
|
||||
var/turf/pickedloc = clear_turfs[i]
|
||||
clear_turfs.Cut(i,i+1)
|
||||
|
||||
var/datum/supply_order/SO = S
|
||||
var/datum/supply_packs/SP = SO.object
|
||||
var/datum/supply_order/SO = S
|
||||
var/datum/supply_packs/SP = SO.object
|
||||
|
||||
var/atom/A = new SP.containertype(pickedloc)
|
||||
A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]"
|
||||
var/atom/A = new SP.containertype(pickedloc)
|
||||
A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]"
|
||||
|
||||
//supply manifest generation begin
|
||||
//supply manifest generation begin
|
||||
|
||||
var/obj/item/weapon/paper/manifest/slip = new /obj/item/weapon/paper/manifest(A)
|
||||
var/obj/item/weapon/paper/manifest/slip = new /obj/item/weapon/paper/manifest(A)
|
||||
|
||||
var printed_station_name = world.name // World name is available in the title bar, station_name can be different based on config.
|
||||
if(prob(5))
|
||||
printed_station_name = new_station_name()
|
||||
slip.erroneous |= MANIFEST_ERROR_NAME // They got our station name wrong. BASTARDS!
|
||||
// IDEA: Have Centcom accidentally send random low-value crates in large orders, give large bonus for returning them intact.
|
||||
var printed_packages_amount = supply_shuttle.shoppinglist.len
|
||||
if(prob(5))
|
||||
printed_packages_amount += rand(1,2) // I considered rand(-2,2), but that could be zero. Heh.
|
||||
slip.erroneous |= MANIFEST_ERROR_COUNT // They typoed the number of crates in this shipment. It won't match the other manifests.
|
||||
var printed_station_name = world.name // World name is available in the title bar, station_name can be different based on config.
|
||||
if(prob(5))
|
||||
printed_station_name = new_station_name()
|
||||
slip.erroneous |= MANIFEST_ERROR_NAME // They got our station name wrong. BASTARDS!
|
||||
// IDEA: Have Centcom accidentally send random low-value crates in large orders, give large bonus for returning them intact.
|
||||
var printed_packages_amount = supply_shuttle.shoppinglist.len
|
||||
if(prob(5))
|
||||
printed_packages_amount += rand(1,2) // I considered rand(-2,2), but that could be zero. Heh.
|
||||
slip.erroneous |= MANIFEST_ERROR_COUNT // They typoed the number of crates in this shipment. It won't match the other manifests.
|
||||
|
||||
slip.points = SP.cost
|
||||
slip.ordernumber = SO.ordernum
|
||||
slip.info = "<h3>[command_name()] Shipping Manifest</h3><hr><br>"
|
||||
slip.info +="Order #[SO.ordernum]<br>"
|
||||
slip.info +="Destination: [printed_station_name]<br>"
|
||||
slip.info +="[printed_packages_amount] PACKAGES IN THIS SHIPMENT<br>"
|
||||
slip.info +="CONTENTS:<br><ul>"
|
||||
slip.points = SP.cost
|
||||
slip.ordernumber = SO.ordernum
|
||||
slip.info = "<h3>[command_name()] Shipping Manifest</h3><hr><br>"
|
||||
slip.info +="Order #[SO.ordernum]<br>"
|
||||
slip.info +="Destination: [printed_station_name]<br>"
|
||||
slip.info +="[printed_packages_amount] PACKAGES IN THIS SHIPMENT<br>"
|
||||
slip.info +="CONTENTS:<br><ul>"
|
||||
|
||||
//spawn the stuff, finish generating the manifest while you're at it
|
||||
if(SP.access)
|
||||
A:req_access = list()
|
||||
A:req_access += text2num(SP.access)
|
||||
//spawn the stuff, finish generating the manifest while you're at it
|
||||
if(SP.access)
|
||||
A:req_access = list()
|
||||
A:req_access += text2num(SP.access)
|
||||
|
||||
var/list/contains
|
||||
if(istype(SP,/datum/supply_packs/misc/randomised))
|
||||
var/datum/supply_packs/misc/randomised/SPR = SP
|
||||
contains = list()
|
||||
if(SPR.contains.len)
|
||||
for(var/j=1,j<=SPR.num_contained,j++)
|
||||
contains += pick(SPR.contains)
|
||||
else
|
||||
contains = SP.contains
|
||||
var/list/contains
|
||||
if(istype(SP,/datum/supply_packs/misc/randomised))
|
||||
var/datum/supply_packs/misc/randomised/SPR = SP
|
||||
contains = list()
|
||||
if(SPR.contains.len)
|
||||
for(var/j=1,j<=SPR.num_contained,j++)
|
||||
contains += pick(SPR.contains)
|
||||
else
|
||||
contains = SP.contains
|
||||
|
||||
for(var/typepath in contains)
|
||||
if(!typepath) continue
|
||||
var/atom/B2 = new typepath(A)
|
||||
if(SP.amount && B2:amount) B2:amount = SP.amount
|
||||
slip.info += "<li>[B2.name]</li>" //add the item to the manifest (even if it was misplaced)
|
||||
// If it has multiple items, there's a 1% of each going missing... Not for secure crates or those large wooden ones, though.
|
||||
if(contains.len > 1 && prob(1) && !findtext(SP.containertype,"/secure/") && !findtext(SP.containertype,"/largecrate/"))
|
||||
slip.erroneous |= MANIFEST_ERROR_ITEM // This item was not included in the shipment!
|
||||
qdel(B2) // Lost in space... or the loading dock.
|
||||
for(var/typepath in contains)
|
||||
if(!typepath) continue
|
||||
var/atom/B2 = new typepath(A)
|
||||
if(SP.amount && B2:amount) B2:amount = SP.amount
|
||||
slip.info += "<li>[B2.name]</li>" //add the item to the manifest (even if it was misplaced)
|
||||
// If it has multiple items, there's a 1% of each going missing... Not for secure crates or those large wooden ones, though.
|
||||
if(contains.len > 1 && prob(1) && !findtext(SP.containertype,"/secure/") && !findtext(SP.containertype,"/largecrate/"))
|
||||
slip.erroneous |= MANIFEST_ERROR_ITEM // This item was not included in the shipment!
|
||||
qdel(B2) // Lost in space... or the loading dock.
|
||||
|
||||
//manifest finalisation
|
||||
slip.info += "</ul><br>"
|
||||
slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS<hr>" // And now this is actually meaningful.
|
||||
//manifest finalisation
|
||||
slip.info += "</ul><br>"
|
||||
slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS<hr>" // And now this is actually meaningful.
|
||||
|
||||
supply_shuttle.shoppinglist.Cut()
|
||||
return
|
||||
supply_shuttle.shoppinglist.Cut()
|
||||
return
|
||||
|
||||
/obj/item/weapon/paper/manifest
|
||||
name = "supply manifest"
|
||||
|
||||
+239
-239
@@ -1,6 +1,6 @@
|
||||
var/datum/controller/vote/vote = new()
|
||||
|
||||
datum/controller/vote
|
||||
/datum/controller/vote
|
||||
var/initiator = null
|
||||
var/started_timeofday = null
|
||||
var/time_remaining = 0
|
||||
@@ -10,253 +10,253 @@ datum/controller/vote
|
||||
var/list/voted = list()
|
||||
var/list/voting = list()
|
||||
|
||||
New()
|
||||
if(vote != src)
|
||||
if(istype(vote))
|
||||
del(vote)
|
||||
vote = src
|
||||
/datum/controller/vote/New()
|
||||
if(vote != src)
|
||||
if(istype(vote))
|
||||
del(vote)
|
||||
vote = src
|
||||
|
||||
proc/process() //called by master_controller
|
||||
if(mode)
|
||||
time_remaining = started_timeofday + config.vote_period
|
||||
if(world.timeofday < started_timeofday)
|
||||
time_remaining -= 864000
|
||||
time_remaining = round((time_remaining - world.timeofday)/10)
|
||||
|
||||
var/i=1
|
||||
if(time_remaining < 0)
|
||||
result()
|
||||
while(i<=voting.len)
|
||||
var/client/C = voting[i]
|
||||
if(C)
|
||||
C << browse(null,"window=vote;can_close=0")
|
||||
i++
|
||||
reset()
|
||||
else
|
||||
var/datum/browser/client_popup
|
||||
while(i<=voting.len)
|
||||
var/client/C = voting[i]
|
||||
if(C)
|
||||
//C << browse(vote.interface(C),"window=vote;can_close=0")
|
||||
client_popup = new(C, "vote", "Voting Panel")
|
||||
client_popup.set_window_options("can_close=0")
|
||||
client_popup.set_content(vote.interface(C))
|
||||
client_popup.open(0)
|
||||
|
||||
i++
|
||||
else
|
||||
voting.Cut(i,i+1)
|
||||
|
||||
proc/reset()
|
||||
initiator = null
|
||||
time_remaining = 0
|
||||
mode = null
|
||||
question = null
|
||||
choices.Cut()
|
||||
voted.Cut()
|
||||
voting.Cut()
|
||||
|
||||
proc/get_result()
|
||||
//get the highest number of votes
|
||||
var/greatest_votes = 0
|
||||
var/total_votes = 0
|
||||
for(var/option in choices)
|
||||
var/votes = choices[option]
|
||||
total_votes += votes
|
||||
if(votes > greatest_votes)
|
||||
greatest_votes = votes
|
||||
//default-vote for everyone who didn't vote
|
||||
if(!config.vote_no_default && choices.len)
|
||||
var/non_voters = (clients.len - total_votes)
|
||||
if(non_voters > 0)
|
||||
if(mode == "restart")
|
||||
choices["Continue Playing"] += non_voters
|
||||
if(choices["Continue Playing"] >= greatest_votes)
|
||||
greatest_votes = choices["Continue Playing"]
|
||||
else if(mode == "gamemode")
|
||||
if(master_mode in choices)
|
||||
choices[master_mode] += non_voters
|
||||
if(choices[master_mode] >= greatest_votes)
|
||||
greatest_votes = choices[master_mode]
|
||||
//get all options with that many votes and return them in a list
|
||||
. = list()
|
||||
if(greatest_votes)
|
||||
for(var/option in choices)
|
||||
if(choices[option] == greatest_votes)
|
||||
. += option
|
||||
return .
|
||||
|
||||
proc/announce_result()
|
||||
var/list/winners = get_result()
|
||||
var/text
|
||||
if(winners.len > 0)
|
||||
if(question) text += "<b>[question]</b>"
|
||||
else text += "<b>[capitalize(mode)] Vote</b>"
|
||||
for(var/i=1,i<=choices.len,i++)
|
||||
var/votes = choices[choices[i]]
|
||||
if(!votes) votes = 0
|
||||
text += "\n<b>[choices[i]]:</b> [votes]"
|
||||
if(mode != "custom")
|
||||
if(winners.len > 1)
|
||||
text = "\n<b>Vote Tied Between:</b>"
|
||||
for(var/option in winners)
|
||||
text += "\n\t[option]"
|
||||
. = pick(winners)
|
||||
text += "\n<b>Vote Result: [.]</b>"
|
||||
else
|
||||
text += "\n<b>Did not vote:</b> [clients.len-voted.len]"
|
||||
else
|
||||
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
|
||||
log_vote(text)
|
||||
world << "\n<font color='purple'>[text]</font>"
|
||||
return .
|
||||
|
||||
proc/result()
|
||||
. = announce_result()
|
||||
var/restart = 0
|
||||
if(.)
|
||||
switch(mode)
|
||||
if("restart")
|
||||
if(. == "Restart Round")
|
||||
restart = 1
|
||||
if("gamemode")
|
||||
if(master_mode != .)
|
||||
world.save_mode(.)
|
||||
if(ticker && ticker.mode)
|
||||
restart = 1
|
||||
else
|
||||
master_mode = .
|
||||
|
||||
if(restart)
|
||||
world << "World restarting due to vote..."
|
||||
feedback_set_details("end_error","restart vote")
|
||||
if(blackbox) blackbox.save_all_data_to_sql()
|
||||
sleep(50)
|
||||
log_game("Rebooting due to restart vote")
|
||||
world.Reboot()
|
||||
|
||||
return .
|
||||
|
||||
proc/submit_vote(var/vote)
|
||||
if(mode)
|
||||
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
|
||||
return 0
|
||||
if(!(usr.ckey in voted))
|
||||
if(vote && 1<=vote && vote<=choices.len)
|
||||
voted += usr.ckey
|
||||
choices[choices[vote]]++ //check this
|
||||
return vote
|
||||
return 0
|
||||
|
||||
proc/initiate_vote(var/vote_type, var/initiator_key)
|
||||
if(!mode)
|
||||
if(started_timeofday != null)
|
||||
var/next_allowed_timeofday = (started_timeofday + config.vote_delay)
|
||||
if(world.timeofday < started_timeofday)
|
||||
next_allowed_timeofday -= 864000
|
||||
if(next_allowed_timeofday > world.timeofday)
|
||||
return 0
|
||||
/datum/controller/vote/proc/process() //called by master_controller
|
||||
if(mode)
|
||||
time_remaining = started_timeofday + config.vote_period
|
||||
if(world.timeofday < started_timeofday)
|
||||
time_remaining -= 864000
|
||||
time_remaining = round((time_remaining - world.timeofday)/10)
|
||||
|
||||
var/i=1
|
||||
if(time_remaining < 0)
|
||||
result()
|
||||
while(i<=voting.len)
|
||||
var/client/C = voting[i]
|
||||
if(C)
|
||||
C << browse(null,"window=vote;can_close=0")
|
||||
i++
|
||||
reset()
|
||||
switch(vote_type)
|
||||
if("restart") choices.Add("Restart Round","Continue Playing")
|
||||
if("gamemode") choices.Add(config.votable_modes)
|
||||
if("custom")
|
||||
question = html_encode(input(usr,"What is the vote for?") as text|null)
|
||||
if(!question) return 0
|
||||
for(var/i=1,i<=10,i++)
|
||||
var/option = capitalize(html_encode(input(usr,"Please enter an option or hit cancel to finish") as text|null))
|
||||
if(!option || mode || !usr.client) break
|
||||
choices.Add(option)
|
||||
else return 0
|
||||
mode = vote_type
|
||||
initiator = initiator_key
|
||||
started_timeofday = world.timeofday
|
||||
var/text = "[capitalize(mode)] vote started by [initiator]."
|
||||
if(mode == "custom")
|
||||
text += "\n[question]"
|
||||
log_vote(text)
|
||||
world << "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
|
||||
time_remaining = round(config.vote_period/10)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
proc/interface(var/client/C)
|
||||
if(!C) return
|
||||
var/admin = 0
|
||||
var/trialmin = 0
|
||||
if(C.holder)
|
||||
admin = 1
|
||||
if(check_rights_for(C, R_ADMIN))
|
||||
trialmin = 1
|
||||
voting |= C
|
||||
|
||||
if(mode)
|
||||
if(question) . += "<h2>Vote: '[question]'</h2>"
|
||||
else . += "<h2>Vote: [capitalize(mode)]</h2>"
|
||||
. += "Time Left: [time_remaining] s<hr><ul>"
|
||||
for(var/i=1,i<=choices.len,i++)
|
||||
var/votes = choices[choices[i]]
|
||||
if(!votes) votes = 0
|
||||
. += "<li><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a> ([votes] votes)</li>"
|
||||
. += "</ul><hr>"
|
||||
if(admin)
|
||||
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
|
||||
else
|
||||
. += "<h2>Start a vote:</h2><hr><ul><li>"
|
||||
//restart
|
||||
if(trialmin || config.allow_vote_restart)
|
||||
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
|
||||
else
|
||||
. += "<font color='grey'>Restart (Disallowed)</font>"
|
||||
if(trialmin)
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
|
||||
. += "</li><li>"
|
||||
//gamemode
|
||||
if(trialmin || config.allow_vote_mode)
|
||||
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
|
||||
else
|
||||
. += "<font color='grey'>GameMode (Disallowed)</font>"
|
||||
if(trialmin)
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
|
||||
var/datum/browser/client_popup
|
||||
while(i<=voting.len)
|
||||
var/client/C = voting[i]
|
||||
if(C)
|
||||
//C << browse(vote.interface(C),"window=vote;can_close=0")
|
||||
client_popup = new(C, "vote", "Voting Panel")
|
||||
client_popup.set_window_options("can_close=0")
|
||||
client_popup.set_content(vote.interface(C))
|
||||
client_popup.open(0)
|
||||
|
||||
. += "</li>"
|
||||
//custom
|
||||
if(trialmin)
|
||||
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
|
||||
. += "</ul><hr>"
|
||||
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a>"
|
||||
return .
|
||||
i++
|
||||
else
|
||||
voting.Cut(i,i+1)
|
||||
|
||||
/datum/controller/vote/proc/reset()
|
||||
initiator = null
|
||||
time_remaining = 0
|
||||
mode = null
|
||||
question = null
|
||||
choices.Cut()
|
||||
voted.Cut()
|
||||
voting.Cut()
|
||||
|
||||
Topic(href,href_list[],hsrc)
|
||||
if(!usr || !usr.client) return //not necessary but meh...just in-case somebody does something stupid
|
||||
switch(href_list["vote"])
|
||||
if("close")
|
||||
voting -= usr.client
|
||||
usr << browse(null, "window=vote")
|
||||
return
|
||||
if("cancel")
|
||||
if(usr.client.holder)
|
||||
reset()
|
||||
if("toggle_restart")
|
||||
if(usr.client.holder)
|
||||
config.allow_vote_restart = !config.allow_vote_restart
|
||||
if("toggle_gamemode")
|
||||
if(usr.client.holder)
|
||||
config.allow_vote_mode = !config.allow_vote_mode
|
||||
/datum/controller/vote/proc/get_result()
|
||||
//get the highest number of votes
|
||||
var/greatest_votes = 0
|
||||
var/total_votes = 0
|
||||
for(var/option in choices)
|
||||
var/votes = choices[option]
|
||||
total_votes += votes
|
||||
if(votes > greatest_votes)
|
||||
greatest_votes = votes
|
||||
//default-vote for everyone who didn't vote
|
||||
if(!config.vote_no_default && choices.len)
|
||||
var/non_voters = (clients.len - total_votes)
|
||||
if(non_voters > 0)
|
||||
if(mode == "restart")
|
||||
choices["Continue Playing"] += non_voters
|
||||
if(choices["Continue Playing"] >= greatest_votes)
|
||||
greatest_votes = choices["Continue Playing"]
|
||||
else if(mode == "gamemode")
|
||||
if(master_mode in choices)
|
||||
choices[master_mode] += non_voters
|
||||
if(choices[master_mode] >= greatest_votes)
|
||||
greatest_votes = choices[master_mode]
|
||||
//get all options with that many votes and return them in a list
|
||||
. = list()
|
||||
if(greatest_votes)
|
||||
for(var/option in choices)
|
||||
if(choices[option] == greatest_votes)
|
||||
. += option
|
||||
return .
|
||||
|
||||
/datum/controller/vote/proc/announce_result()
|
||||
var/list/winners = get_result()
|
||||
var/text
|
||||
if(winners.len > 0)
|
||||
if(question) text += "<b>[question]</b>"
|
||||
else text += "<b>[capitalize(mode)] Vote</b>"
|
||||
for(var/i=1,i<=choices.len,i++)
|
||||
var/votes = choices[choices[i]]
|
||||
if(!votes) votes = 0
|
||||
text += "\n<b>[choices[i]]:</b> [votes]"
|
||||
if(mode != "custom")
|
||||
if(winners.len > 1)
|
||||
text = "\n<b>Vote Tied Between:</b>"
|
||||
for(var/option in winners)
|
||||
text += "\n\t[option]"
|
||||
. = pick(winners)
|
||||
text += "\n<b>Vote Result: [.]</b>"
|
||||
else
|
||||
text += "\n<b>Did not vote:</b> [clients.len-voted.len]"
|
||||
else
|
||||
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
|
||||
log_vote(text)
|
||||
world << "\n<font color='purple'>[text]</font>"
|
||||
return .
|
||||
|
||||
/datum/controller/vote/proc/result()
|
||||
. = announce_result()
|
||||
var/restart = 0
|
||||
if(.)
|
||||
switch(mode)
|
||||
if("restart")
|
||||
if(config.allow_vote_restart || usr.client.holder)
|
||||
initiate_vote("restart",usr.key)
|
||||
if(. == "Restart Round")
|
||||
restart = 1
|
||||
if("gamemode")
|
||||
if(config.allow_vote_mode || usr.client.holder)
|
||||
initiate_vote("gamemode",usr.key)
|
||||
if(master_mode != .)
|
||||
world.save_mode(.)
|
||||
if(ticker && ticker.mode)
|
||||
restart = 1
|
||||
else
|
||||
master_mode = .
|
||||
|
||||
if(restart)
|
||||
world << "World restarting due to vote..."
|
||||
feedback_set_details("end_error","restart vote")
|
||||
if(blackbox) blackbox.save_all_data_to_sql()
|
||||
sleep(50)
|
||||
log_game("Rebooting due to restart vote")
|
||||
world.Reboot()
|
||||
|
||||
return .
|
||||
|
||||
/datum/controller/vote/proc/submit_vote(var/vote)
|
||||
if(mode)
|
||||
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
|
||||
return 0
|
||||
if(!(usr.ckey in voted))
|
||||
if(vote && 1<=vote && vote<=choices.len)
|
||||
voted += usr.ckey
|
||||
choices[choices[vote]]++ //check this
|
||||
return vote
|
||||
return 0
|
||||
|
||||
/datum/controller/vote/proc/initiate_vote(var/vote_type, var/initiator_key)
|
||||
if(!mode)
|
||||
if(started_timeofday != null)
|
||||
var/next_allowed_timeofday = (started_timeofday + config.vote_delay)
|
||||
if(world.timeofday < started_timeofday)
|
||||
next_allowed_timeofday -= 864000
|
||||
if(next_allowed_timeofday > world.timeofday)
|
||||
return 0
|
||||
|
||||
reset()
|
||||
switch(vote_type)
|
||||
if("restart") choices.Add("Restart Round","Continue Playing")
|
||||
if("gamemode") choices.Add(config.votable_modes)
|
||||
if("custom")
|
||||
if(usr.client.holder)
|
||||
initiate_vote("custom",usr.key)
|
||||
else
|
||||
submit_vote(round(text2num(href_list["vote"])))
|
||||
usr.vote()
|
||||
question = html_encode(input(usr,"What is the vote for?") as text|null)
|
||||
if(!question) return 0
|
||||
for(var/i=1,i<=10,i++)
|
||||
var/option = capitalize(html_encode(input(usr,"Please enter an option or hit cancel to finish") as text|null))
|
||||
if(!option || mode || !usr.client) break
|
||||
choices.Add(option)
|
||||
else return 0
|
||||
mode = vote_type
|
||||
initiator = initiator_key
|
||||
started_timeofday = world.timeofday
|
||||
var/text = "[capitalize(mode)] vote started by [initiator]."
|
||||
if(mode == "custom")
|
||||
text += "\n[question]"
|
||||
log_vote(text)
|
||||
world << "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
|
||||
time_remaining = round(config.vote_period/10)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/controller/vote/proc/interface(var/client/C)
|
||||
if(!C) return
|
||||
var/admin = 0
|
||||
var/trialmin = 0
|
||||
if(C.holder)
|
||||
admin = 1
|
||||
if(check_rights_for(C, R_ADMIN))
|
||||
trialmin = 1
|
||||
voting |= C
|
||||
|
||||
if(mode)
|
||||
if(question) . += "<h2>Vote: '[question]'</h2>"
|
||||
else . += "<h2>Vote: [capitalize(mode)]</h2>"
|
||||
. += "Time Left: [time_remaining] s<hr><ul>"
|
||||
for(var/i=1,i<=choices.len,i++)
|
||||
var/votes = choices[choices[i]]
|
||||
if(!votes) votes = 0
|
||||
. += "<li><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a> ([votes] votes)</li>"
|
||||
. += "</ul><hr>"
|
||||
if(admin)
|
||||
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
|
||||
else
|
||||
. += "<h2>Start a vote:</h2><hr><ul><li>"
|
||||
//restart
|
||||
if(trialmin || config.allow_vote_restart)
|
||||
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
|
||||
else
|
||||
. += "<font color='grey'>Restart (Disallowed)</font>"
|
||||
if(trialmin)
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
|
||||
. += "</li><li>"
|
||||
//gamemode
|
||||
if(trialmin || config.allow_vote_mode)
|
||||
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
|
||||
else
|
||||
. += "<font color='grey'>GameMode (Disallowed)</font>"
|
||||
if(trialmin)
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
|
||||
|
||||
. += "</li>"
|
||||
//custom
|
||||
if(trialmin)
|
||||
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
|
||||
. += "</ul><hr>"
|
||||
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a>"
|
||||
return .
|
||||
|
||||
|
||||
/datum/controller/vote/Topic(href,href_list[],hsrc)
|
||||
if(!usr || !usr.client) return //not necessary but meh...just in-case somebody does something stupid
|
||||
switch(href_list["vote"])
|
||||
if("close")
|
||||
voting -= usr.client
|
||||
usr << browse(null, "window=vote")
|
||||
return
|
||||
if("cancel")
|
||||
if(usr.client.holder)
|
||||
reset()
|
||||
if("toggle_restart")
|
||||
if(usr.client.holder)
|
||||
config.allow_vote_restart = !config.allow_vote_restart
|
||||
if("toggle_gamemode")
|
||||
if(usr.client.holder)
|
||||
config.allow_vote_mode = !config.allow_vote_mode
|
||||
if("restart")
|
||||
if(config.allow_vote_restart || usr.client.holder)
|
||||
initiate_vote("restart",usr.key)
|
||||
if("gamemode")
|
||||
if(config.allow_vote_mode || usr.client.holder)
|
||||
initiate_vote("gamemode",usr.key)
|
||||
if("custom")
|
||||
if(usr.client.holder)
|
||||
initiate_vote("custom",usr.key)
|
||||
else
|
||||
submit_vote(round(text2num(href_list["vote"])))
|
||||
usr.vote()
|
||||
|
||||
|
||||
/mob/verb/vote()
|
||||
@@ -268,4 +268,4 @@ datum/controller/vote
|
||||
var/datum/browser/popup = new(src, "vote", "Voting Panel")
|
||||
popup.set_window_options("can_close=0")
|
||||
popup.set_content(vote.interface(client))
|
||||
popup.open(0)
|
||||
popup.open(0)
|
||||
|
||||
Reference in New Issue
Block a user