diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm index 48b1949a86..577fb7cabc 100644 --- a/code/_helpers/global_lists_vr.dm +++ b/code/_helpers/global_lists_vr.dm @@ -828,15 +828,28 @@ var/global/list/xenobio_rainbow_extracts = list( /obj/item/slime_extract/rainbow = 1) -// BLUEPRINT STUFF BELOW HERE +// AREA GENERATION AND BLUEPRINT STUFF BELOW HERE // typecacheof(list) and list() are two completely separate things, don't break! // WHATEVER YOU DO, DO NOT LEAVE THE LAST THING IN THE LIST BELOW HAVE A COMMA OR EVERYTHING EVER WILL BREAK // ENSURE THE LAST AREA OR TURF LISTED IS SIMPLY "/area/clownhideout" AND NOT "/area/clownhideout," OR YOU WILL IMMEDIATELY DIE +// These lists are, obviously, unfinished. + +// ALLOWING BUILDING IN AN AREA: +// If you want someone to be able to build a new area in a place, add the area to the 'BUILDABLE_AREA_TYPES' and 'blacklisted_areas' +// BUILDABLE_AREA_TYPES means they can build an area there. The blacklisted_areas means they CAN NOT EXPAND that area. No making space bigger! + +// DISALLOW BUILDING/AREA MANIPULATION IN AN AREA (OR A TURF TYPE): +// Likewise, if you want someone to never ever EVER be able to do anything area generation/expansion related to an area +// Then add it to SPECIALS and area_or_turf_fail_types + +// If you want someone to var/global/list/BUILDABLE_AREA_TYPES = list( /area/space, /area/mine, +// /area/surface/outside, //SC +// /area/surface/cave, //SC //TETHER STUFF BELOW THIS /area/tether/surfacebase/outside, //GROUNDBASE STUFF BELOW THIS @@ -849,6 +862,8 @@ var/global/list/BUILDABLE_AREA_TYPES = list( var/static/list/blacklisted_areas = typecacheof(list( /area/space, /area/mine, +// /area/surface/outside, //SC +// /area/surface/cave, //SC //TETHER STUFF BELOW THIS /area/tether/surfacebase/outside, //GROUNDBASE STUFF BELOW THIS diff --git a/code/game/objects/items/blueprints_vr.dm b/code/game/objects/items/blueprints_vr.dm index d8ce2021bf..28d577d989 100644 --- a/code/game/objects/items/blueprints_vr.dm +++ b/code/game/objects/items/blueprints_vr.dm @@ -631,7 +631,7 @@ interact() return -/obj/item/areaeditor/proc/move_turfs_to_area(var/list/turf/turfs, var/area/A) +/proc/move_turfs_to_area(var/list/turf/turfs, var/area/A) for(var/T in turfs) ChangeArea(T, A) @@ -742,4 +742,165 @@ usr.client.images.Remove(i) + + + + + + + + + +//GLOBAL VERB FOR PAPER TO ENABLE ANYONE TO MAKE AN AREA IN BUILDABLE AREAS. +//THIS IS 70 TILES. ANYTHING LARGER SHOULD USE ACTUAL BLUEPRINTS. + +/obj/item/weapon/paper + var/created_area = 0 + var/area_cooldown = 0 + +/obj/item/weapon/paper/verb/create_area() + set name = "Create Area" + set category = "Object" + set src in usr + + if(created_area) + to_chat(usr, "This paper has already been used to create an area.") + return + + if(usr.stat || world.time < area_cooldown) + to_chat(usr, "You recently used this paper to try to create an area. Wait one minute before using it again.") + return + + area_cooldown = world.time + 600 //Anti spam. + + create_new_area(usr) + add_fingerprint(usr) + return + +proc/get_new_area_type(area/A) //1 = can build in. 0 = can not build in. + if (!A) + A = get_area(usr) + if(A.outdoors) //ALWAYS able to build outdoors. This means if it's missed in BUILDABLE_AREA_TYPES it's fine. + return 1 + + for (var/type in BUILDABLE_AREA_TYPES) //This works well. + if ( istype(A,type) ) + return 1 + + for (var/type in SPECIALS) + if ( istype(A,type) ) + return 0 + return 0 //If it's not a buildable area, don't let them build in it. + + +/proc/detect_new_area(var/turf/first, var/user) //Heavily simplified version for creating an area yourself. + if(!istype(first)) //Not on a turf. + to_chat(usr, "") + return + if(get_new_area_type(first.loc) == 1) //Are they in an area they can build? I tried to do this BUILDABLE_AREA_TYPES[first.loc.type] but it refused. + var/list/turf/found = new + var/list/turf/pending = list(first) + while(pending.len) + if (found.len+pending.len > 70) + return 1 //TOOLARGE + var/turf/T = pending[1] + pending -= T + for (var/dir in cardinal) + var/turf/NT = get_step(T,dir) + if (!isturf(NT) || (NT in found) || (NT in pending)) + continue + if(!get_new_area_type(NT.loc) == 1) //The contains somewhere that is NOT a buildable area. + return 3 //NOT A BUILDABLE AREA + + if(air_master.air_blocked(T, NT)) //Is the room airtight? + // Okay thats the edge of the room + if(get_new_area_type(NT.loc) == 1 && air_master.air_blocked(NT, NT)) + found += NT // So we include walls/doors not already in any area + continue + if (istype(NT, /turf/space)) + return 2 //SPACE + if (istype(NT, /turf/simulated/shuttle)) + return 2 //SPACE + if (NT.loc != first.loc && !(get_new_area_type(NT.loc) & 1)) + // Edge of a protected area. Lets stop here... + continue + if (!istype(NT, /turf/simulated)) + // Great, unsimulated... eh, just stop searching here + continue + // Okay, NT looks promising, lets continue the search there! + pending += NT + found += T + // end while + return found + else + return 3 + +/proc/create_new_area(mob/creator) //Heavily simplified version of the blueprint version. + var/res = detect_new_area(get_turf(creator), creator) + if(!res) + to_chat(creator, span_warning("Something went wrong.")) + return + + if(!istype(res,/list)) + switch(res) + if(1) + to_chat(creator, "The new area too large! You can only have an area that is up to 70 tiles.") + return + if(2) + to_chat(creator, "The new area must be completely airtight and not be part of a shuttle!") + return + if(3) + to_chat(creator, "There is an area not permitted to be built in somewhere in the room!") + return + else + to_chat(creator, "Error! Please notify administration!") + return + var/list/turf/turfs = res + + var/area/newA //The new area + var/area/oldA = get_area(get_turf(creator)) //The old area (area currently standing in) + var/str //What the new area is named. + + var/list/nearby_turfs_to_check = detect_room(get_turf(creator), area_or_turf_fail_types, 70) //Get the nearby areas. + + if(!nearby_turfs_to_check) + to_chat(creator, span_warning("The new area must have a floor and not a part of a shuttle.")) + return + if(length(turfs) > 70) //Sanity + to_chat(creator, span_warning("The room you're in is too big. It can only be 70 tiles in size, excluding walls.")) + return + + //They can select an area they want to turn their current area into. + str = sanitizeSafe(tgui_input_text(usr, "What would you like to name the area?", "Area Name", null, MAX_NAME_LEN), MAX_NAME_LEN) + if(isnull(str)) //They pressed cancel. + to_chat(creator, "No new area made. Cancelling.") + return + if(!str || !length(str)) //sanity + to_chat(creator, "No new area made. Cancelling.") + return + if(length(str) > MAX_NAME_LEN) + to_chat(creator, "Name too long.") + return + for(var/area/A in world) //Check to make sure we're not making a duplicate name. Sanity. + if(A.name == str) + to_chat(creator, "An area in the world alreay has this name.") + return + newA = new /area + newA.setup(str) + newA.has_gravity = oldA.has_gravity + newA.setup(str) + + for(var/i in 1 to length(turfs)) //Fix lighting. Praise the lord. + var/turf/thing = turfs[i] + newA.contents += thing + thing.change_area(oldA, newA) + + move_turfs_to_area(turfs, newA) + newA.has_gravity = oldA.has_gravity + set_area_machinery(newA, newA.name, oldA.name) + oldA.power_check() //Simply makes the area turn the power off if you nicked an APC from it. + to_chat(creator, span_notice("You have created a new area, named [newA.name]. It is now weather proof, and constructing an APC will allow it to be powered.")) + return + + #undef BP_MAX_ROOM_SIZE diff --git a/code/modules/admin/verbs/buildmode.dm b/code/modules/admin/verbs/buildmode.dm index 28ec8b4999..fc46bd8f16 100644 --- a/code/modules/admin/verbs/buildmode.dm +++ b/code/modules/admin/verbs/buildmode.dm @@ -725,7 +725,6 @@ T.ChangeTurf(floor_type) else new floor_type(T) - log_debug("area_enabled is set to [area_enabled]") if(area_enabled) //Let's try not to make a new area unless you got walls and a floor. create_buildmode_area(area_name, origin) //Generates a new area.