mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-12 03:02:54 +00:00
Refactored random map generator system and added several terrain generators.
Created a global list to track base turfs for explosions/shuttle moves. Remaps the asteroid to be a moonlet. Tidies up some references to 'asteroid', removes moonbase from the accessible z level list.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 << "<u>Zone Air Contents</u>"
|
||||
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 << "<u>Connections: [length(connections)]</u>"
|
||||
|
||||
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 << "\red 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"
|
||||
|
||||
|
||||
@@ -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))
|
||||
@@ -921,7 +921,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 +1004,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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
|
||||
27
code/game/base_turf.dm
Normal file
27
code/game/base_turf.dm
Normal file
@@ -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)].")
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
var/base_turf = get_base_turf(src.z)
|
||||
if(ST.type != base_turf)
|
||||
ST.ChangeTurf(base_turf)
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
desc = "This is an upgraded version of the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)"
|
||||
icon_state = "mecha_diamond_drill"
|
||||
origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINERING = 3)
|
||||
construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"diamond"=6500)
|
||||
construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"diamond"=6500)
|
||||
equip_cooldown = 20
|
||||
force = 15
|
||||
|
||||
@@ -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))
|
||||
@@ -974,7 +974,7 @@
|
||||
desc = "Generates power using uranium. Pollutes the environment."
|
||||
icon_state = "tesla"
|
||||
origin_tech = list(TECH_POWER = 3, TECH_ENGINERING = 3)
|
||||
construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"silver"=500,"glass"=1000)
|
||||
construction_cost = list(DEFAULT_WALL_MATERIAL=10000,"silver"=500,"glass"=1000)
|
||||
max_fuel = 50000
|
||||
fuel_per_cycle_idle = 10
|
||||
fuel_per_cycle_active = 30
|
||||
@@ -1071,8 +1071,8 @@
|
||||
icon_state = "mecha_abooster_ccw"
|
||||
origin_tech = list(TECH_ENGINERING = 1, TECH_BIO = 1)
|
||||
energy_drain = 10
|
||||
range = MELEE
|
||||
construction_cost = list(DEFAULT_WALL_MATERIAL=5000,"glass"=5000)
|
||||
range = MELEE
|
||||
construction_cost = list(DEFAULT_WALL_MATERIAL=5000,"glass"=5000)
|
||||
equip_cooldown = 20
|
||||
var/mob/living/carbon/occupant = null
|
||||
var/door_locked = 1
|
||||
|
||||
@@ -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 << "\red You must be on the ground!"
|
||||
return
|
||||
if (!( istype(T, /turf/space) ))
|
||||
user << "\red 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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
@@ -218,4 +236,4 @@
|
||||
icon_state = "snow"
|
||||
|
||||
/turf/simulated/floor/plating/snow/ex_act(severity)
|
||||
return
|
||||
return
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/turf/space
|
||||
icon = 'icons/turf/space.dmi'
|
||||
name = "\proper space"
|
||||
@@ -69,7 +67,7 @@
|
||||
// Okay, so let's make it so that people can travel z levels but not nuke disks!
|
||||
// if(ticker.mode.name == "mercenary") return
|
||||
if (A.x <= TRANSITIONEDGE || A.x >= (world.maxx - TRANSITIONEDGE - 1) || A.y <= TRANSITIONEDGE || A.y >= (world.maxy - TRANSITIONEDGE - 1))
|
||||
A.touch_map_edge()
|
||||
A.touch_map_edge()
|
||||
|
||||
/turf/space/proc/Sandbox_Spacemove(atom/movable/A as mob|obj)
|
||||
var/cur_x
|
||||
|
||||
@@ -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) )
|
||||
|
||||
|
||||
@@ -167,6 +167,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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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("<span class='notice'>An old dusty crate was buried within!</span>")
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
22
code/modules/random_map/_random_map_setup.dm
Normal file
22
code/modules/random_map/_random_map_setup.dm
Normal file
@@ -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
|
||||
65
code/modules/random_map/automata/automata.dm
Normal file
65
code/modules/random_map/automata/automata.dm
Normal file
@@ -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
|
||||
52
code/modules/random_map/automata/caves.dm
Normal file
52
code/modules/random_map/automata/caves.dm
Normal file
@@ -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
|
||||
55
code/modules/random_map/building/building.dm
Normal file
55
code/modules/random_map/building/building.dm
Normal file
@@ -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
|
||||
65
code/modules/random_map/mazes/maze.dm
Normal file
65
code/modules/random_map/mazes/maze.dm
Normal file
@@ -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
|
||||
18
code/modules/random_map/mazes/maze_cell.dm
Normal file
18
code/modules/random_map/mazes/maze_cell.dm
Normal file
@@ -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
|
||||
@@ -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("<span class='danger'>Insufficient surface minerals. Rerolling...</span>", R_DEBUG)
|
||||
return 0
|
||||
else if(rare_count < MIN_RARE_COUNT)
|
||||
admin_notice("<span class='danger'>Insufficient rare minerals. Rerolling...</span>", R_DEBUG)
|
||||
return 0
|
||||
else if(deep_count < MIN_DEEP_COUNT)
|
||||
admin_notice("<span class='danger'>Insufficient deep minerals. Rerolling...</span>", 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("<span class='danger'>Iteration count exceeded, aborting.</span>", 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,i<chunk_size,i++)
|
||||
if(ty+i>limit_y)
|
||||
continue
|
||||
for(var/j=0,j<chunk_size,j++)
|
||||
if(tx+j>limit_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
|
||||
40
code/modules/random_map/noise/desert.dm
Normal file
40
code/modules/random_map/noise/desert.dm
Normal file
@@ -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 "<font color='#[value][value][value][value][value][value]'>[pick(list(",",".","'","`"))]</font>"
|
||||
|
||||
/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)
|
||||
44
code/modules/random_map/noise/magma.dm
Normal file
44
code/modules/random_map/noise/magma.dm
Normal file
@@ -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
|
||||
168
code/modules/random_map/noise/noise.dm
Normal file
168
code/modules/random_map/noise/noise.dm
Normal file
@@ -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
|
||||
90
code/modules/random_map/noise/ore.dm
Normal file
90
code/modules/random_map/noise/ore.dm
Normal file
@@ -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("<span class='danger'>Insufficient surface minerals. Rerolling...</span>", R_DEBUG)
|
||||
return 0
|
||||
else if(rare_count < MIN_RARE_COUNT)
|
||||
admin_notice("<span class='danger'>Insufficient rare minerals. Rerolling...</span>", R_DEBUG)
|
||||
return 0
|
||||
else if(deep_count < MIN_DEEP_COUNT)
|
||||
admin_notice("<span class='danger'>Insufficient deep minerals. Rerolling...</span>", 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<chunk_size,i++)
|
||||
for(var/j=0,j<chunk_size,j++)
|
||||
var/turf/simulated/T = locate(tx+j, ty+i, origin_z)
|
||||
if(!istype(T) || !T.has_resources)
|
||||
continue
|
||||
if(!priority_process) 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/noise/ore/get_map_char(var/value)
|
||||
if(value < rare_val)
|
||||
return "S"
|
||||
else if(value < deep_val)
|
||||
return "R"
|
||||
else
|
||||
return "D"
|
||||
72
code/modules/random_map/noise/tundra.dm
Normal file
72
code/modules/random_map/noise/tundra.dm
Normal file
@@ -0,0 +1,72 @@
|
||||
/datum/random_map/noise/tundra
|
||||
descriptor = "tundra"
|
||||
smoothing_iterations = 1
|
||||
|
||||
/datum/random_map/noise/tundra/replace_space
|
||||
descriptor = "tundra (replacement)"
|
||||
target_turf_type = /turf/space
|
||||
|
||||
/datum/random_map/noise/tundra/get_map_char(var/value)
|
||||
var/val = min(9,max(0,round((value/cell_range)*10)))
|
||||
if(isnull(val)) val = 0
|
||||
switch(val)
|
||||
if(0)
|
||||
return "<font color='#000099'>~</font>"
|
||||
if(1)
|
||||
return "<font color='#0000BB'>~</font>"
|
||||
if(2)
|
||||
return "<font color='#0000DD'>~</font>"
|
||||
if(3)
|
||||
return "<font color='#66AA00'>[pick(list(".",","))]</font>"
|
||||
if(4)
|
||||
return "<font color='#77CC00'>[pick(list(".",","))]</font>"
|
||||
if(5)
|
||||
return "<font color='#88DD00'>[pick(list(".",","))]</font>"
|
||||
if(6)
|
||||
return "<font color='#99EE00'>[pick(list(".",","))]</font>"
|
||||
if(7)
|
||||
return "<font color='#00BB00'>[pick(list("T","t"))]</font>"
|
||||
if(8)
|
||||
return "<font color='#00DD00'>[pick(list("T","t"))]</font>"
|
||||
if(9)
|
||||
return "<font color='#00FF00'>[pick(list("T","t"))]</font>"
|
||||
|
||||
/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)
|
||||
@@ -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("<span class='danger'>Generating [name].</span>", 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<max_attempts;i++)
|
||||
if(generate())
|
||||
if(!do_not_announce) admin_notice("<span class='danger'>[capitalize(name)] generation completed in [round(0.1*(world.timeofday-start_time),0.1)] seconds.</span>", R_DEBUG)
|
||||
return
|
||||
if(!do_not_announce) admin_notice("<span class='danger'>[capitalize(name)] failed to generate ([round(0.1*(world.timeofday-start_time),0.1)] seconds): could not produce sane map.</span>", 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 = "<code>+------+<br>"
|
||||
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("<span class='danger'>Generating [descriptor].</span>", R_DEBUG)
|
||||
for(var/i = 0;i<max_attempts;i++)
|
||||
if(generate())
|
||||
admin_notice("<span class='danger'>[capitalize(descriptor)] generation completed in [round(0.1*(world.timeofday-start_time),0.1)] seconds.</span>", R_DEBUG)
|
||||
return
|
||||
admin_notice("<span class='danger'>[capitalize(descriptor)] generation failed in [round(0.1*(world.timeofday-start_time),0.1)] seconds: could not produce sane map.</span>", R_DEBUG)
|
||||
dat += get_map_char(map[current_cell])
|
||||
dat += "<br>"
|
||||
user << "[dat]+------+</code>"
|
||||
|
||||
/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("<span class='danger'>Placed [rooms_placed] secrets.</span>", R_DEBUG)
|
||||
return 1
|
||||
/datum/random_map/proc/handle_post_overlay_on(var/datum/random_map/target_map, var/tx, var/ty)
|
||||
return
|
||||
107
code/modules/random_map/random_map_verbs.dm
Normal file
107
code/modules/random_map/random_map_verbs.dm
Normal file
@@ -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)
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user