Files
Bubberstation/code/controllers/subsystem/processing/station.dm
Fikou a3fa541e2e 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>
2023-12-16 20:02:45 -05:00

113 lines
4.9 KiB
Plaintext

PROCESSING_SUBSYSTEM_DEF(station)
name = "Station"
init_order = INIT_ORDER_STATION
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME
wait = 5 SECONDS
///A list of currently active station traits
var/list/station_traits = list()
///Assoc list of trait type || assoc list of traits with weighted value. Used for picking traits from a specific category.
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()
//If doing unit tests we don't do none of that trait shit ya know?
// Autowiki also wants consistent outputs, for example making sure the vending machine page always reports the normal products
#if !defined(UNIT_TESTS) && !defined(AUTOWIKI)
SetupTraits()
display_lobby_traits()
#endif
announcer = new announcer() //Initialize the station's announcer datum
SSparallax.post_station_setup() //Apply station effects that parallax might have
return SS_INIT_SUCCESS
///Rolls for the amount of traits and adds them to the traits list
/datum/controller/subsystem/processing/station/proc/SetupTraits()
if (CONFIG_GET(flag/forbid_station_traits))
return
if (fexists(FUTURE_STATION_TRAITS_FILE))
var/forced_traits_contents = file2text(FUTURE_STATION_TRAITS_FILE)
fdel(FUTURE_STATION_TRAITS_FILE)
var/list/forced_traits_text_paths = json_decode(forced_traits_contents)
forced_traits_text_paths = SANITIZE_LIST(forced_traits_text_paths)
for (var/trait_text_path in forced_traits_text_paths)
var/station_trait_path = text2path(trait_text_path)
if (!ispath(station_trait_path, /datum/station_trait) || station_trait_path == /datum/station_trait)
var/message = "Invalid station trait path [station_trait_path] was requested in the future station traits!"
log_game(message)
message_admins(message)
continue
setup_trait(station_trait_path)
return
for(var/i in subtypesof(/datum/station_trait))
var/datum/station_trait/trait_typepath = i
// If forced, (probably debugging), just set it up now, keep it out of the pool.
if(initial(trait_typepath.force))
setup_trait(trait_typepath)
continue
if(initial(trait_typepath.abstract_type) == trait_typepath)
continue //Dont add abstract ones to it
if(!(initial(trait_typepath.trait_flags) & STATION_TRAIT_PLANETARY) && SSmapping.is_planetary()) // we're on a planet but we can't do planet ;_;
continue
if(!(initial(trait_typepath.trait_flags) & STATION_TRAIT_SPACE_BOUND) && !SSmapping.is_planetary()) //we're in space but we can't do space ;_;
continue
selectable_traits_by_types[initial(trait_typepath.trait_type)][trait_typepath] = initial(trait_typepath.weight)
var/positive_trait_count = pick(20;0, 5;1, 1;2)
var/neutral_trait_count = pick(10;0, 10;1, 3;2)
var/negative_trait_count = pick(20;0, 5;1, 1;2)
pick_traits(STATION_TRAIT_POSITIVE, positive_trait_count)
pick_traits(STATION_TRAIT_NEUTRAL, neutral_trait_count)
pick_traits(STATION_TRAIT_NEGATIVE, negative_trait_count)
///Picks traits of a specific category (e.g. bad or good) and a specified amount, then initializes them, adds them to the list of traits,
///then removes them from possible traits as to not roll twice.
/datum/controller/subsystem/processing/station/proc/pick_traits(trait_sign, amount)
if(!amount)
return
for(var/iterator in 1 to amount)
var/datum/station_trait/trait_type = pick_weight(selectable_traits_by_types[trait_sign]) //Rolls from the table for the specific trait type
selectable_traits_by_types[trait_sign] -= trait_type
setup_trait(trait_type)
///Creates a given trait of a specific type, while also removing any blacklisted ones from the future pool.
/datum/controller/subsystem/processing/station/proc/setup_trait(datum/station_trait/trait_type)
var/datum/station_trait/trait_instance = new trait_type()
station_traits += trait_instance
log_game("Station Trait: [trait_instance.name] chosen for this round.")
if(!trait_instance.blacklist)
return
for(var/i in trait_instance.blacklist)
var/datum/station_trait/trait_to_remove = i
selectable_traits_by_types[initial(trait_to_remove.trait_type)] -= trait_to_remove
/// Update station trait lobby buttons for clients who joined before we initialised this subsystem
/datum/controller/subsystem/processing/station/proc/display_lobby_traits()
for (var/mob/dead/new_player/player as anything in GLOB.new_player_list)
var/datum/hud/new_player/observer_hud = player.hud_used
if (!istype(observer_hud))
continue
observer_hud.add_station_trait_buttons()
observer_hud.show_hud(observer_hud.hud_version)