Merge branch 'Aurorastation/development' into Map-Development

# Conflicts:
#	code/TriDimension/controller_presets.dm
#	code/game/objects/structures/crates_lockers/closets/secure/security.dm
#	code/game/objects/structures/crates_lockers/closets/wardrobe.dm
#	code/game/objects/structures/signs.dm
#	code/game/turfs/simulated/floor_types.dm
#	code/modules/random_map/mining_distribution.dm
#	code/modules/random_map/random_map.dm
#	code/world.dm
#	icons/obj/barsigns.dmi
#	icons/obj/decals.dmi
#	icons/obj/plants.dmi
#	icons/obj/structures.dmi
#	icons/turf/floors.dmi
#	icons/turf/wall_masks.dmi
#	maps/exodus-2.dmm
This commit is contained in:
LordFowl
2017-01-27 01:57:29 -05:00
2113 changed files with 97032 additions and 69020 deletions

View File

@@ -4,162 +4,212 @@
*/
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
var/preserve_map = 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]]"
if(preserve_map) random_maps[name] = src
// Get origins for applying the map later.
set_origins(tx, ty, tz)
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
if(!islist(map))
set_map_size()
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
if(current_cell)
dat += get_map_char(map[current_cell])
dat += "<br>"
user << "[dat]+------+</code>"
/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)
/datum/random_map/proc/within_bounds(var/val)
return (val>0) && (val<=raw_map_size)
/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/set_origins(var/tx, var/ty, var/tz)
origin_x = tx ? tx : 1
origin_y = ty ? ty : 1
origin_z = tz ? tz : 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)
if(!origin_x) origin_x = 1
if(!origin_y) origin_y = 1
if(!origin_z) origin_z = 1
for(var/x = 1, x <= limit_x, x++)
for(var/y = 1, y <= limit_y, y++)
if(!priority_process) sleep(-1)
apply_to_turf(x,y)
/datum/random_map/proc/apply_to_turf(var/x,var/y)
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)
if(!current_cell)
return 0
var/turf/T = locate((origin_x-1)+x,(origin_y-1)+y,origin_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,get_spawn_dir(x, y))
return T
/datum/random_map/proc/get_spawn_dir()
return 0
/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(!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)
return 1
/datum/random_map/proc/handle_post_overlay_on(var/datum/random_map/target_map, var/tx, var/ty)
return