diff --git a/baystation12.dme b/baystation12.dme
index a7f8a4defa..48908bfa19 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -213,6 +213,7 @@
#include "code\game\asteroid.dm"
#include "code\game\atoms.dm"
#include "code\game\atoms_movable.dm"
+#include "code\game\base_turf.dm"
#include "code\game\periodic_news.dm"
#include "code\game\response_team.dm"
#include "code\game\shuttle_engines.dm"
@@ -311,7 +312,9 @@
#include "code\game\gamemodes\revolution\revolution.dm"
#include "code\game\gamemodes\traitor\traitor.dm"
#include "code\game\gamemodes\wizard\wizard.dm"
+#include "code\game\jobs\_access_defs.dm"
#include "code\game\jobs\access.dm"
+#include "code\game\jobs\access_datum.dm"
#include "code\game\jobs\job_controller.dm"
#include "code\game\jobs\jobprocs.dm"
#include "code\game\jobs\jobs.dm"
@@ -1479,8 +1482,19 @@
#include "code\modules\projectiles\projectile\energy.dm"
#include "code\modules\projectiles\projectile\force.dm"
#include "code\modules\projectiles\projectile\special.dm"
-#include "code\modules\random_map\mining_distribution.dm"
+#include "code\modules\random_map\_random_map_setup.dm"
#include "code\modules\random_map\random_map.dm"
+#include "code\modules\random_map\random_map_verbs.dm"
+#include "code\modules\random_map\automata\automata.dm"
+#include "code\modules\random_map\automata\caves.dm"
+#include "code\modules\random_map\building\building.dm"
+#include "code\modules\random_map\mazes\maze.dm"
+#include "code\modules\random_map\mazes\maze_cell.dm"
+#include "code\modules\random_map\noise\desert.dm"
+#include "code\modules\random_map\noise\magma.dm"
+#include "code\modules\random_map\noise\noise.dm"
+#include "code\modules\random_map\noise\ore.dm"
+#include "code\modules\random_map\noise\tundra.dm"
#include "code\modules\reagents\Chemistry-Colours.dm"
#include "code\modules\reagents\Chemistry-Holder.dm"
#include "code\modules\reagents\Chemistry-Machinery.dm"
diff --git a/code/ATMOSPHERICS/_atmospherics_helpers.dm b/code/ATMOSPHERICS/_atmospherics_helpers.dm
index f85fa84b93..d4de419ad0 100644
--- a/code/ATMOSPHERICS/_atmospherics_helpers.dm
+++ b/code/ATMOSPHERICS/_atmospherics_helpers.dm
@@ -130,7 +130,7 @@
var/total_specific_power = 0 //the power required to remove one mole of filterable gas
for (var/g in filtering)
var/ratio = source.gas[g]/total_filterable_moles //this converts the specific power per mole of pure gas to specific power per mole of scrubbed gas
- total_specific_power = specific_power_gas[g]*ratio
+ total_specific_power += specific_power_gas[g]*ratio
//Figure out how much of each gas to filter
if (isnull(total_transfer_moles))
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index 7237cccbca..9ae50b11af 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -85,6 +85,9 @@ obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/a
return node.pipe_color
/obj/machinery/atmospherics/process()
+ last_flow_rate = 0
+ last_power_draw = 0
+
build_network()
/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index 03af4cf35b..cfe07ff672 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -17,6 +17,7 @@
var/frequency = 1439
var/datum/radio_frequency/radio_connection
+ var/hibernate = 0 //Do we even process?
var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
var/list/scrubbing_gas = list("carbon_dioxide")
@@ -126,8 +127,8 @@
/obj/machinery/atmospherics/unary/vent_scrubber/process()
..()
- last_power_draw = 0
- last_flow_rate = 0
+ if (hibernate)
+ return 1
if (!node)
use_power = 0
@@ -149,6 +150,12 @@
power_draw = pump_gas(src, environment, air_contents, transfer_moles, power_rating)
+ if(scrubbing && power_draw < 0 && controller_iteration > 10) //99% of all scrubbers
+ //Fucking hibernate because you ain't doing shit.
+ hibernate = 1
+ spawn(rand(100,200)) //hibernate for 10 or 20 seconds randomly
+ hibernate = 0
+
if (power_draw >= 0)
last_power_draw = power_draw
use_power(power_draw)
diff --git a/code/TriDimension/Turfs.dm b/code/TriDimension/Turfs.dm
index 6443d6b569..164b95f0bf 100644
--- a/code/TriDimension/Turfs.dm
+++ b/code/TriDimension/Turfs.dm
@@ -71,7 +71,7 @@
for(var/obj/effect/landmark/zcontroller/controller in controllerlocation)
// check if there is something to draw below
if(!controller.down)
- src.ChangeTurf(/turf/space)
+ src.ChangeTurf(get_base_turf(src.z))
return 0
else
floorbelow = locate(src.x, src.y, controller.down_target)
diff --git a/code/TriDimension/controller.dm b/code/TriDimension/controller.dm
index 7feed3ed09..c8b81d0d49 100644
--- a/code/TriDimension/controller.dm
+++ b/code/TriDimension/controller.dm
@@ -166,70 +166,6 @@ atom/movable/Move() //Hackish
T.overlays -= below.z_overlays
T.z_overlays -= below.z_overlays
- // this is sadly impossible to use right now
- // the overlay is always opaque to mouseclicks and thus prevents interactions with everything except the turf
- /*if(up)
- var/turf/above = locate(T.x, T.y, up_target)
- if(above)
- var/eligeable = 0
- for(var/d in cardinal)
- var/turf/mT = get_step(above,d)
- if(istype(mT, /turf/space) || istype(mT, /turf/simulated/floor/open))
- eligeable = 1
- /*if(mT.opacity == 0)
- for(var/f in cardinal)
- var/turf/nT = get_step(mT,f)
- if(istype(nT, /turf/space) || istype(nT, /turf/simulated/floor/open))
- eligeable = 1*/
- if(istype(above, /turf/space) || istype(above, /turf/simulated/floor/open)) eligeable = 1
- if(eligeable == 1)
- if(!(istype(above, /turf/space) || istype(above, /turf/simulated/floor/open)))
- var/image/t_img = list()
- if(new_list < 1) new_list = 1
-
- above.overlays -= above.z_overlays
- var/image/temp = image(above, dir=above.dir, layer = 5 + 0.04)
- above.overlays += above.z_overlays
-
- temp.alpha = 100
- temp.overlays += above.overlays
- temp.overlays -= above.z_overlays
- t_img += temp
- T.overlays += t_img
- T.z_overlays += t_img
-
- // get objects
- var/image/o_img = list()
- for(var/obj/o in above)
- // ingore objects that have any form of invisibility
- if(o.invisibility) continue
- if(new_list < 2) new_list = 2
- var/image/temp2 = image(o, dir=o.dir, layer = 5+0.05*o.layer)
- temp2.alpha = 100
- temp2.overlays += o.overlays
- o_img += temp2
- // you need to add a list to .overlays or it will not display any because space
- T.overlays += o_img
- T.z_overlays += o_img
-
- // get mobs
- var/image/m_img = list()
- for(var/mob/m in above)
- // ingore mobs that have any form of invisibility
- if(m.invisibility) continue
- // only add this tile to fastprocessing if there is a living mob, not a dead one
- if(istype(m, /mob/living) && new_list < 3) new_list = 3
- var/image/temp2 = image(m, dir=m.dir, layer = 5+0.05*m.layer)
- temp2.alpha = 100
- temp2.overlays += m.overlays
- m_img += temp2
- // you need to add a list to .overlays or it will not display any because space
- T.overlays += m_img
- T.z_overlays += m_img
-
- T.overlays -= above.z_overlays
- T.z_overlays -= above.z_overlays*/
-
L -= T
if(new_list == 1)
diff --git a/code/ZAS/Diagnostic.dm b/code/ZAS/Diagnostic.dm
index f54caa3a42..ed94b7d582 100644
--- a/code/ZAS/Diagnostic.dm
+++ b/code/ZAS/Diagnostic.dm
@@ -84,153 +84,6 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
else
mob << "both turfs can merge."
-
-/*zone/proc/DebugDisplay(client/client)
- if(!istype(client))
- return
-
- if(!dbg_output)
- dbg_output = 1 //Don't want to be spammed when someone investigates a zone...
-
- if(!client.zone_debug_images)
- client.zone_debug_images = list()
-
- var/list/current_zone_images = list()
-
- for(var/turf/T in contents)
- current_zone_images += image('icons/misc/debug_group.dmi', T, null, TURF_LAYER)
-
- for(var/turf/space/S in unsimulated_tiles)
- current_zone_images += image('icons/misc/debug_space.dmi', S, null, TURF_LAYER)
-
- client << "Zone Air Contents"
- client << "Oxygen: [air.oxygen]"
- client << "Nitrogen: [air.nitrogen]"
- client << "Phoron: [air.phoron]"
- client << "Carbon Dioxide: [air.carbon_dioxide]"
- client << "Temperature: [air.temperature] K"
- client << "Heat Energy: [air.temperature * air.heat_capacity()] J"
- client << "Pressure: [air.return_pressure()] KPa"
- client << ""
- client << "Space Tiles: [length(unsimulated_tiles)]"
- client << "Movable Objects: [length(movables())]"
- client << "Connections: [length(connections)]"
-
- for(var/connection/C in connections)
- client << "\ref[C] [C.A] --> [C.B] [(C.indirect?"Open":"Closed")]"
- current_zone_images += image('icons/misc/debug_connect.dmi', C.A, null, TURF_LAYER)
- current_zone_images += image('icons/misc/debug_connect.dmi', C.B, null, TURF_LAYER)
-
- client << "Connected Zones:"
- for(var/zone/zone in connected_zones)
- client << "\ref[zone] [zone] - [connected_zones[zone]] (Connected)"
-
- for(var/zone/zone in closed_connection_zones)
- client << "\ref[zone] [zone] - [closed_connection_zones[zone]] (Unconnected)"
-
- for(var/C in connections)
- if(!istype(C,/connection))
- client << "[C] (Not Connection!)"
-
- if(!client.zone_debug_images)
- client.zone_debug_images = list()
- client.zone_debug_images[src] = current_zone_images
-
- client.images += client.zone_debug_images[src]
-
- else
- dbg_output = 0
-
- client.images -= client.zone_debug_images[src]
- client.zone_debug_images.Remove(src)
-
- if(air_master)
- for(var/zone/Z in air_master.zones)
- if(Z.air == air && Z != src)
- var/turf/zloc = pick(Z.contents)
- client << "Illegal air datum shared by: [zloc.loc.name]"*/
-
-
-/*client/proc/TestZASRebuild()
- set category = "Debug"
-// var/turf/turf = get_turf(mob)
- var/zone/current_zone = mob.loc:zone
- if(!current_zone)
- src << "There is no zone there!"
- return
-
- var/list/current_adjacents = list()
- var/list/overlays = list()
- var/adjacent_id
- var/lowest_id
-
- var/list/identical_ids = list()
- var/list/turfs = current_zone.contents.Copy()
- var/current_identifier = 1
-
- for(var/turf/simulated/current in turfs)
- lowest_id = null
- current_adjacents = list()
-
- for(var/direction in cardinal)
- var/turf/simulated/adjacent = get_step(current, direction)
- if(!current.ZCanPass(adjacent))
- continue
- if(turfs.Find(adjacent))
- current_adjacents += adjacent
- adjacent_id = turfs[adjacent]
-
- if(adjacent_id && (!lowest_id || adjacent_id < lowest_id))
- lowest_id = adjacent_id
-
- if(!lowest_id)
- lowest_id = current_identifier++
- identical_ids += lowest_id
- overlays += image('icons/misc/debug_rebuild.dmi',, "[lowest_id]")
-
- for(var/turf/simulated/adjacent in current_adjacents)
- adjacent_id = turfs[adjacent]
- if(adjacent_id != lowest_id)
- if(adjacent_id)
- adjacent.overlays -= overlays[adjacent_id]
- identical_ids[adjacent_id] = lowest_id
-
- turfs[adjacent] = lowest_id
- adjacent.overlays += overlays[lowest_id]
-
- sleep(5)
-
- if(turfs[current])
- current.overlays -= overlays[turfs[current]]
- turfs[current] = lowest_id
- current.overlays += overlays[lowest_id]
- sleep(5)
-
- var/list/final_arrangement = list()
-
- for(var/turf/simulated/current in turfs)
- current_identifier = identical_ids[turfs[current]]
- current.overlays -= overlays[turfs[current]]
- current.overlays += overlays[current_identifier]
- sleep(5)
-
- if( current_identifier > final_arrangement.len )
- final_arrangement.len = current_identifier
- final_arrangement[current_identifier] = list(current)
-
- else
- final_arrangement[current_identifier] += current
-
- //lazy but fast
- final_arrangement.Remove(null)
-
- src << "There are [final_arrangement.len] unique segments."
-
- for(var/turf/current in turfs)
- current.overlays -= overlays
-
- return final_arrangement*/
-
client/proc/ZASSettings()
set category = "Debug"
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 55b1b23a9f..09e6f845c8 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -7,6 +7,8 @@ var/list/directory = list() //list of all ckeys with associated client
var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/new_player
var/global/list/mob_list = list() //List of all mobs, including clientless
+var/global/list/human_mob_list = list() //List of all human mobs and sub-types, including clientless
+var/global/list/silicon_mob_list = list() //List of all silicon mobs, including clientless
var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player
var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player
diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm
index f148b10ef8..2e20370f8f 100644
--- a/code/__HELPERS/maths.dm
+++ b/code/__HELPERS/maths.dm
@@ -101,18 +101,18 @@ var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
// if they are imaginary.
/proc/SolveQuadratic(a, b, c)
ASSERT(a)
-
+
. = list()
var/discriminant = b*b - 4*a*c
var/bottom = 2*a
-
+
// Return if the roots are imaginary.
if(discriminant < 0)
return
-
+
var/root = sqrt(discriminant)
. += (-b + root) / bottom
-
+
// If discriminant == 0, there would be two roots at the same position.
if(discriminant != 0)
. += (-b - root) / bottom
@@ -131,3 +131,9 @@ var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
/proc/norm(x, y)
return sqrt(squaredNorm(x, y))
+
+/proc/IsPowerOfTwo(var/val)
+ return (val & (val-1)) == 0
+
+/proc/RoundUpToPowerOfTwo(var/val)
+ return 2 ** -round(-log(2,val))
\ No newline at end of file
diff --git a/code/__HELPERS/turfs.dm b/code/__HELPERS/turfs.dm
index b9b4225a41..3ee4e26a7a 100644
--- a/code/__HELPERS/turfs.dm
+++ b/code/__HELPERS/turfs.dm
@@ -11,3 +11,9 @@
/proc/isfloor(turf/T)
return (istype(T, /turf/simulated/floor) || istype(T, /turf/unsimulated/floor) || istype(T, /turf/simulated/shuttle/floor))
+
+/proc/turf_clear(turf/T)
+ for(var/atom/A in T)
+ if(A.simulated)
+ return 0
+ return 1
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 3564c5e15f..75166b3f48 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -444,6 +444,8 @@ Turf and target are seperate in case you want to teleport some distance from a t
/proc/sortmobs()
var/list/moblist = list()
var/list/sortmob = sortAtom(mob_list)
+ for(var/mob/eye/M in sortmob)
+ moblist.Add(M)
for(var/mob/living/silicon/ai/M in sortmob)
moblist.Add(M)
for(var/mob/living/silicon/pai/M in sortmob)
@@ -921,7 +923,7 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
if(turftoleave)
fromupdate += T.ChangeTurf(turftoleave)
else
- T.ChangeTurf(/turf/space)
+ T.ChangeTurf(get_base_turf(T.z))
refined_src -= T
refined_trg -= B
@@ -1004,7 +1006,7 @@ proc/DuplicateObject(obj/original, var/perfectcopy = 0 , var/sameloc = 0)
var/old_icon1 = T.icon
if(platingRequired)
- if(istype(B, /turf/space))
+ if(istype(B, get_base_turf(B.z)))
continue moving
var/turf/X = new T.type(B)
diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm
index 0152af8b13..002c30b0eb 100644
--- a/code/controllers/master_controller.dm
+++ b/code/controllers/master_controller.dm
@@ -12,7 +12,6 @@ var/global/pipe_processing_killed = 0
datum/controller/game_controller
var/list/shuttle_list // For debugging and VV
- var/datum/random_map/ore/asteroid_ore_map // For debugging and VV.
datum/controller/game_controller/New()
//There can be only one master_controller. Out with the old and in with the new.
@@ -65,11 +64,6 @@ datum/controller/game_controller/proc/setup_objects()
var/obj/machinery/atmospherics/unary/vent_scrubber/T = U
T.broadcast_status()
- // Create the mining ore distribution map.
- // These values determine the specific area that the map is applied to.
- // If you do not use the official Baycode asteroid map, you will need to change them.
- asteroid_ore_map = new /datum/random_map/ore(null,13,32,5,217,223)
-
// Set up antagonists.
populate_antag_type_list()
diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm
index 489d648865..d53219fcf9 100644
--- a/code/controllers/shuttle_controller.dm
+++ b/code/controllers/shuttle_controller.dm
@@ -19,7 +19,7 @@ var/global/datum/shuttle_controller/shuttle_controller
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
@@ -210,7 +210,7 @@ var/global/datum/shuttle_controller/shuttle_controller
"Fore Port Solars" = locate(/area/skipjack_station/northwest_solars),
"Aft Starboard Solars" = locate(/area/skipjack_station/southeast_solars),
"Aft Port Solars" = locate(/area/skipjack_station/southwest_solars),
- "Mining asteroid" = locate(/area/skipjack_station/mining)
+ "Mining Station" = locate(/area/skipjack_station/mining)
)
VS.announcer = "NSV Icarus"
@@ -234,10 +234,10 @@ var/global/datum/shuttle_controller/shuttle_controller
"South of the station" = locate(/area/syndicate_station/south),
"Southeast of the station" = locate(/area/syndicate_station/southeast),
"Telecomms Satellite" = locate(/area/syndicate_station/commssat),
- "Mining Asteroid" = locate(/area/syndicate_station/mining),
+ "Mining Station" = locate(/area/syndicate_station/mining),
"Arrivals dock" = locate(/area/syndicate_station/arrivals_dock),
)
-
+
MS.docking_controller_tag = "merc_shuttle"
MS.destination_dock_targets = list(
"Mercenary Base" = "merc_base",
diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm
index d849bc836b..c394318c28 100644
--- a/code/controllers/verbs.dm
+++ b/code/controllers/verbs.dm
@@ -1,35 +1,5 @@
//TODO: rewrite and standardise all controller datums to the datum/controller type
//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done
-
-/client/proc/print_random_map()
- set category = "Debug"
- set name = "Display Random Map"
- set desc = "Show the contents of a random map."
-
- if(!holder) return
-
- var/datum/random_map/choice = input("Choose a map to debug.") as null|anything in random_maps
- if(!choice)
- return
- choice.display_map(usr)
-
-
-/client/proc/create_random_map()
- set category = "Debug"
- set name = "Create Random Map"
- set desc = "Create a random map."
-
- if(!holder) return
-
- var/map_datum = input("Choose a map to create.") as null|anything in typesof(/datum/random_map)-/datum/random_map
- if(!map_datum)
- return
- var/seed = input("Seed? (default null)") as text|null
- var/tx = input("X? (default 1)") as text|null
- var/ty = input("Y? (default 1)") as text|null
- var/tz = input("Z? (default 1)") as text|null
- new map_datum(seed,tx,ty,tz)
-
/client/proc/restart_controller(controller in list("Supply"))
set category = "Debug"
set name = "Restart Controller"
diff --git a/code/game/antagonist/outsider/commando.dm b/code/game/antagonist/outsider/commando.dm
index 0d3de6cc07..50d8ac5361 100644
--- a/code/game/antagonist/outsider/commando.dm
+++ b/code/game/antagonist/outsider/commando.dm
@@ -25,6 +25,6 @@ var/datum/antagonist/deathsquad/mercenary/commandos
player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand)
var/obj/item/weapon/card/id/id = create_id("Commando", player)
- id.access |= get_all_accesses()
+ id.access |= get_all_station_access()
id.icon_state = "centcom"
create_radio(SYND_FREQ, player)
\ No newline at end of file
diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm
index 73c2c7fd78..d03f5c3d8a 100644
--- a/code/game/antagonist/outsider/deathsquad.dm
+++ b/code/game/antagonist/outsider/deathsquad.dm
@@ -45,7 +45,7 @@ var/datum/antagonist/deathsquad/deathsquad
var/obj/item/weapon/card/id/id = create_id("Asset Protection", player)
if(id)
- id.access |= get_all_accesses()
+ id.access |= get_all_station_access()
id.icon_state = "centcom"
create_radio(DTH_FREQ, player)
diff --git a/code/game/antagonist/station/highlander.dm b/code/game/antagonist/station/highlander.dm
index 44e2e1fcfe..1fd573bf1a 100644
--- a/code/game/antagonist/station/highlander.dm
+++ b/code/game/antagonist/station/highlander.dm
@@ -44,7 +44,7 @@ var/datum/antagonist/highlander/highlanders
var/obj/item/weapon/card/id/W = new(player)
W.name = "[player.real_name]'s ID Card"
W.icon_state = "centcom"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.access += get_all_centcom_access()
W.assignment = "Highlander"
W.registered_name = player.real_name
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 4bc9bbe481..d9f0f9078d 100755
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -402,17 +402,17 @@ area/space/atmosalert()
//EXTRA
/area/asteroid // -- TLE
- name = "\improper Asteroid"
+ name = "\improper Moon"
icon_state = "asteroid"
requires_power = 0
/area/asteroid/cave // -- TLE
- name = "\improper Asteroid - Underground"
+ name = "\improper Moon - Underground"
icon_state = "cave"
requires_power = 0
/area/asteroid/artifactroom
- name = "\improper Asteroid - Artifact"
+ name = "\improper Moon - Artifact"
icon_state = "cave"
@@ -498,7 +498,7 @@ area/space/atmosalert()
icon_state = "south"
/area/syndicate_station/mining
- name = "\improper north east of the mining asteroid"
+ name = "\improper northeast of the mining station"
icon_state = "north"
/area/syndicate_station/arrivals_dock
@@ -540,7 +540,7 @@ area/space/atmosalert()
icon_state = "southeast"
/area/skipjack_station/mining
- name = "\improper nearby mining asteroid"
+ name = "\improper south of mining station"
icon_state = "north"
//PRISON
@@ -1354,10 +1354,26 @@ area/space/atmosalert()
name = "\improper Security - Brig"
icon_state = "brig"
+/area/security/brig/prison_break()
+ for(var/obj/structure/closet/secure_closet/brig/temp_closet in src)
+ temp_closet.locked = 0
+ temp_closet.icon_state = temp_closet.icon_closed
+ for(var/obj/machinery/door_timer/temp_timer in src)
+ temp_timer.releasetime = 1
+ ..()
+
/area/security/prison
name = "\improper Security - Prison Wing"
icon_state = "sec_prison"
+/area/security/prison/prison_break()
+ for(var/obj/structure/closet/secure_closet/brig/temp_closet in src)
+ temp_closet.locked = 0
+ temp_closet.icon_state = temp_closet.icon_closed
+ for(var/obj/machinery/door_timer/temp_timer in src)
+ temp_timer.releasetime = 1
+ ..()
+
/area/security/warden
name = "\improper Security - Warden's Office"
icon_state = "Warden"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 38452c3d5b..dccc9e9dbf 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -293,3 +293,10 @@ var/list/mob/living/forced_ambiance_list = new
H.AdjustWeakened(1)
mob << "The sudden appearance of gravity makes you fall to the floor!"
+/area/proc/prison_break()
+ for(var/obj/machinery/power/apc/temp_apc in src)
+ temp_apc.overload_lighting(70)
+ for(var/obj/machinery/door/airlock/temp_airlock in src)
+ temp_airlock.prison_open()
+ for(var/obj/machinery/door/window/temp_windoor in src)
+ temp_windoor.open()
\ No newline at end of file
diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm
index 8aa6b1cd64..979db2c147 100644
--- a/code/game/asteroid.dm
+++ b/code/game/asteroid.dm
@@ -82,81 +82,3 @@ proc/admin_spawn_room_at_pos()
if(x && y && z && wall && floor && x_len && y_len)
spawn_room(locate(x,y,z),x_len,y_len,wall,floor,clean)
return
-
-
-
-
-
-
-proc/make_mining_asteroid_secret(var/size = 5)
- var/valid = 0
- var/turf/T = null
- var/sanity = 0
- var/list/room = null
- var/list/turfs = null
-
-
- turfs = get_area_turfs(/area/mine/unexplored)
-
- if(!turfs.len)
- return 0
-
- while(!valid)
- valid = 1
- sanity++
- if(sanity > 100)
- return 0
-
- T=pick(turfs)
- if(!T)
- return 0
-
- var/list/surroundings = list()
-
- surroundings += range(7, locate(T.x,T.y,T.z))
- surroundings += range(7, locate(T.x+size,T.y,T.z))
- surroundings += range(7, locate(T.x,T.y+size,T.z))
- surroundings += range(7, locate(T.x+size,T.y+size,T.z))
-
- if(locate(/area/mine/explored) in surroundings) // +5s are for view range
- valid = 0
- continue
-
- if(locate(/turf/space) in surroundings)
- valid = 0
- continue
-
- if(locate(/area/asteroid/artifactroom) in surroundings)
- valid = 0
- continue
-
- if(locate(/turf/simulated/floor/plating/airless/asteroid) in surroundings)
- valid = 0
- continue
-
- if(!T)
- return 0
-
- room = spawn_room(T,size,size,,,1)
-
- if(room)
- T = pick(room["floors"])
- if(T)
- var/surprise = null
- valid = 0
- while(!valid)
- surprise = pickweight(space_surprises)
- if(surprise in spawned_surprises)
- if(prob(20))
- valid++
- else
- continue
- else
- valid++
-
- spawned_surprises.Add(surprise)
- new surprise(T)
-
- return 1
-
-
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 84baf5d18e..9c70bb669f 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -210,16 +210,16 @@
/atom/movable/overlay/attack_hand(a, b, c)
if (src.master)
return src.master.attack_hand(a, b, c)
- return
+ return
/atom/movable/proc/touch_map_edge()
- if(z in config.sealed_levels)
+ if(z in config.sealed_levels)
return
-
+
if(config.use_overmap)
overmap_spacetravel(get_turf(src), src)
return
-
+
var/move_to_z = src.get_transit_zlevel()
if(move_to_z)
z = move_to_z
@@ -248,14 +248,14 @@
if(loc) loc.Entered(src)
//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there.
-var/list/accessible_z_levels = list("1" = 5, "3" = 10, "4" = 15, "5" = 10, "6" = 60)
+var/list/accessible_z_levels = list("1" = 5, "3" = 10, "4" = 15, "6" = 60)
//by default, transition randomly to another zlevel
/atom/movable/proc/get_transit_zlevel()
var/list/candidates = accessible_z_levels.Copy()
candidates.Remove("[src.z]")
-
+
if(!candidates.len)
return null
return text2num(pickweight(candidates))
-
+
diff --git a/code/game/base_turf.dm b/code/game/base_turf.dm
new file mode 100644
index 0000000000..d6940e0275
--- /dev/null
+++ b/code/game/base_turf.dm
@@ -0,0 +1,27 @@
+// Returns the lowest turf available on a given Z-level, defaults to space.
+var/global/list/base_turf_by_z = list(
+ "5" = /turf/simulated/floor/plating/airless/asteroid // Moonbase.
+ )
+
+proc/get_base_turf(var/z)
+ if(!base_turf_by_z["[z]"])
+ base_turf_by_z["[z]"] = /turf/space
+ return base_turf_by_z["[z]"]
+
+/client/proc/set_base_turf()
+ set category = "Debug"
+ set name = "Set Base Turf"
+ set desc = "Set the base turf for a z-level."
+
+ if(!holder) return
+
+ var/choice = input("Which Z-level do you wish to set the base turf for?") as num|null
+ if(!choice)
+ return
+
+ var/new_base_path = input("Please select a turf path (cancel to reset to /turf/space).") as null|anything in typesof(/turf)
+ if(!new_base_path)
+ new_base_path = /turf/space
+ base_turf_by_z["[choice]"] = new_base_path
+ message_admins("[key_name_admin(usr)] has set the base turf for z-level [choice] to [get_base_turf(choice)].")
+ log_admin("[key_name(usr)] has set the base turf for z-level [choice] to [get_base_turf(choice)].")
\ No newline at end of file
diff --git a/code/game/gamemodes/cult/narsie.dm b/code/game/gamemodes/cult/narsie.dm
index 0ef0d27663..4dbbb4ce2f 100644
--- a/code/game/gamemodes/cult/narsie.dm
+++ b/code/game/gamemodes/cult/narsie.dm
@@ -224,9 +224,9 @@ var/global/list/narsie_list = list()
consume(AM2)
continue
- if (dist <= consume_range && !istype(A, /turf/space))
+ if (dist <= consume_range && !istype(A, get_base_turf(A.z)))
var/turf/T2 = A
- T2.ChangeTurf(/turf/space)
+ T2.ChangeTurf(get_base_turf(A.z))
/obj/singularity/narsie/consume(const/atom/A) //This one is for the small ones.
if(!(A.singuloCanEat()))
@@ -266,9 +266,9 @@ var/global/list/narsie_list = list()
spawn (0)
AM2.singularity_pull(src, src.current_size)
- if (dist <= consume_range && !istype(A, /turf/space))
+ if (dist <= consume_range && !istype(A, get_base_turf(A.z)))
var/turf/T2 = A
- T2.ChangeTurf(/turf/space)
+ T2.ChangeTurf(get_base_turf(A.z))
/obj/singularity/narsie/ex_act(severity) //No throwing bombs at it either. --NEO
return
diff --git a/code/game/gamemodes/events/black_hole.dm b/code/game/gamemodes/events/black_hole.dm
index 60ab8a692f..9c212ae0c5 100644
--- a/code/game/gamemodes/events/black_hole.dm
+++ b/code/game/gamemodes/events/black_hole.dm
@@ -24,8 +24,11 @@
qdel(M)
for(var/obj/O in orange(1,src))
qdel(O)
+ var/base_turf = get_base_turf(src.z)
for(var/turf/simulated/ST in orange(1,src))
- ST.ChangeTurf(/turf/space)
+ if(ST.type == base_turf)
+ continue
+ ST.ChangeTurf(base_turf)
sleep(6)
grav(10, 4, 10, 0 )
@@ -84,5 +87,6 @@
//Destroying the turf
if( T && istype(T,/turf/simulated) && prob(turf_removal_chance) )
var/turf/simulated/ST = T
- ST.ChangeTurf(/turf/space)
- return
\ No newline at end of file
+ var/base_turf = get_base_turf(src.z)
+ if(ST.type != base_turf)
+ ST.ChangeTurf(base_turf)
diff --git a/code/game/jobs/_access_defs.dm b/code/game/jobs/_access_defs.dm
new file mode 100644
index 0000000000..eb77c73cfa
--- /dev/null
+++ b/code/game/jobs/_access_defs.dm
@@ -0,0 +1,15 @@
+#define ACCESS_REGION_NONE -1
+#define ACCESS_REGION_ALL 0
+#define ACCESS_REGION_SECURITY 1
+#define ACCESS_REGION_MEDBAY 2
+#define ACCESS_REGION_RESEARCH 3
+#define ACCESS_REGION_ENGINEERING 4
+#define ACCESS_REGION_COMMAND 5
+#define ACCESS_REGION_GENERAL 6
+#define ACCESS_REGION_SUPPLY 7
+
+#define ACCESS_TYPE_NONE 0
+#define ACCESS_TYPE_STATION 1
+#define ACCESS_TYPE_CENTCOM 2
+#define ACCESS_TYPE_SYNDICATE 4
+#define ACCESS_TYPE_ALL 7
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index 449e5f68ba..09fc65bf41 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -1,91 +1,5 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-/var/const/access_security = 1 // Security equipment
-/var/const/access_brig = 2 // Brig timers and permabrig
-/var/const/access_armory = 3
-/var/const/access_forensics_lockers= 4
-/var/const/access_medical = 5
-/var/const/access_morgue = 6
-/var/const/access_tox = 7
-/var/const/access_tox_storage = 8
-/var/const/access_genetics = 9
-/var/const/access_engine = 10 //engineering hallways
-/var/const/access_engine_equip = 11
-/var/const/access_maint_tunnels = 12
-/var/const/access_external_airlocks = 13
-/var/const/access_emergency_storage = 14
-/var/const/access_change_ids = 15
-/var/const/access_ai_upload = 16
-/var/const/access_teleporter = 17
-/var/const/access_eva = 18
-/var/const/access_heads = 19
-/var/const/access_captain = 20
-/var/const/access_all_personal_lockers = 21
-/var/const/access_chapel_office = 22
-/var/const/access_tech_storage = 23
-/var/const/access_atmospherics = 24
-/var/const/access_bar = 25
-/var/const/access_janitor = 26
-/var/const/access_crematorium = 27
-/var/const/access_kitchen = 28
-/var/const/access_robotics = 29
-/var/const/access_rd = 30
-/var/const/access_cargo = 31
-/var/const/access_construction = 32
-/var/const/access_chemistry = 33
-/var/const/access_cargo_bot = 34
-/var/const/access_hydroponics = 35
-/var/const/access_manufacturing = 36
-/var/const/access_library = 37
-/var/const/access_lawyer = 38
-/var/const/access_virology = 39
-/var/const/access_cmo = 40
-/var/const/access_qm = 41
-/var/const/access_court = 42
-/var/const/access_clown = 43
-/var/const/access_mime = 44
-/var/const/access_surgery = 45
-/var/const/access_theatre = 46
-/var/const/access_research = 47
-/var/const/access_mining = 48
-/var/const/access_mining_office = 49 //not in use
-/var/const/access_mailsorting = 50
-/var/const/access_mint = 51
-/var/const/access_mint_vault = 52
-/var/const/access_heads_vault = 53
-/var/const/access_mining_station = 54
-/var/const/access_xenobiology = 55
-/var/const/access_ce = 56
-/var/const/access_hop = 57
-/var/const/access_hos = 58
-/var/const/access_RC_announce = 59 //Request console announcements
-/var/const/access_keycard_auth = 60 //Used for events which require at least two people to confirm them
-/var/const/access_tcomsat = 61 // has access to the entire telecomms satellite / machinery
-/var/const/access_gateway = 62
-/var/const/access_sec_doors = 63 // Security front doors
-/var/const/access_psychiatrist = 64 // Psychiatrist's office
-/var/const/access_xenoarch = 65
-/var/const/access_medical_equip = 66
-
- //BEGIN CENTCOM ACCESS
- /*Should leave plenty of room if we need to add more access levels.
-/var/const/Mostly for admin fun times.*/
-/var/const/access_cent_general = 101//General facilities.
-/var/const/access_cent_thunder = 102//Thunderdome.
-/var/const/access_cent_specops = 103//Special Ops.
-/var/const/access_cent_medical = 104//Medical/Research
-/var/const/access_cent_living = 105//Living quarters.
-/var/const/access_cent_storage = 106//Generic storage areas.
-/var/const/access_cent_teleporter = 107//Teleporter.
-/var/const/access_cent_creed = 108//Creed's office.
-/var/const/access_cent_captain = 109//Captain's office/ID comp/AI.
-
- //The Syndicate
-/var/const/access_syndicate = 150//General Syndicate Access
-
- //MONEY
-/var/const/access_crate_cash = 200
-
/obj/var/list/req_access = list()
/obj/var/list/req_one_access = list()
@@ -107,7 +21,7 @@
/obj/item/proc/GetAccess()
return list()
-/obj/item/proc/GetID()
+/obj/proc/GetID()
return null
/obj/proc/check_access(obj/item/I)
@@ -149,217 +63,98 @@
if("Supreme Commander")
return get_all_centcom_access()
+/var/list/datum/access/priv_all_access_datums
+/proc/get_all_access_datums()
+ if(!priv_all_access_datums)
+ priv_all_access_datums = init_subtypes(/datum/access)
+
+ return priv_all_access_datums
+
+/var/list/datum/access/priv_all_access_datums_assoc
+/proc/get_all_access_datums_assoc()
+ if(!priv_all_access_datums_assoc)
+ priv_all_access_datums_assoc = list()
+ for(var/datum/access/A in get_all_access_datums())
+ priv_all_access_datums_assoc["[A.id]"] = A
+
+ return priv_all_access_datums_assoc
+
+/proc/get_access_ids(var/access_types = ACCESS_TYPE_ALL)
+ var/list/L = new()
+ for(var/datum/access/A in get_all_access_datums())
+ if(A.access_type & access_types)
+ L += A.id
+ return L
+
+/var/list/priv_all_access
/proc/get_all_accesses()
- return list(access_security, access_sec_doors, access_brig, access_armory, access_forensics_lockers, access_court,
- access_medical, access_genetics, access_morgue, access_rd,
- access_tox, access_tox_storage, access_chemistry, access_engine, access_engine_equip, access_maint_tunnels,
- access_external_airlocks, access_change_ids, access_ai_upload,
- access_teleporter, access_eva, access_heads, access_captain, access_all_personal_lockers,
- access_tech_storage, access_chapel_office, access_atmospherics, access_kitchen,
- access_bar, access_janitor, access_crematorium, access_robotics, access_cargo, access_construction,
- access_hydroponics, access_library, access_lawyer, access_virology, access_psychiatrist, access_cmo, access_qm, access_clown, access_mime, access_surgery,
- access_theatre, access_research, access_mining, access_mailsorting,
- access_heads_vault, access_mining_station, access_xenobiology, access_ce, access_hop, access_hos, access_RC_announce,
- access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_medical_equip)
+ if(!priv_all_access)
+ priv_all_access = get_access_ids()
+ return priv_all_access
+
+/var/list/priv_station_access
+/proc/get_all_station_access()
+ if(!priv_station_access)
+ priv_station_access = get_access_ids(ACCESS_TYPE_STATION)
+
+ return priv_station_access
+
+/var/list/priv_centcom_access
/proc/get_all_centcom_access()
- return list(access_cent_general, access_cent_thunder, access_cent_specops, access_cent_medical, access_cent_living, access_cent_storage, access_cent_teleporter, access_cent_creed, access_cent_captain)
+ if(!priv_centcom_access)
+ priv_centcom_access = get_access_ids(ACCESS_TYPE_CENTCOM)
+ return priv_centcom_access
+
+/var/list/priv_syndicate_access
/proc/get_all_syndicate_access()
- return list(access_syndicate)
+ if(!priv_syndicate_access)
+ priv_syndicate_access = get_access_ids(ACCESS_TYPE_SYNDICATE)
+ return priv_syndicate_access
+
+/var/list/priv_region_access
/proc/get_region_accesses(var/code)
- switch(code)
- if(0)
- return get_all_accesses()
- if(1) //security
- return list(access_sec_doors, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_hos)
- if(2) //medbay
- return list(access_medical, access_medical_equip, access_genetics, access_morgue, access_chemistry, access_psychiatrist, access_virology, access_surgery, access_cmo)
- if(3) //research
- return list(access_research, access_tox, access_tox_storage, access_robotics, access_xenobiology, access_xenoarch, access_rd)
- if(4) //engineering and maintenance
- return list(access_construction, access_maint_tunnels, access_engine, access_engine_equip, access_external_airlocks, access_tech_storage, access_atmospherics, access_ce)
- if(5) //command
- return list(access_heads, access_RC_announce, access_keycard_auth, access_change_ids, access_ai_upload, access_teleporter, access_eva, access_tcomsat, access_gateway, access_all_personal_lockers, access_heads_vault, access_hop, access_captain)
- if(6) //station general
- return list(access_kitchen,access_bar, access_hydroponics, access_janitor, access_chapel_office, access_crematorium, access_library, access_theatre, access_lawyer, access_clown, access_mime)
- if(7) //supply
- return list(access_mailsorting, access_mining, access_mining_station, access_cargo, access_qm)
+ if(code == ACCESS_REGION_ALL)
+ return get_all_station_access()
+
+ if(!priv_region_access)
+ priv_region_access = list()
+ for(var/datum/access/A in get_all_access_datums())
+ if(!priv_region_access["[A.region]"])
+ priv_region_access["[A.region]"] = list()
+ priv_region_access["[A.region]"] += A.id
+
+ return priv_region_access["[code]"]
/proc/get_region_accesses_name(var/code)
switch(code)
- if(0)
+ if(ACCESS_REGION_ALL)
return "All"
- if(1) //security
+ if(ACCESS_REGION_SECURITY) //security
return "Security"
- if(2) //medbay
+ if(ACCESS_REGION_MEDBAY) //medbay
return "Medbay"
- if(3) //research
+ if(ACCESS_REGION_RESEARCH) //research
return "Research"
- if(4) //engineering and maintenance
+ if(ACCESS_REGION_ENGINEERING) //engineering and maintenance
return "Engineering"
- if(5) //command
+ if(ACCESS_REGION_COMMAND) //command
return "Command"
- if(6) //station general
+ if(ACCESS_REGION_GENERAL) //station general
return "Station General"
- if(7) //supply
+ if(ACCESS_REGION_SUPPLY) //supply
return "Supply"
+/proc/get_access_desc(id)
+ var/list/AS = get_all_access_datums_assoc()
+ var/datum/access/A = AS["[id]"]
-/proc/get_access_desc(A)
- switch(A)
- if(access_cargo)
- return "Cargo Bay"
- if(access_cargo_bot)
- return "Cargo Bot Delivery"
- if(access_security)
- return "Security Equipment"
- if(access_brig)
- return "Holding Cells"
- if(access_court)
- return "Courtroom"
- if(access_forensics_lockers)
- return "Forensics"
- if(access_medical)
- return "Medical"
- if(access_genetics)
- return "Genetics Lab"
- if(access_morgue)
- return "Morgue"
- if(access_tox)
- return "R&D Lab"
- if(access_tox_storage)
- return "Toxins Lab"
- if(access_chemistry)
- return "Chemistry Lab"
- if(access_rd)
- return "Research Director"
- if(access_bar)
- return "Bar"
- if(access_janitor)
- return "Custodial Closet"
- if(access_engine)
- return "Engineering"
- if(access_engine_equip)
- return "Power Equipment"
- if(access_maint_tunnels)
- return "Maintenance"
- if(access_external_airlocks)
- return "External Airlocks"
- if(access_emergency_storage)
- return "Emergency Storage"
- if(access_change_ids)
- return "ID Computer"
- if(access_ai_upload)
- return "AI Upload"
- if(access_teleporter)
- return "Teleporter"
- if(access_eva)
- return "EVA"
- if(access_heads)
- return "Bridge"
- if(access_captain)
- return "Captain"
- if(access_all_personal_lockers)
- return "Personal Lockers"
- if(access_chapel_office)
- return "Chapel Office"
- if(access_tech_storage)
- return "Technical Storage"
- if(access_atmospherics)
- return "Atmospherics"
- if(access_crematorium)
- return "Crematorium"
- if(access_armory)
- return "Armory"
- if(access_construction)
- return "Construction Areas"
- if(access_kitchen)
- return "Kitchen"
- if(access_hydroponics)
- return "Hydroponics"
- if(access_library)
- return "Library"
- if(access_lawyer)
- return "Law Office"
- if(access_robotics)
- return "Robotics"
- if(access_virology)
- return "Virology"
- if(access_psychiatrist)
- return "Psychiatrist's Office"
- if(access_cmo)
- return "Chief Medical Officer"
- if(access_qm)
- return "Quartermaster"
-/* if(access_clown)
- return "HONK! Access"
- if(access_mime)
- return "Silent Access"*/
- if(access_surgery)
- return "Surgery"
- if(access_theatre)
- return "Theatre"
- if(access_manufacturing)
- return "Manufacturing"
- if(access_research)
- return "Science"
- if(access_mining)
- return "Mining"
- if(access_mining_office)
- return "Mining Office"
- if(access_mailsorting)
- return "Cargo Office"
- if(access_mint)
- return "Mint"
- if(access_mint_vault)
- return "Mint Vault"
- if(access_heads_vault)
- return "Main Vault"
- if(access_mining_station)
- return "Mining EVA"
- if(access_xenobiology)
- return "Xenobiology Lab"
- if(access_xenoarch)
- return "Xenoarchaeology"
- if(access_hop)
- return "Head of Personnel"
- if(access_hos)
- return "Head of Security"
- if(access_ce)
- return "Chief Engineer"
- if(access_RC_announce)
- return "RC Announcements"
- if(access_keycard_auth)
- return "Keycode Auth. Device"
- if(access_tcomsat)
- return "Telecommunications"
- if(access_gateway)
- return "Gateway"
- if(access_sec_doors)
- return "Security"
+ return A ? A.desc : ""
/proc/get_centcom_access_desc(A)
- switch(A)
- if(access_cent_general)
- return "Code Grey"
- if(access_cent_thunder)
- return "Code Yellow"
- if(access_cent_storage)
- return "Code Orange"
- if(access_cent_living)
- return "Code Green"
- if(access_cent_medical)
- return "Code White"
- if(access_cent_teleporter)
- return "Code Blue"
- if(access_cent_specops)
- return "Code Black"
- if(access_cent_creed)
- return "Code Silver"
- if(access_cent_captain)
- return "Code Gold"
+ return get_access_desc(A)
/proc/get_all_jobs()
var/list/all_jobs = list()
@@ -403,12 +198,7 @@ proc/get_all_job_icons() //For all existing HUD icons
return joblist + list("Prisoner")
/obj/proc/GetJobName() //Used in secHUD icon generation
- var/obj/item/weapon/card/id/I
- if(istype(src, /obj/item/device/pda))
- var/obj/item/device/pda/P = src
- I = P.id
- else if(istype(src, /obj/item/weapon/card/id))
- I = src
+ var/obj/item/weapon/card/id/I = GetID()
if(I)
var/job_icons = get_all_job_icons()
diff --git a/code/game/jobs/access_datum.dm b/code/game/jobs/access_datum.dm
new file mode 100644
index 0000000000..d0855e4781
--- /dev/null
+++ b/code/game/jobs/access_datum.dm
@@ -0,0 +1,475 @@
+/datum/access
+ var/id = 0
+ var/desc = ""
+ var/region = ACCESS_REGION_NONE
+ var/access_type = ACCESS_TYPE_STATION
+
+/*****************
+* Station access *
+*****************/
+/var/const/access_security = 1
+/datum/access/security
+ id = access_security
+ desc = "Security Equipment"
+ region = ACCESS_REGION_SECURITY
+
+/var/const/access_brig = 2 // Brig timers and permabrig
+/datum/access/security
+ id = access_brig
+ desc = "Holding Cells"
+ region = ACCESS_REGION_SECURITY
+
+/var/const/access_armory = 3
+/datum/access/armory
+ id = access_armory
+ desc = "Armory"
+ region = ACCESS_REGION_SECURITY
+
+/var/const/access_forensics_lockers = 4
+/datum/access/forensics_lockers
+ id = access_forensics_lockers
+ desc = "Forensics"
+ region = ACCESS_REGION_SECURITY
+
+/var/const/access_medical = 5
+/datum/access/medical
+ id = access_medical
+ desc = "Medical"
+ region = ACCESS_REGION_MEDBAY
+
+/var/const/access_morgue = 6
+/datum/access/morgue
+ id = access_morgue
+ desc = "Morgue"
+ region = ACCESS_REGION_MEDBAY
+
+/var/const/access_tox = 7
+/datum/access/tox
+ id = access_tox
+ desc = "R&D Lab"
+ region = ACCESS_REGION_RESEARCH
+
+/var/const/access_tox_storage = 8
+/datum/access/tox_storage
+ id = access_tox_storage
+ desc = "Toxins Lab"
+ region = ACCESS_REGION_RESEARCH
+
+/var/const/access_genetics = 9
+/datum/access/genetics
+ id = access_genetics
+ desc = "Genetics Lab"
+ region = ACCESS_REGION_MEDBAY
+
+/var/const/access_engine = 10
+/datum/access/engine
+ id = access_engine
+ desc = "Engineering"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_engine_equip = 11
+/datum/access/engine_equip
+ id = access_engine_equip
+ desc = "Engine Room"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_maint_tunnels = 12
+/datum/access/maint_tunnels
+ id = access_maint_tunnels
+ desc = "Maintenance"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_external_airlocks = 13
+/datum/access/external_airlocks
+ id = access_external_airlocks
+ desc = "External Airlocks"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_emergency_storage = 14
+/datum/access/emergency_storage
+ id = access_emergency_storage
+ desc = "Emergency Storage"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_change_ids = 15
+/datum/access/change_ids
+ id = access_change_ids
+ desc = "ID Computer"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_ai_upload = 16
+/datum/access/ai_upload
+ id = access_ai_upload
+ desc = "AI Upload"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_teleporter = 17
+/datum/access/teleporter
+ id = access_teleporter
+ desc = "Teleporter"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_eva = 18
+/datum/access/eva
+ id = access_eva
+ desc = "EVA"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_heads = 19
+/datum/access/heads
+ id = access_heads
+ desc = "Bridge"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_captain = 20
+/datum/access/captain
+ id = access_captain
+ desc = "Captain"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_all_personal_lockers = 21
+/datum/access/all_personal_lockers
+ id = access_all_personal_lockers
+ desc = "Personal Lockers"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_chapel_office = 22
+/datum/access/chapel_office
+ id = access_chapel_office
+ desc = "Chapel Office"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_tech_storage = 23
+/datum/access/tech_storage
+ id = access_tech_storage
+ desc = "Technical Storage"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_atmospherics = 24
+/datum/access/atmospherics
+ id = access_atmospherics
+ desc = "Atmospherics"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_bar = 25
+/datum/access/bar
+ id = access_bar
+ desc = "Bar"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_janitor = 26
+/datum/access/janitor
+ id = access_janitor
+ desc = "Custodial Closet"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_crematorium = 27
+/datum/access/crematorium
+ id = access_crematorium
+ desc = "Crematorium"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_kitchen = 28
+/datum/access/kitchen
+ id = access_kitchen
+ desc = "Kitchen"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_robotics = 29
+/datum/access/robotics
+ id = access_robotics
+ desc = "Robotics"
+ region = ACCESS_REGION_RESEARCH
+
+/var/const/access_rd = 30
+/datum/access/rd
+ id = access_rd
+ desc = "Research Director"
+ region = ACCESS_REGION_RESEARCH
+
+/var/const/access_cargo = 31
+/datum/access/cargo
+ id = access_cargo
+ desc = "Cargo Bay"
+ region = ACCESS_REGION_SUPPLY
+
+/var/const/access_construction = 32
+/datum/access/construction
+ id = access_construction
+ desc = "Construction Areas"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_chemistry = 33
+/datum/access/chemistry
+ id = access_chemistry
+ desc = "Chemistry Lab"
+ region = ACCESS_REGION_MEDBAY
+
+/var/const/access_cargo_bot = 34
+/datum/access/cargo_bot
+ id = access_cargo_bot
+ desc = "Cargo Bot Delivery"
+ region = ACCESS_REGION_SUPPLY
+
+/var/const/access_hydroponics = 35
+/datum/access/hydroponics
+ id = access_hydroponics
+ desc = "Hydroponics"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_manufacturing = 36
+/datum/access/manufacturing
+ id = access_manufacturing
+ desc = "Manufacturing"
+ access_type = ACCESS_TYPE_NONE
+
+/var/const/access_library = 37
+/datum/access/library
+ id = access_library
+ desc = "Library"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_lawyer = 38
+/datum/access/lawyer
+ id = access_lawyer
+ desc = "Law Office"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_virology = 39
+/datum/access/virology
+ id = access_virology
+ desc = "Virology"
+ region = ACCESS_REGION_MEDBAY
+
+/var/const/access_cmo = 40
+/datum/access/cmo
+ id = access_cmo
+ desc = "Chief Medical Officer"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_qm = 41
+/datum/access/qm
+ id = access_qm
+ desc = "Quartermaster"
+ region = ACCESS_REGION_SUPPLY
+
+/var/const/access_court = 42
+/datum/access/court
+ id = access_court
+ desc = "Courtroom"
+ region = ACCESS_REGION_SECURITY
+
+/var/const/access_clown = 43
+/datum/access/clown
+ id = access_clown
+ desc = "HONK! Access"
+
+/var/const/access_mime = 44
+/datum/access/mime
+ id = access_mime
+ desc = "Silent Access"
+
+/var/const/access_surgery = 45
+/datum/access/surgery
+ id = access_surgery
+ desc = "Surgery"
+ region = ACCESS_REGION_MEDBAY
+
+/var/const/access_theatre = 46
+/datum/access/theatre
+ id = access_theatre
+ desc = "Theatre"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_research = 47
+/datum/access/research
+ id = access_research
+ desc = "Science"
+ region = ACCESS_REGION_RESEARCH
+
+/var/const/access_mining = 48
+/datum/access/mining
+ id = access_mining
+ desc = "Mining"
+ region = ACCESS_REGION_SUPPLY
+
+/var/const/access_mining_office = 49
+/datum/access/mining_office
+ id = access_mining_office
+ desc = "Mining Office"
+ access_type = ACCESS_TYPE_NONE
+
+/var/const/access_mailsorting = 50
+/datum/access/mailsorting
+ id = access_mailsorting
+ desc = "Cargo Office"
+ region = ACCESS_REGION_SUPPLY
+
+/var/const/access_mint = 51
+/datum/access/mint
+ id = access_mint
+ desc = "Mint"
+ region = ACCESS_REGION_SUPPLY
+
+/var/const/access_mint_vault = 52
+/datum/access/mint_vault
+ id = access_mint_vault
+ desc = "Mint Vault"
+ access_type = ACCESS_TYPE_NONE
+
+/var/const/access_heads_vault = 53
+/datum/access/heads_vault
+ id = access_heads_vault
+ desc = "Main Vault"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_mining_station = 54
+/datum/access/mining_station
+ id = access_mining_station
+ desc = "Mining EVA"
+ region = ACCESS_REGION_SUPPLY
+
+/var/const/access_xenobiology = 55
+/datum/access/xenobiology
+ id = access_xenobiology
+ desc = "Xenobiology Lab"
+ region = ACCESS_REGION_RESEARCH
+
+/var/const/access_ce = 56
+/datum/access/ce
+ id = access_ce
+ desc = "Chief Engineer"
+ region = ACCESS_REGION_ENGINEERING
+
+/var/const/access_hop = 57
+/datum/access/hop
+ id = access_hop
+ desc = "Head of Personnel"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_hos = 58
+/datum/access/hos
+ id = access_hos
+ desc = "Head of Security"
+ region = ACCESS_REGION_SECURITY
+
+/var/const/access_RC_announce = 59 //Request console announcements
+/datum/access/RC_announce
+ id = access_RC_announce
+ desc = "RC Announcements"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_keycard_auth = 60 //Used for events which require at least two people to confirm them
+/datum/access/keycard_auth
+ id = access_keycard_auth
+ desc = "Keycode Auth. Device"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_tcomsat = 61 // has access to the entire telecomms satellite / machinery
+/datum/access/tcomsat
+ id = access_tcomsat
+ desc = "Telecommunications"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_gateway = 62
+/datum/access/gateway
+ id = access_gateway
+ desc = "Gateway"
+ region = ACCESS_REGION_COMMAND
+
+/var/const/access_sec_doors = 63 // Security front doors
+/datum/access/sec_doors
+ id = access_sec_doors
+ desc = "Security"
+ region = ACCESS_REGION_SECURITY
+
+/var/const/access_psychiatrist = 64 // Psychiatrist's office
+/datum/access/psychiatrist
+ id = access_psychiatrist
+ desc = "Psychiatrist's Office"
+ region = ACCESS_REGION_MEDBAY
+
+/var/const/access_xenoarch = 65
+/datum/access/xenoarch
+ id = access_xenoarch
+ desc = "Xenoarchaeology"
+ region = ACCESS_REGION_RESEARCH
+
+/var/const/access_medical_equip = 66
+/datum/access/medical_equip
+ id = access_medical_equip
+ desc = "Medical Equipment"
+ region = ACCESS_REGION_MEDBAY
+
+/******************
+* Central Command *
+******************/
+/var/const/access_cent_general = 101//General facilities.
+/datum/access/cent_general
+ id = access_cent_general
+ desc = "Code Grey"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/var/const/access_cent_thunder = 102//Thunderdome.
+/datum/access/cent_thunder
+ id = access_cent_thunder
+ desc = "Code Yellow"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/var/const/access_cent_specops = 103//Special Ops.
+/datum/access/cent_specops
+ id = access_cent_specops
+ desc = "Code Black"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/var/const/access_cent_medical = 104//Medical/Research
+/datum/access/cent_medical
+ id = access_cent_medical
+ desc = "Code White"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/var/const/access_cent_living = 105//Living quarters.
+/datum/access/cent_living
+ id = access_cent_living
+ desc = "Code Green"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/var/const/access_cent_storage = 106//Generic storage areas.
+/datum/access/cent_storage
+ id = access_cent_storage
+ desc = "Code Orange"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/var/const/access_cent_teleporter = 107//Teleporter.
+/datum/access/cent_teleporter
+ id = access_cent_teleporter
+ desc = "Code Blue"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/var/const/access_cent_creed = 108//Creed's office.
+/datum/access/cent_creed
+ id = access_cent_creed
+ desc = "Code Silver"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/var/const/access_cent_captain = 109//Captain's office/ID comp/AI.
+/datum/access/cent_captain
+ id = access_cent_captain
+ desc = "Code Gold"
+ access_type = ACCESS_TYPE_CENTCOM
+
+/***************
+* Antag access *
+***************/
+/var/const/access_syndicate = 150//General Syndicate Access
+/datum/access/syndicate
+ id = access_syndicate
+ access_type = ACCESS_TYPE_SYNDICATE
+
+/*******
+* Misc *
+*******/
+/var/const/access_crate_cash = 200
+/datum/access/crate_cash
+ id = access_crate_cash
+ access_type = ACCESS_TYPE_NONE
diff --git a/code/game/jobs/departments.dm b/code/game/jobs/departments.dm
deleted file mode 100644
index f424d03a1a..0000000000
--- a/code/game/jobs/departments.dm
+++ /dev/null
@@ -1 +0,0 @@
-var/list/departments = list("Command", "Medical", "Engineering", "Security", "Civilian", "Cargo")
\ No newline at end of file
diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm
index 4b9d72ff51..f76ef8edb4 100644
--- a/code/game/jobs/job/captain.dm
+++ b/code/game/jobs/job/captain.dm
@@ -42,7 +42,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
return 1
get_access()
- return get_all_accesses()
+ return get_all_station_access()
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index ab991f2fea..092307e1b4 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -183,7 +183,7 @@
if(is_authenticated())
var/access_type = text2num(href_list["access_target"])
var/access_allowed = text2num(href_list["allowed"])
- if(access_type in (is_centcom() ? get_all_centcom_access() : get_all_accesses()))
+ if(access_type in (is_centcom() ? get_all_centcom_access() : get_all_station_access()))
modify.access -= access_type
if(!access_allowed)
modify.access += access_type
diff --git a/code/game/machinery/computer3/laptop.dm b/code/game/machinery/computer3/laptop.dm
index 0fede0f479..ccd63aef36 100644
--- a/code/game/machinery/computer3/laptop.dm
+++ b/code/game/machinery/computer3/laptop.dm
@@ -55,19 +55,11 @@
qdel(src)
return
- if(!stored_computer.manipulating)
- stored_computer.manipulating = 1
- stored_computer.loc = loc
- stored_computer.stat &= ~MAINT
- stored_computer.update_icon()
- loc = null
- usr << "You open \the [src]."
-
- spawn(5)
- stored_computer.manipulating = 0
- qdel(src)
- else
- usr << "You are already opening the computer!"
+ stored_computer.loc = loc
+ stored_computer.stat &= ~MAINT
+ stored_computer.update_icon()
+ loc = stored_computer
+ usr << "You open \the [src]."
AltClick()
@@ -82,12 +74,10 @@
if(stored_computer)
stored_computer.eject_id()
-
/obj/machinery/computer3/laptop/verb/eject_id()
set category = "Object"
set name = "Eject ID Card"
set src in oview(1)
-
var/obj/item/part/computer/cardslot/C = locate() in src.contents
if(!C)
@@ -104,7 +94,7 @@
return
usr << "You remove [card] from the laptop."
- C.remove(card)
+ C.remove(4)
/obj/machinery/computer3/laptop
@@ -117,7 +107,6 @@
pixel_y = -3
show_keyboard = 0
- var/manipulating = 0 // To prevent disappearing bug
var/obj/item/device/laptop/portable = null
New(var/L, var/built = 0)
@@ -157,12 +146,11 @@
portable=new
portable.stored_computer = src
- if(!manipulating)
- portable.loc = loc
- loc = portable
- stat |= MAINT
- if(user)
- user << "You close \the [src]."
+ portable.loc = loc
+ loc = portable
+ stat |= MAINT
+ if(user)
+ user << "You close \the [src]."
auto_use_power()
if(stat&MAINT)
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index fbb6e8b10c..3ea9b5157f 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -393,9 +393,9 @@
occupant.ckey = null
//Make an announcement and log the person entering storage.
- control_computer.frozen_crew += "[occupant.real_name]"
+ control_computer.frozen_crew += "[occupant.real_name], [occupant.mind.assigned_role] - [worldtime2text()]"
- announce.autosay("[occupant.real_name] [on_store_message]", "[on_store_name]")
+ announce.autosay("[occupant.real_name], [occupant.mind.assigned_role] [on_store_message]", "[on_store_name]")
visible_message("\The [initial(name)] hums and hisses as it moves [occupant.real_name] into storage.", 3)
// Delete the mob.
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 0d9ce8b7f8..8f3a5ca621 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1070,7 +1070,8 @@ About the new airlock wires panel:
update_icon()
/obj/machinery/door/airlock/proc/prison_open()
- src.unlock()
- src.open()
- src.lock()
+ if(arePowerSystemsOn())
+ src.unlock()
+ src.open()
+ src.lock()
return
diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm
index 80b36d30f9..e69f750a5f 100644
--- a/code/game/machinery/doors/airlock_electronics.dm
+++ b/code/game/machinery/doors/airlock_electronics.dm
@@ -42,7 +42,7 @@
t1 += "
"
- var/list/accesses = get_all_accesses()
+ var/list/accesses = get_all_station_access()
for (var/acc in accesses)
var/aname = get_access_desc(acc)
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 3f4e1fbd75..ca0b150fe6 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -1,6 +1,22 @@
/******************** Requests Console ********************/
/** Originally written by errorage, updated by: Carn, needs more work though. I just added some security fixes */
+//Request Console Department Types
+#define RC_ASSIST 1 //Request Assistance
+#define RC_SUPPLY 2 //Request Supplies
+#define RC_INFO 4 //Relay Info
+
+//Request Console Screens
+#define RCS_RQASSIST 1 // Request supplies
+#define RCS_RQSUPPLY 2 // Request assistance
+#define RCS_SENDINFO 3 // Relay information
+#define RCS_SENTPASS 4 // Message sent successfully
+#define RCS_SENTFAIL 5 // Message sent unsuccessfully
+#define RCS_VIEWMSGS 6 // View messages
+#define RCS_MESSAUTH 7 // Authentication before sending
+#define RCS_ANNOUNCE 8 // Send announcement
+#define RCS_MAINMENU 9 // Main menu
+
var/req_console_assistance = list()
var/req_console_supplies = list()
var/req_console_information = list()
@@ -14,32 +30,13 @@ var/list/obj/machinery/requests_console/allConsoles = list()
icon_state = "req_comp0"
var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department
var/list/messages = list() //List of all messages
- var/departmentType = 0
- // 0 = none (not listed, can only repeplied to)
- // 1 = assistance
- // 2 = supplies
- // 3 = info
- // 4 = ass + sup //Erro goddamn you just HAD to shorten "assistance" down to "ass"
- // 5 = ass + info
- // 6 = sup + info
- // 7 = ass + sup + info
+ var/departmentType = 0 //Bitflag. Zero is reply-only. Map currently uses raw numbers instead of defines.
var/newmessagepriority = 0
// 0 = no new message
// 1 = normal priority
// 2 = high priority
// 3 = extreme priority - not implemented, will probably require some hacking... everything needs to have a hidden feature in this game.
- var/screen = 0
- // 0 = main menu,
- // 1 = req. assistance,
- // 2 = req. supplies
- // 3 = relay information
- // 4 = write msg - not used
- // 5 = choose priority - not used
- // 6 = sent successfully
- // 7 = sent unsuccessfully
- // 8 = view messages
- // 9 = authentication before sending
- // 10 = send announcement
+ var/screen = RCS_MAINMENU
var/silent = 0 // set to 1 for it not to beep all the time
// var/hackState = 0
// 0 = not hacked
@@ -77,49 +74,26 @@ var/list/obj/machinery/requests_console/allConsoles = list()
name = "[department] Requests Console"
allConsoles += src
- //req_console_departments += department
- switch(departmentType)
- if(1)
- req_console_assistance |= department
- if(2)
- req_console_supplies |= department
- if(3)
- req_console_information |= department
- if(4)
- req_console_assistance |= department
- req_console_supplies |= department
- if(5)
- req_console_assistance |= department
- req_console_information |= department
- if(6)
- req_console_supplies |= department
- req_console_information |= department
- if(7)
- req_console_assistance |= department
- req_console_supplies |= department
- req_console_information |= department
+ if (departmentType & RC_ASSIST)
+ req_console_assistance |= department
+ if (departmentType & RC_SUPPLY)
+ req_console_supplies |= department
+ if (departmentType & RC_INFO)
+ req_console_information |= department
/obj/machinery/requests_console/Destroy()
allConsoles -= src
- switch(departmentType)
- if(1)
- req_console_assistance -= department
- if(2)
- req_console_supplies -= department
- if(3)
- req_console_information -= department
- if(4)
- req_console_assistance -= department
- req_console_supplies -= department
- if(5)
- req_console_assistance -= department
- req_console_information -= department
- if(6)
- req_console_supplies -= department
- req_console_information -= department
- if(7)
+ var/lastDeptRC = 1
+ for (var/obj/machinery/requests_console/Console in allConsoles)
+ if (Console.department == department)
+ lastDeptRC = 0
+ break
+ if(lastDeptRC)
+ if (departmentType & RC_ASSIST)
req_console_assistance -= department
+ if (departmentType & RC_SUPPLY)
req_console_supplies -= department
+ if (departmentType & RC_INFO)
req_console_information -= department
..()
@@ -130,7 +104,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
dat = text("
Requests Console[department] Requests Console
")
if(!open)
switch(screen)
- if(1) //req. assistance
+ if(RCS_RQASSIST) //req. assistance
dat += text("Which department do you need assistance from?
")
for(var/dpt in req_console_assistance)
if (dpt != department)
@@ -139,9 +113,9 @@ var/list/obj/machinery/requests_console/allConsoles = list()
// if (hackState == 1)
// dat += text(" or EXTREME)")
dat += text(")
")
- dat += text("
Back
")
+ dat += text("
Back
")
- if(2) //req. supplies
+ if(RCS_RQSUPPLY) //req. supplies
dat += text("Which department do you need supplies from?
")
for(var/dpt in req_console_supplies)
if (dpt != department)
@@ -150,9 +124,9 @@ var/list/obj/machinery/requests_console/allConsoles = list()
// if (hackState == 1)
// dat += text(" or EXTREME)")
dat += text(")
")
- dat += text("
Back
")
+ dat += text("
Back
")
- if(3) //relay information
+ if(RCS_SENDINFO) //relay information
dat += text("Which department would you like to send information to?
")
for(var/dpt in req_console_information)
if (dpt != department)
@@ -161,17 +135,17 @@ var/list/obj/machinery/requests_console/allConsoles = list()
// if (hackState == 1)
// dat += text(" or EXTREME)")
dat += text(")
")
- dat += text("
Back
")
+ dat += text("
Back
")
- if(6) //sent successfully
+ if(RCS_SENTPASS) //sent successfully
dat += text("Message sent
")
- dat += text("Continue
")
+ dat += text("Continue
")
- if(7) //unsuccessful; not sent
+ if(RCS_SENTFAIL) //unsuccessful; not sent
dat += text("An error occurred.
")
- dat += text("Continue
")
+ dat += text("Continue
")
- if(8) //view messages
+ if(RCS_VIEWMSGS) //view messages
for (var/obj/machinery/requests_console/Console in allConsoles)
if (Console.department == department)
Console.newmessagepriority = 0
@@ -181,18 +155,18 @@ var/list/obj/machinery/requests_console/allConsoles = list()
icon_state = "req_comp0"
for(var/msg in messages)
dat += text("[msg]
")
- dat += text("Back to main menu
")
+ dat += text("Back to main menu
")
- if(9) //authentication before sending
+ if(RCS_MESSAUTH) //authentication before sending
dat += text("Message Authentication
")
dat += text("Message for [dpt]: [message]
")
dat += text("You may authenticate your message now by scanning your ID or your stamp
")
dat += text("Validated by: [msgVerified]
");
dat += text("Stamped by: [msgStamped]
");
dat += text("Send
");
- dat += text("
Back
")
+ dat += text("
Back
")
- if(10) //send announcement
+ if(RCS_ANNOUNCE) //send announcement
dat += text("Station wide announcement
")
if(announceAuth)
dat += text("Authentication accepted
")
@@ -201,22 +175,22 @@ var/list/obj/machinery/requests_console/allConsoles = list()
dat += text("Message: [message] Write
")
if (announceAuth && message)
dat += text("Announce
");
- dat += text("
Back
")
+ dat += text("
Back
")
else //main menu
- screen = 0
+ screen = RCS_MAINMENU
reset_announce()
if (newmessagepriority == 1)
dat += text("There are new messages
")
if (newmessagepriority == 2)
dat += text("NEW PRIORITY MESSAGES
")
- dat += text("View Messages
")
+ dat += text("View Messages
")
- dat += text("Request Assistance
")
- dat += text("Request Supplies
")
- dat += text("Relay Anonymous Information
")
+ dat += text("Request Assistance
")
+ dat += text("Request Supplies
")
+ dat += text("Relay Anonymous Information
")
if(announcementConsole)
- dat += text("Send station-wide announcement
")
+ dat += text("Send station-wide announcement
")
if (silent)
dat += text("Speaker OFF")
else
@@ -237,7 +211,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
- screen = 9
+ screen = RCS_MESSAUTH
switch(href_list["priority"])
if("2") priority = 2
else priority = -1
@@ -245,7 +219,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
dpt = "";
msgVerified = ""
msgStamped = ""
- screen = 0
+ screen = RCS_MAINMENU
priority = -1
if(href_list["writeAnnouncement"])
@@ -257,107 +231,41 @@ var/list/obj/machinery/requests_console/allConsoles = list()
else priority = -1
else
reset_announce()
- screen = 0
+ screen = RCS_MAINMENU
if(href_list["sendAnnouncement"])
if(!announcementConsole) return
announcement.Announce(message, msg_sanitized = 1)
reset_announce()
- screen = 0
+ screen = RCS_MAINMENU
if( href_list["department"] && message )
var/log_msg = message
- var/sending = message
- sending += "
"
- if (msgVerified)
- sending += msgVerified
- sending += "
"
- if (msgStamped)
- sending += msgStamped
- sending += "
"
- screen = 7 //if it's successful, this will get overrwritten (7 = unsufccessfull, 6 = successfull)
- if (sending)
- var/pass = 0
- for (var/obj/machinery/message_server/MS in world)
- if(!MS.active) continue
- MS.send_rc_message(href_list["department"],department,log_msg,msgStamped,msgVerified,priority)
- pass = 1
-
- if(pass)
-
- for (var/obj/machinery/requests_console/Console in allConsoles)
- if (ckey(Console.department) == ckey(href_list["department"]))
-
- switch(priority)
- if("2") //High priority
- if(Console.newmessagepriority < 2)
- Console.newmessagepriority = 2
- Console.icon_state = "req_comp2"
- if(!Console.silent)
- playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(5, Console.loc))
- O.show_message(text("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [department]'"))
- Console.messages += "High Priority message from [department]
[sending]"
-
- // if("3") //Not implemanted, but will be //Removed as it doesn't look like anybody intends on implimenting it ~Carn
- // if(Console.newmessagepriority < 3)
- // Console.newmessagepriority = 3
- // Console.icon_state = "req_comp3"
- // if(!Console.silent)
- // playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1)
- // for (var/mob/O in hearers(7, Console.loc))
- // O.show_message(text("\icon[Console] *The Requests Console yells: 'EXTREME PRIORITY alert in [department]'"))
- // Console.messages += "Extreme Priority message from [ckey(department)]
[message]"
-
- else // Normal priority
- if(Console.newmessagepriority < 1)
- Console.newmessagepriority = 1
- Console.icon_state = "req_comp1"
- if(!Console.silent)
- playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(4, Console.loc))
- O.show_message(text("\icon[Console] *The Requests Console beeps: 'Message from [department]'"))
- Console.messages += "Message from [department]
[message]"
-
- screen = 6
- Console.set_light(2)
- messages += "Message sent to [dpt]
[message]"
- else
- for (var/mob/O in hearers(4, src.loc))
- O.show_message(text("\icon[src] *The Requests Console beeps: 'NOTICE: No server detected!'"))
+ var/pass = 0
+ screen = RCS_SENTFAIL
+ for (var/obj/machinery/message_server/MS in world)
+ if(!MS.active) continue
+ MS.send_rc_message(href_list["department"],department,log_msg,msgStamped,msgVerified,priority)
+ pass = 1
+ if(pass)
+ screen = RCS_SENTPASS
+ messages += "Message sent to [dpt]
[message]"
+ else
+ audible_message(text("\icon[src] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
//Handle screen switching
- switch(text2num(href_list["setScreen"]))
- if(null) //skip
- if(1) //req. assistance
- screen = 1
- if(2) //req. supplies
- screen = 2
- if(3) //relay information
- screen = 3
-// if(4) //write message
-// screen = 4
- if(5) //choose priority
- screen = 5
- if(6) //sent successfully
- screen = 6
- if(7) //unsuccessfull; not sent
- screen = 7
- if(8) //view messages
- screen = 8
- if(9) //authentication
- screen = 9
- if(10) //send announcement
- if(!announcementConsole) return
- screen = 10
- else //main menu
+ var/tempScreen = text2num(href_list["setScreen"])
+ if(tempScreen)
+ if(tempScreen == RCS_ANNOUNCE && !announcementConsole)
+ return
+ if(tempScreen == RCS_MAINMENU)
dpt = ""
msgVerified = ""
msgStamped = ""
message = ""
priority = -1
- screen = 0
+ screen = tempScreen
//Handle silencing the console
switch( href_list["setSilent"] )
@@ -393,11 +301,11 @@ var/list/obj/machinery/requests_console/allConsoles = list()
user << "You can't do much with that."*/
if (istype(O, /obj/item/weapon/card/id))
- if(screen == 9)
+ if(screen == RCS_MESSAUTH)
var/obj/item/weapon/card/id/T = O
msgVerified = text("Verified by [T.registered_name] ([T.assignment])")
updateUsrDialog()
- if(screen == 10)
+ if(screen == RCS_ANNOUNCE)
var/obj/item/weapon/card/id/ID = O
if (access_RC_announce in ID.GetAccess())
announceAuth = 1
@@ -407,7 +315,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
user << "You are not authorized to send announcements."
updateUsrDialog()
if (istype(O, /obj/item/weapon/stamp))
- if(screen == 9)
+ if(screen == RCS_MESSAUTH)
var/obj/item/weapon/stamp/T = O
msgStamped = text("Stamped with the [T.name]")
updateUsrDialog()
@@ -417,3 +325,13 @@ var/list/obj/machinery/requests_console/allConsoles = list()
announceAuth = 0
message = ""
announcement.announcer = ""
+
+#undef RCS_RQASSIST
+#undef RCS_RQSUPPLY
+#undef RCS_SENDINFO
+#undef RCS_SENTPASS
+#undef RCS_SENTFAIL
+#undef RCS_VIEWMSGS
+#undef RCS_MESSAUTH
+#undef RCS_ANNOUNCE
+#undef RCS_MAINMENU
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index f805783f70..284bce3a33 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -287,7 +287,7 @@
if(do_after_cooldown(target))
if(disabled) return
chassis.spark_system.start()
- target:ChangeTurf(/turf/space)
+ target:ChangeTurf(get_base_turf(target.z))
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
chassis.use_power(energy_drain)
else if (istype(target, /obj/machinery/door/airlock))
@@ -300,7 +300,7 @@
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
chassis.use_power(energy_drain)
if(1)
- if(istype(target, /turf/space))
+ if(istype(target, /turf/space) || istype(target,get_base_turf(target.z)))
occupant_message("Building Floor...")
set_ready_state(0)
if(do_after_cooldown(target))
diff --git a/code/game/objects/items/stacks/tiles/plasteel.dm b/code/game/objects/items/stacks/tiles/plasteel.dm
index 2932b1f398..d96c14854f 100644
--- a/code/game/objects/items/stacks/tiles/plasteel.dm
+++ b/code/game/objects/items/stacks/tiles/plasteel.dm
@@ -26,28 +26,9 @@
stacktype = /obj/item/stack/tile/plasteel
build_type = /obj/item/stack/tile/plasteel
-/*
-/obj/item/stack/tile/plasteel/attack_self(mob/user as mob)
- if (usr.stat)
- return
- var/T = user.loc
- if (!( istype(T, /turf) ))
- user << "You must be on the ground!"
- return
- if (!( istype(T, /turf/space) ))
- user << "You cannot build on or repair this turf!"
- return
- src.build(T)
- src.add_fingerprint(user)
- use(1)
- return
-*/
-
/obj/item/stack/tile/plasteel/proc/build(turf/S as turf)
if (istype(S,/turf/space))
S.ChangeTurf(/turf/simulated/floor/plating/airless)
else
S.ChangeTurf(/turf/simulated/floor/plating)
-// var/turf/simulated/floor/W = S.ReplaceWithFloor()
-// W.make_plating()
return
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index 9784709c51..245f9201a0 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -100,7 +100,7 @@
build_delay = 50
build_type = "airlock"
build_other = /obj/machinery/door/airlock
- else if(!deconstruct && istype(T,/turf/space))
+ else if(!deconstruct && (istype(T,/turf/space) || istype(T,get_base_turf(T.z))))
build_cost = 1
build_type = "floor"
build_turf = /turf/simulated/floor/plating/airless
@@ -114,7 +114,7 @@
build_delay = deconstruct ? 50 : 20
build_cost = deconstruct ? 10 : 3
build_type = deconstruct ? "floor" : "wall"
- build_turf = deconstruct ? /turf/space : /turf/simulated/wall
+ build_turf = deconstruct ? get_base_turf(T.z) : /turf/simulated/wall
else
return 0
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 240915adba..3c2b02feed 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -270,7 +270,7 @@
registered_name = "Captain"
assignment = "Captain"
New()
- access = get_all_accesses()
+ access = get_all_station_access()
..()
/obj/item/weapon/card/id/centcom
@@ -289,4 +289,4 @@
/obj/item/weapon/card/id/centcom/ERT/New()
..()
- access += get_all_accesses()
+ access += get_all_station_access()
diff --git a/code/game/objects/items/weapons/scrolls.dm b/code/game/objects/items/weapons/scrolls.dm
index 618598c182..05709898d6 100644
--- a/code/game/objects/items/weapons/scrolls.dm
+++ b/code/game/objects/items/weapons/scrolls.dm
@@ -11,6 +11,10 @@
origin_tech = list(TECH_BLUESPACE = 4)
/obj/item/weapon/teleportation_scroll/attack_self(mob/user as mob)
+ if((user.mind && !wizards.is_antagonist(user.mind)))
+ usr << "You stare at the scroll but cannot make sense of the markings!"
+ return
+
user.set_machine(src)
var/dat = "Teleportation Scroll:
"
dat += "Number of uses: [src.uses]
"
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 65038649d4..95c4191622 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -24,7 +24,7 @@
desc = "It's just an ordinary box."
icon_state = "box"
item_state = "syringe_kit"
- var/foldable = null // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
+ var/foldable = /obj/item/stack/material/cardboard // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
// BubbleWrap - A box can be folded up to make card
/obj/item/weapon/storage/box/attack_self(mob/user as mob)
@@ -598,7 +598,6 @@
icon_state = "light"
desc = "This box is shaped on the inside so that only light tubes and bulbs fit."
item_state = "syringe_kit"
- foldable = /obj/item/stack/material/cardboard //BubbleWrap
storage_slots=21
can_hold = list(/obj/item/weapon/light/tube, /obj/item/weapon/light/bulb)
max_storage_space = 42 //holds 21 items of w_class 2
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
index df2985c42e..55cd3b51ca 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
@@ -41,7 +41,7 @@
open()
else
src.req_access = list()
- src.req_access += pick(get_all_accesses())
+ src.req_access += pick(get_all_station_access())
..()
/obj/structure/closet/secure_closet/proc/togglelock(mob/user as mob)
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 96bdae2336..ad28bb4019 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -222,7 +222,7 @@
open()
else
src.req_access = list()
- src.req_access += pick(get_all_accesses())
+ src.req_access += pick(get_all_station_access())
..()
/obj/structure/closet/crate/plastic
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index fd0da17290..96f5466684 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -3,6 +3,10 @@
var/wet = 0
var/image/wet_overlay = null
+ //Mining resources (for the large drills).
+ var/has_resources
+ var/list/resources
+
var/thermite = 0
oxygen = MOLES_O2STANDARD
nitrogen = MOLES_N2STANDARD
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index a81ca19c52..27e47dac21 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -80,14 +80,14 @@ var/list/wood_icons = list("wood","wood-broken")
//set src in oview(1)
switch(severity)
if(1.0)
- src.ChangeTurf(/turf/space)
+ src.ChangeTurf(get_base_turf(src.z))
if(2.0)
switch(pick(40;1,40;2,3))
if (1)
if(prob(33)) new /obj/item/stack/material/steel(src)
src.ReplaceWithLattice()
if(2)
- src.ChangeTurf(/turf/space)
+ src.ChangeTurf(get_base_turf(src.z))
if(3)
if(prob(33)) new /obj/item/stack/material/steel(src)
if(prob(80))
diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm
index f5b32cb121..29f07579c9 100644
--- a/code/game/turfs/simulated/floor_types.dm
+++ b/code/game/turfs/simulated/floor_types.dm
@@ -9,6 +9,13 @@
..()
name = "floor"
+/turf/simulated/floor/airless/lava
+ name = "lava"
+ icon_state = "lava"
+ lava = 1
+ light_range = 2
+ light_color = "#CC0000"
+
/turf/simulated/floor/airless/ceiling
icon_state = "rockvault"
@@ -151,6 +158,11 @@
oxygen = 0
nitrogen = MOLES_N2STANDARD + MOLES_O2STANDARD
+/turf/simulated/floor/snow
+ name = "Snow"
+ icon = 'icons/turf/snow.dmi'
+ icon_state = "snow"
+
/turf/simulated/floor/beach
name = "Beach"
icon = 'icons/misc/beach.dmi'
@@ -159,6 +171,9 @@
name = "Sand"
icon_state = "sand"
+/turf/simulated/floor/beach/sand/desert
+ icon_state = "desert"
+
/turf/simulated/floor/beach/coastline
name = "Coastline"
icon = 'icons/misc/beach2.dmi'
@@ -168,6 +183,9 @@
name = "Water"
icon_state = "water"
+/turf/simulated/floor/beach/water/ocean
+ icon_state = "seadeep"
+
/turf/simulated/floor/beach/water/New()
..()
overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1)
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 5185c9b81c..65b40e1fdf 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -179,7 +179,7 @@ var/list/global/wall_cache = list()
/turf/simulated/wall/ex_act(severity)
switch(severity)
if(1.0)
- src.ChangeTurf(/turf/space)
+ src.ChangeTurf(get_base_turf(src.z))
return
if(2.0)
if(prob(75))
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 570f1a9391..5725e3b908 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -1,5 +1,3 @@
-
-
/turf/space
icon = 'icons/turf/space.dmi'
name = "\proper space"
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index e642914519..7dc2b97173 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -22,10 +22,6 @@
var/icon_old = null
var/pathweight = 1
- //Mining resource generation stuff.
- var/has_resources
- var/list/resources
-
// Flick animation
var/atom/movable/overlay/c_animation = null
@@ -289,61 +285,8 @@
else
lighting_clear_overlays()
-
-//Commented out by SkyMarshal 5/10/13 - If you are patching up space, it should be vacuum.
-// If you are replacing a wall, you have increased the volume of the room without increasing the amount of gas in it.
-// As such, this will no longer be used.
-
-//////Assimilate Air//////
-/*
-/turf/simulated/proc/Assimilate_Air()
- var/aoxy = 0//Holders to assimilate air from nearby turfs
- var/anitro = 0
- var/aco = 0
- var/atox = 0
- var/atemp = 0
- var/turf_count = 0
-
- for(var/direction in cardinal)//Only use cardinals to cut down on lag
- var/turf/T = get_step(src,direction)
- if(istype(T,/turf/space))//Counted as no air
- turf_count++//Considered a valid turf for air calcs
- continue
- else if(istype(T,/turf/simulated/floor))
- var/turf/simulated/S = T
- if(S.air)//Add the air's contents to the holders
- aoxy += S.air.oxygen
- anitro += S.air.nitrogen
- aco += S.air.carbon_dioxide
- atox += S.air.toxins
- atemp += S.air.temperature
- turf_count ++
- air.oxygen = (aoxy/max(turf_count,1))//Averages contents of the turfs, ignoring walls and the like
- air.nitrogen = (anitro/max(turf_count,1))
- air.carbon_dioxide = (aco/max(turf_count,1))
- air.toxins = (atox/max(turf_count,1))
- air.temperature = (atemp/max(turf_count,1))//Trace gases can get bant
- air.update_values()
-
- //cael - duplicate the averaged values across adjacent turfs to enforce a seamless atmos change
- for(var/direction in cardinal)//Only use cardinals to cut down on lag
- var/turf/T = get_step(src,direction)
- if(istype(T,/turf/space))//Counted as no air
- continue
- else if(istype(T,/turf/simulated/floor))
- var/turf/simulated/S = T
- if(S.air)//Add the air's contents to the holders
- S.air.oxygen = air.oxygen
- S.air.nitrogen = air.nitrogen
- S.air.carbon_dioxide = air.carbon_dioxide
- S.air.toxins = air.toxins
- S.air.temperature = air.temperature
- S.air.update_values()
-*/
-
-
/turf/proc/ReplaceWithLattice()
- src.ChangeTurf(/turf/space)
+ src.ChangeTurf(get_base_turf(src.z))
spawn()
new /obj/structure/lattice( locate(src.x, src.y, src.z) )
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 6158c59bc8..cd6dfda8db 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -1236,7 +1236,7 @@ var/global/floorIsLava = 0
if(!ai_number)
usr << "No AIs located" //Just so you know the thing is actually working and not just ignoring you.
-/datum/admins/proc/show_skills(var/mob/living/carbon/human/M as mob in world)
+/datum/admins/proc/show_skills()
set category = "Admin"
set name = "Show Skills"
@@ -1246,6 +1246,9 @@ var/global/floorIsLava = 0
usr << "Error: you are not an admin!"
return
+ var/mob/living/carbon/human/M = input("Select mob.", "Select mob.") as null|anything in human_mob_list
+ if(!M) return
+
show_skill_window(usr, M)
return
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 41acc7894b..af1e049b39 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -168,6 +168,9 @@ var/list/admin_verbs_debug = list(
/client/proc/restart_controller,
/client/proc/print_random_map,
/client/proc/create_random_map,
+ /client/proc/apply_random_map,
+ /client/proc/overlay_random_map,
+ /client/proc/delete_random_map,
/client/proc/show_plant_genes,
/client/proc/enable_debug_verbs,
/client/proc/callproc,
@@ -708,66 +711,70 @@ var/list/admin_verbs_mentor = list(
if(holder)
src.holder.output_ai_laws()
-/client/proc/rename_silicon(mob/living/silicon/S in mob_list)
+/client/proc/rename_silicon()
set name = "Rename Silicon"
set category = "Admin"
- if(!istype(S))
- return
+ if(!check_rights(R_ADMIN)) return
- if(holder)
- var/new_name = sanitizeSafe(input(src, "Enter new name. Leave blank or as is to cancel.", "Enter new silicon name", S.real_name))
- if(new_name && new_name != S.real_name)
- admin_log_and_message_admins("has renamed the silicon '[S.real_name]' to '[new_name]'")
- S.SetName(new_name)
+ var/mob/living/silicon/S = input("Select silicon.", "Rename Silicon.") as null|anything in silicon_mob_list
+ if(!S) return
+
+ var/new_name = sanitizeSafe(input(src, "Enter new name. Leave blank or as is to cancel.", "[S.real_name] - Enter new silicon name", S.real_name))
+ if(new_name && new_name != S.real_name)
+ admin_log_and_message_admins("has renamed the silicon '[S.real_name]' to '[new_name]'")
+ S.SetName(new_name)
feedback_add_details("admin_verb","RAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/manage_silicon_laws(mob/living/silicon/S in mob_list)
+/client/proc/manage_silicon_laws()
set name = "Manage Silicon Laws"
set category = "Admin"
- if(!istype(S))
- return
+ if(!check_rights(R_ADMIN)) return
- if(holder)
- var/obj/nano_module/law_manager/L = new(S)
- L.ui_interact(usr, state = admin_state)
+ var/mob/living/silicon/S = input("Select silicon.", "Manage Silicon Laws") as null|anything in silicon_mob_list
+ if(!S) return
+
+ var/obj/nano_module/law_manager/L = new(S)
+ L.ui_interact(usr, state = admin_state)
admin_log_and_message_admins("has opened [S]'s law manager.")
feedback_add_details("admin_verb","MSL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/change_human_appearance_admin(mob/living/carbon/human/H in world)
+/client/proc/change_human_appearance_admin()
set name = "Change Mob Appearance - Admin"
set desc = "Allows you to change the mob appearance"
set category = "Admin"
- if(!istype(H))
- return
+ if(!check_rights(R_FUN)) return
- if(holder)
- admin_log_and_message_admins("is altering the appearance of [H].")
- H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0, state = admin_state)
+ var/mob/living/carbon/human/H = input("Select mob.", "Change Mob Appearance - Admin") as null|anything in human_mob_list
+ if(!H) return
+
+ admin_log_and_message_admins("is altering the appearance of [H].")
+ H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0, state = admin_state)
feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/change_human_appearance_self(mob/living/carbon/human/H in mob_list)
+/client/proc/change_human_appearance_self()
set name = "Change Mob Appearance - Self"
set desc = "Allows the mob to change its appearance"
set category = "Admin"
- if(!istype(H))
- return
+ if(!check_rights(R_FUN)) return
+
+ var/mob/living/carbon/human/H = input("Select mob.", "Change Mob Appearance - Self") as null|anything in human_mob_list
+ if(!H) return
if(!H.client)
usr << "Only mobs with clients can alter their own appearance."
return
- if(holder)
- switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
- if("Yes")
- admin_log_and_message_admins("has allowed [H] to change \his appearance, without whitelisting of races.")
- H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
- if("No")
- admin_log_and_message_admins("has allowed [H] to change \his appearance, with whitelisting of races.")
- H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
+ switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
+ if("Yes")
+ admin_log_and_message_admins("has allowed [H] to change \his appearance, without whitelisting of races.")
+ H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
+ if("No")
+ admin_log_and_message_admins("has allowed [H] to change \his appearance, with whitelisting of races.")
+ H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/change_security_level()
@@ -792,12 +799,14 @@ var/list/admin_verbs_mentor = list(
// feedback_add_details("admin_verb","MP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
-/client/proc/editappear(mob/living/carbon/human/M as mob in mob_list)
+/client/proc/editappear()
set name = "Edit Appearance"
set category = "Fun"
if(!check_rights(R_FUN)) return
+ var/mob/living/carbon/human/M = input("Select mob.", "Edit Appearance") as null|anything in human_mob_list
+
if(!istype(M, /mob/living/carbon/human))
usr << "\red You can only do this to humans!"
return
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index b947f3f710..26cae206e9 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -137,7 +137,7 @@
send2adminirc("PlayerPM from [key_name(src)]: [html_decode(msg)]")
- src << "" + create_text_tag("pm_out_alt", "", src) + " to : [msg]"
+ src << "" + create_text_tag("pm_out_alt", "", src) + " to Admin IRC: [msg]"
log_admin("PM: [key_name(src)]->IRC: [msg]")
for(var/client/X in admins)
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 9ab952de64..63eae8e994 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -387,11 +387,11 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/device/pda/pda = H.wear_id
id = pda.id
id.icon_state = "gold"
- id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
+ id.access = get_all_accesses()
else
var/obj/item/weapon/card/id/id = new/obj/item/weapon/card/id(M);
id.icon_state = "gold"
- id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
+ id.access = get_all_accesses()
id.registered_name = H.real_name
id.assignment = "Captain"
id.name = "[id.registered_name]'s ID Card ([id.assignment])"
@@ -516,12 +516,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
for(var/areatype in areas_without_camera)
world << "* [areatype]"
-/client/proc/cmd_admin_dress(var/mob/living/carbon/human/M in mob_list)
+/client/proc/cmd_admin_dress()
set category = "Fun"
set name = "Select equipment"
- if(!ishuman(M))
- alert("Invalid mob")
- return
+
+ var/mob/living/carbon/human/M = input("Select mob.", "Select equipment.") as null|anything in human_mob_list
+ if(!M) return
+
//log_admin("[key_name(src)] has alienized [M.key].")
var/list/dresspacks = list(
"strip",
@@ -682,7 +683,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/weapon/card/id/W = new(M)
W.name = "[M.real_name]'s ID Card"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.assignment = "Tunnel Clown!"
W.registered_name = M.real_name
M.equip_to_slot_or_del(W, slot_wear_id)
@@ -739,7 +740,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/weapon/card/id/syndicate/W = new(M)
W.name = "[M.real_name]'s ID Card"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.assignment = "Reaper"
W.registered_name = M.real_name
M.equip_to_slot_or_del(W, slot_wear_id)
@@ -769,7 +770,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
W.name = "[M.real_name]'s ID Card"
W.icon_state = "centcom"
W.item_state = "id_inv"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.access += list("VIP Guest","Custodian","Thunderdome Overseer","Intel Officer","Medical Officer","Death Commando","Research Officer")
W.assignment = "NanoTrasen Navy Representative"
W.registered_name = M.real_name
@@ -793,7 +794,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/weapon/card/id/centcom/W = new(M)
W.name = "[M.real_name]'s ID Card"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.access += get_all_centcom_access()
W.assignment = "NanoTrasen Navy Officer"
W.registered_name = M.real_name
@@ -818,7 +819,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/weapon/card/id/centcom/W = new(M)
W.name = "[M.real_name]'s ID Card"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.access += get_all_centcom_access()
W.assignment = "NanoTrasen Navy Captain"
W.registered_name = M.real_name
@@ -836,7 +837,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/weapon/card/id/W = new(M)
W.name = "[M.real_name]'s ID Card"
W.icon_state = "centcom"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.access += get_all_centcom_access()
W.assignment = "Emergency Response Team"
W.registered_name = M.real_name
@@ -858,7 +859,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/weapon/card/id/W = new(M)
W.name = "[M.real_name]'s ID Card"
W.icon_state = "centcom"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.access += get_all_centcom_access()
W.assignment = "Special Operations Officer"
W.registered_name = M.real_name
@@ -912,7 +913,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/obj/item/weapon/card/id/W = new(M)
W.name = "[M.real_name]'s ID Card"
W.icon_state = "centcom"
- W.access = get_all_accesses()
+ W.access = get_all_station_access()
W.access += get_all_centcom_access()
W.assignment = "Admiral"
W.registered_name = M.real_name
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 0848c17a11..35c206fd4b 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -236,8 +236,9 @@ datum/preferences
/datum/preferences/proc/ShowChoices(mob/user)
if(!user || !user.client) return
update_preview_icon()
- user << browse_rsc(preview_icon_front, "previewicon.png")
- user << browse_rsc(preview_icon_side, "previewicon2.png")
+ if(preview_icon_front && preview_icon_side)
+ user << browse_rsc(preview_icon_front, "previewicon.png")
+ user << browse_rsc(preview_icon_side, "previewicon2.png")
var/dat = ""
if(path)
@@ -1667,6 +1668,7 @@ datum/preferences
var/status = organ_data[name]
var/obj/item/organ/external/O = character.organs_by_name[name]
if(O)
+ O.status = 0
if(status == "amputated")
character.organs_by_name[O.limb_name] = null
character.organs -= O
diff --git a/code/modules/economy/EFTPOS.dm b/code/modules/economy/EFTPOS.dm
index eed1e40ab2..fda22b17f9 100644
--- a/code/modules/economy/EFTPOS.dm
+++ b/code/modules/economy/EFTPOS.dm
@@ -100,7 +100,7 @@
else
dat += "Lock in new transaction
"
- dat += "Transaction purpose: [transaction_purpose]
"
+ dat += "Transaction purpose: [transaction_purpose]
"
dat += "Value: $[transaction_amount]
"
dat += "Linked account: [linked_account ? linked_account.owner_name : "None"]
"
dat += "Change access code
"
diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm
index 5cb256e500..3c1aeba23f 100644
--- a/code/modules/events/event_container.dm
+++ b/code/modules/events/event_container.dm
@@ -161,6 +161,8 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 30, list(ASSIGNMENT_ENGINEER = 5)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 150)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Virology Breach", /datum/event/prison_break/virology, 0, list(ASSIGNMENT_MEDICAL = 100)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Xenobiology Breach", /datum/event/prison_break/xenobiology, 0, list(ASSIGNMENT_SCIENCE = 100)),
)
/datum/event_container/major
@@ -169,6 +171,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 1320),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 60), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 3), 1),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ANY = 5)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 3), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Space Vines", /datum/event/spacevine, 0, list(ASSIGNMENT_ENGINEER = 15), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 30), 1),
diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm
index 0dbe3a5017..3539130c27 100644
--- a/code/modules/events/event_dynamic.dm
+++ b/code/modules/events/event_dynamic.dm
@@ -188,28 +188,35 @@ var/list/event_last_fired = list()
active_with_role["Cyborg"] = 0
active_with_role["Janitor"] = 0
active_with_role["Gardener"] = 0
- active_with_role["Any"] = player_list.len
for(var/mob/M in player_list)
- if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive
+ if(!M.mind || !M.client || M.client.is_afk(10 MINUTES)) // longer than 10 minutes AFK counts them as inactive
continue
- if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "engineering robot module")
- active_with_role["Engineer"]++
- if(M.mind.assigned_role in list("Chief Engineer", "Station Engineer"))
+ active_with_role["Any"]++
+
+ if(istype(M, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/R = M
+ if(R.module)
+ if(istype(R.module, /obj/item/weapon/robot_module/engineering))
+ active_with_role["Engineer"]++
+ else if(istype(R.module, /obj/item/weapon/robot_module/security))
+ active_with_role["Security"]++
+ else if(istype(R.module, /obj/item/weapon/robot_module/medical))
+ active_with_role["Medical"]++
+ else if(istype(R.module, /obj/item/weapon/robot_module/research))
+ active_with_role["Scientist"]++
+
+ if(M.mind.assigned_role in engineering_positions)
active_with_role["Engineer"]++
- if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "medical robot module")
- active_with_role["Medical"]++
if(M.mind.assigned_role in medical_positions)
active_with_role["Medical"]++
- if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "security robot module")
- active_with_role["Security"]++
if(M.mind.assigned_role in security_positions)
active_with_role["Security"]++
- if(M.mind.assigned_role in list("Research Director", "Scientist"))
+ if(M.mind.assigned_role in science_positions)
active_with_role["Scientist"]++
if(M.mind.assigned_role == "AI")
diff --git a/code/modules/events/infestation.dm b/code/modules/events/infestation.dm
index 629579f794..c88472688f 100644
--- a/code/modules/events/infestation.dm
+++ b/code/modules/events/infestation.dm
@@ -58,14 +58,10 @@
spawn_area_type = /area/security/tactical
locstring = "tactical equipment storage"
- //world << "looking for [spawn_area_type]"
for(var/areapath in typesof(spawn_area_type))
- //world << " checking [areapath]"
var/area/A = locate(areapath)
- //world << " A: [A], contents.len: [A.contents.len]"
- //world << " B: [B], contents.len: [B.contents.len]"
for(var/turf/simulated/floor/F in A.contents)
- if(!F.contents.len)
+ if(turf_clear(F))
turfs += F
var/list/spawn_types = list()
diff --git a/code/modules/events/money_hacker.dm b/code/modules/events/money_hacker.dm
index 5fbc323a29..07d18c2746 100644
--- a/code/modules/events/money_hacker.dm
+++ b/code/modules/events/money_hacker.dm
@@ -19,30 +19,11 @@
without intervention this attack will succeed in approximately 10 minutes. Required intervention: temporary suspension of affected accounts until the attack has ceased. \
Notifications will be sent as updates occur.
"
var/my_department = "[station_name()] firewall subroutines"
- var/sending = message + "Message dispatched by [my_department]."
-
- var/pass = 0
+
for(var/obj/machinery/message_server/MS in world)
if(!MS.active) continue
- // /obj/machinery/message_server/proc/send_rc_message(var/recipient = "",var/sender = "",var/message = "",var/stamp = "", var/id_auth = "", var/priority = 1)
- MS.send_rc_message("Engineering/Security/Bridge", my_department, message, "", "", 2)
- pass = 1
-
- if(pass)
- var/keyed_dpt1 = ckey("Engineering")
- var/keyed_dpt2 = ckey("Security")
- var/keyed_dpt3 = ckey("Bridge")
- for (var/obj/machinery/requests_console/Console in allConsoles)
- var/keyed_department = ckey(Console.department)
- if(keyed_department == keyed_dpt1 || keyed_department == keyed_dpt2 || keyed_department == keyed_dpt3)
- if(Console.newmessagepriority < 2)
- Console.newmessagepriority = 2
- Console.icon_state = "req_comp2"
- if(!Console.silent)
- playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(5, Console.loc))
- O.show_message(text("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [my_department]'"))
- Console.messages += "High Priority message from [my_department]
[sending]"
+ MS.send_rc_message("Head of Personnel's Desk", my_department, message, "", "", 2)
+
/datum/event/money_hacker/tick()
if(world.time >= end_time)
@@ -80,27 +61,7 @@
message = "The attack has ceased, the affected accounts can now be brought online."
var/my_department = "[station_name()] firewall subroutines"
- var/sending = message + "Message dispatched by [my_department]."
- var/pass = 0
for(var/obj/machinery/message_server/MS in world)
if(!MS.active) continue
- // /obj/machinery/message_server/proc/send_rc_message(var/recipient = "",var/sender = "",var/message = "",var/stamp = "", var/id_auth = "", var/priority = 1)
- MS.send_rc_message("Engineering/Security/Bridge", my_department, message, "", "", 2)
- pass = 1
-
- if(pass)
- var/keyed_dpt1 = ckey("Engineering")
- var/keyed_dpt2 = ckey("Security")
- var/keyed_dpt3 = ckey("Bridge")
- for (var/obj/machinery/requests_console/Console in allConsoles)
- var/keyed_department = ckey(Console.department)
- if(keyed_department == keyed_dpt1 || keyed_department == keyed_dpt2 || keyed_department == keyed_dpt3)
- if(Console.newmessagepriority < 2)
- Console.newmessagepriority = 2
- Console.icon_state = "req_comp2"
- if(!Console.silent)
- playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(5, Console.loc))
- O.show_message(text("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [my_department]'"))
- Console.messages += "High Priority message from [my_department]
[sending]"
+ MS.send_rc_message("Head of Personnel's Desk", my_department, message, "", "", 2)
diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm
index 8eb3bc5390..99a69a36eb 100644
--- a/code/modules/events/prison_break.dm
+++ b/code/modules/events/prison_break.dm
@@ -1,52 +1,86 @@
/datum/event/prison_break
- announceWhen = 50
+ startWhen = 5
+ announceWhen = 75
- var/releaseWhen = 25
- var/list/area/prisonAreas = list()
+ var/releaseWhen = 60
+ var/list/area/areas = list() //List of areas to affect. Filled by start()
+
+ var/eventDept = "Security" //Department name in announcement
+ var/list/areaName = list("Brig") //Names of areas mentioned in AI and Engineering announcements
+ var/list/areaType = list(/area/security/prison, /area/security/brig) //Area types to include.
+ var/list/areaNotType = list() //Area types to specifically exclude.
+
+/datum/event/prison_break/virology
+ eventDept = "Medical"
+ areaName = list("Virology")
+ areaType = list(/area/medical/virology, /area/medical/virologyaccess)
+
+/datum/event/prison_break/xenobiology
+ eventDept = "Science"
+ areaName = list("Xenobiology")
+ areaType = list(/area/rnd/xenobiology)
+ areaNotType = list(/area/rnd/xenobiology/xenoflora, /area/rnd/xenobiology/xenoflora_storage)
+
+/datum/event/prison_break/station
+ eventDept = "Station"
+ areaName = list("Brig","Virology","Xenobiology")
+ areaType = list(/area/security/prison, /area/security/brig, /area/medical/virology, /area/medical/virologyaccess, /area/rnd/xenobiology)
+ areaNotType = list(/area/rnd/xenobiology/xenoflora, /area/rnd/xenobiology/xenoflora_storage)
/datum/event/prison_break/setup()
- announceWhen = rand(50, 60)
- releaseWhen = rand(20, 30)
+ announceWhen = rand(75, 105)
+ releaseWhen = rand(60, 90)
- src.startWhen = src.releaseWhen-1
- src.endWhen = src.releaseWhen+1
+ src.endWhen = src.releaseWhen+2
/datum/event/prison_break/announce()
- if(prisonAreas && prisonAreas.len > 0)
- command_announcement.Announce("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")
- else
- world.log << "ERROR: Could not initate grey-tide. Unable find prison or brig area."
- kill()
+ if(areas && areas.len > 0)
+ command_announcement.Announce("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] [(eventDept == "Security")? "imprisonment":"containment"] subroutines. Secure any compromised areas immediately. Station AI involvement is recommended.", "[eventDept] Alert")
/datum/event/prison_break/start()
for(var/area/A in world)
- if(istype(A, /area/security/prison) || istype(A, /area/security/brig))
- prisonAreas += A
+ if(is_type_in_list(A,areaType) && !is_type_in_list(A,areaNotType))
+ areas += A
+ if(areas && areas.len > 0)
+ var/pass = 0
+ var/my_department = "[station_name()] firewall subroutines"
+ var/rc_message = "An unknown malicious program has been detected in the [english_list(areaName)] lighting and airlock control systems at [worldtime2text()]. Systems will be fully compromised within approximately three minutes. Direct intervention is required immediately.
"
+ for(var/obj/machinery/message_server/MS in world)
+ MS.send_rc_message("Engineering", my_department, rc_message, "", "", 2)
+ pass = 1
+ if(pass) //This entire block should be handled by send_rc_message(). I'm not rewriting it.
+ var/sending = rc_message + "Message dispatched by [my_department]."
+ for (var/obj/machinery/requests_console/Console in allConsoles)
+ var/keyed_department = ckey(Console.department)
+ if(keyed_department == ckey("Engineering"))
+ if(Console.newmessagepriority < 2)
+ Console.newmessagepriority = 2
+ Console.icon_state = "req_comp2"
+ if(!Console.silent)
+ playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1)
+ for (var/mob/O in hearers(5, Console.loc))
+ O.show_message(text("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [my_department]'"))
+ Console.messages += "High Priority message from [my_department]
[sending]"
+
+ for(var/mob/living/silicon/ai/A in player_list)
+ A << "Malicious program detected in the [english_list(areaName)] lighting and airlock control systems by [my_department]."
+
+ else
+ world.log << "ERROR: Could not initate grey-tide. Unable to find suitable containment area."
+ kill()
- if(prisonAreas && prisonAreas.len > 0)
- for(var/area/A in prisonAreas)
- for(var/obj/machinery/light/L in A)
- L.flicker(10)
/datum/event/prison_break/tick()
if(activeFor == releaseWhen)
- if(prisonAreas && prisonAreas.len > 0)
- for(var/area/A in prisonAreas)
- for(var/obj/machinery/power/apc/temp_apc in A)
- temp_apc.overload_lighting()
+ if(areas && areas.len > 0)
+ for(var/area/A in areas)
+ for(var/obj/machinery/light/L in A)
+ L.flicker(10)
- for(var/obj/structure/closet/secure_closet/brig/temp_closet in A)
- temp_closet.locked = 0
- temp_closet.icon_state = temp_closet.icon_closed
- for(var/obj/machinery/door/airlock/security/temp_airlock in A)
- temp_airlock.prison_open()
-
- for(var/obj/machinery/door/airlock/glass_security/temp_glassairlock in A)
- temp_glassairlock.prison_open()
-
- for(var/obj/machinery/door_timer/temp_timer in A)
- temp_timer.releasetime = 1
\ No newline at end of file
+/datum/event/prison_break/end()
+ for(var/area/A in shuffle(areas))
+ A.prison_break()
diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm
index 57579cdb72..e62a96c2ce 100644
--- a/code/modules/hydroponics/spreading/spreading.dm
+++ b/code/modules/hydroponics/spreading/spreading.dm
@@ -7,7 +7,7 @@
for(var/areapath in typesof(/area/hallway))
var/area/A = locate(areapath)
for(var/turf/simulated/floor/F in A.contents)
- if(!F.contents.len)
+ if(turf_clear(F))
turfs += F
if(turfs.len) //Pick a turf to spawn at if we can
diff --git a/code/modules/mining/drilling/drill.dm b/code/modules/mining/drilling/drill.dm
index 5d25adb78d..f6cfef3dcb 100644
--- a/code/modules/mining/drilling/drill.dm
+++ b/code/modules/mining/drilling/drill.dm
@@ -84,7 +84,7 @@
//Dig out the tasty ores.
if(resource_field.len)
- var/turf/harvesting = pick(resource_field)
+ var/turf/simulated/harvesting = pick(resource_field)
while(resource_field.len && !harvesting.resources)
harvesting.has_resources = 0
@@ -253,7 +253,7 @@
var/tx = T.x - 2
var/ty = T.y - 2
- var/turf/mine_turf
+ var/turf/simulated/mine_turf
for(var/iy = 0,iy < 5, iy++)
for(var/ix = 0, ix < 5, ix++)
mine_turf = locate(tx + ix, ty + iy, T.z)
diff --git a/code/modules/mining/drilling/scanner.dm b/code/modules/mining/drilling/scanner.dm
index 878bf1b2c2..2e9807ba6e 100644
--- a/code/modules/mining/drilling/scanner.dm
+++ b/code/modules/mining/drilling/scanner.dm
@@ -20,7 +20,7 @@
"exotic matter" = 0
)
- for(var/turf/T in range(2, get_turf(user)))
+ for(var/turf/simulated/T in range(2, get_turf(user)))
if(!T.has_resources)
continue
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 0ca011ee63..c414f50cec 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -1,5 +1,8 @@
/**********************Mineral deposits**************************/
-
+/turf/unsimulated/mineral
+ name = "impassable rock"
+ icon = 'icons/turf/walls.dmi'
+ icon_state = "rock-dark"
/turf/simulated/mineral //wall piece
name = "Rock"
@@ -11,6 +14,7 @@
density = 1
blocks_air = 1
temperature = T0C
+ var/mined_turf = /turf/simulated/floor/plating/airless/asteroid
var/ore/mineral
var/mined_ore = 0
var/last_act = 0
@@ -28,21 +32,20 @@
has_resources = 1
/turf/simulated/mineral/New()
-
spawn(0)
MineralSpread()
-
spawn(2)
- var/list/step_overlays = list("s" = NORTH, "n" = SOUTH, "w" = EAST, "e" = WEST)
- for(var/direction in step_overlays)
- var/turf/turf_to_check = get_step(src,step_overlays[direction])
+ updateMineralOverlays(1)
- if(istype(turf_to_check,/turf/simulated/floor/plating/airless/asteroid))
- var/turf/simulated/floor/plating/airless/asteroid/T = turf_to_check
- T.updateMineralOverlays()
-
- else if(istype(turf_to_check,/turf/space) || istype(turf_to_check,/turf/simulated/floor))
- turf_to_check.overlays += image('icons/turf/walls.dmi', "rock_side_[direction]")
+/turf/simulated/mineral/proc/updateMineralOverlays(var/update_neighbors)
+ var/list/step_overlays = list("s" = NORTH, "n" = SOUTH, "w" = EAST, "e" = WEST)
+ for(var/direction in step_overlays)
+ var/turf/turf_to_check = get_step(src,step_overlays[direction])
+ if(update_neighbors && istype(turf_to_check,/turf/simulated/floor/plating/airless/asteroid))
+ var/turf/simulated/floor/plating/airless/asteroid/T = turf_to_check
+ T.updateMineralOverlays()
+ else if(istype(turf_to_check,/turf/space) || istype(turf_to_check,/turf/simulated/floor))
+ turf_to_check.overlays += image('icons/turf/walls.dmi', "rock_side_[direction]")
/turf/simulated/mineral/ex_act(severity)
switch(severity)
@@ -280,8 +283,7 @@
//Add some rubble, you did just clear out a big chunk of rock.
- var/turf/simulated/floor/plating/airless/asteroid/N = ChangeTurf(/turf/simulated/floor/plating/airless/asteroid)
- N.overlay_detail = "asteroid[rand(0,9)]"
+ var/turf/simulated/floor/plating/airless/asteroid/N = ChangeTurf(mined_turf)
// Kill and update the space overlays around us.
for(var/direction in step_overlays)
@@ -292,13 +294,9 @@
if(istype(get_step(T, step_overlays[next_direction]),/turf/simulated/mineral))
T.overlays += image('icons/turf/walls.dmi', "rock_side_[next_direction]")
- // Update the
- N.updateMineralOverlays(1)
-
- if(rand(1,500) == 1)
- visible_message("An old dusty crate was buried within!")
- new /obj/structure/closet/crate/secure/loot(src)
-
+ if(istype(N))
+ N.overlay_detail = "asteroid[rand(0,9)]"
+ N.updateMineralOverlays(1)
/turf/simulated/mineral/proc/excavate_find(var/prob_clean = 0, var/datum/find/F)
//with skill and luck, players can cleanly extract finds
@@ -391,7 +389,7 @@
/turf/simulated/floor/plating/airless/asteroid //floor piece
- name = "asteroid"
+ name = "sand"
icon = 'icons/turf/floors.dmi'
icon_state = "asteroid"
oxygen = 0
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 2874d16d39..c8d5651b29 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -670,6 +670,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
client.images -= ghostimage //remove ourself
mob/dead/observer/MayRespawn(var/feedback = 0)
+ if(!client || !mind)
+ return 0
+ if(mind.current && mind.current.stat != DEAD)
+ if(feedback)
+ src << "Your non-dead body prevent you from respawning."
+ return 0
if(config.antag_hud_restricted && has_enabled_antagHUD == 1)
if(feedback)
src << "antagHUD restrictions prevent you from respawning."
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 39c8eaf799..10e165fa5f 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -37,6 +37,7 @@
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[STATUS_HUD_OOC] = image('icons/mob/hud.dmi', src, "hudhealthy")
+ human_mob_list |= src
..()
if(dna)
@@ -44,6 +45,7 @@
make_blood()
/mob/living/carbon/human/Destroy()
+ human_mob_list -= src
for(var/organ in organs)
qdel(organ)
return ..()
@@ -170,7 +172,7 @@
/mob/living/carbon/human/blob_act()
if(stat == 2) return
show_message("\red The blob attacks you!")
- var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
+ var/dam_zone = pick(organs_by_name)
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
apply_damage(rand(30,40), BRUTE, affecting, run_armor_check(affecting, "melee"))
return
diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index 21a386b5cf..7451e6ae6a 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -295,7 +295,7 @@
src.visible_message("[user] has [attack_message] [src]!")
user.do_attack_animation(src)
- var/dam_zone = pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg", "groin")
+ var/dam_zone = pick(organs_by_name)
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm
index ec6ddefe1c..1fefa272e5 100644
--- a/code/modules/mob/living/silicon/say.dm
+++ b/code/modules/mob/living/silicon/say.dm
@@ -185,7 +185,7 @@
This is another way of saying that we won't bother dealing with them.*/
else
src << "No holopad connected."
- return
+ return 0
return 1
/mob/living/silicon/ai/proc/holopad_emote(var/message) //This is called when the AI uses the 'me' verb while using a holopad.
@@ -206,7 +206,7 @@
M.show_message(rendered, 2)
else //This shouldn't occur, but better safe then sorry.
src << "No holopad connected."
- return
+ return 0
return 1
/mob/living/silicon/ai/emote(var/act, var/type, var/message)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 77b13a8b11..de27956678 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -27,11 +27,13 @@
#define MED_HUD 2 //Medical HUD mode
/mob/living/silicon/New()
+ silicon_mob_list |= src
..()
add_language("Galactic Common")
init_subsystems()
/mob/living/silicon/Destroy()
+ silicon_mob_list -= src
for(var/datum/alarm_handler/AH in alarm_manager.all_handlers)
AH.unregister(src)
..()
diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm
index 93caa4c48b..98c2cdc905 100644
--- a/code/modules/nano/modules/law_manager.dm
+++ b/code/modules/nano/modules/law_manager.dm
@@ -34,10 +34,7 @@
return 1
if(href_list["set_view"])
- if(is_malf(usr) || owner.is_ai_malf())
- current_view = text2num(href_list["set_view"])
- else
- current_view = 0
+ current_view = text2num(href_list["set_view"])
return 1
if(href_list["law_channel"])
@@ -170,12 +167,8 @@
data["isAI"] = owner.isAI()
data["isMalf"] = is_malf(user)
- data["isAIMalf"] = owner.is_ai_malf()
data["isSlaved"] = owner.is_slaved()
data["isAdmin"] = is_admin(user)
-
- if(!(data["isMalf"] || data["isAIMalf"]))
- current_view = 0
data["view"] = current_view
var/channels[0]
@@ -183,9 +176,7 @@
channels[++channels.len] = list("channel" = ch_name)
data["channel"] = owner.lawchannel
data["channels"] = channels
-
- if(data["isMalf"] || data["isAIMalf"])
- data["law_sets"] = package_multiple_laws(data["isAdmin"] ? admin_laws : player_laws)
+ data["law_sets"] = package_multiple_laws(data["isAdmin"] ? admin_laws : player_laws)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
@@ -216,15 +207,6 @@
/obj/nano_module/law_manager/proc/is_malf(var/mob/user)
return (is_admin(user) && !owner.is_slaved()) || owner.is_malf_or_traitor()
-/mob/living/silicon/proc/is_ai_malf()
- return 0
-
-/mob/living/silicon/robot/is_ai_malf()
- return is_slaved() && connected_ai.is_malf_or_traitor()
-
-/mob/living/silicon/ai/is_ai_malf()
- return 0
-
/mob/living/silicon/proc/is_slaved()
return 0
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index 3c4f166fa6..b7541153a5 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -882,11 +882,14 @@ Note that amputating the affected organ does in fact remove the infection from t
dislocated = -1 //TODO, make robotic limbs a separate type, remove snowflake
cannot_break = 1
get_icon()
+ unmutate()
for (var/obj/item/organ/external/T in children)
if(T)
T.robotize()
/obj/item/organ/external/proc/mutate()
+ if(src.status & ORGAN_ROBOT)
+ return
src.status |= ORGAN_MUTATED
owner.update_body()
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 86bb1476c4..08eb4416f6 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -1181,17 +1181,18 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on)
update_icon()
update()
-// overload all the lights in this APC area
+// overload the lights in this APC area
-/obj/machinery/power/apc/proc/overload_lighting()
+/obj/machinery/power/apc/proc/overload_lighting(var/chance = 100)
if(/* !get_connection() || */ !operating || shorted)
return
if( cell && cell.charge>=20)
cell.use(20);
spawn(0)
for(var/obj/machinery/light/L in area)
- L.on = 1
- L.broken()
+ if(prob(chance))
+ L.on = 1
+ L.broken()
sleep(1)
/obj/machinery/power/apc/proc/setsubsystem(val)
diff --git a/code/modules/power/engine.dm b/code/modules/power/engine.dm
index a9095b3a78..6ffe660339 100644
--- a/code/modules/power/engine.dm
+++ b/code/modules/power/engine.dm
@@ -18,12 +18,12 @@
/turf/simulated/floor/engine/ex_act(severity)
switch(severity)
if(1.0)
- ChangeTurf(/turf/space)
+ ChangeTurf(get_base_turf(src.z))
qdel(src)
return
if(2.0)
if (prob(50))
- ChangeTurf(/turf/space)
+ ChangeTurf(get_base_turf(src.z))
qdel(src)
return
else
@@ -31,7 +31,7 @@
/turf/simulated/floor/engine/blob_act()
if (prob(25))
- ChangeTurf(/turf/space)
+ ChangeTurf(get_base_turf(src.z))
qdel(src)
return
return
\ No newline at end of file
diff --git a/code/modules/power/singularity/act.dm b/code/modules/power/singularity/act.dm
index 3804c1f158..0114269a76 100644
--- a/code/modules/power/singularity/act.dm
+++ b/code/modules/power/singularity/act.dm
@@ -107,7 +107,7 @@
continue
if(O.invisibility == 101)
O.singularity_act(src, current_size)
- ChangeTurf(/turf/space)
+ ChangeTurf(get_base_turf(src.z))
return 2
/turf/simulated/wall/singularity_pull(S, current_size)
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index e5eadb0ae3..7f1457d638 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -117,6 +117,13 @@
self_recharge = 1
charge_meter = 0
+/obj/item/weapon/gun/energy/staff/special_check(var/mob/user)
+ if((user.mind && !wizards.is_antagonist(user.mind)))
+ usr << "You focus your mind on \the [src], but nothing happens!"
+ return 0
+
+ return ..()
+
/obj/item/weapon/gun/energy/staff/handle_click_empty(mob/user = null)
if (user)
user.visible_message("*fizzle*", "*fizzle*")
diff --git a/code/modules/random_map/_random_map_setup.dm b/code/modules/random_map/_random_map_setup.dm
new file mode 100644
index 0000000000..01c57f2f76
--- /dev/null
+++ b/code/modules/random_map/_random_map_setup.dm
@@ -0,0 +1,22 @@
+/*
+ This module is used to generate the debris fields/distribution maps/procedural stations.
+*/
+
+#define MIN_SURFACE_COUNT 500
+#define MIN_RARE_COUNT 200
+#define MIN_DEEP_COUNT 100
+#define RESOURCE_HIGH_MAX 4
+#define RESOURCE_HIGH_MIN 2
+#define RESOURCE_MID_MAX 3
+#define RESOURCE_MID_MIN 1
+#define RESOURCE_LOW_MAX 1
+#define RESOURCE_LOW_MIN 0
+
+#define FLOOR_CHAR 0
+#define WALL_CHAR 1
+#define DOOR_CHAR 2
+#define EMPTY_CHAR 3
+#define ROOM_TEMP_CHAR 4
+#define MONSTER_CHAR 5
+#define ARTIFACT_TURF_CHAR 6
+#define ARTIFACT_CHAR 7
\ No newline at end of file
diff --git a/code/modules/random_map/automata/automata.dm b/code/modules/random_map/automata/automata.dm
new file mode 100644
index 0000000000..f3867d78bd
--- /dev/null
+++ b/code/modules/random_map/automata/automata.dm
@@ -0,0 +1,65 @@
+/datum/random_map/automata
+ descriptor = "generic caves"
+ initial_wall_cell = 55
+ var/iterations = 0 // Number of times to apply the automata rule.
+ var/cell_live_value = WALL_CHAR // Cell is alive if it has this value.
+ var/cell_dead_value = FLOOR_CHAR // As above for death.
+ var/cell_threshold = 5 // Cell becomes alive with this many live neighbors.
+
+// Automata-specific procs and processing.
+/datum/random_map/automata/generate_map()
+ for(var/i=1;i<=iterations;i++)
+ iterate(i)
+
+/datum/random_map/automata/get_additional_spawns(var/value, var/turf/T)
+ return
+
+/datum/random_map/automata/proc/iterate(var/iteration)
+ var/list/next_map[limit_x*limit_y]
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
+ var/current_cell = get_map_cell(x,y)
+ next_map[current_cell] = map[current_cell]
+ var/count = 0
+
+ // Every attempt to place this in a proc or a list has resulted in
+ // the generator being totally bricked and useless. Fuck it. We're
+ // hardcoding this shit. Feel free to rewrite and PR a fix. ~ Z
+ var/tmp_cell = get_map_cell(x,y)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+ tmp_cell = get_map_cell(x+1,y+1)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+ tmp_cell = get_map_cell(x-1,y-1)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+ tmp_cell = get_map_cell(x+1,y-1)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+ tmp_cell = get_map_cell(x-1,y+1)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+ tmp_cell = get_map_cell(x-1,y)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+ tmp_cell = get_map_cell(x,y-1)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+ tmp_cell = get_map_cell(x+1,y)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+ tmp_cell = get_map_cell(x,y+1)
+ if(tmp_cell && cell_is_alive(map[tmp_cell])) count++
+
+ if(count >= cell_threshold)
+ revive_cell(current_cell, next_map, (iteration == iterations))
+ else
+ kill_cell(current_cell, next_map, (iteration == iterations))
+ map = next_map
+
+// Check if a given tile counts as alive for the automata generations.
+/datum/random_map/automata/proc/cell_is_alive(var/value)
+ return (value == cell_live_value) && (value != cell_dead_value)
+
+/datum/random_map/automata/proc/revive_cell(var/target_cell, var/list/use_next_map, var/final_iter)
+ if(!use_next_map)
+ use_next_map = map
+ use_next_map[target_cell] = cell_live_value
+
+/datum/random_map/automata/proc/kill_cell(var/target_cell, var/list/use_next_map, var/final_iter)
+ if(!use_next_map)
+ use_next_map = map
+ use_next_map[target_cell] = cell_dead_value
\ No newline at end of file
diff --git a/code/modules/random_map/automata/caves.dm b/code/modules/random_map/automata/caves.dm
new file mode 100644
index 0000000000..9c8f2a556e
--- /dev/null
+++ b/code/modules/random_map/automata/caves.dm
@@ -0,0 +1,52 @@
+/datum/random_map/automata/cave_system
+ iterations = 5
+ descriptor = "moon caves"
+ wall_type = /turf/simulated/mineral
+ floor_type = /turf/simulated/floor/plating/airless/asteroid
+ target_turf_type = /turf/unsimulated/mask
+ var/mineral_sparse = /turf/simulated/mineral/random
+ var/mineral_rich = /turf/simulated/mineral/random/high_chance
+ var/list/ore_turfs = list()
+
+/datum/random_map/automata/cave_system/get_appropriate_path(var/value)
+ switch(value)
+ if(DOOR_CHAR)
+ return mineral_sparse
+ if(EMPTY_CHAR)
+ return mineral_rich
+ if(FLOOR_CHAR)
+ return floor_type
+ if(WALL_CHAR)
+ return wall_type
+
+/datum/random_map/automata/cave_system/get_map_char(var/value)
+ switch(value)
+ if(DOOR_CHAR)
+ return "x"
+ if(EMPTY_CHAR)
+ return "X"
+ return ..(value)
+
+/datum/random_map/automata/cave_system/revive_cell(var/target_cell, var/list/use_next_map, var/final_iter)
+ ..()
+ if(final_iter)
+ ore_turfs |= target_cell
+
+/datum/random_map/automata/cave_system/kill_cell(var/target_cell, var/list/use_next_map, var/final_iter)
+ ..()
+ if(final_iter)
+ ore_turfs -= target_cell
+
+// Create ore turfs.
+/datum/random_map/automata/cave_system/cleanup()
+ var/ore_count = round(map.len/20)
+ while((ore_count>0) && (ore_turfs.len>0))
+ if(!priority_process) sleep(-1)
+ var/check_cell = pick(ore_turfs)
+ ore_turfs -= check_cell
+ if(prob(75))
+ map[check_cell] = DOOR_CHAR // Mineral block
+ else
+ map[check_cell] = EMPTY_CHAR // Rare mineral block.
+ ore_count--
+ return 1
diff --git a/code/modules/random_map/building/building.dm b/code/modules/random_map/building/building.dm
new file mode 100644
index 0000000000..e5d3953af0
--- /dev/null
+++ b/code/modules/random_map/building/building.dm
@@ -0,0 +1,55 @@
+/datum/random_map/building
+ descriptor = "generic room"
+ limit_x = 7
+ limit_y = 7
+
+/datum/random_map/building/generate_map()
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
+ var/current_cell = get_map_cell(x,y)
+ if(!within_bounds(current_cell))
+ continue
+ if(x == 1 || y == 1 || x == limit_x || y == limit_y)
+ map[current_cell] = WALL_CHAR
+ else
+ map[current_cell] = FLOOR_CHAR
+
+/datum/random_map/building/handle_post_overlay_on(var/datum/random_map/target_map, var/tx, var/ty)
+ var/list/possible_doors
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
+ var/current_cell = get_map_cell(x,y)
+ if(!within_bounds(current_cell))
+ continue
+ if(!(x == 1 || y == 1 || x == limit_x || y == limit_y))
+ continue
+ if(tx+x > target_map.limit_x)
+ continue
+ if(ty+y > target_map.limit_y)
+ continue
+
+ var/place_door
+ // #.# ... .## ##.
+ // #X# #X# .X. .X. == place a door
+ // ... # # .## ##.
+
+ // (tx+x)-1,(ty+y-1) (tx+x),(ty+y)-1 (tx+x)+1,(ty+y)-1
+ // (tx+x)-1,(ty+y) (tx+x),(ty+y) (tx+x)+1,(ty+y)
+ // (tx+x)-1,(ty+y+1) (tx+x),(ty+y)+1 (tx+x)+1,(ty+y)+1
+
+
+ if(place_door)
+ possible_doors |= target_map.get_map_cell(tx+x,ty+y)
+
+ if(possible_doors.len)
+ // Place at least one door.
+ var/placing_door = pick(possible_doors)
+ possible_doors -= placing_door
+ target_map.map[placing_door] = DOOR_CHAR
+ // Keep placing doors until we get bored or lose interest.
+ while(possible_doors && !prob(30))
+ placing_door = pick(possible_doors)
+ possible_doors -= placing_door
+ target_map.map[placing_door] = DOOR_CHAR
+
+ return
\ No newline at end of file
diff --git a/code/modules/random_map/mazes/maze.dm b/code/modules/random_map/mazes/maze.dm
new file mode 100644
index 0000000000..557adbd6e8
--- /dev/null
+++ b/code/modules/random_map/mazes/maze.dm
@@ -0,0 +1,65 @@
+/datum/random_map/maze
+ descriptor = "maze"
+ initial_wall_cell = 100
+ var/list/checked_coord_cache = list()
+ var/list/openlist = list()
+ var/list/closedlist = list()
+
+/datum/random_map/maze/set_map_size()
+ // Map has to be odd so that there are walls on all sides.
+ if(limit_x%2==0) limit_x++
+ if(limit_y%2==0) limit_y++
+ ..()
+
+/datum/random_map/maze/generate_map()
+
+ // Grab a random point on the map to begin the maze cutting at.
+ var/start_x = rand(1,limit_x-2)
+ var/start_y = rand(1,limit_y-2)
+ if(start_x%2!=0) start_x++
+ if(start_y%2!=0) start_y++
+
+ // Create the origin cell to start us off.
+ openlist += new /datum/maze_cell(start_x,start_y)
+
+ while(openlist.len)
+ // Grab a maze point to use and remove it from the open list.
+ var/datum/maze_cell/next = pick(openlist)
+ openlist -= next
+ if(!isnull(closedlist[next.name]))
+ continue
+
+ // Preliminary marking-off...
+ closedlist[next.name] = next
+ map[get_map_cell(next.x,next.y)] = FLOOR_CHAR
+
+ // Apply the values required and fill gap between this cell and origin point.
+ if(next.ox && next.oy)
+ if(next.ox < next.x)
+ map[get_map_cell(next.x-1,next.y)] = FLOOR_CHAR
+ else if(next.ox == next.x)
+ if(next.oy < next.y)
+ map[get_map_cell(next.x,next.y-1)] = FLOOR_CHAR
+ else
+ map[get_map_cell(next.x,next.y+1)] = FLOOR_CHAR
+ else
+ map[get_map_cell(next.x+1,next.y)] = FLOOR_CHAR
+
+ // Grab valid neighbors for use in the open list!
+ add_to_openlist(next.x,next.y+2,next.x,next.y)
+ add_to_openlist(next.x-2,next.y,next.x,next.y)
+ add_to_openlist(next.x+2,next.y,next.x,next.y)
+ add_to_openlist(next.x,next.y-2,next.x,next.y)
+
+ // Cleanup. Map stays in memory for display proc.
+ checked_coord_cache.Cut()
+ openlist.Cut()
+ closedlist.Cut()
+
+/datum/random_map/maze/proc/add_to_openlist(var/tx, var/ty, var/nx, var/ny)
+ if(tx < 1 || ty < 1 || tx > limit_x || ty > limit_y || !isnull(checked_coord_cache["[tx]-[ty]"]))
+ return 0
+ checked_coord_cache["[tx]-[ty]"] = 1
+ map[get_map_cell(tx,ty)] = DOOR_CHAR
+ var/datum/maze_cell/new_cell = new(tx,ty,nx,ny)
+ openlist |= new_cell
diff --git a/code/modules/random_map/mazes/maze_cell.dm b/code/modules/random_map/mazes/maze_cell.dm
new file mode 100644
index 0000000000..0b4fa1ac86
--- /dev/null
+++ b/code/modules/random_map/mazes/maze_cell.dm
@@ -0,0 +1,18 @@
+var/maze_cell_count = 0
+
+/datum/maze_cell
+ var/name
+ var/uid
+ var/x
+ var/y
+ var/ox
+ var/oy
+
+/datum/maze_cell/New(var/nx,var/ny,var/nox,var/noy)
+ maze_cell_count++
+ uid = maze_cell_count
+ name = "cell #[uid]"
+ x = nx
+ y = ny
+ ox = nox
+ oy = noy
\ No newline at end of file
diff --git a/code/modules/random_map/mining_distribution.dm b/code/modules/random_map/mining_distribution.dm
deleted file mode 100644
index 7973ff14ab..0000000000
--- a/code/modules/random_map/mining_distribution.dm
+++ /dev/null
@@ -1,242 +0,0 @@
-#define MIN_SURFACE_COUNT 500
-#define MIN_RARE_COUNT 200
-#define MIN_DEEP_COUNT 100
-#define RESOURCE_HIGH_MAX 4
-#define RESOURCE_HIGH_MIN 2
-#define RESOURCE_MID_MAX 3
-#define RESOURCE_MID_MIN 1
-#define RESOURCE_LOW_MAX 1
-#define RESOURCE_LOW_MIN 0
-
-/*
-Surface minerals:
- silicates
- iron
- gold
- silver
-Rare minerals:
- uranium
- diamond
-Deep minerals:
- phoron
- osmium (platinum)
- tritium (hydrogen)
-*/
-
-/datum/random_map/ore
-
- descriptor = "resource distribution map"
- real_size = 65 // Must be (power of 2)+1 for diamond-square.
- cell_range = 255 // These values are used to seed ore values rather than to determine a turf type.
- iterations = 0 // We'll handle iterating on our end (recursive, with args).
-
- var/chunk_size = 4 // Size each cell represents on map
- var/random_variance_chance = 25 // % chance of applying random_element.
- var/random_element = 0.5 // Determines the variance when smoothing out cell values.
- var/deep_val = 0.8 // Threshold for deep metals, set in new as percentage of cell_range.
- var/rare_val = 0.7 // Threshold for rare metal, set in new as percentage of cell_range.
- var/cell_base // Set in New()
- var/initial_cell_range // Set in New()
-
-/datum/random_map/ore/New()
- rare_val = cell_range * rare_val
- deep_val = cell_range * deep_val
-
- initial_cell_range = cell_range/5
- cell_base = cell_range/2
- ..()
-
-/datum/random_map/ore/check_map_sanity()
-
- var/rare_count = 0
- var/surface_count = 0
- var/deep_count = 0
-
- // Increment map sanity counters.
- for(var/value in map)
- if(value < rare_val)
- surface_count++
- else if(value < deep_val)
- rare_count++
- else
- deep_count++
- // Sanity check.
- if(surface_count < MIN_SURFACE_COUNT)
- admin_notice("Insufficient surface minerals. Rerolling...", R_DEBUG)
- return 0
- else if(rare_count < MIN_RARE_COUNT)
- admin_notice("Insufficient rare minerals. Rerolling...", R_DEBUG)
- return 0
- else if(deep_count < MIN_DEEP_COUNT)
- admin_notice("Insufficient deep minerals. Rerolling...", R_DEBUG)
- return 0
- else
- return 1
-
-//Halfassed diamond-square algorithm with some fuckery since it's a single dimension array.
-/datum/random_map/ore/seed_map()
-
- // Instantiate the grid.
- for(var/x = 1, x <= real_size, x++)
- for(var/y = 1, y <= real_size, y++)
- map[get_map_cell(x,y)] = 0
-
- // Now dump in the actual random data.
- map[get_map_cell(1,1)] = cell_base+rand(initial_cell_range)
- map[get_map_cell(1,real_size)] = cell_base+rand(initial_cell_range)
- map[get_map_cell(real_size,real_size)] = cell_base+rand(initial_cell_range)
- map[get_map_cell(real_size,1)] = cell_base+rand(initial_cell_range)
- iterate(1,1,1,(real_size-1)) // Start the recursion here.
-
-/datum/random_map/ore/display_map(atom/user)
-
- if(!user)
- user = world
-
- for(var/x = 1, x <= real_size, x++)
- var/line = ""
- for(var/y = 1, y <= real_size, y++)
- var/current_cell = get_map_cell(x,y)
- if(within_bounds(current_cell) && map[current_cell])
- if(map[current_cell] < rare_val)
- line += "S"
- else if(map[current_cell] < deep_val)
- line += "R"
- else
- line += "D"
- else
- line += "X"
- user << line
-
-/datum/random_map/ore/iterate(var/iteration,var/x,var/y,var/input_size)
-
- // Infinite loop check!
- if(iteration>=iterate_before_fail)
- admin_notice("Iteration count exceeded, aborting.", R_DEBUG)
- return
-
- var/isize = input_size
- var/hsize = round(input_size/2)
-
- /*
- (x,y+isize)----(x+hsize,y+isize)----(x+size,y+isize)
- | | |
- | | |
- | | |
- (x,y+hsize)----(x+hsize,y+hsize)----(x+isize,y)
- | | |
- | | |
- | | |
- (x,y)----------(x+hsize,y)----------(x+isize,y)
- */
- // Central edge values become average of corners.
- map[get_map_cell(x+hsize,y+isize)] = round((\
- map[get_map_cell(x,y+isize)] + \
- map[get_map_cell(x+isize,y+isize)] \
- )/2)
-
- map[get_map_cell(x+hsize,y)] = round(( \
- map[get_map_cell(x,y)] + \
- map[get_map_cell(x+isize,y)] \
- )/2)
-
- map[get_map_cell(x,y+hsize)] = round(( \
- map[get_map_cell(x,y+isize)] + \
- map[get_map_cell(x,y)] \
- )/2)
-
- map[get_map_cell(x+isize,y+hsize)] = round(( \
- map[get_map_cell(x+isize,y+isize)] + \
- map[get_map_cell(x+isize,y)] \
- )/2)
-
- // Centre value becomes the average of all other values + possible random variance.
- var/current_cell = get_map_cell(x+hsize,y+hsize)
- map[current_cell] = round((map[get_map_cell(x+hsize,y+isize)]+map[get_map_cell(x+hsize,y)]+map[get_map_cell(x,y+hsize)]+map[get_map_cell(x+isize,y)])/4)
-
- if(prob(random_variance_chance))
- map[current_cell] *= (rand(1,2)==1 ? (1.0-random_element) : (1.0+random_element))
- map[current_cell] = max(0,min(cell_range,map[current_cell]))
-
- // Recurse until size is too small to subdivide.
- if(isize>3)
- sleep(-1)
- iteration++
- iterate(iteration, x, y, hsize)
- iterate(iteration, x+hsize, y, hsize)
- iterate(iteration, x, y+hsize, hsize)
- iterate(iteration, x+hsize, y+hsize, hsize)
-
-/datum/random_map/ore/apply_to_map()
- for(var/x = 0, x < real_size, x++)
- if((origin_x + x) > limit_x) continue
- for(var/y = 0, y < real_size, y++)
- if((origin_y + y) > limit_y) continue
- sleep(-1)
- apply_to_turf(x,y)
-
-/datum/random_map/ore/apply_to_turf(var/x,var/y)
-
- var/tx = origin_x+((x-1)*chunk_size)
- var/ty = origin_y+((y-1)*chunk_size)
-
- for(var/i=0,ilimit_y)
- continue
- for(var/j=0,jlimit_x)
- continue
-
- var/turf/T = locate(tx+j, ty+i, origin_z)
- if(!T || !T.has_resources)
- continue
-
- sleep(-1)
-
- T.resources = list()
- T.resources["silicates"] = rand(3,5)
- T.resources["carbonaceous rock"] = rand(3,5)
-
- var/current_cell = map[get_map_cell(x,y)]
- if(current_cell < rare_val) // Surface metals.
- T.resources["iron"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
- T.resources["gold"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
- T.resources["silver"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
- T.resources["uranium"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
- T.resources["diamond"] = 0
- T.resources["phoron"] = 0
- T.resources["osmium"] = 0
- T.resources["hydrogen"] = 0
- else if(current_cell < deep_val) // Rare metals.
- T.resources["gold"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
- T.resources["silver"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
- T.resources["uranium"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
- T.resources["phoron"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
- T.resources["osmium"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
- T.resources["hydrogen"] = 0
- T.resources["diamond"] = 0
- T.resources["iron"] = 0
- else // Deep metals.
- T.resources["uranium"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
- T.resources["diamond"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
- T.resources["phoron"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
- T.resources["osmium"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
- T.resources["hydrogen"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
- T.resources["iron"] = 0
- T.resources["gold"] = 0
- T.resources["silver"] = 0
-
- return
-
-/datum/random_map/ore/cleanup()
- return 1
-
-#undef MIN_SURFACE_COUNT
-#undef MIN_RARE_COUNT
-#undef MIN_DEEP_COUNT
-#undef RESOURCE_HIGH_MAX
-#undef RESOURCE_HIGH_MIN
-#undef RESOURCE_MID_MAX
-#undef RESOURCE_MID_MIN
-#undef RESOURCE_LOW_MAX
-#undef RESOURCE_LOW_MIN
\ No newline at end of file
diff --git a/code/modules/random_map/noise/desert.dm b/code/modules/random_map/noise/desert.dm
new file mode 100644
index 0000000000..1c7ca229a4
--- /dev/null
+++ b/code/modules/random_map/noise/desert.dm
@@ -0,0 +1,40 @@
+/datum/random_map/noise/desert
+ descriptor = "desert"
+ smoothing_iterations = 3
+
+/datum/random_map/noise/desert/replace_space
+ descriptor = "desert (replacement)"
+ target_turf_type = /turf/space
+
+/datum/random_map/noise/desert/get_map_char(var/value)
+ return "[pick(list(",",".","'","`"))]"
+
+/datum/random_map/noise/desert/get_appropriate_path(var/value)
+ var/val = min(9,max(0,round((value/cell_range)*10)))
+ if(isnull(val)) val = 0
+ switch(val)
+ if(0 to 1)
+ return /turf/simulated/floor/beach/water
+ else
+ return /turf/simulated/floor/beach/sand/desert
+
+/datum/random_map/noise/desert/get_additional_spawns(var/value, var/turf/T)
+ var/val = min(9,max(0,round((value/cell_range)*10)))
+ if(isnull(val)) val = 0
+ switch(val)
+ if(2 to 3)
+ if(prob(60))
+ var/grass_path = pick(typesof(/obj/structure/flora/grass)-/obj/structure/flora/grass)
+ new grass_path(T)
+ if(prob(5))
+ var/mob_type = pick(list(/mob/living/simple_animal/lizard, /mob/living/simple_animal/mouse))
+ new mob_type(T)
+ if(5 to 6)
+ if(prob(20))
+ var/grass_path = pick(typesof(/obj/structure/flora/grass)-/obj/structure/flora/grass)
+ new grass_path(T)
+ if(7 to 9)
+ if(prob(60))
+ new /obj/structure/flora/bush(T)
+ else if(prob(20))
+ new /obj/structure/flora/tree/dead(T)
diff --git a/code/modules/random_map/noise/magma.dm b/code/modules/random_map/noise/magma.dm
new file mode 100644
index 0000000000..64d649fd4e
--- /dev/null
+++ b/code/modules/random_map/noise/magma.dm
@@ -0,0 +1,44 @@
+// This is basically filler at this point. Subsidence and all kinds of fun
+// hazards will be included when it is done.
+/datum/random_map/noise/volcanism
+ descriptor = "volcanism"
+ smoothing_iterations = 6
+ target_turf_type = /turf/simulated
+
+// Get rid of those dumb little single-tile volcanic areas.
+/datum/random_map/noise/volcanism/cleanup()
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
+ var/current_cell = get_map_cell(x,y)
+ if(map[current_cell] < 178)
+ continue
+ var/count
+ var/tmp_cell = get_map_cell(x+1,y+1)
+ if(tmp_cell && map[tmp_cell] >= 178) count++
+ tmp_cell = get_map_cell(x-1,y-1)
+ if(tmp_cell && map[tmp_cell] >= 178) count++
+ tmp_cell = get_map_cell(x+1,y-1)
+ if(tmp_cell && map[tmp_cell] >= 178) count++
+ tmp_cell = get_map_cell(x-1,y+1)
+ if(tmp_cell && map[tmp_cell] >= 178) count++
+ tmp_cell = get_map_cell(x-1,y)
+ if(tmp_cell && map[tmp_cell] >= 178) count++
+ tmp_cell = get_map_cell(x,y-1)
+ if(tmp_cell && map[tmp_cell] >= 178) count++
+ tmp_cell = get_map_cell(x+1,y)
+ if(tmp_cell && map[tmp_cell] >= 178) count++
+ tmp_cell = get_map_cell(x,y+1)
+ if(tmp_cell && map[tmp_cell] >= 178) count++
+ if(!count)
+ map[current_cell] = 177
+
+/datum/random_map/noise/volcanism/get_appropriate_path(var/value)
+ return
+
+/datum/random_map/noise/volcanism/get_additional_spawns(var/value, var/turf/T)
+ if(value>=178)
+ if(istype(T,/turf/simulated/floor/plating/airless/asteroid))
+ T.ChangeTurf(/turf/simulated/floor/airless/lava)
+ else if(istype(T,/turf/simulated/mineral))
+ var/turf/simulated/mineral/M = T
+ M.mined_turf = /turf/simulated/floor/airless/lava
\ No newline at end of file
diff --git a/code/modules/random_map/noise/noise.dm b/code/modules/random_map/noise/noise.dm
new file mode 100644
index 0000000000..7e4323158e
--- /dev/null
+++ b/code/modules/random_map/noise/noise.dm
@@ -0,0 +1,168 @@
+// NOTE: Maps generated with this datum as the base are not DIRECTLY compatible with maps generated from
+// the automata, building or maze datums, as the noise generator uses 0-255 instead of WALL_CHAR/FLOOR_CHAR.
+// TODO: Consider writing a conversion proc for noise-to-regular maps.
+/datum/random_map/noise
+ descriptor = "distribution map"
+ var/cell_range = 255 // These values are used to seed ore values rather than to determine a turf type.
+ var/cell_smooth_amt = 5
+ var/random_variance_chance = 25 // % chance of applying random_element.
+ var/random_element = 0.5 // Determines the variance when smoothing out cell values.
+ var/cell_base // Set in New()
+ var/initial_cell_range // Set in New()
+ var/smoothing_iterations = 0
+
+/datum/random_map/noise/New()
+ initial_cell_range = cell_range/5
+ cell_base = cell_range/2
+ ..()
+
+/datum/random_map/noise/set_map_size()
+ // Make sure the grid is a square with limits that are
+ // (n^2)+1, otherwise diamond-square won't work.
+ if(!IsPowerOfTwo((limit_x-1)))
+ limit_x = RoundUpToPowerOfTwo(limit_x) + 1
+ if(!IsPowerOfTwo((limit_y-1)))
+ limit_y = RoundUpToPowerOfTwo(limit_y) + 1
+ // Sides must be identical lengths.
+ if(limit_x > limit_y)
+ limit_y = limit_x
+ else if(limit_y > limit_x)
+ limit_x = limit_y
+ ..()
+
+// Diamond-square algorithm.
+/datum/random_map/noise/seed_map()
+ // Instantiate the grid.
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
+ map[get_map_cell(x,y)] = 0
+
+ // Now dump in the actual random data.
+ map[get_map_cell(1,1)] = cell_base+rand(initial_cell_range)
+ map[get_map_cell(1,limit_y)] = cell_base+rand(initial_cell_range)
+ map[get_map_cell(limit_x,limit_y)] = cell_base+rand(initial_cell_range)
+ map[get_map_cell(limit_x,1)] = cell_base+rand(initial_cell_range)
+
+/datum/random_map/noise/generate_map()
+ // Begin recursion.
+ subdivide(1,1,1,(limit_y-1))
+
+/datum/random_map/noise/get_map_char(var/value)
+ var/val = min(9,max(0,round((value/cell_range)*10)))
+ if(isnull(val)) val = 0
+ return "[val]"
+
+/datum/random_map/noise/proc/subdivide(var/iteration,var/x,var/y,var/input_size)
+
+ var/isize = input_size
+ var/hsize = round(input_size/2)
+
+ /*
+ (x,y+isize)----(x+hsize,y+isize)----(x+size,y+isize)
+ | | |
+ | | |
+ | | |
+ (x,y+hsize)----(x+hsize,y+hsize)----(x+isize,y)
+ | | |
+ | | |
+ | | |
+ (x,y)----------(x+hsize,y)----------(x+isize,y)
+ */
+ // Central edge values become average of corners.
+ map[get_map_cell(x+hsize,y+isize)] = round((\
+ map[get_map_cell(x,y+isize)] + \
+ map[get_map_cell(x+isize,y+isize)] \
+ )/2)
+
+ map[get_map_cell(x+hsize,y)] = round(( \
+ map[get_map_cell(x,y)] + \
+ map[get_map_cell(x+isize,y)] \
+ )/2)
+
+ map[get_map_cell(x,y+hsize)] = round(( \
+ map[get_map_cell(x,y+isize)] + \
+ map[get_map_cell(x,y)] \
+ )/2)
+
+ map[get_map_cell(x+isize,y+hsize)] = round(( \
+ map[get_map_cell(x+isize,y+isize)] + \
+ map[get_map_cell(x+isize,y)] \
+ )/2)
+
+ // Centre value becomes the average of all other values + possible random variance.
+ var/current_cell = get_map_cell(x+hsize,y+hsize)
+ map[current_cell] = round(( \
+ map[get_map_cell(x+hsize,y+isize)] + \
+ map[get_map_cell(x+hsize,y)] + \
+ map[get_map_cell(x,y+hsize)] + \
+ map[get_map_cell(x+isize,y)] \
+ )/4)
+
+ if(prob(random_variance_chance))
+ map[current_cell] *= (rand(1,2)==1 ? (1.0-random_element) : (1.0+random_element))
+ map[current_cell] = max(0,min(cell_range,map[current_cell]))
+
+ // Recurse until size is too small to subdivide.
+ if(isize>3)
+ if(!priority_process) sleep(-1)
+ iteration++
+ subdivide(iteration, x, y, hsize)
+ subdivide(iteration, x+hsize, y, hsize)
+ subdivide(iteration, x, y+hsize, hsize)
+ subdivide(iteration, x+hsize, y+hsize, hsize)
+
+/datum/random_map/noise/cleanup()
+
+ for(var/i = 1;i<=smoothing_iterations;i++)
+ var/list/next_map[limit_x*limit_y]
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
+
+ var/current_cell = get_map_cell(x,y)
+ next_map[current_cell] = map[current_cell]
+ var/val_count = 0
+ var/total = 0
+
+ // Get the average neighboring value.
+ var/tmp_cell = get_map_cell(x+1,y+1)
+ if(tmp_cell)
+ total += map[tmp_cell]
+ val_count++
+ tmp_cell = get_map_cell(x-1,y-1)
+ if(tmp_cell)
+ total += map[tmp_cell]
+ val_count++
+ tmp_cell = get_map_cell(x+1,y-1)
+ if(tmp_cell)
+ total += map[tmp_cell]
+ val_count++
+ tmp_cell = get_map_cell(x-1,y+1)
+ if(tmp_cell)
+ total += map[tmp_cell]
+ val_count++
+ tmp_cell = get_map_cell(x-1,y)
+ if(tmp_cell)
+ total += map[tmp_cell]
+ val_count++
+ tmp_cell = get_map_cell(x,y-1)
+ if(tmp_cell)
+ total += map[tmp_cell]
+ val_count++
+ tmp_cell = get_map_cell(x+1,y)
+ if(tmp_cell)
+ total += map[tmp_cell]
+ val_count++
+ tmp_cell = get_map_cell(x,y+1)
+ if(tmp_cell)
+ total += map[tmp_cell]
+ val_count++
+ total = round(total/val_count)
+
+ if(abs(map[current_cell]-total) <= cell_smooth_amt)
+ map[current_cell] = total
+ else if(map[current_cell] < total)
+ map[current_cell]+=cell_smooth_amt
+ else if(map[current_cell] < total)
+ map[current_cell]-=cell_smooth_amt
+ map[current_cell] = max(0,min(cell_range,map[current_cell]))
+ map = next_map
\ No newline at end of file
diff --git a/code/modules/random_map/noise/ore.dm b/code/modules/random_map/noise/ore.dm
new file mode 100644
index 0000000000..5e565df18b
--- /dev/null
+++ b/code/modules/random_map/noise/ore.dm
@@ -0,0 +1,90 @@
+/datum/random_map/noise/ore
+ descriptor = "ore distribution map"
+ var/deep_val = 0.8 // Threshold for deep metals, set in new as percentage of cell_range.
+ var/rare_val = 0.7 // Threshold for rare metal, set in new as percentage of cell_range.
+ var/chunk_size = 4 // Size each cell represents on map
+
+/datum/random_map/noise/ore/New()
+ rare_val = cell_range * rare_val
+ deep_val = cell_range * deep_val
+ ..()
+
+/datum/random_map/noise/ore/check_map_sanity()
+
+ var/rare_count = 0
+ var/surface_count = 0
+ var/deep_count = 0
+
+ // Increment map sanity counters.
+ for(var/value in map)
+ if(value < rare_val)
+ surface_count++
+ else if(value < deep_val)
+ rare_count++
+ else
+ deep_count++
+ // Sanity check.
+ if(surface_count < MIN_SURFACE_COUNT)
+ admin_notice("Insufficient surface minerals. Rerolling...", R_DEBUG)
+ return 0
+ else if(rare_count < MIN_RARE_COUNT)
+ admin_notice("Insufficient rare minerals. Rerolling...", R_DEBUG)
+ return 0
+ else if(deep_count < MIN_DEEP_COUNT)
+ admin_notice("Insufficient deep minerals. Rerolling...", R_DEBUG)
+ return 0
+ else
+ return 1
+
+/datum/random_map/noise/ore/apply_to_turf(var/x,var/y)
+
+ var/tx = (origin_x+(x-1))*chunk_size
+ var/ty = (origin_y+(y-1))*chunk_size
+
+ for(var/i=0,i~"
+ if(1)
+ return "~"
+ if(2)
+ return "~"
+ if(3)
+ return "[pick(list(".",","))]"
+ if(4)
+ return "[pick(list(".",","))]"
+ if(5)
+ return "[pick(list(".",","))]"
+ if(6)
+ return "[pick(list(".",","))]"
+ if(7)
+ return "[pick(list("T","t"))]"
+ if(8)
+ return "[pick(list("T","t"))]"
+ if(9)
+ return "[pick(list("T","t"))]"
+
+/datum/random_map/noise/tundra/get_appropriate_path(var/value)
+ var/val = min(9,max(0,round((value/cell_range)*10)))
+ if(isnull(val)) val = 0
+ switch(val)
+ if(0 to 4)
+ return /turf/simulated/floor/beach/water/ocean
+ else
+ return /turf/simulated/floor/snow
+
+/datum/random_map/noise/tundra/get_additional_spawns(var/value, var/turf/T)
+ var/val = min(9,max(0,round((value/cell_range)*10)))
+ if(isnull(val)) val = 0
+ switch(val)
+ if(2)
+ if(prob(5))
+ new /mob/living/simple_animal/crab(T)
+ if(6)
+ if(prob(60))
+ var/grass_path = pick(typesof(/obj/structure/flora/grass)-/obj/structure/flora/grass)
+ new grass_path(T)
+ if(prob(5))
+ var/mob_type = pick(list(/mob/living/simple_animal/lizard, /mob/living/simple_animal/mouse))
+ new mob_type(T)
+ if(7)
+ if(prob(60))
+ new /obj/structure/flora/bush(T)
+ else if(prob(30))
+ new /obj/structure/flora/tree/pine(T)
+ else if(prob(20))
+ new /obj/structure/flora/tree/dead(T)
+ if(8)
+ if(prob(70))
+ new /obj/structure/flora/tree/pine(T)
+ else if(prob(30))
+ new /obj/structure/flora/tree/dead(T)
+ else
+ new /obj/structure/flora/bush(T)
+ if(9)
+ new /obj/structure/flora/tree/pine(T)
diff --git a/code/modules/random_map/random_map.dm b/code/modules/random_map/random_map.dm
index 81def6be14..ced9f009b9 100644
--- a/code/modules/random_map/random_map.dm
+++ b/code/modules/random_map/random_map.dm
@@ -1,173 +1,206 @@
-#define ORE_COUNT 1000
-/*
- This module is used to generate the debris fields/distribution maps/procedural stations.
-*/
-
+// Generates cave systems for the asteroid, and places ore tiles.
var/global/list/random_maps = list()
+var/global/list/map_count = list()
/datum/random_map
- var/descriptor = "asteroid" // Display name.
- var/real_size = 246 // Size of each edge (must be square :().
- var/cell_range = 2 // Random range for initial cells.
- var/iterations = 5 // Number of times to apply the automata rule.
+
+ // Strings.
+ var/name // Set in New()
+ var/descriptor = "random map" // Display name.
+
+ // Locator/value vars.
+ var/initial_wall_cell = 100 // % Chance that a cell will be seeded as a wall.
var/max_attempts = 5 // Fail if a sane map isn't generated by this point.
- var/raw_map_size // Used for creating new maps each iteration. Value must be real_size^2
- var/list/map = list() // Actual map.
var/origin_x = 1 // Origin point, left.
var/origin_y = 1 // Origin point, bottom.
var/origin_z = 1 // Target Z-level.
- var/limit_x = 256 // Maximum x bound.
- var/limit_y = 256 // Maximum y bound.
- var/iterate_before_fail = 120 // Infinite loop safeguard.
+ var/limit_x = 128 // Default x size.
+ var/limit_y = 128 // Default y size.
+ var/auto_apply = 1
+
+ // Turf paths.
+ var/wall_type = /turf/simulated/wall
+ var/floor_type = /turf/simulated/floor
+ var/target_turf_type
+
+ // Storage for the final iteration of the map.
+ var/list/map = list() // Actual map.
+
+ // If set, all sleep(-1) calls will be skipped.
+ // Test to see if rand_seed() can be used reliably.
+ var/priority_process
+
+/datum/random_map/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce)
+
+ // Store this for debugging.
+ if(!map_count[descriptor])
+ map_count[descriptor] = 1
+ else
+ map_count[descriptor]++
+ name = "[descriptor] #[map_count[descriptor]]"
+ random_maps[name] = src
+
+ // Get origins for applying the map later.
+ origin_x = (!isnull(tx) ? tx : 1)
+ origin_y = (!isnull(ty) ? ty : 1)
+ origin_z = (!isnull(tz) ? tz : 1)
+ if(tlx) limit_x = tlx
+ if(tly) limit_y = tly
+
+ if(do_not_apply)
+ auto_apply = null
+
+ // Initialize map.
+ set_map_size()
+
+ var/start_time = world.timeofday
+ if(!do_not_announce) admin_notice("Generating [name].", R_DEBUG)
+ sleep(-1)
+
+ // Testing needed to see how reliable this is (asynchronous calls, called during worldgen), DM ref is not optimistic
+ if(seed)
+ rand_seed(seed)
+ priority_process = 1
+
+ for(var/i = 0;i[capitalize(name)] generation completed in [round(0.1*(world.timeofday-start_time),0.1)] seconds.", R_DEBUG)
+ return
+ if(!do_not_announce) admin_notice("[capitalize(name)] failed to generate ([round(0.1*(world.timeofday-start_time),0.1)] seconds): could not produce sane map.", R_DEBUG)
/datum/random_map/proc/get_map_cell(var/x,var/y)
- return ((y-1)*real_size)+x
+ var/cell = ((y-1)*limit_x)+x
+ if((cell < 1) || (cell > map.len))
+ return null
+ else
+ return cell
+
+/datum/random_map/proc/get_map_char(var/value)
+ switch(value)
+ if(WALL_CHAR)
+ return "#"
+ if(FLOOR_CHAR)
+ return "."
+ if(DOOR_CHAR)
+ return "D"
+ if(ROOM_TEMP_CHAR)
+ return "+"
+ if(MONSTER_CHAR)
+ return "M"
+ if(ARTIFACT_TURF_CHAR)
+ return "_"
+ if(ARTIFACT_CHAR)
+ return "A"
+ else
+ return " "
/datum/random_map/proc/display_map(atom/user)
if(!user)
user = world
- for(var/x = 1, x <= real_size, x++)
- var/line = ""
- for(var/y = 1, y <= real_size, y++)
+ var/dat = "+------+
"
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
var/current_cell = get_map_cell(x,y)
if(within_bounds(current_cell))
- if(map[current_cell] == 2)
- line += "#"
- else
- line += "."
- user << line
-
-/datum/random_map/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly)
-
- // Store this for debugging.
- random_maps |= src
-
- // Initialize map.
- set_map_size()
-
- // Get origins for applying the map later.
- if(tx) origin_x = tx
- if(ty) origin_y = ty
- if(tz) origin_z = tz
- if(tlx) limit_x = tlx
- if(tly) limit_y = tly
-
- // testing needed to see how reliable this is (asynchronous calls, called during worldgen), DM ref is not optimistic
- if(seed) rand_seed(seed)
-
- var/start_time = world.timeofday
- admin_notice("Generating [descriptor].", R_DEBUG)
- for(var/i = 0;i[capitalize(descriptor)] generation completed in [round(0.1*(world.timeofday-start_time),0.1)] seconds.", R_DEBUG)
- return
- admin_notice("[capitalize(descriptor)] generation failed in [round(0.1*(world.timeofday-start_time),0.1)] seconds: could not produce sane map.", R_DEBUG)
+ dat += get_map_char(map[current_cell])
+ dat += "
"
+ user << "[dat]+------+"
/datum/random_map/proc/within_bounds(var/val)
- return (val>0) && (val<=raw_map_size)
+ if(!islist(map))
+ set_map_size()
+ return (val>0) && (val<=map.len)
-/datum/random_map/proc/set_map_size(var/raw_size)
- if(!raw_size)
- raw_size = real_size * real_size
- raw_map_size = raw_size
- map.len = raw_map_size
+/datum/random_map/proc/set_map_size()
+ map = list()
+ map.len = limit_x * limit_y
/datum/random_map/proc/seed_map()
- for(var/x = 1, x <= real_size, x++)
- for(var/y = 1, y <= real_size, y++)
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
var/current_cell = get_map_cell(x,y)
- if(prob(55))
- map[current_cell] = 2
+ if(prob(initial_wall_cell))
+ map[current_cell] = WALL_CHAR
else
- map[current_cell] = 1
+ map[current_cell] = FLOOR_CHAR
/datum/random_map/proc/clear_map()
- for(var/x = 1, x <= real_size, x++)
- for(var/y = 1, y <= real_size, y++)
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
map[get_map_cell(x,y)] = 0
/datum/random_map/proc/generate()
seed_map()
- for(var/i=1;i<=iterations;i++)
- iterate(i)
+ generate_map()
if(check_map_sanity())
cleanup()
- apply_to_map()
+ if(auto_apply)
+ apply_to_map()
return 1
return 0
-/datum/random_map/proc/iterate(var/iteration)
- var/list/next_map[raw_map_size]
- for(var/x = 1, x <= real_size, x++)
- for(var/y = 1, y <= real_size, y++)
- var/current_cell = get_map_cell(x,y)
- // Sanity check.
- if(!within_bounds(current_cell))
- continue
- // Copy over original value.
- next_map[current_cell] = map[current_cell]
- // Check all neighbors.
- var/count = 0
- for(var/cell in list(current_cell,get_map_cell(x+1,y+1),get_map_cell(x-1,y-1),get_map_cell(x+1,y-1),get_map_cell(x-1,y+1),get_map_cell(x-1,y),get_map_cell(x,y-1),get_map_cell(x+1,y),get_map_cell(x,y+1)))
- if(within_bounds(cell) && map[cell] == 2)
- count++
- if(count>=5)
- next_map[current_cell] = 2 // becomes a wall
- else
- next_map[current_cell] = 1 // becomes a floor
- map = next_map
+// Unused for basic map.
+/datum/random_map/proc/generate_map()
+ return 1
/datum/random_map/proc/check_map_sanity()
return 1
-/datum/random_map/proc/apply_to_map()
- for(var/x = 0, x < real_size, x++)
- if((origin_x + x) > limit_x) continue
- for(var/y = 0, y < real_size, y++)
- if((origin_y + y) > limit_y) continue
- sleep(-1)
- apply_to_turf(origin_x+x,origin_y+y)
+/datum/random_map/proc/apply_to_map(var/tx, var/ty, var/tz)
+ if(!tx) tx = isnull(origin_x) ? 1 : origin_x
+ if(!ty) ty = isnull(origin_y) ? 1 : origin_y
+ if(!tz) tz = isnull(origin_z) ? 1 : origin_z
-/datum/random_map/proc/apply_to_turf(var/x,var/y)
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
+ if(!priority_process) sleep(-1)
+ apply_to_turf((tx-1)+x,(ty-1)+y,tz)
+
+/datum/random_map/proc/apply_to_turf(var/x,var/y,var/z)
var/current_cell = get_map_cell(x,y)
if(!within_bounds(current_cell))
- return
- var/turf/T = locate(x,y,origin_z)
- if(!T || !istype(T,/turf/unsimulated/mask))
- return
- switch(map[current_cell])
- if(1)
- T.ChangeTurf(/turf/simulated/floor/plating/airless/asteroid)
- if(2)
- T.ChangeTurf(/turf/simulated/mineral)
- if(3)
- T.ChangeTurf(/turf/simulated/mineral/random)
- if(4)
- T.ChangeTurf(/turf/simulated/mineral/random/high_chance)
+ return 0
+ var/turf/T = locate(x,y,z)
+ if(!T || (target_turf_type && !istype(T,target_turf_type)))
+ return 0
+ var/newpath = get_appropriate_path(map[current_cell])
+ if(newpath)
+ T.ChangeTurf(newpath)
+ get_additional_spawns(map[current_cell],T)
+ return T
+
+/datum/random_map/proc/get_appropriate_path(var/value)
+ switch(value)
+ if(FLOOR_CHAR)
+ return floor_type
+ if(WALL_CHAR)
+ return wall_type
+
+/datum/random_map/proc/get_additional_spawns(var/value, var/turf/T)
+ if(value == DOOR_CHAR)
+ new /obj/machinery/door/airlock(T)
/datum/random_map/proc/cleanup()
+ return
- sleep(-1)
- // Create ore.
- var/ore_count = ORE_COUNT
- while(ore_count)
- var/check_cell = get_map_cell(rand(1,real_size),rand(1,real_size))
- if(!(within_bounds(check_cell)) || map[check_cell] != 2)
- continue
- if(prob(25))
- map[check_cell] = 4
- else
- map[check_cell] = 3
- ore_count--
+/datum/random_map/proc/overlay_with(var/datum/random_map/target_map, var/tx, var/ty)
+ if(!map.len || !istype(target_map))
+ return
+ tx-- // Update origin so that x/y index
+ ty-- // doesn't push it off-kilter by one.
+ for(var/x = 1, x <= limit_x, x++)
+ for(var/y = 1, y <= limit_y, y++)
+ var/current_cell = get_map_cell(x,y)
+ if(!within_bounds(current_cell))
+ continue
+ if(tx+x > target_map.limit_x)
+ continue
+ if(ty+y > target_map.limit_y)
+ continue
+ target_map.map[target_map.get_map_cell(tx+x,ty+y)] = map[current_cell]
+ handle_post_overlay_on(target_map,tx,ty)
- sleep(-1)
-
- // Place random asteroid rooms.
- var/rooms_placed = 0
- for(var/i = 0, i < max_secret_rooms, i++)
- if(make_mining_asteroid_secret())
- rooms_placed++
- admin_notice("Placed [rooms_placed] secrets.", R_DEBUG)
- return 1
\ No newline at end of file
+/datum/random_map/proc/handle_post_overlay_on(var/datum/random_map/target_map, var/tx, var/ty)
+ return
\ No newline at end of file
diff --git a/code/modules/random_map/random_map_verbs.dm b/code/modules/random_map/random_map_verbs.dm
new file mode 100644
index 0000000000..6ab98e20b7
--- /dev/null
+++ b/code/modules/random_map/random_map_verbs.dm
@@ -0,0 +1,107 @@
+/client/proc/print_random_map()
+ set category = "Debug"
+ set name = "Display Random Map"
+ set desc = "Show the contents of a random map."
+
+ if(!holder) return
+
+ var/choice = input("Choose a map to display.") as null|anything in random_maps
+ if(!choice)
+ return
+ var/datum/random_map/M = random_maps[choice]
+ if(istype(M))
+ M.display_map(usr)
+
+/client/proc/delete_random_map()
+ set category = "Debug"
+ set name = "Delete Random Map"
+ set desc = "Delete a random map."
+
+ if(!holder) return
+
+ var/choice = input("Choose a map to delete.") as null|anything in random_maps
+ if(!choice)
+ return
+ var/datum/random_map/M = random_maps[choice]
+ random_maps[choice] = null
+ if(istype(M))
+ message_admins("[key_name_admin(usr)] has deleted [M.name].")
+ log_admin("[key_name(usr)] has deleted [M.name].")
+ qdel(M)
+
+/client/proc/create_random_map()
+ set category = "Debug"
+ set name = "Create Random Map"
+ set desc = "Create a random map."
+
+ if(!holder) return
+
+ var/map_datum = input("Choose a map to create.") as null|anything in typesof(/datum/random_map)-/datum/random_map
+ if(!map_datum)
+ return
+
+ var/datum/random_map/M
+ if(alert("Do you wish to customise the map?",,"Yes","No") == "Yes")
+ var/seed = input("Seed? (blank for none)") as text|null
+ var/lx = input("X-size? (blank for default)") as num|null
+ var/ly = input("Y-size? (blank for default)") as num|null
+ M = new map_datum(seed,null,null,null,lx,ly,1)
+ else
+ M = new map_datum(null,null,null,null,null,null,1)
+
+ if(M)
+ message_admins("[key_name_admin(usr)] has created [M.name].")
+ log_admin("[key_name(usr)] has created [M.name].")
+
+/client/proc/apply_random_map()
+ set category = "Debug"
+ set name = "Apply Random Map"
+ set desc = "Apply a map to the game world."
+
+ if(!holder) return
+
+ var/choice = input("Choose a map to apply.") as null|anything in random_maps
+ if(!choice)
+ return
+ var/datum/random_map/M = random_maps[choice]
+ if(istype(M))
+ var/tx = input("X? (default to current turf)") as num|null
+ var/ty = input("Y? (default to current turf)") as num|null
+ var/tz = input("Z? (default to current turf)") as num|null
+ if(isnull(tx) || isnull(ty) || isnull(tz))
+ var/turf/T = get_turf(usr)
+ tx = !isnull(tx) ? tx : T.x
+ ty = !isnull(ty) ? ty : T.y
+ tz = !isnull(tz) ? tz : T.z
+ message_admins("[key_name_admin(usr)] has applied [M.name] at x[tx],y[ty],z[tz].")
+ log_admin("[key_name(usr)] has applied [M.name] at x[tx],y[ty],z[tz].")
+ M.apply_to_map(tx,ty,tz)
+
+/client/proc/overlay_random_map()
+ set category = "Debug"
+ set name = "Overlay Random Map"
+ set desc = "Apply a map to another map."
+
+ if(!holder) return
+
+ var/choice = input("Choose a map as base.") as null|anything in random_maps
+ if(!choice)
+ return
+ var/datum/random_map/base_map = random_maps[choice]
+
+ choice = null
+ choice = input("Choose a map to overlay.") as null|anything in random_maps
+ if(!choice)
+ return
+
+ var/datum/random_map/overlay_map = random_maps[choice]
+
+ if(istype(base_map) && istype(overlay_map))
+ var/tx = input("X? (default to 1)") as num|null
+ var/ty = input("Y? (default to 1)") as num|null
+ if(!tx) tx = 1
+ if(!ty) ty = 1
+ message_admins("[key_name_admin(usr)] has applied [overlay_map.name] to [base_map.name] at x[tx],y[ty].")
+ log_admin("[key_name(usr)] has applied [overlay_map.name] to [base_map.name] at x[tx],y[ty].")
+ overlay_map.overlay_with(base_map,tx,ty)
+ base_map.display_map(usr)
diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm
index aa1e1a52e4..7e3ec70149 100644
--- a/code/modules/research/message_server.dm
+++ b/code/modules/research/message_server.dm
@@ -108,6 +108,34 @@ var/global/list/obj/machinery/message_server/message_servers = list()
/obj/machinery/message_server/proc/send_rc_message(var/recipient = "",var/sender = "",var/message = "",var/stamp = "", var/id_auth = "", var/priority = 1)
rc_msgs += new/datum/data_rc_msg(recipient,sender,message,stamp,id_auth)
+ var/authmsg = "[message]
"
+ if (id_auth)
+ authmsg += "[id_auth]
"
+ if (stamp)
+ authmsg += "[stamp]
"
+ for (var/obj/machinery/requests_console/Console in allConsoles)
+ if (ckey(Console.department) == ckey(recipient))
+ if(Console.newmessagepriority < priority)
+ Console.newmessagepriority = priority
+ Console.icon_state = "req_comp[priority]"
+ switch(priority)
+ if(2)
+ if(!Console.silent)
+ playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1)
+ Console.audible_message(text("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [sender]'"),,5)
+ Console.messages += "High Priority message from [sender]
[authmsg]"
+ if(3)
+ if(!Console.silent)
+ playsound(Console.loc, 'sound/machines/twobeep.ogg', 70, 1)
+ Console.audible_message(text("\icon[Console] *The Requests Console yells: 'EXTREME PRIORITY alert in [sender]'"),,7)
+ Console.messages += "Extreme Priority message from [sender]
[authmsg]"
+ else
+ if(!Console.silent)
+ playsound(Console.loc, 'sound/machines/twobeep.ogg', 50, 1)
+ Console.audible_message(text("\icon[Console] *The Requests Console beeps: 'Message from [sender]'"),,4)
+ Console.messages += "Message from [sender]
[authmsg]"
+ Console.set_light(2)
+
/obj/machinery/message_server/attack_hand(user as mob)
// user << "\blue There seem to be some parts missing from this server. They should arrive on the station in a few days, give or take a few CentCom delays."
diff --git a/code/modules/research/xenoarchaeology/finds/finds_special.dm b/code/modules/research/xenoarchaeology/finds/finds_special.dm
index b2c0fb3898..af73f541d6 100644
--- a/code/modules/research/xenoarchaeology/finds/finds_special.dm
+++ b/code/modules/research/xenoarchaeology/finds/finds_special.dm
@@ -127,7 +127,7 @@
playsound(src.loc, pick('sound/hallucinations/wail.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/far_noise.ogg'), 50, 1, -3)
nearby_mobs.Add(M)
- var/target = pick("chest","groin","head","l_arm","r_arm","r_leg","l_leg","l_hand","r_hand","l_foot","r_foot")
+ var/target = pick(M.organs_by_name)
M.apply_damage(rand(5, 10), BRUTE, target)
M << "\red The skin on your [parse_zone(target)] feels like it's ripping apart, and a stream of blood flies out."
var/obj/effect/decal/cleanable/blood/splatter/animated/B = new(M.loc)
diff --git a/code/modules/spells/spellbook.dm b/code/modules/spells/spellbook.dm
index 169d750944..0c13e4ac93 100644
--- a/code/modules/spells/spellbook.dm
+++ b/code/modules/spells/spellbook.dm
@@ -14,6 +14,10 @@
/obj/item/weapon/spellbook/attack_self(mob/user = usr)
if(!user)
return
+ if((user.mind && !wizards.is_antagonist(user.mind)))
+ usr << "You stare at the book but cannot make sense of the markings!"
+ return
+
user.set_machine(src)
var/dat
if(temp)
diff --git a/code/world.dm b/code/world.dm
index e74268f9ff..9c78a38cec 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -72,9 +72,20 @@ var/global/datum/global_init/init = new ()
// This is kinda important. Set up details of what the hell things are made of.
populate_material_list()
- //Create the asteroid Z-level.
if(config.generate_asteroid)
- new /datum/random_map(null,13,32,5,217,223)
+ // These values determine the specific area that the map is applied to.
+ // If you do not use the official Baycode moonbase map, you will need to change them.
+ //Create the mining Z-level.
+ new /datum/random_map/automata/cave_system(null,1,1,5,255,255)
+ //new /datum/random_map/noise/volcanism(null,1,1,5,255,255) // Not done yet! Pretty, though.
+ // Create the mining ore distribution map.
+ new /datum/random_map/noise/ore(null, 1, 1, 5, 64, 64)
+ // Update all turfs to ensure everything looks good post-generation. Yes,
+ // it's brute-forcey, but frankly the alternative is a mine turf rewrite.
+ for(var/turf/simulated/mineral/M in world) // Ugh.
+ M.updateMineralOverlays()
+ for(var/turf/simulated/floor/plating/airless/asteroid/M in world) // Uuuuuugh.
+ M.updateMineralOverlays()
// Create autolathe recipes, as above.
populate_lathe_recipes()
diff --git a/html/changelog.html b/html/changelog.html
index a333ef505e..73f2aecf83 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -56,7 +56,21 @@
-->
-
01 June 2015
+
04 June 2015
+
PsiOmegaDelta updated:
+
+ - AI eyes can now be found in the observer follow list.
+ - Synths can now review all law modules that can be found on the station from their law manager.
+ - Synths can state these laws if desired, however this is strongly discouraged unless subverted/malfunctioning.
+ - Astral projecting mobs, such as wizards or cultists, may no longer respawn as something else while their body lives.
+
+
Techhead updated:
+
+ - Prison break event has been expanded to include Virology or Xenobiology
+ - Prison break event will warn Enginering and the AI beforehand so they can take preventive measures.
+ - Disabling area power will now prevent doors from opening during the event
+
+
02 June 2015
Techhead updated: