mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 10:11:09 +00:00
Adds some customization to ruin loader (#35209)
* Adds some customization to ruin loader * Bluh * stuff * Fixes
This commit is contained in:
@@ -76,3 +76,13 @@ Last space-z level = empty
|
|||||||
#define CAMERA_LOCK_MINING 2
|
#define CAMERA_LOCK_MINING 2
|
||||||
#define CAMERA_LOCK_CENTCOM 4
|
#define CAMERA_LOCK_CENTCOM 4
|
||||||
#define CAMERA_LOCK_REEBE 8
|
#define CAMERA_LOCK_REEBE 8
|
||||||
|
|
||||||
|
|
||||||
|
//Ruin Generation
|
||||||
|
|
||||||
|
#define PLACEMENT_TRIES 100 //How many times we try to fit the ruin somewhere until giving up (really should just swap to some packing algo)
|
||||||
|
|
||||||
|
#define PLACE_DEFAULT "random"
|
||||||
|
#define PLACE_SAME_Z "same"
|
||||||
|
#define PLACE_SPACE_RUIN "space"
|
||||||
|
#define PLACE_LAVA_RUIN "lavaland"
|
||||||
@@ -6,8 +6,13 @@
|
|||||||
How is there a wooden container filled with 18th century coinage in the middle of a lavawracked hellscape? \
|
How is there a wooden container filled with 18th century coinage in the middle of a lavawracked hellscape? \
|
||||||
It is clearly a mystery."
|
It is clearly a mystery."
|
||||||
|
|
||||||
var/cost = null //negative numbers will always be placed, with lower (negative) numbers being placed first; positive and 0 numbers will be placed randomly
|
var/unpickable = FALSE //If TRUE these won't be placed automatically (can still be forced or loaded with another ruin)
|
||||||
|
var/always_place = FALSE //Will skip the whole weighting process and just plop this down, ideally you want the ruins of this kind to have no cost.
|
||||||
|
var/placement_weight = 1 //How often should this ruin appear
|
||||||
|
var/cost = 0 //Cost in ruin budget placement system
|
||||||
var/allow_duplicates = TRUE
|
var/allow_duplicates = TRUE
|
||||||
|
var/list/always_spawn_with = null //These ruin types will be spawned along with it (where dependent on the flag) eg list(/datum/map_template/ruin/space/teleporter_space = SPACERUIN_Z)
|
||||||
|
var/list/never_spawn_with = null //If this ruin is spawned these will not eg list(/datum/map_template/ruin/base_alternate)
|
||||||
|
|
||||||
var/prefix = null
|
var/prefix = null
|
||||||
var/suffix = null
|
var/suffix = null
|
||||||
|
|||||||
@@ -120,7 +120,7 @@
|
|||||||
id = "hierophant"
|
id = "hierophant"
|
||||||
description = "A strange, square chunk of metal of massive size. Inside awaits only death and many, many squares."
|
description = "A strange, square chunk of metal of massive size. Inside awaits only death and many, many squares."
|
||||||
suffix = "lavaland_surface_hierophant.dmm"
|
suffix = "lavaland_surface_hierophant.dmm"
|
||||||
cost = -1
|
always_place = TRUE
|
||||||
allow_duplicates = FALSE
|
allow_duplicates = FALSE
|
||||||
|
|
||||||
/datum/map_template/ruin/lavaland/blood_drunk_miner
|
/datum/map_template/ruin/lavaland/blood_drunk_miner
|
||||||
|
|||||||
@@ -1,3 +1,39 @@
|
|||||||
|
/datum/map_template/ruin/proc/try_to_place(z,allowed_areas)
|
||||||
|
var/sanity = PLACEMENT_TRIES
|
||||||
|
while(sanity > 0)
|
||||||
|
sanity--
|
||||||
|
var/width_border = TRANSITIONEDGE + SPACERUIN_MAP_EDGE_PAD + round(width / 2)
|
||||||
|
var/height_border = TRANSITIONEDGE + SPACERUIN_MAP_EDGE_PAD + round(height / 2)
|
||||||
|
var/turf/central_turf = locate(rand(width_border, world.maxx - width_border), rand(height_border, world.maxy - height_border), z)
|
||||||
|
var/valid = TRUE
|
||||||
|
|
||||||
|
for(var/turf/check in get_affected_turfs(central_turf,1))
|
||||||
|
var/area/new_area = get_area(check)
|
||||||
|
if(!(istype(new_area, allowed_areas)) || check.flags_1 & NO_RUINS_1)
|
||||||
|
valid = FALSE
|
||||||
|
break
|
||||||
|
|
||||||
|
if(!valid)
|
||||||
|
continue
|
||||||
|
|
||||||
|
log_world("Ruin \"[name]\" placed at ([central_turf.x], [central_turf.y], [central_turf.z])")
|
||||||
|
|
||||||
|
for(var/i in get_affected_turfs(central_turf, 1))
|
||||||
|
var/turf/T = i
|
||||||
|
for(var/mob/living/simple_animal/monster in T)
|
||||||
|
qdel(monster)
|
||||||
|
for(var/obj/structure/flora/ash/plant in T)
|
||||||
|
qdel(plant)
|
||||||
|
|
||||||
|
load(central_turf,centered = TRUE)
|
||||||
|
loaded++
|
||||||
|
|
||||||
|
for(var/turf/T in get_affected_turfs(central_turf, 1))
|
||||||
|
T.flags_1 |= NO_RUINS_1
|
||||||
|
|
||||||
|
new /obj/effect/landmark/ruin(central_turf, src)
|
||||||
|
return TRUE
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
|
||||||
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins)
|
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins)
|
||||||
@@ -11,98 +47,89 @@
|
|||||||
WARNING("Z level [zl] does not exist - Not generating ruins")
|
WARNING("Z level [zl] does not exist - Not generating ruins")
|
||||||
return
|
return
|
||||||
|
|
||||||
var/overall_sanity = 100
|
|
||||||
var/list/ruins = potentialRuins.Copy()
|
var/list/ruins = potentialRuins.Copy()
|
||||||
|
|
||||||
var/is_picking = FALSE
|
var/list/forced_ruins = list() //These go first on the z level associated (same random one by default)
|
||||||
var/last_checked_ruin_index = 0
|
var/list/ruins_availible = list() //we can try these in the current pass
|
||||||
while(budget > 0 && overall_sanity > 0)
|
var/forced_z //If set we won't pick z level and use this one instead.
|
||||||
// Pick a ruin
|
|
||||||
var/datum/map_template/ruin/ruin = null
|
//Set up the starting ruin list
|
||||||
if(ruins && ruins.len)
|
for(var/key in ruins)
|
||||||
last_checked_ruin_index++ //ruins with no cost come first in the ruin list, so they'll get picked really often
|
var/datum/map_template/ruin/R = ruins[key]
|
||||||
if(is_picking)
|
if(R.cost > budget) //Why would you do that
|
||||||
ruin = ruins[pick(ruins)]
|
|
||||||
else
|
|
||||||
var/ruin_key = ruins[last_checked_ruin_index] //get the ruin's key via index
|
|
||||||
ruin = ruins[ruin_key] //use that key to get the ruin datum itself
|
|
||||||
if(ruin.cost >= 0) //if it has a non-negative cost, cancel out and pick another, to ensure true randomness
|
|
||||||
is_picking = TRUE
|
|
||||||
ruin = ruins[pick(ruins)]
|
|
||||||
else
|
|
||||||
log_world("Ruin loader had no ruins to pick from with [budget] left to spend.")
|
|
||||||
break
|
|
||||||
// Can we afford it
|
|
||||||
if(ruin.cost > budget)
|
|
||||||
overall_sanity--
|
|
||||||
continue
|
continue
|
||||||
// If so, try to place it
|
if(R.always_place)
|
||||||
var/sanity = 100
|
forced_ruins[R] = -1
|
||||||
// And if we can't fit it anywhere, give up, try again
|
if(R.unpickable)
|
||||||
|
continue
|
||||||
|
ruins_availible[R] = R.placement_weight
|
||||||
|
|
||||||
while(sanity > 0)
|
while(budget > 0 && (ruins_availible.len || forced_ruins.len))
|
||||||
sanity--
|
var/datum/map_template/ruin/current_pick
|
||||||
var/width_border = TRANSITIONEDGE + SPACERUIN_MAP_EDGE_PAD + round(ruin.width / 2)
|
var/forced = FALSE
|
||||||
var/height_border = TRANSITIONEDGE + SPACERUIN_MAP_EDGE_PAD + round(ruin.height / 2)
|
if(forced_ruins.len) //We have something we need to load right now, so just pick it
|
||||||
var/z_level = pick(z_levels)
|
for(var/ruin in forced_ruins)
|
||||||
var/turf/T = locate(rand(width_border, world.maxx - width_border), rand(height_border, world.maxy - height_border), z_level)
|
current_pick = ruin
|
||||||
var/valid = TRUE
|
if(forced_ruins[ruin] > 0) //Load into designated z
|
||||||
|
forced_z = forced_ruins[ruin]
|
||||||
|
forced = TRUE
|
||||||
|
break
|
||||||
|
else //Otherwise just pick random one
|
||||||
|
current_pick = pickweight(ruins_availible)
|
||||||
|
|
||||||
for(var/turf/check in ruin.get_affected_turfs(T,1))
|
var/placement_tries = PLACEMENT_TRIES
|
||||||
var/area/new_area = get_area(check)
|
var/failed_to_place = TRUE
|
||||||
if(!(istype(new_area, whitelist)) || check.flags_1 & NO_RUINS_1)
|
var/z_placed = 0
|
||||||
valid = FALSE
|
while(placement_tries > 0)
|
||||||
break
|
placement_tries--
|
||||||
|
z_placed = pick(z_levels)
|
||||||
if(!valid)
|
if(!current_pick.try_to_place(forced_z ? forced_z : z_placed,whitelist))
|
||||||
continue
|
continue
|
||||||
|
else
|
||||||
|
failed_to_place = FALSE
|
||||||
|
break
|
||||||
|
|
||||||
log_world("Ruin \"[ruin.name]\" placed at ([T.x], [T.y], [T.z])")
|
//That's done remove from priority even if it failed
|
||||||
|
if(forced)
|
||||||
|
//TODO : handle forced ruins with multiple variants
|
||||||
|
forced_ruins -= current_pick
|
||||||
|
forced = FALSE
|
||||||
|
|
||||||
|
if(failed_to_place)
|
||||||
|
for(var/datum/map_template/ruin/R in ruins_availible)
|
||||||
|
if(R.id == current_pick.id)
|
||||||
|
ruins_availible -= R
|
||||||
|
log_world("Failed to place [current_pick.name] ruin.")
|
||||||
|
else
|
||||||
|
budget -= current_pick.cost
|
||||||
|
if(!current_pick.allow_duplicates)
|
||||||
|
for(var/datum/map_template/ruin/R in ruins_availible)
|
||||||
|
if(R.id == current_pick.id)
|
||||||
|
ruins_availible -= R
|
||||||
|
if(current_pick.never_spawn_with)
|
||||||
|
for(var/blacklisted_type in current_pick.never_spawn_with)
|
||||||
|
for(var/possible_exclusion in ruins_availible)
|
||||||
|
if(istype(possible_exclusion,blacklisted_type))
|
||||||
|
ruins_availible -= possible_exclusion
|
||||||
|
if(current_pick.always_spawn_with)
|
||||||
|
for(var/v in current_pick.always_spawn_with)
|
||||||
|
for(var/ruin_name in SSmapping.ruins_templates) //Because we might want to add space templates as linked of lava templates.
|
||||||
|
var/datum/map_template/ruin/linked = SSmapping.ruins_templates[ruin_name] //why are these assoc, very annoying.
|
||||||
|
if(istype(linked,v))
|
||||||
|
switch(current_pick.always_spawn_with[v])
|
||||||
|
if(PLACE_SAME_Z)
|
||||||
|
forced_ruins[linked] = forced_z ? forced_z : z_placed //I guess you might want a chain somehow
|
||||||
|
if(PLACE_LAVA_RUIN)
|
||||||
|
forced_ruins[linked] = pick(SSmapping.levels_by_trait(ZTRAIT_LAVA_RUINS))
|
||||||
|
if(PLACE_SPACE_RUIN)
|
||||||
|
forced_ruins[linked] = pick(SSmapping.levels_by_trait(ZTRAIT_SPACE_RUINS))
|
||||||
|
if(PLACE_DEFAULT)
|
||||||
|
forced_ruins[linked] = -1
|
||||||
|
forced_z = 0
|
||||||
|
|
||||||
var/obj/effect/ruin_loader/R = new /obj/effect/ruin_loader(T)
|
//Update the availible list
|
||||||
R.Load(ruins,ruin)
|
for(var/datum/map_template/ruin/R in ruins_availible)
|
||||||
if(ruin.cost >= 0)
|
if(R.cost > budget)
|
||||||
budget -= ruin.cost
|
ruins_availible -= R
|
||||||
if(!ruin.allow_duplicates)
|
|
||||||
for(var/m in ruins)
|
log_world("Ruin loader finished with [budget] left to spend.")
|
||||||
var/datum/map_template/ruin/ruin_to_remove = ruins[m]
|
|
||||||
if(ruin_to_remove.id == ruin.id) //remove all ruins with the same ID, to make sure that ruins with multiple variants work properly
|
|
||||||
ruins -= ruin_to_remove.name
|
|
||||||
last_checked_ruin_index--
|
|
||||||
break
|
|
||||||
|
|
||||||
if(!overall_sanity)
|
|
||||||
log_world("Ruin loader gave up with [budget] left to spend.")
|
|
||||||
|
|
||||||
|
|
||||||
/obj/effect/ruin_loader
|
|
||||||
name = "random ruin"
|
|
||||||
icon = 'icons/obj/items_and_weapons.dmi'
|
|
||||||
icon_state = "syndballoon"
|
|
||||||
invisibility = 0
|
|
||||||
|
|
||||||
/obj/effect/ruin_loader/proc/Load(list/potentialRuins, datum/map_template/template)
|
|
||||||
var/list/possible_ruins = list()
|
|
||||||
for(var/A in potentialRuins)
|
|
||||||
var/datum/map_template/T = potentialRuins[A]
|
|
||||||
if(!T.loaded)
|
|
||||||
possible_ruins += T
|
|
||||||
if(!template && possible_ruins.len)
|
|
||||||
template = safepick(possible_ruins)
|
|
||||||
if(!template)
|
|
||||||
return FALSE
|
|
||||||
var/turf/central_turf = get_turf(src)
|
|
||||||
for(var/i in template.get_affected_turfs(central_turf, 1))
|
|
||||||
var/turf/T = i
|
|
||||||
for(var/mob/living/simple_animal/monster in T)
|
|
||||||
qdel(monster)
|
|
||||||
for(var/obj/structure/flora/ash/plant in T)
|
|
||||||
qdel(plant)
|
|
||||||
template.load(central_turf,centered = TRUE)
|
|
||||||
template.loaded++
|
|
||||||
var/datum/map_template/ruin = template
|
|
||||||
if(istype(ruin))
|
|
||||||
new /obj/effect/landmark/ruin(central_turf, ruin)
|
|
||||||
|
|
||||||
qdel(src)
|
|
||||||
return TRUE
|
|
||||||
|
|||||||
Reference in New Issue
Block a user