mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 09:54:52 +00:00
initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
201
code/modules/procedural_mapping/mapGenerator.dm
Normal file
201
code/modules/procedural_mapping/mapGenerator.dm
Normal file
@@ -0,0 +1,201 @@
|
||||
//clusterCheckFlags defines
|
||||
//All based on clusterMin and clusterMax as guides
|
||||
|
||||
//Individual defines
|
||||
#define CLUSTER_CHECK_NONE 0 //No checks are done, cluster as much as possible
|
||||
#define CLUSTER_CHECK_DIFFERENT_TURFS 2 //Don't let turfs of DIFFERENT types cluster
|
||||
#define CLUSTER_CHECK_DIFFERENT_ATOMS 4 //Don't let atoms of DIFFERENT types cluster
|
||||
#define CLUSTER_CHECK_SAME_TURFS 8 //Don't let turfs of the SAME type cluster
|
||||
#define CLUSTER_CHECK_SAME_ATOMS 16 //Don't let atoms of the SAME type cluster
|
||||
|
||||
//Combined defines
|
||||
#define CLUSTER_CHECK_SAMES 24 //Don't let any of the same type cluster
|
||||
#define CLUSTER_CHECK_DIFFERENTS 6 //Don't let any of different types cluster
|
||||
#define CLUSTER_CHECK_ALL_TURFS 10 //Don't let ANY turfs cluster same and different types
|
||||
#define CLUSTER_CHECK_ALL_ATOMS 20 //Don't let ANY atoms cluster same and different types
|
||||
|
||||
//All
|
||||
#define CLUSTER_CHECK_ALL 30 //Don't let anything cluster, like, at all
|
||||
|
||||
|
||||
/datum/mapGenerator
|
||||
|
||||
//Map information
|
||||
var/list/map = list()
|
||||
|
||||
//mapGeneratorModule information
|
||||
var/list/modules = list()
|
||||
|
||||
/datum/mapGenerator/New()
|
||||
..()
|
||||
initialiseModules()
|
||||
|
||||
//Defines the region the map represents, sets map
|
||||
//Returns the map
|
||||
/datum/mapGenerator/proc/defineRegion(turf/Start, turf/End, replace = 0)
|
||||
if(!checkRegion(Start, End))
|
||||
return 0
|
||||
|
||||
if(replace)
|
||||
undefineRegion()
|
||||
map |= block(Start,End)
|
||||
return map
|
||||
|
||||
|
||||
//Defines the region the map represents, as a CIRCLE!, sets map
|
||||
//Returns the map
|
||||
/datum/mapGenerator/proc/defineCircularRegion(turf/Start, turf/End, replace = 0)
|
||||
if(!checkRegion(Start, End))
|
||||
return 0
|
||||
|
||||
var/centerX = max(abs((End.x+Start.x)/2),1)
|
||||
var/centerY = max(abs((End.y+Start.y)/2),1)
|
||||
|
||||
var/lilZ = min(Start.z,End.z)
|
||||
var/bigZ = max(Start.z,End.z)
|
||||
|
||||
var/sphereMagic = max(abs(bigZ-(lilZ/2)),1) //Spherical maps! woo!
|
||||
|
||||
var/radius = abs(max(centerX,centerY)) //take the biggest displacement as the radius
|
||||
|
||||
if(replace)
|
||||
undefineRegion()
|
||||
|
||||
//Even sphere correction engage
|
||||
var/offByOneOffset = 1
|
||||
if(bigZ % 2 == 0)
|
||||
offByOneOffset = 0
|
||||
|
||||
for(var/i = lilZ, i <= bigZ+offByOneOffset, i++)
|
||||
var/theRadius = radius
|
||||
if(i != sphereMagic)
|
||||
theRadius = max(radius/max((2*abs(sphereMagic-i)),1),1)
|
||||
|
||||
|
||||
map |= circlerange(locate(centerX,centerY,i),theRadius)
|
||||
|
||||
|
||||
return map
|
||||
|
||||
|
||||
//Empties the map list, he's dead jim.
|
||||
/datum/mapGenerator/proc/undefineRegion()
|
||||
map = list() //bai bai
|
||||
|
||||
|
||||
//Checks for and Rejects bad region coordinates
|
||||
//Returns 1/0
|
||||
/datum/mapGenerator/proc/checkRegion(turf/Start, turf/End)
|
||||
. = 1
|
||||
|
||||
if(!Start || !End)
|
||||
return 0 //Just bail
|
||||
|
||||
if(Start.x > world.maxx || End.x > world.maxx)
|
||||
. = 0
|
||||
if(Start.y > world.maxy || End.y > world.maxy)
|
||||
. = 0
|
||||
if(Start.z > world.maxz || End.z > world.maxz)
|
||||
. = 0
|
||||
|
||||
|
||||
//Requests the mapGeneratorModule(s) to (re)generate
|
||||
/datum/mapGenerator/proc/generate()
|
||||
set background = 1 //this can get beefy
|
||||
|
||||
syncModules()
|
||||
if(!modules || !modules.len)
|
||||
return
|
||||
for(var/datum/mapGeneratorModule/mod in modules)
|
||||
spawn(0)
|
||||
mod.generate()
|
||||
|
||||
|
||||
//Requests the mapGeneratorModule(s) to (re)generate this one turf
|
||||
/datum/mapGenerator/proc/generateOneTurf(turf/T)
|
||||
if(!T)
|
||||
return
|
||||
syncModules()
|
||||
if(!modules || !modules.len)
|
||||
return
|
||||
for(var/datum/mapGeneratorModule/mod in modules)
|
||||
spawn(0)
|
||||
mod.place(T)
|
||||
|
||||
|
||||
//Replaces all paths in the module list with actual module datums
|
||||
/datum/mapGenerator/proc/initialiseModules()
|
||||
for(var/path in modules)
|
||||
if(ispath(path))
|
||||
modules.Remove(path)
|
||||
modules |= new path
|
||||
syncModules()
|
||||
|
||||
|
||||
//Sync mapGeneratorModule(s) to mapGenerator
|
||||
/datum/mapGenerator/proc/syncModules()
|
||||
for(var/datum/mapGeneratorModule/mod in modules)
|
||||
mod.sync(src)
|
||||
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// HERE BE DEBUG DRAGONS //
|
||||
///////////////////////////
|
||||
|
||||
/client/proc/debugNatureMapGenerator()
|
||||
set name = "Test Nature Map Generator"
|
||||
set category = "Debug"
|
||||
|
||||
var/datum/mapGenerator/nature/N = new()
|
||||
var/startInput = input(usr,"Start turf of Map, (X;Y;Z)", "Map Gen Settings", "1;1;1") as text
|
||||
var/endInput = input(usr,"End turf of Map (X;Y;Z)", "Map Gen Settings", "[world.maxx];[world.maxy];[mob ? mob.z : 1]") as text
|
||||
//maxx maxy and current z so that if you fuck up, you only fuck up one entire z level instead of the entire universe
|
||||
if(!startInput || !endInput)
|
||||
src << "Missing Input"
|
||||
return
|
||||
|
||||
var/list/startCoords = splittext(startInput, ";")
|
||||
var/list/endCoords = splittext(endInput, ";")
|
||||
if(!startCoords || !endCoords)
|
||||
src << "Invalid Coords"
|
||||
src << "Start Input: [startInput]"
|
||||
src << "End Input: [endInput]"
|
||||
return
|
||||
|
||||
var/turf/Start = locate(text2num(startCoords[1]),text2num(startCoords[2]),text2num(startCoords[3]))
|
||||
var/turf/End = locate(text2num(endCoords[1]),text2num(endCoords[2]),text2num(endCoords[3]))
|
||||
if(!Start || !End)
|
||||
src << "Invalid Turfs"
|
||||
src << "Start Coords: [startCoords[1]] - [startCoords[2]] - [startCoords[3]]"
|
||||
src << "End Coords: [endCoords[1]] - [endCoords[2]] - [endCoords[3]]"
|
||||
return
|
||||
|
||||
var/list/clusters = list("None"=CLUSTER_CHECK_NONE,"All"=CLUSTER_CHECK_ALL,"Sames"=CLUSTER_CHECK_SAMES,"Differents"=CLUSTER_CHECK_DIFFERENTS, \
|
||||
"Same turfs"=CLUSTER_CHECK_SAME_TURFS, "Same atoms"=CLUSTER_CHECK_SAME_ATOMS, "Different turfs"=CLUSTER_CHECK_DIFFERENT_TURFS, \
|
||||
"Different atoms"=CLUSTER_CHECK_DIFFERENT_ATOMS, "All turfs"=CLUSTER_CHECK_ALL_TURFS,"All atoms"=CLUSTER_CHECK_ALL_ATOMS)
|
||||
|
||||
var/moduleClusters = input("Cluster Flags (Cancel to leave unchanged from defaults)","Map Gen Settings") as null|anything in clusters
|
||||
//null for default
|
||||
|
||||
var/theCluster = 0
|
||||
if(moduleClusters != "None")
|
||||
if(!clusters[moduleClusters])
|
||||
src << "Invalid Cluster Flags"
|
||||
return
|
||||
theCluster = clusters[moduleClusters]
|
||||
else
|
||||
theCluster = CLUSTER_CHECK_NONE
|
||||
|
||||
if(theCluster)
|
||||
for(var/datum/mapGeneratorModule/M in N.modules)
|
||||
M.clusterCheckFlags = theCluster
|
||||
|
||||
|
||||
src << "Defining Region"
|
||||
N.defineRegion(Start, End)
|
||||
src << "Region Defined"
|
||||
src << "Generating Region"
|
||||
N.generate()
|
||||
src << "Generated Region"
|
||||
|
||||
146
code/modules/procedural_mapping/mapGeneratorModule.dm
Normal file
146
code/modules/procedural_mapping/mapGeneratorModule.dm
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
/datum/mapGeneratorModule
|
||||
var/datum/mapGenerator/mother = null
|
||||
var/list/spawnableAtoms = list()
|
||||
var/list/spawnableTurfs = list()
|
||||
var/clusterMax = 5
|
||||
var/clusterMin = 1
|
||||
var/clusterCheckFlags = CLUSTER_CHECK_SAME_ATOMS
|
||||
var/allowAtomsOnSpace = FALSE
|
||||
|
||||
|
||||
//Syncs the module up with it's mother
|
||||
/datum/mapGeneratorModule/proc/sync(datum/mapGenerator/mum)
|
||||
mother = null
|
||||
if(mum)
|
||||
mother = mum
|
||||
|
||||
|
||||
//Generates it's spawnable atoms and turfs
|
||||
/datum/mapGeneratorModule/proc/generate()
|
||||
if(!mother)
|
||||
return
|
||||
var/list/map = mother.map
|
||||
for(var/turf/T in map)
|
||||
place(T)
|
||||
|
||||
|
||||
//Place a spawnable atom or turf on this turf
|
||||
/datum/mapGeneratorModule/proc/place(turf/T)
|
||||
if(!T)
|
||||
return 0
|
||||
|
||||
var/clustering = 0
|
||||
var/skipLoopIteration = FALSE
|
||||
|
||||
//Turfs don't care whether atoms can be placed here
|
||||
for(var/turfPath in spawnableTurfs)
|
||||
|
||||
//Clustering!
|
||||
if(clusterMax && clusterMin)
|
||||
|
||||
//You're the same as me? I hate you I'm going home
|
||||
if(clusterCheckFlags & CLUSTER_CHECK_SAME_TURFS)
|
||||
clustering = rand(clusterMin,clusterMax)
|
||||
for(var/turf/F in RANGE_TURFS(clustering,T))
|
||||
if(istype(F,turfPath))
|
||||
skipLoopIteration = TRUE
|
||||
break
|
||||
if(skipLoopIteration)
|
||||
skipLoopIteration = FALSE
|
||||
continue
|
||||
|
||||
//You're DIFFERENT to me? I hate you I'm going home
|
||||
if(clusterCheckFlags & CLUSTER_CHECK_DIFFERENT_TURFS)
|
||||
clustering = rand(clusterMin,clusterMax)
|
||||
for(var/turf/F in RANGE_TURFS(clustering,T))
|
||||
if(!(istype(F,turfPath)))
|
||||
skipLoopIteration = TRUE
|
||||
break
|
||||
if(skipLoopIteration)
|
||||
skipLoopIteration = FALSE
|
||||
continue
|
||||
|
||||
//Success!
|
||||
if(prob(spawnableTurfs[turfPath]))
|
||||
T.ChangeTurf(turfPath)
|
||||
|
||||
|
||||
//Atoms DO care whether atoms can be placed here
|
||||
if(checkPlaceAtom(T))
|
||||
|
||||
for(var/atomPath in spawnableAtoms)
|
||||
|
||||
//Clustering!
|
||||
if(clusterMax && clusterMin)
|
||||
|
||||
//You're the same as me? I hate you I'm going home
|
||||
if(clusterCheckFlags & CLUSTER_CHECK_SAME_ATOMS)
|
||||
clustering = rand(clusterMin, clusterMax)
|
||||
for(var/atom/movable/M in range(clustering,T))
|
||||
if(istype(M,atomPath))
|
||||
skipLoopIteration = TRUE
|
||||
break
|
||||
if(skipLoopIteration)
|
||||
skipLoopIteration = FALSE
|
||||
continue
|
||||
|
||||
//You're DIFFERENT from me? I hate you I'm going home
|
||||
if(clusterCheckFlags & CLUSTER_CHECK_DIFFERENT_ATOMS)
|
||||
clustering = rand(clusterMin, clusterMax)
|
||||
for(var/atom/movable/M in range(clustering,T))
|
||||
if(!(istype(M,atomPath)))
|
||||
skipLoopIteration = TRUE
|
||||
break
|
||||
if(skipLoopIteration)
|
||||
skipLoopIteration = FALSE
|
||||
continue
|
||||
|
||||
//Success!
|
||||
if(prob(spawnableAtoms[atomPath]))
|
||||
new atomPath(T)
|
||||
|
||||
. = 1
|
||||
|
||||
|
||||
//Checks and Rejects dense turfs
|
||||
/datum/mapGeneratorModule/proc/checkPlaceAtom(turf/T)
|
||||
. = 1
|
||||
if(!T)
|
||||
return 0
|
||||
if(T.density)
|
||||
. = 0
|
||||
for(var/atom/A in T)
|
||||
if(A.density)
|
||||
. = 0
|
||||
break
|
||||
if(!allowAtomsOnSpace && (istype(T,/turf/open/space)))
|
||||
. = 0
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// PREMADE BASE TEMPLATES //
|
||||
// Appropriate settings for usable types //
|
||||
// Not usable types themselves, use them as parent types //
|
||||
// Seriously, don't use these on their own, just parents //
|
||||
///////////////////////////////////////////////////////////
|
||||
//The /atom and /turf examples are just so these compile, replace those with your typepaths in your subtypes.
|
||||
|
||||
//Settings appropriate for a turf that covers the entire map region, eg a fill colour on a bottom layer in a graphics program.
|
||||
//Should only have one of these in your mapGenerator unless you want to waste CPU
|
||||
/datum/mapGeneratorModule/bottomLayer
|
||||
clusterCheckFlags = CLUSTER_CHECK_NONE
|
||||
spawnableAtoms = list()//Recommended: No atoms.
|
||||
spawnableTurfs = list(/turf = 100)
|
||||
|
||||
//Settings appropriate for turfs/atoms that cover SOME of the map region, sometimes referred to as a splatter layer.
|
||||
/datum/mapGeneratorModule/splatterLayer
|
||||
clusterCheckFlags = CLUSTER_CHECK_ALL
|
||||
spawnableAtoms = list(/atom = 30)
|
||||
spawnableTurfs = list(/turf = 30)
|
||||
|
||||
//Settings appropriate for turfs/atoms that cover a lot of the map region, eg a dense forest.
|
||||
/datum/mapGeneratorModule/denseLayer
|
||||
clusterCheckFlags = CLUSTER_CHECK_NONE
|
||||
spawnableAtoms = list(/atom = 75)
|
||||
spawnableTurfs = list(/turf = 75)
|
||||
@@ -0,0 +1,40 @@
|
||||
//Helper Modules
|
||||
|
||||
|
||||
// Helper to repressurize the area in case it was run in space
|
||||
/datum/mapGeneratorModule/bottomLayer/repressurize
|
||||
spawnableAtoms = list()
|
||||
spawnableTurfs = list()
|
||||
|
||||
/datum/mapGeneratorModule/bottomLayer/repressurize/generate()
|
||||
if(!mother)
|
||||
return
|
||||
var/list/map = mother.map
|
||||
for(var/turf/T in map)
|
||||
SSair.remove_from_active(T)
|
||||
for(var/turf/open/T in map)
|
||||
if(T.air)
|
||||
T.air.copy_from_turf(T)
|
||||
SSair.add_to_active(T)
|
||||
|
||||
//Only places atoms/turfs on area borders
|
||||
/datum/mapGeneratorModule/border
|
||||
clusterCheckFlags = CLUSTER_CHECK_NONE
|
||||
|
||||
/datum/mapGeneratorModule/border/generate()
|
||||
if(!mother)
|
||||
return
|
||||
var/list/map = mother.map
|
||||
for(var/turf/T in map)
|
||||
if(is_border(T))
|
||||
place(T)
|
||||
|
||||
/datum/mapGeneratorModule/border/proc/is_border(turf/T)
|
||||
for(var/direction in list(SOUTH,EAST,WEST,NORTH))
|
||||
if (get_step(T,direction) in mother.map)
|
||||
continue
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/mapGenerator/repressurize
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/repressurize)
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
//Contents exist primarily for the nature generator test type.
|
||||
|
||||
|
||||
//Pine Trees
|
||||
/datum/mapGeneratorModule/pineTrees
|
||||
spawnableAtoms = list(/obj/structure/flora/tree/pine = 30)
|
||||
|
||||
//Dead Trees
|
||||
/datum/mapGeneratorModule/deadTrees
|
||||
spawnableAtoms = list(/obj/structure/flora/tree/dead = 10)
|
||||
|
||||
//Random assortment of bushes
|
||||
/datum/mapGeneratorModule/randBushes
|
||||
spawnableAtoms = list()
|
||||
|
||||
/datum/mapGeneratorModule/randBushes/New()
|
||||
..()
|
||||
spawnableAtoms = typesof(/obj/structure/flora/ausbushes)
|
||||
for(var/i in spawnableAtoms)
|
||||
spawnableAtoms[i] = 20
|
||||
|
||||
|
||||
//Random assortment of rocks and rockpiles
|
||||
/datum/mapGeneratorModule/randRocks
|
||||
spawnableAtoms = list(/obj/structure/flora/rock = 40, /obj/structure/flora/rock/pile = 20)
|
||||
|
||||
|
||||
//Grass turfs
|
||||
/datum/mapGeneratorModule/bottomLayer/grassTurfs
|
||||
spawnableTurfs = list(/turf/open/floor/grass = 100)
|
||||
|
||||
|
||||
//Grass tufts with a high spawn chance
|
||||
/datum/mapGeneratorModule/denseLayer/grassTufts
|
||||
spawnableTurfs = list()
|
||||
spawnableAtoms = list(/obj/structure/flora/ausbushes/grassybush = 75)
|
||||
19
code/modules/procedural_mapping/mapGeneratorObj.dm
Normal file
19
code/modules/procedural_mapping/mapGeneratorObj.dm
Normal file
@@ -0,0 +1,19 @@
|
||||
/obj/effect/landmark/mapGenerator
|
||||
var/startTurfX = 0
|
||||
var/startTurfY = 0
|
||||
var/startTurfZ = -1
|
||||
var/endTurfX = 0
|
||||
var/endTurfY = 0
|
||||
var/endTurfZ = -1
|
||||
var/mapGeneratorType = /datum/mapGenerator/nature
|
||||
var/datum/mapGenerator/mapGenerator
|
||||
|
||||
/obj/effect/landmark/mapGenerator/New()
|
||||
..()
|
||||
if(startTurfZ < 0)
|
||||
startTurfZ = z
|
||||
if(endTurfZ < 0)
|
||||
endTurfZ = z
|
||||
mapGenerator = new mapGeneratorType()
|
||||
mapGenerator.defineRegion(locate(startTurfX,startTurfY,startTurfZ), locate(endTurfX,endTurfY,endTurfZ))
|
||||
mapGenerator.generate()
|
||||
146
code/modules/procedural_mapping/mapGeneratorReadme.dm
Normal file
146
code/modules/procedural_mapping/mapGeneratorReadme.dm
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
/*
|
||||
by RemieRichards
|
||||
|
||||
//////////////////////////////
|
||||
// CODER INFORMATIVE README //
|
||||
//////////////////////////////
|
||||
(See below for Mapper Friendly Readme)
|
||||
|
||||
mapGenerator:
|
||||
Desc: a mapGenerator is a master datum that collects
|
||||
and syncs all mapGeneratorModules in it's modules list
|
||||
|
||||
defineRegion(var/turf/Start, var/turf/End, var/replace = 0)
|
||||
Example: defineRegion(locate(1,1,1),locate(5,5,5),0)
|
||||
Desc: Sets the bounds of the mapGenerator's "map"
|
||||
|
||||
defineCircularRegion(var/turf/Start, var/turf/End, var/replace = 0)
|
||||
Example: defineCircularRegion(locate(1,1,1),locate(5,5,5),0)
|
||||
Desc: Sets the mapGenerator's "map" as a circle, with center in the middle of Start and End's X,Y,Z coordinates
|
||||
|
||||
undefineRegion()
|
||||
Example: undefineRegion()
|
||||
Desc: Empties the map generator list
|
||||
|
||||
checkRegion(var/turf/Start, var/turf/End)
|
||||
Example: checkRegion(locate(1,1,1), locate(5,5,5))
|
||||
Desc: Checks if a rectangle between Start's coords and End's coords is valid
|
||||
Existing Calls: mapGenerator/defineRegion(), mapGenerator/defineCircularRegion()
|
||||
|
||||
generate()
|
||||
Example: generate()
|
||||
Desc: Orders all mapGeneratorModules in the modules list to generate()
|
||||
|
||||
generateOneTurf(var/turf/T)
|
||||
Example: generateOneTurf(locate(1,1,1))
|
||||
Desc: Orders all mapGeneratorModules in the modules list to place(T) on this turf
|
||||
|
||||
initialiseModules()
|
||||
Example: initialiseModules()
|
||||
Desc: Replaces all typepaths in the modules list with actual /datum/mapGenerator/Module types
|
||||
Existing Calls: mapGenerator/New()
|
||||
|
||||
syncModules()
|
||||
Example: syncModules()
|
||||
Desc: Sets the Mother variable on all mapGeneratorModules in the modules list to this mapGenerator
|
||||
Existing Calls: initialiseModules(),generate(),generateOneTurf()
|
||||
|
||||
|
||||
mapGeneratorModule
|
||||
Desc: a mapGeneratorModule has spawnableAtoms and spawnableTurfs lists
|
||||
which it will generate on turfs in it's mother's map based on cluster variables
|
||||
|
||||
sync(var/datum/mapGenerator/mum)
|
||||
Example: sync(a_mapGenerator_as_a_variable)
|
||||
Desc: Sets the Mother variable to the mum argument
|
||||
Existing Calls: mapGenerator/syncModules()
|
||||
|
||||
generate()
|
||||
Example: generate()
|
||||
Desc: Calls place(T) on all turfs in it's mother's map
|
||||
Existing Calls: mapGenerator/generate()
|
||||
|
||||
place(var/turf/T)
|
||||
Example: place(locate(1,1,1))
|
||||
Desc: Run this mapGeneratorModule's effects on this turf (Spawning atoms, Changing turfs)
|
||||
Existing Calls: mapGenerator/generate(), mapGenerator/generateOneTurf()
|
||||
|
||||
checkPlaceAtom(var/turf/T)
|
||||
Example: checkPlace(locate(1,1,1))
|
||||
Desc: Checks if the turf is valid for placing atoms
|
||||
Existing Calls: place()
|
||||
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// MAPPER FRIENDLY README //
|
||||
////////////////////////////
|
||||
|
||||
Simple Workflow:
|
||||
|
||||
1. Define a/some mapGeneratorModule(s) to your liking, choosing atoms and turfs to spawn
|
||||
#Note: I chose to split Turfs and Atoms off into seperate modules, but this is NOT required.
|
||||
#Note: A mapGeneratorModule may have turfs AND atoms, so long as each is in it's appropriate list
|
||||
|
||||
2. Define a mapGenerator type who's modules list contains the typepath(s) of all the module(s) you wish to use
|
||||
#Note: The order of the typepaths in the modules list is the order they will happen in, this is important for clusterCheckFlags.
|
||||
|
||||
3. Take notes of the Bottom Left and Top Right turfs of your rectangular "map"'s coordinates
|
||||
#Note: X,Y AND Z, Yes you can created 3D "maps" by having differing Z coords
|
||||
|
||||
4. Create the mapGenerator type you created
|
||||
|
||||
5. Call yourMapGeneratorType.defineRegion(locate(X,Y,Z), locate(X,Y,Z))
|
||||
#Note: The above X/Y/Zs are the coordinates of the start and end turfs, the locate() simply finds the turf for the code
|
||||
|
||||
6. Call yourMapGeneratorType.generate(), this will cause all the modules in the generator to build within the map bounds
|
||||
|
||||
Option Suggestions:
|
||||
|
||||
* Have seperate modules for Turfs and Atoms, this is not enforced, but it is how I have structured my nature example.
|
||||
* If your map doesn't look quite to your liking, simply jiggle with the variables on your modules and the type probabilities
|
||||
* You can mix and map premade areas with the procedural generation, for example mapping an entire flat land but having code generate just the grass tufts
|
||||
|
||||
|
||||
Using the Modules list
|
||||
|
||||
Simply think of it like each module is a layer in a graphics editing program!
|
||||
To help you do this templates such as /mapGeneratorModule/bottomLayer have been provided with appropriate default settings.
|
||||
These are located near the bottom of mapGeneratorModule.dm
|
||||
you would order your list left to right, top to bottom, e.g:
|
||||
modules = list(bottomLayer,nextLayer,nextNextLayer) etc.
|
||||
|
||||
|
||||
Variable Breakdown (For Mappers):
|
||||
|
||||
mapGenerator
|
||||
map - INTERNAL, do not touch
|
||||
modules - A list of typepaths of mapGeneratorModules
|
||||
|
||||
mapGeneratorModule
|
||||
mother - INTERNAL, do not touch
|
||||
spawnableAtoms - A list of typepaths and their probability to spawn, eg: spawnableAtoms = list(/obj/structure/flora/tree/pine = 30)
|
||||
spawnableTurfs - A list of typepaths and their probability to spawn, eg: spawnableTurfs = list(/turf/unsimulated/floor/grass = 100)
|
||||
clusterMax - The max range to check for something being "too close" for this atom/turf to spawn, the true value is random between clusterMin and clusterMax
|
||||
clusterMin - The min range to check for something being "too close" for this atom/turf to spawn, the true value is random between clusterMin and clusterMax
|
||||
clusterCheckFlags - A Bitfield that controls how the cluster checks work, All based on clusterMin and clusterMax guides
|
||||
allowAtomsOnSpace - A Boolean for if we allow atoms to spawn on space tiles
|
||||
|
||||
clusterCheckFlags flags:
|
||||
CLUSTER_CHECK_NONE 0 //No checks are done, cluster as much as possible
|
||||
CLUSTER_CHECK_DIFFERENT_TURFS 2 //Don't let turfs of DIFFERENT types cluster
|
||||
CLUSTER_CHECK_DIFFERENT_ATOMS 4 //Don't let atoms of DIFFERENT types cluster
|
||||
CLUSTER_CHECK_SAME_TURFS 8 //Don't let turfs of the SAME type cluster
|
||||
CLUSTER_CHECK_SAME_ATOMS 16 //Don't let atoms of the SAME type cluster
|
||||
|
||||
CLUSTER_CHECK_SAMES 24 //Don't let any of the same type cluster
|
||||
CLUSTER_CHECK_DIFFERENTS 6 //Don't let any different types cluster
|
||||
CLUSTER_CHECK_ALL_TURFS 10 //Don't let ANY turfs cluster same and different types
|
||||
CLUSTER_CHECK_ALL_ATOMS 20 //Don't let ANY atoms cluster same and different types
|
||||
|
||||
CLUSTER_CHECK_ALL 30 //Don't let anything cluster, like, at all
|
||||
|
||||
|
||||
|
||||
*/
|
||||
45
code/modules/procedural_mapping/mapGenerators/asteroid.dm
Normal file
45
code/modules/procedural_mapping/mapGenerators/asteroid.dm
Normal file
@@ -0,0 +1,45 @@
|
||||
//Asteroid turfs
|
||||
/datum/mapGeneratorModule/bottomLayer/asteroidTurfs
|
||||
spawnableTurfs = list(/turf/open/floor/plating/asteroid = 100)
|
||||
|
||||
/datum/mapGeneratorModule/bottomLayer/asteroidWalls
|
||||
spawnableTurfs = list(/turf/closed/mineral = 100)
|
||||
|
||||
//Border walls
|
||||
/datum/mapGeneratorModule/border/asteroidWalls
|
||||
spawnableAtoms = list()
|
||||
spawnableTurfs = list(/turf/closed/mineral = 100)
|
||||
|
||||
//Random walls
|
||||
/datum/mapGeneratorModule/splatterLayer/asteroidWalls
|
||||
clusterCheckFlags = CLUSTER_CHECK_NONE
|
||||
spawnableAtoms = list()
|
||||
spawnableTurfs = list(/turf/closed/mineral = 30)
|
||||
|
||||
//Monsters
|
||||
/datum/mapGeneratorModule/splatterLayer/asteroidMonsters
|
||||
spawnableTurfs = list()
|
||||
spawnableAtoms = list(/mob/living/simple_animal/hostile/asteroid/basilisk = 10, \
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelord = 10, \
|
||||
/mob/living/simple_animal/hostile/asteroid/goliath = 10)
|
||||
|
||||
|
||||
// GENERATORS
|
||||
|
||||
/datum/mapGenerator/asteroid/hollow
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/asteroidTurfs, \
|
||||
/datum/mapGeneratorModule/border/asteroidWalls)
|
||||
|
||||
/datum/mapGenerator/asteroid/hollow/random
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/asteroidTurfs, \
|
||||
/datum/mapGeneratorModule/border/asteroidWalls, \
|
||||
/datum/mapGeneratorModule/splatterLayer/asteroidWalls)
|
||||
|
||||
/datum/mapGenerator/asteroid/hollow/random/monsters
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/asteroidTurfs, \
|
||||
/datum/mapGeneratorModule/border/asteroidWalls, \
|
||||
/datum/mapGeneratorModule/splatterLayer/asteroidWalls, \
|
||||
/datum/mapGeneratorModule/splatterLayer/asteroidMonsters)
|
||||
|
||||
/datum/mapGenerator/asteroid/filled
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/asteroidWalls)
|
||||
98
code/modules/procedural_mapping/mapGenerators/cellular.dm
Normal file
98
code/modules/procedural_mapping/mapGenerators/cellular.dm
Normal file
@@ -0,0 +1,98 @@
|
||||
// Very Simple Cellular Automata generators
|
||||
// Mostly for better caves
|
||||
// Should probably move these up and refactor modules so these can be mixed with other ones
|
||||
|
||||
/datum/mapGenerator/ca
|
||||
var/list/b_rule = list() // 0 -> 1, 1 -> 1
|
||||
var/list/s_rule = list() // 0 -> 0, 1 -> 1
|
||||
var/iterations = 1
|
||||
var/loop_edges = 0
|
||||
var/edge_value = 1 //if loop_edges = 0
|
||||
var/list/old_state
|
||||
var/list/current_state
|
||||
var/width = 10
|
||||
var/height = 10
|
||||
var/list/type_map = list(/turf/open/floor/plating,/turf/closed/wall)
|
||||
var/turf/start = null
|
||||
|
||||
/datum/mapGenerator/ca/defineRegion(turf/Start, turf/End, replace = 0)
|
||||
. = ..()
|
||||
|
||||
var/min_x = min(Start.x,End.x)
|
||||
var/max_x = max(Start.x,End.x)
|
||||
var/min_y = min(Start.y,End.y)
|
||||
var/max_y = max(Start.y,End.y)
|
||||
width = max_x - min_x
|
||||
height = max_y - min_y
|
||||
|
||||
//We assume 2D everywhere anyway
|
||||
start = locate(min_x,min_y,Start.z)
|
||||
|
||||
/datum/mapGenerator/ca/proc/initialize()
|
||||
old_state = new/list(width)
|
||||
for(var/i = 1,i<=width,i++)
|
||||
old_state[i] = new/list(height)
|
||||
for(var/j = 1,j<=height,j++)
|
||||
old_state[i][j] = rand(0,1)
|
||||
|
||||
current_state = old_state.Copy()
|
||||
|
||||
/datum/mapGenerator/ca/generate()
|
||||
set background = 1
|
||||
|
||||
//Abandon all hope for efficency all who enter here
|
||||
//Maybe some less basic implemetation later, but this is just simple admin tool
|
||||
initialize()
|
||||
|
||||
for(var/generation = 0,generation<iterations,generation++)
|
||||
for(var/i = 1,i<=width,i++)
|
||||
for(var/j = 1,j<=height,j++)
|
||||
current_state[i][j] = apply_rule(i,j)
|
||||
//copy state over
|
||||
old_state = current_state.Copy()
|
||||
|
||||
for(var/i=1,i<=width,i++)
|
||||
for(var/j=1,j<=height,j++)
|
||||
var/turf/T = locate(start.x+i-1,start.y+j-1,start.z)
|
||||
if(T)
|
||||
T.ChangeTurf(type_map[current_state[i][j]+1])
|
||||
|
||||
/datum/mapGenerator/ca/proc/apply_rule(i,j)
|
||||
var/value = 0
|
||||
for(var/dx=-1,dx<=1,dx++)
|
||||
for(var/dy=-1,dy<=1,dy++)
|
||||
var/n_x = i+dx
|
||||
var/n_y = j+dy
|
||||
if(n_x < 1 || n_x > width || n_y <1 || n_y > height)
|
||||
if(loop_edges)
|
||||
if(n_x < 1)
|
||||
n_x = width
|
||||
else if(n_x > width)
|
||||
n_x = 1
|
||||
if(n_y < 1)
|
||||
n_y = height
|
||||
else if(n_y > height)
|
||||
n_y = 1
|
||||
else
|
||||
value += edge_value
|
||||
continue
|
||||
value += old_state[n_x][n_y]
|
||||
value -= old_state[i][j]
|
||||
|
||||
if(value in b_rule)
|
||||
return 1
|
||||
if(value in s_rule)
|
||||
return old_state[i][j]
|
||||
return 0
|
||||
|
||||
/datum/mapGenerator/ca/caves
|
||||
b_rule = list(5,6,7,8)
|
||||
s_rule = list(4)
|
||||
type_map = list(/turf/open/floor/plating/asteroid/basalt,/turf/closed/mineral/volcanic)
|
||||
iterations = 5
|
||||
|
||||
/datum/mapGenerator/ca/maze
|
||||
b_rule = list(3)
|
||||
s_rule = list(1,2,3,4,5)
|
||||
iterations = 20
|
||||
edge_value = 0
|
||||
27
code/modules/procedural_mapping/mapGenerators/lava_river.dm
Normal file
27
code/modules/procedural_mapping/mapGenerators/lava_river.dm
Normal file
@@ -0,0 +1,27 @@
|
||||
/datum/mapGenerator/lavaland
|
||||
var/start_z = 5
|
||||
var/min_x = 0
|
||||
var/min_y = 0
|
||||
var/max_x = 0
|
||||
var/max_y = 0
|
||||
modules = list(/datum/mapGeneratorModule/river)
|
||||
|
||||
/datum/mapGenerator/lavaland/defineRegion(turf/Start, turf/End, replace = 0)
|
||||
start_z = Start.z
|
||||
min_x = min(Start.x,End.x)
|
||||
min_y = min(Start.y,End.y)
|
||||
max_x = max(Start.x,End.x)
|
||||
max_y = max(Start.y,End.y)
|
||||
..()
|
||||
|
||||
/datum/mapGeneratorModule/river
|
||||
var/river_type = /turf/open/floor/plating/lava/smooth
|
||||
var/river_nodes = 4
|
||||
var/start_z = 5
|
||||
|
||||
/datum/mapGeneratorModule/river/generate()
|
||||
var/datum/mapGenerator/lavaland/L = mother
|
||||
if(!istype(L))
|
||||
return
|
||||
start_z = L.start_z
|
||||
spawn_rivers(start_z, river_nodes, river_type, min_x = L.min_x, min_y = L.min_y, max_x = L.max_x, max_y = L.max_y)
|
||||
11
code/modules/procedural_mapping/mapGenerators/nature.dm
Normal file
11
code/modules/procedural_mapping/mapGenerators/nature.dm
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
//Exists primarily as a test type.
|
||||
|
||||
/datum/mapGenerator/nature
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/grassTurfs, \
|
||||
/datum/mapGeneratorModule/pineTrees, \
|
||||
/datum/mapGeneratorModule/deadTrees, \
|
||||
/datum/mapGeneratorModule/randBushes, \
|
||||
/datum/mapGeneratorModule/randRocks, \
|
||||
/datum/mapGeneratorModule/denseLayer/grassTufts)
|
||||
|
||||
15
code/modules/procedural_mapping/mapGenerators/shuttle.dm
Normal file
15
code/modules/procedural_mapping/mapGenerators/shuttle.dm
Normal file
@@ -0,0 +1,15 @@
|
||||
/datum/mapGeneratorModule/bottomLayer/shuttleFloor
|
||||
spawnableTurfs = list(/turf/open/floor/plasteel/shuttle = 100)
|
||||
|
||||
/datum/mapGeneratorModule/border/shuttleWalls
|
||||
spawnableAtoms = list()
|
||||
spawnableTurfs = list(/turf/closed/wall/shuttle = 100)
|
||||
// Generators
|
||||
|
||||
/datum/mapGenerator/shuttle/full
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/shuttleFloor, \
|
||||
/datum/mapGeneratorModule/border/shuttleWalls,\
|
||||
/datum/mapGeneratorModule/bottomLayer/repressurize)
|
||||
|
||||
/datum/mapGenerator/shuttle/floor
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/shuttleFloor)
|
||||
52
code/modules/procedural_mapping/mapGenerators/syndicate.dm
Normal file
52
code/modules/procedural_mapping/mapGenerators/syndicate.dm
Normal file
@@ -0,0 +1,52 @@
|
||||
// Modules
|
||||
|
||||
/turf/open/floor/plasteel/shuttle/red/syndicate
|
||||
name = "floor" //Not Brig Floor
|
||||
|
||||
/datum/mapGeneratorModule/bottomLayer/syndieFloor
|
||||
spawnableTurfs = list(/turf/open/floor/plasteel/shuttle/red/syndicate = 100)
|
||||
|
||||
/datum/mapGeneratorModule/border/syndieWalls
|
||||
spawnableAtoms = list()
|
||||
spawnableTurfs = list(/turf/closed/wall/r_wall = 100)
|
||||
|
||||
|
||||
/datum/mapGeneratorModule/syndieFurniture
|
||||
clusterCheckFlags = CLUSTER_CHECK_ALL
|
||||
spawnableTurfs = list()
|
||||
spawnableAtoms = list(/obj/structure/table = 20,/obj/structure/chair = 15,/obj/structure/chair/stool = 10, \
|
||||
/obj/structure/frame/computer = 15, /obj/item/weapon/storage/toolbox/syndicate = 15 ,\
|
||||
/obj/structure/closet/syndicate = 25, /obj/machinery/suit_storage_unit/syndicate = 15)
|
||||
|
||||
/datum/mapGeneratorModule/splatterLayer/syndieMobs
|
||||
spawnableAtoms = list(/mob/living/simple_animal/hostile/syndicate = 30, \
|
||||
/mob/living/simple_animal/hostile/syndicate/melee = 20, \
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged = 20, \
|
||||
/mob/living/simple_animal/hostile/viscerator = 30)
|
||||
spawnableTurfs = list()
|
||||
|
||||
// Generators
|
||||
|
||||
/datum/mapGenerator/syndicate/empty //walls and floor only
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
|
||||
/datum/mapGeneratorModule/border/syndieWalls,\
|
||||
/datum/mapGeneratorModule/bottomLayer/repressurize)
|
||||
|
||||
/datum/mapGenerator/syndicate/mobsonly
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
|
||||
/datum/mapGeneratorModule/border/syndieWalls,\
|
||||
/datum/mapGeneratorModule/splatterLayer/syndieMobs, \
|
||||
/datum/mapGeneratorModule/bottomLayer/repressurize)
|
||||
|
||||
/datum/mapGenerator/syndicate/furniture
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
|
||||
/datum/mapGeneratorModule/border/syndieWalls,\
|
||||
/datum/mapGeneratorModule/syndieFurniture, \
|
||||
/datum/mapGeneratorModule/bottomLayer/repressurize)
|
||||
|
||||
/datum/mapGenerator/syndicate/full
|
||||
modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
|
||||
/datum/mapGeneratorModule/border/syndieWalls,\
|
||||
/datum/mapGeneratorModule/syndieFurniture, \
|
||||
/datum/mapGeneratorModule/splatterLayer/syndieMobs, \
|
||||
/datum/mapGeneratorModule/bottomLayer/repressurize)
|
||||
Reference in New Issue
Block a user