mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-18 19:39:42 +01:00
58570e035a
## About PR Adds some building/planning mechanics typically seen in base-building/survival games such as Grounded. Hopefully this will ease the away base construction process. Happy base buildings! Currently, this allows placing blueprint objects that players can click on with the required materials to build whatever the blueprint represents. You can place templates, edit them or build your own glorious base from ground. Sprites for `blueprints` and `blueprints_unfolded` inside `base_planning_blueprints.dmi` are ported from SS20 Russian Paradise Station. ## Images https://youtu.be/FCrZn8BkISU?si=Fst0ksAgi47D_wN7 ### Asset Licenses The following assets that **have not** been created by myself are included in this PR: | Path | Original Author | License | | --- | --- | --- | | icons/obj/item/base_planning_blueprints.dmi | vovakons (SS20 Russian Paradise Station) | AGPLv3 |
219 lines
7.4 KiB
Plaintext
219 lines
7.4 KiB
Plaintext
/**
|
|
* A basic template loader system, allows placing objects, items, turfs in a specified area.
|
|
* Currently this function doesn't support the following:
|
|
*
|
|
* * Uploading templates in-game.
|
|
* * Even number area dimensions.
|
|
*/
|
|
/datum/room_template
|
|
var/name = "base template"
|
|
|
|
/// Top-down view of the room template, which can be edited like the example below:
|
|
/**
|
|
* Define some vars that contains object-turf paths in New() like this:
|
|
* var/W = /turf/simulated/wall
|
|
* var/F = /turf/simulated/floor/plating
|
|
* var/G = /obj/effect/map_effect/window_spawner/full/reinforced
|
|
* var/A = /obj/machinery/door/airlock
|
|
* var/list/AF = list(A, F)
|
|
*
|
|
* then:
|
|
* layouts = list(
|
|
* list(
|
|
* list(W, G, W, W, W),
|
|
* list(W, F, F, F, W),
|
|
* list(W, W, W, AF, W)
|
|
* ) = "average college student dorm",
|
|
* )
|
|
* This is a layout of a 5x3 (5 width, 3 height) room. Vars can contain whatever path you want and you can fit multiple layouts in here.
|
|
* You can also enter values to the keys in this list, it'll be displayed in template selection UI. Make sure each value is unique.
|
|
* This system also supports placing multiple atoms per turf, needs to be defined inside a list on the turf represented in layout, see the example above.
|
|
* Keep the area dimension as odd numbers, reason explained below.
|
|
*/
|
|
var/list/layouts
|
|
|
|
/// Lists for keeping record of template related placements, incase the user wants to revert it.
|
|
var/list/placed_template_objects = list()
|
|
var/list/replaced_turfs = list()
|
|
var/list/deleted_blueprints = list()
|
|
|
|
/datum/room_template/proc/template_selection(turf/center)
|
|
var/list/options = list()
|
|
var/list/chosen_layout = list()
|
|
|
|
for(var/key in layouts)
|
|
options += layouts[key]
|
|
|
|
var/choice = tgui_input_list(usr, "Choose a template to place.", "Template Selection", options)
|
|
|
|
if(!choice)
|
|
return
|
|
|
|
for(var/key in layouts)
|
|
if(layouts[key] == choice) // this is the reason every value needs to be unique
|
|
chosen_layout = key
|
|
break
|
|
|
|
if(chosen_layout)
|
|
build_the_template(center, chosen_layout)
|
|
|
|
/datum/room_template/proc/build_the_template(turf/center, list/chosen_layout)
|
|
var/height = length(chosen_layout)
|
|
var/width = length(chosen_layout[1])
|
|
var/starting_x = center.x - round(width / 2) // this system assumes it's always at the center, hence even numbers aren't supported
|
|
var/starting_y = center.y + round(height / 2)
|
|
var/starting_z = center.z
|
|
|
|
if(width % 2 == 0 || height % 2 == 0)
|
|
CRASH("Room template [name] has a layout with even dimensions as width or height. Only odd numbers are supported.")
|
|
|
|
for(var/row in 1 to height)
|
|
for(var/column in 1 to width)
|
|
// The math and reasoning behind this is, due to how we arrange reading the layout list
|
|
// (consider the top-down view, and now visualise the list getting flattened), we start placing the template from top-left corner to bottom right.
|
|
// We simply pick a turf that is specified by width*height area, and see where this exact turf corrresponds to in the layout given to us.
|
|
var/turf/T = locate(starting_x + column - 1, starting_y - row + 1, starting_z) // we're locating while assuming we're in the center
|
|
if(!T || T.density)
|
|
continue
|
|
|
|
var/tile_data = chosen_layout[row][column]
|
|
if(!tile_data)
|
|
continue
|
|
|
|
for(var/obj/structure/blueprint/colliding_blueprint in T)
|
|
deleted_blueprints += list(list("turf" = T, "type" = colliding_blueprint.type))
|
|
qdel(colliding_blueprint)
|
|
|
|
if(islist(tile_data))
|
|
for(var/i in tile_data)
|
|
place_tile_data(T, i)
|
|
else
|
|
place_tile_data(T, tile_data)
|
|
|
|
// Finalizing template placement
|
|
if(usr?.client)
|
|
if(tgui_alert(usr, "Would you like to keep the placed template?", "Template Confirmation", list("Confirm", "Cancel")) != "Confirm")
|
|
QDEL_LAZYLIST(placed_template_objects) // revert placed objects
|
|
|
|
for(var/turf/T in replaced_turfs) // restore turfs
|
|
T.ChangeTurf(replaced_turfs[T])
|
|
|
|
for(var/tile in deleted_blueprints) // restore blueprints
|
|
var/blueprint_to_restore = tile["type"]
|
|
new blueprint_to_restore(tile["turf"])
|
|
|
|
to_chat(usr, SPAN_NOTICE("Template has been reverted."))
|
|
|
|
replaced_turfs = null
|
|
deleted_blueprints = null
|
|
|
|
/datum/room_template/proc/place_tile_data(turf/T, tile_data)
|
|
if(ispath(tile_data, /turf)) // Turf
|
|
replaced_turfs[T] = T.type
|
|
T.ChangeTurf(tile_data)
|
|
return
|
|
|
|
placed_template_objects += new tile_data(T) // Object or anything else
|
|
|
|
// ---- Subtypes
|
|
|
|
// Base Planner Templates
|
|
/datum/room_template/base_planner_template
|
|
name = "Base Planner Template"
|
|
|
|
/datum/room_template/base_planner_template/New()
|
|
var/G = /obj/structure/blueprint/girder
|
|
var/W = /obj/structure/blueprint/window_frame
|
|
var/A = /obj/structure/blueprint/airlock_frame
|
|
var/F = /obj/structure/blueprint/turf_plating
|
|
var/list/X = list(A, F)
|
|
var/N
|
|
|
|
layouts = list(
|
|
list(
|
|
list(G, G ,G, G, G),
|
|
list(G, F, F, F, G),
|
|
list(G, F, F, F, G),
|
|
list(G, F, F, F, G),
|
|
list(G, G, G, G, G),
|
|
) = "5x5 Room",
|
|
|
|
list(
|
|
list(G, G ,G, G, G, G, G),
|
|
list(G, F, F, F, F, F, G),
|
|
list(G, F, F, F, F, F, G),
|
|
list(G, F, F, F, F, F, G),
|
|
list(G, F, F, F, F, F, G),
|
|
list(G, F, F, F, F, F, G),
|
|
list(G, G, G, G, G, G, G),
|
|
) = "7x7 Room",
|
|
|
|
list(
|
|
list(N, G, G, X, W, X, G, G, N),
|
|
list(G, G, F, F, F, F, F, G, G),
|
|
list(G, F, F, F, F, F, F, F, G),
|
|
list(W, F, F, F, F, F, F, F, W),
|
|
list(W, F, F, F, F, F, F, F, W),
|
|
list(W, F, F, F, F, F, F, F, W),
|
|
list(G, F, F, F, F, F, F, F, G),
|
|
list(G, G, F, F, F, F, F, G, G),
|
|
list(N, G, G, X, W, X, G, G, N)
|
|
) = "9x9 Room with Windows and Airlocks",
|
|
|
|
list(
|
|
list(N, G ,G, G, X, W, X, G, G, G, N),
|
|
list(G, G ,F, F, F, F, F, F, F, G, G),
|
|
list(G, F ,F, F, F, F, F, F, F, F, G),
|
|
list(W, F ,F, F, F, F, F, F, F, F, W),
|
|
list(W, F ,F, F, F, F, F, F, F, F, W),
|
|
list(X, F ,F, F, F, F, F, F, F, F, X),
|
|
list(W, F ,F, F, F, F, F, F, F, F, W),
|
|
list(W, F ,F, F, F, F, F, F, F, F, W),
|
|
list(G, F ,F, F, F, F, F, F, F, F, G),
|
|
list(G, G ,F, F, F, F, F, F, F, G, G),
|
|
list(N, G ,G, G, X, W, X, G, G, G, N),
|
|
) = "11x11 Room with Windows and Airlocks",
|
|
|
|
list(
|
|
list(N, G ,W, A, A, G, G, G, G, G, N),
|
|
list(G, G ,F, F, F, G, F, F, F, G, G),
|
|
list(G, F ,F, F, F, G, F, F, F, F, W),
|
|
list(G, F ,F, F, F, X, F, F, F, F, X),
|
|
list(W, F ,F, F, F, W, F, F, F, F, G),
|
|
list(W, F ,F, F, F, G, G, F, F, F, G),
|
|
list(W, F ,F, F, F, F, G, G, W, G, G),
|
|
list(G, F ,F, F, F, F, W, F, F, F, G),
|
|
list(G, F ,F, F, F, F, X, F, F, F, G),
|
|
list(G, G ,F, F, F, F, G, F, F, G, G),
|
|
list(N, G ,W, X, X, G, G, G, G, G, N),
|
|
) = "11x11 Base Template - A",
|
|
|
|
list(
|
|
list(N, G ,G, G, X, W, X, G, G, G, N),
|
|
list(G, G ,F, G, F, F, F, G, F, G, G),
|
|
list(W, F ,F, W, F, F, F, W, F, F, W),
|
|
list(G, F ,F, X, F, F, F, X, F, F, G),
|
|
list(G, F ,F, G, F, F, F, G, F, F, G),
|
|
list(G, G ,G, G, F, F, F, G, G, G, G),
|
|
list(G, F ,F, G, F, F, F, G, F, F, G),
|
|
list(G, F ,F, X, F, F, F, X, F, F, G),
|
|
list(W, F ,F, W, F, F, F, W, F, F, W),
|
|
list(G, G ,F, G, F, F, F, G, F, G, G),
|
|
list(N, G ,G, G, X, W, X, G, G, G, N),
|
|
) = "11x11 Base Template - B",
|
|
|
|
list(
|
|
list(N, G ,X, X, W, G, G, W, W, G, N),
|
|
list(G, G ,F, F, F, F, F, F, F, G, G),
|
|
list(G, F ,F, F, F, F, F, F, F, F, G),
|
|
list(W, F ,F, F, F, F, F, F, F, F, G),
|
|
list(G, F ,F, F, F, F, G, W, X, G, G),
|
|
list(G, G ,X, X, G, G, G, F, F, F, G),
|
|
list(G, F ,F, F, F, G, F, F, F, F, G),
|
|
list(W, F ,F, F, F, X, F, F, F, F, X),
|
|
list(G, F ,F, F, F, X, F, F, F, F, X),
|
|
list(G, G ,F, F, F, G, F, F, F, G, G),
|
|
list(N, G ,G, G, G, G, G, X, X, G, N),
|
|
) = "11x11 Base Template - C"
|
|
)
|