From 9bfdc779f1a9aedd04d9966ef7f5cae44d52b717 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 21 Feb 2023 22:29:35 -0800 Subject: [PATCH] MM: MM1: Adding a character select dialog --- devtools/create_mm/files/mm1/strings_en.yml | 2 + engines/mm/mm1/data/party.cpp | 9 +++ engines/mm/mm1/data/party.h | 5 ++ engines/mm/mm1/views_enh/character_select.cpp | 75 +++++++++++++++++++ engines/mm/mm1/views_enh/character_select.h | 60 +++++++++++++++ engines/mm/mm1/views_enh/dialogs.h | 6 +- engines/mm/mm1/views_enh/party_view.cpp | 2 +- engines/mm/mm1/views_enh/party_view.h | 7 ++ .../mm/mm1/views_enh/spells/cast_spell.cpp | 26 ++++++- engines/mm/mm1/views_enh/spells/cast_spell.h | 10 +++ engines/mm/module.mk | 1 + 11 files changed, 196 insertions(+), 7 deletions(-) create mode 100644 engines/mm/mm1/views_enh/character_select.cpp create mode 100644 engines/mm/mm1/views_enh/character_select.h diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml index 6077276c8d0..b7c78204b7e 100644 --- a/devtools/create_mm/files/mm1/strings_en.yml +++ b/devtools/create_mm/files/mm1/strings_en.yml @@ -479,6 +479,8 @@ enhdialogs: exchange: "\x01""37Exch" conditions: good: "Good" + character_select: + title: "Select target" location: store: "store" options: "options" diff --git a/engines/mm/mm1/data/party.cpp b/engines/mm/mm1/data/party.cpp index e2cb78484e3..1f20a66eb66 100644 --- a/engines/mm/mm1/data/party.cpp +++ b/engines/mm/mm1/data/party.cpp @@ -165,5 +165,14 @@ void Party::rearrange(const Common::Array &party) { } } +int Party::indexOf(const Character *c) { + for (uint i = 0; i < size(); ++i) { + if (&(*this)[i] == c) + return i; + } + + return -1; +} + } // namespace MM1 } // namespace MM diff --git a/engines/mm/mm1/data/party.h b/engines/mm/mm1/data/party.h index 4f56a4f91c6..92bbae46c7a 100644 --- a/engines/mm/mm1/data/party.h +++ b/engines/mm/mm1/data/party.h @@ -97,6 +97,11 @@ struct Party : public Common::Array { * Synchronizes the party to/from savegames */ void synchronize(Common::Serializer &s); + + /** + * Return the index of a given character + */ + int indexOf(const Character *c); }; } // namespace MM1 diff --git a/engines/mm/mm1/views_enh/character_select.cpp b/engines/mm/mm1/views_enh/character_select.cpp new file mode 100644 index 00000000000..ff804b37161 --- /dev/null +++ b/engines/mm/mm1/views_enh/character_select.cpp @@ -0,0 +1,75 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "mm/mm1/views_enh/character_select.h" +#include "mm/mm1/events.h" +#include "mm/mm1/globals.h" + +namespace MM { +namespace MM1 { +namespace ViewsEnh { + +CharacterSelect::CharacterSelect() : PartyView("CharacterSelect") { + _bounds = Common::Rect(225, 18 * 8, 320, 200); +} + +bool CharacterSelect::msgFocus(const FocusMessage &msg) { + _currCharacter = g_globals->_currCharacter; + g_globals->_currCharacter = nullptr; + return PartyView::msgFocus(msg); +} + +void CharacterSelect::draw() { + ScrollView::draw(); + + _fontReduced = true; + writeString(STRING["enhdialogs.character_select.title"]); +} + +bool CharacterSelect::msgAction(const ActionMessage &msg) { + if (msg._action == KEYBIND_ESCAPE) { + close(); + g_events->send(g_events->focusedView()->getName(), + GameMessage("CHAR_SELECTED", -1)); + return true; + } else { + return PartyView::msgAction(msg); + } +} + +bool CharacterSelect::msgGame(const GameMessage &msg) { + if (msg._name == "UPDATE") { + close(); + + int charNum = g_globals->_party.indexOf(g_globals->_currCharacter); + g_globals->_currCharacter = _currCharacter; + + g_events->send(g_events->focusedView()->getName(), + GameMessage("CHAR_SELECTED", charNum)); + return true; + } + + return true; +} + +} // namespace ViewsEnh +} // namespace MM1 +} // namespace MM diff --git a/engines/mm/mm1/views_enh/character_select.h b/engines/mm/mm1/views_enh/character_select.h new file mode 100644 index 00000000000..591adebf7ec --- /dev/null +++ b/engines/mm/mm1/views_enh/character_select.h @@ -0,0 +1,60 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef MM1_VIEWS_ENH_CHARACTER_SELECT_H +#define MM1_VIEWS_ENH_CHARACTER_SELECT_H + +#include "mm/mm1/messages.h" +#include "mm/mm1/data/character.h" +#include "mm/mm1/views_enh/party_view.h" + +namespace MM { +namespace MM1 { +namespace ViewsEnh { + +/** + * Dialog for choosing a character target + */ +class CharacterSelect : public PartyView { +private: + Character *_currCharacter = nullptr; +protected: + /** + * Return true if a character should be selected by default + */ + virtual bool selectCharByDefault() const { + return false; + } +public: + CharacterSelect(); + virtual ~CharacterSelect() {} + + bool msgFocus(const FocusMessage &msg) override; + void draw() override; + bool msgAction(const ActionMessage &msg) override; + bool msgGame(const GameMessage &msg) override; +}; + +} // namespace ViewsEnh +} // namespace MM1 +} // namespace MM + +#endif diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h index 60e2c249560..b32cc784c2e 100644 --- a/engines/mm/mm1/views_enh/dialogs.h +++ b/engines/mm/mm1/views_enh/dialogs.h @@ -28,6 +28,7 @@ #include "mm/mm1/views/protect.h" #include "mm/mm1/views/title.h" #include "mm/mm1/views_enh/character_info.h" +#include "mm/mm1/views_enh/character_select.h" #include "mm/mm1/views_enh/game.h" #include "mm/mm1/views_enh/main_menu.h" #include "mm/mm1/views_enh/map_popup.h" @@ -53,13 +54,14 @@ private: Views::Protect _protect; Views::Title _title; // Views::ViewCharacter _viewCharacter; + ViewsEnh::Locations::Market _market; + ViewsEnh::Locations::Temple _temple; ViewsEnh::Spells::CastSpell _castSpell; ViewsEnh::Spells::Spellbook _spellbook; + ViewsEnh::CharacterSelect _characterSelect; ViewsEnh::MainMenu _mainMenu; ViewsEnh::MapPopup _mapPopup; ViewsEnh::QuickRef _quickRef; - ViewsEnh::Locations::Market _market; - ViewsEnh::Locations::Temple _temple; public: Dialogs() {} }; diff --git a/engines/mm/mm1/views_enh/party_view.cpp b/engines/mm/mm1/views_enh/party_view.cpp index 2af20caeb86..d2a21076da5 100644 --- a/engines/mm/mm1/views_enh/party_view.cpp +++ b/engines/mm/mm1/views_enh/party_view.cpp @@ -31,7 +31,7 @@ namespace ViewsEnh { bool PartyView::msgFocus(const FocusMessage &msg) { // Turn on highlight for selected character - if (!g_globals->_currCharacter) + if (!g_globals->_currCharacter && selectCharByDefault()) g_globals->_currCharacter = &g_globals->_party[0]; g_events->send("GameParty", GameMessage("CHAR_HIGHLIGHT", (int)true)); diff --git a/engines/mm/mm1/views_enh/party_view.h b/engines/mm/mm1/views_enh/party_view.h index a45fb940172..458aa17f582 100644 --- a/engines/mm/mm1/views_enh/party_view.h +++ b/engines/mm/mm1/views_enh/party_view.h @@ -36,6 +36,13 @@ protected: virtual bool canSwitchChar() const { return true; } + + /** + * Return true if a character should be selected by default + */ + virtual bool selectCharByDefault() const { + return true; + } public: PartyView(const Common::String &name) : ScrollView(name) {} PartyView(const Common::String &name, UIElement *owner) : diff --git a/engines/mm/mm1/views_enh/spells/cast_spell.cpp b/engines/mm/mm1/views_enh/spells/cast_spell.cpp index 4b3f02bec57..140bb75d720 100644 --- a/engines/mm/mm1/views_enh/spells/cast_spell.cpp +++ b/engines/mm/mm1/views_enh/spells/cast_spell.cpp @@ -80,13 +80,20 @@ void CastSpell::draw() { bool CastSpell::msgKeypress(const KeypressMessage &msg) { if (msg.keycode == Common::KEYCODE_c) { - close(); - + // Cast a spell const Character &c = *g_globals->_currCharacter; - if (c._nonCombatSpell != -1) { - // TODO: Cast spell here + + if (!canCast()) { + close(); + spellError(); + } else if (hasCharTarget()) { + addView("CharacterSelect"); + } else { + close(); + castSpell(); } return true; + } else if (msg.keycode == Common::KEYCODE_n) { // Select a new spell addView("Spellbook"); @@ -113,6 +120,9 @@ bool CastSpell::msgGame(const GameMessage &msg) { updateSelectedSpell(); draw(); return true; + } else if (msg._name == "CHAR_SELECTED" && msg._value != -1) { + close(); + castSpell(&g_globals->_party[msg._value]); } return true; @@ -133,6 +143,14 @@ void CastSpell::updateSelectedSpell() { } } +void CastSpell::castSpell(Character *target) { + warning("TODO: cast spell"); +} + +void CastSpell::spellError() { + warning("TODO: spell error"); +} + } // namespace Spells } // namespace ViewsEnh } // namespace MM1 diff --git a/engines/mm/mm1/views_enh/spells/cast_spell.h b/engines/mm/mm1/views_enh/spells/cast_spell.h index 108f334f118..e0ca1f8528c 100644 --- a/engines/mm/mm1/views_enh/spells/cast_spell.h +++ b/engines/mm/mm1/views_enh/spells/cast_spell.h @@ -43,6 +43,16 @@ private: */ void updateSelectedSpell(); + /** + * Casts the selected spell + */ + void castSpell(Character *target = nullptr); + + /** + * Handles spell errors + */ + void spellError(); + public: CastSpell(); virtual ~CastSpell() {} diff --git a/engines/mm/module.mk b/engines/mm/module.mk index d9854c53c10..af30563d0eb 100644 --- a/engines/mm/module.mk +++ b/engines/mm/module.mk @@ -123,6 +123,7 @@ MODULE_OBJS += \ mm1/views_enh/spells/spellbook.o \ mm1/views_enh/button_container.o \ mm1/views_enh/character_info.o \ + mm1/views_enh/character_select.o \ mm1/views_enh/dialogs.o \ mm1/views_enh/game.o \ mm1/views_enh/game_commands.o \