mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-21 15:42:35 +00:00
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:
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/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
|
||||
172
code/modules/random_map/automata/diona.dm
Normal file
172
code/modules/random_map/automata/diona.dm
Normal file
@@ -0,0 +1,172 @@
|
||||
/turf/simulated/wall/diona/New(var/newloc)
|
||||
..(newloc,"biomass")
|
||||
|
||||
/turf/simulated/wall/diona/attack_generic(var/mob/user, var/damage, var/attack_message)
|
||||
if(istype(user, /mob/living/carbon/alien/diona))
|
||||
if(can_open == WALL_OPENING)
|
||||
return
|
||||
can_open = WALL_CAN_OPEN
|
||||
user.visible_message("<span class='alium'>\The [user] strokes its feelers against \the [src] and the biomass [density ? "moves aside" : "closes up"].</span>")
|
||||
toggle_open(user)
|
||||
sleep(15)
|
||||
if(can_open == WALL_CAN_OPEN) can_open = 0
|
||||
else
|
||||
return ..(user, damage, attack_message)
|
||||
|
||||
/obj/structure/diona
|
||||
icon = 'icons/obj/diona.dmi'
|
||||
anchored = 1
|
||||
density = 1
|
||||
opacity = 0
|
||||
layer = TURF_LAYER + 0.01
|
||||
|
||||
/obj/structure/diona/vines
|
||||
name = "alien vines"
|
||||
desc = "Thick, heavy vines of some sort."
|
||||
icon_state = "vines3"
|
||||
var/growth = 0
|
||||
|
||||
/obj/structure/diona/vines/proc/spread()
|
||||
var/turf/origin = get_turf(src)
|
||||
for(var/turf/T in range(src,2))
|
||||
if(T.density || T == origin || istype(T, /turf/space))
|
||||
continue
|
||||
var/new_growth = 1
|
||||
switch(get_dist(origin,T))
|
||||
if(0)
|
||||
new_growth = 3
|
||||
if(1)
|
||||
new_growth = 2
|
||||
var/obj/structure/diona/vines/existing = locate() in T
|
||||
if(!istype(existing)) existing = PoolOrNew(/obj/structure/diona/vines, T)
|
||||
if(existing.growth < new_growth)
|
||||
existing.growth = new_growth
|
||||
existing.update_icon()
|
||||
|
||||
/obj/structure/diona/vines/update_icon()
|
||||
icon_state = "vines[growth]"
|
||||
|
||||
/obj/structure/diona/bulb
|
||||
name = "glow bulb"
|
||||
desc = "A glowing bulb of some sort."
|
||||
icon_state = "glowbulb"
|
||||
|
||||
/obj/structure/diona/bulb/New(var/newloc)
|
||||
..()
|
||||
set_light(3,3,"#557733")
|
||||
|
||||
/datum/random_map/automata/diona
|
||||
iterations = 3
|
||||
descriptor = "diona gestalt"
|
||||
limit_x = 32
|
||||
limit_y = 32
|
||||
|
||||
wall_type = /turf/simulated/wall/diona
|
||||
floor_type = /turf/simulated/floor/diona
|
||||
|
||||
// This is disgusting.
|
||||
/datum/random_map/automata/diona/proc/search_neighbors_for(var/search_val, var/x, var/y)
|
||||
var/current_cell = get_map_cell(x-1,y-1)
|
||||
if(current_cell && map[current_cell] == search_val) return 1
|
||||
current_cell = get_map_cell(x-1,y)
|
||||
if(current_cell && map[current_cell] == search_val) return 1
|
||||
current_cell = get_map_cell(x-1,y+1)
|
||||
if(current_cell && map[current_cell] == search_val) return 1
|
||||
current_cell = get_map_cell(x,y-1)
|
||||
if(current_cell && map[current_cell] == search_val) return 1
|
||||
current_cell = get_map_cell(x,y+1)
|
||||
if(current_cell && map[current_cell] == search_val) return 1
|
||||
current_cell = get_map_cell(x+1,y-1)
|
||||
if(current_cell && map[current_cell] == search_val) return 1
|
||||
current_cell = get_map_cell(x+1,y)
|
||||
if(current_cell && map[current_cell] == search_val) return 1
|
||||
current_cell = get_map_cell(x+1,y+1)
|
||||
if(current_cell && map[current_cell] == search_val) return 1
|
||||
return 0
|
||||
|
||||
/datum/random_map/automata/diona/cleanup()
|
||||
|
||||
// Hollow out the interior spaces.
|
||||
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(map[current_cell] == WALL_CHAR)
|
||||
if(!search_neighbors_for(FLOOR_CHAR,x,y) && !search_neighbors_for(DOOR_CHAR,x,y) && !(x == 1 || y == 1 || x == limit_x || y == limit_y))
|
||||
map[current_cell] = EMPTY_CHAR
|
||||
|
||||
// Prune exposed floor turfs away from the edges.
|
||||
var/changed = 1
|
||||
while(changed)
|
||||
for(var/x = 1, x <= limit_x, x++)
|
||||
for(var/y = 1, y <= limit_y, y++)
|
||||
changed = 0
|
||||
var/current_cell = get_map_cell(x,y)
|
||||
if(!current_cell) continue
|
||||
if(map[current_cell] == EMPTY_CHAR)
|
||||
if((search_neighbors_for(FLOOR_CHAR,x,y)) || (x == 1 || y == 1 || x == limit_x || y == limit_y))
|
||||
map[current_cell] = FLOOR_CHAR
|
||||
changed = 1
|
||||
|
||||
// Count and track the floors.
|
||||
var/list/floor_turfs = list()
|
||||
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(map[current_cell] == EMPTY_CHAR)
|
||||
floor_turfs |= current_cell
|
||||
|
||||
// Add vine decals.
|
||||
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 || map[current_cell] != EMPTY_CHAR) continue
|
||||
if(search_neighbors_for(WALL_CHAR,x,y))
|
||||
map[current_cell] = DOOR_CHAR
|
||||
|
||||
// Add bulbs and doona nymphs.
|
||||
if(floor_turfs.len)
|
||||
var/bulb_count = rand(round(floor_turfs.len/10),round(floor_turfs.len/8))
|
||||
while(floor_turfs.len && bulb_count)
|
||||
var/cell = pick(floor_turfs)
|
||||
floor_turfs -= cell
|
||||
map[cell] = ARTIFACT_CHAR
|
||||
bulb_count--
|
||||
if(floor_turfs.len)
|
||||
var/nymph_count = rand(round(floor_turfs.len/10),round(floor_turfs.len/8))
|
||||
while(floor_turfs.len && nymph_count)
|
||||
var/cell = pick(floor_turfs)
|
||||
floor_turfs -= cell
|
||||
map[cell] = MONSTER_CHAR
|
||||
nymph_count--
|
||||
return
|
||||
|
||||
/datum/random_map/automata/diona/get_appropriate_path(var/value)
|
||||
switch(value)
|
||||
if(EMPTY_CHAR, DOOR_CHAR, MONSTER_CHAR, ARTIFACT_CHAR)
|
||||
return floor_type
|
||||
if(WALL_CHAR)
|
||||
return wall_type
|
||||
|
||||
/datum/random_map/automata/diona/get_additional_spawns(var/value, var/turf/T)
|
||||
|
||||
if(value != FLOOR_CHAR)
|
||||
for(var/thing in T)
|
||||
if(istype(thing, /atom))
|
||||
var/atom/A = thing
|
||||
if(A.simulated)
|
||||
continue
|
||||
qdel(thing)
|
||||
|
||||
switch(value)
|
||||
if(ARTIFACT_CHAR)
|
||||
PoolOrNew(/obj/structure/diona/bulb,T)
|
||||
if(MONSTER_CHAR)
|
||||
spawn_diona_nymph(T)
|
||||
if(DOOR_CHAR)
|
||||
var/obj/structure/diona/vines/V = PoolOrNew(/obj/structure/diona/vines,T)
|
||||
V.growth = 3
|
||||
V.update_icon()
|
||||
spawn(1)
|
||||
V.spread()
|
||||
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(!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(!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
|
||||
195
code/modules/random_map/drop/drop_types.dm
Normal file
195
code/modules/random_map/drop/drop_types.dm
Normal file
@@ -0,0 +1,195 @@
|
||||
var/global/list/datum/supply_drop_loot/supply_drop
|
||||
|
||||
/proc/supply_drop_random_loot_types()
|
||||
if(!supply_drop)
|
||||
supply_drop = init_subtypes(/datum/supply_drop_loot)
|
||||
supply_drop = dd_sortedObjectList(supply_drop)
|
||||
return supply_drop
|
||||
|
||||
/datum/supply_drop_loot
|
||||
var/name = ""
|
||||
var/container = null
|
||||
var/list/contents = null
|
||||
|
||||
/datum/supply_drop_loot/proc/contents()
|
||||
return contents
|
||||
|
||||
/datum/supply_drop_loot/proc/drop(turf/T)
|
||||
var/C = container ? new container(T) : T
|
||||
for(var/content in contents())
|
||||
new content(C)
|
||||
|
||||
/datum/supply_drop_loot/dd_SortValue()
|
||||
return name
|
||||
|
||||
/datum/supply_drop_loot/supermatter
|
||||
name = "Supermatter"
|
||||
/datum/supply_drop_loot/supermatter/New()
|
||||
..()
|
||||
contents = list(/obj/machinery/power/supermatter)
|
||||
|
||||
/datum/supply_drop_loot/lasers
|
||||
name = "Lasers"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/lasers/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/weapon/gun/energy/laser,
|
||||
/obj/item/weapon/gun/energy/laser,
|
||||
/obj/item/weapon/gun/energy/sniperrifle,
|
||||
/obj/item/weapon/gun/energy/ionrifle)
|
||||
|
||||
/datum/supply_drop_loot/ballistics
|
||||
name = "Ballistics"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/ballistics/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/weapon/gun/projectile/sec,
|
||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
|
||||
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
|
||||
/obj/item/weapon/gun/projectile/automatic/wt550,
|
||||
/obj/item/weapon/gun/projectile/automatic/rifle/z8)
|
||||
|
||||
/datum/supply_drop_loot/ballistics
|
||||
name = "Ballistics"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/ballistics/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/weapon/gun/projectile/sec,
|
||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
|
||||
/obj/item/weapon/gun/projectile/shotgun/pump/combat,
|
||||
/obj/item/weapon/gun/projectile/automatic/wt550,
|
||||
/obj/item/weapon/gun/projectile/automatic/rifle/z8)
|
||||
|
||||
/datum/supply_drop_loot/seeds
|
||||
name = "Seeds"
|
||||
container = /obj/structure/closet/crate
|
||||
/datum/supply_drop_loot/seeds/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/seeds/chiliseed,
|
||||
/obj/item/seeds/berryseed,
|
||||
/obj/item/seeds/cornseed,
|
||||
/obj/item/seeds/eggplantseed,
|
||||
/obj/item/seeds/tomatoseed,
|
||||
/obj/item/seeds/appleseed,
|
||||
/obj/item/seeds/soyaseed,
|
||||
/obj/item/seeds/wheatseed,
|
||||
/obj/item/seeds/carrotseed,
|
||||
/obj/item/seeds/lemonseed,
|
||||
/obj/item/seeds/orangeseed,
|
||||
/obj/item/seeds/grassseed,
|
||||
/obj/item/seeds/sunflowerseed,
|
||||
/obj/item/seeds/chantermycelium,
|
||||
/obj/item/seeds/potatoseed,
|
||||
/obj/item/seeds/sugarcaneseed)
|
||||
|
||||
/datum/supply_drop_loot/food
|
||||
name = "Food"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/food/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/weapon/reagent_containers/food/condiment/flour,
|
||||
/obj/item/weapon/reagent_containers/food/condiment/flour,
|
||||
/obj/item/weapon/reagent_containers/food/condiment/flour,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/milk,
|
||||
/obj/item/weapon/reagent_containers/food/drinks/milk,
|
||||
/obj/item/weapon/storage/fancy/egg_box,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/tofu,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/tofu,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat)
|
||||
|
||||
/datum/supply_drop_loot/armour
|
||||
name = "Armour"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/armour/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/clothing/head/helmet/riot,
|
||||
/obj/item/clothing/suit/armor/riot,
|
||||
/obj/item/clothing/head/helmet/riot,
|
||||
/obj/item/clothing/suit/armor/riot,
|
||||
/obj/item/clothing/head/helmet/riot,
|
||||
/obj/item/clothing/suit/armor/riot,
|
||||
/obj/item/clothing/suit/armor/vest,
|
||||
/obj/item/clothing/suit/armor/vest,
|
||||
/obj/item/clothing/suit/storage/vest,
|
||||
/obj/item/clothing/suit/storage/vest,
|
||||
/obj/item/clothing/suit/armor/laserproof,
|
||||
/obj/item/clothing/suit/armor/bulletproof)
|
||||
|
||||
/datum/supply_drop_loot/materials
|
||||
name = "Materials"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/materials/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/stack/material/steel,
|
||||
/obj/item/stack/material/steel,
|
||||
/obj/item/stack/material/steel,
|
||||
/obj/item/stack/material/glass,
|
||||
/obj/item/stack/material/glass,
|
||||
/obj/item/stack/material/wood,
|
||||
/obj/item/stack/material/plastic,
|
||||
/obj/item/stack/material/glass/reinforced,
|
||||
/obj/item/stack/material/plasteel)
|
||||
|
||||
/datum/supply_drop_loot/medical
|
||||
name = "Medical"
|
||||
container = /obj/structure/closet/crate/medical
|
||||
/datum/supply_drop_loot/medical/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/weapon/storage/firstaid/regular,
|
||||
/obj/item/weapon/storage/firstaid/fire,
|
||||
/obj/item/weapon/storage/firstaid/toxin,
|
||||
/obj/item/weapon/storage/firstaid/o2,
|
||||
/obj/item/weapon/storage/firstaid/adv,
|
||||
/obj/item/weapon/reagent_containers/glass/bottle/antitoxin,
|
||||
/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline,
|
||||
/obj/item/weapon/reagent_containers/glass/bottle/stoxin,
|
||||
/obj/item/weapon/storage/box/syringes,
|
||||
/obj/item/weapon/storage/box/autoinjectors)
|
||||
|
||||
/datum/supply_drop_loot/power
|
||||
name = "Power"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/power/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/item/stack/material/steel,
|
||||
/obj/item/stack/material/steel,
|
||||
/obj/item/stack/material/steel,
|
||||
/obj/item/stack/material/glass,
|
||||
/obj/item/stack/material/glass,
|
||||
/obj/item/stack/material/wood,
|
||||
/obj/item/stack/material/plastic,
|
||||
/obj/item/stack/material/glass/reinforced,
|
||||
/obj/item/stack/material/plasteel)
|
||||
|
||||
/datum/supply_drop_loot/hydroponics
|
||||
name = "Hydroponics"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/hydroponics/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/machinery/portable_atmospherics/hydroponics,
|
||||
/obj/machinery/portable_atmospherics/hydroponics,
|
||||
/obj/machinery/portable_atmospherics/hydroponics)
|
||||
|
||||
/datum/supply_drop_loot/power
|
||||
name = "Power"
|
||||
container = /obj/structure/largecrate
|
||||
/datum/supply_drop_loot/power/New()
|
||||
..()
|
||||
contents = list(
|
||||
/obj/machinery/power/port_gen/pacman,
|
||||
/obj/machinery/power/port_gen/pacman/super,
|
||||
/obj/machinery/power/port_gen/pacman/mrs)
|
||||
|
||||
/datum/supply_drop_loot/power/contents()
|
||||
return list(pick(contents))
|
||||
227
code/modules/random_map/drop/droppod.dm
Normal file
227
code/modules/random_map/drop/droppod.dm
Normal file
@@ -0,0 +1,227 @@
|
||||
#define SD_FLOOR_TILE 0
|
||||
#define SD_WALL_TILE 1
|
||||
#define SD_DOOR_TILE 2
|
||||
#define SD_EMPTY_TILE 3
|
||||
#define SD_SUPPLY_TILE 7
|
||||
|
||||
/datum/random_map/droppod
|
||||
descriptor = "drop pod"
|
||||
initial_wall_cell = 0
|
||||
limit_x = 3
|
||||
limit_y = 3
|
||||
preserve_map = 0
|
||||
|
||||
wall_type = /turf/simulated/wall/titanium
|
||||
floor_type = /turf/simulated/floor/reinforced
|
||||
var/list/supplied_drop_types = list()
|
||||
var/door_type = /obj/structure/droppod_door
|
||||
var/drop_type = /mob/living/simple_animal/parrot
|
||||
var/auto_open_doors
|
||||
|
||||
var/placement_explosion_dev = 1
|
||||
var/placement_explosion_heavy = 2
|
||||
var/placement_explosion_light = 6
|
||||
var/placement_explosion_flash = 4
|
||||
|
||||
/datum/random_map/droppod/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce, var/supplied_drop, var/list/supplied_drops, var/automated)
|
||||
|
||||
if(supplied_drop)
|
||||
drop_type = supplied_drop
|
||||
else if(islist(supplied_drops) && supplied_drops.len)
|
||||
supplied_drop_types = supplied_drops
|
||||
drop_type = "custom"
|
||||
if(automated)
|
||||
auto_open_doors = 1
|
||||
|
||||
//Make sure there is a clear midpoint.
|
||||
if(limit_x % 2 == 0) limit_x++
|
||||
if(limit_y % 2 == 0) limit_y++
|
||||
..()
|
||||
|
||||
/datum/random_map/droppod/generate_map()
|
||||
|
||||
// No point calculating these 200 times.
|
||||
var/x_midpoint = n_ceil(limit_x / 2)
|
||||
var/y_midpoint = n_ceil(limit_y / 2)
|
||||
|
||||
// Draw walls/floors/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(!current_cell)
|
||||
continue
|
||||
|
||||
var/on_x_bound = (x == 1 || x == limit_x)
|
||||
var/on_y_bound = (y == 1 || y == limit_x)
|
||||
var/draw_corners = (limit_x < 5 && limit_y < 5)
|
||||
if(on_x_bound || on_y_bound)
|
||||
// Draw access points in midpoint of each wall.
|
||||
if(x == x_midpoint || y == y_midpoint)
|
||||
map[current_cell] = SD_DOOR_TILE
|
||||
// Draw the actual walls.
|
||||
else if(draw_corners || (!on_x_bound || !on_y_bound))
|
||||
map[current_cell] = SD_WALL_TILE
|
||||
//Don't draw the far corners on large pods.
|
||||
else
|
||||
map[current_cell] = SD_EMPTY_TILE
|
||||
else
|
||||
// Fill in the corners.
|
||||
if((x == 2 || x == (limit_x-1)) && (y == 2 || y == (limit_y-1)))
|
||||
map[current_cell] = SD_WALL_TILE
|
||||
// Fill in EVERYTHING ELSE.
|
||||
else
|
||||
map[current_cell] = SD_FLOOR_TILE
|
||||
|
||||
// Draw the drop contents.
|
||||
var/current_cell = get_map_cell(x_midpoint,y_midpoint)
|
||||
if(current_cell)
|
||||
map[current_cell] = SD_SUPPLY_TILE
|
||||
return 1
|
||||
|
||||
/datum/random_map/droppod/apply_to_map()
|
||||
if(placement_explosion_dev || placement_explosion_heavy || placement_explosion_light || placement_explosion_flash)
|
||||
var/turf/T = locate((origin_x + n_ceil(limit_x / 2)-1), (origin_y + n_ceil(limit_y / 2)-1), origin_z)
|
||||
if(istype(T))
|
||||
explosion(T, placement_explosion_dev, placement_explosion_heavy, placement_explosion_light, placement_explosion_flash)
|
||||
sleep(15) // Let the explosion finish proccing before we ChangeTurf(), otherwise it might destroy our spawned objects.
|
||||
return ..()
|
||||
|
||||
/datum/random_map/droppod/get_appropriate_path(var/value)
|
||||
if(value == SD_FLOOR_TILE || value == SD_SUPPLY_TILE)
|
||||
return floor_type
|
||||
else if(value == SD_WALL_TILE)
|
||||
return wall_type
|
||||
else if(value == SD_DOOR_TILE )
|
||||
return wall_type
|
||||
return null
|
||||
|
||||
// Pods are circular. Get the direction this object is facing from the center of the pod.
|
||||
/datum/random_map/droppod/get_spawn_dir(var/x, var/y)
|
||||
var/x_midpoint = n_ceil(limit_x / 2)
|
||||
var/y_midpoint = n_ceil(limit_y / 2)
|
||||
if(x == x_midpoint && y == y_midpoint)
|
||||
return null
|
||||
var/turf/target = locate(origin_x+x-1, origin_y+y-1, origin_z)
|
||||
var/turf/middle = locate(origin_x+x_midpoint-1, origin_y+y_midpoint-1, origin_z)
|
||||
if(!istype(target) || !istype(middle))
|
||||
return null
|
||||
return get_dir(middle, target)
|
||||
|
||||
/datum/random_map/droppod/get_additional_spawns(var/value, var/turf/T, var/spawn_dir)
|
||||
|
||||
// Splatter anything under us that survived the explosion.
|
||||
if(value != SD_EMPTY_TILE && T.contents.len)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(AM.simulated && !istype(AM, /mob/dead))
|
||||
qdel(AM)
|
||||
|
||||
// Also spawn doors and loot.
|
||||
if(value == SD_DOOR_TILE)
|
||||
var/obj/structure/S = new door_type(T, auto_open_doors)
|
||||
S.set_dir(spawn_dir)
|
||||
|
||||
else if(value == SD_SUPPLY_TILE)
|
||||
get_spawned_drop(T)
|
||||
|
||||
/datum/random_map/droppod/proc/get_spawned_drop(var/turf/T)
|
||||
var/obj/structure/bed/chair/C = new(T)
|
||||
C.set_light(3, l_color = "#CC0000")
|
||||
var/mob/living/drop
|
||||
// This proc expects a list of mobs to be passed to the spawner.
|
||||
// Use the supply pod if you don't want to drop mobs.
|
||||
// Mobs will not double up; if you want multiple mobs, you
|
||||
// will need multiple drop tiles.
|
||||
if(islist(supplied_drop_types) && supplied_drop_types.len)
|
||||
while(supplied_drop_types.len)
|
||||
drop = pick(supplied_drop_types)
|
||||
supplied_drop_types -= drop
|
||||
if(istype(drop))
|
||||
drop.tag = null
|
||||
if(drop.buckled)
|
||||
drop.buckled = null
|
||||
drop.forceMove(T)
|
||||
else if(ispath(drop_type))
|
||||
drop = new drop_type(T)
|
||||
if(istype(drop))
|
||||
if(drop.buckled)
|
||||
drop.buckled = null
|
||||
drop.forceMove(T)
|
||||
|
||||
/datum/admins/proc/call_drop_pod()
|
||||
set category = "Fun"
|
||||
set desc = "Call an immediate drop pod on your location."
|
||||
set name = "Call Drop Pod"
|
||||
|
||||
if(!check_rights(R_FUN)) return
|
||||
|
||||
var/client/selected_player
|
||||
var/mob/living/spawned_mob
|
||||
var/list/spawned_mobs = list()
|
||||
|
||||
var/spawn_path = input("Select a mob type.", "Drop Pod Selection", null) as null|anything in typesof(/mob/living)-/mob/living
|
||||
if(!spawn_path)
|
||||
return
|
||||
|
||||
if(alert("Do you wish the mob to have a player?",,"No","Yes") == "No")
|
||||
var/spawn_count = input("How many mobs do you wish the pod to contain?", "Drop Pod Selection", null) as num
|
||||
if(spawn_count <= 0)
|
||||
return
|
||||
for(var/i=0;i<spawn_count;i++)
|
||||
var/mob/living/M = new spawn_path()
|
||||
M.tag = "awaiting drop"
|
||||
spawned_mobs |= M
|
||||
else
|
||||
var/list/candidates = list()
|
||||
for(var/client/player in clients)
|
||||
if(player.mob && istype(player.mob, /mob/dead/observer))
|
||||
candidates |= player
|
||||
|
||||
if(!candidates.len)
|
||||
usr << "There are no candidates for a drop pod launch."
|
||||
return
|
||||
|
||||
// Get a player and a mob type.
|
||||
selected_player = input("Select a player.", "Drop Pod Selection", null) as null|anything in candidates
|
||||
if(!selected_player)
|
||||
return
|
||||
|
||||
// Spawn the mob in nullspace for now.
|
||||
spawned_mob = new spawn_path()
|
||||
spawned_mob.tag = "awaiting drop"
|
||||
|
||||
// Equip them, if they are human and it is desirable.
|
||||
if(istype(spawned_mob, /mob/living/carbon/human))
|
||||
var/antag_type = input("Select an equipment template to use or cancel for nude.", null) as null|anything in all_antag_types
|
||||
if(antag_type)
|
||||
var/datum/antagonist/A = all_antag_types[antag_type]
|
||||
A.equip(spawned_mob)
|
||||
|
||||
if(alert("Are you SURE you wish to deploy this drop pod? It will cause a sizable explosion and gib anyone underneath it.",,"No","Yes") == "No")
|
||||
if(spawned_mob)
|
||||
qdel(spawned_mob)
|
||||
if(spawned_mobs.len)
|
||||
for(var/mob/living/M in spawned_mobs)
|
||||
spawned_mobs -= M
|
||||
M.tag = null
|
||||
qdel(M)
|
||||
spawned_mobs.Cut()
|
||||
return
|
||||
|
||||
// Chuck them into the pod.
|
||||
var/automatic_pod
|
||||
if(spawned_mob && selected_player)
|
||||
if(selected_player.mob.mind)
|
||||
selected_player.mob.mind.transfer_to(spawned_mob)
|
||||
else
|
||||
spawned_mob.ckey = selected_player.mob.ckey
|
||||
spawned_mobs = list(spawned_mob)
|
||||
message_admins("[key_name(usr)] dropped a pod containing \the [spawned_mob] ([spawned_mob.key]) at ([usr.x],[usr.y],[usr.z])")
|
||||
log_admin("[key_name(usr)] dropped a pod containing \the [spawned_mob] ([spawned_mob.key]) at ([usr.x],[usr.y],[usr.z])")
|
||||
else if(spawned_mobs.len)
|
||||
automatic_pod = 1
|
||||
message_admins("[key_name(usr)] dropped a pod containing [spawned_mobs.len] [spawned_mobs[1]] at ([usr.x],[usr.y],[usr.z])")
|
||||
log_admin("[key_name(usr)] dropped a pod containing [spawned_mobs.len] [spawned_mobs[1]] at ([usr.x],[usr.y],[usr.z])")
|
||||
else
|
||||
return
|
||||
|
||||
new /datum/random_map/droppod(null, usr.x-1, usr.y-1, usr.z, supplied_drops = spawned_mobs, automated = automatic_pod)
|
||||
80
code/modules/random_map/drop/droppod_doors.dm
Normal file
80
code/modules/random_map/drop/droppod_doors.dm
Normal file
@@ -0,0 +1,80 @@
|
||||
/obj/structure/droppod_door
|
||||
name = "pod door"
|
||||
desc = "A drop pod door. Opens rapidly using explosive bolts."
|
||||
icon = 'icons/obj/structures.dmi'
|
||||
icon_state = "droppod_door_closed"
|
||||
anchored = 1
|
||||
density = 1
|
||||
opacity = 1
|
||||
layer = TURF_LAYER + 0.1
|
||||
var/deploying
|
||||
var/deployed
|
||||
|
||||
/obj/structure/droppod_door/New(var/newloc, var/autoopen)
|
||||
..(newloc)
|
||||
if(autoopen)
|
||||
spawn(100)
|
||||
deploy()
|
||||
|
||||
/obj/structure/droppod_door/attack_ai(var/mob/user)
|
||||
if(!user.Adjacent(src))
|
||||
return
|
||||
attack_hand(user)
|
||||
|
||||
/obj/structure/droppod_door/attack_generic(var/mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/structure/droppod_door/attack_hand(var/mob/user)
|
||||
if(deploying) return
|
||||
user << "<span class='danger'>You prime the explosive bolts. Better get clear!</span>"
|
||||
sleep(30)
|
||||
deploy()
|
||||
|
||||
/obj/structure/droppod_door/proc/deploy()
|
||||
if(deployed)
|
||||
return
|
||||
|
||||
deployed = 1
|
||||
visible_message("<span class='danger'>The explosive bolts on \the [src] detonate, throwing it open!</span>")
|
||||
playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 5)
|
||||
|
||||
// This is shit but it will do for the sake of testing.
|
||||
for(var/obj/structure/droppod_door/D in orange(1,src))
|
||||
if(D.deployed)
|
||||
continue
|
||||
D.deploy()
|
||||
|
||||
// Overwrite turfs.
|
||||
var/turf/origin = get_turf(src)
|
||||
origin.ChangeTurf(/turf/simulated/floor/reinforced)
|
||||
origin.set_light(0) // Forcing updates
|
||||
var/turf/T = get_step(origin, src.dir)
|
||||
T.ChangeTurf(/turf/simulated/floor/reinforced)
|
||||
T.set_light(0) // Forcing updates
|
||||
|
||||
// Destroy turf contents.
|
||||
for(var/obj/O in origin)
|
||||
if(!O.simulated)
|
||||
continue
|
||||
qdel(O) //crunch
|
||||
for(var/obj/O in T)
|
||||
if(!O.simulated)
|
||||
continue
|
||||
qdel(O) //crunch
|
||||
|
||||
// Hurl the mobs away.
|
||||
for(var/mob/living/M in T)
|
||||
M.throw_at(get_edge_target_turf(T,src.dir),rand(0,3),50)
|
||||
for(var/mob/living/M in origin)
|
||||
M.throw_at(get_edge_target_turf(origin,src.dir),rand(0,3),50)
|
||||
|
||||
// Create a decorative ramp bottom and flatten out our current ramp.
|
||||
density = 0
|
||||
opacity = 0
|
||||
icon_state = "ramptop"
|
||||
var/obj/structure/droppod_door/door_bottom = new(T)
|
||||
door_bottom.deployed = 1
|
||||
door_bottom.density = 0
|
||||
door_bottom.opacity = 0
|
||||
door_bottom.dir = src.dir
|
||||
door_bottom.icon_state = "rampbottom"
|
||||
93
code/modules/random_map/drop/supply.dm
Normal file
93
code/modules/random_map/drop/supply.dm
Normal file
@@ -0,0 +1,93 @@
|
||||
/datum/random_map/droppod/supply
|
||||
descriptor = "supply drop"
|
||||
limit_x = 5
|
||||
limit_y = 5
|
||||
|
||||
placement_explosion_light = 7
|
||||
placement_explosion_flash = 5
|
||||
|
||||
// UNLIKE THE DROP POD, this map deals ENTIRELY with strings and types.
|
||||
// Drop type is a string representing a mode rather than an atom or path.
|
||||
// supplied_drop_types is a list of types to spawn in the pod.
|
||||
/datum/random_map/droppod/supply/get_spawned_drop(var/turf/T)
|
||||
|
||||
if(!drop_type) drop_type = pick(supply_drop_random_loot_types())
|
||||
|
||||
if(drop_type == "custom")
|
||||
if(supplied_drop_types.len)
|
||||
var/obj/structure/largecrate/C = locate() in T
|
||||
for(var/drop_type in supplied_drop_types)
|
||||
var/atom/movable/A = new drop_type(T)
|
||||
if(!istype(A, /mob))
|
||||
if(!C) C = new(T)
|
||||
C.contents |= A
|
||||
return
|
||||
else
|
||||
drop_type = pick(supply_drop_random_loot_types())
|
||||
|
||||
if(istype(drop_type, /datum/supply_drop_loot))
|
||||
var/datum/supply_drop_loot/SDL = drop_type
|
||||
SDL.drop(T)
|
||||
else
|
||||
error("Unhandled drop type: [drop_type]")
|
||||
|
||||
|
||||
/datum/admins/proc/call_supply_drop()
|
||||
set category = "Fun"
|
||||
set desc = "Call an immediate supply drop on your location."
|
||||
set name = "Call Supply Drop"
|
||||
|
||||
if(!check_rights(R_FUN)) return
|
||||
|
||||
var/chosen_loot_type
|
||||
var/list/chosen_loot_types
|
||||
var/choice = alert("Do you wish to supply a custom loot list?",,"No","Yes")
|
||||
if(choice == "Yes")
|
||||
chosen_loot_types = list()
|
||||
|
||||
choice = alert("Do you wish to add mobs?",,"No","Yes")
|
||||
if(choice == "Yes")
|
||||
while(1)
|
||||
var/adding_loot_type = input("Select a new loot path. Cancel to finish.", "Loot Selection", null) as null|anything in typesof(/mob/living)
|
||||
if(!adding_loot_type)
|
||||
break
|
||||
chosen_loot_types |= adding_loot_type
|
||||
choice = alert("Do you wish to add structures or machines?",,"No","Yes")
|
||||
if(choice == "Yes")
|
||||
while(1)
|
||||
var/adding_loot_type = input("Select a new loot path. Cancel to finish.", "Loot Selection", null) as null|anything in typesof(/obj) - typesof(/obj/item)
|
||||
if(!adding_loot_type)
|
||||
break
|
||||
chosen_loot_types |= adding_loot_type
|
||||
choice = alert("Do you wish to add any non-weapon items?",,"No","Yes")
|
||||
if(choice == "Yes")
|
||||
while(1)
|
||||
var/adding_loot_type = input("Select a new loot path. Cancel to finish.", "Loot Selection", null) as null|anything in typesof(/obj/item) - typesof(/obj/item/weapon)
|
||||
if(!adding_loot_type)
|
||||
break
|
||||
chosen_loot_types |= adding_loot_type
|
||||
|
||||
choice = alert("Do you wish to add weapons?",,"No","Yes")
|
||||
if(choice == "Yes")
|
||||
while(1)
|
||||
var/adding_loot_type = input("Select a new loot path. Cancel to finish.", "Loot Selection", null) as null|anything in typesof(/obj/item/weapon)
|
||||
if(!adding_loot_type)
|
||||
break
|
||||
chosen_loot_types |= adding_loot_type
|
||||
choice = alert("Do you wish to add ABSOLUTELY ANYTHING ELSE? (you really shouldn't need to)",,"No","Yes")
|
||||
if(choice == "Yes")
|
||||
while(1)
|
||||
var/adding_loot_type = input("Select a new loot path. Cancel to finish.", "Loot Selection", null) as null|anything in typesof(/atom/movable)
|
||||
if(!adding_loot_type)
|
||||
break
|
||||
chosen_loot_types |= adding_loot_type
|
||||
else
|
||||
choice = alert("Do you wish to specify a loot type?",,"No","Yes")
|
||||
if(choice == "Yes")
|
||||
chosen_loot_type = input("Select a loot type.", "Loot Selection", null) as null|anything in supply_drop_random_loot_types()
|
||||
|
||||
choice = alert("Are you SURE you wish to deploy this supply drop? It will cause a sizable explosion and gib anyone underneath it.",,"No","Yes")
|
||||
if(choice == "No")
|
||||
return
|
||||
log_admin("[key_name(usr)] dropped supplies at ([usr.x],[usr.y],[usr.z])")
|
||||
new /datum/random_map/droppod/supply(null, usr.x-2, usr.y-2, usr.z, supplied_drops = chosen_loot_types, supplied_drop = chosen_loot_type)
|
||||
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 1000
|
||||
#define MIN_RARE_COUNT 400
|
||||
#define MIN_DEEP_COUNT 200
|
||||
#define RESOURCE_HIGH_MAX 8
|
||||
#define RESOURCE_HIGH_MIN 4
|
||||
#define RESOURCE_MID_MAX 6
|
||||
#define RESOURCE_MID_MIN 2
|
||||
#define RESOURCE_LOW_MAX 2
|
||||
#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/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-1)+x)*chunk_size
|
||||
var/ty = ((origin_y-1)+y)*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)
|
||||
@@ -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
|
||||
|
||||
108
code/modules/random_map/random_map_verbs.dm
Normal file
108
code/modules/random_map/random_map_verbs.dm
Normal file
@@ -0,0 +1,108 @@
|
||||
/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.set_origins(tx,ty,tz)
|
||||
M.apply_to_map()
|
||||
|
||||
/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)
|
||||
Reference in New Issue
Block a user