mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-20 19:44:46 +01:00
Merge pull request #14887 from Runa-Dacino/TraitTutorial
Adds new human ability: "Explain Custom Traits"
This commit is contained in:
@@ -85,6 +85,16 @@
|
||||
/datum/trait/neutral/bloodsucker
|
||||
name = "Bloodsucker, Obligate"
|
||||
desc = "Makes you unable to gain nutrition from anything but blood. To compenstate, you get fangs that can be used to drain blood from prey."
|
||||
tutorial = "This trait forces you to only consume blood - you cannot have normal food anymore. Vore is, of course, an exception! <br> \
|
||||
You can satisfy this by clicking bloodbags in your hand on harm intent, drinking from glasses, blood tomatoes \
|
||||
or finding a (un)willing donor for your appropriate appendage! <br><br> \
|
||||
Controls for taking blood from your victim can be changed at will by trying to drink from yourself. <br>\
|
||||
Intent-based control scheme: <br> \
|
||||
HELP - Loud, No Bleeding <br> \
|
||||
DISARM - Subtle, Causes bleeding <br> \
|
||||
GRAB - Subtle, No Bleeding <br> \
|
||||
HARM - Loud, Causes Bleeding"
|
||||
|
||||
cost = 0
|
||||
custom_only = FALSE
|
||||
var_changes = list("organic_food_coeff" = 0, "bloodsucker" = TRUE)
|
||||
@@ -97,6 +107,15 @@
|
||||
/datum/trait/neutral/bloodsucker_freeform
|
||||
name = "Bloodsucker"
|
||||
desc = "You get fangs that can be used to drain blood from prey."
|
||||
tutorial = "This trait allows you to consume blood on top of normal food! <br> \
|
||||
You can do this by clicking bloodbags in your hand on harm intent, drinking from glasses, blood tomatoes \
|
||||
or finding a (un)willing donor for your appropriate appendage! <br><br> \
|
||||
Controls for taking blood from your victim can be changed at will by trying to drink from yourself. <br>\
|
||||
Intent-based control scheme: <br> \
|
||||
HELP - Loud, No Bleeding <br> \
|
||||
DISARM - Subtle, Causes bleeding <br> \
|
||||
GRAB - Subtle, No Bleeding <br> \
|
||||
HARM - Loud, Causes Bleeding"
|
||||
cost = 0
|
||||
custom_only = FALSE
|
||||
var_changes = list("bloodsucker" = TRUE)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/datum/trait
|
||||
var/name
|
||||
var/desc = "Contact a developer if you see this trait."
|
||||
var/tutorial = "This trait has no detailed tutorial yet. Suggest one at #Dev-Suggestions on the discord!" //Use <br> for newlines, NOT \n
|
||||
|
||||
var/cost = 0
|
||||
var/sort = TRAIT_SORT_NORMAL // Sort order, 1 before 2 before 3 etc. Alphabetical is used for same-group traits.
|
||||
@@ -32,6 +33,7 @@
|
||||
S.vars[trait] = trait_prefs[trait]
|
||||
if(TRAIT_VAREDIT_TARGET_MOB)
|
||||
H.vars[trait] = trait_prefs[trait]
|
||||
H.verbs |= /mob/living/carbon/human/proc/trait_tutorial
|
||||
return
|
||||
|
||||
//Applying trait to preferences rather than just us.
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
A new Ability given to those human mobs that have a non-zero number of traits.
|
||||
Verb is added by /datum/trait/proc/apply() in code\modules\mob\living\carbon\human\species\station\traits_vr\trait.dm file.
|
||||
This proc gets called whenever the user is spawned, resleeved, autoresleeved and so forth.
|
||||
If there are special cases that do NOT call this var that result in a completely new body -
|
||||
I will fix it once I am informed of their existence.
|
||||
Been tested - does NOT lead to multiples of the verb thanks to the |=.
|
||||
Given the apply() proc is only called if they have verbs - this should avoid it erronously popping up for traitless people.
|
||||
|
||||
This ability intends to retrieve all positive, neutral and negative traits chosen in the character set-up
|
||||
then retrieve their relevant vars by assuming the character's species has the full list. This should always work. Should
|
||||
|
||||
The ability is intended to be developed both as a to_chat() and a tgui window.
|
||||
The user is given the ability to choose which they would like whenever they press the ability to better suit whatever scenario they find themselves
|
||||
thirsty for knowledge.
|
||||
|
||||
When adding new tutorials for trait subtypes, use <br> rather than \n newlines
|
||||
|
||||
TGUI backend path: code\modules\tgui\modules\trait_tutorial_tgui.dm
|
||||
TGUI frontend path: tgui\packages\tgui\interfaces\TraitTutorial.tsx
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/trait_tutorial()
|
||||
set name = "Explain Custom Traits"
|
||||
set desc = "Click this verb to obtain a detailed tutorial on your selected traits. "
|
||||
set category = "Abilities"
|
||||
var/datum/tgui_module/trait_tutorial_tgui/fancy_UI
|
||||
if(!fancy_UI)
|
||||
fancy_UI = new /datum/tgui_module/trait_tutorial_tgui/ //Preventing a bunch of instances being spawned all over the place. Hopefully
|
||||
|
||||
|
||||
|
||||
var/list/list_of_traits = species.traits
|
||||
if(!LAZYLEN(list_of_traits)) //Although we shouldn't show up if no traits, leaving this in case someone loses theirs after (re)spawning.
|
||||
to_chat(usr, SPAN_NOTICE("You do not have any custom traits!"))
|
||||
return //Dont want an empty TGUI panel and list by accident after all.
|
||||
|
||||
|
||||
var/UI_choice = tgui_alert(src, "Would you like the tutorial text to be printed to chat?", "Choose preferred tutorial interface", list("TGUI","To Chat", "Cancel"))
|
||||
if(UI_choice == "Cancel")
|
||||
return
|
||||
|
||||
//Initializing associative lists
|
||||
var/trait_names = list() //List of keys
|
||||
var/trait_category = list() // name:category
|
||||
var/trait_desc = list() // name:desc
|
||||
var/trait_tutorial = list() //name:tutorial
|
||||
for(var/trait in list_of_traits)
|
||||
var/datum/trait/T = all_traits[trait]
|
||||
trait_names += T.name
|
||||
trait_desc[T.name] = T.desc
|
||||
trait_tutorial[T.name] = T.tutorial
|
||||
switch(T.category)
|
||||
if(TRAIT_TYPE_NEGATIVE)
|
||||
trait_category[T.name] = "Negative Trait"
|
||||
if(TRAIT_TYPE_NEUTRAL)
|
||||
trait_category[T.name] = "Neutral Trait"
|
||||
if(TRAIT_TYPE_POSITIVE)
|
||||
trait_category[T.name] = "Positive Trait"
|
||||
|
||||
|
||||
if(UI_choice == "To Chat")
|
||||
var/to_chat_choice = tgui_input_list(usr, "Please choose the trait to be explained", "Print to Chat", trait_names, null)
|
||||
if(to_chat_choice)
|
||||
to_chat(usr,SPAN_NOTICE("<b>Name:</b> [to_chat_choice] \n <b>Category:</b> [trait_category[to_chat_choice]] \n <b>Description:</b> [trait_desc[to_chat_choice]] \n \
|
||||
<b>Guide:</b> \n [trait_tutorial[to_chat_choice]]"))
|
||||
|
||||
|
||||
else if(UI_choice == "TGUI")
|
||||
|
||||
fancy_UI.set_vars(trait_names, trait_category, trait_desc, trait_tutorial)
|
||||
fancy_UI.tgui_interact(usr)
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Verb/Main definition path: code\modules\mob\living\carbon\human\species\station\traits_vr\traits_tutorial.dm
|
||||
Frontend path: tgui\packages\tgui\interfaces\TraitTutorial.tsx
|
||||
*/
|
||||
|
||||
/datum/tgui_module/trait_tutorial_tgui
|
||||
name = "Explain Custom Traits"
|
||||
tgui_id = "TraitTutorial"
|
||||
var/trait_names = list()
|
||||
var/trait_category = list() // name:category
|
||||
var/trait_desc = list() // name:desc
|
||||
var/trait_tutorial = list() //name:tutorial
|
||||
var/trait_selected = ""
|
||||
|
||||
/datum/tgui_module/trait_tutorial_tgui/proc/set_vars(list/names, list/categories, list/descriptions, list/tutorials)
|
||||
trait_names = names
|
||||
trait_category = categories
|
||||
trait_desc = descriptions
|
||||
trait_tutorial = tutorials
|
||||
|
||||
/datum/tgui_module/trait_tutorial_tgui/tgui_interact(mob/living/carbon/human/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, tgui_id, name)
|
||||
ui.open()
|
||||
|
||||
/datum/tgui_module/trait_tutorial_tgui/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["names"] = trait_names //passes a list of strings
|
||||
data["descriptions"] = trait_desc //passes an assoc list as obj
|
||||
data["categories"] = trait_category //passes an assoc list as obj
|
||||
data["tutorials"] = trait_tutorial //passes an assoc list as obj
|
||||
data["selection"] = trait_selected //passes a string
|
||||
return data
|
||||
|
||||
/datum/tgui_module/trait_tutorial_tgui/tgui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(action == "select_trait")
|
||||
var/selection = params["name"]
|
||||
trait_selected = selection
|
||||
|
||||
|
||||
. = TRUE
|
||||
|
||||
/datum/tgui_module/trait_tutorial_tgui/tgui_state(mob/user)
|
||||
return GLOB.tgui_always_state
|
||||
@@ -0,0 +1,80 @@
|
||||
/* eslint-disable react/no-danger */
|
||||
import { useBackend } from '../backend';
|
||||
import { Flex, Tabs, Section, Box, Divider } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
type data = {
|
||||
namae: string;
|
||||
names: string[];
|
||||
descriptions: { key: string; val: string }[];
|
||||
categories: { key: string; val: string }[];
|
||||
tutorials: { key: string; val: string }[];
|
||||
selection: string;
|
||||
};
|
||||
|
||||
export const TraitTutorial = (props, context) => {
|
||||
const { act, data } = useBackend<data>(context);
|
||||
return (
|
||||
<Window width={804} height={426} scrollable>
|
||||
<Window.Content scrollable>
|
||||
<Section title="Guide to Custom Traits" scrollable>
|
||||
<TraitSelection />
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
export const TraitSelection = (props, context) => {
|
||||
const { act, data } = useBackend<data>(context);
|
||||
|
||||
const { names, selection } = data;
|
||||
|
||||
return (
|
||||
<Flex scrollable>
|
||||
<Flex.Item shrink scrollable>
|
||||
<Section title="Trait Selection" scrollable>
|
||||
<Tabs vertical scrollable>
|
||||
{names.map((name) => (
|
||||
<Tabs.Tab key={name} selected={name === selection} onClick={() => act('select_trait', { name })}>
|
||||
<Box inline>{name}</Box>
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
</Section>
|
||||
</Flex.Item>
|
||||
<Flex.Item grow={2}>
|
||||
<Divider vertical />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow={8} scrollable>
|
||||
{selection && (
|
||||
<Section title={selection} scrollable>
|
||||
<TraitDescription name={selection} />
|
||||
</Section>
|
||||
)}
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export const TraitDescription = (props, context) => {
|
||||
const { act, data } = useBackend<data>(context);
|
||||
|
||||
const { name } = props;
|
||||
const { descriptions, categories, tutorials } = data;
|
||||
|
||||
return (
|
||||
<Section scrollable flexWrap>
|
||||
<b>Name:</b> {name}
|
||||
<br />
|
||||
<b>Category:</b> {categories[name]}
|
||||
<br />
|
||||
<b>Description:</b> {descriptions[name]}
|
||||
<br />
|
||||
<b>Details & How to Use:</b>
|
||||
<br />
|
||||
<br />
|
||||
<div dangerouslySetInnerHTML={{ __html: tutorials[name] as unknown as string }} />
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -2928,6 +2928,7 @@
|
||||
#include "code\modules\mob\living\carbon\human\species\station\traits_vr\neutral.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\traits_vr\positive.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\traits_vr\trait.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\traits_vr\traits_tutorial.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\traits_vr\weaver_objs.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\station\traits_vr\weaver_recipies.dm"
|
||||
#include "code\modules\mob\living\carbon\human\species\virtual_reality\avatar.dm"
|
||||
@@ -3980,6 +3981,7 @@
|
||||
#include "code\modules\tgui\modules\shutoff_monitor.dm"
|
||||
#include "code\modules\tgui\modules\supermatter_monitor.dm"
|
||||
#include "code\modules\tgui\modules\teleporter.dm"
|
||||
#include "code\modules\tgui\modules\trait_tutorial_tgui.dm"
|
||||
#include "code\modules\tgui\modules\admin\player_notes.dm"
|
||||
#include "code\modules\tgui\modules\ntos-only\cardmod.dm"
|
||||
#include "code\modules\tgui\modules\ntos-only\configurator.dm"
|
||||
|
||||
Reference in New Issue
Block a user