Bridge Assistant Station Trait (#80279)

## About The Pull Request
adds a station trait which adds a new role, the bridge assistant
he is designed to help commandeer the bridge and help out other heads
when needed. he is armed with the mini energy gun (the one heads used to
have on kilostation), a flash, a toolbelt (with an inducer), some cool
shades and a swanky scarf.
as he is a nerd he is weak and unable to twohand weapons, preventing him
from wielding the fire axe.
currently he does not have a mindshield but he cannot roll antag
he currently has access to the bridge, announcement console, eva,
teleporter, gateway, maint, and a weapon permit (somewhat (not really
other than for nerds) interestingly this is the first job that isnt
assistant that doesnt have access to any lathes, so he doesnt have orm
access unlike all the other jobs (except assistant))
the trait also makes a coffee machine spawn on the bridge
here is some useful art of your role

![image](https://github.com/tgstation/tgstation/assets/23585223/905e5527-9069-4226-b160-8dedd1ea7b74)
and ingame screenshots

![image](https://github.com/tgstation/tgstation/assets/23585223/0aa537ac-a791-4249-a702-490584919fd9)

![image](https://github.com/tgstation/tgstation/assets/23585223/eb93e2d1-0291-4ade-9208-b1c0b68648c7)

![image](https://github.com/tgstation/tgstation/assets/23585223/1d3c2f11-8ac0-4ee9-91a5-176f81a08dcb)


## Why It's Good For The Game
Adds upon the station trait job system with a straight forward role that
IS just a human (unlike the cargorilla), and is pretty basic with no
custom assets or whatever other than hud icons
Having the bridge assistant in some rounds seems like a neat way to
protect it since it gets fucked up in like half the time, while also not
having enough mechanical depth or gameplay as to warrant it as a
permanent role

## Changelog
🆑
add: Bridge Assistant job accessible from a station trait.
/🆑

---------

Co-authored-by: san7890 <the@san7890.com>
This commit is contained in:
Fikou
2023-12-17 02:02:45 +01:00
committed by GitHub
parent fb01a2bf98
commit a3fa541e2e
33 changed files with 347 additions and 115 deletions
+1
View File
@@ -83,6 +83,7 @@
#define SECHUD_BARTENDER "hudbartender"
#define SECHUD_BITRUNNER "hudbitrunner"
#define SECHUD_BOTANIST "hudbotanist"
#define SECHUD_BRIDGE_ASSISTANT "hudbridgeassistant"
#define SECHUD_CAPTAIN "hudcaptain"
#define SECHUD_CARGO_TECHNICIAN "hudcargotechnician"
#define SECHUD_CHAPLAIN "hudchaplain"
+39 -35
View File
@@ -48,6 +48,7 @@
#define JOB_RESEARCH_DIRECTOR "Research Director"
#define JOB_CHIEF_ENGINEER "Chief Engineer"
#define JOB_CHIEF_MEDICAL_OFFICER "Chief Medical Officer"
#define JOB_BRIDGE_ASSISTANT "Bridge Assistant"
//Silicon
#define JOB_AI "AI"
#define JOB_CYBORG "Cyborg"
@@ -122,41 +123,42 @@
#define JOB_DISPLAY_ORDER_ASSISTANT 1
#define JOB_DISPLAY_ORDER_CAPTAIN 2
#define JOB_DISPLAY_ORDER_HEAD_OF_PERSONNEL 3
#define JOB_DISPLAY_ORDER_BARTENDER 4
#define JOB_DISPLAY_ORDER_BOTANIST 5
#define JOB_DISPLAY_ORDER_COOK 6
#define JOB_DISPLAY_ORDER_JANITOR 7
#define JOB_DISPLAY_ORDER_CLOWN 8
#define JOB_DISPLAY_ORDER_MIME 9
#define JOB_DISPLAY_ORDER_CURATOR 10
#define JOB_DISPLAY_ORDER_LAWYER 11
#define JOB_DISPLAY_ORDER_CHAPLAIN 12
#define JOB_DISPLAY_ORDER_PSYCHOLOGIST 13
#define JOB_DISPLAY_ORDER_AI 14
#define JOB_DISPLAY_ORDER_CYBORG 15
#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 16
#define JOB_DISPLAY_ORDER_STATION_ENGINEER 17
#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 18
#define JOB_DISPLAY_ORDER_QUARTERMASTER 19
#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 20
#define JOB_DISPLAY_ORDER_SHAFT_MINER 21
#define JOB_DISPLAY_ORDER_BITRUNNER 22
#define JOB_DISPLAY_ORDER_CARGO_GORILLA 23
#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 24
#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 25
#define JOB_DISPLAY_ORDER_PARAMEDIC 26
#define JOB_DISPLAY_ORDER_CHEMIST 27
#define JOB_DISPLAY_ORDER_VIROLOGIST 28
#define JOB_DISPLAY_ORDER_CORONER 29
#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 30
#define JOB_DISPLAY_ORDER_SCIENTIST 31
#define JOB_DISPLAY_ORDER_ROBOTICIST 32
#define JOB_DISPLAY_ORDER_GENETICIST 33
#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 34
#define JOB_DISPLAY_ORDER_WARDEN 35
#define JOB_DISPLAY_ORDER_DETECTIVE 36
#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 37
#define JOB_DISPLAY_ORDER_PRISONER 38
#define JOB_DISPLAY_ORDER_BRIDGE_ASSISTANT 4
#define JOB_DISPLAY_ORDER_BARTENDER 5
#define JOB_DISPLAY_ORDER_BOTANIST 6
#define JOB_DISPLAY_ORDER_COOK 7
#define JOB_DISPLAY_ORDER_JANITOR 8
#define JOB_DISPLAY_ORDER_CLOWN 9
#define JOB_DISPLAY_ORDER_MIME 10
#define JOB_DISPLAY_ORDER_CURATOR 11
#define JOB_DISPLAY_ORDER_LAWYER 12
#define JOB_DISPLAY_ORDER_CHAPLAIN 13
#define JOB_DISPLAY_ORDER_PSYCHOLOGIST 14
#define JOB_DISPLAY_ORDER_AI 15
#define JOB_DISPLAY_ORDER_CYBORG 16
#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 17
#define JOB_DISPLAY_ORDER_STATION_ENGINEER 18
#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 19
#define JOB_DISPLAY_ORDER_QUARTERMASTER 20
#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 21
#define JOB_DISPLAY_ORDER_SHAFT_MINER 22
#define JOB_DISPLAY_ORDER_BITRUNNER 23
#define JOB_DISPLAY_ORDER_CARGO_GORILLA 24
#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 25
#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 26
#define JOB_DISPLAY_ORDER_PARAMEDIC 27
#define JOB_DISPLAY_ORDER_CHEMIST 28
#define JOB_DISPLAY_ORDER_VIROLOGIST 29
#define JOB_DISPLAY_ORDER_CORONER 30
#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 31
#define JOB_DISPLAY_ORDER_SCIENTIST 32
#define JOB_DISPLAY_ORDER_ROBOTICIST 33
#define JOB_DISPLAY_ORDER_GENETICIST 34
#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 35
#define JOB_DISPLAY_ORDER_WARDEN 36
#define JOB_DISPLAY_ORDER_DETECTIVE 37
#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 38
#define JOB_DISPLAY_ORDER_PRISONER 39
#define DEPARTMENT_UNASSIGNED "No Department"
@@ -209,6 +211,8 @@
/// Combination flag for jobs which are considered regular crew members of the station.
#define STATION_JOB_FLAGS (JOB_ANNOUNCE_ARRIVAL|JOB_CREW_MANIFEST|JOB_EQUIP_RANK|JOB_CREW_MEMBER|JOB_NEW_PLAYER_JOINABLE|JOB_REOPEN_ON_ROUNDSTART_LOSS|JOB_ASSIGN_QUIRKS|JOB_CAN_BE_INTERN)
/// Combination flag for jobs which should be there for every station trait job.
#define STATION_TRAIT_JOB_FLAGS (JOB_CANNOT_OPEN_SLOTS|JOB_HIDE_WHEN_EMPTY|JOB_LATEJOIN_ONLY&~JOB_REOPEN_ON_ROUNDSTART_LOSS)
#define FACTION_NONE "None"
#define FACTION_STATION "Station"
+6
View File
@@ -489,6 +489,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Is the mob standing on an elevated surface? This prevents them from dropping down if not elevated first.
#define TRAIT_ON_ELEVATED_SURFACE "on_elevated_surface"
// Prevents you from twohanding weapons.
#define TRAIT_NO_TWOHANDING "no_twohanding"
// METABOLISMS
// Various jobs on the station have historically had better reactions
// to various drinks and foodstuffs. Security liking donuts is a classic
@@ -817,6 +820,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Similar trait given to temporary bodies inhabited by players
#define TRAIT_TEMPORARY_BODY "temporary_body"
/// Trait given to objects with the wallmounted component
#define TRAIT_WALLMOUNTED "wallmounted"
/// Trait given to mechs that can have orebox functionality on movement
#define TRAIT_OREBOX_FUNCTIONAL "orebox_functional"
+4
View File
@@ -98,6 +98,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
/datum/wound = list(
"TRAIT_WOUND_SCANNED" = TRAIT_WOUND_SCANNED,
),
/obj = list(
"TRAIT_WALLMOUNTED" = TRAIT_WALLMOUNTED,
),
/mob = list(
"TRAIT_ABDUCTOR_SCIENTIST_TRAINING" = TRAIT_ABDUCTOR_SCIENTIST_TRAINING,
"TRAIT_ABDUCTOR_TRAINING" = TRAIT_ABDUCTOR_TRAINING,
@@ -304,6 +307,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_NO_SOUL" = TRAIT_NO_SOUL,
"TRAIT_NO_STRIP" = TRAIT_NO_STRIP,
"TRAIT_NO_TRANSFORM" = TRAIT_NO_TRANSFORM,
"TRAIT_NO_TWOHANDING" = TRAIT_NO_TWOHANDING,
"TRAIT_NOCRITDAMAGE" = TRAIT_NOCRITDAMAGE,
"TRAIT_NO_UNDERWEAR" = TRAIT_NO_UNDERWEAR,
"TRAIT_NO_ZOMBIFY" = TRAIT_NO_ZOMBIFY,
+1 -1
View File
@@ -39,7 +39,7 @@
var/y_offset = 397
var/y_button_offset = 27
for (var/datum/station_trait/trait as anything in GLOB.lobby_station_traits)
if (!trait.can_display_lobby_button())
if (!trait.can_display_lobby_button(mymob.client))
continue
var/atom/movable/screen/lobby/button/sign_up/sign_up_button = new(our_hud = src)
sign_up_button.SlowInit()
@@ -931,6 +931,9 @@ SUBSYSTEM_DEF(dynamic)
stack_trace("Invalid dynamic configuration variable [variable] in [ruleset.ruletype] [ruleset.name].")
continue
ruleset.vars[variable] = rule_conf[variable]
ruleset.restricted_roles |= SSstation.antag_restricted_roles
if(length(ruleset.protected_roles)) //if we care to protect any role, we should protect station trait roles too
ruleset.protected_roles |= SSstation.antag_protected_roles
if(CONFIG_GET(flag/protect_roles_from_antagonist))
ruleset.restricted_roles |= ruleset.protected_roles
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
@@ -11,6 +11,10 @@ PROCESSING_SUBSYSTEM_DEF(station)
var/list/selectable_traits_by_types = list(STATION_TRAIT_POSITIVE = list(), STATION_TRAIT_NEUTRAL = list(), STATION_TRAIT_NEGATIVE = list())
///Currently active announcer. Starts as a type but gets initialized after traits are selected
var/datum/centcom_announcer/announcer = /datum/centcom_announcer/default
///A list of trait roles that should be protected from antag
var/list/antag_protected_roles = list()
///A list of trait roles that should never be able to roll antag
var/list/antag_restricted_roles = list()
/datum/controller/subsystem/processing/station/Initialize()
+12 -4
View File
@@ -173,17 +173,25 @@
/datum/component/two_handed/proc/wield(mob/living/carbon/user)
if(wielded)
return
var/atom/atom_parent = parent
if(HAS_TRAIT(user, TRAIT_NO_TWOHANDING))
if(require_twohands)
atom_parent.balloon_alert(user, "too weak to wield!")
user.dropItemToGround(parent, force = TRUE)
else
atom_parent.balloon_alert(user, "too weak to wield with both hands!")
return
if(user.get_inactive_held_item())
if(require_twohands)
to_chat(user, span_notice("[parent] is too cumbersome to carry in one hand!"))
user.dropItemToGround(parent, force=TRUE)
atom_parent.balloon_alert(user, "can't carry in one hand!")
user.dropItemToGround(parent, force = TRUE)
else
to_chat(user, span_warning("You need your other hand to be empty!"))
atom_parent.balloon_alert(user, "holding something in other hand!")
return
if(user.usable_hands < 2)
if(require_twohands)
user.dropItemToGround(parent, force=TRUE)
to_chat(user, span_warning("You don't have enough intact hands."))
atom_parent.balloon_alert(user, "not enough hands!")
return
// wield update status
+2
View File
@@ -16,12 +16,14 @@
on_drop = on_drop_callback
/datum/component/wall_mounted/RegisterWithParent()
ADD_TRAIT(parent, TRAIT_WALLMOUNTED, REF(src))
RegisterSignal(hanging_wall_turf, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
RegisterSignal(hanging_wall_turf, COMSIG_TURF_CHANGE, PROC_REF(on_turf_changing))
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(drop_wallmount))
RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_linked_destroyed))
/datum/component/wall_mounted/UnregisterFromParent()
REMOVE_TRAIT(parent, TRAIT_WALLMOUNTED, REF(src))
UnregisterSignal(hanging_wall_turf, list(COMSIG_ATOM_EXAMINE, COMSIG_TURF_CHANGE))
UnregisterSignal(parent, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED))
hanging_wall_turf = null
+22
View File
@@ -202,6 +202,28 @@
)
job = /datum/job/botanist
/datum/id_trim/job/bridge_assistant
assignment = "Bridge Assistant"
trim_state = "trim_assistant"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_COMMAND_BLUE
sechud_icon_state = SECHUD_BRIDGE_ASSISTANT
minimal_access = list(
ACCESS_COMMAND,
ACCESS_EVA,
ACCESS_GATEWAY,
ACCESS_MAINT_TUNNELS,
ACCESS_RC_ANNOUNCE,
ACCESS_TELEPORTER,
ACCESS_WEAPONS,
)
extra_access = list()
template_access = list(
ACCESS_CAPTAIN,
ACCESS_CHANGE_IDS,
)
job = /datum/job/bridge_assistant
/datum/id_trim/job/captain
assignment = "Captain"
intern_alt_name = "Captain-in-Training"
+33
View File
@@ -160,3 +160,36 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new)
target.rank = assignment
target.trim = trim
/datum/manifest/ui_state(mob/user)
return GLOB.always_state
/datum/manifest/ui_status(mob/user, datum/ui_state/state)
return (isnewplayer(user) || isobserver(user) || isAI(user) || ispAI(user) || user.client?.holder) ? UI_INTERACTIVE : UI_CLOSE
/datum/manifest/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "CrewManifest")
ui.open()
/datum/manifest/ui_data(mob/user)
var/list/positions = list()
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
var/open = 0
var/list/exceptions = list()
for(var/datum/job/job as anything in department.department_jobs)
if(job.total_positions == -1)
exceptions += job.title
continue
var/open_slots = job.total_positions - job.current_positions
if(open_slots < 1)
continue
open += open_slots
positions[department.department_name] = list("exceptions" = exceptions, "open" = open)
return list(
"manifest" = get_manifest(),
"positions" = positions
)
+1 -1
View File
@@ -83,7 +83,7 @@ GLOBAL_LIST_EMPTY(lobby_station_traits)
return
/// Return TRUE if we want to show a lobby button, by default we assume we don't want it after the round begins
/datum/station_trait/proc/can_display_lobby_button()
/datum/station_trait/proc/can_display_lobby_button(client/player)
return sign_up_button && !SSticker.HasRoundStarted()
/// Apply any additional handling we need to our lobby button
+81 -6
View File
@@ -1,3 +1,7 @@
#define CAN_ROLL_ALWAYS 1 //always can roll for antag
#define CAN_ROLL_PROTECTED 2 //can roll if config lets protected roles roll
#define CAN_ROLL_NEVER 3 //never roll antag
/**
* A station trait which enables a temporary job
* Generally speaking these should always all be mutually exclusive, don't have too many at once
@@ -7,13 +11,22 @@
abstract_type = /datum/station_trait/job
/// What tooltip to show on the button
var/button_desc = "Sign up to gain some kind of unusual job, not available in most rounds."
/// Can this job roll antag?
var/can_roll_antag = CAN_ROLL_ALWAYS
/// How many positions to spawn?
var/position_amount = 1
/// Type of job to enable
var/job_to_add = /datum/job/clown
var/datum/job/job_to_add = /datum/job/clown
/// Who signed up to this in the lobby
var/list/lobby_candidates
/datum/station_trait/job/New()
. = ..()
switch(can_roll_antag)
if(CAN_ROLL_PROTECTED)
SSstation.antag_protected_roles += job_to_add::title
if(CAN_ROLL_NEVER)
SSstation.antag_restricted_roles += job_to_add::title
blacklist += subtypesof(/datum/station_trait/job) - type // All but ourselves
RegisterSignal(SSdcs, COMSIG_GLOB_PRE_JOBS_ASSIGNED, PROC_REF(pre_jobs_assigned))
@@ -50,16 +63,19 @@
if (!LAZYLEN(lobby_candidates))
on_failed_assignment()
return // Nobody signed up :(
var/mob/dead/new_player/picked_player = pick(lobby_candidates)
picked_player.mind.assigned_role = new job_to_add()
for(var/_ in 1 to position_amount)
var/mob/dead/new_player/picked_player = pick_n_take(lobby_candidates)
picked_player.mind.assigned_role = new job_to_add()
lobby_candidates = null
/// Called if we didn't assign a role before the round began, we add it to the latejoin menu instead
/datum/station_trait/job/proc/on_failed_assignment()
var/datum/job/our_job = job_to_add
our_job = SSjob.GetJob(our_job::title)
our_job.total_positions++
var/datum/job/our_job = SSjob.GetJob(job_to_add::title)
our_job.total_positions = position_amount
/datum/station_trait/job/can_display_lobby_button(client/player)
var/datum/job/our_job = SSjob.GetJob(job_to_add::title)
return our_job.player_old_enough(player) && ..()
/// Adds a gorilla to the cargo department, replacing the sloth and the mech
/datum/station_trait/job/cargorilla
@@ -67,6 +83,7 @@
button_desc = "Sign up to become the Cargo Gorilla, a peaceful shepherd of boxes."
weight = 1
show_in_report = FALSE // Selective attention test. Did you spot the gorilla?
can_roll_antag = CAN_ROLL_NEVER
job_to_add = /datum/job/cargo_gorilla
/datum/station_trait/job/cargorilla/New()
@@ -92,3 +109,61 @@
// monkey carries the crates, the age of robot is over
if(GLOB.cargo_ripley)
qdel(GLOB.cargo_ripley)
/datum/station_trait/job/bridge_assistant
name = "Bridge Assistant"
button_desc = "Sign up to become the Bridge Assistant and watch over the Bridge."
weight = 2
report_message = "We have installed a Bridge Assistant on your station."
show_in_report = TRUE
can_roll_antag = CAN_ROLL_PROTECTED
job_to_add = /datum/job/bridge_assistant
/datum/station_trait/job/bridge_assistant/New()
. = ..()
RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(add_coffeemaker))
/datum/station_trait/job/bridge_assistant/on_lobby_button_update_overlays(atom/movable/screen/lobby/button/sign_up/lobby_button, list/overlays)
. = ..()
overlays += "bridge_assistant"
/// Creates a coffeemaker in the bridge, if we don't have one yet.
/datum/station_trait/job/bridge_assistant/proc/add_coffeemaker(datum/source)
SIGNAL_HANDLER
var/area/bridge = GLOB.areas_by_type[/area/station/command/bridge]
if(isnull(bridge)) //no bridge, what will he assist?
return
var/list/possible_coffeemaker_positions = list(/area/station/command/bridge, /area/station/command/meeting_room)
var/list/coffeemakers = SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/coffeemaker)
for(var/obj/machinery/coffeemaker as anything in coffeemakers) //don't spawn a coffeemaker if there is already one on the bridge
if(is_type_in_list(get_area(coffeemaker), possible_coffeemaker_positions))
return
var/list/tables = list()
for(var/turf/area_turf as anything in bridge.get_contained_turfs())
var/obj/structure/table/table = locate() in area_turf
if(isnull(table))
continue
if(area_turf.is_blocked_turf(ignore_atoms = list(table))) //don't spawn a coffeemaker on a fax machine or smth
continue
tables += table
if(!length(tables))
return
var/picked_table = pick_n_take(tables)
var/picked_turf = get_turf(picked_table)
if(length(tables))
var/another_table = pick(tables)
for(var/obj/thing_on_table in picked_turf) //if there's paper bins or other shit on the table, get that off
if(thing_on_table == picked_table)
continue
if(HAS_TRAIT(thing_on_table, TRAIT_WALLMOUNTED) || (thing_on_table.flags_1 & ON_BORDER_1) || thing_on_table.layer < TABLE_LAYER)
continue
if(thing_on_table.invisibility || !thing_on_table.alpha || !thing_on_table.mouse_opacity)
continue
thing_on_table.forceMove(get_turf(another_table))
new /obj/machinery/coffeemaker/impressa(picked_turf)
new /obj/item/reagent_containers/cup/coffeepot(picked_turf)
new /obj/item/storage/box/coffeepack(picked_turf)
#undef CAN_ROLL_ALWAYS
#undef CAN_ROLL_PROTECTED
#undef CAN_ROLL_NEVER
+3 -3
View File
@@ -2,7 +2,7 @@
name = "Bananium Shipment"
trait_type = STATION_TRAIT_NEUTRAL
weight = 5
report_message = "Rumors has it that the clown planet has been sending support packages to clowns in this system"
report_message = "Rumors has it that the clown planet has been sending support packages to clowns in this system."
trait_to_give = STATION_TRAIT_BANANIUM_SHIPMENTS
/datum/station_trait/unnatural_atmosphere
@@ -10,7 +10,7 @@
trait_type = STATION_TRAIT_NEUTRAL
weight = 5
show_in_report = TRUE
report_message = "System's local planet has irregular atmospherical properties"
report_message = "System's local planet has irregular atmospherical properties."
trait_to_give = STATION_TRAIT_UNNATURAL_ATMOSPHERE
// This station trait modifies the atmosphere, which is too far past the time admins are able to revert it
@@ -197,7 +197,7 @@
/datum/station_trait/birthday/proc/announce_birthday()
report_message = "We here at Nanotrasen would all like to wish [birthday_person ? birthday_person_name : "Employee Name"] a very happy birthday"
report_message = "We here at Nanotrasen would all like to wish [birthday_person ? birthday_person_name : "Employee Name"] a very happy birthday."
priority_announce("Happy birthday to [birthday_person ? birthday_person_name : "Employee Name"]! Nanotrasen wishes you a very happy [birthday_person ? thtotext(birthday_person.age + 1) : "255th"] birthday.")
if(birthday_person)
playsound(birthday_person, 'sound/items/party_horn.ogg', 50)
+20
View File
@@ -190,6 +190,26 @@
to_preload += /obj/item/extinguisher/mini
return to_preload
/obj/item/storage/belt/utility/full/inducer/PopulateContents()
SSwardrobe.provide_type(/obj/item/screwdriver, src)
SSwardrobe.provide_type(/obj/item/wrench, src)
SSwardrobe.provide_type(/obj/item/weldingtool, src)
SSwardrobe.provide_type(/obj/item/crowbar/red, src)
SSwardrobe.provide_type(/obj/item/wirecutters, src)
SSwardrobe.provide_type(/obj/item/multitool, src)
SSwardrobe.provide_type(/obj/item/inducer, src)
/obj/item/storage/belt/utility/full/inducer/get_types_to_preload()
var/list/to_preload = list() //Yes this is a pain. Yes this is the point
to_preload += /obj/item/screwdriver
to_preload += /obj/item/wrench
to_preload += /obj/item/weldingtool
to_preload += /obj/item/crowbar
to_preload += /obj/item/wirecutters
to_preload += /obj/item/multitool
to_preload += /obj/item/inducer
return to_preload
/obj/item/storage/belt/utility/syndicate
preload = FALSE
+1 -6
View File
@@ -51,12 +51,7 @@
if(!SSticker.HasRoundStarted())
tgui_alert(usr, "The game hasn't started yet!")
return
var/data = "<b>Showing Crew Manifest.</b><hr>"
data += "<table cellspacing=5 border=1><tr><th>Name</th><th>Position</th></tr>"
for(var/datum/record/crew/entry in GLOB.manifest.general)
data += "<tr><td>[entry.name]</td><td>[entry.rank][entry.rank != entry.trim ? " ([entry.trim])" : ""]</td></tr>"
data += "</table>"
usr << browse(data, "window=manifest;size=440x410")
GLOB.manifest.ui_interact(usr)
/datum/admins/proc/output_ai_laws()
var/law_bound_entities = 0
+1 -1
View File
@@ -29,7 +29,7 @@
/obj/item/food/cornchips/blue = 1,
)
rpg_title = "Recluse"
job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN
job_flags = STATION_JOB_FLAGS
/datum/outfit/job/bitrunner
name = "Bitrunner"
@@ -288,3 +288,10 @@
uniform = /obj/item/clothing/under/plasmaman/bitrunner
gloves = /obj/item/clothing/gloves/color/plasmaman/black
head = /obj/item/clothing/head/helmet/space/plasmaman/bitrunner
/datum/outfit/plasmaman/bridge_assistant
name = "Bridge Assistant Plasmaman"
uniform = /obj/item/clothing/under/plasmaman //call me when this is gags and not 10 million new assets
gloves = /obj/item/clothing/gloves/color/plasmaman/black
head = /obj/item/clothing/head/helmet/space/plasmaman
+7 -2
View File
@@ -45,14 +45,16 @@ Assistant
/datum/outfit/job/assistant/pre_equip(mob/living/carbon/human/target)
..()
give_hat()
give_jumpsuit(target)
/datum/outfit/job/assistant/proc/give_hat()
for(var/holidayname in GLOB.holidays)
var/datum/holiday/holiday_today = GLOB.holidays[holidayname]
var/obj/item/special_hat = holiday_today.holiday_hat
if(prob(HOLIDAY_HAT_CHANCE) && !isnull(special_hat) && isnull(head))
head = special_hat
give_jumpsuit(target)
/datum/outfit/job/assistant/proc/give_jumpsuit(mob/living/carbon/human/target)
var/static/jumpsuit_number = 0
jumpsuit_number += 1
@@ -73,6 +75,9 @@ Assistant
/datum/outfit/job/assistant/consistent
name = "Assistant - Consistent"
/datum/outfit/job/assistant/consistent/give_hat()
return
/datum/outfit/job/assistant/consistent/give_jumpsuit(mob/living/carbon/human/target)
uniform = /obj/item/clothing/under/color/grey
+1 -1
View File
@@ -23,7 +23,7 @@
family_heirlooms = list(/obj/item/pen/blue)
rpg_title = "Defeated Miniboss"
job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN | JOB_CANNOT_OPEN_SLOTS
job_flags = STATION_JOB_FLAGS | JOB_CANNOT_OPEN_SLOTS & ~JOB_REOPEN_ON_ROUNDSTART_LOSS
/datum/job/prisoner/New()
. = ..()
@@ -0,0 +1,79 @@
/datum/job/bridge_assistant
title = JOB_BRIDGE_ASSISTANT
description = "Watch over the Bridge, command its consoles, and spend your days brewing coffee for higher-ups."
auto_deadmin_role_flags = DEADMIN_POSITION_HEAD //not really a head but close enough
department_head = list(JOB_CAPTAIN)
faction = FACTION_STATION
total_positions = 0
spawn_positions = 0
supervisors = "the Captain, and in non-Bridge related situations the other heads"
minimal_player_age = 7
exp_requirements = 300
exp_required_type = EXP_TYPE_CREW
exp_granted_type = EXP_TYPE_CREW
config_tag = "BRIDGE_ASSISTANT"
outfit = /datum/outfit/job/bridge_assistant
plasmaman_outfit = /datum/outfit/plasmaman/bridge_assistant
paycheck = PAYCHECK_CREW
paycheck_department = ACCOUNT_CIV
liver_traits = list(TRAIT_PRETENDER_ROYAL_METABOLISM)
display_order = JOB_DISPLAY_ORDER_BRIDGE_ASSISTANT
departments_list = list(/datum/job_department/command)
family_heirlooms = list(/obj/item/banner/command/mundane)
mail_goodies = list(
/obj/item/storage/fancy/cigarettes = 1,
/obj/item/pen/fountain = 1,
)
rpg_title = "Royal Guard"
allow_bureaucratic_error = FALSE
job_flags = STATION_JOB_FLAGS | STATION_TRAIT_JOB_FLAGS
ignore_human_authority = TRUE
/datum/job/bridge_assistant/after_spawn(mob/living/spawned, client/player_client)
. = ..()
ADD_TRAIT(spawned, TRAIT_NO_TWOHANDING, JOB_TRAIT)
/datum/job/bridge_assistant/get_roundstart_spawn_point()
var/list/chair_turfs = list()
var/list/possible_turfs = list()
var/area/bridge = GLOB.areas_by_type[/area/station/command/bridge]
if(isnull(bridge))
return ..() //if no bridge, spawn on the arrivals shuttle (but also what the fuck)
for(var/turf/possible_turf as anything in bridge.get_contained_turfs())
if(possible_turf.is_blocked_turf())
continue
if(locate(/obj/structure/chair) in possible_turf)
chair_turfs += possible_turf
continue
possible_turfs += possible_turf
if(length(chair_turfs))
return pick(chair_turfs) //prioritize turfs with a chair
if(length(possible_turfs))
return pick(possible_turfs) //if none, just pick a random turf in the bridge
return ..() //if the bridge has no turfs, spawn on the arrivals shuttle
/datum/outfit/job/bridge_assistant
name = "Bridge Assistant"
jobtype = /datum/job/bridge_assistant
id_trim = /datum/id_trim/job/bridge_assistant
backpack_contents = list(
/obj/item/modular_computer/pda/bridge_assistant = 1,
)
uniform = /obj/item/clothing/under/trek/command/next
neck = /obj/item/clothing/neck/large_scarf/blue
belt = /obj/item/storage/belt/utility/full/inducer
ears = /obj/item/radio/headset/headset_com
glasses = /obj/item/clothing/glasses/sunglasses
gloves = /obj/item/clothing/gloves/fingerless
head = /obj/item/clothing/head/soft/black
shoes = /obj/item/clothing/shoes/laceup
l_pocket = /obj/item/gun/energy/e_gun/mini
r_pocket = /obj/item/assembly/flash/handheld
@@ -16,7 +16,7 @@
)
rpg_title = "Beast of Burden"
allow_bureaucratic_error = FALSE
job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_NEW_PLAYER_JOINABLE | JOB_EQUIP_RANK | JOB_CANNOT_OPEN_SLOTS | JOB_HIDE_WHEN_EMPTY | JOB_LATEJOIN_ONLY
job_flags = STATION_TRAIT_JOB_FLAGS | JOB_ANNOUNCE_ARRIVAL | JOB_NEW_PLAYER_JOINABLE | JOB_EQUIP_RANK
/datum/job/cargo_gorilla/get_roundstart_spawn_point()
if (length(GLOB.gorilla_start))
-38
View File
@@ -1,38 +0,0 @@
/datum/crew_manifest
/datum/crew_manifest/ui_state(mob/user)
return GLOB.always_state
/datum/crew_manifest/ui_status(mob/user, datum/ui_state/state)
return (isnewplayer(user) || isobserver(user) || isAI(user) || ispAI(user)) ? UI_INTERACTIVE : UI_CLOSE
/datum/crew_manifest/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "CrewManifest")
ui.open()
/datum/crew_manifest/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
/datum/crew_manifest/ui_data(mob/user)
var/list/positions = list()
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
var/open = 0
var/list/exceptions = list()
for(var/datum/job/job as anything in department.department_jobs)
if(job.total_positions == -1)
exceptions += job.title
continue
var/open_slots = job.total_positions - job.current_positions
if(open_slots < 1)
continue
open += open_slots
positions[department.department_name] = list("exceptions" = exceptions, "open" = open)
return list(
"manifest" = GLOB.manifest.get_manifest(),
"positions" = positions
)
@@ -296,10 +296,7 @@
return
client.crew_manifest_delay = world.time + (1 SECONDS)
if(!GLOB.crew_manifest_tgui)
GLOB.crew_manifest_tgui = new /datum/crew_manifest(src)
GLOB.crew_manifest_tgui.ui_interact(src)
GLOB.manifest.ui_interact(src)
/mob/dead/new_player/Move()
return 0
+1 -4
View File
@@ -711,10 +711,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
client.crew_manifest_delay = world.time + (1 SECONDS)
if(!GLOB.crew_manifest_tgui)
GLOB.crew_manifest_tgui = new /datum/crew_manifest(src)
GLOB.crew_manifest_tgui.ui_interact(src)
GLOB.manifest.ui_interact(src)
//this is called when a ghost is drag clicked to something.
/mob/dead/observer/MouseDrop(atom/over)
+1 -4
View File
@@ -349,10 +349,7 @@
return
client.crew_manifest_delay = world.time + (1 SECONDS)
if(!GLOB.crew_manifest_tgui)
GLOB.crew_manifest_tgui = new /datum/crew_manifest(src)
GLOB.crew_manifest_tgui.ui_interact(src)
GLOB.manifest.ui_interact(src)
/mob/living/silicon/proc/set_autosay() //For allowing the AI and borgs to set the radio behavior of auto announcements (state laws, arrivals).
if(!radio)
@@ -103,7 +103,7 @@
/obj/item/modular_computer/pda/heads/quartermaster
name = "quartermaster PDA"
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#c4b787#18191e#8b4c31"
inserted_item = /obj/item/pen/survival
stored_paper = 20
@@ -412,7 +412,7 @@
)
/**
* No Department
* No Department/Station Trait
*/
/obj/item/modular_computer/pda/assistant
@@ -421,6 +421,14 @@
/datum/computer_file/program/bounty_board,
)
/obj/item/modular_computer/pda/bridge_assistant
name = "bridge assistant PDA"
greyscale_colors = "#374f7e#a92323"
starting_programs = list(
/datum/computer_file/program/crew_manifest,
/datum/computer_file/program/status,
)
/**
* Non-roles
*/
@@ -6,5 +6,7 @@
for(var/datum/job/job as anything in subtypesof(/datum/job))
if(!(initial(job.job_flags) & JOB_CREW_MEMBER))
continue
if((initial(job.job_flags) & STATION_TRAIT_JOB_FLAGS) == STATION_TRAIT_JOB_FLAGS)
continue
if(!(job in cyber_trait.job_to_cybernetic))
TEST_FAIL("Job [job] does not have an assigned cybernetic for [cyber_trait.type] station trait.")
Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 B

After

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

+2 -2
View File
@@ -4116,7 +4116,6 @@
#include "code\modules\jobs\job_types\bartender.dm"
#include "code\modules\jobs\job_types\botanist.dm"
#include "code\modules\jobs\job_types\captain.dm"
#include "code\modules\jobs\job_types\cargo_gorilla.dm"
#include "code\modules\jobs\job_types\cargo_technician.dm"
#include "code\modules\jobs\job_types\chemist.dm"
#include "code\modules\jobs\job_types\chief_engineer.dm"
@@ -4201,6 +4200,8 @@
#include "code\modules\jobs\job_types\spawner\syndicate_cybersun_captain.dm"
#include "code\modules\jobs\job_types\spawner\venus_human_trap.dm"
#include "code\modules\jobs\job_types\spawner\zombie.dm"
#include "code\modules\jobs\job_types\station_trait\bridge_assistant.dm"
#include "code\modules\jobs\job_types\station_trait\cargo_gorilla.dm"
#include "code\modules\keybindings\bindings_atom.dm"
#include "code\modules\keybindings\bindings_client.dm"
#include "code\modules\keybindings\focus.dm"
@@ -4425,7 +4426,6 @@
#include "code\modules\mob\status_procs.dm"
#include "code\modules\mob\transform_procs.dm"
#include "code\modules\mob\camera\camera.dm"
#include "code\modules\mob\dead\crew_manifest.dm"
#include "code\modules\mob\dead\dead.dm"
#include "code\modules\mob\dead\new_player\latejoin_menu.dm"
#include "code\modules\mob\dead\new_player\login.dm"
@@ -9,6 +9,7 @@ export const JOB2ICON = {
'Bit Avatar': 'code',
Bitrunner: 'gamepad',
Botanist: 'seedling',
'Bridge Assistant': 'building-shield',
Captain: 'crown',
'Cargo Gorilla': 'paw',
'Cargo Technician': 'box',