Away mission refactoring (#9850)

* Away mission refactor

* add to config example

* Better interface

* Attempt to make map loading less laggy. Change category of new verb

* Let admins jump to created away missions

* Fix issues noticed by PJB

* Check admin rights

* Let gateways connect to multiple away missions. Fix gateway connections

* switch order of ..() and gateways.Remove(src)

* change var name
This commit is contained in:
unid15
2016-05-14 08:45:56 +02:00
committed by clusterfack
parent e962363660
commit 5bf7f08ee1
16 changed files with 349 additions and 90 deletions

View File

@@ -171,6 +171,8 @@
var/skip_vault_generation = 0 //If 1, don't generate vaults
var/shut_up_automatic_diagnostic_and_announcement_system = 0 //If 1, don't play the vox sounds at the start of every shift.
var/enable_roundstart_away_missions = 0
/datum/configuration/New()
. = ..()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
@@ -534,6 +536,8 @@
skip_vault_generation = 1
if("shut_up_automatic_diagnostic_and_announcement_system")
shut_up_automatic_diagnostic_and_announcement_system = 1
if("enable_roundstart_away_missions")
enable_roundstart_away_missions = 1
else
diary << "Unknown setting in configuration: '[name]'"

View File

@@ -76,7 +76,9 @@ datum/controller/game_controller/proc/setup()
socket_talk = new /datum/socket_talk()
socket_talk.send_raw("type=startup")
createRandomZlevel()
if(config.enable_roundstart_away_missions)
log_startup_progress("Attempting to generate an away mission...")
createRandomZlevel()
/*
if(!air_master)
air_master = new /datum/controller/air_system()

View File

@@ -16,6 +16,12 @@
opacity = 0
canSmoothWith = null
/turf/unsimulated/wall/rock
name = "unnaturally hard rock wall"
icon = 'icons/turf/walls.dmi'
icon_state = "rock"
canSmoothWith = null
/turf/unsimulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob)
user.delayNextAttack(8)
if (!user.dexterity_check())

View File

@@ -252,9 +252,6 @@ var/datum/nanomanager/nanomanager = new()
#define shuttle_time_in_station 1800 // 3 minutes in the station
#define shuttle_time_to_arrive 6000 // 10 minutes to arrive
//away missions
var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to
// MySQL configuration
var/sqladdress = "localhost"

View File

@@ -45,6 +45,7 @@ var/list/admin_verbs_admin = list(
/client/proc/jumptomob, /*allows us to jump to a specific mob*/
/client/proc/jumptoturf, /*allows us to jump to a specific turf*/
/client/proc/jumptovault, /*allows us to jump to a specific vault*/
/client/proc/jumptoaway, /*allows us to jump to a specific away mission*/
/client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/
/client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcomm*/
/client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/
@@ -126,7 +127,8 @@ var/list/admin_verbs_spawn = list(
/client/proc/spawn_datum, //Allows us to spawn datums to the marked datum buffer
/client/proc/cmd_admin_dress, //Allows us to spawn clothing and dress a mob with it in one click
/client/proc/respawn_character, //Allows us to re-spawn someone
/client/proc/debug_reagents //Allows us to spawn reagents in mobs/containers
/client/proc/debug_reagents, //Allows us to spawn reagents in mobs/containers
/client/proc/create_awaymission, //Allows us to summon away missions
)
var/list/admin_verbs_server = list(
/client/proc/Set_Holiday,
@@ -181,6 +183,7 @@ var/list/admin_verbs_debug = list(
/client/proc/test_snap_UI,
/client/proc/configFood,
/client/proc/debug_reagents,
/client/proc/create_awaymission,
/client/proc/make_invulnerable,
/client/proc/cmd_admin_dump_delprofile,
/client/proc/mob_list,
@@ -1100,3 +1103,48 @@ var/list/admin_verbs_mod = list(
log_admin("[key_name(src)] sent a fax to all machines.: [sent]")
message_admins("[key_name_admin(src)] sent a fax to all machines.", 1)
/client/proc/create_awaymission()
set category = "Admin"
set name = "Create Away Mission"
set desc = "Creates an away mission and links it to the station's gateway."
//Check admin rights
if(!check_rights(R_SPAWN))
return
var/list/L = getRandomZlevels(1)
var/list/choices = list()
if(!L.len)
to_chat(src, "No away missions found.")
return
to_chat(src, "<span class='danger'>WARNING: Loading large away missions may temporarily hang up the server. Usually the lag will last for less than a minute.</span><hr>")
for(var/datum/away_mission/AM in L)
if(AM.name)
choices[AM.name] = AM
else
choices[AM.file_path] = AM
to_chat(src, "<b>[(AM.name ? AM.name : AM.file_path)]</b> - <span class='info'>[(AM.desc ? AM.desc : "No description")]</span>")
var/choice = input(src, "Select an away mission to load. See chat for descriptions!", "AWAY MISSIONS") as null|anything in choices
if(!choice) return
log_admin("[key_name(src)] is loading an away mission: [choice]")
message_admins("[key_name_admin(src)] is loading an away mission: [choice]", 1)
var/datum/away_mission/AM = choices[choice]
var/override = 0
if(existing_away_missions.len)
var/continue_loading = alert(src, "There is already an away mission loaded. Do you want to load [AM.name] anyway? If there are more than two away mission gateways, the station gateway will be able to teleport its users to both of them.", "AWAY MISSIONS", "Yes", "No")
if(!continue_loading) return
if(continue_loading == "Yes")
override = 1
to_chat(src, "Attempting to load [AM.name] ([AM.file_path])...")
createRandomZlevel(override, AM, usr)
to_chat(src, "The away mission has been generated on z-level [world.maxz] [AM.location ? "([formatJumpTo(AM.location)])" : ""]")

View File

@@ -137,6 +137,33 @@
else
alert("Admin jumping disabled")
/client/proc/jumptoaway()
set category = "Admin"
set name = "Jump to Away Mission"
if(!check_rights())
return
if(!config.allow_admin_jump)
alert("Admin jumping disabled")
return
var/list/awaymissions = list()
for(var/datum/away_mission/AM in existing_away_missions)
awaymissions["[AM.name] ([AM.file_path][AM.location ? ", Z:[AM.location.z]" : ""])"] = AM
var/selection = input("Select a vault to teleport to.", "Admin Jumping", null, null) as null|anything in sortList(awaymissions)
if(!selection)
return
var/datum/away_mission/AM = awaymissions[selection]
if(!AM.location)
to_chat(src, "[AM.name] doesn't have a location! Panic")
return
usr.forceMove(AM.location)
feedback_add_details("admin_verb","JV")
/client/proc/Getmob(var/mob/M in mob_list)
set category = "Admin"
set name = "Get Mob"

View File

@@ -0,0 +1,205 @@
//#define DISABLE_AWAYMISSIONS_ON_ROUNDSTART
var/list/datum/away_mission/existing_away_missions = list()
var/list/awaydestinations = list() //List of landmarks
/obj/effect/landmark/awaystart
name = "awaystart"
/*
There are two ways to add an away mission to the game
A) Add the map file's location to maps/RandomZLevels/fileList.txt
B) Create a subtype of /datum/away_mission and set its file_path to the map file's location (see below)
First method sucks
Second method lets you use the initialize() proc to interact with the away mission after it has loaded (for example generate map elements, create shuttles, etc).
It also lets you write a description for the away mission, as well as many other things
Example of the second method:
/datum/away_mission/my_shit
file_path = "maps/RandomZLevels/fresh_dump.dmm"
desc = "This stinks"
****READ THIS****
Because a z-level is 500x500 in size, loading an away mission creates 250,000 new turfs - in addition to any additonal mobs and objects.
If your away mission is smaller than 500x500, its northern and eastern borders will be surrounded with space turfs. Unless you're fine with this, you
should secure these borders with an indestructible wall (insert a trump meme here) so that nobody can get out
*/
/datum/away_mission
var/name = "" //Name of the mission
var/file_path = "" //Path of the file. Example: "maps/RandomZLevels/test.dmm"
var/desc //Short description. It will be visible to admins when they attempt to create an away mission
var/generate_randomly = 1 //If 0, don't generate this away mission randomly
var/datum/zLevel/zLevel
var/turf/location
/datum/away_mission/proc/pre_load() //Called before loading the map
return
/datum/away_mission/proc/initialize(list/objects) //objects: list of all atoms in the away mission. This proc is called after the away mission is loaded
var/z = world.maxz //z coordinate
for(var/turf/T in block(locate(1,1,z), locate(world.maxx, world.maxy, z)))
turfs.Add(T)
if(accessable_z_levels.len >= z)
zLevel = accessable_z_levels[z]
for(var/obj/effect/landmark/L in objects) //Add all landmarks to away destinations. Also set the away mission's location for admins to jump to
if(L.name != "awaystart") continue
awaydestinations.Add(L)
if(!location)
location = get_turf(L)
for(var/obj/machinery/gateway/G in objects)
G.initialize()
if(objects.len && !location)
location = get_turf(pick(objects))
/datum/away_mission/empty_space
name = "empty space"
file_path = "maps/RandomZLevels/space.dmm" //1x1 space tile. It changes its size according to the map's dimensions
generate_randomly = 0
/datum/away_mission/empty_space/New()
..()
desc = "[world.maxx]x[world.maxy] tiles of pure space. No structures, no humans, absolutely nothing. Not even a gateway - you'll have to spawn one yourself."
/datum/away_mission/arcticwaste
name = "arctic waste"
file_path = "maps/RandomZLevels/arcticwaste.dmm"
desc = "A frozen wasteland with an underground bunker. Features a gateway."
/datum/away_mission/assistantchamber
name = "assistant chamber"
file_path = "maps/RandomZLevels/assistantChamber.dmm"
desc = "A tiny unbreachable room full of angry turrets and loot."
generate_randomly = 0
/datum/away_mission/challenge
name = "emitter hell"
file_path = "maps/RandomZLevels/unused/challenge.dmm"
desc = "A long hallway featuring emitters, turrets and syndicate agents. Features loot and a gateway."
/datum/away_mission/spaceship
name = "stranded spaceship"
file_path = "maps/RandomZLevels/unused/blackmarketpackers.dmm"
desc = "A mysteriously empty shuttle crashed into the asteroid."
/datum/away_mission/academy
name = "academy"
file_path = "maps/RandomZLevels/unused/Academy.dmm"
/datum/away_mission/beach
name = "beach"
file_path = "maps/RandomZLevels/unused/beach.dmm"
desc = "A small, comfy seaside area with a bar."
generate_randomly = 0
/datum/away_mission/listeningpost
name = "listening post"
file_path = "maps/RandomZLevels/unused/listeningpost.dmm"
desc = "A large asteroid with a hidden syndicate listening post. Don't forget to bring pickaxes!"
/datum/away_mission/stationcollision
name = "station collision"
file_path = "maps/RandomZLevels/unused/stationCollision.dmm"
desc = "A shuttlecraft crashed into a small space station, bringing aboard aliens and cultists. Features the Lord Nar-Sie himself."
/datum/away_mission/wildwest
name = "wild west"
file_path = "maps/RandomZLevels/unused/wildwest.dmm"
desc = "An exciting adventure for the toughest adventures your station can offer. Those who defeat all of the final area's guardians will find a wish granter."
var/static/list/away_mission_subtypes = typesof(/datum/away_mission) - /datum/away_mission
//Returns a list containing /datum/away_mission objects.
/proc/getRandomZlevels(include_unrandom = 0)
var/list/potentialRandomZlevels = away_mission_subtypes.Copy()
for(var/T in potentialRandomZlevels) //Fill the list with away mission datums (because currently it only contains paths)
potentialRandomZlevels.Add(new T)
potentialRandomZlevels.Remove(T)
var/list/Lines = file2list("maps/RandomZLevels/fileList.txt")
if(!Lines.len) return
for (var/t in Lines)
if (!t)
continue
t = trim(t)
if (length(t) == 0)
continue
else if (copytext(t, 1, 2) == "#")
continue
var/pos = findtext(t, " ")
var/name = null
// var/value = null
if (pos)
// No, don't do lowertext here, that breaks paths on linux
name = copytext(t, 1, pos)
// value = copytext(t, pos + 1)
else
// No, don't do lowertext here, that breaks paths on linux
name = t
if (!name)
continue
if(!isfile(name))
warning("fileList.txt contains a map that does not exist: [name]")
continue
var/datum/away_mission/AM = new /datum/away_mission
AM.file_path = name
potentialRandomZlevels.Add(AM)
if(!include_unrandom)
for(var/datum/away_mission/AM in potentialRandomZlevels)
if(!AM.generate_randomly) potentialRandomZlevels.Remove(AM)
return potentialRandomZlevels
/proc/createRandomZlevel(override = 0, var/datum/away_mission/AM, var/messages = null)
if(!messages) messages = world
if(existing_away_missions.len && !override) //crude, but it saves another var!
return
if(!AM) //If we were provided an away mission datum, don't generate the list of away missions
to_chat(messages, "<span class='danger'>Searching for away missions...</span>")
var/list/potentialRandomZlevels = getRandomZlevels()
if(!potentialRandomZlevels.len)
return
AM = pick(potentialRandomZlevels)
to_chat(messages, "<span class='danger'>[potentialRandomZlevels.len] away missions found. Loading...</span>")
else
to_chat(messages, "<span class='danger'>Loading an away mission...</span>")
log_game("Loading away mission [AM.file_path]")
var/file = file(AM.file_path)
if(isfile(file))
AM.pre_load()
var/list/L = maploader.load_map(file)
to_chat(messages, "<span class='danger'>Initializing away mission...</span>")
AM.initialize(L)
to_chat(messages, "<span class='danger'>Away mission loaded.</span>")
existing_away_missions.Add(AM)
return
to_chat(messages, "<span class='danger'>Failed to load away mission [AM.file_path] (file doesn't exist).</span>")

View File

@@ -1,3 +1,5 @@
var/list/gateways = list() //List containing the gateways on away missions
/obj/machinery/gateway
name = "gateway"
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
@@ -7,7 +9,6 @@
anchored = 1
var/active = 0
/obj/machinery/gateway/initialize()
update_icon()
if(dir == 2)
@@ -83,7 +84,7 @@ obj/machinery/gateway/centerstation/process()
if(!ready) return
if(linked.len != 8) return
if(!powered()) return
if(!awaygate)
if(!gateways.len)
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
return
if(world.time < wait)
@@ -119,18 +120,25 @@ obj/machinery/gateway/centerstation/process()
/obj/machinery/gateway/centerstation/Bumped(atom/movable/M as mob|obj)
if(!ready) return
if(!active) return
if(!awaygate) return
if(awaygate.calibrated)
M.loc = get_step(awaygate.loc, SOUTH)
if(!gateways.len) return
var/obj/machinery/gateway/centeraway/dest = pick(gateways) //Pick a random gateway from an away mission
if(dest.calibrated) //If it's calibrated, move to it
M.forceMove(get_step(dest.loc, SOUTH))
M.dir = SOUTH
return
else
var/obj/effect/landmark/dest = pick(awaydestinations)
if(dest)
M.loc = dest.loc
M.dir = SOUTH
use_power(5000)
return
else //Otherwise teleport to a landmark on the same z-level
var/list/good_landmarks = list()
for(var/obj/effect/landmark/L in awaydestinations)
if(L.z == dest.z)
good_landmarks.Add(L)
if(!good_landmarks.len) return
var/obj/effect/landmark/L_dest = pick(good_landmarks)
M.forceMove(get_turf(L_dest))
M.dir = SOUTH
use_power(5000)
/obj/machinery/gateway/centerstation/attackby(obj/item/device/W as obj, mob/user as mob)
@@ -150,6 +158,15 @@ obj/machinery/gateway/centerstation/process()
var/ready = 0
var/obj/machinery/gateway/centeraway/stationgate = null
/obj/machinery/gateway/centeraway/New()
..()
gateways.Add(src)
/obj/machinery/gateway/centeraway/Destroy()
gateways.Remove(src)
..()
/obj/machinery/gateway/centeraway/initialize()
update_icon()
@@ -223,7 +240,7 @@ obj/machinery/gateway/centerstation/process()
if(E.imp_in == M)//Checking that it's actually implanted vs just in their pocket
to_chat(M, "\black The station gate has detected your exile implant and is blocking your entry.")
return
M.loc = get_step(stationgate.loc, SOUTH)
M.forceMove(get_step(stationgate.loc, SOUTH))
M.dir = SOUTH

View File

@@ -230,7 +230,8 @@ var/global/dmm_suite/preloader/_preloader = null
if(ispath(path, /turf)) //Turfs use ChangeTurf
var/turf/oldTurf = locate(x,y,z)
instance = oldTurf.ChangeTurf(path, allow = 1)
if(path != oldTurf.type)
instance = oldTurf.ChangeTurf(path, allow = 1)
else
instance = new path (locate(x,y,z))//first preloader pass

View File

@@ -1,71 +1,3 @@
/datum/zLevel/away
name = "awaymission"
movementJammed = 1 //no drifting here
/proc/createRandomZlevel(override = 0)
if(awaydestinations.len && !override) //crude, but it saves another var!
return
var/list/potentialRandomZlevels = list()
to_chat(world, "<span class='danger'>Searching for away missions...</span>")
var/list/Lines = file2list("maps/RandomZLevels/fileList.txt")
if(!Lines.len) return
for (var/t in Lines)
if (!t)
continue
t = trim(t)
if (length(t) == 0)
continue
else if (copytext(t, 1, 2) == "#")
continue
var/pos = findtext(t, " ")
var/name = null
// var/value = null
if (pos)
// No, don't do lowertext here, that breaks paths on linux
name = copytext(t, 1, pos)
// value = copytext(t, pos + 1)
else
// No, don't do lowertext here, that breaks paths on linux
name = t
if (!name)
continue
if(!isfile(name))
warning("fileList.txt contains a map that does not exist: [name]")
continue
potentialRandomZlevels.Add(name)
while(1)
if(potentialRandomZlevels.len)
to_chat(world, "<span class='danger'>Loading away mission...</span>")
var/map = pick(potentialRandomZlevels)
log_game("Loading away mission [map]")
var/file = file(map)
if(isfile(file))
maploader.load_map(file)
for(var/x = 1 to world.maxx)
for(var/y = 1 to world.maxy)
turfs += locate(x,y,world.maxz)
for(var/obj/effect/landmark/L in landmarks_list)
if (L.name != "awaystart")
continue
awaydestinations.Add(L)
to_chat(world, "<span class='danger'>Away mission loaded.</span>")
return
to_chat(world, "<span class='danger'>Failed to load away mission. Trying again...</span>")
// Remove map from list
potentialRandomZlevels -= map
else
to_chat(world, "<span class='danger'>No away missions found.</span>")
return

View File

@@ -5,7 +5,7 @@ var/list/existing_vaults = list()
var/list/map_blacklist = list() //Don't spawn on these maps
var/map_directory = "maps/randomVaults/"
var/map_name = "" //Don't include the preffix or "maps/randomVaults/". If the vault is maps/randomVaults/hell.dmm, this should be "hell"
var/map_name = "" //Don't include the suffix or "maps/randomVaults/". If the vault is maps/randomVaults/hell.dmm, this should be "hell"
var/only_spawn_once = 1 //If 0, this vault can spawn multiple times on a single map

View File

@@ -285,3 +285,7 @@ SKIP_MINIMAP_GENERATION
## Uncomment to disable the lovely robotic voice that tells you the time at the start of every shift.
## Recommended for your sanity if you start the server a lot for testing things.
#SHUT_UP_AUTOMATIC_DIAGNOSTIC_AND_ANNOUNCEMENT_SYSTEM
##ENABLE_ROUNDSTART_AWAY_MISSIONS
## Uncomment to genereate an away mission at the beginning of each round
#ENABLE_ROUNDSTART_AWAY_MISSIONS

View File

@@ -0,0 +1,7 @@
author: Unid
delete-after: True
changes:
- tweak: Refactored away missions.
- rscadd: Admins can now spawn away missions during the round using a new button in the Admin tab.

View File

@@ -0,0 +1,5 @@
"a" = (/turf/space,/area)
(1,1,1) = {"
a
"}

View File

@@ -109,6 +109,8 @@
if(!level.movementJammed)
accessable_z_levels += list("[z_to_use]" = level.movementChance)
level.z = z_to_use
var/global/list/accessable_z_levels = list()
//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there.
@@ -125,6 +127,7 @@ var/global/list/accessable_z_levels = list()
var/movementJammed = 0 //Prevents you from accessing the zlevel by drifting
var/movementChance = ZLEVEL_BASE_CHANCE
var/base_turf //Our base turf, what shows under the station when destroyed. Defaults to space because it's fukken Space Station 13
var/z //Number of the z-level (the z coordinate)
////////////////////////////////

View File

@@ -965,6 +965,7 @@
#include "code\modules\atmos_automation\implementation\sensors.dm"
#include "code\modules\atmos_automation\implementation\supermatter.dm"
#include "code\modules\atmos_automation\implementation\vent_pump.dm"
#include "code\modules\awaymissions\_awaymission.dm"
#include "code\modules\awaymissions\bluespaceartillery.dm"
#include "code\modules\awaymissions\corpse.dm"
#include "code\modules\awaymissions\gateway.dm"