Skip to content

Commit

Permalink
roles framework
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Atlas committed Aug 22, 2024
1 parent 42ffa6b commit 2effb67
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 12 deletions.
1 change: 1 addition & 0 deletions aurorastation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@
#include "code\datums\repositories\singletons.dm"
#include "code\datums\repositories\sound_channels.dm"
#include "code\datums\repositories\unique.dm"
#include "code\datums\scenarios\roles.dm"
#include "code\datums\scenarios\scenario.dm"
#include "code\datums\scenarios\noncanon\zenghu_clone_facility.dm"
#include "code\datums\state_machine\state.dm"
Expand Down
53 changes: 53 additions & 0 deletions code/controllers/subsystems/processing/odyssey.dm
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,56 @@ SUBSYSTEM_DEF(odyssey)
*/
/datum/controller/subsystem/odyssey/proc/remove_storyteller(mob/abstract/storyteller/S)
LAZYREMOVE(storytellers, S)

/datum/controller/subsystem/odyssey/ui_state()
return GLOB.always_state

/datum/controller/subsystem/odyssey/ui_interact(mob/user, datum/tgui/ui)
. = ..()
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OdysseyPanel", "Odyssey Panel")
ui.open()

/datum/controller/subsystem/odyssey/ui_data(mob/user)
var/list/data = list()
if(scenario)
data["scenario_name"] = SSodyssey.scenario.name
data["scenario_desc"] = SSodyssey.scenario.desc
data["scenario_canonicity"] = SSodyssey.scenario.scenario_type == SCENARIO_TYPE_CANON ? "Canon" : "Non-Canon"

if(length(scenario.roles))
data["scenario_roles"] = list()
for(var/role_singleton in scenario.roles)
var/singleton/role/scenario_role = GET_SINGLETON(role_singleton)
data["scenario_roles"] += list(
list(
"name" = scenario_role.name,
"desc" = scenario_role.desc,
"outfit" = "[scenario_role.outfit]"
)
)
return data

/datum/controller/subsystem/odyssey/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()

switch(action)
if("equip_outfit")
if(!ishuman(usr))
return

var/mob/living/carbon/human/player = usr
if(player.incapacitated())
return

if(player.z != SSodyssey.scenario_zlevel)
to_chat(player, SPAN_WARNING("You can't equip an outfit on a different z-level from the scenario's!"))
return

var/outfit_type = text2path(params["outfit_type"])
if(ispath(outfit_type, /obj/outfit))
player.preEquipOutfit(outfit_type, FALSE)
player.equipOutfit(outfit_type, FALSE)


4 changes: 4 additions & 0 deletions code/controllers/subsystems/statpanel.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ SUBSYSTEM_DEF(statpanels)
if(eta_status)
global_data += eta_status

if(SSodyssey && SSodyssey.scenario)
global_data += "Odyssey: [SSodyssey.scenario.name]"
global_data += "Storytellers: [length(SSodyssey.storytellers)]"

src.currentrun = GLOB.clients.Copy()
mc_data = null

Expand Down
26 changes: 26 additions & 0 deletions code/datums/scenarios/noncanon/zenghu_clone_facility.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,29 @@

min_player_amount = 0
min_actor_amount = 1 //should be 4 todomatt

roles = list(
/singleton/role/cryo_outpost,
/singleton/role/cryo_outpost/mercenary,
/singleton/role/cryo_outpost/scientist
)

/singleton/role/cryo_outpost
name = "Cryo Outpost Mercenary Team Lead"
desc = "You are the leader of a mercenary detachment found in the cloning outpost. Your team could have been an independent mercenary company contracted \
to take this secret Zeng-Hu base, or you could've just found it yourselves. You are equipped with a Heavy Sol Marine's gear."
outfit = /obj/outfit/admin/event/sol_marine/heavy

/singleton/role/cryo_outpost/mercenary
name = "Cryo Outpost Mercenary"
desc = "You are part of a mercenary detachment that has occupied this cloning outpost - either because you were contracted by someone, or because you simply \
found this place. Some of these Zeng-Hu secrets could sell for a pretty penny... Your creativity's the limit! You are equipped with \
a Sol Marine's gear."
outfit = /obj/outfit/admin/event/sol_marine

/singleton/role/cryo_outpost/scientist
name = "Cryo Outpost Zeng-Hu Scientist"
desc = "You are a Zeng-Hu scentist that once worked on unspeakable clone technologies in this outpost. Zeng-Hu wants you to carry some of these cloning \
secrets to the grave, but your wishes don't need to align with them, if your safety was at risk... You are equipped with a Zeng-Hu scientist's gear."
outfit = /obj/outfit/job/scientist/zeng_hu

7 changes: 7 additions & 0 deletions code/datums/scenarios/roles.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/singleton/role
/// The role's name.
var/name = "Generic Goon"
/// The role's description. It should contain the information on what it's supposed to do.
var/desc = "Your job is to be a generic goon in this scenario. Nothing special."
/// The /obj/outfit this role equips you with.
var/outfit = /obj/outfit/admin/generic
8 changes: 8 additions & 0 deletions code/datums/scenarios/scenario.dm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@
/// The announcement message sent to the Horizon at roundstart, typically telling them to go investigate the Odyssey and why.
var/horizon_announcement_message = "There is a Situation on this away site you're probably supposed to know about. Go investigate it."

/// The default outfit every actor is given on this scenario.
/// They can select their role and outfit on the Odyssey UI when ingame.
var/default_outfit = /obj/outfit/admin/generic

/// The displayed list of scenario roles. List of /singleton/role
/// The players will be able to see the role names in the Odyssey UI, and when they click them, they'll equip the relevant outfit.
var/list/roles


/**
* This proc handles the creation and spawning of everything that the odyssey needs.
Expand Down
50 changes: 47 additions & 3 deletions code/game/antagonist/outsider/actor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,62 @@ GLOBAL_DATUM(actors, /datum/antagonist/actor)

/datum/antagonist/actor
id = MODE_ACTOR
landmark_id = "Actor"
role_text = "Actor"
role_text_plural = "Actors"
welcome_text = "You are an actor in a Mission. Roleplay your heart out."
welcome_text = "You are an actor. Your role is to provide an interesting roleplay scenario for the crew. You may use your scenario's guidelines, or \
agree with everyone else to play something different. Your creativity is the limit! Remember that you are an antagonist, and so you have \
all the freedoms an antagonist does."
faction = "actor"
landmark_id = "Actor Spawn Landmark"
landmark_id = "ActorSpawnLandmark"
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_HAS_NUKE | ANTAG_SET_APPEARANCE | ANTAG_NO_FLAVORTEXT
hard_cap = 10
hard_cap_round = 15

bantype = "actor"

faction_verbs = list(
/mob/living/carbon/human/verb/odyssey_panel
)

/datum/antagonist/actor/New()
..(1)
GLOB.actors = src

/datum/antagonist/actor/equip(var/mob/living/carbon/human/player)
if(!..())
return FALSE

for (var/obj/item/I in player)
if (istype(I, /obj/item/implant))
continue
player.drop_from_inventory(I)
if(I.loc != player)
qdel(I)

if(SSodyssey?.scenario)
//TODO: full actor outfit mechanics, role selection
player.preEquipOutfit(SSodyssey.scenario.default_outfit, FALSE)
player.equipOutfit(SSodyssey.scenario.default_outfit, FALSE)

player.force_update_limbs()
player.update_eyes()
player.regenerate_icons()

return TRUE

/obj/effect/landmark/actor_spawn
name = "ActorSpawnLandmark"

/mob/living/carbon/human/verb/odyssey_panel()
set name = "Odyssey Panel"
set category = "Actor"

if(!ishuman(usr))
return

var/mob/living/carbon/human/H = usr
if(H.incapacitated())
return

SSodyssey.ui_interact(H)

4 changes: 2 additions & 2 deletions code/game/gamemodes/odyssey/odyssey.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
/datum/game_mode/odyssey/post_finalize_vote()
GLOB.round_progressing = FALSE
SSodyssey.pick_odyssey()
to_world(FONT_LARGE(EXAMINE_BLOCK_ODYSSEY("The Odyssey picked for this round is: <b>[SPAN_NOTICE(SSodyssey.scenario.name)]</b>.\n\
to_world(FONT_LARGE(EXAMINE_BLOCK_ODYSSEY("The scenario picked for this round is: <b>[SPAN_NOTICE(SSodyssey.scenario.name)]</b>.\n\
[SSodyssey.scenario.desc]\n\
It is a <b>[SSodyssey.scenario.scenario_type == SCENARIO_TYPE_NONCANON ? "non-canon" : "canon"]</b> Odyssey.\n\
It is a <b>[SSodyssey.scenario.scenario_type == SCENARIO_TYPE_NONCANON ? "non-canon" : "canon"]</b> scenario.\n\
Please keep in mind that the Storyteller may alter the story as they see fit, and remember to go along with what they have planned!")))
SSodyssey.scenario.setup_scenario()
GLOB.round_progressing = TRUE
8 changes: 4 additions & 4 deletions maps/away/odysseys/cryo_outpost/cryo_outpost.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -5275,7 +5275,7 @@
/obj/structure/bed/stool/chair/office/light{
dir = 4
},
/obj/effect/landmark/actor,
/obj/effect/landmark/actor_spawn,
/turf/simulated/floor/wood/bamboo,
/area/cryo_outpost/inside/labs_offices)
"fPz" = (
Expand Down Expand Up @@ -5476,7 +5476,7 @@
/obj/structure/bed/stool/chair/office/light{
dir = 8
},
/obj/effect/landmark/actor,
/obj/effect/landmark/actor_spawn,
/turf/simulated/floor/wood/bamboo,
/area/cryo_outpost/inside/labs_offices)
"gdW" = (
Expand Down Expand Up @@ -5856,7 +5856,7 @@
/area/cryo_outpost/inside/maint_habitation)
"gzI" = (
/obj/structure/bed/stool/chair/office/light,
/obj/effect/landmark/actor,
/obj/effect/landmark/actor_spawn,
/turf/simulated/floor/wood/bamboo,
/area/cryo_outpost/inside/labs_offices)
"gAb" = (
Expand Down Expand Up @@ -12949,7 +12949,7 @@
/obj/structure/bed/stool/chair/office/light{
dir = 1
},
/obj/effect/landmark/actor,
/obj/effect/landmark/actor_spawn,
/turf/simulated/floor/wood/bamboo,
/area/cryo_outpost/inside/labs_offices)
"oRy" = (
Expand Down
68 changes: 68 additions & 0 deletions tgui/packages/tgui/interfaces/OdysseyPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useBackend } from '../backend';
import { Button, NoticeBox, Section } from '../components';
import { Window } from '../layouts';

export type OdysseyData = {
scenario_name: string;
scenario_desc: string;
scenario_canonicity: string;

scenario_roles: Role[];
};

type Role = {
name: string;
desc: string;
outfit: string;
};

export const OdysseyPanel = (props, context) => {
const { act, data } = useBackend<OdysseyData>(context);

return (
<Window resizable theme="malfunction" width={500} height={600}>
<Window.Content scrollable>
<Section title={data.scenario_name}>
<NoticeBox>{data.scenario_desc}</NoticeBox>
This is a {data.scenario_canonicity} scenario.
</Section>
{data.scenario_roles && data.scenario_roles.length ? (
<RoleDisplay />
) : (
<NoticeBox>There are no roles for this scenario.</NoticeBox>
)}
</Window.Content>
</Window>
);
};

export const RoleDisplay = (props, context) => {
const { act, data } = useBackend<OdysseyData>(context);

return (
<Section title="Roles">
<NoticeBox>
Remember that you are not beholden to following the role names and
descriptions. You can use their equipment and change up the premises or
what your objective is as you like! These are just guidelines in the
end, or how the developer envisioned the story. Your creativity is the
limit!
</NoticeBox>
{data.scenario_roles.map((role) => (
<Section
title={role.name}
key={role.name}
buttons={
<Button
name="Equip"
color="green"
icon="star"
onClick={() => act('equip_outfit', { outfit_type: role.outfit })}
/>
}>
{role.desc}
</Section>
))}
</Section>
);
};
6 changes: 3 additions & 3 deletions tgui/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3451,9 +3451,9 @@ __metadata:
linkType: hard

"caniuse-lite@npm:^1.0.30001248":
version: 1.0.30001480
resolution: "caniuse-lite@npm:1.0.30001480"
checksum: c0b40f02f45ee99c73f732a3118028b2ab1544962d473d84f2afcb898a5e3099bd4c45f316ebc466fb1dbda904e86b72695578ca531a0bfa9d6337e7aad1ee2a
version: 1.0.30001651
resolution: "caniuse-lite@npm:1.0.30001651"
checksum: c31a5a01288e70cdbbfb5cd94af3df02f295791673173b8ce6d6a16db4394a6999197d44190be5a6ff06b8c2c7d2047e94dfd5e5eb4c103ab000fca2d370afc7
languageName: node
linkType: hard

Expand Down

0 comments on commit 2effb67

Please sign in to comment.