Merge branch 'master' into Viro-Update-1

This commit is contained in:
Guti
2024-11-29 22:56:42 +01:00
491 changed files with 4757 additions and 5851 deletions
+6
View File
@@ -80,3 +80,9 @@
**Creator:** VerySoft (https://github.com/TS-Rogue-Star/Rogue-Star/pull/435)<br>
**URL:** [Website](https://rogue-star.net/)<br>
**License:** Permission granting in writing for use by Virgo and Chomp with proper attribution
<br>
**File:** `icons/mob/turkey.dmi`
**Title:** Turkey<br>
**Creator:** VerySoft (https://github.com/TS-Rogue-Star/Rogue-Star/pull/669)<br>
**URL:** [Website](https://rogue-star.net/)<br>
**License:** Permission granted in writing for use by Virgo and Chomp with proper attribution
@@ -206,10 +206,10 @@
return data
/obj/machinery/atmospherics/binary/algae_farm/tgui_act(action, params)
/obj/machinery/atmospherics/binary/algae_farm/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
add_fingerprint(usr)
add_fingerprint(ui.user)
switch(action)
if("toggle")
@@ -203,7 +203,7 @@
/obj/machinery/atmospherics/binary/passive_gate/attack_hand(user as mob)
if(..())
return
add_fingerprint(usr)
add_fingerprint(user)
if(!allowed(user))
to_chat(user, span_warning("Access denied."))
return
@@ -235,7 +235,7 @@
return data
/obj/machinery/atmospherics/binary/passive_gate/tgui_act(action, params)
/obj/machinery/atmospherics/binary/passive_gate/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -258,7 +258,7 @@
if("max")
target_pressure = max_pressure_setting
if("set")
var/new_pressure = tgui_input_number(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure,max_pressure_setting,0)
var/new_pressure = tgui_input_number(ui.user,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure,max_pressure_setting,0)
src.target_pressure = between(0, new_pressure, max_pressure_setting)
if("set_flow_rate")
@@ -269,11 +269,11 @@
if("max")
set_flow_rate = air1.volume
if("set")
var/new_flow_rate = tgui_input_number(usr,"Enter new flow rate limit (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate,air1.volume,0)
var/new_flow_rate = tgui_input_number(ui.user,"Enter new flow rate limit (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate,air1.volume,0)
src.set_flow_rate = between(0, new_flow_rate, air1.volume)
update_icon()
add_fingerprint(usr)
add_fingerprint(ui.user)
/obj/machinery/atmospherics/binary/passive_gate/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
@@ -201,13 +201,13 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/binary/pump/attack_hand(mob/user)
if(..())
return
add_fingerprint(usr)
add_fingerprint(user)
if(!allowed(user))
to_chat(user, span_warning("Access denied."))
return
tgui_interact(user)
/obj/machinery/atmospherics/binary/pump/tgui_act(action, params)
/obj/machinery/atmospherics/binary/pump/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -223,11 +223,11 @@ Thus, the two variables affect pump operation are set in New():
if("max")
target_pressure = max_pressure_setting
if("set")
var/new_pressure = tgui_input_number(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure,max_pressure_setting,0)
var/new_pressure = tgui_input_number(ui.user,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure,max_pressure_setting,0)
src.target_pressure = between(0, new_pressure, max_pressure_setting)
. = TRUE
add_fingerprint(usr)
add_fingerprint(ui.user)
update_icon()
/obj/machinery/atmospherics/binary/pump/power_change()
@@ -152,7 +152,7 @@
else
return null
/obj/machinery/atmospherics/omni/atmos_filter/tgui_act(action, params)
/obj/machinery/atmospherics/omni/atmos_filter/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -171,7 +171,7 @@
if("set_flow_rate")
if(!configuring || use_power)
return
var/new_flow_rate = tgui_input_number(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate,max_flow_rate,0)
var/new_flow_rate = tgui_input_number(ui.user,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate,max_flow_rate,0)
set_flow_rate = between(0, new_flow_rate, max_flow_rate)
. = TRUE
if("switch_mode")
@@ -182,7 +182,7 @@
if("switch_filter")
if(!configuring || use_power)
return
var/new_filter = tgui_input_list(usr, "Select filter mode:", "Change filter", list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Phoron", "Nitrous Oxide"))
var/new_filter = tgui_input_list(ui.user, "Select filter mode:", "Change filter", list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Phoron", "Nitrous Oxide"))
if(!new_filter)
return
switch_filter(dir_flag(params["dir"]), mode_return_switch(new_filter))
@@ -164,7 +164,7 @@
return data
/obj/machinery/atmospherics/omni/mixer/tgui_act(action, params)
/obj/machinery/atmospherics/omni/mixer/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -184,7 +184,7 @@
. = TRUE
if(!configuring || use_power)
return
var/new_flow_rate = tgui_input_number(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate,max_flow_rate,0)
var/new_flow_rate = tgui_input_number(ui.user,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate,max_flow_rate,0)
set_flow_rate = between(0, new_flow_rate, max_flow_rate)
if("switch_mode")
. = TRUE
@@ -195,7 +195,7 @@
. = TRUE
if(!configuring || use_power)
return
change_concentration(dir_flag(params["dir"]))
change_concentration(dir_flag(params["dir"]), ui.user)
if("switch_conlock")
. = TRUE
if(!configuring || use_power)
@@ -244,7 +244,7 @@
update_ports()
rebuild_mixing_inputs()
/obj/machinery/atmospherics/omni/mixer/proc/change_concentration(var/port = NORTH)
/obj/machinery/atmospherics/omni/mixer/proc/change_concentration(var/port = NORTH, mob/user)
tag_north_con = null
tag_south_con = null
tag_east_con = null
@@ -266,7 +266,7 @@
if(non_locked < 1)
return
var/new_con = (tgui_input_number(usr,"Enter a new concentration (0-[round(remain_con * 100, 0.5)])%","Concentration control", min(remain_con, old_con)*100, round(remain_con * 100, 0.5), 0)) / 100
var/new_con = (tgui_input_number(user,"Enter a new concentration (0-[round(remain_con * 100, 0.5)])%","Concentration control", min(remain_con, old_con)*100, round(remain_con * 100, 0.5), 0)) / 100
//cap it between 0 and the max remaining concentration
new_con = between(0, new_con, remain_con)
@@ -101,7 +101,7 @@
if(..())
return
src.add_fingerprint(usr)
src.add_fingerprint(user)
tgui_interact(user)
return
+1 -1
View File
@@ -32,7 +32,7 @@ GLOBAL_LIST_EMPTY(shutoff_valves)
return src.attack_hand(user)
/obj/machinery/atmospherics/valve/shutoff/attack_hand(var/mob/user)
src.add_fingerprint(usr)
src.add_fingerprint(user)
update_icon(1)
close_on_leaks = !close_on_leaks
to_chat(user, "You [close_on_leaks ? "enable" : "disable"] the automatic shutoff circuit.")
@@ -182,7 +182,7 @@
return data
/obj/machinery/atmospherics/trinary/atmos_filter/tgui_act(action, params)
/obj/machinery/atmospherics/trinary/atmos_filter/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -216,7 +216,7 @@
if(4)//removing N2O
filtered_out += "nitrous_oxide"
add_fingerprint(usr)
add_fingerprint(ui.user)
update_icon()
//
@@ -100,11 +100,11 @@
if(..())
return
tgui_interact(user)
// src.add_fingerprint(usr)
// src.add_fingerprint(user)
// if(!src.allowed(user))
// to_chat(user, span_warning("Access denied."))
// return
// usr.set_machine(src)
// user.set_machine(src)
// var/list/node_connects = get_node_connect_dirs()
// var/dat = {span_bold("Power: ") + "<a href='?src=\ref[src];power=1'>[use_power?"On":"Off"]</a><br>
// <b>Set Flow Rate Limit: </b>
+1 -1
View File
@@ -161,7 +161,7 @@
return
/obj/machinery/atmospherics/tvalve/attack_hand(mob/user as mob)
src.add_fingerprint(usr)
src.add_fingerprint(user)
update_icon(1)
sleep(10)
if (src.state)
@@ -84,7 +84,7 @@
return data
/obj/machinery/atmospherics/unary/freezer/tgui_act(action, params)
/obj/machinery/atmospherics/unary/freezer/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -103,7 +103,7 @@
var/new_setting = between(0, text2num(params["value"]), 100)
set_power_level(new_setting)
add_fingerprint(usr)
add_fingerprint(ui.user)
/obj/machinery/atmospherics/unary/freezer/process()
..()
@@ -36,11 +36,11 @@
if(!partner)
return 0
if(!air_master || air_master.current_cycle <= update_cycle)
if(!SSair || SSair.current_cycle <= update_cycle)
return 0
update_cycle = air_master.current_cycle
partner.update_cycle = air_master.current_cycle
update_cycle = SSair.current_cycle
partner.update_cycle = SSair.current_cycle
var/air_heat_capacity = air_contents.heat_capacity()
var/other_air_heat_capacity = partner.air_contents.heat_capacity()
@@ -104,7 +104,7 @@
return data
/obj/machinery/atmospherics/unary/heater/tgui_act(action, params)
/obj/machinery/atmospherics/unary/heater/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -123,7 +123,7 @@
var/new_setting = between(0, text2num(params["value"]), 100)
set_power_level(new_setting)
add_fingerprint(usr)
add_fingerprint(ui.user)
//upgrading parts
/obj/machinery/atmospherics/unary/heater/RefreshParts()
+1 -1
View File
@@ -131,7 +131,7 @@
return
/obj/machinery/atmospherics/valve/attack_hand(mob/user as mob)
src.add_fingerprint(usr)
src.add_fingerprint(user)
update_icon(1)
sleep(10)
if (src.open)
+2 -2
View File
@@ -36,11 +36,11 @@
//Convenience function for atoms to update turfs they occupy
/atom/movable/proc/update_nearby_tiles(need_rebuild)
if(!air_master)
if(!SSair)
return 0
for(var/turf/simulated/turf in locs)
air_master.mark_for_update(turf)
SSair.mark_for_update(turf)
return 1
+8 -8
View File
@@ -5,7 +5,7 @@
/*
Overview:
Connections are made between turfs by air_master.connect(). They represent a single point where two zones converge.
Connections are made between turfs by SSair.connect(). They represent a single point where two zones converge.
Class Vars:
A - Always a simulated turf.
@@ -60,19 +60,19 @@ Class Procs:
/connection/New(turf/simulated/A, turf/simulated/B)
#ifdef ZASDBG
ASSERT(air_master.has_valid_zone(A))
//ASSERT(air_master.has_valid_zone(B))
ASSERT(HAS_VALID_ZONE(A))
//ASSERT(HAS_VALID_ZONE(B))
#endif
src.A = A
src.B = B
zoneA = A.zone
if(!istype(B))
mark_space()
edge = air_master.get_edge(A.zone,B)
edge = SSair.get_edge(A.zone,B)
edge.add_connection(src)
else
zoneB = B.zone
edge = air_master.get_edge(A.zone,B.zone)
edge = SSair.get_edge(A.zone,B.zone)
edge.add_connection(src)
/connection/proc/mark_direct()
@@ -108,7 +108,7 @@ Class Procs:
erase()
return
var/block_status = air_master.air_blocked(A,B)
var/block_status = SSair.air_blocked(A,B)
if(block_status & AIR_BLOCKED)
//to_world("Blocked connection.")
erase()
@@ -133,7 +133,7 @@ Class Procs:
return
else
edge.remove_connection(src)
edge = air_master.get_edge(A.zone, B)
edge = SSair.get_edge(A.zone, B)
edge.add_connection(src)
zoneA = A.zone
@@ -155,7 +155,7 @@ Class Procs:
//to_world("Zones changed, \...")
if(A.zone && B.zone)
edge.remove_connection(src)
edge = air_master.get_edge(A.zone, B.zone)
edge = SSair.get_edge(A.zone, B.zone)
edge.add_connection(src)
zoneA = A.zone
zoneB = B.zone
+10 -10
View File
@@ -2,7 +2,7 @@
Overview:
These are what handle gas transfers between zones and into space.
They are found in a zone's edges list and in air_master.edges.
They are found in a zone's edges list and in SSair.edges.
Each edge updates every air tick due to their role in gas transfer.
They come in two flavors, /connection_edge/zone and /connection_edge/unsimulated.
As the type names might suggest, they handle inter-zone and spacelike connections respectively.
@@ -82,7 +82,7 @@ Class Procs:
/connection_edge/proc/contains_zone(zone/Z)
/connection_edge/proc/erase()
air_master.remove_edge(src)
SSair.remove_edge(src)
//to_world("[type] Erased.")
/connection_edge/proc/tick()
@@ -169,19 +169,19 @@ Class Procs:
if(equiv)
if(direct)
erase()
air_master.merge(A, B)
SSair.merge(A, B)
return
else
A.air.equalize(B.air)
air_master.mark_edge_sleeping(src)
SSair.mark_edge_sleeping(src)
air_master.mark_zone_update(A)
air_master.mark_zone_update(B)
SSair.mark_zone_update(A)
SSair.mark_zone_update(B)
/connection_edge/zone/recheck()
// Edges with only one side being vacuum need processing no matter how close.
if(!A.air.compare(B.air, vacuum_exception = 1))
air_master.mark_edge_active(src)
SSair.mark_edge_active(src)
//Helper proc to get connections for a zone.
/connection_edge/zone/proc/get_connected_zone(zone/from)
@@ -233,16 +233,16 @@ Class Procs:
if(equiv)
A.air.copy_from(air)
air_master.mark_edge_sleeping(src)
SSair.mark_edge_sleeping(src)
air_master.mark_zone_update(A)
SSair.mark_zone_update(A)
/connection_edge/unsimulated/recheck()
// Edges with only one side being vacuum need processing no matter how close.
// Note: This handles the glaring flaw of a room holding pressure while exposed to space, but
// does not specially handle the less common case of a simulated room exposed to an unsimulated pressurized turf.
if(!A.air.compare(air, vacuum_exception = 1))
air_master.mark_edge_active(src)
SSair.mark_edge_active(src)
/proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
//This implements a simplistic version of the Stefan-Boltzmann law.
+1 -1
View File
@@ -16,7 +16,7 @@ Class Procs:
Preferable to accessing the connection directly because it checks validity.
place(connection/c, d)
Called by air_master.connect(). Sets the connection in the specified direction to c.
Called by SSair.connect(). Sets the connection in the specified direction to c.
update_all()
Called after turf/update_air_properties(). Updates the validity of all connections on this turf.
-231
View File
@@ -1,231 +0,0 @@
var/datum/controller/subsystem/air/air_master
var/tick_multiplier = 2
/*
Overview:
The air controller does everything. There are tons of procs in here.
Class Vars:
zones - All zones currently holding one or more turfs.
edges - All processing edges.
tiles_to_update - Tiles scheduled to update next tick.
zones_to_update - Zones which have had their air changed and need air archival.
active_hotspots - All processing fire objects.
active_zones - The number of zones which were archived last tick. Used in debug verbs.
next_id - The next UID to be applied to a zone. Mostly useful for debugging purposes as zones do not need UIDs to function.
Class Procs:
mark_for_update(turf/T)
Adds the turf to the update list. When updated, update_air_properties() will be called.
When stuff changes that might affect airflow, call this. It's basically the only thing you need.
add_zone(zone/Z) and remove_zone(zone/Z)
Adds zones to the zones list. Does not mark them for update.
air_blocked(turf/A, turf/B)
Returns a bitflag consisting of:
AIR_BLOCKED - The connection between turfs is physically blocked. No air can pass.
ZONE_BLOCKED - There is a door between the turfs, so zones cannot cross. Air may or may not be permeable.
has_valid_zone(turf/T)
Checks the presence and validity of T's zone.
May be called on unsimulated turfs, returning 0.
merge(zone/A, zone/B)
Called when zones have a direct connection and equivalent pressure and temperature.
Merges the zones to create a single zone.
connect(turf/simulated/A, turf/B)
Called by turf/update_air_properties(). The first argument must be simulated.
Creates a connection between A and B.
mark_zone_update(zone/Z)
Adds zone to the update list. Unlike mark_for_update(), this one is called automatically whenever
air is returned from a simulated turf.
equivalent_pressure(zone/A, zone/B)
Currently identical to A.air.compare(B.air). Returns 1 when directly connected zones are ready to be merged.
get_edge(zone/A, zone/B)
get_edge(zone/A, turf/B)
Gets a valid connection_edge between A and B, creating a new one if necessary.
has_same_air(turf/A, turf/B)
Used to determine if an unsimulated edge represents a specific turf.
Simulated edges use connection_edge/contains_zone() for the same purpose.
Returns 1 if A has identical gases and temperature to B.
remove_edge(connection_edge/edge)
Called when an edge is erased. Removes it from processing.
*/
//
// The rest of the air subsystem is defined in air.dm
//
/datum/controller/subsystem/air
//Geometry lists
var/list/zones = list()
var/list/edges = list()
//Geometry updates lists
var/list/tiles_to_update = list()
var/list/zones_to_update = list()
var/list/active_fire_zones = list()
var/list/active_hotspots = list()
var/list/active_edges = list()
var/active_zones = 0
var/current_cycle = 0
var/next_id = 1 //Used to keep track of zone UIDs.
/datum/controller/subsystem/air/proc/add_zone(zone/z)
zones.Add(z)
z.name = "Zone [next_id++]"
mark_zone_update(z)
/datum/controller/subsystem/air/proc/remove_zone(zone/z)
zones.Remove(z)
zones_to_update.Remove(z)
/datum/controller/subsystem/air/proc/air_blocked(turf/A, turf/B)
#ifdef ZASDBG
ASSERT(isturf(A))
ASSERT(isturf(B))
#endif
var/ablock = A.c_airblock(B)
if(ablock == BLOCKED) return BLOCKED
return ablock | B.c_airblock(A)
/datum/controller/subsystem/air/proc/has_valid_zone(turf/simulated/T)
#ifdef ZASDBG
ASSERT(istype(T))
#endif
return istype(T) && T.zone && !T.zone.invalid
/datum/controller/subsystem/air/proc/merge(zone/A, zone/B)
#ifdef ZASDBG
ASSERT(istype(A))
ASSERT(istype(B))
ASSERT(!A.invalid)
ASSERT(!B.invalid)
ASSERT(A != B)
#endif
if(A.contents.len < B.contents.len)
A.c_merge(B)
mark_zone_update(B)
else
B.c_merge(A)
mark_zone_update(A)
/datum/controller/subsystem/air/proc/connect(turf/simulated/A, turf/simulated/B)
#ifdef ZASDBG
ASSERT(istype(A))
ASSERT(isturf(B))
ASSERT(A.zone)
ASSERT(!A.zone.invalid)
//ASSERT(B.zone)
ASSERT(A != B)
#endif
var/block = air_master.air_blocked(A,B)
if(block & AIR_BLOCKED) return
var/direct = !(block & ZONE_BLOCKED)
var/space = !istype(B)
if(!space)
if(min(A.zone.contents.len, B.zone.contents.len) < ZONE_MIN_SIZE || (direct && (equivalent_pressure(A.zone,B.zone) || current_cycle == 0)))
merge(A.zone,B.zone)
return
var/a_to_b = get_dir(A,B)
var/b_to_a = get_dir(B,A)
if(!A.connections) A.connections = new
if(!B.connections) B.connections = new
if(A.connections.get(a_to_b)) return
if(B.connections.get(b_to_a)) return
if(!space)
if(A.zone == B.zone) return
var/connection/c = new /connection(A,B)
A.connections.place(c, a_to_b)
B.connections.place(c, b_to_a)
if(direct) c.mark_direct()
/datum/controller/subsystem/air/proc/mark_for_update(turf/T)
#ifdef ZASDBG
ASSERT(isturf(T))
#endif
if(T.needs_air_update) return
tiles_to_update |= T
#ifdef ZASDBG
T.add_overlay(mark)
#endif
T.needs_air_update = 1
/datum/controller/subsystem/air/proc/mark_zone_update(zone/Z)
#ifdef ZASDBG
ASSERT(istype(Z))
#endif
if(Z.needs_update) return
zones_to_update.Add(Z)
Z.needs_update = 1
/datum/controller/subsystem/air/proc/mark_edge_sleeping(connection_edge/E)
#ifdef ZASDBG
ASSERT(istype(E))
#endif
if(E.sleeping) return
active_edges.Remove(E)
E.sleeping = 1
/datum/controller/subsystem/air/proc/mark_edge_active(connection_edge/E)
#ifdef ZASDBG
ASSERT(istype(E))
#endif
if(!E.sleeping) return
active_edges.Add(E)
E.sleeping = 0
/datum/controller/subsystem/air/proc/equivalent_pressure(zone/A, zone/B)
return A.air.compare(B.air)
/datum/controller/subsystem/air/proc/get_edge(zone/A, zone/B)
if(istype(B))
for(var/connection_edge/zone/edge in A.edges)
if(edge.contains_zone(B)) return edge
var/connection_edge/edge = new/connection_edge/zone(A,B)
edges.Add(edge)
edge.recheck()
return edge
else
for(var/connection_edge/unsimulated/edge in A.edges)
if(has_same_air(edge.B,B)) return edge
var/connection_edge/edge = new/connection_edge/unsimulated(A,B)
edges.Add(edge)
edge.recheck()
return edge
/datum/controller/subsystem/air/proc/has_same_air(turf/A, turf/B)
if(A.oxygen != B.oxygen) return 0
if(A.nitrogen != B.nitrogen) return 0
if(A.phoron != B.phoron) return 0
if(A.carbon_dioxide != B.carbon_dioxide) return 0
if(A.temperature != B.temperature) return 0
return 1
/datum/controller/subsystem/air/proc/remove_edge(connection_edge/E)
edges.Remove(E)
if(!E.sleeping) active_edges.Remove(E)
+2 -2
View File
@@ -8,12 +8,12 @@
/*
if(!check_rights(R_DEBUG)) return
var/result = air_master.Tick()
var/result = SSair.Tick()
if(result)
to_chat(src, "Successfully Processed.")
else
to_chat(src, "Failed to process! ([air_master.tick_progress])")
to_chat(src, "Failed to process! ([SSair.tick_progress])")
*/
/client/proc/Zone_Info(turf/T as null|turf)
+4 -4
View File
@@ -58,7 +58,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
fuel_objs.Cut()
if(!fire_tiles.len)
air_master.active_fire_zones.Remove(src)
SSair.active_fire_zones.Remove(src)
/zone/proc/remove_liquidfuel(var/used_liquid_fuel, var/remove_fire=0)
if(!fuel_objs.len)
@@ -94,7 +94,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
return 1
fire = new(src, fl)
air_master.active_fire_zones |= zone
SSair.active_fire_zones |= zone
var/obj/effect/decal/cleanable/liquid_fuel/fuel = locate() in src
zone.fire_tiles |= src
@@ -191,7 +191,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
set_light(3, 1, color)
firelevel = fl
air_master.active_hotspots.Add(src)
SSair.active_hotspots.Add(src)
/obj/fire/proc/fire_color(var/env_temperature)
var/temperature = max(4000*sqrt(firelevel/vsc.fire_firelevel_multiplier), env_temperature)
@@ -209,7 +209,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
T.fire = null
loc = null
air_master.active_hotspots.Remove(src)
SSair.active_hotspots.Remove(src)
/turf/simulated/var/fire_protection = 0 //Protects newly extinguished tiles from being overrun again.
+7 -8
View File
@@ -41,9 +41,8 @@
if(istype(unsim, /turf/simulated))
var/turf/simulated/sim = unsim
if(air_master.has_valid_zone(sim))
air_master.connect(sim, src)
if(HAS_VALID_ZONE(sim))
SSair.connect(sim, src)
/*
Simple heuristic for determining if removing the turf from it's zone will not partition the zone (A very bad thing).
@@ -162,7 +161,7 @@
var/turf/simulated/sim = unsim
sim.open_directions |= reverse_dir[d]
if(air_master.has_valid_zone(sim))
if(HAS_VALID_ZONE(sim))
//Might have assigned a zone, since this happens for each direction.
if(!zone)
@@ -195,7 +194,7 @@
if(verbose) to_world("Connecting to [sim.zone]")
#endif
air_master.connect(src, sim)
SSair.connect(src, sim)
#ifdef ZASDBG
@@ -210,7 +209,7 @@
if(!postponed) postponed = list()
postponed.Add(unsim)
if(!air_master.has_valid_zone(src)) //Still no zone, make a new one.
if(!HAS_VALID_ZONE(src)) //Still no zone, make a new one.
var/zone/newzone = new/zone()
newzone.add(src)
@@ -223,7 +222,7 @@
//At this point, a zone should have happened. If it hasn't, don't add more checks, fix the bug.
for(var/turf/T in postponed)
air_master.connect(src, T)
SSair.connect(src, T)
/turf/proc/post_update_air_properties()
if(connections) connections.update_all()
@@ -279,7 +278,7 @@
/turf/simulated/return_air()
if(zone)
if(!zone.invalid)
air_master.mark_zone_update(zone)
SSair.mark_zone_update(zone)
return zone.air
else
if(!air)
+9 -9
View File
@@ -56,7 +56,7 @@ Class Procs:
/zone/var/list/graphic_remove = list()
/zone/New()
air_master.add_zone(src)
SSair.add_zone(src)
air.temperature = TCMB
air.group_multiplier = 1
air.volume = CELL_VOLUME
@@ -65,7 +65,7 @@ Class Procs:
#ifdef ZASDBG
ASSERT(!invalid)
ASSERT(istype(T))
ASSERT(!air_master.has_valid_zone(T))
ASSERT(!HAS_VALID_ZONE(T))
#endif
var/datum/gas_mixture/turf_air = T.return_air()
@@ -75,7 +75,7 @@ Class Procs:
if(T.fire)
var/obj/effect/decal/cleanable/liquid_fuel/fuel = locate() in T
fire_tiles.Add(T)
air_master.active_fire_zones |= src
SSair.active_fire_zones |= src
if(fuel) fuel_objs += fuel
if(air.graphic)
T.update_graphic(air.graphic)
@@ -122,11 +122,11 @@ Class Procs:
if(E.contains_zone(into))
continue //don't need to rebuild this edge
for(var/turf/T in E.connecting_turfs)
air_master.mark_for_update(T)
SSair.mark_for_update(T)
/zone/proc/c_invalidate()
invalid = 1
air_master.remove_zone(src)
SSair.remove_zone(src)
#ifdef ZASDBG
for(var/turf/simulated/T in contents)
T.dbg(invalid_zone)
@@ -141,7 +141,7 @@ Class Procs:
T.update_graphic(graphic_remove = air_graphic) //we need to remove the overlays so they're not doubled when the zone is rebuilt
//T.dbg(invalid_zone)
T.needs_air_update = 0 //Reset the marker so that it will be added to the list.
air_master.mark_for_update(T)
SSair.mark_for_update(T)
/zone/proc/add_tile_air(datum/gas_mixture/tile_air)
//air.volume += CELL_VOLUME
@@ -152,7 +152,7 @@ Class Procs:
air.group_multiplier = contents.len+1
/zone/proc/tick()
if(air.temperature >= PHORON_FLASHPOINT && !(src in air_master.active_fire_zones) && air.check_combustability() && contents.len)
if(air.temperature >= PHORON_FLASHPOINT && !(src in SSair.active_fire_zones) && air.check_combustability() && contents.len)
var/turf/T = pick(contents)
if(istype(T))
T.create_fire(vsc.fire_firelevel_multiplier)
@@ -171,7 +171,7 @@ Class Procs:
to_chat(M,name)
for(var/g in air.gas)
to_chat(M, "[gas_data.name[g]]: [air.gas[g]]")
to_chat(M, "P: [air.return_pressure()] kPa V: [air.volume]L T: [air.temperature]°K ([air.temperature - T0C]°C)")
to_chat(M, "P: [air.return_pressure()] kPa V: [air.volume]L T: [air.temperature]K ([air.temperature - T0C]C)")
to_chat(M, "O2 per N2: [(air.gas["nitrogen"] ? air.gas["oxygen"]/air.gas["nitrogen"] : "N/A")] Moles: [air.total_moles]")
to_chat(M, "Simulated: [contents.len] ([air.group_multiplier])")
//to_chat(M, "Unsimulated: [unsimulated_contents.len]")
@@ -192,4 +192,4 @@ Class Procs:
to_chat(M, "Space Edges: [space_edges] ([space_coefficient] connections)")
//for(var/turf/T in unsimulated_contents)
// to_chat(M, "[T] at ([T.x],[T.y])")
// to_chat(M, "[T] at ([T.x],[T.y])")
+1 -1
View File
@@ -15,7 +15,7 @@ Every air tick:
Important Functions:
air_master.mark_for_update(turf)
SSair.mark_for_update(turf)
When stuff happens, call this. It works on everything. You basically don't need to worry about any other
functions besides CanPass().
+30 -4
View File
@@ -18,6 +18,15 @@
#define MC_AVG_FAST_UP_SLOW_DOWN(average, current) (average > current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
#define MC_AVG_SLOW_UP_FAST_DOWN(average, current) (average < current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
///creates a running average of "things elapsed" per time period when you need to count via a smaller time period.
///eg you want an average number of things happening per second but you measure the event every tick (50 milliseconds).
///make sure both time intervals are in the same units. doesn't work if current_duration > total_duration or if total_duration == 0
#define MC_AVG_OVER_TIME(average, current, total_duration, current_duration) ((((total_duration) - (current_duration)) / (total_duration)) * (average) + (current))
#define MC_AVG_MINUTES(average, current, current_duration) (MC_AVG_OVER_TIME(average, current, 1 MINUTES, current_duration))
#define MC_AVG_SECONDS(average, current, current_duration) (MC_AVG_OVER_TIME(average, current, 1 SECONDS, current_duration))
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
#define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum}
@@ -70,18 +79,35 @@
#define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\
/datum/controller/subsystem/##X/New(){\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
}\
/datum/controller/subsystem/##X
#define TIMER_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/timer/##X);\
/datum/controller/subsystem/timer/##X/New(){\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
}\
/datum/controller/subsystem/timer/##X/fire() {..() /*just so it shows up on the profiler*/} \
/datum/controller/subsystem/timer/##X
#define PROCESSING_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/processing/##X);\
/datum/controller/subsystem/processing/##X/New(){\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
}\
/datum/controller/subsystem/processing/##X/fire() {..() /*just so it shows up on the profiler*/} \
/datum/controller/subsystem/processing/##X
#define VERB_MANAGER_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/verb_manager/##X);\
/datum/controller/subsystem/verb_manager/##X/New(){\
NEW_SS_GLOBAL(SS##X);\
PreInit();\
}\
/datum/controller/subsystem/verb_manager/##X/fire() {..() /*just so it shows up on the profiler*/} \
/datum/controller/subsystem/verb_manager/##X
// Boilerplate code for multi-step processors. See machines.dm for example use.
#define INTERNAL_PROCESS_STEP(this_step, initial_step, proc_to_call, cost_var, next_step)\
if(current_step == this_step || (initial_step && !resumed)) /* So we start at step 1 if not resumed.*/ {\
+2
View File
@@ -11,3 +11,5 @@
#define ATMOS_PASS_NO 2 // Never blocks air or zones.
#define ATMOS_PASS_DENSITY 3 // Blocks air and zones if density = TRUE, allows both if density = FALSE
#define ATMOS_PASS_PROC 4 // Call CanZASPass() using c_airblock
#define HAS_VALID_ZONE(T) (T.zone && !T.zone.invalid)
+6 -2
View File
@@ -1,4 +1,8 @@
#define GLOBAL_PROC "some_magic_bullshit"
#define GLOBAL_PROC "some_magic_bullshit"
/// A shorthand for the callback datum, [documented here](datum/callback.html)
#define CALLBACK new /datum/callback
#define INVOKE_ASYNC world.ImmediateInvokeAsync
/// like CALLBACK but specifically for verb callbacks
#define VERB_CALLBACK new /datum/callback/verb_callback
+1
View File
@@ -105,6 +105,7 @@
#define FACTION_SWARMER "swarmer"
#define FACTION_TEPPI "teppi"
#define FACTION_TUNNELCLOWN "tunnelclown"
#define FACTION_TURKEY "turkey"
#define FACTION_WILD_ANIMAL "wild animal"
#define FACTION_WOLFGIRL "wolfgirl"
#define FACTION_WOLFTAUR "wolftaur"
+2
View File
@@ -189,6 +189,8 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_CHAT 400
#define FIRE_PRIORITY_OVERLAYS 500
#define FIRE_PRIORITY_TIMER 700
#define FIRE_PRIORITY_SPEECH_CONTROLLER 900
#define FIRE_PRIORITY_DELAYED_VERBS 950
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
/**
+36
View File
@@ -0,0 +1,36 @@
/**
* verb queuing thresholds. remember that since verbs execute after SendMaps the player wont see the effects of the verbs on the game world
* until SendMaps executes next tick, and then when that later update reaches them. thus most player input has a minimum latency of world.tick_lag + player ping.
* however thats only for the visual effect of player input, when a verb processes the actual latency of game state changes or semantic latency is effectively 1/2 player ping,
* unless that verb is queued for the next tick in which case its some number probably smaller than world.tick_lag.
* so some verbs that represent player input are important enough that we only introduce semantic latency if we absolutely need to.
* its for this reason why player clicks are handled in SSinput before even movement - semantic latency could cause someone to move out of range
* when the verb finally processes but it was in range if the verb had processed immediately and overtimed.
*/
///queuing tick_usage threshold for verbs that are high enough priority that they only queue if the server is overtiming.
///ONLY use for critical verbs
#define VERB_OVERTIME_QUEUE_THRESHOLD 100
///queuing tick_usage threshold for verbs that need lower latency more than most verbs.
#define VERB_HIGH_PRIORITY_QUEUE_THRESHOLD 95
///default queuing tick_usage threshold for most verbs which can allow a small amount of latency to be processed in the next tick
#define VERB_DEFAULT_QUEUE_THRESHOLD 85
///attempt to queue this verb process if the server is overloaded. evaluates to FALSE if queuing isnt necessary or if it failed.
///_verification_args... are only necessary if the verb_manager subsystem youre using checks them in can_queue_verb()
///if you put anything in _verification_args that ISNT explicitely put in the can_queue_verb() override of the subsystem youre using,
///it will runtime.
#define TRY_QUEUE_VERB(_verb_callback, _tick_check, _subsystem_to_use, _verification_args...) (_queue_verb(_verb_callback, _tick_check, _subsystem_to_use, _verification_args))
///queue wrapper for TRY_QUEUE_VERB() when you want to call the proc if the server isnt overloaded enough to queue
#define QUEUE_OR_CALL_VERB(_verb_callback, _tick_check, _subsystem_to_use, _verification_args...) \
if(!TRY_QUEUE_VERB(_verb_callback, _tick_check, _subsystem_to_use, _verification_args)) {\
_verb_callback:InvokeAsync() \
};
//goes straight to SSverb_manager with default tick threshold
#define DEFAULT_TRY_QUEUE_VERB(_verb_callback, _verification_args...) (TRY_QUEUE_VERB(_verb_callback, VERB_DEFAULT_QUEUE_THRESHOLD, null, _verification_args))
#define DEFAULT_QUEUE_OR_CALL_VERB(_verb_callback, _verification_args...) QUEUE_OR_CALL_VERB(_verb_callback, VERB_DEFAULT_QUEUE_THRESHOLD, null, _verification_args)
//default tick threshold but nondefault subsystem
#define TRY_QUEUE_VERB_FOR(_verb_callback, _subsystem_to_use, _verification_args...) (TRY_QUEUE_VERB(_verb_callback, VERB_DEFAULT_QUEUE_THRESHOLD, _subsystem_to_use, _verification_args))
#define QUEUE_OR_CALL_VERB_FOR(_verb_callback, _subsystem_to_use, _verification_args...) QUEUE_OR_CALL_VERB(_verb_callback, VERB_DEFAULT_QUEUE_THRESHOLD, _subsystem_to_use, _verification_args)
+6 -5
View File
@@ -343,16 +343,17 @@
//The icon var could be local in the proc, but it's a waste of resources
// to always create it and then throw it out.
/var/icon/text_tag_icons = 'icons/chattags.dmi'
/var/list/text_tag_cache = list()
GLOBAL_LIST_EMPTY(text_tag_cache)
/proc/create_text_tag(var/tagname, var/tagdesc = tagname, var/client/C = null)
if(!(C && C.prefs?.read_preference(/datum/preference/toggle/chat_tags)))
return tagdesc
if(!text_tag_cache[tagname])
var/icon/tag = icon(text_tag_icons, tagname)
text_tag_cache[tagname] = tag
if(!GLOB.text_tag_cache[tagname])
var/datum/asset/spritesheet/chatassets = get_asset_datum(/datum/asset/spritesheet/chat)
GLOB.text_tag_cache[tagname] = chatassets.icon_tag(tagname)
if(!C.tgui_panel.is_ready() || C.tgui_panel.oldchat)
return "<IMG src='\ref[text_tag_icons]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"
return icon2html(text_tag_cache[tagname], C, extra_classes = "text_tag")
return GLOB.text_tag_cache[tagname]
/proc/create_text_tag_old(var/tagname, var/tagdesc = tagname, var/client/C = null)
if(!(C && C.prefs?.read_preference(/datum/preference/toggle/chat_tags)))
+2 -2
View File
@@ -420,7 +420,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
/proc/select_active_ai(var/mob/user)
var/list/ais = active_ais()
if(ais.len)
if(user) . = tgui_input_list(usr, "AI signals detected:", "AI selection", ais)
if(user) . = tgui_input_list(user, "AI signals detected:", "AI selection", ais)
else . = pick(ais)
return .
@@ -974,7 +974,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
if(toupdate.len)
for(var/turf/simulated/T1 in toupdate)
air_master.mark_for_update(T1)
SSair.mark_for_update(T1)
return copiedobjs
+1 -1
View File
@@ -44,7 +44,7 @@
if(aiCamera && aiCamera.in_camera_mode)
aiCamera.camera_mode_off()
if(is_component_functioning("camera"))
aiCamera.captureimage(A, usr)
aiCamera.captureimage(A, src)
else
to_chat(src, span_userdanger("Your camera isn't functional."))
return
+1 -1
View File
@@ -396,7 +396,7 @@ var/list/global_huds = list(
set hidden = 1
if(!hud_used)
to_chat(usr, span_warning("This mob type does not use a HUD."))
to_chat(src, span_warning("This mob type does not use a HUD."))
return FALSE
if(!client)
return FALSE
+2 -2
View File
@@ -282,11 +282,11 @@ var/obj/screen/robot_inventory
//r.client.screen += robot_inventory //"store" icon
if(!r.module)
to_chat(usr, span_danger("No module selected"))
to_chat(r, span_danger("No module selected"))
return
if(!r.module.modules)
to_chat(usr, span_danger("Selected module has no modules to select"))
to_chat(r, span_danger("Selected module has no modules to select"))
return
if(!r.robot_modules_background)
File diff suppressed because it is too large Load Diff
-64
View File
@@ -1,64 +0,0 @@
//
// Lets read our settings from the configuration file on startup too!
//
/datum/configuration
var/static/time_off = FALSE
var/static/pto_job_change = FALSE
var/static/limit_interns = -1 //Unlimited by default
var/static/limit_visitors = -1 //Unlimited by default
var/static/pto_cap = 100 //Hours
var/static/require_flavor = FALSE
var/static/ipqualityscore_apikey //API key for ipqualityscore.com
var/static/use_playtime_restriction_for_jobs = FALSE
/hook/startup/proc/read_vs_config()
var/list/Lines = file2list("config/config.txt")
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)
name = lowertext(copytext(t, 1, pos))
value = copytext(t, pos + 1)
else
name = lowertext(t)
if (!name)
continue
switch (name)
if ("chat_webhook_url")
config.chat_webhook_url = value
if ("chat_webhook_key")
config.chat_webhook_key = value
if ("fax_export_dir")
config.fax_export_dir = value
if ("items_survive_digestion")
config.items_survive_digestion = 1
if ("limit_interns")
config.limit_interns = text2num(value)
if ("limit_visitors")
config.limit_visitors = text2num(value)
if ("pto_cap")
config.pto_cap = text2num(value)
if ("time_off")
config.time_off = TRUE
if ("pto_job_change")
config.pto_job_change = TRUE
if ("require_flavor")
config.require_flavor = TRUE
if ("ipqualityscore_apikey")
config.ipqualityscore_apikey = value
if ("use_playtime_restriction_for_jobs")
config.use_playtime_restriction_for_jobs = TRUE
return 1
+104 -26
View File
@@ -1,10 +1,11 @@
/**
* Failsafe
*
* Pretty much pokes the MC to make sure it's still alive.
/**
* Failsafe
*
* Pretty much pokes the MC to make sure it's still alive.
**/
var/datum/controller/failsafe/Failsafe
// See initialization order in /code/game/world.dm
GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
/datum/controller/failsafe // This thing pretty much just keeps poking the master controller
name = "Failsafe"
@@ -15,7 +16,7 @@ var/datum/controller/failsafe/Failsafe
// The alert level. For every failed poke, we drop a DEFCON level. Once we hit DEFCON 1, restart the MC.
var/defcon = 5
//the world.time of the last check, so the mc can restart US if we hang.
// (Real friends look out for *eachother*)
// (Real friends look out for *each other*)
var/lasttick = 0
// Track the MC iteration to make sure its still on track.
@@ -31,8 +32,24 @@ var/datum/controller/failsafe/Failsafe
Initialize()
/datum/controller/failsafe/Initialize()
set waitfor = 0
set waitfor = FALSE
Failsafe.Loop()
if (!Master || defcon == 0) //Master is gone/not responding and Failsafe just exited its loop
defcon = 3 //Reset defcon level as its used inside the emergency loop
while (defcon > 0)
var/recovery_result = emergency_loop()
if (recovery_result == 1) //Exit emergency loop and delete self if it was able to recover MC
break
else if (defcon == 1) //Exit Failsafe if we weren't able to recover the MC in the last stage
log_game("FailSafe: Failed to recover MC while in emergency state. Failsafe exiting.")
message_admins(span_boldannounce("Failsafe failed critically while trying to recreate broken MC. Please manually fix the MC or reboot the server. Failsafe exiting now."))
message_admins(span_boldannounce("You can try manually calling these two procs:."))
message_admins(span_boldannounce("/proc/recover_all_SS_and_recreate_master: Most stuff should still function but expect instability/runtimes/broken stuff."))
message_admins(span_boldannounce("/proc/delete_all_SS_and_recreate_master: Most stuff will be broken but basic stuff like movement and chat should still work."))
else if (recovery_result == -1) //Failed to recreate MC
defcon--
sleep(initial(processing_interval)) //Wait a bit until the next try
if(!QDELETED(src))
qdel(src) //when Loop() returns, we delete ourselves and let the mc recreate us
@@ -45,43 +62,56 @@ var/datum/controller/failsafe/Failsafe
while(running)
lasttick = world.time
if(!Master)
// Replace the missing Master! This should never, ever happen.
new /datum/controller/master()
// Break out of the main loop so we go into emergency state
break
// Only poke it if overrides are not in effect.
if(processing_interval > 0)
if(Master.processing && Master.iteration)
if (defcon > 1 && (!Master.stack_end_detector || !Master.stack_end_detector.check()))
to_chat(GLOB.admins, span_boldannounce("ERROR: The Master Controller code stack has exited unexpectedly, Restarting..."))
defcon = 0
var/rtn = Recreate_MC()
if(rtn > 0)
master_iteration = 0
to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
else if(rtn < 0)
log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
to_chat(GLOB.admins, span_boldannounce("ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying."))
// Check if processing is done yet.
if(Master.iteration == master_iteration)
log_debug("DEFCON [defcon]: Master.iteration=[Master.iteration] Master.last_run=[Master.last_run] world.time=[world.time]")
switch(defcon)
if(4,5)
--defcon
if(3)
log_and_message_admins(span_adminnotice("SSfailsafe Notice: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has not fired in the last [(5-defcon) * processing_interval] ticks."))
--defcon
if(2)
log_and_message_admins(span_boldannounce("SSfailsafe Warning: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has not fired in the last [(5-defcon) * processing_interval] ticks. Automatic restart in [processing_interval] ticks."))
--defcon
if(1)
log_and_message_admins(span_boldannounce("SSfailsafe Warning: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has still not fired within the last [(5-defcon) * processing_interval] ticks. Killing and restarting..."))
if(3)
message_admins(span_adminnotice("Notice: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks."))
--defcon
if(2)
to_chat(GLOB.admins, span_boldannounce("Warning: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks. Automatic restart in [processing_interval] ticks."))
--defcon
if(1)
to_chat(GLOB.admins, span_boldannounce("Warning: DEFCON [defcon_pretty()]. The Master Controller has still not fired within the last [(5-defcon) * processing_interval] ticks. Killing and restarting..."))
--defcon
var/rtn = Recreate_MC()
if(rtn > 0)
defcon = 4
master_iteration = 0
log_and_message_admins(span_adminnotice("SSfailsafe Notice: MC (New:\ref[Master]) restarted successfully"))
to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
else if(rtn < 0)
log_game("SSfailsafe Notice: Could not restart MC (\ref[Master]), runtime encountered. Entering defcon 0")
log_and_message_admins(span_boldannounce("SSFAILSAFE ERROR: DEFCON [defcon_pretty()]. Could not restart MC (\ref[Master]), runtime encountered. I will silently keep retrying."))
log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
to_chat(GLOB.admins, span_boldannounce("ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying."))
//if the return number was 0, it just means the mc was restarted too recently, and it just needs some time before we try again
//no need to handle that specially when defcon 0 can handle it
if(0) //DEFCON 0! (mc failed to restart)
var/rtn = Recreate_MC()
if(rtn > 0)
defcon = 4
master_iteration = 0
log_and_message_admins(span_adminnotice("SSfailsafe Notice: MC (New:\ref[Master]) restarted successfully"))
to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
else
defcon = min(defcon + 1,5)
master_iteration = Master.iteration
@@ -93,12 +123,60 @@ var/datum/controller/failsafe/Failsafe
defcon = 5
sleep(initial(processing_interval))
//Emergency loop used when Master got deleted or the main loop exited while Defcon == 0
//Loop is driven externally so runtimes only cancel the current recovery attempt
/datum/controller/failsafe/proc/emergency_loop()
//The code in this proc should be kept as simple as possible, anything complicated like to_chat might rely on master existing and runtime
//The goal should always be to get a new Master up and running before anything else
. = -1
switch (defcon) //The lower defcon goes the harder we try to fix the MC
if (2 to 3) //Try to normally recreate the MC two times
. = Recreate_MC()
if (1) //Delete the old MC first so we don't transfer any info, in case that caused any issues
del(Master)
. = Recreate_MC()
if (. == 1) //We were able to create a new master
master_iteration = 0
SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
Master.Initialize(10, FALSE, FALSE) //Need to manually start the MC, normally world.new would do this
to_chat(GLOB.admins, span_adminnotice("Failsafe recovered MC while in emergency state [defcon_pretty()]"))
else
log_game("FailSafe: Failsafe in emergency state and was unable to recreate MC while in defcon state [defcon_pretty()].")
message_admins(span_boldannounce("Failsafe in emergency state and master down, trying to recreate MC while in defcon level [defcon_pretty()] failed."))
///Recreate all SSs which will still cause data survive due to Recover(), the new Master will then find and take them from global.vars
/proc/recover_all_SS_and_recreate_master()
del(Master)
var/list/subsytem_types = subtypesof(/datum/controller/subsystem)
sortTim(subsytem_types, GLOBAL_PROC_REF(cmp_subsystem_init))
for(var/I in subsytem_types)
new I
. = Recreate_MC()
if (. == 1) //We were able to create a new master
SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
Master.Initialize(10, FALSE, FALSE) //Need to manually start the MC, normally world.new would do this
to_chat(GLOB.admins, span_adminnotice("MC successfully recreated after recovering all subsystems!"))
else
message_admins(span_boldannounce("Failed to create new MC!"))
///Delete all existing SS to basically start over
/proc/delete_all_SS_and_recreate_master()
del(Master)
for(var/global_var in global.vars)
if (istype(global.vars[global_var], /datum/controller/subsystem))
del(global.vars[global_var])
. = Recreate_MC()
if (. == 1) //We were able to create a new master
SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
Master.Initialize(10, FALSE, FALSE) //Need to manually start the MC, normally world.new would do this
to_chat(GLOB.admins, span_adminnotice("MC successfully recreated after deleting and recreating all subsystems!"))
else
message_admins(span_boldannounce("Failed to create new MC!"))
/datum/controller/failsafe/proc/defcon_pretty()
return defcon
/datum/controller/failsafe/stat_entry(msg)
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
msg = "Failsafe Controller: [statclick.update("Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])")]"
msg = "Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])"
return msg
+17 -16
View File
@@ -1,26 +1,23 @@
/**
* StonedMC
*
* Designed to properly split up a given tick among subsystems
* Note: if you read parts of this code and think "why is it doing it that way"
* Odds are, there is a reason
*
/**
* StonedMC
*
* Designed to properly split up a given tick among subsystems
* Note: if you read parts of this code and think "why is it doing it that way"
* Odds are, there is a reason
*
**/
//This is the ABSOLUTE ONLY THING that should init globally like this
// See initialization order in /code/game/world.dm
GLOBAL_REAL(Master, /datum/controller/master) = new
//THIS IS THE INIT ORDER
//Master -> SSPreInit -> GLOB -> world -> config -> SSInit -> Failsafe
//GOT IT MEMORIZED?
/datum/controller/master
name = "Master"
// Are we processing (higher values increase the processing delay by n ticks)
/// Are we processing (higher values increase the processing delay by n ticks)
var/processing = TRUE
// How many times have we ran
/// How many times have we ran
var/iteration = 0
/// Stack end detector to detect stack overflows that kill the mc's main loop
var/datum/stack_end_detector/stack_end_detector
// world.time of last fire, for tracking lag outside of the mc
var/last_run
@@ -291,8 +288,12 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/error_level = 0
var/sleep_delta = 1
var/list/subsystems_to_check
//the actual loop.
//setup the stack overflow detector
stack_end_detector = new()
var/datum/stack_canary/canary = stack_end_detector.prime_canary()
canary.use_variable()
//the actual loop.
while (1)
tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag)))
var/starting_tick_usage = TICK_USAGE
-2
View File
@@ -11,8 +11,6 @@ var/global/datum/controller/game_controller/master_controller //Set in world.New
var/global/controller_iteration = 0
var/global/last_tick_duration = 0
var/global/pipe_processing_killed = 0
/datum/controller/game_controller
var/list/shuttle_list // For debugging and VV
+228 -7
View File
@@ -1,3 +1,60 @@
/*
Overview:
SSair does everything. There are tons of procs in here.
Class Vars:
zones - All zones currently holding one or more turfs.
edges - All processing edges.
tiles_to_update - Tiles scheduled to update next tick.
zones_to_update - Zones which have had their air changed and need air archival.
active_hotspots - All processing fire objects.
active_zones - The number of zones which were archived last tick. Used in debug verbs.
next_id - The next UID to be applied to a zone. Mostly useful for debugging purposes as zones do not need UIDs to function.
Class Procs:
mark_for_update(turf/T)
Adds the turf to the update list. When updated, update_air_properties() will be called.
When stuff changes that might affect airflow, call this. It's basically the only thing you need.
add_zone(zone/Z) and remove_zone(zone/Z)
Adds zones to the zones list. Does not mark them for update.
air_blocked(turf/A, turf/B)
Returns a bitflag consisting of:
AIR_BLOCKED - The connection between turfs is physically blocked. No air can pass.
ZONE_BLOCKED - There is a door between the turfs, so zones cannot cross. Air may or may not be permeable.
merge(zone/A, zone/B)
Called when zones have a direct connection and equivalent pressure and temperature.
Merges the zones to create a single zone.
connect(turf/simulated/A, turf/B)
Called by turf/update_air_properties(). The first argument must be simulated.
Creates a connection between A and B.
mark_zone_update(zone/Z)
Adds zone to the update list. Unlike mark_for_update(), this one is called automatically whenever
air is returned from a simulated turf.
equivalent_pressure(zone/A, zone/B)
Currently identical to A.air.compare(B.air). Returns 1 when directly connected zones are ready to be merged.
get_edge(zone/A, zone/B)
get_edge(zone/A, turf/B)
Gets a valid connection_edge between A and B, creating a new one if necessary.
has_same_air(turf/A, turf/B)
Used to determine if an unsimulated edge represents a specific turf.
Simulated edges use connection_edge/contains_zone() for the same purpose.
Returns 1 if A has identical gases and temperature to B.
remove_edge(connection_edge/edge)
Called when an edge is erased. Removes it from processing.
*/
// Air update stages
#define SSAIR_TURFS 1
#define SSAIR_EDGES 2
@@ -30,8 +87,19 @@ SUBSYSTEM_DEF(air)
// This is used to tell CI WHERE the edges are.
var/list/startup_active_edge_log = list()
/datum/controller/subsystem/air/PreInit()
air_master = src
//Geometry lists
var/list/zones = list()
var/list/edges = list()
//Geometry updates lists
var/list/tiles_to_update = list()
var/list/zones_to_update = list()
var/list/active_fire_zones = list()
var/list/active_hotspots = list()
var/list/active_edges = list()
var/active_zones = 0
var/current_cycle = 0
var/next_id = 1 //Used to keep track of zone UIDs.
/datum/controller/subsystem/air/Initialize(timeofday)
report_progress("Processing Geometry...")
@@ -109,7 +177,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
log_and_message_admins("SSair: Was told to start a new run, but the previous run wasn't finished! currentrun.len=[currentrun.len], current_step=[current_step]")
resumed = TRUE
else
current_cycle++ // Begin a new air_master cycle!
current_cycle++ // Begin a new SSair cycle!
current_step = SSAIR_TURFS // Start with Step 1 of course
INTERNAL_PROCESS_STEP(SSAIR_TURFS, TRUE, process_tiles_to_update, cost_turfs, SSAIR_EDGES)
@@ -118,7 +186,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
INTERNAL_PROCESS_STEP(SSAIR_HOTSPOTS, FALSE, process_active_hotspots, cost_hotspots, SSAIR_ZONES)
INTERNAL_PROCESS_STEP(SSAIR_ZONES, FALSE, process_zones_to_update, cost_zones, SSAIR_DONE)
// Okay, we're done! Woo! Got thru a whole air_master cycle!
// Okay, we're done! Woo! Got thru a whole SSair cycle!
if(LAZYLEN(currentrun) || current_step != SSAIR_DONE)
log_and_message_admins("SSair: Was not able to complete a full air cycle despite reaching the end of fire(). This shouldn't happen.")
else
@@ -305,9 +373,162 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
next_fire = world.time + wait
can_fire = TRUE // Unpause
//
// The procs from the ZAS Air Controller are in ZAS/Controller.dm
//
/datum/controller/subsystem/air/proc/add_zone(zone/z)
zones.Add(z)
z.name = "Zone [next_id++]"
mark_zone_update(z)
/datum/controller/subsystem/air/proc/remove_zone(zone/z)
zones.Remove(z)
zones_to_update.Remove(z)
/datum/controller/subsystem/air/proc/air_blocked(turf/A, turf/B)
#ifdef ZASDBG
ASSERT(isturf(A))
ASSERT(isturf(B))
#endif
var/ablock = A.c_airblock(B)
if(ablock == BLOCKED)
return BLOCKED
return ablock | B.c_airblock(A)
/datum/controller/subsystem/air/proc/merge(zone/A, zone/B)
#ifdef ZASDBG
ASSERT(istype(A))
ASSERT(istype(B))
ASSERT(!A.invalid)
ASSERT(!B.invalid)
ASSERT(A != B)
#endif
if(A.contents.len < B.contents.len)
A.c_merge(B)
mark_zone_update(B)
else
B.c_merge(A)
mark_zone_update(A)
/datum/controller/subsystem/air/proc/connect(turf/simulated/A, turf/simulated/B)
#ifdef ZASDBG
ASSERT(istype(A))
ASSERT(isturf(B))
ASSERT(A.zone)
ASSERT(!A.zone.invalid)
//ASSERT(B.zone)
ASSERT(A != B)
#endif
var/block = SSair.air_blocked(A,B)
if(block & AIR_BLOCKED) return
var/direct = !(block & ZONE_BLOCKED)
var/space = !istype(B)
if(!space)
if(min(A.zone.contents.len, B.zone.contents.len) < ZONE_MIN_SIZE || (direct && (equivalent_pressure(A.zone,B.zone) || current_cycle == 0)))
merge(A.zone,B.zone)
return
var/a_to_b = get_dir(A,B)
var/b_to_a = get_dir(B,A)
if(!A.connections)
A.connections = new
if(!B.connections)
B.connections = new
if(A.connections.get(a_to_b))
return
if(B.connections.get(b_to_a))
return
if(!space)
if(A.zone == B.zone)
return
var/connection/c = new /connection(A,B)
A.connections.place(c, a_to_b)
B.connections.place(c, b_to_a)
if(direct) c.mark_direct()
/datum/controller/subsystem/air/proc/mark_for_update(turf/T)
#ifdef ZASDBG
ASSERT(isturf(T))
#endif
if(T.needs_air_update)
return
tiles_to_update |= T
#ifdef ZASDBG
T.add_overlay(mark)
#endif
T.needs_air_update = 1
/datum/controller/subsystem/air/proc/mark_zone_update(zone/Z)
#ifdef ZASDBG
ASSERT(istype(Z))
#endif
if(Z.needs_update)
return
zones_to_update.Add(Z)
Z.needs_update = 1
/datum/controller/subsystem/air/proc/mark_edge_sleeping(connection_edge/E)
#ifdef ZASDBG
ASSERT(istype(E))
#endif
if(E.sleeping)
return
active_edges.Remove(E)
E.sleeping = 1
/datum/controller/subsystem/air/proc/mark_edge_active(connection_edge/E)
#ifdef ZASDBG
ASSERT(istype(E))
#endif
if(!E.sleeping)
return
active_edges.Add(E)
E.sleeping = 0
/datum/controller/subsystem/air/proc/equivalent_pressure(zone/A, zone/B)
return A.air.compare(B.air)
/datum/controller/subsystem/air/proc/get_edge(zone/A, zone/B)
if(istype(B))
for(var/connection_edge/zone/edge in A.edges)
if(edge.contains_zone(B))
return edge
var/connection_edge/edge = new /connection_edge/zone(A,B)
edges.Add(edge)
edge.recheck()
return edge
else
for(var/connection_edge/unsimulated/edge in A.edges)
if(has_same_air(edge.B,B))
return edge
var/connection_edge/edge = new /connection_edge/unsimulated(A,B)
edges.Add(edge)
edge.recheck()
return edge
/datum/controller/subsystem/air/proc/has_same_air(turf/A, turf/B)
if(A.oxygen != B.oxygen)
return FALSE
if(A.nitrogen != B.nitrogen)
return FALSE
if(A.phoron != B.phoron)
return FALSE
if(A.carbon_dioxide != B.carbon_dioxide)
return FALSE
if(A.temperature != B.temperature)
return FALSE
return TRUE
/datum/controller/subsystem/air/proc/remove_edge(connection_edge/E)
edges.Remove(E)
if(!E.sleeping)
active_edges.Remove(E)
#undef SSAIR_TURFS
#undef SSAIR_EDGES
@@ -0,0 +1,5 @@
/// verb_manager subsystem just for handling say's
VERB_MANAGER_SUBSYSTEM_DEF(speech_controller)
name = "Speech Controller"
wait = 1
priority = FIRE_PRIORITY_SPEECH_CONTROLLER//has to be high priority, second in priority ONLY to SSinput
+167
View File
@@ -0,0 +1,167 @@
/**
* SSverb_manager, a subsystem that runs every tick and runs through its entire queue without yielding like SSinput.
* this exists because of how the byond tick works and where user inputted verbs are put within it.
*
* see TICK_ORDER.md for more info on how the byond tick is structured.
*
* The way the MC allots its time is via TICK_LIMIT_RUNNING, it simply subtracts the cost of SendMaps (MAPTICK_LAST_INTERNAL_TICK_USAGE)
* plus TICK_BYOND_RESERVE from the tick and uses up to that amount of time (minus the percentage of the tick used by the time it executes subsystems)
* on subsystems running cool things like atmospherics or Life or SSInput or whatever.
*
* Without this subsystem, verbs are likely to cause overtime if the MC uses all of the time it has allotted for itself in the tick, and SendMaps
* uses as much as its expected to, and an expensive verb ends up executing that tick. This is because the MC is completely blind to the cost of
* verbs, it can't account for it at all. The only chance for verbs to not cause overtime in a tick where the MC used as much of the tick
* as it allotted itself and where SendMaps costed as much as it was expected to is if the verb(s) take less than TICK_BYOND_RESERVE percent of
* the tick, which isn't much. Not to mention if SendMaps takes more than 30% of the tick and the MC forces itself to take at least 70% of the
* normal tick duration which causes ticks to naturally overrun even in the absence of verbs.
*
* With this subsystem, the MC can account for the cost of verbs and thus stop major overruns of ticks. This means that the most important subsystems
* like SSinput can start at the same time they were supposed to, leading to a smoother experience for the player since ticks aren't riddled with
* minor hangs over and over again.
*/
SUBSYSTEM_DEF(verb_manager)
name = "Verb Manager"
wait = 1
flags = SS_TICKER | SS_NO_INIT
priority = FIRE_PRIORITY_DELAYED_VERBS
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
///list of callbacks to procs called from verbs or verblike procs that were executed when the server was overloaded and had to delay to the next tick.
///this list is ran through every tick, and the subsystem does not yield until this queue is finished.
var/list/datum/callback/verb_callback/verb_queue = list()
///running average of how many verb callbacks are executed every second. used for the stat entry
var/verbs_executed_per_second = 0
///if TRUE we treat usr's with holders just like usr's without holders. otherwise they always execute immediately
var/can_queue_admin_verbs = FALSE
///if this is true all verbs immediately execute and don't queue. in case the mc is fucked or something
var/FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs = FALSE
///used for subtypes to determine if they use their own stats for the stat entry
var/use_default_stats = TRUE
///if TRUE this will... message admins every time a verb is queued to this subsystem for the next tick with stats.
///for obvious reasons don't make this be TRUE on the code level this is for admins to turn on
var/message_admins_on_queue = FALSE
///always queue if possible. overrides can_queue_admin_verbs but not FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs
var/always_queue = FALSE
/**
* queue a callback for the given verb/verblike proc and any given arguments to the specified verb subsystem, so that they process in the next tick.
* intended to only work with verbs or verblike procs called directly from client input, use as part of TRY_QUEUE_VERB() and co.
*
* returns TRUE if the queuing was successful, FALSE otherwise.
*/
/proc/_queue_verb(datum/callback/verb_callback/incoming_callback, tick_check, datum/controller/subsystem/verb_manager/subsystem_to_use = SSverb_manager, ...)
if(QDELETED(incoming_callback))
var/destroyed_string
if(!incoming_callback)
destroyed_string = "callback is null."
else
destroyed_string = "callback was deleted [DS2TICKS(world.time - incoming_callback.gc_destroyed)] ticks ago. callback was created [DS2TICKS(world.time) - incoming_callback.creation_time] ticks ago."
stack_trace("_queue_verb() returned false because it was given a deleted callback! [destroyed_string]")
return FALSE
if(!istext(incoming_callback.object) && QDELETED(incoming_callback.object)) //just in case the object is GLOBAL_PROC
var/destroyed_string
if(!incoming_callback.object)
destroyed_string = "callback.object is null."
else
destroyed_string = "callback.object was deleted [DS2TICKS(world.time - incoming_callback.object.gc_destroyed)] ticks ago. callback was created [DS2TICKS(world.time) - incoming_callback.creation_time] ticks ago."
stack_trace("_queue_verb() returned false because it was given a callback acting on a qdeleted object! [destroyed_string]")
return FALSE
//we want unit tests to be able to directly call verbs that attempt to queue, and since unit tests should test internal behavior, we want the queue
//to happen as if it was actually from player input if its called on a mob.
#ifdef UNIT_TESTS
if(QDELETED(usr) && ismob(incoming_callback.object))
incoming_callback.user = WEAKREF(incoming_callback.object)
var/datum/callback/new_us = CALLBACK(arglist(list(GLOBAL_PROC, GLOBAL_PROC_REF(_queue_verb)) + args.Copy()))
return world.push_usr(incoming_callback.object, new_us)
#else
if(QDELETED(usr) || isnull(usr.client))
stack_trace("_queue_verb() returned false because it wasn't called from player input!")
return FALSE
#endif
if(!istype(subsystem_to_use))
stack_trace("_queue_verb() returned false because it was given an invalid subsystem to queue for!")
return FALSE
if((TICK_USAGE < tick_check) && !subsystem_to_use.always_queue)
return FALSE
var/list/args_to_check = args.Copy()
args_to_check.Cut(2, 4)//cut out tick_check and subsystem_to_use
//any subsystem can use the additional arguments to refuse queuing
if(!subsystem_to_use.can_queue_verb(arglist(args_to_check)))
return FALSE
return subsystem_to_use.queue_verb(incoming_callback)
/**
* subsystem-specific check for whether a callback can be queued.
* intended so that subsystem subtypes can verify whether
*
* subtypes may include additional arguments here if they need them! you just need to include them properly
* in TRY_QUEUE_VERB() and co.
*/
/datum/controller/subsystem/verb_manager/proc/can_queue_verb(datum/callback/verb_callback/incoming_callback)
if(always_queue && !FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs)
return TRUE
if((usr.client?.holder && !can_queue_admin_verbs) \
|| (!subsystem_initialized && !(flags & SS_NO_INIT)) \
|| FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs \
|| !(runlevels & Master.current_runlevel))
return FALSE
return TRUE
/**
* queue a callback for the given proc, so that it is invoked in the next tick.
* intended to only work with verbs or verblike procs called directly from client input, use as part of TRY_QUEUE_VERB()
*
* returns TRUE if the queuing was successful, FALSE otherwise.
*/
/datum/controller/subsystem/verb_manager/proc/queue_verb(datum/callback/verb_callback/incoming_callback)
. = FALSE //errored
if(message_admins_on_queue)
message_admins("[name] verb queuing: tick usage: [TICK_USAGE]%, proc: [incoming_callback.delegate], object: [incoming_callback.object], usr: [usr]")
verb_queue += incoming_callback
return TRUE
/datum/controller/subsystem/verb_manager/fire(resumed)
run_verb_queue()
/// runs through all of this subsystems queue of verb callbacks.
/// goes through the entire verb queue without yielding.
/// used so you can flush the queue outside of fire() without interfering with anything else subtype subsystems might do in fire().
/datum/controller/subsystem/verb_manager/proc/run_verb_queue()
var/executed_verbs = 0
for(var/datum/callback/verb_callback/verb_callback as anything in verb_queue)
if(!istype(verb_callback))
stack_trace("non /datum/callback/verb_callback inside [name]'s verb_queue!")
continue
verb_callback.InvokeAsync()
executed_verbs++
verb_queue.Cut()
verbs_executed_per_second = MC_AVG_SECONDS(verbs_executed_per_second, executed_verbs, wait SECONDS)
//note that wait SECONDS is incorrect if this is called outside of fire() but because byond is garbage i need to add a timer to rustg to find a valid solution
/datum/controller/subsystem/verb_manager/stat_entry(msg)
. = ..()
if(use_default_stats)
. += "V/S: [round(verbs_executed_per_second, 0.01)]"
-1
View File
@@ -89,7 +89,6 @@
//Goon PS stuff, and other yet-to-be-subsystem things.
options["LEGACY: master_controller"] = master_controller
options["LEGACY: air_master"] = air_master
options["LEGACY: job_master"] = job_master
options["LEGACY: radio_controller"] = radio_controller
options["LEGACY: emergency_shuttle"] = emergency_shuttle
+6 -6
View File
@@ -43,7 +43,7 @@
/datum/ColorMate/tgui_state(mob/user)
return GLOB.tgui_conscious_state
/datum/ColorMate/tgui_data()
/datum/ColorMate/tgui_data(mob/user)
. = list()
.["activemode"] = active_mode
.["matrixcolors"] = list(
@@ -69,7 +69,7 @@
.["item"] = list()
.["item"]["name"] = inserted.name
.["item"]["sprite"] = icon2base64(get_flat_icon(inserted,dir=SOUTH,no_anim=TRUE))
.["item"]["preview"] = icon2base64(build_preview())
.["item"]["preview"] = icon2base64(build_preview(user))
else
.["item"] = null
@@ -159,7 +159,7 @@
return TRUE
/// Produces the preview image of the item, used in the UI, the way the color is not stacking is a sin.
/datum/ColorMate/proc/build_preview()
/datum/ColorMate/proc/build_preview(mob/user)
if(inserted) //sanity
var/list/cm
switch(active_mode)
@@ -178,17 +178,17 @@
text2num(color_matrix_last[11]),
text2num(color_matrix_last[12]),
)
if(!check_valid_color(cm, usr))
if(!check_valid_color(cm, user))
return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE)
if(COLORMATE_TINT)
if(!check_valid_color(activecolor, usr))
if(!check_valid_color(activecolor, user))
return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE)
if(COLORMATE_HSV)
cm = color_matrix_hsv(build_hue, build_sat, build_val)
color_matrix_last = cm
if(!check_valid_color(cm, usr))
if(!check_valid_color(cm, user))
return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE)
var/cur_color = inserted.color
+9 -10
View File
@@ -452,26 +452,25 @@
data["crafting_recipes"] = crafting_recipes
return data
/datum/component/personal_crafting/tgui_act(action, params)
/datum/component/personal_crafting/tgui_act(action, params, datum/tgui/ui)
. = ..()
if(.)
return
switch(action)
if("make")
var/mob/user = usr
var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes
busy = TRUE
tgui_interact(user)
var/atom/movable/result = construct_item(user, TR)
tgui_interact(ui.user)
var/atom/movable/result = construct_item(ui.user, TR)
if(!istext(result)) //We made an item and didn't get a fail message
if(ismob(user) && isitem(result)) //In case the user is actually possessing a non mob like a machine
user.put_in_hands(result)
if(ismob(ui.user) && isitem(result)) //In case the user is actually possessing a non mob like a machine
ui.user.put_in_hands(result)
else
result.forceMove(user.drop_location())
to_chat(user, span_notice("[TR.name] constructed."))
TR.on_craft_completion(user, result)
result.forceMove(ui.user.drop_location())
to_chat(ui.user, span_notice("[TR.name] constructed."))
TR.on_craft_completion(ui.user, result)
else
to_chat(user, span_warning("Construction failed[result]"))
to_chat(ui.user, span_warning("Construction failed[result]"))
busy = FALSE
if("toggle_recipes")
display_craftable_only = !display_craftable_only
+2 -5
View File
@@ -80,7 +80,7 @@
if(prob(15/D.permeability_mod))
return
if(nutrition > 300 && prob(nutrition/10))
if(nutrition > 300 && prob(nutrition/50))
return
var/list/zone_weights = list(
@@ -178,16 +178,13 @@
return FALSE
var/disease = tgui_input_list(usr, "Choose virus", "Viruses", subtypesof(/datum/disease), subtypesof(/datum/disease))
var/mob/living/carbon/human/H = tgui_input_list(usr, "Choose infectee", human_mob_list)
var/mob/living/carbon/human/H = tgui_input_list(usr, "Choose infectee", "Characters", human_mob_list)
var/datum/disease/D = new disease
if(isnull(D) || isnull(H))
return FALSE
if(H.stat == DEAD)
return FALSE
if(!H.HasDisease(D))
H.ForceContractDisease(D)
+2 -2
View File
@@ -91,7 +91,7 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease))
var/cures_found = 0
for(var/C_id in cures)
if(affected_mob.reagents.has_reagent(C_id))
if(affected_mob.bloodstr.has_reagent(C_id) || affected_mob.ingested.has_reagent(C_id))
cures_found++
if(needs_all_cures && cures_found < length(cures))
@@ -106,7 +106,7 @@ GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease))
if((spread_flags & SPECIAL || spread_flags & NON_CONTAGIOUS || spread_flags & BLOOD) && !force_spread)
return
if(affected_mob.reagents.has_reagent("spaceacilin") || (affected_mob.nutrition > 300 && prob(affected_mob.nutrition/10)))
if(affected_mob.bloodstr.has_reagent("spaceacillin") || (affected_mob.nutrition > 300 && prob(affected_mob.nutrition/50)))
return
var/spread_range = 1
+6 -5
View File
@@ -2,7 +2,7 @@ GLOBAL_LIST_EMPTY(archive_diseases)
GLOBAL_LIST_INIT(advance_cures, list(
"sodiumchloride", "sugar", "orangejuice",
"spaceacilin", "glucose", "ethanol",
"spaceacillin", "glucose", "ethanol",
"leporazine", "impedrezene", "hepanephrodaxon",
"silver", "gold"
))
@@ -16,6 +16,7 @@ GLOBAL_LIST_INIT(advance_cures, list(
spread_text = "Unknown"
viable_mobtypes = list(/mob/living/carbon/human)
var/s_processing = FALSE
var/list/symptoms = list()
var/id = ""
@@ -36,7 +37,7 @@ GLOBAL_LIST_INIT(advance_cures, list(
return
/datum/disease/advance/Destroy()
if(processing)
if(s_processing)
for(var/datum/symptom/S in symptoms)
S.End(src)
return ..()
@@ -46,8 +47,8 @@ GLOBAL_LIST_INIT(advance_cures, list(
return FALSE
if(symptoms && length(symptoms))
if(!processing)
processing = TRUE
if(!s_processing)
s_processing = TRUE
for(var/datum/symptom/S in symptoms)
S.Start(src)
@@ -368,7 +369,7 @@ GLOBAL_LIST_INIT(advance_cures, list(
for(var/datum/disease/advance/AD in active_diseases)
AD.Refresh()
H = tgui_input_list(usr, "Choose infectee", human_mob_list)
H = tgui_input_list(usr, "Choose infectee", "Infectees", human_mob_list)
if(isnull(H))
return FALSE
@@ -10,7 +10,8 @@ Coughing
Low Level.
BONUS
Will force the affected mob to drop small items!
Will force the affected mob to drop small items.
Small spread if not wearing a mask
//////////////////////////////////////
*/
@@ -36,4 +37,6 @@ BONUS
var/obj/item/I = M.get_active_hand()
if(I && I.w_class == ITEMSIZE_SMALL)
M.drop_item()
if(!M.wear_mask) // Small spread if not wearing a mask
A.spread(2)
return
@@ -33,7 +33,7 @@ Bonus
return
/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A)
var/get_damage = (sqrtor0(20+A.totalStageSpeed())*(1+rand()))
var/get_damage = max(0, (sqrtor0(20+A.totalStageSpeed())*(1+rand())))
M.adjustToxLoss(-get_damage)
return TRUE
@@ -144,7 +144,7 @@ Bonus
level = 5
/datum/symptom/heal/dna/Heal(var/mob/living/carbon/M, var/datum/disease/advance/A)
var/amt_healed = (sqrtor0(20+A.totalStageSpeed()*(3+rand())))-(sqrtor0(16+A.totalStealth()*rand()))
M.apply_damage(-amt_healed, CLONE)
var/amt_healed = max(0, (sqrtor0(20+A.totalStageSpeed()*(3+rand())))-(sqrtor0(16+A.totalStealth()*rand())))
M.adjustBrainLoss(-amt_healed)
M.radiation = max(M.radiation - 3, 0)
return TRUE
@@ -30,14 +30,14 @@ Bonus
var/mob/living/M = A.affected_mob
if(A.stage >= 3)
M.slurring = min(0, M.slurring-4)
M.druggy = min(0, M.druggy-4)
M.slurring = max(0, M.slurring-4)
M.druggy = max(0, M.druggy-4)
M.reagents.remove_reagent("ethanol", 3)
if(A.stage >= 4)
M.drowsyness = min(0, M.drowsyness-4)
M.drowsyness = max(0, M.drowsyness-4)
if(M.reagents.has_reagent("bliss"))
M.reagents.del_reagent("bliss")
M.hallucination = min(0, M.hallucination-4)
M.hallucination = max(0, M.hallucination-4)
if(A.stage >= 5)
if(M.reagents.get_reagent_amount("alkysine") < 10)
M.reagents.add_reagent("alkysine", 5)
@@ -34,8 +34,10 @@ Bonus
M.emote("sniff")
else
M.emote("sneeze")
A.spread(5)
if(prob(30))
if(!M.wear_mask) // Spread only if they're not covering their face
A.spread(5)
if(prob(30) && !M.wear_mask) // Same for mucus
var/obj/effect/decal/cleanable/mucus/icky = new(get_turf(M))
icky.viruses |= A.Copy()
+3 -2
View File
@@ -3,8 +3,9 @@
max_stages = 3
spread_text = "Airborne"
spread_flags = AIRBORNE
cure_text = "Rest & Spaceacilin"
cures = list("spaceacilin")
cure_text = "Rest & Spaceacillin"
cures = list("spaceacillin", "chicken_soup")
needs_all_cures = FALSE
agent = "XY-rhinovirus"
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
permeability_mod = 0.5
+3 -2
View File
@@ -2,8 +2,9 @@
name = "The Flu"
max_stages = 3
spread_text = "Airborne"
cure_text = "Spaceacilin"
cures = list("spaceacilin")
cure_text = "Spaceacillin"
cures = list("spaceacillin", "chicken_soup")
needs_all_cures = FALSE
cure_chance = 10
agent = "H13N1 flu virion"
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
+2 -2
View File
@@ -4,9 +4,9 @@
stage_prob = 2
spread_text = "Blood and close contact"
spread_flags = BLOOD
cure_text = "Spaceacilin"
cure_text = "Spaceacillin"
agent = "Chimera cells"
cures = list("spaceacilin")
cures = list("spaceacillin")
cure_chance = 10
viable_mobtypes = list(/mob/living/carbon/human)
desc = "If left untreated, subject will become a xenochimera upon perishing."
@@ -0,0 +1,32 @@
/**
Stack End Detector.
Can detect if a given code stack has exited, used by the mc for stack overflow detection.
**/
/datum/stack_end_detector
var/datum/weakref/_WF
var/datum/stack_canary/_canary
/datum/stack_end_detector/New()
_canary = new()
_WF = WEAKREF(_canary)
/** Prime the stack overflow detector.
Store the return value of this proc call in a proc level var.
Can only be called once.
**/
/datum/stack_end_detector/proc/prime_canary()
if (!_canary)
CRASH("Prime_canary called twice")
. = _canary
_canary = null
/// Returns true if the stack is still going. Calling before the canary has been primed also returns true
/datum/stack_end_detector/proc/check()
return !!_WF.resolve()
/// Stack canary. Will go away if the stack it was primed by is ended by byond for return or stack overflow reasons.
/datum/stack_canary
/// empty proc to avoid warnings about unused variables. Call this proc on your canary in the stack it's watching.
/datum/stack_canary/proc/use_variable()
+12 -3
View File
@@ -5,7 +5,6 @@
gloves = /obj/item/clothing/gloves/black
mask = /obj/item/clothing/mask/gas/clown_hat
head = /obj/item/clothing/head/chaplain_hood
l_ear = /obj/item/radio/headset
glasses = /obj/item/clothing/glasses/thermal/plain/monocle
suit = /obj/item/clothing/suit/storage/hooded/chaplain_hoodie
r_pocket = /obj/item/bikehorn
@@ -15,6 +14,10 @@
id_type = /obj/item/card/id/syndicate/station_access
id_pda_assignment = "Tunnel Clown!"
headset = /obj/item/radio/headset
headset_alt = /obj/item/radio/headset/alt
headset_earbud = /obj/item/radio/headset/earbud
/decl/hierarchy/outfit/masked_killer
name = "Masked Killer"
uniform = /obj/item/clothing/under/overalls
@@ -22,13 +25,16 @@
gloves = /obj/item/clothing/gloves/sterile/latex
mask = /obj/item/clothing/mask/surgical
head = /obj/item/clothing/head/welding
l_ear = /obj/item/radio/headset
glasses = /obj/item/clothing/glasses/thermal/plain/monocle
suit = /obj/item/clothing/suit/storage/apron
l_pocket = /obj/item/material/knife/tacknife
r_pocket = /obj/item/surgical/scalpel
r_hand = /obj/item/material/twohanded/fireaxe
headset = /obj/item/radio/headset
headset_alt = /obj/item/radio/headset/alt
headset_earbud = /obj/item/radio/headset/earbud
/decl/hierarchy/outfit/masked_killer/post_equip(var/mob/living/carbon/human/H)
var/victim = get_mannequin(H.ckey)
for(var/obj/item/carried_item in H.get_equipped_items(TRUE))
@@ -39,7 +45,6 @@
uniform = /obj/item/clothing/under/suit_jacket{ starting_accessories=list(/obj/item/clothing/accessory/wcoat) }
shoes = /obj/item/clothing/shoes/black
gloves = /obj/item/clothing/gloves/black
l_ear = /obj/item/radio/headset
glasses = /obj/item/clothing/glasses/sunglasses
l_pocket = /obj/item/melee/energy/sword
mask = /obj/item/clothing/mask/gas/clown_hat
@@ -49,6 +54,10 @@
pda_slot = slot_belt
pda_type = /obj/item/pda/heads
headset = /obj/item/radio/headset
headset_alt = /obj/item/radio/headset/alt
headset_earbud = /obj/item/radio/headset/earbud
/decl/hierarchy/outfit/professional/post_equip(var/mob/living/carbon/human/H)
var/obj/item/storage/secure/briefcase/sec_briefcase = new(H)
for(var/obj/item/briefcase_item in sec_briefcase)
+8 -2
View File
@@ -4,24 +4,30 @@
gloves = /obj/item/clothing/gloves/white
shoes = /obj/item/clothing/shoes/laceup
head = /obj/item/clothing/head/beret/centcom/officer
l_ear = /obj/item/radio/headset/centcom
glasses = /obj/item/clothing/glasses/omnihud/all
id_type = /obj/item/card/id/centcom
pda_type = /obj/item/pda/centcom
flags = OUTFIT_EXTENDED_SURVIVAL|OUTFIT_COMPREHENSIVE_SURVIVAL
headset = /obj/item/radio/headset/centcom
headset_alt = /obj/item/radio/headset/centcom
headset_earbud = /obj/item/radio/headset/centcom
/decl/hierarchy/outfit/job/emergency_responder
name = OUTFIT_JOB_NAME("Emergency Responder")
uniform = /obj/item/clothing/under/ert
shoes = /obj/item/clothing/shoes/boots/swat
gloves = /obj/item/clothing/gloves/swat
l_ear = /obj/item/radio/headset/ert
glasses = /obj/item/clothing/glasses/sunglasses
back = /obj/item/storage/backpack/satchel
id_type = /obj/item/card/id/centcom/ERT
pda_type = /obj/item/pda/centcom
flags = OUTFIT_EXTENDED_SURVIVAL|OUTFIT_COMPREHENSIVE_SURVIVAL
headset = /obj/item/radio/headset/ert
headset_alt = /obj/item/radio/headset/ert
headset_earbud = /obj/item/radio/headset/ert
/decl/hierarchy/outfit/job/emergency_responder/post_equip(var/mob/living/carbon/human/H)
..()
ert.add_antagonist(H.mind)
+3 -1
View File
@@ -2,4 +2,6 @@
name = "Military Uniform"
hierarchy_type = /decl/hierarchy/outfit/military
l_ear = /obj/item/radio/headset
headset = /obj/item/radio/headset
headset_alt = /obj/item/radio/headset
headset_earbud = /obj/item/radio/headset
+8 -2
View File
@@ -29,7 +29,6 @@
/decl/hierarchy/outfit/soviet_soldier/admiral
name = "Soviet admiral"
head = /obj/item/clothing/head/hgpiratecap
l_ear = /obj/item/radio/headset/heads/captain
glasses = /obj/item/clothing/glasses/thermal/plain/eyepatch
suit = /obj/item/clothing/suit/hgpirate
@@ -37,10 +36,13 @@
id_type = /obj/item/card/id/centcom //station
id_pda_assignment = "Admiral"
headset = /obj/item/radio/headset/heads/captain
headset_alt = /obj/item/radio/headset/heads/captain
headset_earbud = /obj/item/radio/headset/heads/captain
/decl/hierarchy/outfit/merchant
name = "Merchant"
shoes = /obj/item/clothing/shoes/black
l_ear = /obj/item/radio/headset
uniform = /obj/item/clothing/under/color/grey
id_slot = slot_wear_id
id_type = /obj/item/card/id/civilian //merchant
@@ -48,6 +50,10 @@
pda_type = /obj/item/pda/chef //cause I like the look
id_pda_assignment = "Merchant"
headset = /obj/item/radio/headset
headset_alt = /obj/item/radio/headset
headset_earbud = /obj/item/radio/headset
/decl/hierarchy/outfit/merchant/vox
name = "Merchant - Vox"
shoes = /obj/item/clothing/shoes/boots/jackboots/toeless
+12 -3
View File
@@ -3,7 +3,6 @@
uniform = /obj/item/clothing/under/rank/centcom
shoes = /obj/item/clothing/shoes/laceup
gloves = /obj/item/clothing/gloves/white
l_ear = /obj/item/radio/headset/heads/hop
glasses = /obj/item/clothing/glasses/sunglasses
id_slot = slot_wear_id
@@ -11,6 +10,10 @@
pda_slot = slot_r_store
pda_type = /obj/item/pda/heads
headset = /obj/item/radio/headset/heads/hop
headset_alt = /obj/item/radio/headset/heads/hop
headset_earbud = /obj/item/radio/headset/heads/hop
/decl/hierarchy/outfit/nanotrasen/representative
name = "Nanotrasen representative"
belt = /obj/item/clipboard
@@ -19,14 +22,20 @@
/decl/hierarchy/outfit/nanotrasen/officer
name = "Nanotrasen officer"
head = /obj/item/clothing/head/beret/centcom/officer
l_ear = /obj/item/radio/headset/heads/captain
belt = /obj/item/gun/energy
id_pda_assignment = "NanoTrasen Navy Officer"
headset = /obj/item/radio/headset/heads/captain
headset_alt = /obj/item/radio/headset/heads/captain
headset_earbud = /obj/item/radio/headset/heads/captain
/decl/hierarchy/outfit/nanotrasen/captain
name = "Nanotrasen captain"
uniform = /obj/item/clothing/under/rank/centcom_captain
l_ear = /obj/item/radio/headset/heads/captain
head = /obj/item/clothing/head/beret/centcom/captain
belt = /obj/item/gun/energy
id_pda_assignment = "NanoTrasen Navy Captain"
headset = /obj/item/radio/headset/heads/captain
headset_alt = /obj/item/radio/headset/heads/captain
headset_earbud = /obj/item/radio/headset/heads/captain
+20 -5
View File
@@ -3,7 +3,6 @@
uniform = /obj/item/clothing/under/solgov/utility/army/urban
shoes = /obj/item/clothing/shoes/boots/jackboots
gloves = /obj/item/clothing/gloves/combat
l_ear = /obj/item/radio/headset/centcom
r_pocket = /obj/item/ammo_magazine/m95
l_pocket = /obj/item/ammo_magazine/m95
l_hand = /obj/item/ammo_magazine/m95
@@ -15,6 +14,10 @@
suit = /obj/item/clothing/suit/armor/combat/USDF
belt = /obj/item/storage/belt/security/tactical
headset = /obj/item/radio/headset/centcom
headset_alt = /obj/item/radio/headset/centcom
headset_earbud = /obj/item/radio/headset/centcom
/decl/hierarchy/outfit/USDF/Marine/equip_id(mob/living/carbon/human/H)
var/obj/item/card/id/C = ..()
C.name = "[H.real_name]'s military ID Card"
@@ -29,7 +32,6 @@
name = "USDF officer"
head = /obj/item/clothing/head/dress/army/command
shoes = /obj/item/clothing/shoes/boots/jackboots
l_ear = /obj/item/radio/headset/centcom
uniform = /obj/item/clothing/under/solgov/mildress/army/command
back = /obj/item/storage/backpack/satchel
belt = /obj/item/gun/projectile/revolver/consul
@@ -38,6 +40,10 @@
r_hand = /obj/item/clothing/accessory/holster/hip
l_hand = /obj/item/clothing/accessory/tie/black
headset = /obj/item/radio/headset/centcom
headset_alt = /obj/item/radio/headset/centcom
headset_earbud = /obj/item/radio/headset/centcom
/decl/hierarchy/outfit/USDF/Officer/equip_id(mob/living/carbon/human/H)
var/obj/item/card/id/C = ..()
C.name = "[H.real_name]'s military ID Card"
@@ -51,7 +57,6 @@
/decl/hierarchy/outfit/solcom/representative
name = "SolCom Representative"
shoes = /obj/item/clothing/shoes/laceup
l_ear = /obj/item/radio/headset/centcom
uniform = /obj/item/clothing/under/suit_jacket/navy
back = /obj/item/storage/backpack/satchel
l_pocket = /obj/item/pen/blue
@@ -59,6 +64,10 @@
r_hand = /obj/item/pda/centcom
l_hand = /obj/item/clipboard
headset = /obj/item/radio/headset/centcom
headset_alt = /obj/item/radio/headset/centcom
headset_earbud = /obj/item/radio/headset/centcom
/decl/hierarchy/outfit/solcom/representative/equip_id(mob/living/carbon/human/H)
var/obj/item/card/id/C = ..()
C.name = "[H.real_name]'s SolCom ID Card"
@@ -74,7 +83,6 @@
head = /obj/item/clothing/head/helmet/combat/imperial
shoes =/obj/item/clothing/shoes/leg_guard/combat/imperial
gloves = /obj/item/clothing/gloves/arm_guard/combat/imperial
l_ear = /obj/item/radio/headset/syndicate
uniform = /obj/item/clothing/under/imperial
mask = /obj/item/clothing/mask/gas/imperial
suit = /obj/item/clothing/suit/armor/combat/imperial
@@ -86,12 +94,15 @@
l_hand = /obj/item/shield/energy/imperial
suit_store = /obj/item/gun/energy/imperial
headset = /obj/item/radio/headset/syndicate
headset_alt = /obj/item/radio/headset/syndicate
headset_earbud = /obj/item/radio/headset/syndicate
/decl/hierarchy/outfit/imperial/officer
name = "Imperial officer"
head = /obj/item/clothing/head/helmet/combat/imperial/centurion
shoes = /obj/item/clothing/shoes/leg_guard/combat/imperial
gloves = /obj/item/clothing/gloves/arm_guard/combat/imperial
l_ear = /obj/item/radio/headset/syndicate
uniform = /obj/item/clothing/under/imperial
mask = /obj/item/clothing/mask/gas/imperial
suit = /obj/item/clothing/suit/armor/combat/imperial/centurion
@@ -102,6 +113,10 @@
l_hand = /obj/item/shield/energy/imperial
suit_store = /obj/item/gun/energy/imperial
headset = /obj/item/radio/headset/syndicate
headset_alt = /obj/item/radio/headset/syndicate
headset_earbud = /obj/item/radio/headset/syndicate
/*
SOUTHERN CROSS OUTFITS
Keep outfits simple. Spawn with basic uniforms and minimal gear. Gear instead goes in lockers. Keep this in mind if editing.
+12 -3
View File
@@ -2,7 +2,6 @@
name = "Special ops - Officer"
uniform = /obj/item/clothing/under/syndicate/combat
suit = /obj/item/clothing/suit/armor/swat/officer
l_ear = /obj/item/radio/headset/ert
glasses = /obj/item/clothing/glasses/thermal/plain/eyepatch
mask = /obj/item/clothing/mask/smokable/cigarette/cigar/havana
head = /obj/item/clothing/head/beret //deathsquad
@@ -16,6 +15,10 @@
id_desc = "Special operations ID."
id_pda_assignment = "Special Operations Officer"
headset = /obj/item/radio/headset/ert
headset_alt = /obj/item/radio/headset/ert
headset_earbud = /obj/item/radio/headset/ert
/decl/hierarchy/outfit/spec_op_officer/space
name = "Special ops - Officer in space"
suit = /obj/item/clothing/suit/armor/swat //obj/item/clothing/suit/space/void/swat
@@ -29,7 +32,6 @@
uniform = /obj/item/clothing/under/ert
shoes = /obj/item/clothing/shoes/boots/swat
gloves = /obj/item/clothing/gloves/swat
l_ear = /obj/item/radio/headset/ert
belt = /obj/item/gun/energy/gun
glasses = /obj/item/clothing/glasses/sunglasses
back = /obj/item/storage/backpack/satchel
@@ -37,6 +39,10 @@
id_slot = slot_wear_id
id_type = /obj/item/card/id/centcom/ERT
headset = /obj/item/radio/headset/ert
headset_alt = /obj/item/radio/headset/ert
headset_earbud = /obj/item/radio/headset/ert
/decl/hierarchy/outfit/death_command
name = "Spec ops - Death commando"
@@ -55,7 +61,6 @@
name = "Spec ops - Mercenary"
uniform = /obj/item/clothing/under/syndicate
shoes = /obj/item/clothing/shoes/boots/combat
l_ear = /obj/item/radio/headset/syndicate
belt = /obj/item/storage/belt/security
glasses = /obj/item/clothing/glasses/sunglasses
gloves = /obj/item/clothing/gloves/swat
@@ -66,4 +71,8 @@
id_type = /obj/item/card/id/syndicate
id_pda_assignment = "Mercenary"
headset = /obj/item/radio/headset/syndicate
headset_alt = /obj/item/radio/headset/alt/syndicate
headset_earbud = /obj/item/radio/headset/earbud/syndicate
flags = OUTFIT_HAS_BACKPACK
+4 -1
View File
@@ -1,7 +1,6 @@
/decl/hierarchy/outfit/wizard
uniform = /obj/item/clothing/under/color/lightpurple
shoes = /obj/item/clothing/shoes/sandal
l_ear = /obj/item/radio/headset
r_pocket = /obj/item/teleportation_scroll
l_hand = /obj/item/staff
r_hand = /obj/item/spellbook
@@ -9,6 +8,10 @@
backpack_contents = list(/obj/item/storage/box = 1)
hierarchy_type = /decl/hierarchy/outfit/wizard
headset = /obj/item/radio/headset
headset_alt = /obj/item/radio/headset
headset_earbud = /obj/item/radio/headset
/decl/hierarchy/outfit/wizard/blue
name = "Wizard - Blue"
head = /obj/item/clothing/head/wizard
+7
View File
@@ -95,6 +95,13 @@
containername = "Chicken crate"
access = access_hydroponics
/datum/supply_pack/hydro/turkey
name = "Turkey crate"
cost = 25
containertype = /obj/structure/largecrate/animal/turkey
containername = "Turkey crate"
access = access_hydroponics
/datum/supply_pack/hydro/seeds
name = "Seeds crate"
contains = list(
+27
View File
@@ -0,0 +1,27 @@
///like normal callbacks but they also record their creation time for measurement purposes
///they also require the same usr/user that made the callback to both still exist and to still have a client in order to execute
/datum/callback/verb_callback
///the tick this callback datum was created in. used for testing latency
var/creation_time = 0
/datum/callback/verb_callback/New(thingtocall, proctocall, ...)
creation_time = DS2TICKS(world.time)
. = ..()
#ifndef UNIT_TEST
/datum/callback/verb_callback/Invoke(...)
var/mob/our_user = user?.resolve()
if(QDELETED(our_user) || isnull(our_user.client))
return
var/mob/temp = usr
. = ..()
usr = temp
/datum/callback/verb_callback/InvokeAsync(...)
var/mob/our_user = user?.resolve()
if(QDELETED(our_user) || isnull(our_user.client))
return
var/mob/temp = usr
. = ..()
usr = temp
#endif
+11 -12
View File
@@ -153,24 +153,23 @@
data["status"] = status
return data
/datum/wires/tgui_act(action, list/params)
/datum/wires/tgui_act(action, list/params, datum/tgui/ui)
if(..())
return TRUE
var/mob/user = usr
if(!interactable(user))
if(!interactable(ui.user))
return
var/obj/item/I = user.get_active_hand()
var/obj/item/I = ui.user.get_active_hand()
var/color = lowertext(params["wire"])
holder.add_hiddenprint(user)
holder.add_hiddenprint(ui.user)
switch(action)
// Toggles the cut/mend status.
if("cut")
// if(!I.has_tool_quality(TOOL_WIRECUTTER) && !user.can_admin_interact())
if(!istype(I) || !I.has_tool_quality(TOOL_WIRECUTTER))
to_chat(user, span_warning("You need wirecutters!"))
to_chat(ui.user, span_warning("You need wirecutters!"))
return
playsound(holder, I.usesound, 20, 1)
@@ -181,7 +180,7 @@
if("pulse")
// if(!I.has_tool_quality(TOOL_MULTITOOL) && !user.can_admin_interact())
if(!istype(I) || !I.has_tool_quality(TOOL_MULTITOOL))
to_chat(user, span_warning("You need a multitool!"))
to_chat(ui.user, span_warning("You need a multitool!"))
return
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
@@ -189,7 +188,7 @@
// If they pulse the electrify wire, call interactable() and try to shock them.
if(get_wire(color) == WIRE_ELECTRIFY)
interactable(user)
interactable(ui.user)
return TRUE
@@ -198,18 +197,18 @@
if(is_attached(color))
var/obj/item/O = detach_assembly(color)
if(O)
user.put_in_hands(O)
ui.user.put_in_hands(O)
return TRUE
if(!istype(I, /obj/item/assembly/signaler))
to_chat(user, span_warning("You need a remote signaller!"))
to_chat(ui.user, span_warning("You need a remote signaller!"))
return
if(user.unEquip(I))
if(ui.user.unEquip(I))
attach_assembly(color, I)
return TRUE
else
to_chat(user, span_warning("[I] is stuck to your hand!"))
to_chat(ui.user, span_warning("[I] is stuck to your hand!"))
/**
* Proc called to determine if the user can see wire define information, such as "Contraband", "Door Bolts", etc.
+5 -5
View File
@@ -325,13 +325,13 @@
throw_speed = 4
throw_range = 20
/obj/item/camera_bug/attack_self(mob/usr as mob)
/obj/item/camera_bug/attack_self(mob/user as mob)
var/list/cameras = new/list()
for (var/obj/machinery/camera/C in cameranet.cameras)
if (C.bugged && C.status)
cameras.Add(C)
if (length(cameras) == 0)
to_chat(usr, span_warning("No bugged functioning cameras found."))
to_chat(user, span_warning("No bugged functioning cameras found."))
return
var/list/friendly_cameras = new/list()
@@ -339,16 +339,16 @@
for (var/obj/machinery/camera/C in cameras)
friendly_cameras.Add(C.c_tag)
var/target = tgui_input_list(usr, "Select the camera to observe", "Select Camera", friendly_cameras)
var/target = tgui_input_list(user, "Select the camera to observe", "Select Camera", friendly_cameras)
if (!target)
return
for (var/obj/machinery/camera/C in cameras)
if (C.c_tag == target)
target = C
break
if (usr.stat == 2) return
if (user.stat == 2) return
usr.client.eye = target
user.client.eye = target
/*
/obj/item/cigarpacket
+19
View File
@@ -56,6 +56,8 @@ GLOBAL_LIST_EMPTY(areas_by_type)
var/forbid_singulo = FALSE // If true singulo will not move in.
var/no_spoilers = FALSE // If true, makes it much more difficult to see what is inside an area with things like mesons.
var/soundproofed = FALSE // If true, blocks sounds from other areas and prevents hearers on other areas from hearing the sounds within.
var/block_phase_shift = FALSE //Stops phase shifted mobs from entering // RS Port #658
var/block_ghosts = FALSE //Stops ghosts from entering //RS Port #658
/area/New()
// Used by the maploader, this must be done in New, not init
@@ -398,6 +400,7 @@ var/list/mob/living/forced_ambiance_list = new
play_ambience(L, initial = TRUE)
if(no_spoilers)
L.disable_spoiler_vision()
check_phase_shift(M) //RS Port #658
/area/proc/play_ambience(var/mob/living/L, initial = TRUE)
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
@@ -554,3 +557,19 @@ GLOBAL_DATUM(spoiler_obfuscation_image, /image)
add_overlay(GLOB.spoiler_obfuscation_image)
else
cut_overlay(GLOB.spoiler_obfuscation_image)
// RS Port #658 Start
/area/proc/check_phase_shift(var/mob/ourmob)
if(!block_phase_shift || !ourmob.incorporeal_move)
return
if(!isliving(ourmob))
return
if(isanimal(ourmob))
var/mob/living/simple_mob/shadekin/SK = ourmob
if(SK.ability_flags & AB_PHASE_SHIFTED)
SK.phase_in(SK.loc)
if(ishuman(ourmob))
var/mob/living/carbon/human/SK = ourmob
if(SK.ability_flags & AB_PHASE_SHIFTED)
SK.phase_in(SK.loc)
// RS Port #658 End
+3 -3
View File
@@ -449,17 +449,17 @@
return data
/obj/machinery/computer/scan_consolenew/tgui_act(action, params)
/obj/machinery/computer/scan_consolenew/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
if(!istype(usr.loc, /turf))
if(!istype(ui.user.loc, /turf))
return TRUE
if(!src || !src.connected)
return TRUE
if(irradiating) // Make sure that it isn't already irradiating someone...
return TRUE
add_fingerprint(usr)
add_fingerprint(ui.user)
if(tgui_act_modal(action, params))
return TRUE
@@ -22,7 +22,7 @@
to_chat(src, span_notice("We return our vocal glands to their original location."))
return
var/mimic_voice = sanitize(tgui_input_text(usr, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN), MAX_NAME_LEN)
var/mimic_voice = sanitize(tgui_input_text(src, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN), MAX_NAME_LEN)
if(!mimic_voice)
return
+12 -13
View File
@@ -315,8 +315,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
/obj/item/book/tome/attack_self(mob/living/user as mob)
usr = user
if(!usr.canmove || usr.stat || usr.restrained())
if(!user.canmove || user.stat || user.restrained())
return
if(!cultwords["travel"])
@@ -337,11 +336,11 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
if("Cancel", null)
return
if("Read it")
if(usr.get_active_hand() != src)
if(user.get_active_hand() != src)
return
user << browse("[tomedat]", "window=Arcane Tome")
return
if(usr.get_active_hand() != src)
if(user.get_active_hand() != src)
return
var/list/dictionary = list (
@@ -386,7 +385,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
var/chosen_rune = null
if(usr)
if(user)
chosen_rune = input ("Choose a rune to scribe.") in scribewords
if (!chosen_rune)
return
@@ -398,7 +397,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
if (chosen_rune == "teleport other")
dictionary[chosen_rune] += input ("Choose a destination word") in english
if(usr.get_active_hand() != src)
if(user.get_active_hand() != src)
return
for (var/mob/V in viewers(src))
@@ -408,7 +407,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
if(do_after(user, 50))
var/area/A = get_area(user)
log_and_message_admins("created \an [chosen_rune] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].")
if(usr.get_active_hand() != src)
if(user.get_active_hand() != src)
return
var/mob/living/carbon/human/H = user
var/obj/effect/rune/R = new /obj/effect/rune(user.loc)
@@ -439,7 +438,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
w_class = ITEMSIZE_SMALL
var/cultistsonly = 1
/obj/item/book/tome/imbued/attack_self(mob/user as mob)
if(src.cultistsonly && !iscultist(usr))
if(src.cultistsonly && !iscultist(user))
return
if(!cultwords["travel"])
runerandom()
@@ -448,7 +447,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
if (!istype(user.loc,/turf))
to_chat(user, span_notice("You do not have enough space to write a proper rune."))
var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "seer", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun")
r = input(usr, "Choose a rune to scribe", "Rune Scribing") in runes // Remains input() for extreme blocking
r = input(user, "Choose a rune to scribe", "Rune Scribing") in runes // Remains input() for extreme blocking
var/obj/effect/rune/R = new /obj/effect/rune
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
@@ -460,8 +459,8 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
if("teleport")
var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri")
var/beacon
if(usr)
beacon = input(usr, "Select the last rune", "Rune Scribing") in words // Remains input() for extreme blocking
if(user)
beacon = input(user, "Select the last rune", "Rune Scribing") in words // Remains input() for extreme blocking
R.word1=cultwords["travel"]
R.word2=cultwords["self"]
R.word3=beacon
@@ -470,8 +469,8 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
if("itemport")
var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri")
var/beacon
if(usr)
beacon = input(usr, "Select the last rune", "Rune Scribing") in words // Remains input() for extreme blocking
if(user)
beacon = input(user, "Select the last rune", "Rune Scribing") in words // Remains input() for extreme blocking
R.word1=cultwords["travel"]
R.word2=cultwords["other"]
R.word3=beacon
+1 -1
View File
@@ -14,7 +14,7 @@
if("armor")
call(/obj/effect/rune/proc/armor)()
if("emp")
call(/obj/effect/rune/proc/emp)(usr.loc,3)
call(/obj/effect/rune/proc/emp)(user.loc,3)
if("conceal")
call(/obj/effect/rune/proc/obscure)(2)
if("revealrunes")
@@ -68,7 +68,7 @@
var/list/sound_options = available_sounds
if(check_for_scepter())
sound_options["!!AIR HORN!!"] = 'sound/items/AirHorn.ogg'
var/new_sound = tgui_input_list(usr, "Select the sound you want to make.", "Sounds", sound_options)
var/new_sound = tgui_input_list(user, "Select the sound you want to make.", "Sounds", sound_options)
if(new_sound)
selected_sound = sound_options[new_sound]
+115
View File
@@ -57,3 +57,118 @@
title_blurb = "A " + JOB_ALT_RESIDENT + " is an individual who resides on the station, frequently in a different part of the station than what is seen. \
They are considered to be part of the crew for most purposes, but have no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/resident
//////////////////////////////////
// Intern
//////////////////////////////////
/datum/job/intern
title = JOB_INTERN
flag = INTERN
departments = list(DEPARTMENT_CIVILIAN)
department_flag = ENGSEC // Ran out of bits
faction = FACTION_STATION
total_positions = -1
spawn_positions = -1
supervisors = "the staff from the department you're interning in"
selection_color = "#555555"
economic_modifier = 2
access = list() //See /datum/job/intern/get_access()
minimal_access = list() //See /datum/job/intern/get_access()
outfit_type = /decl/hierarchy/outfit/job/assistant/intern
alt_titles = list(JOB_ALT_APPRENTICE_ENGINEER = /datum/alt_title/intern_eng,
JOB_ALT_MEDICAL_INTERN = /datum/alt_title/intern_med,
JOB_ALT_RESEARCH_INTERN = /datum/alt_title/intern_sci,
JOB_ALT_SECURITY_CADET = /datum/alt_title/intern_sec,
JOB_ALT_JR_CARGO_TECH = /datum/alt_title/intern_crg,
JOB_ALT_SERVER = /datum/alt_title/server,
JOB_ALT_ASSISTANT = /datum/alt_title/assistant)
job_description = "An " + JOB_INTERN + " does whatever is requested of them, often doing so in process of learning \
another job. Though they are part of the crew, they have no real authority."
timeoff_factor = 0 // Interns, noh
requestable = FALSE
/datum/alt_title/intern_eng
title = JOB_ALT_APPRENTICE_ENGINEER
title_blurb = "An " + JOB_ALT_APPRENTICE_ENGINEER + " attempts to provide whatever the Engineering department needs. They are not proper Engineers, and are \
often in training to become an Engineer. An " + JOB_ALT_APPRENTICE_ENGINEER + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/engineer
/datum/alt_title/intern_med
title = JOB_ALT_MEDICAL_INTERN
title_blurb = "A " + JOB_ALT_MEDICAL_INTERN + " attempts to provide whatever the Medical department needs. They are not proper Doctors, and are \
often in training to become a Doctor. A " + JOB_ALT_MEDICAL_INTERN + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/medic
/datum/alt_title/intern_sci
title = JOB_ALT_RESEARCH_INTERN
title_blurb = "A " + JOB_ALT_RESEARCH_INTERN + " attempts to provide whatever the Research department needs. They are not proper " + JOB_SCIENTIST + "s, and are \
often in training to become a " + JOB_SCIENTIST + ". A " + JOB_ALT_RESEARCH_INTERN + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/scientist
/datum/alt_title/intern_sec
title = JOB_ALT_SECURITY_CADET
title_blurb = "A " + JOB_ALT_SECURITY_CADET + " attempts to provide whatever the Security department needs. They are not proper Officers, and are \
often in training to become an Officer. A " + JOB_ALT_SECURITY_CADET + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/officer
/datum/alt_title/intern_crg
title = JOB_ALT_JR_CARGO_TECH
title_blurb = "A " + JOB_ALT_JR_CARGO_TECH + " attempts to provide whatever the Cargo department needs. They are not proper Cargo Technicians, and are \
often in training to become a " + JOB_CARGO_TECHNICIAN + ". A " + JOB_ALT_JR_CARGO_TECH + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/cargo
/*
/datum/alt_title/intern_exp
title = "Jr. " + JOB_EXPLORER + ""
title_blurb = "A Jr. " + JOB_EXPLORER + " attempts to provide whatever the Exploration department needs. They are not proper " + JOB_EXPLORER + "s, and are \
often in training to become an " + JOB_EXPLORER + ". A Jr. " + JOB_EXPLORER + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/explorer
*/
/datum/alt_title/server
title = JOB_ALT_SERVER
title_blurb = "A " + JOB_ALT_SERVER + " helps out kitchen and diner staff with various tasks, primarily food delivery. A " + JOB_ALT_SERVER + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/service/server
/datum/alt_title/assistant
title = JOB_ALT_ASSISTANT
title_blurb = "An " + JOB_ALT_ASSISTANT + " helps out wherever they might be needed. They have no authority, but can volunteer to help if help is needed."
title_outfit = /decl/hierarchy/outfit/job/service/server
/datum/job/intern/New()
..()
if(config)
total_positions = CONFIG_GET(number/limit_interns)
spawn_positions = CONFIG_GET(number/limit_interns)
/datum/job/intern/get_access()
if(CONFIG_GET(flag/assistant_maint))
return list(access_maint_tunnels)
else
return list()
//////////////////////////////////
// Visitor
//////////////////////////////////
/datum/job/assistant // Visitor
title = JOB_ALT_VISITOR
supervisors = "nobody! You don't work here"
job_description = "A " + JOB_ALT_VISITOR + " is just there to visit the place. They have no real authority or responsibility."
timeoff_factor = 0
requestable = FALSE
alt_titles = list("Guest" = /datum/alt_title/guest, "Traveler" = /datum/alt_title/traveler)
/datum/job/assistant/New()
..()
if(config)
total_positions = CONFIG_GET(number/limit_visitors)
spawn_positions = CONFIG_GET(number/limit_visitors)
/datum/job/assistant/get_access()
return list()
/datum/alt_title/guest
title = "Guest"
/datum/alt_title/traveler
title = "Traveler"
-115
View File
@@ -1,115 +0,0 @@
//////////////////////////////////
// Intern
//////////////////////////////////
/datum/job/intern
title = JOB_INTERN
flag = INTERN
departments = list(DEPARTMENT_CIVILIAN)
department_flag = ENGSEC // Ran out of bits
faction = FACTION_STATION
total_positions = -1
spawn_positions = -1
supervisors = "the staff from the department you're interning in"
selection_color = "#555555"
economic_modifier = 2
access = list() //See /datum/job/intern/get_access()
minimal_access = list() //See /datum/job/intern/get_access()
outfit_type = /decl/hierarchy/outfit/job/assistant/intern
alt_titles = list(JOB_ALT_APPRENTICE_ENGINEER = /datum/alt_title/intern_eng,
JOB_ALT_MEDICAL_INTERN = /datum/alt_title/intern_med,
JOB_ALT_RESEARCH_INTERN = /datum/alt_title/intern_sci,
JOB_ALT_SECURITY_CADET = /datum/alt_title/intern_sec,
JOB_ALT_JR_CARGO_TECH = /datum/alt_title/intern_crg,
JOB_ALT_SERVER = /datum/alt_title/server,
JOB_ALT_ASSISTANT = /datum/alt_title/assistant)
job_description = "An " + JOB_INTERN + " does whatever is requested of them, often doing so in process of learning \
another job. Though they are part of the crew, they have no real authority."
timeoff_factor = 0 // Interns, noh
requestable = FALSE
/datum/alt_title/intern_eng
title = JOB_ALT_APPRENTICE_ENGINEER
title_blurb = "An " + JOB_ALT_APPRENTICE_ENGINEER + " attempts to provide whatever the Engineering department needs. They are not proper Engineers, and are \
often in training to become an Engineer. An " + JOB_ALT_APPRENTICE_ENGINEER + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/engineer
/datum/alt_title/intern_med
title = JOB_ALT_MEDICAL_INTERN
title_blurb = "A " + JOB_ALT_MEDICAL_INTERN + " attempts to provide whatever the Medical department needs. They are not proper Doctors, and are \
often in training to become a Doctor. A " + JOB_ALT_MEDICAL_INTERN + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/medic
/datum/alt_title/intern_sci
title = JOB_ALT_RESEARCH_INTERN
title_blurb = "A " + JOB_ALT_RESEARCH_INTERN + " attempts to provide whatever the Research department needs. They are not proper " + JOB_SCIENTIST + "s, and are \
often in training to become a " + JOB_SCIENTIST + ". A " + JOB_ALT_RESEARCH_INTERN + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/scientist
/datum/alt_title/intern_sec
title = JOB_ALT_SECURITY_CADET
title_blurb = "A " + JOB_ALT_SECURITY_CADET + " attempts to provide whatever the Security department needs. They are not proper Officers, and are \
often in training to become an Officer. A " + JOB_ALT_SECURITY_CADET + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/officer
/datum/alt_title/intern_crg
title = JOB_ALT_JR_CARGO_TECH
title_blurb = "A " + JOB_ALT_JR_CARGO_TECH + " attempts to provide whatever the Cargo department needs. They are not proper Cargo Technicians, and are \
often in training to become a " + JOB_CARGO_TECHNICIAN + ". A " + JOB_ALT_JR_CARGO_TECH + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/cargo
/*
/datum/alt_title/intern_exp
title = "Jr. " + JOB_EXPLORER + ""
title_blurb = "A Jr. " + JOB_EXPLORER + " attempts to provide whatever the Exploration department needs. They are not proper " + JOB_EXPLORER + "s, and are \
often in training to become an " + JOB_EXPLORER + ". A Jr. " + JOB_EXPLORER + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/explorer
*/
/datum/alt_title/server
title = JOB_ALT_SERVER
title_blurb = "A " + JOB_ALT_SERVER + " helps out kitchen and diner staff with various tasks, primarily food delivery. A " + JOB_ALT_SERVER + " has no real authority."
title_outfit = /decl/hierarchy/outfit/job/service/server
/datum/alt_title/assistant
title = JOB_ALT_ASSISTANT
title_blurb = "An " + JOB_ALT_ASSISTANT + " helps out wherever they might be needed. They have no authority, but can volunteer to help if help is needed."
title_outfit = /decl/hierarchy/outfit/job/service/server
/datum/job/intern/New()
..()
if(config)
total_positions = CONFIG_GET(number/limit_interns)
spawn_positions = CONFIG_GET(number/limit_interns)
/datum/job/intern/get_access()
if(CONFIG_GET(flag/assistant_maint))
return list(access_maint_tunnels)
else
return list()
//////////////////////////////////
// Visitor
//////////////////////////////////
/datum/job/assistant // Visitor
title = JOB_ALT_VISITOR
supervisors = "nobody! You don't work here"
job_description = "A " + JOB_ALT_VISITOR + " is just there to visit the place. They have no real authority or responsibility."
timeoff_factor = 0
requestable = FALSE
alt_titles = list("Guest" = /datum/alt_title/guest, "Traveler" = /datum/alt_title/traveler)
/datum/job/assistant/New()
..()
if(config)
total_positions = CONFIG_GET(number/limit_visitors)
spawn_positions = CONFIG_GET(number/limit_visitors)
/datum/job/assistant/get_access()
return list()
/datum/alt_title/guest
title = "Guest"
/datum/alt_title/traveler
title = "Traveler"
+63 -14
View File
@@ -28,11 +28,16 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
ideal_age_by_species = list(SPECIES_HUMAN_VATBORN = 55) /// Vatborn live shorter, no other race eligible for captain besides human/skrell
banned_job_species = list(SPECIES_UNATHI, SPECIES_TAJ, SPECIES_DIONA, SPECIES_PROMETHEAN, SPECIES_ZADDAT, "mechanical", "digital")
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
dept_time_required = 80 //Pending something more complicated
outfit_type = /decl/hierarchy/outfit/job/captain
job_description = "The " + JOB_SITE_MANAGER + " manages the other Command Staff, and through them the rest of the station. Though they have access to everything, \
they do not understand everything, and are expected to delegate tasks to the appropriate crew member. The " + JOB_SITE_MANAGER + " is expected to \
have an understanding of Standard Operating Procedure, and is subject to it, and legal action, in the same way as every other crew member."
alt_titles = list(JOB_ALT_OVERSEER= /datum/alt_title/overseer)
alt_titles = list(JOB_ALT_OVERSEER= /datum/alt_title/overseer, JOB_ALT_FACILITY_DIRECTOR = /datum/alt_title/facility_director, JOB_ALT_CHIEF_SUPERVISOR = /datum/alt_title/chief_supervisor,
JOB_ALT_CAPTAIN = /datum/alt_title/captain)
/*
@@ -45,11 +50,22 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
/datum/job/captain/get_access()
return get_all_station_access().Copy()
/datum/job/captain/get_request_reasons()
return list("Training crew", "Assembling expedition team")
// Captain Alt Titles
/datum/alt_title/overseer
title = JOB_ALT_OVERSEER
/datum/alt_title/facility_director
title = JOB_ALT_FACILITY_DIRECTOR
/datum/alt_title/chief_supervisor
title = JOB_ALT_CHIEF_SUPERVISOR
/datum/alt_title/captain
title = JOB_ALT_CAPTAIN
//////////////////////////////////
// Head of Personnel
//////////////////////////////////
@@ -75,29 +91,42 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
ideal_age_by_species = list(SPECIES_UNATHI = 140, SPECIES_TESHARI = 27, "mechanical" = 20, SPECIES_HUMAN_VATBORN = 20)
banned_job_species = list(SPECIES_PROMETHEAN, SPECIES_ZADDAT, "digital", SPECIES_DIONA)
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
departments = list(DEPARTMENT_COMMAND, DEPARTMENT_CIVILIAN)
departments_managed = list(DEPARTMENT_CIVILIAN, DEPARTMENT_CARGO, DEPARTMENT_PLANET)
dept_time_required = 60
outfit_type = /decl/hierarchy/outfit/job/hop
job_description = "The " + JOB_HEAD_OF_PERSONNEL + " manages the Service department, the Exploration team, and most other civilians. They also \
manage the Supply department, through the " + JOB_QUARTERMASTER + ". In addition, the " + JOB_HEAD_OF_PERSONNEL + " oversees the personal accounts \
of the crew, including their money and access. If necessary, the " + JOB_HEAD_OF_PERSONNEL + " is first in line to assume Acting Command."
alt_titles = list(JOB_ALT_CREW_RESOURCE_OFFICER = /datum/alt_title/cro)
access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
access_hop, access_RC_announce, access_keycard_auth, access_gateway)
minimal_access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
access_hop, access_RC_announce, access_keycard_auth, access_gateway)
access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers, access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway, access_entertainment)
minimal_access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway, access_entertainment)
alt_titles = list(JOB_ALT_CREW_RESOURCE_OFFICER = /datum/alt_title/cro, JOB_ALT_DEPUTY_MANAGER = /datum/alt_title/deputy_manager, JOB_ALT_STAFF_MANAGER = /datum/alt_title/staff_manager,
JOB_ALT_FACILITY_STEWARD = /datum/alt_title/facility_steward, JOB_ALT_FIRST_MATE = /datum/alt_title/first_mate)
/datum/job/hop/get_request_reasons()
return list("ID modification", "Training crew", "Assembling expedition team")
// HOP Alt Titles
/datum/alt_title/cro
title = JOB_ALT_CREW_RESOURCE_OFFICER
/datum/alt_title/deputy_manager
title = JOB_ALT_DEPUTY_MANAGER
/datum/alt_title/staff_manager
title = JOB_ALT_STAFF_MANAGER
/datum/alt_title/facility_steward
title = JOB_ALT_FACILITY_STEWARD
/datum/alt_title/first_mate
title = JOB_ALT_FIRST_MATE
//////////////////////////////////
// Command Secretary
//////////////////////////////////
@@ -116,9 +145,29 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
minimal_player_age = 5
economic_modifier = 7
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
alt_titles = list(JOB_ALT_COMMAND_LIAISON = /datum/alt_title/command_liaison, JOB_ALT_COMMAND_ASSISTANT = /datum/alt_title/command_assistant, JOB_ALT_COMMAND_INTERN = /datum/alt_title/command_intern,
JOB_ALT_BRIDGE_SECRETARY = /datum/alt_title/bridge_secretary, JOB_ALT_BRIDGE_ASSISTANT = /datum/alt_title/bridge_assistant)
access = list(access_heads, access_keycard_auth)
minimal_access = list(access_heads, access_keycard_auth)
outfit_type = /decl/hierarchy/outfit/job/secretary
job_description = "A " + JOB_COMMAND_SECRETARY + " handles paperwork duty for the Heads of Staff, so they can better focus on managing their departments. \
They are not Heads of Staff, and have no real authority."
/datum/alt_title/command_liaison
title = JOB_ALT_COMMAND_LIAISON
/datum/alt_title/command_assistant
title = JOB_ALT_COMMAND_ASSISTANT
/datum/alt_title/command_intern
title = JOB_ALT_COMMAND_INTERN
/datum/alt_title/bridge_secretary
title = JOB_ALT_BRIDGE_SECRETARY
/datum/alt_title/bridge_assistant
title = JOB_ALT_BRIDGE_ASSISTANT
-78
View File
@@ -1,78 +0,0 @@
/datum/job/captain
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
dept_time_required = 80 //Pending something more complicated
alt_titles = list(JOB_ALT_OVERSEER= /datum/alt_title/overseer, JOB_ALT_FACILITY_DIRECTOR = /datum/alt_title/facility_director, JOB_ALT_CHIEF_SUPERVISOR = /datum/alt_title/chief_supervisor,
JOB_ALT_CAPTAIN = /datum/alt_title/captain)
/datum/alt_title/facility_director
title = JOB_ALT_FACILITY_DIRECTOR
/datum/alt_title/chief_supervisor
title = JOB_ALT_CHIEF_SUPERVISOR
/datum/alt_title/captain
title = JOB_ALT_CAPTAIN
/datum/job/captain/get_request_reasons()
return list("Training crew", "Assembling expedition team")
/datum/job/hop
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
departments = list(DEPARTMENT_COMMAND, DEPARTMENT_CIVILIAN)
departments_managed = list(DEPARTMENT_CIVILIAN, DEPARTMENT_CARGO, DEPARTMENT_PLANET)
dept_time_required = 60
alt_titles = list(JOB_ALT_CREW_RESOURCE_OFFICER = /datum/alt_title/cro, JOB_ALT_DEPUTY_MANAGER = /datum/alt_title/deputy_manager, JOB_ALT_STAFF_MANAGER = /datum/alt_title/staff_manager,
JOB_ALT_FACILITY_STEWARD = /datum/alt_title/facility_steward, JOB_ALT_FIRST_MATE = /datum/alt_title/first_mate)
access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway, access_entertainment)
minimal_access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway, access_entertainment)
/datum/alt_title/deputy_manager
title = JOB_ALT_DEPUTY_MANAGER
/datum/alt_title/staff_manager
title = JOB_ALT_STAFF_MANAGER
/datum/alt_title/facility_steward
title = JOB_ALT_FACILITY_STEWARD
/datum/alt_title/first_mate
title = JOB_ALT_FIRST_MATE
/datum/job/hop/get_request_reasons()
return list("ID modification", "Training crew", "Assembling expedition team")
/datum/job/secretary
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
alt_titles = list(JOB_ALT_COMMAND_LIAISON = /datum/alt_title/command_liaison, JOB_ALT_COMMAND_ASSISTANT = /datum/alt_title/command_assistant, JOB_ALT_COMMAND_INTERN = /datum/alt_title/command_intern,
JOB_ALT_BRIDGE_SECRETARY = /datum/alt_title/bridge_secretary, JOB_ALT_BRIDGE_ASSISTANT = /datum/alt_title/bridge_assistant)
/datum/alt_title/command_liaison
title = JOB_ALT_COMMAND_LIAISON
/datum/alt_title/command_assistant
title = JOB_ALT_COMMAND_ASSISTANT
/datum/alt_title/command_intern
title = JOB_ALT_COMMAND_INTERN
/datum/alt_title/bridge_secretary
title = JOB_ALT_BRIDGE_SECRETARY
/datum/alt_title/bridge_assistant
title = JOB_ALT_BRIDGE_ASSISTANT
+122
View File
@@ -0,0 +1,122 @@
//Cargo
//////////////////////////////////
// Quartermaster
//////////////////////////////////
/datum/job/qm
title = JOB_QUARTERMASTER
flag = QUARTERMASTER
departments = list(DEPARTMENT_CARGO)
sorting_order = 1 // QM is above the cargo techs, but below the HoP.
departments_managed = list(DEPARTMENT_CARGO)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 1
spawn_positions = 1
pto_type = PTO_CARGO
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#9b633e"
economic_modifier = 5
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station, access_RC_announce)
minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station, access_RC_announce)
banned_job_species = list("digital", SPECIES_PROMETHEAN)
ideal_character_age = 40
dept_time_required = 20
outfit_type = /decl/hierarchy/outfit/job/cargo/qm
job_description = "The " + JOB_QUARTERMASTER + " manages the Supply department, checking cargo orders and ensuring supplies get to where they are needed."
alt_titles = list(JOB_ALT_SUPPLY_CHIEF = /datum/alt_title/supply_chief, JOB_ALT_LOGISTICS_MANAGER = /datum/alt_title/logistics_manager, JOB_ALT_CARGO_SUPERVISOR = /datum/alt_title/cargo_supervisor)
/datum/job/qm/get_request_reasons()
return list("Training crew")
// Quartermaster Alt Titles
/datum/alt_title/supply_chief
title = JOB_ALT_SUPPLY_CHIEF
/datum/alt_title/logistics_manager
title = JOB_ALT_LOGISTICS_MANAGER
/datum/alt_title/cargo_supervisor
title = JOB_ALT_CARGO_SUPERVISOR
//////////////////////////////////
// Cargo Tech
//////////////////////////////////
/datum/job/cargo_tech
title = JOB_CARGO_TECHNICIAN
flag = CARGOTECH
departments = list(DEPARTMENT_CARGO)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 3
spawn_positions = 3
pto_type = PTO_CARGO
supervisors = "the " + JOB_QUARTERMASTER + " and the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#7a4f33"
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_mining, access_mining_station)
minimal_access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting)
outfit_type = /decl/hierarchy/outfit/job/cargo/cargo_tech
job_description = "A " + JOB_CARGO_TECHNICIAN + " fills and delivers cargo orders. They are encouraged to return delivered crates to the Cargo Shuttle, \
because Central Command gives a partial refund."
alt_titles = list(JOB_ALT_CARGO_LOADER = /datum/alt_title/cargo_loader, JOB_ALT_CARGO_HANDLER = /datum/alt_title/cargo_handler, JOB_ALT_SUPPLY_COURIER = /datum/alt_title/supply_courier,
JOB_ALT_DISPOSALS_SORTER = /datum/alt_title/disposal_sorter)
/datum/alt_title/supply_courier
title = JOB_ALT_SUPPLY_COURIER
title_blurb = "A " + JOB_ALT_SUPPLY_COURIER + " is usually tasked with delivering packages or cargo directly to whoever requires it."
/datum/alt_title/cargo_loader
title = JOB_ALT_CARGO_LOADER
title_blurb = "A " + JOB_ALT_CARGO_LOADER + " is usually tasked with more menial labor within Supply department, such as loading and unloading supply shuttle."
/datum/alt_title/cargo_handler
title = JOB_ALT_CARGO_HANDLER
title_blurb = "A " + JOB_ALT_CARGO_HANDLER + " is usually tasked with more menial labor within Supply department, such as loading and unloading supply shuttle."
/datum/alt_title/disposal_sorter
title = JOB_ALT_DISPOSALS_SORTER
title_blurb = "A " + JOB_ALT_DISPOSALS_SORTER + " is usually tasked with operating disposals delivery system, sorting the trash and tagging parcels for delivery."
//////////////////////////////////
// Shaft Miner
//////////////////////////////////
/datum/job/mining
title = JOB_SHAFT_MINER
flag = MINER
departments = list(DEPARTMENT_CARGO)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 4
spawn_positions = 4
pto_type = PTO_CARGO
supervisors = "the " + JOB_QUARTERMASTER + " and the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#7a4f33"
economic_modifier = 5
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_mining, access_mining_station)
minimal_access = list(access_mining, access_mining_station, access_mailsorting)
outfit_type = /decl/hierarchy/outfit/job/cargo/mining
job_description = "A " + JOB_SHAFT_MINER + " mines and processes minerals to be delivered to departments that need them."
alt_titles = list(JOB_ALT_DEEP_SPACE_MINER = /datum/alt_title/deep_space_miner, JOB_ALT_DRILL_TECHNICIAN = /datum/alt_title/drill_tech, JOB_ALT_PROSPECTOR = /datum/alt_title/prospector,
JOB_ALT_EXCAVATOR = /datum/alt_title/excavator)
/datum/job/mining/get_request_reasons()
return list("Assembling expedition team")
/datum/alt_title/drill_tech
title = JOB_ALT_DRILL_TECHNICIAN
title_blurb = "A " + JOB_ALT_DRILL_TECHNICIAN + " specializes in operating and maintaining the machinery needed to extract ore from veins deep below the surface."
/datum/alt_title/deep_space_miner
title = JOB_ALT_DEEP_SPACE_MINER
title_blurb = "A " + JOB_ALT_DEEP_SPACE_MINER + " specializes primarily in mining operations in zero-g environments, mostly in asteroid and debris fields."
/datum/alt_title/prospector
title = JOB_ALT_PROSPECTOR
/datum/alt_title/excavator
title = JOB_ALT_EXCAVATOR
+315 -87
View File
@@ -12,6 +12,7 @@
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
pto_type = PTO_CIVILIAN
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list(access_hydroponics, access_bar, access_kitchen)
@@ -19,7 +20,7 @@
outfit_type = /decl/hierarchy/outfit/job/service/bartender
job_description = "A " + JOB_BARTENDER + " mixes drinks for the crew. They generally have permission to charge for drinks or deny service to unruly patrons."
alt_titles = list(JOB_ALT_BARISTA = /datum/alt_title/barista)
alt_titles = list(JOB_ALT_BARKEEPR = /datum/alt_title/barkeeper, JOB_ALT_BARMAID = /datum/alt_title/barmaid, JOB_ALT_BARISTA = /datum/alt_title/barista, JOB_ALT_MIXOLOGIST = /datum/alt_title/mixologist)
// Bartender Alt Titles
/datum/alt_title/barista
@@ -28,6 +29,15 @@
or deny service to unruly patrons."
title_outfit = /decl/hierarchy/outfit/job/service/bartender/barista
/datum/alt_title/barkeeper
title = JOB_ALT_BARKEEPR
/datum/alt_title/barmaid
title = JOB_ALT_BARMAID
/datum/alt_title/mixologist
title = JOB_ALT_MIXOLOGIST
//////////////////////////////////
// Chef
//////////////////////////////////
@@ -40,6 +50,7 @@
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
pto_type = PTO_CIVILIAN
supervisors = "the "+ JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list(access_hydroponics, access_bar, access_kitchen)
@@ -47,13 +58,20 @@
outfit_type = /decl/hierarchy/outfit/job/service/chef
job_description = "A " + JOB_CHEF + " cooks food for the crew. They generally have permission to charge for food or deny service to unruly diners."
alt_titles = list(JOB_ALT_COOK = /datum/alt_title/cook)
alt_titles = list(JOB_ALT_SOUSCHEF = /datum/alt_title/souschef, JOB_ALT_COOK = /datum/alt_title/cook, JOB_ALT_KITCHEN_WORKER = /datum/alt_title/kitchen_worker)
// Chef Alt Titles
/datum/alt_title/cook
title = JOB_ALT_COOK
title_blurb = "A " + JOB_ALT_COOK + " has the same duties, though they may be less experienced."
/datum/alt_title/souschef
title = JOB_ALT_SOUSCHEF
/datum/alt_title/kitchen_worker
title = JOB_ALT_KITCHEN_WORKER
title_blurb = "A " + JOB_ALT_KITCHEN_WORKER + " has the same duties, though they may be less experienced."
//////////////////////////////////
// Botanist
//////////////////////////////////
@@ -66,6 +84,7 @@
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
pto_type = PTO_CIVILIAN
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list(access_hydroponics, access_bar, access_kitchen)
@@ -73,89 +92,30 @@
outfit_type = /decl/hierarchy/outfit/job/service/gardener
job_description = "A " + JOB_BOTANIST+ " grows plants for the " + JOB_CHEF + " and " + JOB_BARTENDER + "."
alt_titles = list(JOB_ALT_GARDENER = /datum/alt_title/gardener)
alt_titles = list(JOB_ALT_HYDROPONICIST = /datum/alt_title/hydroponicist, JOB_ALT_CULTIVATOR = /datum/alt_title/cultivator, JOB_ALT_FARMER = /datum/alt_title/farmer,
JOB_ALT_GARDENER = /datum/alt_title/gardener, JOB_ALT_FLORIST = /datum/alt_title/florsit, JOB_ALT_RANCHER = /datum/alt_title/rancher)
//Botanist Alt Titles
/datum/alt_title/gardener
title = JOB_ALT_GARDENER
title_blurb = "A " + JOB_ALT_GARDENER + " may be less professional than their counterparts, and are more likely to tend to the public gardens if they aren't needed elsewhere."
//Cargo
//////////////////////////////////
// Quartermaster
//////////////////////////////////
/datum/job/qm
title = JOB_QUARTERMASTER
flag = QUARTERMASTER
departments = list(DEPARTMENT_CARGO)
sorting_order = 1 // QM is above the cargo techs, but below the HoP.
departments_managed = list(DEPARTMENT_CARGO)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 1
spawn_positions = 1
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#9b633e"
economic_modifier = 5
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station, access_RC_announce)
minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station, access_RC_announce)
banned_job_species = list("digital", SPECIES_PROMETHEAN)
/datum/alt_title/hydroponicist
title = JOB_ALT_HYDROPONICIST
ideal_character_age = 40
/datum/alt_title/cultivator
title = JOB_ALT_CULTIVATOR
outfit_type = /decl/hierarchy/outfit/job/cargo/qm
job_description = "The " + JOB_QUARTERMASTER + " manages the Supply department, checking cargo orders and ensuring supplies get to where they are needed."
alt_titles = list(JOB_ALT_SUPPLY_CHIEF = /datum/alt_title/supply_chief)
/datum/alt_title/farmer
title = JOB_ALT_FARMER
// Quartermaster Alt Titles
/datum/alt_title/supply_chief
title = JOB_ALT_SUPPLY_CHIEF
/datum/alt_title/florsit
title = JOB_ALT_FLORIST
title_blurb = "A " + JOB_ALT_FLORIST + " may be less professional than their counterparts, and are more likely to tend to the public gardens if they aren't needed elsewhere."
//////////////////////////////////
// Cargo Tech
//////////////////////////////////
/datum/job/cargo_tech
title = JOB_CARGO_TECHNICIAN
flag = CARGOTECH
departments = list(DEPARTMENT_CARGO)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
supervisors = "the " + JOB_QUARTERMASTER + " and the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#7a4f33"
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_mining, access_mining_station)
minimal_access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting)
outfit_type = /decl/hierarchy/outfit/job/cargo/cargo_tech
job_description = "A " + JOB_CARGO_TECHNICIAN + " fills and delivers cargo orders. They are encouraged to return delivered crates to the Cargo Shuttle, \
because Central Command gives a partial refund."
//////////////////////////////////
// Shaft Miner
//////////////////////////////////
/datum/job/mining
title = JOB_SHAFT_MINER
flag = MINER
departments = list(DEPARTMENT_CARGO)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 3
spawn_positions = 3
supervisors = "the " + JOB_QUARTERMASTER + " and the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#7a4f33"
economic_modifier = 5
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_mining, access_mining_station)
minimal_access = list(access_mining, access_mining_station, access_mailsorting)
outfit_type = /decl/hierarchy/outfit/job/cargo/mining
job_description = "A " + JOB_SHAFT_MINER + " mines and processes minerals to be delivered to departments that need them."
alt_titles = list(JOB_ALT_DRILL_TECHNICIAN = /datum/alt_title/drill_tech)
/datum/alt_title/drill_tech
title = JOB_ALT_DRILL_TECHNICIAN
title_blurb = "A " + JOB_ALT_DRILL_TECHNICIAN + " specializes in operating and maintaining the machinery needed to extract ore from veins deep below the surface."
/datum/alt_title/rancher
title = JOB_ALT_RANCHER
title_blurb = "A " + JOB_ALT_RANCHER + " is tasked with the care, feeding, raising, and harvesting of livestock."
//Service
//////////////////////////////////
@@ -167,8 +127,9 @@
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
total_positions = 3
spawn_positions = 3
pto_type = PTO_CIVILIAN
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list(access_janitor, access_maint_tunnels)
@@ -176,12 +137,23 @@
outfit_type = /decl/hierarchy/outfit/job/service/janitor
job_description = "A " + JOB_JANITOR + " keeps the station clean, as long as it doesn't interfere with active crime scenes."
alt_titles = list(JOB_ALT_CUSTODIAN = /datum/alt_title/custodian)
alt_titles = list(JOB_ALT_CUSTODIAN = /datum/alt_title/custodian, JOB_ALT_SANITATION_TECHNICIAN = /datum/alt_title/sanitation_tech,
JOB_ALT_MAID = /datum/alt_title/maid, JOB_ALT_GARBAGE_COLLECTOR = /datum/alt_title/garbage_collector)
// Janitor Alt Titles
/datum/alt_title/custodian
title = JOB_ALT_CUSTODIAN
/datum/alt_title/sanitation_tech
title = JOB_ALT_SANITATION_TECHNICIAN
/datum/alt_title/maid
title = JOB_ALT_MAID
/datum/alt_title/garbage_collector
title = JOB_ALT_GARBAGE_COLLECTOR
title_blurb = "A " + JOB_ALT_GARBAGE_COLLECTOR + " keeps the station clean, though focuses moreso on collecting larger trash, with wet cleaning being secondary task."
//More or less assistants
//////////////////////////////////
// Librarian
@@ -192,8 +164,9 @@
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 1
spawn_positions = 1
total_positions = 2
spawn_positions = 2
pto_type = PTO_CIVILIAN
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list(access_library, access_maint_tunnels)
@@ -201,7 +174,9 @@
outfit_type = /decl/hierarchy/outfit/job/librarian
job_description = "The " + JOB_LIBRARIAN + " curates the book selection in the Library, so the crew might enjoy it."
alt_titles = list(JOB_ALT_JOURNALIST = /datum/alt_title/journalist, JOB_ALT_WRITER = /datum/alt_title/writer)
alt_titles = list(JOB_ALT_JOURNALIST = /datum/alt_title/journalist, JOB_ALT_REPORTER = /datum/alt_title/reporter, JOB_ALT_WRITER = /datum/alt_title/writer,
JOB_ALT_HISTORIAN = /datum/alt_title/historian, JOB_ALT_ARCHIVIST = /datum/alt_title/archivist, JOB_ALT_PROFESSOR = /datum/alt_title/professor,
JOB_ALT_ACADEMIC = /datum/alt_title/academic, JOB_ALT_PHILOSOPHER = /datum/alt_title/philosopher, JOB_ALT_CURATOR = /datum/alt_title/curator)
// Librarian Alt Titles
/datum/alt_title/journalist
@@ -213,6 +188,34 @@
title = JOB_ALT_WRITER
title_blurb = "The " + JOB_ALT_WRITER + " uses the Library as a quiet place to write whatever it is they choose to write."
/datum/alt_title/reporter
title = JOB_ALT_REPORTER
title_blurb = "The " + JOB_ALT_REPORTER + " uses the Library as a base of operations, from which they can report the news and goings-on on the station with their camera."
/datum/alt_title/historian
title = JOB_ALT_HISTORIAN
title_blurb = "The " + JOB_ALT_HISTORIAN + " uses the Library as a base of operation to record any important events occurring on station."
/datum/alt_title/archivist
title = JOB_ALT_ARCHIVIST
title_blurb = "The " + JOB_ALT_ARCHIVIST + " uses the Library as a base of operation to record any important events occurring on station."
/datum/alt_title/professor
title = JOB_ALT_PROFESSOR
title_blurb = "The " + JOB_ALT_PROFESSOR + " uses the Library as a base of operations to share their vast knowledge with the crew."
/datum/alt_title/academic
title = JOB_ALT_ACADEMIC
title_blurb = "The " + JOB_ALT_ACADEMIC + " uses the Library as a base of operations to share their vast knowledge with the crew."
/datum/alt_title/philosopher
title = JOB_ALT_PHILOSOPHER
title_blurb = "The " + JOB_ALT_PHILOSOPHER + " uses the Library as a base of operation to ruminate on nature of life and other great questions, and share their opinions with the crew."
/datum/alt_title/curator
title = JOB_ALT_CURATOR
title_blurb = "The " + JOB_ALT_CURATOR + " uses the Library as a base of operation to gather the finest of art for display and preservation."
//////////////////////////////////
// Internal Affairs Agent
//////////////////////////////////
@@ -226,6 +229,8 @@
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
pto_type = PTO_CIVILIAN
disallow_jobhop = TRUE
supervisors = "company officials and Corporate Regulations"
selection_color = "#515151"
economic_modifier = 7
@@ -238,10 +243,233 @@
job_description = "An " + JOB_INTERNAL_AFFAIRS_AGENT + " makes sure that the crew is following Standard Operating Procedure. They also \
handle complaints against crew members, and can have issues brought to the attention of Central Command, \
assuming their paperwork is in order."
alt_titles = list(JOB_ALT_INTERNAL_AFFAIRS_LIAISON = /datum/alt_title/ia_liaison, JOB_ALT_INTERNAL_AFFAIRS_DELEGATE = /datum/alt_title/ia_delegate,
JOB_ALT_INTERNAL_AFFAIRS_INVESTIGATOR = /datum/alt_title/ia_investigator)
/*
/datum/job/lawyer/equip(var/mob/living/carbon/human/H)
. = ..()
if(.)
H.implant_loyalty(H)
*/
/datum/alt_title/ia_liaison
title = JOB_ALT_INTERNAL_AFFAIRS_LIAISON
/datum/alt_title/ia_delegate
title = JOB_ALT_INTERNAL_AFFAIRS_DELEGATE
/datum/alt_title/ia_investigator
title = JOB_ALT_INTERNAL_AFFAIRS_INVESTIGATOR
//////////////////////////////////
// Pilot
//////////////////////////////////
/datum/job/pilot
title = JOB_PILOT
flag = PILOT
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
economic_modifier = 5
minimal_player_age = 3
pto_type = PTO_CIVILIAN
access = list(access_eva, access_maint_tunnels, access_external_airlocks, access_pilot)
minimal_access = list(access_eva, access_maint_tunnels, access_external_airlocks, access_pilot)
outfit_type = /decl/hierarchy/outfit/job/pilot
job_description = "A " + JOB_PILOT + " flies the various shuttles in the Virgo-Erigone System."
alt_titles = list(JOB_ALT_COPILOT = /datum/alt_title/co_pilot, JOB_ALT_NAVIGATOR = /datum/alt_title/navigator, JOB_ALT_HELMSMAN = /datum/alt_title/helmsman)
/datum/alt_title/co_pilot
title = JOB_ALT_COPILOT
title_blurb = "A Co-" + JOB_ALT_COPILOT + " is there primarily to assist main pilot as well as learn from them"
/datum/alt_title/navigator
title = JOB_ALT_NAVIGATOR
/datum/alt_title/helmsman
title = JOB_ALT_HELMSMAN
/datum/job/pilot/get_request_reasons()
return list("Assembling expedition team")
//////////////////////////////////
// Entertainer
//////////////////////////////////
/datum/job/entertainer
title = JOB_ENTERTAINER
flag = ENTERTAINER
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 4
spawn_positions = 4
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list(access_entertainment)
minimal_access = list(access_entertainment)
pto_type = PTO_CIVILIAN
outfit_type = /decl/hierarchy/outfit/job/assistant/entertainer
job_description = "An " + JOB_ENTERTAINER + " does just that, entertains! Put on plays, play music, sing songs, tell stories, or read your favorite fanfic."
alt_titles = list(JOB_ALT_PERFORMER = /datum/alt_title/performer, JOB_ALT_MUSICIAN = /datum/alt_title/musician, JOB_ALT_STAGEHAND = /datum/alt_title/stagehand,
JOB_ALT_ACTOR = /datum/alt_title/actor, JOB_ALT_DANCER = /datum/alt_title/dancer, JOB_ALT_SINGER = /datum/alt_title/singer,
JOB_ALT_MAGICIAN = /datum/alt_title/magician, JOB_ALT_COMEDIAN = /datum/alt_title/comedian, JOB_ALT_ARTIST = /datum/alt_title/tragedian,
JOB_ALT_ARTIST = /datum/alt_title/artist, JOB_ALT_GAME_MASTER = /datum/alt_title/game_master)
// Entertainer Alt Titles
/datum/alt_title/actor
title = JOB_ALT_ACTOR
title_blurb = "An " + JOB_ALT_ACTOR + " is someone who acts out a role! Whatever sort of character it is, get into it and impress people with power of comedy and tragedy!"
/datum/alt_title/performer
title = JOB_ALT_PERFORMER
title_blurb = "A " + JOB_ALT_PERFORMER + " is someone who performs! Whatever sort of performance will come to your mind, the world's a stage!"
/datum/alt_title/musician
title = JOB_ALT_MUSICIAN
title_blurb = "A " + JOB_ALT_MUSICIAN + " is someone who makes music with a wide variety of musical instruments!"
/datum/alt_title/stagehand
title = JOB_ALT_STAGEHAND
title_blurb = "A " + JOB_ALT_STAGEHAND + " typically performs everything the rest of the entertainers don't. Operate lights, shutters, windows, or narrate through your voicebox!"
/datum/alt_title/dancer
title = JOB_ALT_DANCER
title_blurb = "A " + JOB_ALT_DANCER + " is someone who impresses people through power of their own body! From waltz to breakdance, as long as crowd as cheering!"
/datum/alt_title/singer
title = JOB_ALT_SINGER
title_blurb = "A " + JOB_ALT_SINGER + " is someone with gift of melodious voice! Impress people with your vocal range!"
/datum/alt_title/magician
title = JOB_ALT_MAGICIAN
title_blurb = "A " + JOB_ALT_MAGICIAN + " is someone who awes those around them with impossible! Show off your repertoire of magic tricks, while keeping the secret hidden!"
/datum/alt_title/comedian
title = JOB_ALT_COMEDIAN
title_blurb = "A " + JOB_ALT_COMEDIAN + " will focus on making people laugh with the power of wit! Telling jokes, stand-up comedy, you are here to make others smile!"
/datum/alt_title/tragedian
title = JOB_ALT_ARTIST
title_blurb = "A " + JOB_ALT_ARTIST + " will focus on making people think about life and world around them! Life is a tragedy, and who's better to convey its emotions than you?"
/datum/alt_title/artist
title = JOB_ALT_ARTIST
title_blurb = "An " + JOB_ALT_ARTIST + "'s calling is to create beautiful arts! Whatever form may they take, create and have people astonished with your creativity."
/datum/alt_title/game_master
title = JOB_ALT_GAME_MASTER
title_blurb = "A " + JOB_ALT_GAME_MASTER + " provides recreation for the crew by hosting variety of games. From cards to roleplaying to something more personalized."
//////////////////////////////////
// Entrepreneur
//////////////////////////////////
/datum/job/entrepreneur
title = JOB_ENTREPRENEUR
flag = ENTREPRENEUR
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 4
spawn_positions = 4
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list()
minimal_access = list()
pto_type = PTO_CIVILIAN
outfit_type = /decl/hierarchy/outfit/job/assistant/entrepreneur
job_description = "An " + JOB_ENTREPRENEUR + " is basically a visitor that obtained special permission to offer personal services to people on station. \
They will offer people these services and, potentially, even demand payment!"
alt_titles = list(JOB_ALT_LAWYER = /datum/alt_title/lawyer, JOB_ALT_PRIVATE_EYE = /datum/alt_title/private_eye, JOB_ALT_BODYGUARD = /datum/alt_title/bodyguard,
JOB_ALT_PERSONAL_PHYSICIAN = /datum/alt_title/personal_physician, JOB_ALT_DENTIST = /datum/alt_title/dentist, JOB_ALT_FITNESS_INSTRUCTOR = /datum/alt_title/fitness_instructor,
JOB_ALT_YOGA_TEACHER = /datum/alt_title/yoga_teacher, JOB_ALT_MASSEUSE = /datum/alt_title/masseuse, JOB_ALT_TRADESPERSON = /datum/alt_title/tradesperson,
JOB_ALT_STREAMER = /datum/alt_title/streamer, JOB_ALT_INFLUENCER = /datum/alt_title/influencer, JOB_ALT_PARANORMAL_INVESTIGATOR = /datum/alt_title/paranormal_investigator,
JOB_ALT_PERSONAL_SECRETARY = /datum/alt_title/personal_secretary, JOB_ALT_STYLIST = /datum/alt_title/stylist, JOB_ALT_FISHER = /datum/alt_title/fisher,
JOB_ALT_FORTUNE_TELLER = /datum/alt_title/fortune_teller, JOB_ALT_SPIRIT_HEALER = /datum/alt_title/spirit_healer)
/datum/alt_title/lawyer
title = JOB_ALT_LAWYER
title_blurb = "A " + JOB_ALT_LAWYER + " is knowledgable in various legal systems, including station's operations. They can try to offer their legal counsel, although nobody is really obliged to listen."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_secretary
/datum/alt_title/private_eye
title = JOB_ALT_PRIVATE_EYE
title_blurb = "A " + JOB_ALT_PRIVATE_EYE + " is a detective that has no credentials or equipment. But if someone wants something found without security's knowledge, they are the one to go to."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/private_eye
/datum/alt_title/bodyguard
title = JOB_ALT_BODYGUARD
title_blurb = "A " + JOB_ALT_BODYGUARD + " offers service of personal protection. They may not be allowed any weapons, but their own body is weapon enough."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/bodyguard
/datum/alt_title/personal_physician
title = JOB_ALT_PERSONAL_PHYSICIAN
title_blurb = "A " + JOB_ALT_PERSONAL_PHYSICIAN + " is a doctor dedicated less to Hippocratic Oath and more to the moneymaking grind. Their license may be expired, but the grindset never will be."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_physician
/datum/alt_title/dentist
title = JOB_ALT_DENTIST
title_blurb = "A " + JOB_ALT_DENTIST + " is a doctor that specializes in oral care. Company may not recognize them as a proper doctor, but surely their customers will."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/dentist
/datum/alt_title/fitness_instructor
title = JOB_ALT_FITNESS_INSTRUCTOR
title_blurb = "A " + JOB_ALT_FITNESS_INSTRUCTOR + " dedicates themselves to improving the health of the crew through physical activity, and boy, do they need the help."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fitness_instructor
/datum/alt_title/yoga_teacher
title = JOB_ALT_YOGA_TEACHER
title_blurb = "A " + JOB_ALT_YOGA_TEACHER + " is similar to a fitness instructor, but rather than turning the round bodies into firm ones, they focus on helping people find balance and harmony."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/yoga_teacher
/datum/alt_title/masseuse
title = JOB_ALT_MASSEUSE
title_blurb = "A " + JOB_ALT_MASSEUSE + " is master of physical therapy and working others' bodies with their hands."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/masseuse
/datum/alt_title/tradesperson
title = JOB_ALT_TRADESPERSON
title_blurb = "A " + JOB_ALT_TRADESPERSON + " is someone attempting to make money via the most obvious act of all - buying and selling. Now if only customs allowed you to bring your goods along..."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/tradesperson
/datum/alt_title/streamer
title = JOB_ALT_STREAMER
title_blurb = "A " + JOB_ALT_STREAMER + " is here to entertain. Not the crew! Their audience across exonet!"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/streamer
/datum/alt_title/influencer
title = JOB_ALT_INFLUENCER
title_blurb = "An " + JOB_ALT_INFLUENCER + " has lucked out with some exonet following, and was given permission to go onstation to provide free exposure. Don't let it go to your head."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/influencer
/datum/alt_title/paranormal_investigator
title = JOB_ALT_PARANORMAL_INVESTIGATOR
title_blurb = "A " + JOB_ALT_PARANORMAL_INVESTIGATOR + " looks beyond what is accepted by modern science, and searches for the true unknown. Aliens, alternate dimensions, ghosts... The truth is out there!"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/paranormal_investigator
/datum/alt_title/personal_secretary
title = JOB_ALT_PERSONAL_SECRETARY
title_blurb = "A " + JOB_ALT_PERSONAL_SECRETARY + " offers services of general assistance. Although it's doubtful anyone will ever actually need those."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_secretary
/datum/alt_title/stylist
title = JOB_ALT_STYLIST
title_blurb = "A " + JOB_ALT_STYLIST + " offers fashion advice, as well as helps with adjusting appearance of the crew to better suit their beauty standards."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/stylist
/datum/alt_title/fisher
title = JOB_ALT_FISHER
title_blurb = "A " + JOB_ALT_FISHER + " is a capable angler, who is good at obtaining large amounts of marine goods. Whether you generously give them to station or attempt to make a quick thaler by selling, it's up to you!"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fisher
/datum/alt_title/fortune_teller
title = JOB_ALT_FORTUNE_TELLER
title_blurb = "A " + JOB_ALT_FORTUNE_TELLER + " peers into the future, and offers these visions to others. Occasionally those visions may even come true!"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fortune_teller
/datum/alt_title/spirit_healer
title = JOB_ALT_SPIRIT_HEALER
title_blurb = "A " + JOB_ALT_SPIRIT_HEALER + " offers alternative forms of medicine. Rituals, magic rocks, seances... It totally works. What's that about placebo?"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/spirit_healer
+23 -1
View File
@@ -7,6 +7,7 @@
faction = FACTION_STATION
total_positions = 1
spawn_positions = 1
pto_type = PTO_CIVILIAN
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list(access_morgue, access_chapel_office, access_crematorium, access_maint_tunnels)
@@ -14,13 +15,34 @@
outfit_type = /decl/hierarchy/outfit/job/chaplain
job_description = "The " + JOB_CHAPLAIN + " ministers to the spiritual needs of the crew."
alt_titles = list(JOB_ALT_COUNSELOR = /datum/alt_title/counselor)
alt_titles = list(JOB_ALT_MISSIONARY = /datum/alt_title/missionary, JOB_ALT_PREACHER = /datum/alt_title/preacher, JOB_ALT_PRIEST = /datum/alt_title/priest,
JOB_ALT_NUN = /datum/alt_title/nun, JOB_ALT_MONK = /datum/alt_title/monk, JOB_ALT_COUNSELOR = /datum/alt_title/counselor,
JOB_ALT_GURU = /datum/alt_title/guru)
// Chaplain Alt Titles
/datum/alt_title/counselor
title = JOB_ALT_COUNSELOR
title_blurb = "The " + JOB_ALT_COUNSELOR + " attends to the emotional needs of the crew, without a specific medicinal or spiritual focus."
/datum/alt_title/guru
title = JOB_ALT_GURU
title_blurb = "The " + JOB_ALT_GURU + " primarily tries to offer spiritual guidance to those who come seeking it."
/datum/alt_title/missionary
title = JOB_ALT_MISSIONARY
/datum/alt_title/preacher
title = JOB_ALT_PREACHER
/datum/alt_title/priest
title = JOB_ALT_PRIEST
/datum/alt_title/nun
title = JOB_ALT_NUN
/datum/alt_title/monk
title = JOB_ALT_MONK
/datum/job/chaplain/equip(var/mob/living/carbon/human/H, var/alt_title, var/ask_questions = TRUE)
. = ..()
if(!.)
-426
View File
@@ -1,426 +0,0 @@
/datum/job/bartender
pto_type = PTO_CIVILIAN
alt_titles = list(JOB_ALT_BARKEEPR = /datum/alt_title/barkeeper, JOB_ALT_BARMAID = /datum/alt_title/barmaid, JOB_ALT_BARISTA = /datum/alt_title/barista, JOB_ALT_MIXOLOGIST = /datum/alt_title/mixologist)
/datum/alt_title/barkeeper
title = JOB_ALT_BARKEEPR
/datum/alt_title/barmaid
title = JOB_ALT_BARMAID
/datum/alt_title/mixologist
title = JOB_ALT_MIXOLOGIST
/datum/job/chef
total_positions = 2 //IT TAKES A LOT TO MAKE A STEW
spawn_positions = 2 //A PINCH OF SALT AND LAUGHTER, TOO
pto_type = PTO_CIVILIAN
alt_titles = list(JOB_ALT_SOUSCHEF = /datum/alt_title/souschef, JOB_ALT_COOK = /datum/alt_title/cook, JOB_ALT_KITCHEN_WORKER = /datum/alt_title/kitchen_worker)
/datum/alt_title/souschef
title = JOB_ALT_SOUSCHEF
/datum/alt_title/kitchen_worker
title = JOB_ALT_KITCHEN_WORKER
title_blurb = "A " + JOB_ALT_KITCHEN_WORKER + " has the same duties, though they may be less experienced."
/datum/job/hydro
spawn_positions = 2
pto_type = PTO_CIVILIAN
alt_titles = list(JOB_ALT_HYDROPONICIST = /datum/alt_title/hydroponicist, JOB_ALT_CULTIVATOR = /datum/alt_title/cultivator, JOB_ALT_FARMER = /datum/alt_title/farmer,
JOB_ALT_GARDENER = /datum/alt_title/gardener, JOB_ALT_FLORIST = /datum/alt_title/florsit, JOB_ALT_RANCHER = /datum/alt_title/rancher)
/datum/alt_title/hydroponicist
title = JOB_ALT_HYDROPONICIST
/datum/alt_title/cultivator
title = JOB_ALT_CULTIVATOR
/datum/alt_title/farmer
title = JOB_ALT_FARMER
/datum/alt_title/florsit
title = JOB_ALT_FLORIST
title_blurb = "A " + JOB_ALT_FLORIST + " may be less professional than their counterparts, and are more likely to tend to the public gardens if they aren't needed elsewhere."
/datum/alt_title/rancher
title = JOB_ALT_RANCHER
title_blurb = "A " + JOB_ALT_RANCHER + " is tasked with the care, feeding, raising, and harvesting of livestock."
/datum/job/qm
pto_type = PTO_CARGO
dept_time_required = 20
alt_titles = list(JOB_ALT_SUPPLY_CHIEF = /datum/alt_title/supply_chief, JOB_ALT_LOGISTICS_MANAGER = /datum/alt_title/logistics_manager, JOB_ALT_CARGO_SUPERVISOR = /datum/alt_title/cargo_supervisor)
/datum/alt_title/logistics_manager
title = JOB_ALT_LOGISTICS_MANAGER
/datum/alt_title/cargo_supervisor
title = JOB_ALT_CARGO_SUPERVISOR
/datum/job/qm/get_request_reasons()
return list("Training crew")
/datum/job/cargo_tech
total_positions = 3
spawn_positions = 3
pto_type = PTO_CARGO
alt_titles = list(JOB_ALT_CARGO_LOADER = /datum/alt_title/cargo_loader, JOB_ALT_CARGO_HANDLER = /datum/alt_title/cargo_handler, JOB_ALT_SUPPLY_COURIER = /datum/alt_title/supply_courier,
JOB_ALT_DISPOSALS_SORTER = /datum/alt_title/disposal_sorter)
/datum/alt_title/supply_courier
title = JOB_ALT_SUPPLY_COURIER
title_blurb = "A " + JOB_ALT_SUPPLY_COURIER + " is usually tasked with delivering packages or cargo directly to whoever requires it."
/datum/alt_title/cargo_loader
title = JOB_ALT_CARGO_LOADER
title_blurb = "A " + JOB_ALT_CARGO_LOADER + " is usually tasked with more menial labor within Supply department, such as loading and unloading supply shuttle."
/datum/alt_title/cargo_handler
title = JOB_ALT_CARGO_HANDLER
title_blurb = "A " + JOB_ALT_CARGO_HANDLER + " is usually tasked with more menial labor within Supply department, such as loading and unloading supply shuttle."
/datum/alt_title/disposal_sorter
title = JOB_ALT_DISPOSALS_SORTER
title_blurb = "A " + JOB_ALT_DISPOSALS_SORTER + " is usually tasked with operating disposals delivery system, sorting the trash and tagging parcels for delivery."
/datum/job/mining
total_positions = 4
spawn_positions = 4
pto_type = PTO_CARGO
alt_titles = list(JOB_ALT_DEEP_SPACE_MINER = /datum/alt_title/deep_space_miner, JOB_ALT_DRILL_TECHNICIAN = /datum/alt_title/drill_tech, JOB_ALT_PROSPECTOR = /datum/alt_title/prospector,
JOB_ALT_EXCAVATOR = /datum/alt_title/excavator)
/datum/alt_title/deep_space_miner
title = JOB_ALT_DEEP_SPACE_MINER
title_blurb = "A " + JOB_ALT_DEEP_SPACE_MINER + " specializes primarily in mining operations in zero-g environments, mostly in asteroid and debris fields."
/datum/alt_title/prospector
title = JOB_ALT_PROSPECTOR
/datum/alt_title/excavator
title = JOB_ALT_EXCAVATOR
/datum/job/mining/get_request_reasons()
return list("Assembling expedition team")
/datum/job/janitor //Lots of janitor substations on station.
total_positions = 3
spawn_positions = 3
pto_type = PTO_CIVILIAN
alt_titles = list(JOB_ALT_CUSTODIAN = /datum/alt_title/custodian, JOB_ALT_SANITATION_TECHNICIAN = /datum/alt_title/sanitation_tech,
JOB_ALT_MAID = /datum/alt_title/maid, JOB_ALT_GARBAGE_COLLECTOR = /datum/alt_title/garbage_collector)
/datum/alt_title/sanitation_tech
title = JOB_ALT_SANITATION_TECHNICIAN
/datum/alt_title/maid
title = JOB_ALT_MAID
/datum/alt_title/garbage_collector
title = JOB_ALT_GARBAGE_COLLECTOR
title_blurb = "A " + JOB_ALT_GARBAGE_COLLECTOR + " keeps the station clean, though focuses moreso on collecting larger trash, with wet cleaning being secondary task."
/datum/job/librarian
total_positions = 2
spawn_positions = 2
alt_titles = list(JOB_ALT_JOURNALIST = /datum/alt_title/journalist, JOB_ALT_REPORTER = /datum/alt_title/reporter, JOB_ALT_WRITER = /datum/alt_title/writer,
JOB_ALT_HISTORIAN = /datum/alt_title/historian, JOB_ALT_ARCHIVIST = /datum/alt_title/archivist, JOB_ALT_PROFESSOR = /datum/alt_title/professor,
JOB_ALT_ACADEMIC = /datum/alt_title/academic, JOB_ALT_PHILOSOPHER = /datum/alt_title/philosopher, JOB_ALT_CURATOR = /datum/alt_title/curator)
pto_type = PTO_CIVILIAN
/datum/alt_title/reporter
title = JOB_ALT_REPORTER
title_blurb = "The " + JOB_ALT_REPORTER + " uses the Library as a base of operations, from which they can report the news and goings-on on the station with their camera."
/datum/alt_title/historian
title = JOB_ALT_HISTORIAN
title_blurb = "The " + JOB_ALT_HISTORIAN + " uses the Library as a base of operation to record any important events occurring on station."
/datum/alt_title/archivist
title = JOB_ALT_ARCHIVIST
title_blurb = "The " + JOB_ALT_ARCHIVIST + " uses the Library as a base of operation to record any important events occurring on station."
/datum/alt_title/professor
title = JOB_ALT_PROFESSOR
title_blurb = "The " + JOB_ALT_PROFESSOR + " uses the Library as a base of operations to share their vast knowledge with the crew."
/datum/alt_title/academic
title = JOB_ALT_ACADEMIC
title_blurb = "The " + JOB_ALT_ACADEMIC + " uses the Library as a base of operations to share their vast knowledge with the crew."
/datum/alt_title/philosopher
title = JOB_ALT_PHILOSOPHER
title_blurb = "The " + JOB_ALT_PHILOSOPHER + " uses the Library as a base of operation to ruminate on nature of life and other great questions, and share their opinions with the crew."
/datum/alt_title/curator
title = JOB_ALT_CURATOR
title_blurb = "The " + JOB_ALT_CURATOR + " uses the Library as a base of operation to gather the finest of art for display and preservation."
/datum/job/lawyer
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
alt_titles = list(JOB_ALT_INTERNAL_AFFAIRS_LIAISON = /datum/alt_title/ia_liaison, JOB_ALT_INTERNAL_AFFAIRS_DELEGATE = /datum/alt_title/ia_delegate,
JOB_ALT_INTERNAL_AFFAIRS_INVESTIGATOR = /datum/alt_title/ia_investigator)
/datum/alt_title/ia_liaison
title = JOB_ALT_INTERNAL_AFFAIRS_LIAISON
/datum/alt_title/ia_delegate
title = JOB_ALT_INTERNAL_AFFAIRS_DELEGATE
/datum/alt_title/ia_investigator
title = JOB_ALT_INTERNAL_AFFAIRS_INVESTIGATOR
/datum/job/chaplain
pto_type = PTO_CIVILIAN
alt_titles = list(JOB_ALT_MISSIONARY = /datum/alt_title/missionary, JOB_ALT_PREACHER = /datum/alt_title/preacher, JOB_ALT_PRIEST = /datum/alt_title/priest,
JOB_ALT_NUN = /datum/alt_title/nun, JOB_ALT_MONK = /datum/alt_title/monk, JOB_ALT_COUNSELOR = /datum/alt_title/counselor,
JOB_ALT_GURU = /datum/alt_title/guru)
/datum/alt_title/guru
title = JOB_ALT_GURU
title_blurb = "The " + JOB_ALT_GURU + " primarily tries to offer spiritual guidance to those who come seeking it."
/datum/alt_title/missionary
title = JOB_ALT_MISSIONARY
/datum/alt_title/preacher
title = JOB_ALT_PREACHER
/datum/alt_title/priest
title = JOB_ALT_PRIEST
/datum/alt_title/nun
title = JOB_ALT_NUN
/datum/alt_title/monk
title = JOB_ALT_MONK
//////////////////////////////////
// Pilot
//////////////////////////////////
/datum/job/pilot
title = JOB_PILOT
flag = PILOT
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
economic_modifier = 5
minimal_player_age = 3
pto_type = PTO_CIVILIAN
access = list(access_eva, access_maint_tunnels, access_external_airlocks, access_pilot)
minimal_access = list(access_eva, access_maint_tunnels, access_external_airlocks, access_pilot)
outfit_type = /decl/hierarchy/outfit/job/pilot
job_description = "A " + JOB_PILOT + " flies the various shuttles in the Virgo-Erigone System."
alt_titles = list(JOB_ALT_COPILOT = /datum/alt_title/co_pilot, JOB_ALT_NAVIGATOR = /datum/alt_title/navigator, JOB_ALT_HELMSMAN = /datum/alt_title/helmsman)
/datum/alt_title/co_pilot
title = JOB_ALT_COPILOT
title_blurb = "A Co-" + JOB_ALT_COPILOT + " is there primarily to assist main pilot as well as learn from them"
/datum/alt_title/navigator
title = JOB_ALT_NAVIGATOR
/datum/alt_title/helmsman
title = JOB_ALT_HELMSMAN
/datum/job/pilot/get_request_reasons()
return list("Assembling expedition team")
//////////////////////////////////
// Entertainer
//////////////////////////////////
/datum/job/entertainer
title = JOB_ENTERTAINER
flag = ENTERTAINER
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 4
spawn_positions = 4
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list(access_entertainment)
minimal_access = list(access_entertainment)
pto_type = PTO_CIVILIAN
outfit_type = /decl/hierarchy/outfit/job/assistant/entertainer
job_description = "An " + JOB_ENTERTAINER + " does just that, entertains! Put on plays, play music, sing songs, tell stories, or read your favorite fanfic."
alt_titles = list(JOB_ALT_PERFORMER = /datum/alt_title/performer, JOB_ALT_MUSICIAN = /datum/alt_title/musician, JOB_ALT_STAGEHAND = /datum/alt_title/stagehand,
JOB_ALT_ACTOR = /datum/alt_title/actor, JOB_ALT_DANCER = /datum/alt_title/dancer, JOB_ALT_SINGER = /datum/alt_title/singer,
JOB_ALT_MAGICIAN = /datum/alt_title/magician, JOB_ALT_COMEDIAN = /datum/alt_title/comedian, JOB_ALT_ARTIST = /datum/alt_title/tragedian,
JOB_ALT_ARTIST = /datum/alt_title/artist, JOB_ALT_GAME_MASTER = /datum/alt_title/game_master)
// Entertainer Alt Titles
/datum/alt_title/actor
title = JOB_ALT_ACTOR
title_blurb = "An " + JOB_ALT_ACTOR + " is someone who acts out a role! Whatever sort of character it is, get into it and impress people with power of comedy and tragedy!"
/datum/alt_title/performer
title = JOB_ALT_PERFORMER
title_blurb = "A " + JOB_ALT_PERFORMER + " is someone who performs! Whatever sort of performance will come to your mind, the world's a stage!"
/datum/alt_title/musician
title = JOB_ALT_MUSICIAN
title_blurb = "A " + JOB_ALT_MUSICIAN + " is someone who makes music with a wide variety of musical instruments!"
/datum/alt_title/stagehand
title = JOB_ALT_STAGEHAND
title_blurb = "A " + JOB_ALT_STAGEHAND + " typically performs everything the rest of the entertainers don't. Operate lights, shutters, windows, or narrate through your voicebox!"
/datum/alt_title/dancer
title = JOB_ALT_DANCER
title_blurb = "A " + JOB_ALT_DANCER + " is someone who impresses people through power of their own body! From waltz to breakdance, as long as crowd as cheering!"
/datum/alt_title/singer
title = JOB_ALT_SINGER
title_blurb = "A " + JOB_ALT_SINGER + " is someone with gift of melodious voice! Impress people with your vocal range!"
/datum/alt_title/magician
title = JOB_ALT_MAGICIAN
title_blurb = "A " + JOB_ALT_MAGICIAN + " is someone who awes those around them with impossible! Show off your repertoire of magic tricks, while keeping the secret hidden!"
/datum/alt_title/comedian
title = JOB_ALT_COMEDIAN
title_blurb = "A " + JOB_ALT_COMEDIAN + " will focus on making people laugh with the power of wit! Telling jokes, stand-up comedy, you are here to make others smile!"
/datum/alt_title/tragedian
title = JOB_ALT_ARTIST
title_blurb = "A " + JOB_ALT_ARTIST + " will focus on making people think about life and world around them! Life is a tragedy, and who's better to convey its emotions than you?"
/datum/alt_title/artist
title = JOB_ALT_ARTIST
title_blurb = "An " + JOB_ALT_ARTIST + "'s calling is to create beautiful arts! Whatever form may they take, create and have people astonished with your creativity."
/datum/alt_title/game_master
title = JOB_ALT_GAME_MASTER
title_blurb = "A " + JOB_ALT_GAME_MASTER + " provides recreation for the crew by hosting variety of games. From cards to roleplaying to something more personalized."
//////////////////////////////////
// Entrepreneur
//////////////////////////////////
/datum/job/entrepreneur
title = JOB_ENTREPRENEUR
flag = ENTREPRENEUR
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = FACTION_STATION
total_positions = 4
spawn_positions = 4
supervisors = "the " + JOB_HEAD_OF_PERSONNEL
selection_color = "#515151"
access = list()
minimal_access = list()
pto_type = PTO_CIVILIAN
outfit_type = /decl/hierarchy/outfit/job/assistant/entrepreneur
job_description = "An " + JOB_ENTREPRENEUR + " is basically a visitor that obtained special permission to offer personal services to people on station. \
They will offer people these services and, potentially, even demand payment!"
alt_titles = list(JOB_ALT_LAWYER = /datum/alt_title/lawyer, JOB_ALT_PRIVATE_EYE = /datum/alt_title/private_eye, JOB_ALT_BODYGUARD = /datum/alt_title/bodyguard,
JOB_ALT_PERSONAL_PHYSICIAN = /datum/alt_title/personal_physician, JOB_ALT_DENTIST = /datum/alt_title/dentist, JOB_ALT_FITNESS_INSTRUCTOR = /datum/alt_title/fitness_instructor,
JOB_ALT_YOGA_TEACHER = /datum/alt_title/yoga_teacher, JOB_ALT_MASSEUSE = /datum/alt_title/masseuse, JOB_ALT_TRADESPERSON = /datum/alt_title/tradesperson,
JOB_ALT_STREAMER = /datum/alt_title/streamer, JOB_ALT_INFLUENCER = /datum/alt_title/influencer, JOB_ALT_PARANORMAL_INVESTIGATOR = /datum/alt_title/paranormal_investigator,
JOB_ALT_PERSONAL_SECRETARY = /datum/alt_title/personal_secretary, JOB_ALT_STYLIST = /datum/alt_title/stylist, JOB_ALT_FISHER = /datum/alt_title/fisher,
JOB_ALT_FORTUNE_TELLER = /datum/alt_title/fortune_teller, JOB_ALT_SPIRIT_HEALER = /datum/alt_title/spirit_healer)
/datum/alt_title/lawyer
title = JOB_ALT_LAWYER
title_blurb = "A " + JOB_ALT_LAWYER + " is knowledgable in various legal systems, including station's operations. They can try to offer their legal counsel, although nobody is really obliged to listen."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_secretary
/datum/alt_title/private_eye
title = JOB_ALT_PRIVATE_EYE
title_blurb = "A " + JOB_ALT_PRIVATE_EYE + " is a detective that has no credentials or equipment. But if someone wants something found without security's knowledge, they are the one to go to."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/private_eye
/datum/alt_title/bodyguard
title = JOB_ALT_BODYGUARD
title_blurb = "A " + JOB_ALT_BODYGUARD + " offers service of personal protection. They may not be allowed any weapons, but their own body is weapon enough."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/bodyguard
/datum/alt_title/personal_physician
title = JOB_ALT_PERSONAL_PHYSICIAN
title_blurb = "A " + JOB_ALT_PERSONAL_PHYSICIAN + " is a doctor dedicated less to Hippocratic Oath and more to the moneymaking grind. Their license may be expired, but the grindset never will be."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_physician
/datum/alt_title/dentist
title = JOB_ALT_DENTIST
title_blurb = "A " + JOB_ALT_DENTIST + " is a doctor that specializes in oral care. Company may not recognize them as a proper doctor, but surely their customers will."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/dentist
/datum/alt_title/fitness_instructor
title = JOB_ALT_FITNESS_INSTRUCTOR
title_blurb = "A " + JOB_ALT_FITNESS_INSTRUCTOR + " dedicates themselves to improving the health of the crew through physical activity, and boy, do they need the help."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fitness_instructor
/datum/alt_title/yoga_teacher
title = JOB_ALT_YOGA_TEACHER
title_blurb = "A " + JOB_ALT_YOGA_TEACHER + " is similar to a fitness instructor, but rather than turning the round bodies into firm ones, they focus on helping people find balance and harmony."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/yoga_teacher
/datum/alt_title/masseuse
title = JOB_ALT_MASSEUSE
title_blurb = "A " + JOB_ALT_MASSEUSE + " is master of physical therapy and working others' bodies with their hands."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/masseuse
/datum/alt_title/tradesperson
title = JOB_ALT_TRADESPERSON
title_blurb = "A " + JOB_ALT_TRADESPERSON + " is someone attempting to make money via the most obvious act of all - buying and selling. Now if only customs allowed you to bring your goods along..."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/tradesperson
/datum/alt_title/streamer
title = JOB_ALT_STREAMER
title_blurb = "A " + JOB_ALT_STREAMER + " is here to entertain. Not the crew! Their audience across exonet!"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/streamer
/datum/alt_title/influencer
title = JOB_ALT_INFLUENCER
title_blurb = "An " + JOB_ALT_INFLUENCER + " has lucked out with some exonet following, and was given permission to go onstation to provide free exposure. Don't let it go to your head."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/influencer
/datum/alt_title/paranormal_investigator
title = JOB_ALT_PARANORMAL_INVESTIGATOR
title_blurb = "A " + JOB_ALT_PARANORMAL_INVESTIGATOR + " looks beyond what is accepted by modern science, and searches for the true unknown. Aliens, alternate dimensions, ghosts... The truth is out there!"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/paranormal_investigator
/datum/alt_title/personal_secretary
title = JOB_ALT_PERSONAL_SECRETARY
title_blurb = "A " + JOB_ALT_PERSONAL_SECRETARY + " offers services of general assistance. Although it's doubtful anyone will ever actually need those."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/personal_secretary
/datum/alt_title/stylist
title = JOB_ALT_STYLIST
title_blurb = "A " + JOB_ALT_STYLIST + " offers fashion advice, as well as helps with adjusting appearance of the crew to better suit their beauty standards."
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/stylist
/datum/alt_title/fisher
title = JOB_ALT_FISHER
title_blurb = "A " + JOB_ALT_FISHER + " is a capable angler, who is good at obtaining large amounts of marine goods. Whether you generously give them to station or attempt to make a quick thaler by selling, it's up to you!"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fisher
/datum/alt_title/fortune_teller
title = JOB_ALT_FORTUNE_TELLER
title_blurb = "A " + JOB_ALT_FORTUNE_TELLER + " peers into the future, and offers these visions to others. Occasionally those visions may even come true!"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/fortune_teller
/datum/alt_title/spirit_healer
title = JOB_ALT_SPIRIT_HEALER
title_blurb = "A " + JOB_ALT_SPIRIT_HEALER + " offers alternative forms of medicine. Rituals, magic rocks, seances... It totally works. What's that about placebo?"
title_outfit = /decl/hierarchy/outfit/job/assistant/entrepreneur/spirit_healer
+1 -1
View File
@@ -60,7 +60,7 @@
name = "Miscellaneous"
short_name = "Misc"
color = "#666666"
sorting_order = 0
sorting_order = -5
assignable = FALSE
/datum/department/synthetic
-6
View File
@@ -1,6 +0,0 @@
/datum/department/misc
name = "Off-Duty"
short_name = "Offduty"
color = "#666666"
sorting_order = -5
assignable = FALSE
+68 -9
View File
@@ -22,15 +22,20 @@
ideal_age_by_species = list(SPECIES_UNATHI = 140, "mechanical" = 20, SPECIES_HUMAN_VATBORN = 20)
banned_job_species = list(SPECIES_TESHARI, SPECIES_DIONA, SPECIES_PROMETHEAN, SPECIES_ZADDAT, "digital")
disallow_jobhop = TRUE
pto_type = PTO_ENGINEERING
dept_time_required = 60
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction, access_sec_doors,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_gateway)
minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction, access_sec_doors,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_gateway)
alt_titles = list(JOB_ALT_HEAD_ENGINEER = /datum/alt_title/head_engineer, JOB_ALT_FOREMAN = /datum/alt_title/foreman, JOB_ALT_MAINTENANCE_MANAGER = /datum/alt_title/maintenance_manager)
minimal_player_age = 7
outfit_type = /decl/hierarchy/outfit/job/engineering/chief_engineer
@@ -38,6 +43,18 @@
of manpower as much as they handle hands-on operations and repairs. They are also expected to keep the rest of the station informed of \
any structural threats to the station that may be hazardous to health or disruptive to work."
/datum/job/chief_engineer/get_request_reasons()
return list("Engine setup", "Construction project", "Repairs necessary", "Training crew", "Assembling expedition team")
/datum/alt_title/head_engineer
title = JOB_ALT_HEAD_ENGINEER
/datum/alt_title/foreman
title = JOB_ALT_FOREMAN
/datum/alt_title/maintenance_manager
title = JOB_ALT_MAINTENANCE_MANAGER
//////////////////////////////////
// Engineer
//////////////////////////////////
@@ -52,10 +69,12 @@
supervisors = "the "+ JOB_CHIEF_ENGINEER
selection_color = "#5B4D20"
economic_modifier = 5
pto_type = PTO_ENGINEERING
access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics)
minimal_access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction)
alt_titles = list(JOB_ALT_MAINTENANCE_TECHNICIAN = /datum/alt_title/maint_tech,
JOB_ALT_ENGINE_TECHNICIAN = /datum/alt_title/engine_tech, JOB_ALT_ELECTRICIAN = /datum/alt_title/electrician)
alt_titles = list(JOB_ALT_MAINTENANCE_TECHNICIAN = /datum/alt_title/maint_tech, JOB_ALT_ENGINE_TECHNICIAN = /datum/alt_title/engine_tech,
JOB_ALT_ELECTRICIAN = /datum/alt_title/electrician, JOB_ALT_CONSTRUCTION_ENGINEER = /datum/alt_title/construction_engi, JOB_ALT_ENGINEERING_CONTRACTOR = /datum/alt_title/engineering_contractor, JOB_ALT_COMPUTER_TECHNICIAN = /datum/alt_title/computer_tech, JOB_ALT_SALVAGE_TECHNICIAN = /datum/alt_title/salvage_tech)
minimal_player_age = 3
min_age_by_species = list(SPECIES_PROMETHEAN = 2)
@@ -64,6 +83,9 @@
job_description = "An " + JOB_ENGINEER + " keeps the station running. They repair damages, keep the atmosphere stable, and ensure that power is being \
generated and distributed. On quiet shifts, they may be called upon to make cosmetic alterations to the station."
/datum/job/engineer/get_request_reasons()
return list("Engine setup", "Construction project", "Repairs necessary", "Assembling expedition team")
// Engineer Alt Titles
/datum/alt_title/maint_tech
title = JOB_ALT_MAINTENANCE_TECHNICIAN
@@ -80,6 +102,23 @@
title_blurb = "An " + JOB_ALT_ELECTRICIAN + "'s primary duty is making sure power is properly distributed thoughout the station, utilizing solars, substations, and other \
methods to ensure every department has power in an emergency."
/datum/alt_title/construction_engi
title = JOB_ALT_CONSTRUCTION_ENGINEER
title_blurb = "A " + JOB_ALT_CONSTRUCTION_ENGINEER + " fulfills similar duties to other engineers, but usually occupies spare time with construction of extra facilities in dedicated areas or \
as additions to station layout."
/datum/alt_title/engineering_contractor
title = JOB_ALT_ENGINEERING_CONTRACTOR
title_blurb = "An " + JOB_ALT_ENGINEERING_CONTRACTOR + " fulfills similar duties to other engineers, but isn't directly employed by NT proper."
/datum/alt_title/computer_tech
title = JOB_ALT_COMPUTER_TECHNICIAN
title_blurb = "A " + JOB_ALT_COMPUTER_TECHNICIAN + " fulfills similar duties to other engineers, but specializes in working with software and computers. They also often deal with integrated circuits."
/datum/alt_title/salvage_tech
title = JOB_ALT_SALVAGE_TECHNICIAN
title_blurb = "A " + JOB_ALT_SALVAGE_TECHNICIAN + " is responsible for breaking down debris and obsolete equipment to recover useful components and materials."
//////////////////////////////////
// Atmos Tech
//////////////////////////////////
@@ -90,16 +129,36 @@
department_flag = ENGSEC
faction = FACTION_STATION
total_positions = 3
spawn_positions = 2
spawn_positions = 3
pto_type = PTO_ENGINEERING
supervisors = "the " + JOB_CHIEF_ENGINEER
selection_color = "#5B4D20"
economic_modifier = 5
access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics, access_external_airlocks)
minimal_access = list(access_eva, access_engine, access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction, access_external_airlocks)
alt_titles = list(JOB_ALT_ATMOSPHERIC_ENGINEER = /datum/alt_title/atmos_engi, JOB_ALT_ATMOSPHERIC_MAINTAINER = /datum/alt_title/atmos_maint, JOB_ALT_DISPOSALS_TECHNICIAN = /datum/alt_title/disposals_tech,
JOB_ALT_FUEL_TECHNICIAN = /datum/alt_title/refuel_tech)
minimal_player_age = 3
min_age_by_species = list(SPECIES_PROMETHEAN = 2)
outfit_type = /decl/hierarchy/outfit/job/engineering/atmos
job_description = "An " + JOB_ATMOSPHERIC_TECHNICIAN + " is primarily concerned with keeping the station's atmosphere breathable. They are expected to have a good \
understanding of the pipes, vents, and scrubbers that move gasses around the station, and to be familiar with proper firefighting procedure."
/datum/job/atmos/get_request_reasons()
return list("Construction project", "Repairs necessary", "Assembling expedition team")
/datum/alt_title/refuel_tech
title = JOB_ALT_FUEL_TECHNICIAN
/datum/alt_title/atmos_maint
title = JOB_ALT_ATMOSPHERIC_MAINTAINER
/datum/alt_title/atmos_engi
title = JOB_ALT_ATMOSPHERIC_ENGINEER
/datum/alt_title/disposals_tech
title = JOB_ALT_DISPOSALS_TECHNICIAN
title_blurb = "A " + JOB_ALT_DISPOSALS_TECHNICIAN + " is an " + JOB_ATMOSPHERIC_TECHNICIAN + " still and can fulfill all the same duties, although specializes more in disposals delivery system's operations and configurations."
-75
View File
@@ -1,75 +0,0 @@
/datum/job/chief_engineer
disallow_jobhop = TRUE
pto_type = PTO_ENGINEERING
dept_time_required = 60
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_gateway)
minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_gateway)
alt_titles = list(JOB_ALT_HEAD_ENGINEER = /datum/alt_title/head_engineer, JOB_ALT_FOREMAN = /datum/alt_title/foreman, JOB_ALT_MAINTENANCE_MANAGER = /datum/alt_title/maintenance_manager)
/datum/alt_title/head_engineer
title = JOB_ALT_HEAD_ENGINEER
/datum/alt_title/foreman
title = JOB_ALT_FOREMAN
/datum/alt_title/maintenance_manager
title = JOB_ALT_MAINTENANCE_MANAGER
/datum/job/chief_engineer/get_request_reasons()
return list("Engine setup", "Construction project", "Repairs necessary", "Training crew", "Assembling expedition team")
/datum/job/engineer
pto_type = PTO_ENGINEERING
alt_titles = list(JOB_ALT_MAINTENANCE_TECHNICIAN = /datum/alt_title/maint_tech, JOB_ALT_ENGINE_TECHNICIAN = /datum/alt_title/engine_tech,
JOB_ALT_ELECTRICIAN = /datum/alt_title/electrician, JOB_ALT_CONSTRUCTION_ENGINEER = /datum/alt_title/construction_engi, JOB_ALT_ENGINEERING_CONTRACTOR = /datum/alt_title/engineering_contractor, JOB_ALT_COMPUTER_TECHNICIAN = /datum/alt_title/computer_tech)
/datum/alt_title/construction_engi
title = JOB_ALT_CONSTRUCTION_ENGINEER
title_blurb = "A " + JOB_ALT_CONSTRUCTION_ENGINEER + " fulfills similar duties to other engineers, but usually occupies spare time with construction of extra facilities in dedicated areas or \
as additions to station layout."
/datum/alt_title/engineering_contractor
title = JOB_ALT_ENGINEERING_CONTRACTOR
title_blurb = "An " + JOB_ALT_ENGINEERING_CONTRACTOR + " fulfills similar duties to other engineers, but isn't directly employed by NT proper."
/datum/job/engineer/get_request_reasons()
return list("Engine setup", "Construction project", "Repairs necessary", "Assembling expedition team")
/datum/alt_title/computer_tech
title = JOB_ALT_COMPUTER_TECHNICIAN
title_blurb = "A " + JOB_ALT_COMPUTER_TECHNICIAN + " fulfills similar duties to other engineers, but specializes in working with software and computers. They also often deal with integrated circuits."
/datum/alt_title/salvage_tech
title = JOB_ALT_SALVAGE_TECHNICIAN
title_blurb = "A " + JOB_ALT_SALVAGE_TECHNICIAN + " is responsible for breaking down debris and obsolete equipment to recover useful components and materials."
/datum/job/atmos
spawn_positions = 3
pto_type = PTO_ENGINEERING
alt_titles = list(JOB_ALT_ATMOSPHERIC_ENGINEER = /datum/alt_title/atmos_engi, JOB_ALT_ATMOSPHERIC_MAINTAINER = /datum/alt_title/atmos_maint, JOB_ALT_DISPOSALS_TECHNICIAN = /datum/alt_title/disposals_tech,
JOB_ALT_FUEL_TECHNICIAN = /datum/alt_title/refuel_tech)
/datum/alt_title/atmos_maint
title = JOB_ALT_ATMOSPHERIC_MAINTAINER
/datum/alt_title/atmos_engi
title = JOB_ALT_ATMOSPHERIC_ENGINEER
/datum/alt_title/disposals_tech
title = JOB_ALT_DISPOSALS_TECHNICIAN
title_blurb = "A " + JOB_ALT_DISPOSALS_TECHNICIAN + " is an " + JOB_ATMOSPHERIC_TECHNICIAN + " still and can fulfill all the same duties, although specializes more in disposals delivery system's operations and configurations."
/datum/alt_title/refuel_tech
title = JOB_ALT_FUEL_TECHNICIAN
/datum/job/atmos/get_request_reasons()
return list("Construction project", "Repairs necessary", "Assembling expedition team")
+67
View File
@@ -39,6 +39,29 @@
// Description of the job's role and minimum responsibilities.
var/job_description = "This Job doesn't have a description! Please report it!"
//Requires a ckey to be whitelisted in jobwhitelist.txt
var/whitelist_only = 0
//Does not display this job on the occupation setup screen
var/latejoin_only = 0
//Every hour playing this role gains this much time off. (Can be negative for off duty jobs!)
var/timeoff_factor = 3
//What type of PTO is that job earning?
var/pto_type
//Disallow joining as this job midround from off-duty position via going on-duty
var/disallow_jobhop = FALSE
//Time required in the department as other jobs before playing this one (in hours)
var/dept_time_required = 0
//Do we forbid ourselves from earning PTO?
var/playtime_only = FALSE
var/requestable = TRUE
/datum/job/New()
. = ..()
department_accounts = department_accounts || departments_managed
@@ -184,3 +207,47 @@
if(brain_type in banned_job_species)
return TRUE
*/
// Check client-specific availability rules.
/datum/job/proc/player_has_enough_pto(client/C)
return timeoff_factor >= 0 || (C && LAZYACCESS(C.department_hours, pto_type) > 0)
/datum/job/proc/player_has_enough_playtime(client/C)
return (available_in_playhours(C) == 0)
/datum/job/proc/available_in_playhours(client/C)
if(C && CONFIG_GET(flag/use_playtime_restriction_for_jobs) && dept_time_required)
if(isnum(C.play_hours[pto_type])) // Has played that department before
return max(0, dept_time_required - C.play_hours[pto_type])
else // List doesn't have that entry, maybe never played, maybe invalid PTO type (you should fix that...)
return dept_time_required // Could be 0, too, which is fine! They can play that
return 0
// Special treatment for some the more complicated heads
// Captain gets every department combined
/datum/job/captain/available_in_playhours(client/C)
if(C && CONFIG_GET(flag/use_playtime_restriction_for_jobs) && dept_time_required)
var/remaining_time_needed = dept_time_required
for(var/key in C.play_hours)
if(isnum(C.play_hours[key]) && !(key == PTO_TALON))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[key])
return remaining_time_needed
return 0
// HoP gets civilian, cargo, and exploration combined
/datum/job/hop/available_in_playhours(client/C)
if(C && CONFIG_GET(flag/use_playtime_restriction_for_jobs) && dept_time_required)
var/remaining_time_needed = dept_time_required
if(isnum(C.play_hours[PTO_CIVILIAN]))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[PTO_CIVILIAN])
if(isnum(C.play_hours[PTO_CARGO]))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[PTO_CARGO])
if(isnum(C.play_hours[PTO_EXPLORATION]))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[PTO_EXPLORATION])
return remaining_time_needed
return 0
/datum/job/proc/get_request_reasons()
return list()
-66
View File
@@ -1,66 +0,0 @@
/datum/job
//Requires a ckey to be whitelisted in jobwhitelist.txt
var/whitelist_only = 0
//Does not display this job on the occupation setup screen
var/latejoin_only = 0
//Every hour playing this role gains this much time off. (Can be negative for off duty jobs!)
var/timeoff_factor = 3
//What type of PTO is that job earning?
var/pto_type
//Disallow joining as this job midround from off-duty position via going on-duty
var/disallow_jobhop = FALSE
//Time required in the department as other jobs before playing this one (in hours)
var/dept_time_required = 0
//Do we forbid ourselves from earning PTO?
var/playtime_only = FALSE
var/requestable = TRUE
// Check client-specific availability rules.
/datum/job/proc/player_has_enough_pto(client/C)
return timeoff_factor >= 0 || (C && LAZYACCESS(C.department_hours, pto_type) > 0)
/datum/job/proc/player_has_enough_playtime(client/C)
return (available_in_playhours(C) == 0)
/datum/job/proc/available_in_playhours(client/C)
if(C && CONFIG_GET(flag/use_playtime_restriction_for_jobs) && dept_time_required)
if(isnum(C.play_hours[pto_type])) // Has played that department before
return max(0, dept_time_required - C.play_hours[pto_type])
else // List doesn't have that entry, maybe never played, maybe invalid PTO type (you should fix that...)
return dept_time_required // Could be 0, too, which is fine! They can play that
return 0
// Special treatment for some the more complicated heads
// Captain gets every department combined
/datum/job/captain/available_in_playhours(client/C)
if(C && CONFIG_GET(flag/use_playtime_restriction_for_jobs) && dept_time_required)
var/remaining_time_needed = dept_time_required
for(var/key in C.play_hours)
if(isnum(C.play_hours[key]) && !(key == PTO_TALON))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[key])
return remaining_time_needed
return 0
// HoP gets civilian, cargo, and exploration combined
/datum/job/hop/available_in_playhours(client/C)
if(C && CONFIG_GET(flag/use_playtime_restriction_for_jobs) && dept_time_required)
var/remaining_time_needed = dept_time_required
if(isnum(C.play_hours[PTO_CIVILIAN]))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[PTO_CIVILIAN])
if(isnum(C.play_hours[PTO_CARGO]))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[PTO_CARGO])
if(isnum(C.play_hours[PTO_EXPLORATION]))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[PTO_EXPLORATION])
return remaining_time_needed
return 0
/datum/job/proc/get_request_reasons()
return list()
+82 -16
View File
@@ -16,11 +16,13 @@
req_admin_notify = 1
economic_modifier = 10
access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels, access_gateway)
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels, access_gateway)
alt_titles = list(JOB_ALT_CHIEF_PHYSICIAN = /datum/alt_title/chief_physician, JOB_ALT_MEDICAL_DIRECTOR = /datum/alt_title/medical_director, JOB_ALT_HEALTHCARE_MANAGER = /datum/alt_title/healthcare_manager)
minimum_character_age = 25
min_age_by_species = list(SPECIES_UNATHI = 70, "mechanical" = 10, SPECIES_HUMAN_VATBORN = 14)
@@ -29,12 +31,28 @@
ideal_age_by_species = list(SPECIES_UNATHI = 140, "mechanical" = 20, SPECIES_HUMAN_VATBORN = 20)
banned_job_species = list(SPECIES_TESHARI, SPECIES_DIONA, SPECIES_PROMETHEAN, SPECIES_ZADDAT, "digital")
disallow_jobhop = TRUE
pto_type = PTO_MEDICAL
dept_time_required = 60
outfit_type = /decl/hierarchy/outfit/job/medical/cmo
job_description = "The CMO manages the Medical department and is a position requiring experience and skill; their goal is to ensure that their \
staff keep the station's crew healthy and whole. They are primarily interested in making sure that patients are safely found and \
transported to Medical for treatment. They are expected to keep the crew informed about threats to their health and safety, and \
about the importance of Suit Sensors."
/datum/job/cmo/get_request_reasons()
return list("Surgery pending", "Viral outbreak", "Training crew", "Assembling expedition team")
/datum/alt_title/chief_physician
title = JOB_ALT_CHIEF_PHYSICIAN
/datum/alt_title/medical_director
title = JOB_ALT_MEDICAL_DIRECTOR
/datum/alt_title/healthcare_manager
title = JOB_ALT_HEALTHCARE_MANAGER
//////////////////////////////////
// Medical Doctor
//////////////////////////////////
@@ -45,7 +63,8 @@
department_flag = MEDSCI
faction = FACTION_STATION
total_positions = 5
spawn_positions = 3
spawn_positions = 5
pto_type = PTO_MEDICAL
supervisors = "the " + JOB_CHIEF_MEDICAL_OFFICER
selection_color = "#013D3B"
economic_modifier = 7
@@ -55,14 +74,15 @@
job_description = "A " + JOB_MEDICAL_DOCTOR + " is a Jack-of-All-Trades Medical title, covering a variety of skill levels and minor specializations. They are likely \
familiar with basic first aid, and a number of accompanying medications, and can generally save, if not cure, a majority of the \
patients they encounter."
alt_titles = list(
JOB_ALT_SURGEON = /datum/alt_title/surgeon,
JOB_ALT_EMERGENCY_PHYSICIAN = /datum/alt_title/emergency_physician,
JOB_ALT_NURSE = /datum/alt_title/nurse,
JOB_ALT_VIROLOGIST = /datum/alt_title/virologist)
alt_titles = list(JOB_ALT_PHYSICIAN = /datum/alt_title/physician, JOB_ALT_MEDICAL_PRACTITIONER = /datum/alt_title/medical_practitioner, JOB_ALT_SURGEON = /datum/alt_title/surgeon,
JOB_ALT_EMERGENCY_PHYSICIAN = /datum/alt_title/emergency_physician, JOB_ALT_NURSE = /datum/alt_title/nurse, JOB_ALT_ORDERLY = /datum/alt_title/orderly,
JOB_ALT_VIROLOGIST = /datum/alt_title/virologist, JOB_ALT_MEDICAL_CONTRACTOR = /datum/alt_title/medical_contractor)
min_age_by_species = list(SPECIES_PROMETHEAN = 3)
/datum/job/doctor/get_request_reasons()
return list("Surgery pending", "Viral outbreak", "Assembling expedition team")
//Medical Doctor Alt Titles
/datum/alt_title/surgeon
title = JOB_ALT_SURGEON
@@ -90,7 +110,22 @@
to produce the various types of virus foods or mutagens."
title_outfit = /decl/hierarchy/outfit/job/medical/doctor/virologist
//Chemist is a medical job damnit //YEAH FUCK YOU SCIENCE -Pete //Guys, behave -Erro
/datum/alt_title/physician
title = JOB_ALT_PHYSICIAN
/datum/alt_title/medical_practitioner
title = JOB_ALT_MEDICAL_PRACTITIONER
/datum/alt_title/orderly
title = JOB_ALT_ORDERLY
title_blurb = "An " + JOB_ALT_ORDERLY + " acts as Medbay's general helping hand, assisting any doctor that might need some form of help, as well as handling manual \
and dirty labor around the department."
title_outfit = /decl/hierarchy/outfit/job/medical/doctor/nurse
/datum/alt_title/medical_contractor
title = JOB_ALT_MEDICAL_CONTRACTOR
title_blurb = "A " + JOB_ALT_MEDICAL_CONTRACTOR + " can be anything from a full-blown doctor to the likes of a nurse or orderly, but isn't directly employed by NT proper."
//////////////////////////////////
// Chemist
//////////////////////////////////
@@ -102,6 +137,7 @@
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
pto_type = PTO_MEDICAL
supervisors = "the " + JOB_CHIEF_MEDICAL_OFFICER
selection_color = "#013D3B"
economic_modifier = 5
@@ -113,13 +149,17 @@
outfit_type = /decl/hierarchy/outfit/job/medical/chemist
job_description = "A " + JOB_CHEMIST + " produces and maintains a stock of basic to advanced chemicals for medical and occasionally research use. \
They are likely to know the use and dangers of many lab-produced chemicals."
alt_titles = list(JOB_ALT_PHARMACIST = /datum/alt_title/pharmacist)
alt_titles = list(JOB_ALT_PHARMACIST = /datum/alt_title/pharmacist, JOB_ALT_PHARMACOLOGIST = /datum/alt_title/pharmacologist)
// Chemist Alt Titles
/datum/alt_title/pharmacist
title = JOB_ALT_PHARMACIST
title_blurb = "A " + JOB_ALT_PHARMACIST + " focuses on the chemical needs of the Medical Department, and often offers to fill crew prescriptions at their discretion."
/datum/alt_title/pharmacologist
title = JOB_ALT_PHARMACOLOGIST
title_blurb = "A " + JOB_ALT_PHARMACOLOGIST + " focuses on the chemical needs of the Medical Department, primarily specializing in producing more advanced forms of medicine."
/* I'm commenting out Geneticist so you can't actually see it in the job menu, given that you can't play as one - Jon.
//////////////////////////////////
// Geneticist
@@ -154,6 +194,7 @@
faction = FACTION_STATION
total_positions = 1
spawn_positions = 1
pto_type = PTO_MEDICAL
economic_modifier = 5
supervisors = "the " + JOB_CHIEF_MEDICAL_OFFICER
selection_color = "#013D3B"
@@ -162,7 +203,7 @@
outfit_type = /decl/hierarchy/outfit/job/medical/psychiatrist
job_description = "A " + JOB_PSYCHIATRIST + " provides mental health services to crew members in need. They may also be called upon to determine whatever \
ails the mentally unwell, frequently under Security supervision. They understand the effects of various psychoactive drugs."
alt_titles = list(JOB_ALT_PSYCHOLOGIST = /datum/alt_title/psychologist)
alt_titles = list(JOB_ALT_PSYCHOLOGIST = /datum/alt_title/psychologist, JOB_ALT_PSYCHOANALYST = /datum/alt_title/psychoanalyst, JOB_ALT_PSYCHOTHERAPIST = /datum/alt_title/psychotherapist)
banned_job_species = list(SPECIES_PROMETHEAN, SPECIES_DIONA)
//Psychiatrist Alt Titles
@@ -172,6 +213,18 @@
called upon to determine whatever ails the mentally unwell, frequently under Security supervision."
title_outfit = /decl/hierarchy/outfit/job/medical/psychiatrist/psychologist
/datum/alt_title/psychoanalyst
title = JOB_ALT_PSYCHOANALYST
title_blurb = "A " + JOB_ALT_PSYCHOANALYST + " provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \
called upon to determine whatever ails the mentally unwell, frequently under Security supervision."
title_outfit = /decl/hierarchy/outfit/job/medical/psychiatrist/psychologist
/datum/alt_title/psychotherapist
title = JOB_ALT_PSYCHOTHERAPIST
title_blurb = "A " + JOB_ALT_PSYCHOTHERAPIST + " provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \
called upon to determine whatever ails the mentally unwell, frequently under Security supervision."
title_outfit = /decl/hierarchy/outfit/job/medical/psychiatrist/psychologist
//////////////////////////////////
// Paramedic
//////////////////////////////////
@@ -181,8 +234,9 @@
departments = list(DEPARTMENT_MEDICAL)
department_flag = MEDSCI
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
total_positions = 3
spawn_positions = 3
pto_type = PTO_MEDICAL
supervisors = "the " + JOB_CHIEF_MEDICAL_OFFICER
selection_color = "#013D3B"
economic_modifier = 4
@@ -191,14 +245,26 @@
outfit_type = /decl/hierarchy/outfit/job/medical/paramedic
job_description = "A " + JOB_PARAMEDIC + " is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their own. \
They may also be called upon to keep patients stable when Medical is busy or understaffed."
alt_titles = list(JOB_ALT_EMERGENCY_MEDICAL_TECHNICIAN = /datum/alt_title/emt)
alt_titles = list(JOB_ALT_EMERGENCY_MEDICAL_TECHNICIAN = /datum/alt_title/emt, JOB_ALT_MEDICAL_RESPONDER = /datum/alt_title/medical_responder, JOB_ALT_SEARCH_AND_RESCUE = /datum/alt_title/sar)
banned_job_species = list(SPECIES_DIONA)
min_age_by_species = list(SPECIES_PROMETHEAN = 2)
/datum/job/paramedic/get_request_reasons()
return list("Assembling expedition team")
// Paramedic Alt Titles
/datum/alt_title/emt
title = JOB_ALT_EMERGENCY_MEDICAL_TECHNICIAN
title_blurb = "An " + JOB_ALT_EMERGENCY_MEDICAL_TECHNICIAN + " is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their \
own. They are capable of keeping a patient stabilized until they reach the hands of someone with more training."
title_outfit = /decl/hierarchy/outfit/job/medical/paramedic/emt
/datum/alt_title/medical_responder
title = JOB_ALT_MEDICAL_RESPONDER
title_blurb = "A " + JOB_ALT_MEDICAL_RESPONDER + " is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their \
own. They are capable of keeping a patient stabilized until they reach the hands of someone with more training."
title_outfit = /decl/hierarchy/outfit/job/medical/paramedic/emt
/datum/alt_title/sar
title = JOB_ALT_SEARCH_AND_RESCUE
-97
View File
@@ -1,97 +0,0 @@
/datum/job/cmo
disallow_jobhop = TRUE
pto_type = PTO_MEDICAL
dept_time_required = 60
access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels, access_gateway)
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels, access_gateway)
alt_titles = list(JOB_ALT_CHIEF_PHYSICIAN = /datum/alt_title/chief_physician, JOB_ALT_MEDICAL_DIRECTOR = /datum/alt_title/medical_director, JOB_ALT_HEALTHCARE_MANAGER = /datum/alt_title/healthcare_manager)
/datum/alt_title/chief_physician
title = JOB_ALT_CHIEF_PHYSICIAN
/datum/alt_title/medical_director
title = JOB_ALT_MEDICAL_DIRECTOR
/datum/alt_title/healthcare_manager
title = JOB_ALT_HEALTHCARE_MANAGER
/datum/job/cmo/get_request_reasons()
return list("Surgery pending", "Viral outbreak", "Training crew", "Assembling expedition team")
/datum/job/doctor
spawn_positions = 5
pto_type = PTO_MEDICAL
alt_titles = list(JOB_ALT_PHYSICIAN = /datum/alt_title/physician, JOB_ALT_MEDICAL_PRACTITIONER = /datum/alt_title/medical_practitioner, JOB_ALT_SURGEON = /datum/alt_title/surgeon,
JOB_ALT_EMERGENCY_PHYSICIAN = /datum/alt_title/emergency_physician, JOB_ALT_NURSE = /datum/alt_title/nurse, JOB_ALT_ORDERLY = /datum/alt_title/orderly,
JOB_ALT_VIROLOGIST = /datum/alt_title/virologist, JOB_ALT_MEDICAL_CONTRACTOR = /datum/alt_title/medical_contractor)
/datum/alt_title/physician
title = JOB_ALT_PHYSICIAN
/datum/alt_title/medical_practitioner
title = JOB_ALT_MEDICAL_PRACTITIONER
/datum/alt_title/orderly
title = JOB_ALT_ORDERLY
title_blurb = "An " + JOB_ALT_ORDERLY + " acts as Medbay's general helping hand, assisting any doctor that might need some form of help, as well as handling manual \
and dirty labor around the department."
title_outfit = /decl/hierarchy/outfit/job/medical/doctor/nurse
/datum/alt_title/medical_contractor
title = JOB_ALT_MEDICAL_CONTRACTOR
title_blurb = "A " + JOB_ALT_MEDICAL_CONTRACTOR + " can be anything from a full-blown doctor to the likes of a nurse or orderly, but isn't directly employed by NT proper."
/datum/job/doctor/get_request_reasons()
return list("Surgery pending", "Viral outbreak", "Assembling expedition team")
/datum/job/chemist
pto_type = PTO_MEDICAL
alt_titles = list(JOB_ALT_PHARMACIST = /datum/alt_title/pharmacist, JOB_ALT_PHARMACOLOGIST = /datum/alt_title/pharmacologist)
/datum/alt_title/pharmacologist
title = JOB_ALT_PHARMACOLOGIST
title_blurb = "A " + JOB_ALT_PHARMACOLOGIST + " focuses on the chemical needs of the Medical Department, primarily specializing in producing more advanced forms of medicine."
/datum/job/psychiatrist
pto_type = PTO_MEDICAL
alt_titles = list(JOB_ALT_PSYCHOLOGIST = /datum/alt_title/psychologist, JOB_ALT_PSYCHOANALYST = /datum/alt_title/psychoanalyst, JOB_ALT_PSYCHOTHERAPIST = /datum/alt_title/psychotherapist)
/datum/alt_title/psychoanalyst
title = JOB_ALT_PSYCHOANALYST
title_blurb = "A " + JOB_ALT_PSYCHOANALYST + " provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \
called upon to determine whatever ails the mentally unwell, frequently under Security supervision."
title_outfit = /decl/hierarchy/outfit/job/medical/psychiatrist/psychologist
/datum/alt_title/psychotherapist
title = JOB_ALT_PSYCHOTHERAPIST
title_blurb = "A " + JOB_ALT_PSYCHOTHERAPIST + " provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \
called upon to determine whatever ails the mentally unwell, frequently under Security supervision."
title_outfit = /decl/hierarchy/outfit/job/medical/psychiatrist/psychologist
/datum/job/paramedic
pto_type = PTO_MEDICAL
alt_titles = list(JOB_ALT_EMERGENCY_MEDICAL_TECHNICIAN = /datum/alt_title/emt, JOB_ALT_MEDICAL_RESPONDER = /datum/alt_title/medical_responder, JOB_ALT_SEARCH_AND_RESCUE = /datum/alt_title/sar)
total_positions = 3
spawn_positions = 3
/datum/alt_title/medical_responder
title = JOB_ALT_MEDICAL_RESPONDER
title_blurb = "A " + JOB_ALT_MEDICAL_RESPONDER + " is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their \
own. They are capable of keeping a patient stabilized until they reach the hands of someone with more training."
title_outfit = /decl/hierarchy/outfit/job/medical/paramedic/emt
/datum/alt_title/sar
title = JOB_ALT_SEARCH_AND_RESCUE
/datum/job/paramedic/get_request_reasons()
return list("Assembling expedition team")
+118 -16
View File
@@ -16,13 +16,13 @@
req_admin_notify = 1
economic_modifier = 15
access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue,
access_tox_storage, access_teleporter, access_sec_doors,
access_tox_storage, access_teleporter,
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_network)
access_RC_announce, access_keycard_auth, access_tcomsat, access_xenoarch, access_eva, access_network, access_xenobotany)
minimal_access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue,
access_tox_storage, access_teleporter, access_sec_doors,
access_tox_storage, access_teleporter,
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_network)
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva, access_network, access_xenobotany)
minimum_character_age = 25
minimal_player_age = 14
@@ -30,19 +30,34 @@
ideal_character_age = 50
ideal_age_by_species = list(SPECIES_UNATHI = 140, "mechanical" = 20, SPECIES_HUMAN_VATBORN = 20)
banned_job_species = list(SPECIES_TESHARI, SPECIES_DIONA, SPECIES_PROMETHEAN, SPECIES_ZADDAT, "digital")
disallow_jobhop = TRUE
pto_type = PTO_SCIENCE
dept_time_required = 60
outfit_type = /decl/hierarchy/outfit/job/science/rd
job_description = "The " + JOB_RESEARCH_DIRECTOR + " manages and maintains the Research department. They are required to ensure the safety of the entire crew, \
at least with regards to anything occurring in the Research department, and to inform the crew of any disruptions that \
might originate from Research. The " + JOB_RESEARCH_DIRECTOR + " often has at least passing knowledge of most of the Research department, but \
are encouraged to allow their staff to perform their own duties."
alt_titles = list(JOB_ALT_RESEARCH_SUPERVISOR = /datum/alt_title/research_supervisor)
alt_titles = list(JOB_ALT_RESEARCH_SUPERVISOR = /datum/alt_title/research_supervisor, JOB_ALT_RESEARCH_MANAGER = /datum/alt_title/research_manager,
JOB_ALT_HEAD_OF_DEVELOPMENT = /datum/alt_title/head_of_development,JOB_ALT_HEAD_SCIENTIST = /datum/alt_title/head_scientist)
/datum/job/rd/get_request_reasons()
return list("Repairs needed", "Training crew", "Assembling expedition team")
// " + JOB_RESEARCH_DIRECTOR + " Alt Titles
/datum/alt_title/research_supervisor
title = JOB_ALT_RESEARCH_SUPERVISOR
/datum/alt_title/research_manager
title = JOB_ALT_RESEARCH_MANAGER
/datum/alt_title/head_of_development
title = JOB_ALT_HEAD_OF_DEVELOPMENT
/datum/alt_title/head_scientist
title = JOB_ALT_HEAD_SCIENTIST
//////////////////////////////////
// Scientist
//////////////////////////////////
@@ -53,11 +68,12 @@
department_flag = MEDSCI
faction = FACTION_STATION
total_positions = 5
spawn_positions = 3
spawn_positions = 5
pto_type = PTO_SCIENCE
supervisors = "the " + JOB_RESEARCH_DIRECTOR
selection_color = "#633D63"
economic_modifier = 7
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_xenoarch)
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_xenoarch, access_xenobotany)
minimal_access = list(access_tox, access_tox_storage, access_research, access_xenoarch)
min_age_by_species = list(SPECIES_PROMETHEAN = 2)
banned_job_species = list("digital")
@@ -68,8 +84,12 @@
job_description = "A " + JOB_SCIENTIST + " is a generalist working in the Research department, with general knowledge of the scientific process, as well as \
the principles and requirements of Research and Development. They may also formulate experiments of their own devising, if \
they find an appropriate topic."
alt_titles = list(JOB_ALT_XENOARCHAEOLOGIST = /datum/alt_title/xenoarch, JOB_ALT_ANOMALIST = /datum/alt_title/anomalist, \
JOB_ALT_PHORON_RESEARCHER = /datum/alt_title/phoron_research)
alt_titles = list(JOB_ALT_RESEARCHER = /datum/alt_title/researcher, JOB_ALT_LAB_ASSISTANT = /datum/alt_title/lab_assistant, JOB_ALT_XENOARCHAEOLOGIST = /datum/alt_title/xenoarch,
JOB_ALT_XENOPALEONTOLOGIST = /datum/alt_title/xenopaleontologist, JOB_ALT_ANOMALIST = /datum/alt_title/anomalist, JOB_ALT_PHORON_RESEARCHER = /datum/alt_title/phoron_research,
JOB_ALT_GAS_PHYSICIST = /datum/alt_title/gas_physicist, JOB_ALT_CIRCUIT_DESIGNER = /datum/alt_title/circuit_designer, JOB_ALT_CIRCUIT_PROGRAMMER = /datum/alt_title/circuit_programmer)
/datum/job/scientist/get_request_reasons()
return list("Assembling expedition team")
// Scientist Alt Titles
/datum/alt_title/xenoarch
@@ -88,6 +108,35 @@
Many " + JOB_ALT_PHORON_RESEARCHER + "s are interested in the combustability and explosive properties of gaseous phoron, as well as the specific hazards \
of working with the substance in that state."
/datum/alt_title/researcher
title = JOB_ALT_RESEARCHER
/datum/alt_title/lab_assistant
title = JOB_ALT_LAB_ASSISTANT
title_blurb = "A " + JOB_ALT_LAB_ASSISTANT + " is a lower-level member of research staff, whose main purpose is to help scientists with their specialized work in more menial fashion, while also \
learning the specializations in process."
/datum/alt_title/xenopaleontologist
title = JOB_ALT_XENOPALEONTOLOGIST
title_blurb = "A " + JOB_ALT_XENOPALEONTOLOGIST + " enters digsites in search of fossils and other ancient remants of alien life. These digsites are frequently in vacuum or other inhospitable \
locations, and as such a " + JOB_ALT_XENOPALEONTOLOGIST + " should be prepared to handle hostile evironmental conditions."
/datum/alt_title/gas_physicist
title = JOB_ALT_GAS_PHYSICIST
title_blurb = "A " + JOB_ALT_GAS_PHYSICIST + " is a specialist in various practical applications of gasses, but currently focuses their attention on phoron, and has knowledge of its practical uses and dangers. \
Many " + JOB_ALT_GAS_PHYSICIST + "s are interested in the combustability and explosive properties of gaseous phoron, as well as the specific hazards \
of working with the substance in that state."
/datum/alt_title/circuit_designer
title = JOB_ALT_CIRCUIT_DESIGNER
title_blurb = "A " + JOB_ALT_CIRCUIT_DESIGNER + " is a " + JOB_SCIENTIST + " whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \
They work to create various useful devices using the capabilities of integrated circuitry."
/datum/alt_title/circuit_programmer
title = JOB_ALT_CIRCUIT_PROGRAMMER
title_blurb = "A " + JOB_ALT_CIRCUIT_PROGRAMMER + " is a " + JOB_SCIENTIST + " whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \
They work to create various useful devices using the capabilities of integrated circuitry."
//////////////////////////////////
// Xenobiologist
//////////////////////////////////
@@ -98,7 +147,8 @@
department_flag = MEDSCI
faction = FACTION_STATION
total_positions = 3
spawn_positions = 2
spawn_positions = 3
pto_type = PTO_SCIENCE
supervisors = "the " + JOB_RESEARCH_DIRECTOR
selection_color = "#633D63"
economic_modifier = 7
@@ -112,15 +162,21 @@
outfit_type = /decl/hierarchy/outfit/job/science/xenobiologist
job_description = "A " + JOB_XENOBIOLOGIST + " studies esoteric lifeforms, usually in the relative safety of their lab. They attempt to find ways to benefit \
from the byproducts of these lifeforms, and their main subject at present is the Giant Slime."
/*VR edit start
alt_titles = list(JOB_XENOBOTANIST = /datum/alt_title/xenobot)
Xenibiologist Alt Titles
alt_titles = list(JOB_ALT_XENOZOOLOGIST = /datum/alt_title/xenozoologist, JOB_ALT_XENOANTHROPOLOGIST = /datum/alt_title/xenoanthropologist)
// Xenobiologist Alt Titles
/datum/alt_title/xenobot
title = JOB_XENOBOTANIST
title_blurb = "A " + JOB_XENOBOTANIST + " grows and cares for a variety of abnormal, custom made, and frequently dangerous plant life. When the products of these plants \
is both safe and beneficial to the station, they may choose to introduce it to the rest of the crew."
VR edit end*/
/datum/alt_title/xenozoologist
title = JOB_ALT_XENOZOOLOGIST
/datum/alt_title/xenoanthropologist
title = JOB_ALT_XENOANTHROPOLOGIST
title_blurb = JOB_ALT_XENOANTHROPOLOGIST + " still heavily focuses their study on alien lifeforms, but their specialty leans more towards fellow sapient beings than simple animals."
//////////////////////////////////
// Roboticist
@@ -131,8 +187,9 @@ VR edit end*/
departments = list(DEPARTMENT_RESEARCH)
department_flag = MEDSCI
faction = FACTION_STATION
total_positions = 2
total_positions = 3
spawn_positions = 2
pto_type = PTO_SCIENCE
supervisors = "the " + JOB_RESEARCH_DIRECTOR
selection_color = "#633D63"
economic_modifier = 5
@@ -145,7 +202,14 @@ VR edit end*/
outfit_type = /decl/hierarchy/outfit/job/science/roboticist
job_description = "A " + JOB_ROBOTICIST + " maintains and repairs the station's synthetics, including crew with prosthetic limbs. \
They can also assist the station by producing simple robots and even pilotable exosuits."
alt_titles = list(JOB_ALT_BIOMECHANICAL_ENGINEER = /datum/alt_title/biomech, JOB_ALT_MECHATRONIC_ENGINEER = /datum/alt_title/mech_tech)
alt_titles = list(
JOB_ALT_ASSEMBLY_TECHNICIAN = /datum/alt_title/assembly_tech,
JOB_ALT_BIOMECHANICAL_ENGINEER = /datum/alt_title/biomech,
JOB_ALT_MECHATRONIC_ENGINEER = /datum/alt_title/mech_tech,
JOB_ALT_SOFTWARE_ENGINEER = /datum/alt_title/software_engi)
/datum/job/roboticist/get_request_reasons()
return list("Repairs needed")
// Roboticist Alt Titles
/datum/alt_title/biomech
@@ -157,3 +221,41 @@ VR edit end*/
title = JOB_ALT_MECHATRONIC_ENGINEER
title_blurb = "A " + JOB_ALT_MECHATRONIC_ENGINEER + " focuses on the construction and maintenance of Exosuits, and should be well versed in their use. \
They may also be called upon to work on synthetics and prosthetics, if needed."
/datum/alt_title/software_engi
title = JOB_ALT_SOFTWARE_ENGINEER
title_blurb = "A " + JOB_ALT_SOFTWARE_ENGINEER + " specializes in working with software and firmware. They also often deal with integrated circuits."
/datum/alt_title/assembly_tech
title = JOB_ALT_ASSEMBLY_TECHNICIAN
//////////////////////////////////
// Xenobotanist
//////////////////////////////////
/datum/job/xenobotanist
title = JOB_XENOBOTANIST
flag = XENOBOTANIST
departments = list(DEPARTMENT_RESEARCH)
department_flag = MEDSCI
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
supervisors = "the " + JOB_RESEARCH_DIRECTOR
selection_color = "#633D63"
economic_modifier = 7
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobotany, access_hydroponics)
minimal_access = list(access_research, access_xenobotany, access_hydroponics, access_tox_storage)
pto_type = PTO_SCIENCE
minimal_player_age = 14
outfit_type = /decl/hierarchy/outfit/job/science/xenobiologist
job_description = "A " + JOB_XENOBOTANIST + " grows and cares for a variety of abnormal, custom made, and frequently dangerous plant life. When the products of these plants \
are both safe and beneficial to the station, they may choose to introduce it to the rest of the crew."
alt_titles = list(JOB_ALT_XENOHYDROPONICIST = /datum/alt_title/xenohydroponicist, JOB_ALT_XENOFLORIST = /datum/alt_title/xenoflorist)
/datum/alt_title/xenoflorist
title = JOB_ALT_XENOFLORIST
/datum/alt_title/xenohydroponicist
title = JOB_ALT_XENOHYDROPONICIST
-134
View File
@@ -1,134 +0,0 @@
/datum/job/rd
disallow_jobhop = TRUE
pto_type = PTO_SCIENCE
dept_time_required = 60
access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue,
access_tox_storage, access_teleporter,
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
access_RC_announce, access_keycard_auth, access_tcomsat, access_xenoarch, access_eva, access_network, access_xenobotany)
minimal_access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue,
access_tox_storage, access_teleporter,
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva, access_network, access_xenobotany)
alt_titles = list(JOB_ALT_RESEARCH_SUPERVISOR = /datum/alt_title/research_supervisor, JOB_ALT_RESEARCH_MANAGER = /datum/alt_title/research_manager,
JOB_ALT_HEAD_OF_DEVELOPMENT = /datum/alt_title/head_of_development,JOB_ALT_HEAD_SCIENTIST = /datum/alt_title/head_scientist)
/datum/alt_title/research_manager
title = JOB_ALT_RESEARCH_MANAGER
/datum/alt_title/head_of_development
title = JOB_ALT_HEAD_OF_DEVELOPMENT
/datum/alt_title/head_scientist
title = JOB_ALT_HEAD_SCIENTIST
/datum/job/rd/get_request_reasons()
return list("Repairs needed", "Training crew", "Assembling expedition team")
/datum/job/scientist
spawn_positions = 5
pto_type = PTO_SCIENCE
alt_titles = list(JOB_ALT_RESEARCHER = /datum/alt_title/researcher, JOB_ALT_LAB_ASSISTANT = /datum/alt_title/lab_assistant, JOB_ALT_XENOARCHAEOLOGIST = /datum/alt_title/xenoarch,
JOB_ALT_XENOPALEONTOLOGIST = /datum/alt_title/xenopaleontologist, JOB_ALT_ANOMALIST = /datum/alt_title/anomalist, JOB_ALT_PHORON_RESEARCHER = /datum/alt_title/phoron_research,
JOB_ALT_GAS_PHYSICIST = /datum/alt_title/gas_physicist, JOB_ALT_CIRCUIT_DESIGNER = /datum/alt_title/circuit_designer, JOB_ALT_CIRCUIT_PROGRAMMER = /datum/alt_title/circuit_programmer)
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_xenoarch, access_xenobotany)
minimal_access = list(access_tox, access_tox_storage, access_research, access_xenoarch) // Unchanged (for now?), mostly here for reference
/datum/alt_title/researcher
title = JOB_ALT_RESEARCHER
/datum/alt_title/lab_assistant
title = JOB_ALT_LAB_ASSISTANT
title_blurb = "A " + JOB_ALT_LAB_ASSISTANT + " is a lower-level member of research staff, whose main purpose is to help scientists with their specialized work in more menial fashion, while also \
learning the specializations in process."
/datum/alt_title/xenopaleontologist
title = JOB_ALT_XENOPALEONTOLOGIST
title_blurb = "A " + JOB_ALT_XENOPALEONTOLOGIST + " enters digsites in search of fossils and other ancient remants of alien life. These digsites are frequently in vacuum or other inhospitable \
locations, and as such a " + JOB_ALT_XENOPALEONTOLOGIST + " should be prepared to handle hostile evironmental conditions."
/datum/alt_title/gas_physicist
title = JOB_ALT_GAS_PHYSICIST
title_blurb = "A " + JOB_ALT_GAS_PHYSICIST + " is a specialist in various practical applications of gasses, but currently focuses their attention on phoron, and has knowledge of its practical uses and dangers. \
Many " + JOB_ALT_GAS_PHYSICIST + "s are interested in the combustability and explosive properties of gaseous phoron, as well as the specific hazards \
of working with the substance in that state."
/datum/alt_title/circuit_designer
title = JOB_ALT_CIRCUIT_DESIGNER
title_blurb = "A " + JOB_ALT_CIRCUIT_DESIGNER + " is a " + JOB_SCIENTIST + " whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \
They work to create various useful devices using the capabilities of integrated circuitry."
/datum/alt_title/circuit_programmer
title = JOB_ALT_CIRCUIT_PROGRAMMER
title_blurb = "A " + JOB_ALT_CIRCUIT_PROGRAMMER + " is a " + JOB_SCIENTIST + " whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \
They work to create various useful devices using the capabilities of integrated circuitry."
/datum/job/scientist/get_request_reasons()
return list("Assembling expedition team")
/datum/job/xenobiologist
spawn_positions = 3
pto_type = PTO_SCIENCE
alt_titles = list(JOB_ALT_XENOZOOLOGIST = /datum/alt_title/xenozoologist, JOB_ALT_XENOANTHROPOLOGIST = /datum/alt_title/xenoanthropologist)
/datum/alt_title/xenozoologist
title = JOB_ALT_XENOZOOLOGIST
/datum/alt_title/xenoanthropologist
title = JOB_ALT_XENOANTHROPOLOGIST
title_blurb = JOB_ALT_XENOANTHROPOLOGIST + " still heavily focuses their study on alien lifeforms, but their specialty leans more towards fellow sapient beings than simple animals."
/datum/job/roboticist
total_positions = 3
pto_type = PTO_SCIENCE
alt_titles = list(
JOB_ALT_ASSEMBLY_TECHNICIAN = /datum/alt_title/assembly_tech,
JOB_ALT_BIOMECHANICAL_ENGINEER = /datum/alt_title/biomech,
JOB_ALT_MECHATRONIC_ENGINEER = /datum/alt_title/mech_tech,
JOB_ALT_SOFTWARE_ENGINEER = /datum/alt_title/software_engi)
/datum/alt_title/software_engi
title = JOB_ALT_SOFTWARE_ENGINEER
title_blurb = "A " + JOB_ALT_SOFTWARE_ENGINEER + " specializes in working with software and firmware. They also often deal with integrated circuits."
/datum/alt_title/assembly_tech
title = JOB_ALT_ASSEMBLY_TECHNICIAN
/datum/job/roboticist/get_request_reasons()
return list("Repairs needed")
//////////////////////////////////
// Xenobotanist
//////////////////////////////////
/datum/job/xenobotanist
title = JOB_XENOBOTANIST
flag = XENOBOTANIST
departments = list(DEPARTMENT_RESEARCH)
department_flag = MEDSCI
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
supervisors = "the " + JOB_RESEARCH_DIRECTOR
selection_color = "#633D63"
economic_modifier = 7
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobotany, access_hydroponics)
minimal_access = list(access_research, access_xenobotany, access_hydroponics, access_tox_storage)
pto_type = PTO_SCIENCE
minimal_player_age = 14
outfit_type = /decl/hierarchy/outfit/job/science/xenobiologist
job_description = "A " + JOB_XENOBOTANIST + " grows and cares for a variety of abnormal, custom made, and frequently dangerous plant life. When the products of these plants \
are both safe and beneficial to the station, they may choose to introduce it to the rest of the crew."
alt_titles = list(JOB_ALT_XENOHYDROPONICIST = /datum/alt_title/xenohydroponicist, JOB_ALT_XENOFLORIST = /datum/alt_title/xenoflorist)
/datum/alt_title/xenoflorist
title = JOB_ALT_XENOFLORIST
/datum/alt_title/xenohydroponicist
title = JOB_ALT_XENOHYDROPONICIST
+62 -12
View File
@@ -16,26 +16,31 @@
req_admin_notify = 1
economic_modifier = 10
access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_construction,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
minimal_access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_construction,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
minimum_character_age = 25
min_age_by_species = list(SPECIES_HUMAN_VATBORN = 14)
minimal_player_age = 14
ideal_character_age = 50
ideal_age_by_species = list(SPECIES_HUMAN_VATBORN = 20)
banned_job_species = list(SPECIES_TESHARI, SPECIES_DIONA, SPECIES_PROMETHEAN, SPECIES_ZADDAT, "digital", SPECIES_UNATHI, "mechanical")
disallow_jobhop = TRUE
pto_type = PTO_SECURITY
dept_time_required = 60
outfit_type = /decl/hierarchy/outfit/job/security/hos
job_description = " The " + JOB_HEAD_OF_SECURITY + " manages the Security Department, keeping the station safe and making sure the rules are followed. They are expected to \
keep the other Department Heads, and the rest of the crew, aware of developing situations that may be a threat. If necessary, the HoS may \
perform the duties of absent Security roles, such as distributing gear from the Armory."
alt_titles = list(JOB_ALT_SECURITY_COMMANDER = /datum/alt_title/sec_commander, JOB_ALT_CHIEF_OF_SECURITY = /datum/alt_title/sec_chief)
alt_titles = list(JOB_ALT_SECURITY_COMMANDER = /datum/alt_title/sec_commander, JOB_ALT_CHIEF_OF_SECURITY = /datum/alt_title/sec_chief, JOB_ALT_SECURITY_MANAGER = /datum/alt_title/security_manager)
/datum/job/hos/get_request_reasons()
return list("Wildlife management", "Forensic investigation", "Training crew", "Assembling expedition team")
// Head of Security Alt Titles
/datum/alt_title/sec_commander
@@ -44,6 +49,9 @@
/datum/alt_title/sec_chief
title = JOB_ALT_CHIEF_OF_SECURITY
/datum/alt_title/security_manager
title = JOB_ALT_SECURITY_MANAGER
//////////////////////////////////
// Warden
//////////////////////////////////
@@ -59,17 +67,32 @@
supervisors = "the " + JOB_HEAD_OF_SECURITY
selection_color = "#601C1C"
economic_modifier = 5
pto_type = PTO_SECURITY
dept_time_required = 20
access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory, access_maint_tunnels, access_morgue, access_external_airlocks)
minimal_access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory, access_maint_tunnels, access_external_airlocks)
minimal_player_age = 5
banned_job_species = list(SPECIES_ZADDAT, SPECIES_PROMETHEAN, SPECIES_TESHARI, SPECIES_DIONA)
alt_titles = list(JOB_ALT_BRIG_SENTRY = /datum/alt_title/brig_sentry, JOB_ALT_ARMORY_SUPERINTENDENT = /datum/alt_title/armory_superintendent, JOB_ALT_MASTERATARMS = /datum/alt_title/master_at_arms)
outfit_type = /decl/hierarchy/outfit/job/security/warden
job_description = "The " + JOB_WARDEN + " watches over the physical Security Department, making sure the Brig and Armoury are secure and in order at all times. They oversee \
prisoners that have been processed and brigged, and are responsible for their well being. The " + JOB_WARDEN + " is also in charge of distributing \
Armoury gear in a crisis, and retrieving it when the crisis has passed. In an emergency, the " + JOB_WARDEN + " may be called upon to direct the \
Security Department as a whole."
/datum/job/warden/get_request_reasons()
return list("Wildlife management")
//Warden Alt Titles
/datum/alt_title/brig_sentry
title = JOB_ALT_BRIG_SENTRY
/datum/alt_title/armory_superintendent
title = JOB_ALT_ARMORY_SUPERINTENDENT
/datum/alt_title/master_at_arms
title = JOB_ALT_MASTERATARMS
//////////////////////////////////
// Detective
//////////////////////////////////
@@ -81,6 +104,7 @@
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
pto_type = PTO_SECURITY
supervisors = "the " + JOB_HEAD_OF_SECURITY
selection_color = "#601C1C"
access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_eva, access_external_airlocks, access_brig) //Vorestation edit - access_brig
@@ -92,7 +116,10 @@
outfit_type = /decl/hierarchy/outfit/job/security/detective
job_description = "A " + JOB_DETECTIVE + " works to help Security find criminals who have not properly been identified, through interviews and forensic work. \
For crimes only witnessed after the fact, or those with no survivors, they attempt to piece together what they can from pure evidence."
alt_titles = list(JOB_ALT_FORENSIC_TECHNICIAN = /datum/alt_title/forensic_tech)
alt_titles = list(JOB_ALT_INVESTIGATOR = /datum/alt_title/investigator, JOB_ALT_SECURITY_INSPECTOR = /datum/alt_title/security_inspector, JOB_ALT_FORENSIC_TECHNICIAN = /datum/alt_title/forensic_tech)
/datum/job/detective/get_request_reasons()
return list("Forensic investigation")
// Detective Alt Titles
/datum/alt_title/forensic_tech
@@ -100,6 +127,12 @@
title_blurb = "A " + JOB_ALT_FORENSIC_TECHNICIAN + " works more with hard evidence and labwork than a " + JOB_DETECTIVE + ", but they share the purpose of solving crimes."
title_outfit = /decl/hierarchy/outfit/job/security/detective/forensic
/datum/alt_title/investigator
title = JOB_ALT_INVESTIGATOR
/datum/alt_title/security_inspector
title = JOB_ALT_SECURITY_INSPECTOR
//////////////////////////////////
// Security Officer
//////////////////////////////////
@@ -109,8 +142,9 @@
departments = list(DEPARTMENT_SECURITY)
department_flag = ENGSEC
faction = FACTION_STATION
total_positions = 4
spawn_positions = 4
total_positions = 5
spawn_positions = 5
pto_type = PTO_SECURITY
supervisors = "the " + JOB_HEAD_OF_SECURITY
selection_color = "#601C1C"
economic_modifier = 4
@@ -123,13 +157,29 @@
job_description = "A " + JOB_SECURITY_OFFICER + " is concerned with maintaining the safety and security of the station as a whole, dealing with external threats and \
apprehending criminals. A " + JOB_SECURITY_OFFICER + " is responsible for the health, safety, and processing of any prisoner they arrest. \
No one is above the Law, not Security or Command."
alt_titles = list(JOB_ALT_JUNIOR_OFFICER = /datum/alt_title/junior_officer)
alt_titles = list(JOB_ALT_PATROL_OFFICER = /datum/alt_title/patrol_officer, JOB_ALT_SECURITY_GUARD = /datum/alt_title/security_guard,
JOB_ALT_SECURITY_DEPUTY = /datum/alt_title/security_guard, JOB_ALT_JUNIOR_OFFICER = /datum/alt_title/junior_officer, JOB_ALT_SECURITY_CONTRACTOR = /datum/alt_title/security_contractor)
min_age_by_species = list(SPECIES_PROMETHEAN = 3)
/datum/job/officer/get_request_reasons()
return list("Wildlife management", "Assembling expedition team")
// Security Officer Alt Titles
/datum/alt_title/junior_officer
title = JOB_ALT_JUNIOR_OFFICER
title_blurb = "A " + JOB_ALT_JUNIOR_OFFICER + " is an inexperienced " + JOB_SECURITY_OFFICER + ". They likely have training, but not experience, and are frequently \
paired off with a more senior co-worker. Junior Officers may also be expected to take over the boring duties of other Officers \
including patrolling the station or maintaining specific posts."
/datum/alt_title/patrol_officer
title = JOB_ALT_PATROL_OFFICER
/datum/alt_title/security_guard
title = JOB_ALT_SECURITY_GUARD
/datum/alt_title/security_deputy
title = JOB_ALT_SECURITY_DEPUTY
/datum/alt_title/security_contractor
title = JOB_ALT_SECURITY_CONTRACTOR
-75
View File
@@ -1,75 +0,0 @@
/datum/job/hos
disallow_jobhop = TRUE
pto_type = PTO_SECURITY
dept_time_required = 60
access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_construction,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
minimal_access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_construction,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
alt_titles = list(JOB_ALT_SECURITY_COMMANDER = /datum/alt_title/sec_commander, JOB_ALT_CHIEF_OF_SECURITY = /datum/alt_title/sec_chief, JOB_ALT_SECURITY_MANAGER = /datum/alt_title/security_manager)
/datum/alt_title/security_manager
title = JOB_ALT_SECURITY_MANAGER
/datum/job/hos/get_request_reasons()
return list("Wildlife management", "Forensic investigation", "Training crew", "Assembling expedition team")
/datum/job/warden
pto_type = PTO_SECURITY
dept_time_required = 20
alt_titles = list(JOB_ALT_BRIG_SENTRY = /datum/alt_title/brig_sentry, JOB_ALT_ARMORY_SUPERINTENDENT = /datum/alt_title/armory_superintendent, JOB_ALT_MASTERATARMS = /datum/alt_title/master_at_arms)
/datum/alt_title/brig_sentry
title = JOB_ALT_BRIG_SENTRY
/datum/alt_title/armory_superintendent
title = JOB_ALT_ARMORY_SUPERINTENDENT
/datum/alt_title/master_at_arms
title = JOB_ALT_MASTERATARMS
/datum/job/warden/get_request_reasons()
return list("Wildlife management")
/datum/job/detective
pto_type = PTO_SECURITY
alt_titles = list(JOB_ALT_INVESTIGATOR = /datum/alt_title/investigator, JOB_ALT_SECURITY_INSPECTOR = /datum/alt_title/security_inspector, JOB_ALT_FORENSIC_TECHNICIAN = /datum/alt_title/forensic_tech)
/datum/alt_title/investigator
title = JOB_ALT_INVESTIGATOR
/datum/alt_title/security_inspector
title = JOB_ALT_SECURITY_INSPECTOR
/datum/job/detective/get_request_reasons()
return list("Forensic investigation")
/datum/job/officer
total_positions = 5
spawn_positions = 5
pto_type = PTO_SECURITY
alt_titles = list(JOB_ALT_PATROL_OFFICER = /datum/alt_title/patrol_officer, JOB_ALT_SECURITY_GUARD = /datum/alt_title/security_guard,
JOB_ALT_SECURITY_DEPUTY = /datum/alt_title/security_guard, JOB_ALT_JUNIOR_OFFICER = /datum/alt_title/junior_officer, JOB_ALT_SECURITY_CONTRACTOR = /datum/alt_title/security_contractor)
/datum/alt_title/patrol_officer
title = JOB_ALT_PATROL_OFFICER
/datum/alt_title/security_guard
title = JOB_ALT_SECURITY_GUARD
/datum/alt_title/security_deputy
title = JOB_ALT_SECURITY_DEPUTY
/datum/alt_title/security_contractor
title = JOB_ALT_SECURITY_CONTRACTOR
/datum/job/officer/get_request_reasons()
return list("Wildlife management", "Assembling expedition team")
+6 -2
View File
@@ -19,6 +19,8 @@
has_headset = FALSE
assignable = FALSE
mob_type = JOB_SILICON_AI
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
outfit_type = /decl/hierarchy/outfit/job/silicon/ai
job_description = "The " + JOB_AI + " oversees the operation of the station and its crew, but has no real authority over them. \
The " + JOB_AI + " is required to follow its Laws, and Lawbound Synthetics that are linked to it are expected to follow \
@@ -46,8 +48,10 @@
departments = list(DEPARTMENT_SYNTHETIC)
department_flag = ENGSEC
faction = FACTION_STATION
total_positions = 2
spawn_positions = 2
pto_type = PTO_CYBORG
minimal_player_age = 3 //1 day is a little too little time
total_positions = 4 //Along with one able to spawn later in the round.
spawn_positions = 3 //Let's have 3 able to spawn in roundstart
supervisors = "your Laws and the " + JOB_AI //Nodrak
selection_color = "#254C25"
minimal_player_age = 1
-9
View File
@@ -1,9 +0,0 @@
/datum/job/ai
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
/datum/job/cyborg
pto_type = PTO_CYBORG
minimal_player_age = 3 //1 day is a little too little time
total_positions = 4 //Along with one able to spawn later in the round.
spawn_positions = 3 //Let's have 3 able to spawn in roundstart

Some files were not shown because too many files have changed in this diff Show More