mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-22 12:29:46 +01:00
Overmap exoplanet generation, ported from Bay. (#12362)
This commit is contained in:
@@ -0,0 +1,419 @@
|
||||
/obj/effect/overmap/visitable/sector/exoplanet
|
||||
name = "exoplanet"
|
||||
icon_state = "globe"
|
||||
in_space = 0
|
||||
var/area/planetary_area
|
||||
var/list/seeds = list()
|
||||
var/list/animals = list()
|
||||
var/max_animal_count
|
||||
var/datum/gas_mixture/atmosphere
|
||||
var/list/breathgas = list() //list of gases animals/plants require to survive
|
||||
var/badgas //id of gas that is toxic to life here
|
||||
|
||||
var/lightlevel = 0 //This default makes turfs not generate light. Adjust to have exoplanents be lit.
|
||||
var/night = TRUE
|
||||
var/daycycle //How often do we change day and night
|
||||
var/daycolumn = 0 //Which column's light needs to be updated next?
|
||||
var/daycycle_column_delay = 10 SECONDS
|
||||
|
||||
var/maxx
|
||||
var/maxy
|
||||
var/landmark_type = /obj/effect/shuttle_landmark/automatic
|
||||
|
||||
var/list/rock_colors = list(COLOR_ASTEROID_ROCK)
|
||||
var/list/plant_colors = list("RANDOM")
|
||||
var/grass_color
|
||||
var/surface_color = COLOR_ASTEROID_ROCK
|
||||
var/water_color = "#436499"
|
||||
var/image/skybox_image
|
||||
|
||||
var/list/actors = list() //things that appear in engravings on xenoarch finds.
|
||||
var/list/species = list() //list of names to use for simple animals
|
||||
|
||||
var/repopulating = 0
|
||||
var/repopulate_types = list() // animals which have died that may come back
|
||||
|
||||
var/list/possible_themes = list(/datum/exoplanet_theme)
|
||||
var/list/themes = list()
|
||||
|
||||
var/list/map_generators = list()
|
||||
|
||||
//Flags deciding what features to pick
|
||||
var/ruin_tags_whitelist
|
||||
var/ruin_tags_blacklist
|
||||
var/features_budget = 4
|
||||
var/list/possible_features = list()
|
||||
var/list/spawned_features
|
||||
|
||||
var/habitability_class
|
||||
|
||||
var/list/mobs_to_tolerate = list()
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_habitability()
|
||||
var/roll = rand(1,100)
|
||||
switch(roll)
|
||||
if(1 to 10)
|
||||
habitability_class = HABITABILITY_IDEAL
|
||||
if(11 to 50)
|
||||
habitability_class = HABITABILITY_OKAY
|
||||
else
|
||||
habitability_class = HABITABILITY_BAD
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/New(nloc, max_x, max_y)
|
||||
if(!current_map.use_overmap)
|
||||
return
|
||||
|
||||
maxx = max_x ? max_x : world.maxx
|
||||
maxy = max_y ? max_y : world.maxy
|
||||
planetary_area = new planetary_area()
|
||||
|
||||
name = "[generate_planet_name()], \a [name]"
|
||||
|
||||
world.maxz++
|
||||
forceMove(locate(1,1,world.maxz))
|
||||
|
||||
if(LAZYLEN(possible_themes))
|
||||
var/datum/exoplanet_theme/T = pick(possible_themes)
|
||||
themes += new T
|
||||
|
||||
for(var/T in subtypesof(/datum/map_template/ruin/exoplanet))
|
||||
var/datum/map_template/ruin/exoplanet/ruin = T
|
||||
if(ruin_tags_whitelist && !(ruin_tags_whitelist & initial(ruin.ruin_tags)))
|
||||
continue
|
||||
if(ruin_tags_blacklist & initial(ruin.ruin_tags))
|
||||
continue
|
||||
possible_features += new ruin
|
||||
..()
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/build_level()
|
||||
generate_habitability()
|
||||
generate_atmosphere()
|
||||
generate_map()
|
||||
generate_features()
|
||||
generate_landing(2)
|
||||
update_biome()
|
||||
generate_daycycle()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
//attempt at more consistent history generation for xenoarch finds.
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/get_engravings()
|
||||
if(!actors.len)
|
||||
actors += pick("alien humanoid","an amorphic blob","a short, hairy being","a rodent-like creature","a robot","a primate","a reptilian alien","an unidentifiable object","a statue","a starship","unusual devices","a structure")
|
||||
actors += pick("alien humanoids","amorphic blobs","short, hairy beings","rodent-like creatures","robots","primates","reptilian aliens")
|
||||
|
||||
var/engravings = "[actors[1]] \
|
||||
[pick("surrounded by","being held aloft by","being struck by","being examined by","communicating with")] \
|
||||
[actors[2]]"
|
||||
if(prob(50))
|
||||
engravings += ", [pick("they seem to be enjoying themselves","they seem extremely angry","they look pensive","they are making gestures of supplication","the scene is one of subtle horror","the scene conveys a sense of desperation","the scene is completely bizarre")]"
|
||||
engravings += "."
|
||||
return engravings
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/process(wait, tick)
|
||||
if(animals.len < 0.5*max_animal_count && !repopulating)
|
||||
repopulating = 1
|
||||
max_animal_count = round(max_animal_count * 0.5)
|
||||
for(var/zlevel in map_z)
|
||||
if(repopulating)
|
||||
for(var/i = 1 to round(max_animal_count - animals.len))
|
||||
if(prob(10))
|
||||
var/turf/simulated/T = pick_area_turf(planetary_area, list(/proc/not_turf_contains_dense_objects))
|
||||
var/mob_type = pick(repopulate_types)
|
||||
var/mob/S = new mob_type(T)
|
||||
animals += S
|
||||
death_event.register(S, src, /obj/effect/overmap/visitable/sector/exoplanet/proc/remove_animal)
|
||||
destroyed_event.register(S, src, /obj/effect/overmap/visitable/sector/exoplanet/proc/remove_animal)
|
||||
adapt_animal(S)
|
||||
if(animals.len >= max_animal_count)
|
||||
repopulating = 0
|
||||
|
||||
if(!atmosphere)
|
||||
continue
|
||||
var/zone/Z
|
||||
for(var/i = 1 to maxx)
|
||||
var/turf/simulated/T = locate(i, 2, zlevel)
|
||||
if(istype(T) && T.zone && T.zone.contents.len > (maxx*maxy*0.25)) //if it's a zone quarter of zlevel, good enough odds it's planetary main one
|
||||
Z = T.zone
|
||||
break
|
||||
if(Z && !Z.fire_tiles.len && !atmosphere.compare(Z.air)) //let fire die out first if there is one
|
||||
var/datum/gas_mixture/daddy = new() //make a fake 'planet' zone gas
|
||||
daddy.copy_from(atmosphere)
|
||||
daddy.group_multiplier = Z.air.group_multiplier
|
||||
Z.air.equalize(daddy)
|
||||
|
||||
if(daycycle)
|
||||
if(tick % round(daycycle / wait) == 0)
|
||||
night = !night
|
||||
daycolumn = 1
|
||||
if(daycolumn && tick % round(daycycle_column_delay / wait) == 0)
|
||||
update_daynight()
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/update_daynight()
|
||||
var/light = 0.1
|
||||
if(!night)
|
||||
light = lightlevel
|
||||
for(var/turf/simulated/floor/exoplanet/T in block(locate(daycolumn,1,min(map_z)),locate(daycolumn,maxy,max(map_z))))
|
||||
T.set_light(light, 0.1, 2)
|
||||
daycolumn++
|
||||
if(daycolumn > maxx)
|
||||
daycolumn = 0
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/remove_animal(var/mob/M)
|
||||
animals -= M
|
||||
death_event.unregister(M, src)
|
||||
destroyed_event.unregister(M, src)
|
||||
repopulate_types |= M.type
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_map()
|
||||
var/list/grasscolors = plant_colors.Copy()
|
||||
grasscolors -= "RANDOM"
|
||||
if(length(grasscolors))
|
||||
grass_color = pick(grasscolors)
|
||||
|
||||
for(var/datum/exoplanet_theme/T as anything in themes)
|
||||
T.before_map_generation(src)
|
||||
for(var/zlevel in map_z)
|
||||
for(var/map_type in map_generators)
|
||||
if(ispath(map_type, /datum/random_map/noise/exoplanet))
|
||||
var/datum/random_map/noise/exoplanet/RM = new map_type(null,1,1,zlevel,maxx,maxy,0,1,1,planetary_area, plant_colors)
|
||||
get_biostuff(RM)
|
||||
else
|
||||
new map_type(null,1,1,zlevel,maxx,maxy,0,1,1,planetary_area)
|
||||
|
||||
var/list/edges
|
||||
edges += block(locate(1, 1, zlevel), locate(TRANSITIONEDGE, maxy, zlevel))
|
||||
edges |= block(locate(maxx-TRANSITIONEDGE+1, 1, zlevel),locate(maxx, maxy, zlevel))
|
||||
edges |= block(locate(1, 1, zlevel), locate(maxx, TRANSITIONEDGE, zlevel))
|
||||
edges |= block(locate(1, maxy-TRANSITIONEDGE+1, zlevel),locate(maxx, maxy, zlevel))
|
||||
for(var/turf/T in edges)
|
||||
T.ChangeTurf(/turf/simulated/planet_edge)
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_features()
|
||||
spawned_features = seedRuins(map_z, features_budget, possible_features, /area/exoplanet, maxx, maxy)
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/get_biostuff(var/datum/random_map/noise/exoplanet/random_map)
|
||||
if(!istype(random_map))
|
||||
return
|
||||
seeds += random_map.small_flora_types
|
||||
if(random_map.big_flora_types)
|
||||
seeds += random_map.big_flora_types
|
||||
for(var/mob/living/simple_animal/A in living_mob_list)
|
||||
if(A.z in map_z)
|
||||
animals += A
|
||||
death_event.register(A, src, /obj/effect/overmap/visitable/sector/exoplanet/proc/remove_animal)
|
||||
destroyed_event.register(A, src, /obj/effect/overmap/visitable/sector/exoplanet/proc/remove_animal)
|
||||
max_animal_count = animals.len
|
||||
for(var/type in random_map.fauna_types)
|
||||
mobs_to_tolerate[type] = TRUE
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/update_biome()
|
||||
for(var/datum/seed/S as anything in seeds)
|
||||
adapt_seed(S)
|
||||
|
||||
for(var/mob/living/simple_animal/A as anything in animals)
|
||||
adapt_animal(A)
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_daycycle()
|
||||
if(lightlevel)
|
||||
night = FALSE //we start with a day if we have light.
|
||||
|
||||
//When you set daycycle ensure that the minimum is larger than [maxx * daycycle_column_delay].
|
||||
//Otherwise the right side of the exoplanet can get stuck in a forever day.
|
||||
daycycle = rand(10 MINUTES, 40 MINUTES)
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/adapt_seed(var/datum/seed/S)
|
||||
S.set_trait(TRAIT_IDEAL_HEAT, atmosphere.temperature + rand(-5,5),800,70)
|
||||
S.set_trait(TRAIT_HEAT_TOLERANCE, S.get_trait(TRAIT_HEAT_TOLERANCE) + rand(-5,5),800,70)
|
||||
S.set_trait(TRAIT_LOWKPA_TOLERANCE, atmosphere.return_pressure() + rand(-5,-50),80,0)
|
||||
S.set_trait(TRAIT_HIGHKPA_TOLERANCE, atmosphere.return_pressure() + rand(5,50),500,110)
|
||||
if(S.exude_gasses)
|
||||
S.exude_gasses -= badgas
|
||||
if(atmosphere)
|
||||
if(S.consume_gasses)
|
||||
S.consume_gasses = list(pick(atmosphere.gas)) // ensure that if the plant consumes a gas, the atmosphere will have it
|
||||
for(var/g in atmosphere.gas)
|
||||
if(gas_data.flags[g] & XGM_GAS_CONTAMINANT)
|
||||
S.set_trait(TRAIT_TOXINS_TOLERANCE, rand(10,15))
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/adapt_animal(var/mob/living/simple_animal/A)
|
||||
if(species[A.type])
|
||||
A.name = species[A.type]
|
||||
A.real_name = species[A.type]
|
||||
else
|
||||
A.name = "alien creature"
|
||||
A.real_name = "alien creature"
|
||||
A.verbs |= /mob/living/simple_animal/proc/name_species
|
||||
if(istype(A, /mob/living/simple_animal/hostile))
|
||||
var/mob/living/simple_animal/hostile/AH = A
|
||||
AH.tolerated_types = mobs_to_tolerate.Copy()
|
||||
if(atmosphere)
|
||||
//Set up gases for living things
|
||||
if(!LAZYLEN(breathgas))
|
||||
var/list/goodgases = gas_data.gases.Copy()
|
||||
var/gasnum = min(rand(1,3), goodgases.len)
|
||||
for(var/i = 1 to gasnum)
|
||||
var/gas = pick(goodgases)
|
||||
breathgas[gas] = round(0.4*goodgases[gas], 0.1)
|
||||
goodgases -= gas
|
||||
if(!badgas)
|
||||
var/list/badgases = gas_data.gases.Copy()
|
||||
badgases -= atmosphere.gas
|
||||
badgas = pick(badgases)
|
||||
|
||||
A.minbodytemp = atmosphere.temperature - 20
|
||||
A.maxbodytemp = atmosphere.temperature + 30
|
||||
A.bodytemperature = (A.maxbodytemp+A.minbodytemp)/2
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/get_random_species_name()
|
||||
return pick("nol","shan","can","fel","xor")+pick("a","e","o","t","ar")+pick("ian","oid","ac","ese","inian","rd")
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/rename_species(var/species_type, var/newname, var/force = FALSE)
|
||||
if(species[species_type] && !force)
|
||||
return FALSE
|
||||
|
||||
species[species_type] = newname
|
||||
log_and_message_admins("renamed [species_type] to [newname]")
|
||||
for(var/mob/living/simple_animal/A in animals)
|
||||
if(istype(A,species_type))
|
||||
A.name = newname
|
||||
A.real_name = newname
|
||||
A.verbs -= /mob/living/simple_animal/proc/name_species
|
||||
return TRUE
|
||||
|
||||
//This tries to generate "num" landing spots on the map.
|
||||
// A landing spot is a 20x20 zone where the shuttle can land where each tile has a area of /area/exoplanet and no ruins on top of it
|
||||
// It makes num*20 attempts to pick a landing spot, during which it attempts to find a area which meets the above criteria.
|
||||
// If it that does not work, it tries to clear the area
|
||||
//There is also a sanity check to ensure that the map isnt too small to handle the landing spot
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_landing(num = 1)
|
||||
var/places = list()
|
||||
var/attempts = 20*num
|
||||
var/new_type = landmark_type
|
||||
|
||||
//sanity-check map size
|
||||
var/lm_min_x = TRANSITIONEDGE+10
|
||||
var/lm_max_x = maxx-TRANSITIONEDGE-10
|
||||
var/lm_min_y = TRANSITIONEDGE+10
|
||||
var/lm_max_y = maxy-TRANSITIONEDGE-10
|
||||
if (lm_max_x < lm_min_x || lm_max_y < lm_min_y)
|
||||
log_and_message_admins("Map Size is too small to Support Away Mission Shuttle Landmark. [lm_min_x] [lm_max_x] [lm_min_y] [lm_max_y]")
|
||||
return
|
||||
|
||||
while(num)
|
||||
attempts--
|
||||
var/turf/T = locate(rand(lm_min_x, lm_max_x), rand(lm_min_y, lm_max_y),map_z[map_z.len])
|
||||
if(!T || (T in places)) // Two landmarks on one turf is forbidden as the landmark code doesn't work with it.
|
||||
continue
|
||||
if(attempts >= 0) // While we have the patience, try to find better spawn points. If out of patience, put them down wherever, so long as there are no repeats.
|
||||
var/valid = 1
|
||||
var/list/block_to_check = block(locate(T.x - 10, T.y - 10, T.z), locate(T.x + 10, T.y + 10, T.z))
|
||||
for(var/turf/check in block_to_check)
|
||||
if(!istype(get_area(check), /area/exoplanet) || check.flags & TURF_NORUINS)
|
||||
valid = 0
|
||||
break
|
||||
if(attempts >= 10)
|
||||
if(check_collision(T.loc, block_to_check)) //While we have lots of patience, ensure landability
|
||||
valid = 0
|
||||
else //Running out of patience, but would rather not clear ruins, so switch to clearing landmarks and bypass landability check
|
||||
new_type = /obj/effect/shuttle_landmark/automatic/clearing
|
||||
|
||||
if(!valid)
|
||||
continue
|
||||
|
||||
num--
|
||||
places += T
|
||||
new new_type(T)
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_atmosphere()
|
||||
atmosphere = new
|
||||
if(habitability_class == HABITABILITY_IDEAL)
|
||||
atmosphere.adjust_gas(GAS_OXYGEN, MOLES_O2STANDARD, 0)
|
||||
atmosphere.adjust_gas(GAS_NITROGEN, MOLES_N2STANDARD)
|
||||
else //let the fuckery commence
|
||||
var/list/newgases = gas_data.gases.Copy()
|
||||
if(prob(90)) //all phoron planet should be rare
|
||||
newgases -= GAS_PHORON
|
||||
if(prob(50)) //alium gas should be slightly less common than mundane shit
|
||||
newgases -= GAS_ALIEN
|
||||
newgases -= GAS_STEAM
|
||||
|
||||
var/total_moles = MOLES_CELLSTANDARD * rand(80,120)/100
|
||||
var/badflag = 0
|
||||
|
||||
//Breathable planet
|
||||
if(habitability_class == HABITABILITY_OKAY)
|
||||
atmosphere.gas[GAS_OXYGEN] += MOLES_O2STANDARD
|
||||
total_moles -= MOLES_O2STANDARD
|
||||
badflag = XGM_GAS_FUEL|XGM_GAS_CONTAMINANT
|
||||
|
||||
var/gasnum = rand(1,4)
|
||||
var/i = 1
|
||||
var/sanity = prob(99.9)
|
||||
while(i <= gasnum && total_moles && newgases.len)
|
||||
if(badflag && sanity)
|
||||
for(var/g in newgases)
|
||||
if(gas_data.flags[g] & badflag)
|
||||
newgases -= g
|
||||
var/ng = pick_n_take(newgases) //pick a gas
|
||||
if(sanity) //make sure atmosphere is not flammable... always
|
||||
if(gas_data.flags[ng] & XGM_GAS_OXIDIZER)
|
||||
badflag |= XGM_GAS_FUEL
|
||||
if(gas_data.flags[ng] & XGM_GAS_FUEL)
|
||||
badflag |= XGM_GAS_OXIDIZER
|
||||
sanity = 0
|
||||
|
||||
var/part = total_moles * rand(3,80)/100 //allocate percentage to it
|
||||
if(i == gasnum || !newgases.len) //if it's last gas, let it have all remaining moles
|
||||
part = total_moles
|
||||
atmosphere.gas[ng] += part
|
||||
total_moles = max(total_moles - part, 0)
|
||||
i++
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/get_scan_data(mob/user)
|
||||
. = ..()
|
||||
var/list/extra_data = list("<hr>")
|
||||
if(atmosphere)
|
||||
var/list/gases = list()
|
||||
for(var/g in atmosphere.gas)
|
||||
if(atmosphere.gas[g] > atmosphere.total_moles * 0.05)
|
||||
gases += gas_data.name[g]
|
||||
extra_data += "Atmosphere composition: [english_list(gases)]"
|
||||
var/inaccuracy = rand(8,12)/10
|
||||
extra_data += "Atmosphere pressure [atmosphere.return_pressure()*inaccuracy] kPa, temperature [atmosphere.temperature*inaccuracy] K"
|
||||
extra_data += "<hr>"
|
||||
|
||||
if(seeds.len)
|
||||
extra_data += "Xenoflora detected"
|
||||
|
||||
if(animals.len)
|
||||
extra_data += "Life traces detected"
|
||||
|
||||
if(LAZYLEN(spawned_features))
|
||||
var/ruin_num = 0
|
||||
for(var/datum/map_template/ruin/exoplanet/R in spawned_features)
|
||||
if(!(R.ruin_tags & RUIN_NATURAL))
|
||||
ruin_num++
|
||||
if(ruin_num)
|
||||
extra_data += "<hr>[ruin_num] possible artificial structure\s detected."
|
||||
|
||||
. += jointext(extra_data, "<br>")
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/get_skybox_representation()
|
||||
return skybox_image
|
||||
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/get_surface_color()
|
||||
return surface_color
|
||||
|
||||
/obj/effect/overmap/visitable/sector/exoplanet/proc/get_atmosphere_color()
|
||||
var/list/colors = list()
|
||||
for(var/g in atmosphere.gas)
|
||||
if(gas_data.tile_overlay_color[g])
|
||||
colors += gas_data.tile_overlay_color[g]
|
||||
if(colors.len)
|
||||
return MixColors(colors)
|
||||
|
||||
/area/exoplanet
|
||||
name = "\improper Planetary surface"
|
||||
ambience = list('sound/effects/wind/wind_2_1.ogg','sound/effects/wind/wind_2_2.ogg','sound/effects/wind/wind_3_1.ogg','sound/effects/wind/wind_4_1.ogg','sound/effects/wind/wind_4_2.ogg','sound/effects/wind/wind_5_1.ogg')
|
||||
always_unpowered = 1
|
||||
@@ -0,0 +1,127 @@
|
||||
/datum/random_map/noise/exoplanet
|
||||
descriptor = "exoplanet"
|
||||
smoothing_iterations = 1
|
||||
|
||||
var/water_level
|
||||
var/water_level_min = 0
|
||||
var/water_level_max = 5
|
||||
var/land_type = /turf/simulated/floor
|
||||
var/water_type
|
||||
|
||||
//intended x*y size, used to adjust spawn probs
|
||||
var/intended_x = 150
|
||||
var/intended_y = 150
|
||||
var/flora_prob = 10
|
||||
var/flora_diversity = 4
|
||||
var/fauna_prob = 2
|
||||
var/megafauna_spawn_prob = 0.5 //chance that a given fauna mob will instead be a megafauna
|
||||
|
||||
var/list/fauna_types = list()
|
||||
var/list/small_flora_types = list()
|
||||
var/list/big_flora_types = list()
|
||||
var/list/plantcolors = list("RANDOM")
|
||||
var/list/grass_cache
|
||||
|
||||
/datum/random_map/noise/exoplanet/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce, var/never_be_priority = 0, var/used_area, var/list/_plant_colors)
|
||||
log_debug("Generating Random Exoplanet Map with tx: [tx], ty: [ty], tz: [tz], tlx: [tlx], tly: [tly]")
|
||||
target_turf_type = world.turf
|
||||
water_level = rand(water_level_min,water_level_max)
|
||||
//automagically adjust probs for bigger maps to help with lag
|
||||
var/size_mod = intended_x / tlx * intended_y / tly
|
||||
flora_prob *= size_mod
|
||||
fauna_prob *= size_mod
|
||||
if(_plant_colors)
|
||||
plantcolors = _plant_colors
|
||||
generate_flora()
|
||||
..()
|
||||
|
||||
current_map.base_turf_by_z[num2text(tz)] = land_type
|
||||
|
||||
/datum/random_map/noise/exoplanet/proc/is_edge_turf(turf/T)
|
||||
return T.x <= TRANSITIONEDGE || T.x >= (limit_x - TRANSITIONEDGE + 1) || T.y <= TRANSITIONEDGE || T.y >= (limit_y - TRANSITIONEDGE + 1)
|
||||
|
||||
/datum/random_map/noise/exoplanet/get_map_char(var/value)
|
||||
if(water_type && noise2value(value) < water_level)
|
||||
return "~"
|
||||
return "[noise2value(value)]"
|
||||
|
||||
/datum/random_map/noise/exoplanet/get_appropriate_path(var/value)
|
||||
if(water_type && noise2value(value) < water_level)
|
||||
return water_type
|
||||
else
|
||||
return land_type
|
||||
|
||||
/datum/random_map/noise/exoplanet/get_additional_spawns(var/value, var/turf/T)
|
||||
if(is_edge_turf(T))
|
||||
return
|
||||
if(T.is_wall())
|
||||
return
|
||||
var/parsed_value = noise2value(value)
|
||||
switch(parsed_value)
|
||||
if(2 to 3)
|
||||
if(prob(fauna_prob))
|
||||
spawn_fauna(T)
|
||||
if(5 to 6)
|
||||
if(flora_prob > 5 && prob(flora_prob * 5))
|
||||
spawn_grass(T)
|
||||
if(prob(flora_prob/3))
|
||||
spawn_flora(T)
|
||||
if(7 to 9)
|
||||
if(flora_prob > 1 && prob(flora_prob * 10))
|
||||
spawn_grass(T)
|
||||
if(prob(flora_prob))
|
||||
spawn_flora(T)
|
||||
|
||||
/datum/random_map/noise/exoplanet/proc/spawn_fauna(var/turf/T)
|
||||
if(LAZYLEN(fauna_types))
|
||||
var/beastie = pick(fauna_types)
|
||||
new beastie(T)
|
||||
|
||||
/datum/random_map/noise/exoplanet/proc/generate_flora()
|
||||
for(var/i = 1 to flora_diversity)
|
||||
var/datum/seed/S = new()
|
||||
S.randomize()
|
||||
var/planticon = "alien[rand(1,4)]"
|
||||
S.set_trait(TRAIT_PRODUCT_ICON,planticon)
|
||||
S.set_trait(TRAIT_PLANT_ICON,planticon)
|
||||
var/color = pick(plantcolors)
|
||||
if(color == "RANDOM")
|
||||
color = get_random_colour(0,75,190)
|
||||
S.set_trait(TRAIT_PLANT_COLOUR,color)
|
||||
var/carnivore_prob = rand(100)
|
||||
if(carnivore_prob < 10)
|
||||
S.set_trait(TRAIT_CARNIVOROUS,2)
|
||||
S.set_trait(TRAIT_SPREAD,1)
|
||||
else if(carnivore_prob < 20)
|
||||
S.set_trait(TRAIT_CARNIVOROUS,1)
|
||||
small_flora_types += S
|
||||
|
||||
/datum/random_map/noise/exoplanet/proc/get_grass_overlay()
|
||||
var/grass_num = "[rand(1,6)]"
|
||||
if(!LAZYACCESS(grass_cache, grass_num))
|
||||
var/color = pick(plantcolors)
|
||||
if(color == "RANDOM")
|
||||
color = get_random_colour(0,75,190)
|
||||
var/image/grass = overlay_image('icons/obj/flora/greygrass.dmi', "grass_[grass_num]", color, RESET_COLOR)
|
||||
grass.underlays += overlay_image('icons/obj/flora/greygrass.dmi', "grass_[grass_num]_shadow", null, RESET_COLOR)
|
||||
LAZYSET(grass_cache, grass_num, grass)
|
||||
return grass_cache[grass_num]
|
||||
|
||||
/datum/random_map/noise/exoplanet/proc/spawn_flora(var/turf/T, var/big)
|
||||
if(big)
|
||||
if(LAZYLEN(big_flora_types))
|
||||
new /obj/machinery/portable_atmospherics/hydroponics/soil/invisible(T, pick(big_flora_types), 1)
|
||||
for(var/turf/neighbor as anything in RANGE_TURFS(1,T))
|
||||
spawn_grass(neighbor)
|
||||
else
|
||||
if(LAZYLEN(small_flora_types))
|
||||
new /obj/machinery/portable_atmospherics/hydroponics/soil/invisible(T, pick(small_flora_types), 1)
|
||||
spawn_grass(T)
|
||||
|
||||
/datum/random_map/noise/exoplanet/proc/spawn_grass(var/turf/T)
|
||||
if(istype(T, water_type))
|
||||
return
|
||||
if(locate(/obj/effect/floor_decal) in T)
|
||||
return
|
||||
var/obj/effect/floor_decal/FD = new /obj/effect/floor_decal(T)
|
||||
FD.appearance = get_grass_overlay()
|
||||
@@ -0,0 +1,36 @@
|
||||
/datum/exoplanet_theme
|
||||
var/name = "Nothing Special"
|
||||
|
||||
/datum/exoplanet_theme/proc/before_map_generation(obj/effect/overmap/visitable/sector/exoplanet/E)
|
||||
|
||||
/datum/exoplanet_theme/proc/get_planet_image_extra()
|
||||
|
||||
/datum/exoplanet_theme/mountains
|
||||
name = "Mountains"
|
||||
var/rock_color
|
||||
|
||||
/datum/exoplanet_theme/mountains/before_map_generation(obj/effect/overmap/visitable/sector/exoplanet/E)
|
||||
rock_color = pick(E.rock_colors)
|
||||
for(var/zlevel in E.map_z)
|
||||
new /datum/random_map/automata/cave_system/mountains(null,TRANSITIONEDGE,TRANSITIONEDGE,zlevel,E.maxx-TRANSITIONEDGE,E.maxy-TRANSITIONEDGE,0,1,1, E.planetary_area, rock_color)
|
||||
|
||||
/datum/random_map/automata/cave_system/mountains
|
||||
iterations = 2
|
||||
descriptor = "space mountains"
|
||||
wall_type = /turf/simulated/mineral
|
||||
cell_threshold = 6
|
||||
var/rock_color
|
||||
|
||||
/datum/random_map/automata/cave_system/mountains/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce, var/never_be_priority = 0, var/used_area, var/_rock_color)
|
||||
if(_rock_color)
|
||||
rock_color = _rock_color
|
||||
target_turf_type = world.turf
|
||||
floor_type = world.turf
|
||||
..()
|
||||
|
||||
/datum/random_map/automata/cave_system/mountains/get_additional_spawns(value, var/turf/simulated/mineral/T)
|
||||
T.color = rock_color
|
||||
if(use_area)
|
||||
if(istype(T))
|
||||
T.mined_turf = use_area.base_turf
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
/turf/simulated/floor/exoplanet
|
||||
name = "space land"
|
||||
icon = 'icons/turf/desert.dmi'
|
||||
icon_state = "desert"
|
||||
has_resources = 1
|
||||
footstep_sound = /decl/sound_category/asteroid_footstep
|
||||
var/diggable = 1
|
||||
var/dirt_color = "#7c5e42"
|
||||
|
||||
/turf/simulated/floor/exoplanet/New()
|
||||
if(current_map.use_overmap)
|
||||
var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
|
||||
if(istype(E))
|
||||
if(E.atmosphere)
|
||||
temperature = E.atmosphere.temperature
|
||||
else
|
||||
temperature = T0C
|
||||
//Must be done here, as light data is not fully carried over by ChangeTurf (but overlays are).
|
||||
set_light(E.lightlevel, 0.1, 2)
|
||||
if(E.planetary_area && istype(loc, world.area))
|
||||
ChangeArea(src, E.planetary_area)
|
||||
..()
|
||||
|
||||
/turf/simulated/floor/exoplanet/attackby(obj/item/C, mob/user)
|
||||
if(diggable && istype(C,/obj/item/shovel))
|
||||
visible_message("<span class='notice'>\The [user] starts digging \the [src]</span>")
|
||||
if(do_after(user, 50))
|
||||
to_chat(user,"<span class='notice'>You dig a deep pit.</span>")
|
||||
new /obj/structure/pit(src)
|
||||
diggable = 0
|
||||
else
|
||||
to_chat(user,"<span class='notice'>You stop shoveling.</span>")
|
||||
else if(istype(C, /obj/item/stack/tile))
|
||||
var/obj/item/stack/tile/T = C
|
||||
if(T.use(1))
|
||||
playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
|
||||
ChangeTurf(/turf/simulated/floor, FALSE, FALSE, TRUE)
|
||||
else
|
||||
..()
|
||||
|
||||
/turf/simulated/floor/exoplanet/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1)
|
||||
ChangeTurf(get_base_turf_by_area(src))
|
||||
if(2)
|
||||
if(prob(40))
|
||||
ChangeTurf(get_base_turf_by_area(src))
|
||||
|
||||
/turf/simulated/floor/exoplanet/Initialize()
|
||||
. = ..()
|
||||
update_icon(1)
|
||||
|
||||
/turf/simulated/floor/exoplanet/update_icon(var/update_neighbors)
|
||||
cut_overlays()
|
||||
if(LAZYLEN(decals))
|
||||
add_overlay(decals)
|
||||
for(var/direction in cardinal)
|
||||
var/turf/turf_to_check = get_step(src,direction)
|
||||
if(!istype(turf_to_check, type))
|
||||
var/image/rock_side = image(icon, "edge[pick(0,1,2)]", dir = turn(direction, 180))
|
||||
switch(direction)
|
||||
if(NORTH)
|
||||
rock_side.pixel_y += world.icon_size
|
||||
if(SOUTH)
|
||||
rock_side.pixel_y -= world.icon_size
|
||||
if(EAST)
|
||||
rock_side.pixel_x += world.icon_size
|
||||
if(WEST)
|
||||
rock_side.pixel_x -= world.icon_size
|
||||
overlays += rock_side
|
||||
else if(update_neighbors)
|
||||
turf_to_check.update_icon()
|
||||
|
||||
//Water
|
||||
/turf/simulated/floor/exoplanet/water/update_icon()
|
||||
return
|
||||
|
||||
/turf/simulated/floor/exoplanet/water/shallow
|
||||
name = "shallow water"
|
||||
icon = 'icons/misc/beach.dmi'
|
||||
icon_state = "seashallow"
|
||||
footstep_sound = /decl/sound_category/water_footstep
|
||||
var/reagent_type = /decl/reagent/water
|
||||
|
||||
/turf/simulated/floor/exoplanet/water/shallow/attackby(obj/item/O, var/mob/living/user)
|
||||
var/obj/item/reagent_containers/RG = O
|
||||
if (reagent_type && istype(RG) && RG.is_open_container() && RG.reagents)
|
||||
RG.reagents.add_reagent(reagent_type, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this))
|
||||
user.visible_message("<span class='notice'>[user] fills \the [RG] from \the [src].</span>","<span class='notice'>You fill \the [RG] from \the [src].</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/turf/simulated/floor/exoplanet/water/update_dirt()
|
||||
return // Water doesn't become dirty
|
||||
|
||||
//Ice
|
||||
/turf/simulated/floor/exoplanet/ice
|
||||
name = "ice"
|
||||
icon = 'icons/turf/snow.dmi'
|
||||
icon_state = "ice"
|
||||
|
||||
/turf/simulated/floor/exoplanet/ice/update_icon()
|
||||
return
|
||||
|
||||
//Snow
|
||||
/turf/simulated/floor/exoplanet/snow
|
||||
name = "snow"
|
||||
icon = 'icons/turf/snow.dmi'
|
||||
icon_state = "snow"
|
||||
dirt_color = "#e3e7e8"
|
||||
footstep_sound = /decl/sound_category/snow_footstep
|
||||
|
||||
/turf/simulated/floor/exoplanet/snow/Initialize()
|
||||
. = ..()
|
||||
icon_state = pick("snow[rand(1,12)]","snow0")
|
||||
|
||||
/turf/simulated/floor/exoplanet/snow/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
melt()
|
||||
|
||||
/turf/simulated/floor/exoplanet/snow/melt()
|
||||
name = "permafrost"
|
||||
icon_state = "permafrost"
|
||||
footstep_sound = /decl/sound_category/asteroid_footstep
|
||||
|
||||
//Grass
|
||||
/turf/simulated/floor/exoplanet/grass
|
||||
name = "grass"
|
||||
icon = 'icons/turf/jungle.dmi'
|
||||
icon_state = "greygrass"
|
||||
color = "#799c4b"
|
||||
footstep_sound = /decl/sound_category/grass_footstep
|
||||
|
||||
/turf/simulated/floor/exoplanet/grass/Initialize()
|
||||
. = ..()
|
||||
if(current_map.use_overmap)
|
||||
var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
|
||||
if(istype(E) && E.grass_color)
|
||||
color = E.grass_color
|
||||
if(!resources)
|
||||
resources = list()
|
||||
if(prob(5))
|
||||
resources[MATERIAL_URANIUM] = rand(1,3)
|
||||
if(prob(2))
|
||||
resources[MATERIAL_DIAMOND] = 1
|
||||
|
||||
//Sand
|
||||
/turf/simulated/floor/exoplanet/desert
|
||||
name = "sand"
|
||||
desc = "It's coarse and gets everywhere."
|
||||
dirt_color = "#ae9e66"
|
||||
footstep_sound = /decl/sound_category/sand_footstep
|
||||
|
||||
/turf/simulated/floor/exoplanet/desert/Initialize()
|
||||
. = ..()
|
||||
icon_state = "desert[rand(0,5)]"
|
||||
|
||||
//Concrete
|
||||
/turf/simulated/floor/exoplanet/concrete
|
||||
name = "concrete"
|
||||
desc = "Stone-like artificial material."
|
||||
icon = 'icons/turf/flooring/misc.dmi'
|
||||
icon_state = "concrete"
|
||||
|
||||
//Special world edge turf
|
||||
|
||||
/turf/simulated/planet_edge
|
||||
name = "world's edge"
|
||||
desc = "Government didn't want you to see this!"
|
||||
density = TRUE
|
||||
blocks_air = TRUE
|
||||
dynamic_lighting = FALSE
|
||||
icon = null
|
||||
icon_state = null
|
||||
|
||||
/turf/simulated/planet_edge/Initialize()
|
||||
. = ..()
|
||||
var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
|
||||
if(!istype(E))
|
||||
return
|
||||
|
||||
var/nx = x
|
||||
if (x <= TRANSITIONEDGE)
|
||||
nx = x + (E.maxx - 2*TRANSITIONEDGE)
|
||||
else if (x >= (E.maxx - TRANSITIONEDGE + 1))
|
||||
nx = x - (E.maxx - 2*TRANSITIONEDGE)
|
||||
|
||||
var/ny = y
|
||||
if(y <= TRANSITIONEDGE)
|
||||
ny = y + (E.maxy - 2*TRANSITIONEDGE)
|
||||
else if (y >= (E.maxy - TRANSITIONEDGE + 1))
|
||||
ny = y - (E.maxy - 2*TRANSITIONEDGE)
|
||||
|
||||
var/turf/NT = locate(nx, ny, z)
|
||||
if(NT)
|
||||
vis_contents = list(NT)
|
||||
|
||||
//Need to put a mouse-opaque overlay there to prevent people turning/shooting towards ACTUAL location of vis_content things
|
||||
var/obj/effect/overlay/O = new(src)
|
||||
O.mouse_opacity = 2
|
||||
O.name = "distant terrain"
|
||||
O.desc = "You need to come over there to take a better look."
|
||||
|
||||
/turf/simulated/planet_edge/CollidedWith(atom/movable/A)
|
||||
. = ..()
|
||||
var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
|
||||
if(!istype(E))
|
||||
return
|
||||
if(E.planetary_area && istype(loc, world.area))
|
||||
ChangeArea(src, E.planetary_area)
|
||||
var/new_x = A.x
|
||||
var/new_y = A.y
|
||||
if(x <= TRANSITIONEDGE)
|
||||
new_x = E.maxx - TRANSITIONEDGE
|
||||
else if (x >= (E.maxx - TRANSITIONEDGE + 1))
|
||||
new_x = TRANSITIONEDGE + 1
|
||||
else if (y <= TRANSITIONEDGE)
|
||||
new_y = E.maxy - TRANSITIONEDGE
|
||||
else if (y >= (E.maxy - TRANSITIONEDGE + 1))
|
||||
new_y = TRANSITIONEDGE + 1
|
||||
|
||||
var/turf/T = locate(new_x, new_y, A.z)
|
||||
if(T && !T.density)
|
||||
A.forceMove(T)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
if(L.pulling)
|
||||
var/atom/movable/AM = L.pulling
|
||||
AM.forceMove(T)
|
||||
@@ -97,13 +97,13 @@
|
||||
controller = new(src)
|
||||
update_nearby_tiles(need_rebuild=1)
|
||||
|
||||
for(var/ship in SSshuttle.ships)
|
||||
var/obj/effect/overmap/visitable/ship/S = ship
|
||||
if(S.check_ownership(src))
|
||||
S.engines |= controller
|
||||
if(dir != S.fore_dir)
|
||||
stat |= BROKEN
|
||||
break
|
||||
if(length(SSshuttle.shuttle_areas) && !length(SSshuttle.shuttles_to_initialize) && SSshuttle.init_state == SS_INITSTATE_DONE)
|
||||
for(var/obj/effect/overmap/visitable/ship/S as anything in SSshuttle.ships)
|
||||
if(S.check_ownership(src))
|
||||
S.engines |= controller
|
||||
if(dir != S.fore_dir)
|
||||
stat |= BROKEN
|
||||
break
|
||||
|
||||
/obj/machinery/atmospherics/unary/engine/Destroy()
|
||||
QDEL_NULL(controller)
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
icon_state = "shuttle"
|
||||
moving_state = "shuttle_moving"
|
||||
|
||||
/obj/effect/overmap/visitable/ship/landable/Destroy()
|
||||
shuttle_moved_event.unregister(SSshuttle.shuttles[shuttle], src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/overmap/visitable/ship/landable/can_burn()
|
||||
if(status != SHIP_STATUS_OVERMAP)
|
||||
return 0
|
||||
@@ -57,6 +61,7 @@
|
||||
/obj/effect/overmap/visitable/ship/landable/populate_sector_objects()
|
||||
..()
|
||||
var/datum/shuttle/shuttle_datum = SSshuttle.shuttles[shuttle]
|
||||
shuttle_moved_event.register(shuttle_datum, src, .proc/on_shuttle_jump)
|
||||
on_landing(landmark, shuttle_datum.current_location) // We "land" at round start to properly place ourselves on the overmap.
|
||||
|
||||
/obj/effect/shuttle_landmark/ship
|
||||
@@ -110,9 +115,11 @@
|
||||
|
||||
/obj/effect/shuttle_landmark/visiting_shuttle/shuttle_arrived(datum/shuttle/shuttle)
|
||||
LAZYSET(core_landmark.visitors, src, shuttle)
|
||||
shuttle_moved_event.register(shuttle, src, .proc/shuttle_left)
|
||||
|
||||
/obj/effect/shuttle_landmark/visiting_shuttle/proc/shuttle_left(datum/shuttle/shuttle, obj/effect/shuttle_landmark/old_landmark, obj/effect/shuttle_landmark/new_landmark)
|
||||
if(old_landmark == src)
|
||||
shuttle_moved_event.unregister(shuttle, src)
|
||||
LAZYREMOVE(core_landmark.visitors, src)
|
||||
|
||||
/obj/effect/overmap/visitable/ship/landable/proc/on_shuttle_jump(datum/shuttle/given_shuttle, obj/effect/shuttle_landmark/from, obj/effect/shuttle_landmark/into)
|
||||
|
||||
Reference in New Issue
Block a user