Skip to content

Commit

Permalink
Bridge Assistant Station Trait (#80279)
Browse files Browse the repository at this point in the history
## 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
:cl:
add: Bridge Assistant job accessible from a station trait.
/:cl:

---------

Co-authored-by: san7890 <the@san7890.com>
  • Loading branch information
Fikou and san7890 committed Dec 17, 2023
1 parent fb01a2b commit a3fa541
Show file tree
Hide file tree
Showing 33 changed files with 347 additions and 115 deletions.
1 change: 1 addition & 0 deletions code/__DEFINES/atom_hud.dm
Expand Up @@ -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"
Expand Down
74 changes: 39 additions & 35 deletions code/__DEFINES/jobs.dm
Expand Up @@ -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"
Expand Down Expand Up @@ -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"

Expand Down Expand Up @@ -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"
Expand Down
6 changes: 6 additions & 0 deletions code/__DEFINES/traits/declarations.dm
Expand Up @@ -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
Expand Down Expand Up @@ -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"

Expand Down
4 changes: 4 additions & 0 deletions code/_globalvars/traits/_traits.dm
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion code/_onclick/hud/new_player.dm
Expand Up @@ -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()
Expand Down
3 changes: 3 additions & 0 deletions code/controllers/subsystem/dynamic/dynamic.dm
Expand Up @@ -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))
Expand Down
4 changes: 4 additions & 0 deletions code/controllers/subsystem/processing/station.dm
Expand Up @@ -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()

Expand Down
16 changes: 12 additions & 4 deletions code/datums/components/twohanded.dm
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions code/datums/components/wall_mounted.dm
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions code/datums/id_trim/jobs.dm
Expand Up @@ -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"
Expand Down
33 changes: 33 additions & 0 deletions code/datums/records/manifest.dm
Expand Up @@ -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
)

2 changes: 1 addition & 1 deletion code/datums/station_traits/_station_trait.dm
Expand Up @@ -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
Expand Down

0 comments on commit a3fa541

Please sign in to comment.