diff options
author | Chuck Miller <shadowmil@gmail.com> | 2012-07-31 12:13:35 -0400 |
---|---|---|
committer | Erik Schilling <ablu.erikschilling@googlemail.com> | 2012-08-01 13:53:26 +0200 |
commit | 0ba2b8cf8040594b0780c66d68f32aba0cc56f89 (patch) | |
tree | 866235995a84bb7bb57bedef73a65c427db0ef21 /src | |
parent | 40e15ec4676cf74713685c74f8feeeab6213ade7 (diff) | |
download | mana-0ba2b8cf8040594b0780c66d68f32aba0cc56f89.tar.gz mana-0ba2b8cf8040594b0780c66d68f32aba0cc56f89.tar.bz2 mana-0ba2b8cf8040594b0780c66d68f32aba0cc56f89.tar.xz mana-0ba2b8cf8040594b0780c66d68f32aba0cc56f89.zip |
Modify the NPC Dialog to be more RPG-Like
Diffstat (limited to 'src')
-rw-r--r-- | src/defaults.cpp | 1 | ||||
-rw-r--r-- | src/gui/npcdialog.cpp | 291 | ||||
-rw-r--r-- | src/gui/npcdialog.h | 77 | ||||
-rw-r--r-- | src/gui/setup_interface.cpp | 13 | ||||
-rw-r--r-- | src/gui/setup_interface.h | 2 | ||||
-rw-r--r-- | src/resources/theme.cpp | 1 | ||||
-rw-r--r-- | src/resources/theme.h | 1 |
7 files changed, 146 insertions, 240 deletions
diff --git a/src/defaults.cpp b/src/defaults.cpp index e8a6e6e6..facff7d8 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -101,7 +101,6 @@ DefaultsData* getConfigDefaults() AddDEF(configData, "downTolerance", 100); AddDEF(configData, "leftTolerance", 100); AddDEF(configData, "rightTolerance", 100); - AddDEF(configData, "logNpcInGui", true); AddDEF(configData, "download-music", false); AddDEF(configData, "guialpha", 0.8f); AddDEF(configData, "ChatLogLength", 0); diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp index 74d8a4aa..16d8d5bd 100644 --- a/src/gui/npcdialog.cpp +++ b/src/gui/npcdialog.cpp @@ -41,16 +41,13 @@ #include "net/net.h" #include "net/npchandler.h" +#include "resources/theme.h" + #include "utils/gettext.h" #include "utils/stringutils.h" #include <guichan/font.hpp> -#define CAPTION_WAITING _("Waiting for server") -#define CAPTION_NEXT _("Next") -#define CAPTION_CLOSE _("Close") -#define CAPTION_SUBMIT _("Submit") - typedef std::map<int, NpcDialog*> NpcDialogs; class NpcEventListener : public EventListener @@ -71,37 +68,36 @@ static NpcEventListener *npcListener = NULL; NpcDialog::DialogList NpcDialog::instances; NpcDialog::NpcDialog(int npcId) - : Window(_("NPC")), + : Window("", false, NULL, "npcdialog.xml"), mNpcId(npcId), - mLogInteraction(config.getBoolValue("logNpcInGui")), mDefaultInt(0), + mText(""), + mTextPlayTime(tick_time), + mClearTextOnNextPlay(true), mInputState(NPC_INPUT_NONE), mActionState(NPC_ACTION_WAIT) { // Basic Window Setup setWindowName("NpcText"); - setResizable(true); + setResizable(false); setCloseButton(false); + setMovable(false); setFocusable(true); - setMinWidth(200); - setMinHeight(150); - - setDefaultSize(260, 200, ImageRect::CENTER); - // Setup output text box mTextBox = new TextBox; mTextBox->setEditable(false); mTextBox->setOpaque(false); - mScrollArea = new ScrollArea(mTextBox); - mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); - mScrollArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS); + mTextBox->setTextColor(&(Theme::instance()->getColor(Theme::ThemePalette::NPC_DIALOG_TEXT))); + + // Place the window + setContentSize(getParent()->getWidth() / 2, 175); + setLocationRelativeTo(ImageRect::LOWER_CENTER, 0, -50); // Setup listbox mItemList = new ListBox(this); mItemList->setWrappingEnabled(true); - setContentSize(260, 175); mListScrollArea = new ScrollArea(mItemList); mListScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); @@ -116,35 +112,17 @@ NpcDialog::NpcDialog(int npcId) mIntField = new IntTextField; mIntField->setVisible(true); - mClearButton = new Button(_("Clear log"), "clear", this); - - // Setup button - mNextButton = new Button("", "ok", this); - - //Setup more and less buttons (int input) - mPlusButton = new Button(_("+"), "inc", this); - mMinusButton = new Button(_("-"), "dec", this); - - int width = std::max(mNextButton->getFont()->getWidth(CAPTION_WAITING), - mNextButton->getFont()->getWidth(CAPTION_NEXT)); - width = std::max(width, mNextButton->getFont()->getWidth(CAPTION_CLOSE)); - width = std::max(width, mNextButton->getFont()->getWidth(CAPTION_SUBMIT)); - - mNextButton->setWidth(8 + width); - - mResetButton = new Button(_("Reset"), "reset", this); + mSubmitButton = new Button(_("Submit"), "submit", this); // Place widgets buildLayout(); - center(); - loadWindowState(); - instances.push_back(this); setVisible(true); requestFocus(); - listen(Event::ConfigChannel); + this->addKeyListener(this); + PlayerInfo::setNPCInteractionCount(PlayerInfo::getNPCInteractionCount() + 1); } @@ -152,130 +130,127 @@ NpcDialog::NpcDialog(int npcId) NpcDialog::~NpcDialog() { // These might not actually be in the layout, so lets be safe - delete mScrollArea; + delete mTextBox; delete mItemList; delete mTextField; delete mIntField; - delete mResetButton; - delete mPlusButton; - delete mMinusButton; - delete mNextButton; + delete mSubmitButton; instances.remove(this); + this->removeKeyListener(this); + PlayerInfo::setNPCInteractionCount(PlayerInfo::getNPCInteractionCount() - 1); npcListener->removeDialog(mNpcId); } -void NpcDialog::setText(const std::string &text) +void NpcDialog::logic() { - mText = text; - mTextBox->setTextWrapped(mText, mScrollArea->getWidth() - 15); + + if (get_elapsed_time(mTextPlayTime) > 10) + { + mTextPlayTime = tick_time; + + ushort currentLength = mTextBox->getText().length(); + if (currentLength < mText.length()) + { + setText(mText.substr(0, currentLength + 1)); + } + } + Window::logic(); } -void NpcDialog::addText(const std::string &text, bool save) +void NpcDialog::playText(const std::string &text) { - if (save || mLogInteraction) + if (mClearTextOnNextPlay) { - mNewText += text + "\n"; - setText(mText + text + "\n"); + mClearTextOnNextPlay = false; + mText = ""; + setText(""); + } - mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); - mActionState = NPC_ACTION_WAIT; - buildLayout(); + mText += text + "\n"; +} + +void NpcDialog::setText(const std::string &text) +{ + mTextBox->setTextWrapped(text, getWidth() - 15); } -void NpcDialog::showNextButton() +void NpcDialog::setStateNext() { mActionState = NPC_ACTION_NEXT; buildLayout(); } -void NpcDialog::showCloseButton() +void NpcDialog::setStateClose() { mActionState = NPC_ACTION_CLOSE; buildLayout(); } -void NpcDialog::action(const gcn::ActionEvent &event) +void NpcDialog::keyPressed(gcn::KeyEvent &keyEvent) { - if (event.getId() == "ok") + if (!keyEvent.isConsumed()) { - if (mActionState == NPC_ACTION_NEXT) + if (keyEvent.getKey() == gcn::Key::SPACE) { - nextDialog(); - addText(std::string(), false); + keyEvent.consume(); + proceed(); } - else if (mActionState == NPC_ACTION_CLOSE) - { - close(); - } - else if (mActionState == NPC_ACTION_INPUT) - { - std::string printText = ""; // Text that will get printed in the textbox - - if (mInputState == NPC_INPUT_LIST) - { - int selectedIndex = mItemList->getSelected(); - - if (selectedIndex >= (int) mItems.size() || selectedIndex < 0) - return; + } +} - printText = mItems[selectedIndex]; +void NpcDialog::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "submit") + { + proceed(); + } +} - Net::getNpcHandler()->menuSelect(mNpcId, selectedIndex + 1); - } - else if (mInputState == NPC_INPUT_STRING) - { - printText = mTextField->getText(); +void NpcDialog::proceed() +{ + // If the message isn't done typing out, finish it + if (mTextBox->getText().length() < mText.length()) + { + setText(mText); + return; + } - Net::getNpcHandler()->stringInput(mNpcId, printText); - } - else if (mInputState == NPC_INPUT_INTEGER) - { - printText = strprintf("%d", mIntField->getValue()); + if (mActionState == NPC_ACTION_NEXT) + { + mClearTextOnNextPlay = true; + Net::getNpcHandler()->nextDialog(mNpcId); + } + else if (mActionState == NPC_ACTION_CLOSE) + { + close(); + } + else if (mActionState == NPC_ACTION_INPUT) + { + if (mInputState == NPC_INPUT_LIST) + { + int selectedIndex = mItemList->getSelected(); - Net::getNpcHandler()->integerInput(mNpcId, mIntField->getValue()); - } - // addText will auto remove the input layout - addText(strprintf("\n> \"%s\"\n", printText.c_str()), false); + if (selectedIndex >= (int) mItems.size() || selectedIndex < 0) + return; - mNewText.clear(); + Net::getNpcHandler()->menuSelect(mNpcId, selectedIndex + 1); } - - if (!mLogInteraction) - setText(""); - } - else if (event.getId() == "reset") - { - if (mInputState == NPC_INPUT_STRING) + else if (mInputState == NPC_INPUT_STRING) { - mTextField->setText(mDefaultString); + Net::getNpcHandler()->stringInput(mNpcId, mTextField->getText()); } else if (mInputState == NPC_INPUT_INTEGER) { - mIntField->setValue(mDefaultInt); + Net::getNpcHandler()->integerInput(mNpcId, mIntField->getValue()); } + mClearTextOnNextPlay = true; } - else if (event.getId() == "inc") - { - mIntField->setValue(mIntField->getValue() + 1); - } - else if (event.getId() == "dec") - { - mIntField->setValue(mIntField->getValue() - 1); - } - else if (event.getId() == "clear") - { - setText(mNewText); - } -} -void NpcDialog::nextDialog() -{ - Net::getNpcHandler()->nextDialog(mNpcId); } void NpcDialog::close() @@ -284,6 +259,7 @@ void NpcDialog::close() Window::close(); } + int NpcDialog::getNumberOfElements() { return mItems.size(); @@ -376,13 +352,6 @@ void NpcDialog::move(int amount) } } -void NpcDialog::widgetResized(const gcn::Event &event) -{ - Window::widgetResized(event); - - setText(mText); -} - void NpcDialog::setVisible(bool visible) { Window::setVisible(visible); @@ -393,31 +362,18 @@ void NpcDialog::setVisible(bool visible) } } -void NpcDialog::event(Event::Channel channel, const Event &event) -{ - if (channel != Event::ConfigChannel) - return; - - if (event.getType() == Event::ConfigOptionChanged && - event.getString("option") == "logNpcInGui") - { - mLogInteraction = config.getBoolValue("logNpcInGui"); - } -} - -void NpcDialog::mouseClicked(gcn::MouseEvent &mouseEvent) +void NpcDialog::mousePressed(gcn::MouseEvent &mouseEvent) { if (mouseEvent.getSource() == mItemList && isDoubleClick(mItemList->getSelected())) { - action(gcn::ActionEvent(mNextButton, mNextButton->getActionEventId())); + proceed(); } - if (mouseEvent.getSource() == mTextBox && isDoubleClick((int)(long)mTextBox)) + if (mActionState == NPC_ACTION_NEXT || mActionState == NPC_ACTION_CLOSE) { - if (mActionState == NPC_ACTION_NEXT || mActionState == NPC_ACTION_CLOSE) - action(gcn::ActionEvent(mNextButton, - mNextButton->getActionEventId())); + proceed(); } + Window::mousePressed(mouseEvent); } NpcDialog *NpcDialog::getActive() @@ -466,67 +422,35 @@ void NpcDialog::buildLayout() if (mActionState != NPC_ACTION_INPUT) { - if (mActionState == NPC_ACTION_WAIT) - { - mNextButton->setCaption(CAPTION_WAITING); - } - else if (mActionState == NPC_ACTION_NEXT) - { - mNextButton->setCaption(CAPTION_NEXT); - } - else if (mActionState == NPC_ACTION_CLOSE) - { - mNextButton->setCaption(CAPTION_CLOSE); - } - place(0, 0, mScrollArea, 5, 3); - place(3, 3, mClearButton); - place(4, 3, mNextButton); + place(0, 0, mTextBox, 5, 3); } else if (mInputState != NPC_INPUT_NONE) { - if (!mLogInteraction) - setText(mNewText); - - mNextButton->setCaption(CAPTION_SUBMIT); if (mInputState == NPC_INPUT_LIST) { - place(0, 0, mScrollArea, 6, 3); + place(0, 0, mTextBox, 6, 3); place(0, 3, mListScrollArea, 6, 3); - place(2, 6, mClearButton, 2); - place(4, 6, mNextButton, 2); mItemList->setSelected(-1); } else if (mInputState == NPC_INPUT_STRING) { - place(0, 0, mScrollArea, 6, 3); - place(0, 3, mTextField, 6); - place(0, 4, mResetButton, 2); - place(2, 4, mClearButton, 2); - place(4, 4, mNextButton, 2); + place(0, 0, mTextBox, 6, 3); + place(1, 3, mTextField, 3); + place(4, 3, mSubmitButton, 1); } else if (mInputState == NPC_INPUT_INTEGER) { - place(0, 0, mScrollArea, 6, 3); - place(0, 3, mMinusButton, 1); - place(1, 3, mIntField, 4); - place(5, 3, mPlusButton, 1); - place(0, 4, mResetButton, 2); - place(2, 4, mClearButton, 2); - place(4, 4, mNextButton, 2); + place(0, 0, mTextBox, 6, 3); + place(1, 3, mIntField, 3); + place(4, 3, mSubmitButton, 1); } } Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); - bool waitState = isWaitingForTheServer(); - mNextButton->setEnabled(!waitState); - setCloseButton(waitState); - redraw(); - - mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); } void NpcEventListener::event(Event::Channel channel, @@ -538,8 +462,7 @@ void NpcEventListener::event(Event::Channel channel, if (event.getType() == Event::Message) { NpcDialog *dialog = getDialog(event.getInt("id")); - - dialog->addText(event.getString("text")); + dialog->playText(event.getString("text")); } else if (event.getType() == Event::Menu) { @@ -587,7 +510,7 @@ void NpcEventListener::event(Event::Channel channel, return; } - dialog->showNextButton(); + dialog->setStateNext(); } else if (event.getType() == Event::Close) { @@ -601,7 +524,7 @@ void NpcEventListener::event(Event::Channel channel, return; } - dialog->showCloseButton(); + dialog->setStateClose(); } else if (event.getType() == Event::CloseAll) { diff --git a/src/gui/npcdialog.h b/src/gui/npcdialog.h index 9c6839b0..5f2b61be 100644 --- a/src/gui/npcdialog.h +++ b/src/gui/npcdialog.h @@ -27,8 +27,10 @@ #include "gui/widgets/window.h" #include <guichan/actionlistener.hpp> +#include <guichan/keylistener.hpp> #include <guichan/listmodel.hpp> + #include <list> #include <string> #include <vector> @@ -47,7 +49,7 @@ class Button; class NpcDialog : public Window, public gcn::ActionListener, public gcn::ListModel, - public EventListener + public gcn::KeyListener { public: NpcDialog(int npcId); @@ -59,36 +61,46 @@ class NpcDialog : public Window, */ void action(const gcn::ActionEvent &event); + void keyPressed(gcn::KeyEvent &keyEvent); + /** - * Sets the text shows in the dialog. - * - * @param string The new text. - */ - void setText(const std::string &string); + * Moves the dialog forward + */ + void proceed(); /** - * Adds the text to the text shows in the dialog. Also adds a newline - * to the end. + * Update the text being written to the screen * - * @param string The text to add. + * @overload Window::logic */ - void addText(const std::string &string, bool save = true); + void logic(); /** - * When called, the widget will show a "Next" button. + * Has the dialog window animate playing the text + * + * @param string The text that will be played */ - void showNextButton(); + void playText(const std::string &string); + + /** + * Sets the text shows in the dialog. + * + * @param string The new text. + */ + void setText(const std::string &string); /** - * When called, the widget will show a "Close" button and will close - * the dialog when clicked. + * When called the window's next interaction + * with the player will be to request the next + * stage in the interaction. */ - void showCloseButton(); + void setStateNext(); /** - * Notifies the server that client has performed a next action. + * When called the window's next interaction + * with the player will be to close the window. */ - void nextDialog(); + void setStateClose(); /** * Notifies the server that the client has performed a close action. @@ -139,18 +151,9 @@ class NpcDialog : public Window, void move(int amount); - /** - * Called when resizing the window. - * - * @param event The calling event - */ - void widgetResized(const gcn::Event &event); - void setVisible(bool visible); - void event(Event::Channel channel, const Event &event); - - void mouseClicked(gcn::MouseEvent &mouseEvent); + void mousePressed(gcn::MouseEvent &mouseEvent); /** * Returns the first active instance. Useful for pushing user @@ -175,16 +178,19 @@ class NpcDialog : public Window, void buildLayout(); int mNpcId; - bool mLogInteraction; int mDefaultInt; std::string mDefaultString; // Used for the main input area - gcn::ScrollArea *mScrollArea; TextBox *mTextBox; + // Target string to be displayed into mTextBox std::string mText; - std::string mNewText; + // Timer for when to add a new character + int mTextPlayTime; + // When set, if playText() is called again + // It will clear the existing values + bool mClearTextOnNextPlay; // Used for choice input ListBox *mItemList; @@ -194,16 +200,7 @@ class NpcDialog : public Window, // Used for string and integer input TextField *mTextField; IntTextField *mIntField; - Button *mPlusButton; - Button *mMinusButton; - - Button *mClearButton; - - // Used for the button - Button *mNextButton; - - // Will reset the text and integer input to the provided default - Button *mResetButton; + Button *mSubmitButton; enum NpcInputState { diff --git a/src/gui/setup_interface.cpp b/src/gui/setup_interface.cpp index b35a30fe..90cfba48 100644 --- a/src/gui/setup_interface.cpp +++ b/src/gui/setup_interface.cpp @@ -97,7 +97,6 @@ Setup_Interface::Setup_Interface(): mShowMonsterDamageEnabled(config.getBoolValue("showMonstersTakedDamage")), mVisibleNamesEnabled(config.getBoolValue("visiblenames")), mNameEnabled(config.getBoolValue("showownname")), - mNPCLogEnabled(config.getBoolValue("logNpcInGui")), mPickupChatEnabled(config.getBoolValue("showpickupchat")), mPickupParticleEnabled(config.getBoolValue("showpickupparticle")), mOpacity(config.getFloatValue("guialpha")), @@ -105,7 +104,6 @@ Setup_Interface::Setup_Interface(): mVisibleNamesCheckBox(new CheckBox(_("Visible names"), mVisibleNamesEnabled)), mNameCheckBox(new CheckBox(_("Show own name"), mNameEnabled)), - mNPCLogCheckBox(new CheckBox(_("Log NPC dialogue"), mNPCLogEnabled)), mPickupNotifyLabel(new Label(_("Show pickup notification:"))), // TRANSLATORS: Refers to "Show pickup notification" mPickupChatCheckBox(new CheckBox(_("in chat"), mPickupChatEnabled)), @@ -143,7 +141,6 @@ Setup_Interface::Setup_Interface(): mPickupChatCheckBox->setActionEventId("pickupchat"); mPickupParticleCheckBox->setActionEventId("pickupparticle"); mNameCheckBox->setActionEventId("showownname"); - mNPCLogCheckBox->setActionEventId("lognpc"); mAlphaSlider->setActionEventId("guialpha"); mSpeechSlider->setActionEventId("speech"); @@ -153,7 +150,6 @@ Setup_Interface::Setup_Interface(): mPickupChatCheckBox->addActionListener(this); mPickupParticleCheckBox->addActionListener(this); mNameCheckBox->addActionListener(this); - mNPCLogCheckBox->addActionListener(this); mAlphaSlider->addActionListener(this); mSpeechSlider->addActionListener(this); @@ -168,7 +164,6 @@ Setup_Interface::Setup_Interface(): place(3, 0, mNameCheckBox, 3); place(0, 1, mShowMonsterDamageCheckBox, 3); - place(3, 1, mNPCLogCheckBox, 3); place(0, 2, space, 1, 1); @@ -204,7 +199,6 @@ void Setup_Interface::apply() mShowMonsterDamageEnabled = config.getBoolValue("showMonstersTakedDamage"); mVisibleNamesEnabled = config.getBoolValue("visiblenames"); mNameEnabled = config.getBoolValue("showownname"); - mNPCLogEnabled = config.getBoolValue("logNpcInGui"); mSpeechMode = static_cast<Being::Speech>(config.getIntValue("speech")); mOpacity = config.getFloatValue("guialpha"); mPickupChatEnabled = config.getBoolValue("showpickupchat"); @@ -217,7 +211,6 @@ void Setup_Interface::cancel() mVisibleNamesCheckBox->setSelected(mVisibleNamesEnabled); mSpeechSlider->setValue(mSpeechMode); mNameCheckBox->setSelected(mNameEnabled); - mNPCLogCheckBox->setSelected(mNPCLogEnabled); mAlphaSlider->setValue(mOpacity); //mAlphaSlider->setEnabled(!mSDLTransparencyDisabled); @@ -227,7 +220,6 @@ void Setup_Interface::cancel() config.setValue("showownname", mNameEnabled); if (local_player) local_player->setCheckNameSetting(true); - config.setValue("logNpcInGui", mNPCLogEnabled); config.setValue("guialpha", mOpacity); config.setValue("showpickupchat", mPickupChatEnabled); config.setValue("showpickupparticle", mPickupParticleEnabled); @@ -273,10 +265,5 @@ void Setup_Interface::action(const gcn::ActionEvent &event) local_player->setCheckNameSetting(true); config.setValue("showownname", mNameCheckBox->isSelected()); } - else if (id == "lognpc") - { - config.setValue("logNpcInGui", mNPCLogCheckBox->isSelected()); - } - } diff --git a/src/gui/setup_interface.h b/src/gui/setup_interface.h index 2b1de5b7..d3ddefdb 100644 --- a/src/gui/setup_interface.h +++ b/src/gui/setup_interface.h @@ -48,7 +48,6 @@ class Setup_Interface : public SetupTab, public gcn::ActionListener, bool mShowMonsterDamageEnabled; bool mVisibleNamesEnabled; bool mNameEnabled; - bool mNPCLogEnabled; bool mPickupChatEnabled; bool mPickupParticleEnabled; double mOpacity; @@ -63,7 +62,6 @@ class Setup_Interface : public SetupTab, public gcn::ActionListener, gcn::CheckBox *mShowMonsterDamageCheckBox; gcn::CheckBox *mVisibleNamesCheckBox; gcn::CheckBox *mNameCheckBox; - gcn::CheckBox *mNPCLogCheckBox; gcn::Label *mPickupNotifyLabel; gcn::CheckBox *mPickupChatCheckBox; diff --git a/src/resources/theme.cpp b/src/resources/theme.cpp index e95a1fa9..4b46b003 100644 --- a/src/resources/theme.cpp +++ b/src/resources/theme.cpp @@ -396,6 +396,7 @@ static int readColorType(const std::string &type) { static std::string colors[] = { "TEXT", + "NPC_DIALOG_TEXT", "SHADOW", "OUTLINE", "PROGRESS_BAR", diff --git a/src/resources/theme.h b/src/resources/theme.h index b2dd10de..9c1ec293 100644 --- a/src/resources/theme.h +++ b/src/resources/theme.h @@ -121,6 +121,7 @@ class Theme : public Palette, public EventListener enum ThemePalette { TEXT, + NPC_DIALOG_TEXT, SHADOW, OUTLINE, PROGRESS_BAR, |