[Scummvm-git-logs] scummvm master -> 3b7bb9cfa92af9fe81344d60bc4e336003dc5f28
dreammaster
noreply at scummvm.org
Sun Mar 26 05:26:41 UTC 2023
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
b9fb7c9fca MM: MM1: Beginnings of enhanced mode combat view
bb220307f0 MM: MM1: Support inverse characters
a4e5e01414 MM: MM1: Adding initial combat info display
8b91aa90e1 MM: MM1: Adding combat options display
e8492022ef MM: MM1: Camel case the monster list
3b7bb9cfa9 MM: MM1: Fix display of combat party names
Commit: b9fb7c9fca8c32da66351c98c2a0beb73ece1b8f
https://github.com/scummvm/scummvm/commit/b9fb7c9fca8c32da66351c98c2a0beb73ece1b8f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-25T22:21:37-07:00
Commit Message:
MM: MM1: Beginnings of enhanced mode combat view
Changed paths:
A engines/mm/mm1/views_enh/combat.cpp
A engines/mm/mm1/views_enh/combat.h
engines/mm/mm1/views_enh/dialogs.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/views_enh/combat.cpp b/engines/mm/mm1/views_enh/combat.cpp
new file mode 100644
index 00000000000..2519702da29
--- /dev/null
+++ b/engines/mm/mm1/views_enh/combat.cpp
@@ -0,0 +1,854 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/combat.h"
+#include "mm/mm1/views/character_view_combat.h"
+#include "mm/mm1/game/encounter.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/mm1.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+Combat::Combat() : ScrollView("Combat") {
+}
+
+void Combat::setMode(Mode newMode) {
+ _mode = newMode;
+
+ if (newMode == SELECT_OPTION) {
+ _option = OPTION_NONE;
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_COMBAT);
+ } else {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ }
+
+ if (_mode == MONSTER_SPELL)
+ // Make a copy of monster spell
+ _monsterSpellLines = getMonsterSpellMessage();
+
+ if (_mode != MONSTER_ADVANCES && _mode != MONSTER_ATTACK &&
+ _mode != MONSTER_SPELL)
+ _activeMonsterNum = -1;
+
+ redraw();
+}
+
+void Combat::disableAttacks() {
+ _allowFight = false;
+ _allowShoot = false;
+ _allowCast = false;
+ _allowAttack = false;
+}
+
+bool Combat::msgFocus(const FocusMessage &msg) {
+ g_globals->_currCharacter = g_globals->_combatParty[_currentChar];
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_COMBAT);
+
+ return true;
+}
+
+bool Combat::msgUnfocus(const UnfocusMessage &msg) {
+ MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+ return ScrollView::msgUnfocus(msg);
+}
+
+bool Combat::msgGame(const GameMessage &msg) {
+ if (msg._name == "COMBAT") {
+ // Clear combat data
+ clear();
+
+ loadMonsters();
+ setupCanAttacks();
+ setupHandicap();
+
+ addView();
+ combatLoop();
+ return true;
+
+ } else if (msg._name == "SPELL_RESULT") {
+ assert(msg._value >= 0 && msg._value < 40);
+ _spellResult._lines.clear();
+ _spellResult._lines.push_back(Line(msg._value, 1, msg._stringValue));
+ _spellResult._delaySeconds = 3;
+
+ setMode(SPELL_RESULT);
+ return true;
+ }
+
+ return false;
+}
+
+void Combat::draw() {
+ switch (_mode) {
+ case NEXT_ROUND:
+ writeMonsters();
+ resetBottom();
+ highlightNextRound();
+ delaySeconds(1);
+ return;
+ case MONSTER_ADVANCES:
+ writeString(0, 20, _monsterName);
+ writeString(STRING["dialogs.combat.advances"]);
+ writeSpaces(30);
+ writeRound();
+ writeMonsters();
+ delaySeconds(2);
+ return;
+ case MONSTERS_AFFECTED:
+ writeMonsterEffects();
+ delaySeconds(2);
+ return;
+ case MONSTER_SPELL:
+ writeMonsterSpell();
+ delaySeconds(2);
+ return;
+ case INFILTRATION:
+ writeInfiltration();
+ delaySeconds(3);
+ return;
+ case WAITS_FOR_OPENING:
+ writeWaitsForOpening();
+ delaySeconds(2);
+ return;
+ case CHAR_ATTACKS:
+ writeMonsters();
+ writeCharAttackDamage();
+ delaySeconds(3);
+ return;
+ case NO_EFFECT:
+ writeCharAttackNoEffect();
+ delaySeconds(3);
+ return;
+ case DEFEATED_MONSTERS:
+ writeDefeat();
+ Sound::sound2(SOUND_3);
+ delaySeconds(3);
+ return;
+ default:
+ break;
+ }
+
+ clearSurface();
+ writeStaticContent();
+ writeHandicap();
+ writeRound();
+ writePartyNumbers();
+ writeMonsters();
+ writeParty();
+
+ switch (_mode) {
+ case SELECT_OPTION:
+ writeOptions();
+ break;
+
+ case SPELL_RESULT:
+ writeSpellResult();
+ if (_spellResult._delaySeconds)
+ delaySeconds(_spellResult._delaySeconds);
+ break;
+
+ case MONSTER_ATTACK:
+ writeMonsterAttack();
+ delaySeconds(2);
+ break;
+
+ case MONSTER_FLEES:
+ case MONSTER_WANDERS:
+ writeMonsterAction(_mode == MONSTER_FLEES);
+ delaySeconds(2);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Combat::timeout() {
+ switch (_mode) {
+ case NEXT_ROUND:
+ nextRound2();
+ break;
+ case MONSTER_ADVANCES:
+ nextRound3();
+ break;
+ case MONSTERS_AFFECTED:
+ case CHAR_ATTACKS:
+ case NO_EFFECT:
+ case MONSTER_FLEES:
+ removeDeadMonsters();
+ combatLoop();
+ break;
+ case MONSTER_WANDERS:
+ case INFILTRATION:
+ case MONSTER_ATTACK:
+ writeParty();
+ writeMonsters();
+ checkParty();
+ break;
+ case MONSTER_SPELL:
+ checkMonsterSpellDone();
+ break;
+ case WAITS_FOR_OPENING:
+ combatLoop(true);
+ break;
+ case DEFEATED_MONSTERS:
+ combatDone();
+ break;
+ case SPELL_RESULT:
+ if (_spellResult._timeoutCallback)
+ _spellResult._timeoutCallback();
+ else
+ // Character is done
+ block();
+ break;
+ default:
+ break;
+ }
+}
+
+bool Combat::msgKeypress(const KeypressMessage &msg) {
+ if (endDelay())
+ return true;
+
+ if (_mode == SELECT_OPTION && _option != OPTION_NONE) {
+ switch (_option) {
+ case OPTION_FIGHT:
+ case OPTION_SHOOT:
+ if (msg.keycode >= Common::KEYCODE_a &&
+ msg.keycode < (int)(Common::KEYCODE_a + _attackableCount)) {
+ if (_option == OPTION_FIGHT)
+ fightMonster(msg.keycode - Common::KEYCODE_a);
+ else
+ shootMonster(msg.keycode - Common::KEYCODE_a);
+ }
+ break;
+
+ case OPTION_DELAY:
+ if (msg.keycode >= Common::KEYCODE_0 &&
+ msg.keycode <= Common::KEYCODE_9) {
+ g_globals->_delay = msg.keycode - Common::KEYCODE_0;
+ combatLoop();
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_mode == SPELL_RESULT && !isDelayActive()) {
+ // Displaying a spell result that required waiting for keypress
+ assert(_spellResult._timeoutCallback);
+ _spellResult._timeoutCallback();
+
+ } else if (isDelayActive()) {
+ // In all other modes, if a delay is active, any keypress
+ // will cause the delay to end immediately
+ endDelay();
+ }
+
+ return true;
+}
+
+bool Combat::msgAction(const ActionMessage &msg) {
+ if (endDelay())
+ return true;
+
+ if (_mode != SELECT_OPTION || (_option != OPTION_NONE &&
+ _option != OPTION_EXCHANGE))
+ return false;
+
+ switch (msg._action) {
+ case KEYBIND_VIEW_PARTY1:
+ case KEYBIND_VIEW_PARTY2:
+ case KEYBIND_VIEW_PARTY3:
+ case KEYBIND_VIEW_PARTY4:
+ case KEYBIND_VIEW_PARTY5:
+ case KEYBIND_VIEW_PARTY6: {
+ uint charNum = msg._action - KEYBIND_VIEW_PARTY1;
+ if (charNum < g_globals->_combatParty.size()) {
+ if (_option == OPTION_EXCHANGE) {
+ if (g_globals->_combatParty[charNum] != g_globals->_currCharacter)
+ exchangeWith(charNum);
+ } else {
+ g_globals->_currCharacter = g_globals->_combatParty[charNum];
+ addView("CharacterViewCombat");
+ }
+ return true;
+ }
+ break;
+ }
+
+ case KEYBIND_COMBAT_ATTACK:
+ attack();
+ break;
+ case KEYBIND_COMBAT_BLOCK:
+ block();
+ break;
+ case KEYBIND_COMBAT_CAST:
+ cast();
+ break;
+ case KEYBIND_DELAY:
+ delay();
+ break;
+ case KEYBIND_COMBAT_EXCHANGE:
+ exchange();
+ break;
+ case KEYBIND_COMBAT_FIGHT:
+ fight();
+ break;
+ case KEYBIND_PROTECT:
+ addView("Protect");
+ break;
+ case KEYBIND_QUICKREF:
+ addView("QuickRef");
+ break;
+ case KEYBIND_COMBAT_RETREAT:
+ retreat();
+ break;
+ case KEYBIND_COMBAT_SHOOT:
+ shoot();
+ break;
+ case KEYBIND_COMBAT_USE:
+ use();
+ break;
+ case KEYBIND_ESCAPE:
+ if (_mode == SELECT_OPTION) {
+ _option = OPTION_NONE;
+ combatLoop();
+ }
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Combat::writeOptions() {
+ resetBottom();
+
+ switch (_option) {
+ case OPTION_NONE:
+ writeAllOptions();
+ break;
+ case OPTION_DELAY:
+ writeDelaySelect();
+ break;
+ case OPTION_EXCHANGE:
+ writeExchangeSelect();
+ break;
+ case OPTION_FIGHT:
+ writeFightSelect();
+ break;
+ case OPTION_SHOOT:
+ writeShootSelect();
+ break;
+ default:
+ break;
+ }
+}
+
+void Combat::writeAllOptions() {
+ assert(g_globals->_currCharacter &&
+ g_globals->_currCharacter == g_globals->_combatParty[_currentChar]);
+ const Character &c = *g_globals->_currCharacter;
+ writeString(0, 20, STRING["dialogs.combat.options_for"]);
+ writeString(0, 22, c._name);
+
+ // Highlight the currently active character
+ writeChar(3 + 4 * (_currentChar % 2), 3 + (_currentChar / 2),
+ (unsigned char)'1' + _currentChar + 0x80);
+
+ bool testShoot;
+ if (c._canAttack) {
+ writeAttackOptions();
+ _allowAttack = true;
+ _allowFight = true;
+
+ // Archers can always attack
+ testShoot = c._class == ARCHER;
+ } else {
+ testShoot = true;
+ }
+ if (testShoot && c._missileAttr._base) {
+ _allowShoot = true;
+ writeShootOption();
+ }
+
+ if (c._sp._current) {
+ writeCastOption();
+ _allowCast = true;
+ }
+
+ writeString(16, 22, STRING["dialogs.combat.exchange_use"]);
+ writeString(16, 23, STRING["dialogs.combat.retreat_block"]);
+}
+
+void Combat::writeDelaySelect() {
+ resetBottom();
+ writeString(0, 20, STRING["dialogs.combat.set_delay"]);
+ writeString(0, 23, Common::String::format(
+ STRING["dialogs.combat.delay_currently"].c_str(),
+ g_globals->_delay));
+ escToGoBack(0, 23);
+}
+
+void Combat::writeExchangeSelect() {
+ resetBottom();
+ writeString(7, 20, Common::String::format(
+ STRING["dialogs.combat.exchange_places"].c_str(),
+ '0' + g_globals->_combatParty.size()));
+ escToGoBack(12, 23);
+}
+
+void Combat::writeFightSelect() {
+ _attackableCount = MIN(_attackersCount, (int)_remainingMonsters.size());
+
+ writeString(10, 20, Common::String::format(
+ STRING["dialogs.combat.fight_which"].c_str(), 'A' + _attackableCount - 1));
+ escToGoBack(12, 23);
+}
+
+void Combat::writeShootSelect() {
+ _attackableCount = MIN(_attackersCount, (int)_remainingMonsters.size());
+
+ writeString(10, 20, Common::String::format(
+ STRING["dialogs.combat.shoot_which"].c_str(), 'A' + _attackableCount - 1));
+ escToGoBack(12, 23);
+}
+
+void Combat::writeAttackOptions() {
+ writeString(16, 20, STRING["dialogs.combat.attack"]);
+ writeString(16, 21, STRING["dialogs.combat.fight"]);
+}
+
+void Combat::writeCastOption() {
+ writeString(30, 21, STRING["dialogs.combat.cast"]);
+}
+
+void Combat::writeShootOption() {
+ writeString(30, 20, STRING["dialogs.combat.shoot"]);
+}
+
+void Combat::resetBottom() {
+ clearLines(20, 24);
+ _allowFight = _allowShoot = false;
+ _allowCast = _allowAttack = false;
+}
+
+void Combat::writeStaticContent() {
+ writeString(0, 0, STRING["dialogs.combat.combat"]);
+ writeString(0, 1, STRING["dialogs.combat.round"]);
+ writeString(0, 7, STRING["dialogs.combat.delay"]);
+ writeString(0, 8, STRING["dialogs.combat.protect"]);
+ writeString(0, 9, STRING["dialogs.combat.quickref"]);
+ writeString(0, 10, STRING["dialogs.combat.view_char"]);
+ writeString(0, 12, STRING["dialogs.combat.handicap"]);
+
+ _textPos = Common::Point(0, 15);
+ for (int i = 0; i < 40; ++i)
+ writeChar('-');
+}
+
+void Combat::writeHandicap() {
+ writeString(0, 13, " ");
+ _textPos.x = 0;
+
+ switch (_handicap) {
+ case HANDICAP_EVEN:
+ writeString(STRING["dialogs.combat.even"]);
+ break;
+ case HANDICAP_PARTY:
+ writeString(STRING["dialogs.combat.party_plus"]);
+ writeNumber(_handicapDelta);
+ break;
+ case HANDICAP_MONSTER:
+ writeString(STRING["dialogs.combat.monster_plus"]);
+ writeNumber(_handicapDelta);
+ break;
+ }
+}
+
+void Combat::writeRound() {
+ writeNumber(7, 1, _roundNum);
+}
+
+void Combat::writePartyNumbers() {
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
+ writeChar(2 + 4 * (i % 2), 3 + (i / 2),
+ g_globals->_combatParty[i]->_canAttack ? '+' : ' ');
+ writeChar('1' + i);
+ }
+}
+
+void Combat::writeMonsters() {
+ if (_remainingMonsters.empty()) {
+ _textPos = Common::Point(10, 0);
+ writeSpaces(30);
+ } else {
+ for (int i = 0; i < (int)_remainingMonsters.size(); ++i) {
+ _textPos = Common::Point(11, i);
+ writeChar(i < _attackersCount ? '+' : ' ');
+ unsigned char c = 'A' + i;
+ if ((i == _activeMonsterNum) && (_mode == MONSTER_ADVANCES ||
+ _mode == MONSTER_ATTACK || _mode == MONSTER_SPELL))
+ c |= 0x80;
+
+ writeChar(c);
+ writeString(") ");
+ writeString(_remainingMonsters[i]->_name);
+ writeMonsterStatus(i);
+ }
+ }
+
+ for (; _textPos.y < 15; _textPos.y++) {
+ _textPos.x = 10;
+ writeSpaces(30);
+ }
+}
+
+void Combat::writeMonsterStatus(int monsterNum) {
+ _monsterP = _remainingMonsters[monsterNum];
+ monsterIndexOf();
+ byte statusBits = _remainingMonsters[monsterNum]->_status;
+
+ if (statusBits) {
+ writeDots();
+
+ int status;
+ if (statusBits == MONFLAG_DEAD) {
+ status = MON_DEAD;
+ } else {
+ for (status = MON_PARALYZED; !(statusBits & 0x80);
+ ++status, statusBits <<= 1) {
+ }
+ }
+
+ writeString(STRING[Common::String::format("dialogs.combat.status.%d",
+ status)]);
+ } else if (_monsterP->_hp != _monsterP->_defaultHP) {
+ writeDots();
+ writeString(STRING["dialogs.combat.status.wounded"]);
+ } else {
+ writeSpaces(40 - _textPos.x);
+ }
+}
+
+void Combat::writeDots() {
+ while (_textPos.x < 30)
+ writeChar('.');
+}
+
+void Combat::writeParty() {
+ clearPartyArea();
+
+ for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
+ const Character &c = *g_globals->_combatParty[i];
+ writeString(21 * (i % 2), 16 + (i / 2),
+ Common::String::format("%c%c) %s",
+ (c._condition == 0) ? ' ' : '*',
+ '1' + i,
+ c._name
+ )
+ );
+ }
+}
+
+void Combat::clearPartyArea() {
+ clearLines(16, 18);
+}
+
+void Combat::writeDefeat() {
+ writeString(10, 0, "+----------------------------+");
+ for (int y = 1; y < 8; ++y)
+ writeString(10, y, "! !");
+ writeString(10, 8, "+----------------------------+");
+
+ writeString(10, 2, STRING["dialogs.combat.defeating1"]);
+ writeString(10, 4, STRING["dialogs.combat.defeating2"]);
+ writeNumber(14, 6, _totalExperience);
+ _textPos.x++;
+ writeString(STRING["dialogs.combat.xp"]);
+}
+
+void Combat::highlightNextRound() {
+ Common::String s = Common::String::format("%s%d",
+ STRING["dialogs.combat.round"].c_str(),
+ _roundNum);
+
+ for (uint i = 0; i < s.size(); ++i)
+ s.setChar(s[i] | 0x80, i);
+
+ writeString(0, 1, s);
+}
+
+void Combat::writeMonsterEffects() {
+ if (_monstersRegenerate)
+ writeString(0, 21, STRING["dialogs.combat.regenerate"]);
+
+ if (_monstersResistSpells) {
+ if (_textPos.y != 21)
+ _textPos.y = 20;
+
+ writeString(0, _textPos.y + 1, STRING["dialogs.combat.overcome"]);
+ }
+
+ writeMonsters();
+}
+
+void Combat::writeMonsterAction(bool flees) {
+ resetBottom();
+ writeString(0, 20, _monsterName);
+ writeChar(' ');
+ writeString(STRING[flees ?
+ "dialogs.combat.monster_flees" : "dialogs.combat.monster_wanders"
+ ]);
+}
+
+void Combat::writeMonsterSpell() {
+ resetBottom();
+
+ for (int i = 0, y = 0; i < (int)_monsterSpellLines.size() &&
+ _monsterSpellLines[i].y > y;
+ y = _monsterSpellLines[i].y, ++i) {
+ Common::String text = _monsterSpellLines[i]._text;
+ size_t idx;
+ while ((idx = text.findFirstOf(' ')) != Common::String::npos)
+ text.deleteChar(idx);
+
+ writeString(0, _monsterSpellLines[i].y, text);
+ }
+}
+
+void Combat::writeMonsterAttack() {
+ Common::String monsterName = _monsterP->_name;
+ Common::String attackStyle = STRING[Common::String::format(
+ "dialogs.combat.attack_types.%d", _monsterAttackStyle)];
+ Character &c = *g_globals->_currCharacter;
+
+ Common::String line = Common::String::format("%s %s %s",
+ monsterName.c_str(),
+ attackStyle.c_str(),
+ c._name
+ );
+ writeString(0, 20, line);
+ writeString(0, 21, getAttackString());
+
+ if (_damage) {
+ // Attacks wake up sleeping characters
+ if (!(c._condition & BAD_CONDITION))
+ c._condition &= ~ASLEEP;
+
+ // Also check for secondary monster touch action here
+ // This returns a text line to display, and can also
+ // adjust the damage amount. Another reason why we
+ // can't actually apply damage until here
+ int yp = 22;
+ if (monsterTouch(line))
+ writeString(0, yp++, line);
+
+ Common::String damageStr = subtractDamageFromChar();
+ if (!damageStr.empty())
+ writeString(0, yp, damageStr);
+ }
+}
+
+void Combat::writeInfiltration() {
+ Common::String line = Common::String::format("%s %s",
+ _monsterP->getDisplayName().c_str(),
+ STRING["dialogs.combat.infiltration"].c_str());
+
+ resetBottom();
+ writeString(0, 20, line);
+ Sound::sound(SOUND_2);
+ Sound::sound(SOUND_2);
+}
+
+void Combat::writeWaitsForOpening() {
+ Common::String line = Common::String::format("%s %s",
+ _monsterP->getDisplayName().c_str(),
+ STRING["dialogs.combat.infiltration"].c_str()
+ );
+
+ resetBottom();
+ writeString(0, 20, line);
+}
+
+void Combat::writeSpellResult() {
+ for (uint i = 0; i < _spellResult._lines.size(); ++i) {
+ const Line &l = _spellResult._lines[i];
+ writeString(l.x, l.y + 20, l._text);
+ }
+}
+
+void Combat::checkMonsterSpellDone() {
+ for (uint i = 0; i < _monsterSpellLines.size(); ++i) {
+ if (i > 0 && _monsterSpellLines[i].y ==
+ _monsterSpellLines[i - 1].y) {
+ // Remove the message line just displayed, and redraw
+ // so the next one can be shown
+ _monsterSpellLines.remove_at(i - 1);
+ redraw();
+ return;
+ }
+ }
+
+ checkParty();
+}
+
+void Combat::delay() {
+ setOption(OPTION_DELAY);
+}
+
+void Combat::exchange() {
+ if (g_globals->_combatParty.size() > 1)
+ setOption(OPTION_EXCHANGE);
+}
+
+void Combat::fight() {
+ if (_allowFight) {
+ if (_remainingMonsters.size() < 2) {
+ attackMonsterPhysical();
+ } else {
+ setOption(OPTION_FIGHT);
+ }
+ }
+}
+
+void Combat::shoot() {
+ if (_allowShoot) {
+ if (_remainingMonsters.size() < 2) {
+ attackMonsterPhysical();
+ } else {
+ setOption(OPTION_SHOOT);
+ }
+ }
+}
+
+void Combat::writeMessage() {
+ resetBottom();
+ for (const auto &line : _message)
+ writeString(line.x, line.y, line._text);
+}
+
+void Combat::writeCharAttackDamage() {
+ resetBottom();
+
+ writeString(0, 20, Common::String::format("%s %s %s",
+ g_globals->_currCharacter->_name,
+ STRING[_isShooting ? "dialogs.combat.shoots" :
+ "dialogs.combat.attacks"].c_str(),
+ _monsterP->_name.c_str()
+ ));
+ _isShooting = false;
+
+ writeString(0, 21, getAttackString());
+
+ if (_monsterP->_status == MONFLAG_DEAD) {
+ writeString(0, 22, Common::String::format("%s %s",
+ _monsterP->_name.c_str(),
+ STRING["dialogs.combat.goes_down"].c_str()));
+ }
+}
+
+void Combat::writeCharAttackNoEffect() {
+ resetBottom();
+
+ writeString(0, 20, Common::String::format("%s %s %s",
+ g_globals->_currCharacter->_name,
+ STRING[_isShooting ? "dialogs.combat.shoots" :
+ "dialogs.combat.attacks"].c_str(),
+ _monsterP->_name.c_str()
+ ));
+ _isShooting = false;
+
+ writeString(0, 21, STRING["dialogs.combat.weapon_no_effect"]);
+}
+
+Common::String Combat::getAttackString() {
+ Common::String line1;
+ if (_numberOfTimes == 1) {
+ line1 = STRING["dialogs.combat.once"];
+ } else {
+ line1 = Common::String::format("%d %s", _numberOfTimes,
+ STRING["dialogs.combat.times"].c_str());
+ }
+
+ line1 += Common::String::format(" %s ", STRING["dialogs.combat.and"].c_str());
+
+ if (_displayedDamage == 0) {
+ line1 += STRING["dialogs.combat.misses"];
+ } else {
+ line1 += STRING["dialogs.combat.hit"];
+
+ if (_numberOfTimes > 1) {
+ line1 += ' ';
+
+ if (_timesHit == 1) {
+ line1 += STRING["dialogs.combat.once"];
+ } else {
+ line1 += Common::String::format("%d %s", _timesHit,
+ STRING["dialogs.combat.times"].c_str());
+ }
+ }
+
+ line1 += Common::String::format(" %s %d %s",
+ STRING["dialogs.combat.for"].c_str(), _displayedDamage,
+ STRING[_damage == 1 ? "dialogs.combat.point" : "dialogs.combat.points"].c_str());
+
+ if (line1.size() < 30) {
+ line1 += ' ';
+ line1 += STRING["dialogs.combat.of_damage"];
+ } else {
+ line1 += '!';
+ }
+ }
+
+ return line1;
+}
+
+void Combat::setOption(SelectedOption option) {
+ MetaEngine::setKeybindingMode((option == OPTION_EXCHANGE) ?
+ KeybindingMode::KBMODE_PARTY_MENUS :
+ KeybindingMode::KBMODE_MENUS);
+ _option = option;
+ redraw();
+}
+
+void Combat::displaySpellResult(const InfoMessage &msg) {
+ assert(msg._delaySeconds);
+ _spellResult = msg;
+
+ setMode(SPELL_RESULT);
+}
+
+void Combat::combatDone() {
+ Game::Combat::combatDone();
+
+ close();
+ g_events->send("Game", GameMessage("UPDATE"));
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/combat.h b/engines/mm/mm1/views_enh/combat.h
new file mode 100644
index 00000000000..445c42f64c5
--- /dev/null
+++ b/engines/mm/mm1/views_enh/combat.h
@@ -0,0 +1,282 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_COMBAT_H
+#define MM1_VIEWS_ENH_COMBAT_H
+
+#include "mm/mm1/game/combat.h"
+#include "mm/mm1/views_enh/scroll_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class Combat : public ScrollView, public Game::Combat {
+private:
+ // TODO: Stuff to refactor
+ void writeSpaces(int count) { error("TODO"); }
+ void clearLines(int y1, int y2) { error("TODO"); }
+ void escToGoBack(int x, int y) { error("TODO"); }
+
+private:
+ LineArray _monsterSpellLines;
+ uint _attackableCount = 0;
+ InfoMessage _spellResult;
+ // Combat options that have sub-option selection
+ enum SelectedOption {
+ OPTION_NONE, OPTION_DELAY, OPTION_EXCHANGE,
+ OPTION_FIGHT, OPTION_SHOOT
+ };
+ SelectedOption _option = OPTION_NONE;
+
+ /**
+ * Selects a combat option that requires a selection
+ */
+ void setOption(SelectedOption option);
+
+ void writeOptions();
+ void writeAllOptions();
+ void writeAttackOptions();
+ void writeCastOption();
+ void writeShootOption();
+ void resetBottom();
+
+ /**
+ * Write the encounter handicap
+ */
+ void writeHandicap();
+
+ /**
+ * Write out all the static content
+ */
+ void writeStaticContent();
+
+ /**
+ * Write out the round number
+ */
+ void writeRound();
+
+ /**
+ * Writes out the party member numbers,
+ * with a plus next to each if they can attack
+ */
+ void writePartyNumbers();
+
+ /**
+ * Write the monsters list
+ */
+ void writeMonsters();
+
+ /**
+ * Write out a monster's status
+ */
+ void writeMonsterStatus(int monsterNum);
+
+ /**
+ * Write out a series of dots
+ */
+ void writeDots();
+
+ /**
+ * Writes out the party members
+ */
+ void writeParty();
+
+ /**
+ * Clears the party area
+ */
+ void clearPartyArea();
+
+ /**
+ * Writes the result of defeating all the monsters
+ */
+ void writeDefeat();
+
+ /**
+ * Highlight the round number indicator
+ */
+ void highlightNextRound();
+
+ /**
+ * Write monster changes
+ */
+ void writeMonsterEffects();
+
+ /**
+ * Handles a monster action
+ */
+ void writeMonsterAction(bool flees);
+
+ /**
+ * Write out message from a monster casting a spell
+ */
+ void writeMonsterSpell();
+
+ /**
+ * Write out monster's attack
+ */
+ void writeMonsterAttack();
+
+ /**
+ * Write message for monster infiltrating the party
+ */
+ void writeInfiltration();
+
+ /**
+ * Write message for monster waits for an opening
+ */
+ void writeWaitsForOpening();
+
+ /**
+ * Writes the result of a spell
+ */
+ void writeSpellResult();
+
+ /**
+ * Whether there's messages remaining
+ */
+ void checkMonsterSpellDone();
+
+ /**
+ * Delay option
+ */
+ void delay();
+
+ /**
+ * Exchange option
+ */
+ void exchange();
+
+ /**
+ * Fight option
+ */
+ void fight();
+
+ /**
+ * Shoot option
+ */
+ void shoot();
+
+ /**
+ * Write message for characters attacking monsters
+ */
+ void writeCharAttackDamage();
+
+ /**
+ * Write message for character attack having no effect
+ */
+ void writeCharAttackNoEffect();
+
+ /**
+ * Get attack damage string
+ */
+ Common::String getAttackString();
+
+ /**
+ * Writes out a message
+ */
+ void writeMessage();
+
+ /**
+ * Writes text for delay number selection
+ */
+ void writeDelaySelect();
+
+ /**
+ * Write text for exchange party member
+ */
+ void writeExchangeSelect();
+
+ /**
+ * Having selected to fight, selects monster to attack
+ */
+ void writeFightSelect();
+
+ /**
+ * Having selected to shoot, selects monster to attack
+ */
+ void writeShootSelect();
+
+protected:
+ /**
+ * Sets a new display mode
+ */
+ void setMode(Mode newMode) override;
+
+ /**
+ * Does final cleanup when combat is done
+ */
+ void combatDone() override;
+
+public:
+ Combat();
+ virtual ~Combat() {}
+
+ void displaySpellResult(const InfoMessage &msg) override;
+
+ /**
+ * Disable the flags for allowing attacks for
+ * the current character
+ */
+ void disableAttacks();
+
+ /**
+ * Called when the view is focused
+ */
+ bool msgFocus(const FocusMessage &msg) override;
+
+ /**
+ * Called when the view is unfocused
+ */
+ bool msgUnfocus(const UnfocusMessage &msg) override;
+
+ /**
+ * Called for game messages
+ */
+ bool msgGame(const GameMessage &msg) override;
+
+ /**
+ * Draw the Combat details overlayed on
+ * the existing game screen
+ */
+ void draw() override;
+
+ /**
+ * Handles delay timeouts
+ */
+ void timeout() override;
+
+ /**
+ * Handles keypresses
+ */
+ bool msgKeypress(const KeypressMessage &msg) override;
+
+ /**
+ * Key binder actions
+ */
+ bool msgAction(const ActionMessage &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 3ab802a3dee..60e6b8f1fb0 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -29,6 +29,7 @@
#include "mm/mm1/views_enh/character_inventory.h"
#include "mm/mm1/views_enh/character_select.h"
#include "mm/mm1/views_enh/characters.h"
+#include "mm/mm1/views_enh/combat.h"
#include "mm/mm1/views_enh/confirm.h"
#include "mm/mm1/views_enh/create_characters.h"
#include "mm/mm1/views_enh/encounter.h"
@@ -79,6 +80,7 @@ private:
ViewsEnh::CharacterInventory _characterInventory;
ViewsEnh::CharacterSelect _characterSelect;
ViewsEnh::Characters _characters;
+ ViewsEnh::Combat _combat;
ViewsEnh::Confirm _confirm;
ViewsEnh::CreateCharacters _createCharacters;
ViewsEnh::Encounter _encounter;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 650d34bcfce..98d9d534bdf 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -133,6 +133,7 @@ MODULE_OBJS += \
mm1/views_enh/character_select.o \
mm1/views_enh/character_view.o \
mm1/views_enh/characters.o \
+ mm1/views_enh/combat.o \
mm1/views_enh/confirm.o \
mm1/views_enh/create_characters.o \
mm1/views_enh/dialogs.o \
Commit: bb220307f04e9d497c5eab60df942706372e26ba
https://github.com/scummvm/scummvm/commit/bb220307f04e9d497c5eab60df942706372e26ba
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-25T22:21:38-07:00
Commit Message:
MM: MM1: Support inverse characters
Changed paths:
engines/mm/mm1/views_enh/text_view.cpp
engines/mm/mm1/views_enh/text_view.h
engines/mm/shared/utils/xeen_font.cpp
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 026a85770b9..3bfc4fbd6a0 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -50,10 +50,9 @@ XeenFont *TextView::getFont() const {
&g_globals->_fontNormal;
}
-void TextView::writeChar(char c) {
- assert((unsigned char)c < 0x80);
+void TextView::writeChar(unsigned char c) {
XeenFont::setColors(_colorsNum);
- Graphics::Font &font = *getFont();
+ XeenFont &font = *getFont();
if (c == '\r' || c == '\n') {
_textPos.x = 0;
@@ -74,7 +73,7 @@ void TextView::writeChar(char c) {
}
}
-void TextView::writeChar(int x, int y, char c) {
+void TextView::writeChar(int x, int y, unsigned char c) {
_textPos.x = x;
_textPos.y = y;
writeChar(c);
diff --git a/engines/mm/mm1/views_enh/text_view.h b/engines/mm/mm1/views_enh/text_view.h
index 53565172651..e8e770f7ce2 100644
--- a/engines/mm/mm1/views_enh/text_view.h
+++ b/engines/mm/mm1/views_enh/text_view.h
@@ -52,8 +52,8 @@ protected:
/**
* Write a character
*/
- void writeChar(char c);
- void writeChar(int x, int y, char c);
+ void writeChar(unsigned char c);
+ void writeChar(int x, int y, unsigned char c);
/**
* Write some text
diff --git a/engines/mm/shared/utils/xeen_font.cpp b/engines/mm/shared/utils/xeen_font.cpp
index fd8e449ff53..5b84d437702 100644
--- a/engines/mm/shared/utils/xeen_font.cpp
+++ b/engines/mm/shared/utils/xeen_font.cpp
@@ -56,15 +56,18 @@ void XeenFont::setColors(uint index) {
}
int XeenFont::getCharWidth(uint32 chr) const {
- assert(chr < 128);
+ assert(chr < 256);
return _widths[chr & 0x7f];
}
void XeenFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const {
- assert(chr < 128);
+ assert(chr < 256);
if (chr == 'g' || chr == 'p' || chr == 'q' || chr == 'y')
++y;
+ bool isInverse = (chr >= 128);
+ chr &= 0x7f;
+
const uint16 *src = &_data[chr * FONT_HEIGHT];
for (int yCtr = 0; yCtr < FONT_HEIGHT; ++yCtr, ++src) {
if ((y + yCtr) < 0 || (y + yCtr) > dst->h)
@@ -75,8 +78,12 @@ void XeenFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32
for (int xCtr = 0; xCtr < _widths[chr];
++xCtr, ++dest, srcVal >>= 2) {
- if ((srcVal & 3) && (x + xCtr) >= 0 && (x + xCtr) < dst->w)
- *dest = _colors[srcVal & 3];
+ if ((x + xCtr) >= 0 && (x + xCtr) < dst->w) {
+ if (isInverse)
+ *dest = (srcVal & 3) ? 2 : 0;
+ else if (srcVal & 3)
+ *dest = _colors[srcVal & 3];
+ }
}
}
}
Commit: a4e5e014143302f6c27b05341a87246f5cc273af
https://github.com/scummvm/scummvm/commit/a4e5e014143302f6c27b05341a87246f5cc273af
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-25T22:21:38-07:00
Commit Message:
MM: MM1: Adding initial combat info display
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/views_enh/combat.cpp
engines/mm/mm1/views_enh/combat.h
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/scroll_view.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index fbc07fd9edb..9b525c735b1 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -354,23 +354,23 @@ dialogs:
alignment_slips: "*** Alignment slips ***"
combat: "Combat!"
combat:
- combat: "combat"
+ combat: "Combat"
round: "Round #"
- delay: "d delay"
- protect: "p protect"
- quickref: "q quickref"
- view_char: "# view ch"
- handicap: "handicap"
- options_for: "options for: "
- attack: "'a' attack(a)"
- cast: "'c' cast"
- fight: "'f' fight(+)"
- shoot: "'s' shoot"
- exchange_use: "'e' exchange 'u' use"
- retreat_block: "'r' retreat 'b' block"
- even: "even"
- party_plus: "party +"
- monster_plus: "monster +"
+ delay: "D Delay"
+ protect: "P Protect"
+ quickref: "Q QuickRef"
+ view_char: "# View Ch"
+ handicap: "Handicap"
+ options_for: "Options for: "
+ attack: "'A' Attack(a)"
+ cast: "'C' Cast"
+ fight: "'F' Fight(+)"
+ shoot: "'S' Shoot"
+ exchange_use: "'E' Exchange 'U' Use"
+ retreat_block: "'R' Retreat 'B' Block"
+ even: "Even"
+ party_plus: "Party +"
+ monster_plus: "Monster +"
and_goes_down: "and goes down!!!"
goes_down: "goes down!!!"
dies: "dies!"
diff --git a/engines/mm/mm1/views_enh/combat.cpp b/engines/mm/mm1/views_enh/combat.cpp
index 2519702da29..bfab55cfb32 100644
--- a/engines/mm/mm1/views_enh/combat.cpp
+++ b/engines/mm/mm1/views_enh/combat.cpp
@@ -30,6 +30,10 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
+#define MONSTERS_X 120
+#define BOTTOM_Y 120
+#define LINE_H 8
+
Combat::Combat() : ScrollView("Combat") {
}
@@ -156,6 +160,7 @@ void Combat::draw() {
writePartyNumbers();
writeMonsters();
writeParty();
+ return; //***DEBUG***
switch (_mode) {
case SELECT_OPTION:
@@ -450,29 +455,54 @@ void Combat::writeShootOption() {
writeString(30, 20, STRING["dialogs.combat.shoot"]);
}
+void Combat::clearSurface() {
+ frame();
+ fill();
+
+ clearBottom();
+
+ drawButtons();
+}
+
+void Combat::clearBottom() {
+ _bounds = Common::Rect(0, BOTTOM_Y, 320, 200);
+ frame();
+ fill();
+
+ _bounds = Common::Rect(0, 0, 320, 200);
+}
+
+void Combat::clearArea(const Common::Rect &r) {
+ Graphics::ManagedSurface s = getSurface();
+ Common::Rect area = r;
+ area.translate(_innerBounds.left, _innerBounds.top);
+ area.right = MIN(area.right, _innerBounds.right);
+
+ s.fillRect(area, 0x99);
+}
+
+
void Combat::resetBottom() {
- clearLines(20, 24);
+ clearBottom();
_allowFight = _allowShoot = false;
_allowCast = _allowAttack = false;
}
void Combat::writeStaticContent() {
+ setReduced(false);
writeString(0, 0, STRING["dialogs.combat.combat"]);
- writeString(0, 1, STRING["dialogs.combat.round"]);
- writeString(0, 7, STRING["dialogs.combat.delay"]);
- writeString(0, 8, STRING["dialogs.combat.protect"]);
- writeString(0, 9, STRING["dialogs.combat.quickref"]);
- writeString(0, 10, STRING["dialogs.combat.view_char"]);
- writeString(0, 12, STRING["dialogs.combat.handicap"]);
-
- _textPos = Common::Point(0, 15);
- for (int i = 0; i < 40; ++i)
- writeChar('-');
+ writeString(0, 7 * LINE_H, STRING["dialogs.combat.delay"]);
+ writeString(0, 8 * LINE_H, STRING["dialogs.combat.protect"]);
+ writeString(0, 9 * LINE_H, STRING["dialogs.combat.quickref"]);
+ writeString(0, 10 * LINE_H, STRING["dialogs.combat.view_char"]);
}
void Combat::writeHandicap() {
- writeString(0, 13, " ");
- _textPos.x = 0;
+ writeString(0, 12 * LINE_H, STRING["dialogs.combat.handicap"]);
+
+ clearArea(Common::Rect(0, 13 * LINE_H, 100, 14 * LINE_H));
+
+ _textPos = Common::Point(0, 13 * LINE_H);
switch (_handicap) {
case HANDICAP_EVEN:
@@ -490,40 +520,34 @@ void Combat::writeHandicap() {
}
void Combat::writeRound() {
- writeNumber(7, 1, _roundNum);
+ writeString(0, LINE_H, Common::String::format("%s%d",
+ STRING["dialogs.combat.round"].c_str(), _roundNum));
}
void Combat::writePartyNumbers() {
for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
- writeChar(2 + 4 * (i % 2), 3 + (i / 2),
+ writeChar((2 + 4 * (i % 2)) * 8, (3 + (i / 2)) * LINE_H,
g_globals->_combatParty[i]->_canAttack ? '+' : ' ');
writeChar('1' + i);
}
}
void Combat::writeMonsters() {
- if (_remainingMonsters.empty()) {
- _textPos = Common::Point(10, 0);
- writeSpaces(30);
- } else {
- for (int i = 0; i < (int)_remainingMonsters.size(); ++i) {
- _textPos = Common::Point(11, i);
- writeChar(i < _attackersCount ? '+' : ' ');
- unsigned char c = 'A' + i;
- if ((i == _activeMonsterNum) && (_mode == MONSTER_ADVANCES ||
- _mode == MONSTER_ATTACK || _mode == MONSTER_SPELL))
- c |= 0x80;
-
- writeChar(c);
- writeString(") ");
- writeString(_remainingMonsters[i]->_name);
- writeMonsterStatus(i);
- }
- }
+ Common::String mStr = "A)";
+ setReduced(true);
- for (; _textPos.y < 15; _textPos.y++) {
- _textPos.x = 10;
- writeSpaces(30);
+ for (int i = 0; i < (int)_remainingMonsters.size(); ++i) {
+ writeString(MONSTERS_X, i * LINE_H, (i < _attackersCount) ? "+" : " ");
+
+ unsigned char c = 'A' + i;
+ if ((i == _activeMonsterNum) && (_mode == MONSTER_ADVANCES ||
+ _mode == MONSTER_ATTACK || _mode == MONSTER_SPELL))
+ c |= 0x80;
+ mStr.setChar(c, 0);
+ writeString(MONSTERS_X + 16, i * LINE_H, mStr, ALIGN_RIGHT);
+
+ writeString(MONSTERS_X + 22, i * LINE_H, _remainingMonsters[i]->_name);
+ writeMonsterStatus(i);
}
}
@@ -549,13 +573,14 @@ void Combat::writeMonsterStatus(int monsterNum) {
} else if (_monsterP->_hp != _monsterP->_defaultHP) {
writeDots();
writeString(STRING["dialogs.combat.status.wounded"]);
- } else {
- writeSpaces(40 - _textPos.x);
}
}
void Combat::writeDots() {
- while (_textPos.x < 30)
+ const int dotWidth = getStringWidth(".");
+ _textPos.x = ((_textPos.x + dotWidth - 1) / dotWidth) * dotWidth;
+
+ while (_textPos.x < 240)
writeChar('.');
}
@@ -564,7 +589,7 @@ void Combat::writeParty() {
for (uint i = 0; i < g_globals->_combatParty.size(); ++i) {
const Character &c = *g_globals->_combatParty[i];
- writeString(21 * (i % 2), 16 + (i / 2),
+ writeString(160 * (i % 2), (15 + (i / 2)) * LINE_H,
Common::String::format("%c%c) %s",
(c._condition == 0) ? ' ' : '*',
'1' + i,
@@ -575,7 +600,7 @@ void Combat::writeParty() {
}
void Combat::clearPartyArea() {
- clearLines(16, 18);
+ clearArea(Common::Rect(0, 15 * LINE_H, 320, 18 * LINE_H));
}
void Combat::writeDefeat() {
diff --git a/engines/mm/mm1/views_enh/combat.h b/engines/mm/mm1/views_enh/combat.h
index 445c42f64c5..727e0f60526 100644
--- a/engines/mm/mm1/views_enh/combat.h
+++ b/engines/mm/mm1/views_enh/combat.h
@@ -57,6 +57,10 @@ private:
void writeAttackOptions();
void writeCastOption();
void writeShootOption();
+
+ void clearSurface();
+ void clearBottom();
+ void clearArea(const Common::Rect &r);
void resetBottom();
/**
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index 60ebd15f771..bec4e037e36 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -82,6 +82,11 @@ void ScrollView::resetSelectedButton() {
void ScrollView::draw() {
frame();
fill();
+
+ drawButtons();
+}
+
+void ScrollView::drawButtons() {
setTextColor(0);
Graphics::ManagedSurface s = getSurface();
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
index eefc8cbd365..6bfc0054a1d 100644
--- a/engines/mm/mm1/views_enh/scroll_view.h
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -99,6 +99,12 @@ protected:
size_t getButtonCount() const {
return _buttons.size();
}
+
+ /**
+ * Draws the buttons
+ */
+ void drawButtons();
+
public:
ScrollView(const Common::String &name);
ScrollView(const Common::String &name, UIElement *owner);
Commit: 8b91aa90e1e8bc58bfacca26b7e0882ef9c436c0
https://github.com/scummvm/scummvm/commit/8b91aa90e1e8bc58bfacca26b7e0882ef9c436c0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-25T22:21:39-07:00
Commit Message:
MM: MM1: Adding combat options display
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
engines/mm/mm1/globals.cpp
engines/mm/mm1/globals.h
engines/mm/mm1/views_enh/combat.cpp
engines/mm/mm1/views_enh/combat.h
engines/mm/mm1/views_enh/select_number.cpp
engines/mm/mm1/views_enh/select_number.h
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 9b525c735b1..05711deb37b 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -513,6 +513,15 @@ enhdialogs:
title: "Select target"
characters:
left_click: "Left click portraits to view"
+ combat:
+ attack: "\x01""37Attack(A)"
+ cast: "\x01""37Cast"
+ fight: "\x01""37Fight(+)"
+ shoot: "\x01""37Shoot"
+ exchange: "\x01""37Exchange"
+ use: "\x01""37Use"
+ retreat: "\x01""37Retreat"
+ block: "\x01""37Block"
create_characters:
intellect: "Intellect ="
might: "Might ="
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 4cdbbf9e4a3..198fb6d3ef6 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -41,6 +41,17 @@ Globals::~Globals() {
g_globals = nullptr;
}
+void Globals::createBlankButton() {
+ // Get the Escape glyph we'll use as a base
+ Shared::Xeen::SpriteResource escSprite;
+ escSprite.load("esc.icn");
+ _blankButton.create(20, 20);
+ _blankButton.clear(255);
+ _blankButton.setTransparentColor(255);
+ escSprite.draw(&_blankButton, 0, Common::Point(0, 0));
+ _blankButton.fillRect(Common::Rect(2, 2, 18, 18), 0x9f);
+}
+
bool Globals::load(bool isEnhanced) {
// Initialise engine data for the game
Common::U32String errMsg;
@@ -68,6 +79,8 @@ bool Globals::load(bool isEnhanced) {
_tileSprites.load("town.til");
_escSprites.load("esc.icn");
+ createBlankButton();
+
{
Common::File f;
if (!f.open("symbols.bin"))
diff --git a/engines/mm/mm1/globals.h b/engines/mm/mm1/globals.h
index 788e1da025e..a32db31598d 100644
--- a/engines/mm/mm1/globals.h
+++ b/engines/mm/mm1/globals.h
@@ -64,6 +64,11 @@ public:
bool _encountersOn = true;
bool _allSpells = false;
+ /**
+ * Creates a blank button with no inner glyph
+ */
+ void createBlankButton();
+
public:
// Enhanced mode globals
Shared::Xeen::SpriteResource _mainIcons;
@@ -71,6 +76,7 @@ public:
Shared::Xeen::SpriteResource _globalSprites;
Shared::Xeen::SpriteResource _tileSprites;
Shared::Xeen::SpriteResource _escSprites;
+ Graphics::ManagedSurface _blankButton;
byte SYMBOLS[20][64];
XeenFont _fontNormal;
XeenFont _fontReduced;
diff --git a/engines/mm/mm1/views_enh/combat.cpp b/engines/mm/mm1/views_enh/combat.cpp
index bfab55cfb32..153ecbb1ead 100644
--- a/engines/mm/mm1/views_enh/combat.cpp
+++ b/engines/mm/mm1/views_enh/combat.cpp
@@ -160,7 +160,6 @@ void Combat::draw() {
writePartyNumbers();
writeMonsters();
writeParty();
- return; //***DEBUG***
switch (_mode) {
case SELECT_OPTION:
@@ -377,11 +376,11 @@ void Combat::writeAllOptions() {
assert(g_globals->_currCharacter &&
g_globals->_currCharacter == g_globals->_combatParty[_currentChar]);
const Character &c = *g_globals->_currCharacter;
- writeString(0, 20, STRING["dialogs.combat.options_for"]);
- writeString(0, 22, c._name);
+ writeBottomText(0, 0, STRING["dialogs.combat.options_for"]);
+ writeBottomText(0, 2, c._name);
// Highlight the currently active character
- writeChar(3 + 4 * (_currentChar % 2), 3 + (_currentChar / 2),
+ writeChar((2 + 4 * (_currentChar % 2)) * 8 + 8, (3 + (_currentChar / 2)) * LINE_H,
(unsigned char)'1' + _currentChar + 0x80);
bool testShoot;
@@ -405,8 +404,10 @@ void Combat::writeAllOptions() {
_allowCast = true;
}
- writeString(16, 22, STRING["dialogs.combat.exchange_use"]);
- writeString(16, 23, STRING["dialogs.combat.retreat_block"]);
+ writeOption(0, 2, STRING["enhdialogs.combat.exchange"]);
+ writeOption(1, 2, STRING["enhdialogs.combat.use"]);
+ writeOption(0, 3, STRING["enhdialogs.combat.retreat"]);
+ writeOption(1, 3, STRING["enhdialogs.combat.block"]);
}
void Combat::writeDelaySelect() {
@@ -443,16 +444,16 @@ void Combat::writeShootSelect() {
}
void Combat::writeAttackOptions() {
- writeString(16, 20, STRING["dialogs.combat.attack"]);
- writeString(16, 21, STRING["dialogs.combat.fight"]);
+ writeOption(0, 0, STRING["dialogs.combat.attack"]);
+ writeOption(0, 1, STRING["dialogs.combat.fight"]);
}
void Combat::writeCastOption() {
- writeString(30, 21, STRING["dialogs.combat.cast"]);
+ writeOption(1, 1, STRING["dialogs.combat.cast"]);
}
void Combat::writeShootOption() {
- writeString(30, 20, STRING["dialogs.combat.shoot"]);
+ writeString(1, 0, STRING["dialogs.combat.shoot"]);
}
void Combat::clearSurface() {
@@ -477,17 +478,39 @@ void Combat::clearArea(const Common::Rect &r) {
Common::Rect area = r;
area.translate(_innerBounds.left, _innerBounds.top);
area.right = MIN(area.right, _innerBounds.right);
+ area.bottom = MIN(area.bottom, _innerBounds.bottom);
s.fillRect(area, 0x99);
}
void Combat::resetBottom() {
- clearBottom();
+ clearArea(Common::Rect(0, BOTTOM_Y, 320, 200));
_allowFight = _allowShoot = false;
_allowCast = _allowAttack = false;
}
+void Combat::writeBottomText(int x, int line, const Common::String &msg) {
+ writeString(x, (line + 19) * LINE_H, msg);
+}
+
+void Combat::writeOption(uint col, uint row, const Common::String &msg) {
+ assert(col < 2 && row < 4);
+ int x = col ? 240 : 100;
+ int y = (row + 19) * LINE_H;
+
+ // Create an 8x8 blank button
+ Graphics::ManagedSurface btnSmall(8, 8);
+ btnSmall.blitFrom(g_globals->_blankButton, Common::Rect(0, 0, 20, 20),
+ Common::Rect(0, 0, 8, 8));
+
+ Graphics::ManagedSurface s = getSurface();
+ s.blitFrom(btnSmall, Common::Point(x + _innerBounds.left,
+ y + _innerBounds.top));
+
+ writeBottomText(x + 12, row, msg);
+}
+
void Combat::writeStaticContent() {
setReduced(false);
writeString(0, 0, STRING["dialogs.combat.combat"]);
diff --git a/engines/mm/mm1/views_enh/combat.h b/engines/mm/mm1/views_enh/combat.h
index 727e0f60526..d5bf35e5ddb 100644
--- a/engines/mm/mm1/views_enh/combat.h
+++ b/engines/mm/mm1/views_enh/combat.h
@@ -62,6 +62,8 @@ private:
void clearBottom();
void clearArea(const Common::Rect &r);
void resetBottom();
+ void writeBottomText(int x, int line, const Common::String &msg);
+ void writeOption(uint col, uint row, const Common::String &msg);
/**
* Write the encounter handicap
diff --git a/engines/mm/mm1/views_enh/select_number.cpp b/engines/mm/mm1/views_enh/select_number.cpp
index 40a2f180da6..8070ab518df 100644
--- a/engines/mm/mm1/views_enh/select_number.cpp
+++ b/engines/mm/mm1/views_enh/select_number.cpp
@@ -47,15 +47,6 @@ bool SelectNumber::msgMouseDown(const MouseDownMessage &msg) {
SelectNumberSubview::SelectNumberSubview() : ScrollView("SelectNumberSubview") {
_bounds = Common::Rect(234, 144, 320, 200);
-
- // Get the Escape glyph we'll use as a base
- Shared::Xeen::SpriteResource escSprite;
- escSprite.load("esc.icn");
- _button.create(20, 20);
- _button.clear(255);
- _button.setTransparentColor(255);
- escSprite.draw(&_button, 0, Common::Point(0, 0));
- _button.fillRect(Common::Rect(2, 2, 18, 18), 0x9f);
}
void SelectNumberSubview::open(int maxNum, SelectNumberProc callback) {
@@ -80,7 +71,7 @@ void SelectNumberSubview::draw() {
for (int i = 0; i < _maxNumber; ++i) {
- s.blitFrom(_button, Common::Point((i % 3) * 22 + 8,
+ s.blitFrom(g_globals->_blankButton, Common::Point((i % 3) * 22 + 8,
(i / 3) * 22 + 4));
writeString((i % 3) * 22 + 10, (i / 3) * 22 + 2,
Common::String::format("%d", i + 1), ALIGN_MIDDLE);
diff --git a/engines/mm/mm1/views_enh/select_number.h b/engines/mm/mm1/views_enh/select_number.h
index 80299c87a09..fd27b290e79 100644
--- a/engines/mm/mm1/views_enh/select_number.h
+++ b/engines/mm/mm1/views_enh/select_number.h
@@ -34,7 +34,6 @@ typedef void (*SelectNumberProc)(int choiceNum);
class SelectNumberSubview : public ScrollView {
private:
SelectNumberProc _callback = nullptr;
- Graphics::ManagedSurface _button;
int _maxNumber = 0;
public:
Commit: e8492022ef74b83dee756048d20f95c007e6c041
https://github.com/scummvm/scummvm/commit/e8492022ef74b83dee756048d20f95c007e6c041
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-25T22:21:39-07:00
Commit Message:
MM: MM1: Camel case the monster list
Changed paths:
devtools/create_mm/files/mm1/monsters.txt
diff --git a/devtools/create_mm/files/mm1/monsters.txt b/devtools/create_mm/files/mm1/monsters.txt
index f4765d782fd..3758ee13347 100644
--- a/devtools/create_mm/files/mm1/monsters.txt
+++ b/devtools/create_mm/files/mm1/monsters.txt
@@ -1,195 +1,195 @@
-"FLESH EATER ", 6, 0, 2, 2, 6, 1, 7, 50, 0, 0, 0, 130, 0, 0, 16, 4
-"BATTLE RAT ", 10, 1, 1, 3, 3, 1, 12, 50, 2, 0, 0, 130, 0, 0, 0, 6
-"SLITHER BEAST ", 6, 0, 2, 4, 8, 1, 10, 125, 0, 0, 0, 0, 0, 0, 0, 35
-"GNOME ", 6, 50, 3, 5, 6, 1, 12, 125, 2, 20, 1, 0, 132, 0, 6, 8
-"GOBLIN ", 12, 0, 1, 4, 6, 1, 10, 50, 2, 0, 0, 0, 131, 0, 4, 15
-"GREMLIN ", 6, 1, 1, 3, 3, 2, 4, 125, 10, 0, 4, 129, 0, 0, 0, 10
-"GUARDSMAN ", 6, 10, 0, 2, 6, 1, 14, 75, 2, 0, 0, 0, 134, 0, 150, 55
-"KOBOLD ", 10, 1, 1, 4, 4, 1, 6, 50, 2, 0, 0, 0, 131, 0, 4, 5
-"MUTANT LARVA ", 6, 0, 0, 0, 3, 1, 2, 50, 0, 0, 7, 130, 0, 0, 0, 20
-"ORC ", 12, 5, 2, 4, 6, 1, 11, 75, 10, 0, 0, 0, 134, 0, 22, 14
-"POLTERGEIST ", 6, 0, 1, 0, 2, 2, 16, 150, 0, 128, 7, 131, 0, 0, 160, 60
-"RABID JACKAL ", 6, 0, 0, 3, 2, 1, 15, 50, 0, 0, 0, 130, 0, 0, 16, 29
-"SKELETON ", 12, 0, 1, 3, 6, 1, 9, 50, 2, 128, 7, 0, 0, 0, 160, 63
-"SNAKE ", 6, 0, 0, 2, 3, 1, 17, 125, 0, 0, 0, 132, 0, 0, 16, 35
-"SPRITE ", 8, 60, 0, 10, 2, 1, 20, 250, 11, 30, 1, 133, 1, 50, 8, 9
-"VAMPIRE BAT ", 8, 0, 0, 2, 3, 1, 14, 125, 0, 0, 0, 134, 0, 0, 16, 24
-"MINOR DEMON ", 10, 0, 10, 5, 8, 2, 16, 200, 5, 20, 15, 135, 2, 25, 218, 11
-"DEMON DOG ", 10, 3, 8, 3, 10, 2, 14, 100, 0, 0, 0, 0, 0, 0, 16, 32
-"DUNG BEETLE ", 6, 1, 8, 6, 8, 1, 8, 100, 8, 0, 1, 130, 0, 0, 16, 1
-"FIRE ANT ", 15, 0, 5, 5, 6, 1, 7, 100, 26, 0, 67, 0, 3, 10, 20, 0
-"GHOUL ", 6, 0, 8, 4, 5, 3, 13, 200, 5, 128, 7, 136, 0, 0, 16, 58
-"GNOLL ", 10, 0, 8, 5, 8, 1, 10, 100, 10, 0, 0, 0, 134, 0, 6, 15
-"HAG ", 2, 0, 3, 1, 4, 2, 8, 100, 1, 0, 0, 138, 4, 20, 20, 12
-"LOCUST PLAGUE ", 4, 0, 8, 5, 1, 10, 17, 200, 0, 0, 7, 130, 32, 10, 47, 2
-"ORC LEADER ", 1, 0, 10, 5, 8, 1, 14, 100, 28, 0, 0, 0, 138, 0, 38, 14
-"RABID LEPER ", 4, 0, 5, 0, 3, 1, 11, 100, 0, 0, 0, 137, 0, 0, 16, 65
-"ROTTING CORPSE ", 6, 0, 8, 2, 4, 2, 3, 100, 0, 128, 7, 137, 0, 0, 16, 65
-"SAVAGE SHREW ", 4, 5, 4, 3, 5, 3, 13, 150, 0, 0, 0, 0, 0, 0, 0, 32
-"STRANGLING VINE", 10, 0, 1, 3, 3, 4, 6, 100, 40, 0, 3, 134, 0, 0, 51, 47
-"THIEF ", 8, 0, 6, 3, 8, 1, 16, 100, 20, 0, 0, 139, 134, 0, 4, 49
-"TROGLODYTE ", 6, 1, 8, 5, 4, 3, 11, 100, 10, 0, 3, 132, 5, 20, 22, 37
-"ZOMBIE ", 8, 0, 8, 2, 8, 1, 2, 100, 0, 128, 7, 130, 0, 0, 32, 7
-"ACIDIC BLOB ", 6, 0, 8, 1, 8, 2, 8, 300, 0, 0, 127, 140, 6, 20, 118, 20
-"CENTAUR ", 12, 60, 20, 4, 4, 4, 12, 200, 27, 0, 3, 0, 7, 20, 20, 18
-"CLERIC ", 4, 10, 15, 5, 8, 1, 12, 300, 11, 0, 0, 0, 8, 50, 20, 53
-"MINOR DEVIL ", 10, 0, 15, 4, 4, 2, 15, 250, 61, 20, 15, 136, 2, 30, 234, 11
-"FIRE BEETLE ", 5, 0, 16, 7, 15, 1, 6, 200, 2, 0, 65, 0, 3, 30, 22, 1
-"GARGOYLE ", 6, 0, 24, 5, 4, 4, 12, 300, 3, 20, 15, 136, 0, 0, 16, 11
-"GARGANTUAN ANT ", 6, 0, 18, 8, 12, 1, 9, 200, 24, 0, 3, 0, 0, 0, 160, 0
-"DINOLIZARD ", 6, 0, 16, 5, 10, 1, 11, 200, 0, 0, 3, 0, 0, 0, 16, 36
-"GIANT SPIDER ", 6, 1, 20, 5, 8, 1, 18, 200, 1, 0, 1, 140, 0, 0, 16, 0
-"HARPY ", 6, 0, 15, 3, 5, 3, 15, 200, 28, 0, 3, 0, 8, 10, 20, 25
-"HIPPOGRIFF ", 6, 5, 18, 5, 8, 3, 14, 200, 12, 0, 0, 138, 0, 0, 16, 39
-"KILLER BEES ", 4, 0, 10, 10, 2, 10, 16, 300, 0, 0, 7, 132, 32, 20, 42, 2
-"PEGASUS ", 6, 90, 25, 4, 8, 3, 20, 250, 27, 10, 15, 135, 9, 10, 4, 38
-"SHADOW BEAST ", 6, 0, 20, 3, 5, 1, 18, 200, 0, 0, 15, 141, 0, 0, 32, 60
-"WILD BOAR ", 6, 5, 15, 3, 12, 1, 14, 200, 0, 0, 0, 0, 0, 0, 16, 32
-"WOLVERINE ", 3, 0, 10, 5, 5, 3, 12, 250, 10, 0, 1, 0, 0, 0, 16, 29
-"BARBARIAN ", 10, 5, 50, 8, 12, 2, 15, 400, 12, 20, 1, 0, 140, 0, 170, 23
-"CARYATID GUARD ", 6, 2, 20, 5, 10, 1, 15, 400, 1, 25, 255, 142, 9, 10, 54, 64
-"COCKATRICE ", 6, 3, 28, 4, 8, 1, 8, 500, 0, 0, 3, 143, 0, 0, 16, 28
-"CYCLOPS ", 8, 1, 32, 6, 15, 2, 10, 400, 28, 0, 1, 0, 148, 0, 168, 22
-"DRUID ", 4, 2, 24, 4, 8, 2, 14, 400, 3, 0, 1, 138, 7, 50, 22, 53
-"RHINO BEETLE ", 4, 0, 25, 7, 20, 1, 7, 500, 24, 0, 3, 0, 6, 30, 35, 3
-"GIANT CENTIPEDE", 4, 0, 15, 5, 4, 8, 9, 500, 2, 0, 3, 136, 0, 0, 32, 1
-"MAGICIAN ", 3, 1, 25, 5, 8, 1, 15, 600, 29, 0, 1, 0, 10, 90, 24, 52
-"MILITIAMAN ", 6, 10, 30, 9, 10, 2, 9, 300, 2, 0, 1, 0, 138, 0, 150, 50
-"ORC CHIEFTAIN ", 1, 0, 60, 10, 12, 2, 15, 500, 28, 0, 1, 136, 140, 0, 170, 14
-"OGRE ", 6, 0, 45, 7, 10, 2, 12, 350, 12, 0, 1, 0, 140, 0, 170, 19
-"SATYR ", 5, 50, 28, 5, 8, 2, 10, 300, 26, 0, 15, 135, 8, 40, 24, 18
-"SWARMING WASPS ", 4, 0, 20, 4, 2, 10, 17, 400, 0, 0, 7, 132, 32, 25, 47, 2
-"UNICORN ", 4, 90, 35, 8, 10, 3, 22, 500, 7, 20, 127, 141, 9, 20, 69, 38
-"WEREWOLF ", 4, 10, 30, 7, 8, 2, 14, 400, 0, 0, 7, 137, 0, 0, 144, 30
-"WIGHT ", 6, 0, 20, 6, 10, 1, 12, 500, 0, 128, 7, 142, 0, 0, 160, 60
-"BARBARIAN CHIEF", 1, 0, 80, 10, 12, 3, 18, 800, 28, 0, 3, 0, 143, 0, 184, 23
-"BASILISK ", 4, 2, 30, 5, 15, 1, 14, 1000, 0, 0, 3, 143, 11, 30, 163, 45
-"CELESTIAL STAG ", 2, 1, 50, 14, 10, 3, 19, 700, 34, 0, 3, 0, 0, 0, 32, 39
-"DUST DEMON ", 3, 0, 30, 9, 12, 3, 15, 600, 1, 0, 15, 7, 7, 20, 154, 34
-"GIANT SCORPION ", 4, 0, 30, 7, 8, 3, 13, 600, 0, 0, 3, 12, 0, 0, 32, 0
-"5 HEADED HYDRA ", 1, 0, 80, 7, 8, 5, 12, 1500, 60, 0, 3, 0, 14, 40, 160, 44
-"WARRIOR CAT ", 4, 5, 40, 6, 6, 4, 17, 600, 0, 0, 3, 0, 0, 0, 16, 33
-"MINOTAUR ", 2, 0, 55, 7, 35, 1, 15, 1500, 60, 20, 143, 144, 0, 0, 240, 40
-"OGRE CHIEF ", 1, 0, 64, 9, 15, 2, 15, 750, 28, 0, 131, 0, 148, 0, 160, 19
-"PANTHRO MIST ", 6, 5, 40, 7, 8, 4, 18, 600, 0, 0, 3, 0, 0, 0, 16, 33
-"PHANTOM ", 6, 0, 35, 7, 8, 2, 10, 600, 0, 0, 3, 145, 0, 0, 16, 63
-"SWORDSMAN ", 6, 5, 40, 6, 10, 2, 18, 600, 20, 0, 3, 0, 143, 0, 166, 55
-"TROLL ", 6, 0, 40, 6, 9, 3, 12, 600, 12, 0, 131, 0, 0, 0, 224, 17
-"WOOD GOLEM ", 3, 0, 30, 5, 15, 2, 5, 800, 1, 0, 191, 0, 0, 0, 176, 16
-"WRAITH ", 6, 0, 35, 6, 6, 2, 9, 800, 0, 0, 135, 14, 0, 0, 176, 60
-"YETI ", 6, 5, 50, 4, 10, 2, 13, 600, 10, 0, 3, 0, 148, 0, 24, 31
-"DEADLY SPORES ", 15, 0, 10, 2, 1, 1, 10, 600, 0, 0, 3, 4, 12, 90, 54, 48
-"ENCHANTRESS ", 2, 1, 30, 6, 6, 2, 15, 1000, 37, 0, 3, 136, 13, 80, 26, 54
-"FIRE LIZARD ", 4, 1, 40, 7, 10, 3, 12, 800, 0, 0, 67, 0, 3, 20, 166, 36
-"GIANT SLOTH ", 3, 70, 40, 5, 8, 4, 14, 750, 8, 0, 19, 0, 0, 0, 0, 31
-"GRIFFIN ", 8, 10, 45, 7, 8, 3, 14, 700, 28, 0, 3, 143, 0, 0, 16, 28
-"PYRO HYDRA ", 1, 0, 60, 7, 8, 5, 12, 2000, 96, 0, 195, 0, 14, 50, 164, 44
-"MAN EATING MARE", 4, 0, 42, 6, 8, 3, 14, 600, 52, 0, 3, 0, 0, 0, 32, 39
-"MANTICORE ", 4, 1, 40, 6, 6, 4, 12, 600, 28, 0, 3, 0, 3, 20, 42, 26
-"MEDUSA ", 2, 1, 32, 5, 4, 1, 9, 1000, 0, 0, 135, 143, 15, 20, 36, 12
-"RAKSHASHA ", 4, 5, 40, 14, 5, 3, 14, 3000, 255, 50, 255, 142, 13, 80, 31, 11
-"STONE GOLEM ", 3, 0, 50, 7, 40, 1, 6, 1500, 1, 20, 255, 0, 0, 0, 48, 16
-"CAVE TROLL ", 6, 1, 50, 7, 11, 3, 10, 900, 28, 0, 163, 0, 0, 0, 96, 17
-"HILL TROLL ", 5, 2, 50, 8, 12, 3, 11, 1100, 10, 0, 179, 0, 0, 0, 96, 17
-"WARLOCK ", 4, 60, 40, 8, 8, 1, 16, 800, 21, 0, 3, 0, 16, 95, 26, 52
-"WEREBEAR ", 4, 10, 45, 8, 8, 4, 14, 800, 0, 0, 135, 137, 0, 0, 160, 31
-"WICKED WITCH ", 4, 50, 30, 4, 6, 2, 14, 1000, 3, 0, 3, 151, 10, 40, 26, 12
-"ASSASSIN ", 4, 0, 45, 6, 8, 1, 19, 2000, 48, 0, 3, 146, 153, 0, 166, 57
-"BANSHEE ", 2, 1, 40, 10, 10, 1, 12, 3000, 0, 128, 135, 145, 8, 40, 52, 62
-"CAVE GIANT ", 6, 5, 50, 10, 16, 3, 12, 2000, 60, 0, 3, 0, 158, 0, 42, 17
-"CHIMERA ", 4, 1, 60, 8, 5, 6, 14, 5000, 28, 0, 127, 0, 14, 40, 35, 26
-"AIR ELEMENTAL ", 1, 5, 70, 7, 15, 1, 20, 4000, 0, 20, 175, 147, 17, 30, 180, 27
-"EXECUTIONER ", 1, 0, 60, 8, 12, 2, 14, 4000, 28, 0, 3, 146, 0, 0, 160, 57
-"GORGON ", 4, 5, 55, 8, 12, 1, 12, 6000, 0, 0, 3, 143, 11, 40, 35, 45
-"LESSER DEMON ", 4, 0, 40, 10, 8, 4, 16, 2500, 125, 20, 255, 145, 9, 15, 244, 59
-"LESSER DEVIL ", 4, 0, 40, 8, 6, 5, 16, 2500, 125, 20, 255, 145, 9, 25, 244, 59
-"MUMMY ", 6, 0, 50, 7, 20, 2, 7, 2000, 96, 128, 191, 9, 0, 0, 48, 61
-"NECROMANCER ", 4, 1, 35, 7, 8, 2, 17, 2000, 63, 40, 3, 0, 18, 95, 42, 54
-"SPECTER ", 6, 0, 47, 8, 12, 1, 12, 3000, 0, 128, 143, 17, 0, 0, 48, 58
-"WHITE WOLF ", 6, 0, 42, 10, 12, 3, 14, 2500, 4, 0, 19, 9, 27, 30, 50, 29
-"WYVERN ", 6, 5, 45, 7, 18, 2, 12, 2000, 38, 0, 3, 149, 0, 0, 32, 46
-"GREEN DRAGON ", 2, 0, 55, 8, 8, 3, 12, 6000, 63, 20, 255, 12, 25, 50, 163, 43
-"BLUE DRAGON ", 3, 5, 50, 8, 10, 3, 13, 6000, 63, 20, 255, 12, 26, 50, 163, 43
-"EVIL EYE ", 2, 0, 65, 10, 10, 2, 10, 5000, 103, 20, 255, 143, 21, 60, 38, 21
-"EARTH ELEMENTAL", 1, 5, 80, 8, 20, 1, 18, 4000, 0, 0, 215, 147, 17, 35, 180, 27
-"GHOST ", 3, 0, 60, 10, 10, 1, 10, 4000, 0, 128, 135, 16, 0, 0, 48, 62
-"FROST GIANT ", 6, 0, 70, 10, 24, 1, 12, 5000, 62, 0, 147, 0, 148, 0, 166, 23
-"STONE GIANT ", 6, 2, 80, 10, 10, 4, 12, 4000, 62, 0, 131, 0, 148, 0, 166, 19
-"8 HEADED HYDRA ", 1, 0, 75, 10, 8, 8, 13, 7500, 116, 0, 131, 0, 14, 35, 162, 44
-"LAVA BEAST ", 6, 0, 50, 5, 12, 2, 9, 4000, 0, 0, 231, 0, 14, 20, 35, 20
-"MANTIS WARRIOR ", 3, 0, 70, 8, 12, 4, 16, 4000, 68, 0, 131, 12, 0, 0, 160, 4
-"NAGA ", 3, 0, 65, 8, 8, 1, 15, 4000, 60, 25, 131, 136, 8, 40, 22, 35
-"DINOBEETLE ", 4, 0, 200, 10, 50, 1, 8, 6000, 28, 0, 131, 0, 0, 0, 160, 3
-"SPHINX ", 2, 50, 60, 11, 10, 3, 18, 5000, 63, 40, 255, 7, 8, 40, 22, 34
-"VAMPIRE ", 4, 0, 55, 9, 12, 2, 14, 5000, 61, 138, 135, 145, 13, 50, 246, 59
-"WARRIOR ", 4, 1, 75, 12, 12, 2, 14, 4000, 38, 0, 131, 0, 148, 0, 168, 50
-"WIZARD ", 2, 1, 60, 8, 6, 2, 18, 7000, 39, 0, 139, 0, 19, 95, 42, 52
-"WHITE DRAGON ", 3, 0, 65, 8, 12, 3, 15, 10000, 127, 30, 255, 0, 27, 60, 163, 42
-"GRAY DRAGON ", 3, 2, 70, 8, 15, 3, 16, 10000, 127, 30, 255, 0, 28, 60, 163, 42
-"ARCH DRUID ", 1, 5, 65, 10, 8, 2, 18, 15000, 29, 0, 255, 151, 20, 90, 34, 53
-"CHAOTIC KNIGHT ", 2, 0, 90, 14, 15, 3, 18, 7000, 134, 20, 135, 148, 158, 0, 250, 61
-"GREATER DEMON ", 2, 0, 60, 15, 8, 7, 19, 10000, 127, 30, 255, 21, 13, 25, 250, 13
-"GREATER DEVIL ", 2, 0, 65, 12, 15, 4, 19, 10000, 127, 30, 255, 21, 13, 35, 250, 13
-"FIRE ELEMENTAL ", 1, 5, 90, 9, 30, 1, 20, 8000, 0, 0, 199, 147, 17, 40, 180, 27
-"GUARDIAN SPIRIT", 2, 0, 60, 8, 6, 6, 16, 6000, 0, 128, 135, 17, 0, 0, 48, 64
-"STORM GIANT ", 4, 1, 100, 9, 30, 2, 14, 10000, 198, 0, 167, 0, 19, 40, 38, 23
-"12 HEADED HYDRA", 1, 0, 70, 10, 10, 12, 16, 12000, 127, 0, 131, 0, 14, 25, 162, 44
-"INVISIBLE THING", 4, 2, 50, 14, 10, 3, 25, 6000, 0, 0, 255, 22, 0, 0, 32, 58
-"MAGE ", 2, 1, 60, 10, 6, 3, 20, 8000, 39, 20, 143, 0, 21, 95, 42, 52
-"MASTER THIEF ", 2, 1, 65, 12, 8, 2, 20, 5000, 62, 0, 131, 23, 148, 0, 42, 49
-"STEEL GOLEM ", 2, 0, 70, 15, 25, 2, 10, 7500, 129, 30, 255, 0, 0, 0, 176, 61
-"WEREPHASE MUMMY", 4, 1, 70, 20, 20, 2, 35, 8000, 1, 50, 255, 9, 0, 0, 240, 61
-"BLACK DRAGON ", 2, 0, 75, 12, 18, 3, 16, 15000, 127, 30, 255, 135, 29, 70, 163, 41
-"RED DRAGON ", 2, 2, 80, 12, 20, 3, 15, 15000, 127, 30, 255, 141, 30, 70, 163, 41
-"XX!XX!XX!XX!XX ", 2, 0, 10, 20, 1, 1, 18, 15000, 0, 50, 255, 151, 0, 0, 0, 9
-"BLACK KNIGHT ", 1, 0, 150, 16, 50, 3, 20, 10000, 134, 30, 255, 14, 168, 0, 246, 56
-"DEMON LORD ", 1, 0, 150, 20, 50, 2, 30, 60000, 255, 50, 255, 24, 23, 20, 246, 13
-"ARCH DEVIL ", 1, 0, 200, 16, 100, 1, 30, 60000, 255, 50, 255, 24, 23, 30, 246, 13
-"GOLD DRAGON ", 1, 10, 150, 10, 20, 5, 16, 50000, 255, 40, 255, 136, 31, 80, 180, 41
-"SILVER DRAGON ", 2, 0, 90, 8, 16, 4, 16, 20000, 255, 40, 255, 136, 31, 80, 180, 41
-"DIAMOND GOLEM ", 2, 0, 100, 15, 60, 3, 12, 15000, 1, 40, 255, 0, 0, 0, 48, 16
-"16 HEADED HYDRA", 1, 0, 100, 15, 12, 16, 12, 20000, 255, 20, 255, 0, 29, 25, 246, 44
-"HIGH CLERIC ", 1, 5, 100, 14, 16, 3, 18, 10000, 127, 20, 131, 0, 22, 80, 36, 54
-"KIRIN ", 1, 50, 90, 15, 40, 4, 22, 14000, 135, 30, 255, 25, 9, 25, 42, 26
-"LICH ", 1, 0, 80, 10, 10, 2, 20, 20000, 135, 218, 255, 17, 23, 90, 54, 65
-"ARCH MAGE ", 1, 0, 70, 12, 8, 2, 25, 25000, 63, 30, 255, 0, 24, 95, 42, 52
-"MASTER ARCHER ", 1, 5, 120, 10, 16, 8, 18, 25000, 199, 20, 255, 150, 250, 0, 47, 51
-"PHOENIX ", 1, 50, 150, 13, 8, 3, 24, 15000, 129, 10, 255, 144, 14, 60, 42, 27
-"ROC ", 2, 20, 130, 10, 50, 3, 14, 15000, 0, 0, 255, 0, 0, 0, 32, 39
-"SAND WORM ", 3, 1, 200, 7, 200, 1, 8, 15000, 129, 0, 143, 146, 0, 0, 176, 35
-"TITAN ", 1, 50, 180, 13, 60, 2, 30, 20000, 255, 95, 255, 0, 250, 0, 122, 36
-"ALGAE BEAST ", 15, 0, 1, 0, 6, 1, 1, 50, 0, 0, 7, 130, 0, 0, 16, 20
-"WATER RAT ", 15, 0, 3, 1, 6, 1, 6, 100, 0, 0, 6, 130, 0, 0, 16, 6
-"LAMPREY ", 10, 0, 10, 2, 8, 1, 15, 200, 0, 0, 7, 131, 0, 0, 32, 35
-"GIANT LEECH ", 6, 0, 10, 2, 8, 1, 3, 250, 0, 0, 7, 132, 0, 0, 32, 75
-"CROCODILE ", 8, 0, 30, 5, 10, 2, 12, 300, 0, 0, 6, 0, 0, 0, 160, 75
-"GIANT CRAB ", 6, 0, 25, 9, 10, 2, 12, 300, 0, 0, 7, 0, 0, 0, 32, 0
-"BARRACUDA ", 15, 0, 20, 5, 20, 1, 16, 350, 0, 0, 7, 0, 0, 0, 48, 75
-"GIANT SQUID ", 4, 0, 30, 5, 6, 8, 14, 400, 0, 0, 7, 136, 6, 20, 38, 75
-"ELECTRIC EEL ", 10, 0, 30, 5, 8, 1, 15, 500, 0, 0, 47, 136, 10, 20, 47, 75
-"SEA HAG ", 6, 0, 40, 8, 6, 3, 12, 500, 0, 20, 15, 12, 15, 30, 102, 12
-"HIPPOCAMPUS ", 8, 0, 50, 12, 10, 4, 18, 600, 0, 20, 15, 7, 0, 0, 224, 38
-"SHARK ", 15, 0, 40, 6, 30, 2, 24, 700, 0, 0, 15, 0, 0, 0, 176, 75
-"SIREN ", 8, 0, 30, 8, 8, 2, 13, 700, 0, 20, 255, 143, 7, 20, 102, 64
-"WATER ELEMENTAL", 6, 0, 80, 12, 50, 1, 30, 1200, 0, 20, 255, 0, 17, 50, 247, 9
-"SEA SERPENT ", 3, 32, 100, 10, 100, 1, 20, 3000, 0, 40, 143, 146, 0, 0, 240, 42
-"SEA DRAGON ", 3, 32, 150, 15, 50, 4, 32, 20000, 0, 50, 255, 8, 31, 50, 243, 42
-"SCORPION ", 1, 0, 210, 12, 60, 2, 20, 12000, 0, 50, 207, 12, 0, 0, 240, 1
-"DARK RIDER ", 1, 0, 210, 15, 50, 4, 30, 12000, 0, 90, 127, 17, 19, 20, 255, 56
-"WINGED BEAST ", 1, 0, 210, 12, 120, 1, 30, 12000, 0, 50, 159, 8, 0, 0, 240, 46
-"GREAT SEA BEAST", 1, 0, 210, 12, 100, 1, 30, 12000, 0, 50, 143, 147, 0, 0, 240, 75
-"DEMON KING ", 1, 0, 240, 30, 50, 5, 35, 50000, 255, 120, 255, 24, 23, 30, 255, 73
-"SUCCUBUS QUEEN ", 1, 0, 150, 20, 30, 3, 20, 10000, 127, 100, 239, 147, 21, 50, 255, 74
-"TYRANNOSAURUS ", 3, 0, 240, 10, 200, 1, 12, 5000, 6, 0, 7, 147, 0, 0, 160, 45
-"ALIEN ", 6, 16, 100, 15, 20, 2, 15, 1000, 1, 40, 7, 149, 24, 30, 35, 4
-"NATIVES ", 15, 21, 40, 6, 10, 2, 10, 200, 3, 0, 3, 132, 32, 20, 163, 7
-"VOLCANO GOD ", 1, 0, 220, 30, 40, 6, 32, 60000, 255, 120, 255, 24, 13, 50, 255, 20
-"PAUL PEAD ", 1, 0, 100, 10, 30, 1, 19, 2000, 61, 50, 143, 14, 13, 40, 243, 50
-"PIRATE ", 15, 0, 40, 8, 20, 1, 17, 500, 7, 10, 135, 138, 0, 0, 176, 58
-"PIRATE CAPTAIN ", 1, 0, 80, 10, 20, 3, 18, 1000, 15, 30, 135, 11, 7, 20, 51, 58
-"GRAY MINOTAUR ", 1, 0, 150, 13, 30, 4, 20, 15000, 63, 40, 143, 7, 10, 30, 255, 40
-"LORD ARCHER ", 1, 0, 32, 15, 80, 3, 21, 20000, 63, 100, 207, 6, 250, 0, 255, 51
-"BRONTASAURUS ", 3, 16, 200, 8, 150, 1, 6, 5000, 6, 0, 7, 147, 0, 0, 160, 45
-"STEGOSAURUS ", 3, 5, 200, 15, 200, 1, 6, 5000, 6, 0, 7, 147, 0, 0, 160, 45
-"KILLER CADAVER ", 3, 1, 50, 8, 12, 3, 15, 1500, 255, 0, 1, 9, 0, 0, 240, 65
-"OKRIM ", 2, 1, 80, 11, 6, 4, 18, 20000, 39, 0, 139, 0, 19, 95, 42, 52
+"Flesh Eater ", 6, 0, 2, 2, 6, 1, 7, 50, 0, 0, 0, 130, 0, 0, 16, 4
+"Battle Rat ", 10, 1, 1, 3, 3, 1, 12, 50, 2, 0, 0, 130, 0, 0, 0, 6
+"Slither Beast ", 6, 0, 2, 4, 8, 1, 10, 125, 0, 0, 0, 0, 0, 0, 0, 35
+"Gnome ", 6, 50, 3, 5, 6, 1, 12, 125, 2, 20, 1, 0, 132, 0, 6, 8
+"Goblin ", 12, 0, 1, 4, 6, 1, 10, 50, 2, 0, 0, 0, 131, 0, 4, 15
+"Gremlin ", 6, 1, 1, 3, 3, 2, 4, 125, 10, 0, 4, 129, 0, 0, 0, 10
+"Guardsman ", 6, 10, 0, 2, 6, 1, 14, 75, 2, 0, 0, 0, 134, 0, 150, 55
+"Kobold ", 10, 1, 1, 4, 4, 1, 6, 50, 2, 0, 0, 0, 131, 0, 4, 5
+"Mutant Larva ", 6, 0, 0, 0, 3, 1, 2, 50, 0, 0, 7, 130, 0, 0, 0, 20
+"Orc ", 12, 5, 2, 4, 6, 1, 11, 75, 10, 0, 0, 0, 134, 0, 22, 14
+"Poltergeist ", 6, 0, 1, 0, 2, 2, 16, 150, 0, 128, 7, 131, 0, 0, 160, 60
+"Rabid Jackal ", 6, 0, 0, 3, 2, 1, 15, 50, 0, 0, 0, 130, 0, 0, 16, 29
+"Skeleton ", 12, 0, 1, 3, 6, 1, 9, 50, 2, 128, 7, 0, 0, 0, 160, 63
+"Snake ", 6, 0, 0, 2, 3, 1, 17, 125, 0, 0, 0, 132, 0, 0, 16, 35
+"Sprite ", 8, 60, 0, 10, 2, 1, 20, 250, 11, 30, 1, 133, 1, 50, 8, 9
+"Vampire Bat ", 8, 0, 0, 2, 3, 1, 14, 125, 0, 0, 0, 134, 0, 0, 16, 24
+"Minor Demon ", 10, 0, 10, 5, 8, 2, 16, 200, 5, 20, 15, 135, 2, 25, 218, 11
+"Demon Dog ", 10, 3, 8, 3, 10, 2, 14, 100, 0, 0, 0, 0, 0, 0, 16, 32
+"Dung Beetle ", 6, 1, 8, 6, 8, 1, 8, 100, 8, 0, 1, 130, 0, 0, 16, 1
+"Fire Ant ", 15, 0, 5, 5, 6, 1, 7, 100, 26, 0, 67, 0, 3, 10, 20, 0
+"Ghoul ", 6, 0, 8, 4, 5, 3, 13, 200, 5, 128, 7, 136, 0, 0, 16, 58
+"Gnoll ", 10, 0, 8, 5, 8, 1, 10, 100, 10, 0, 0, 0, 134, 0, 6, 15
+"Hag ", 2, 0, 3, 1, 4, 2, 8, 100, 1, 0, 0, 138, 4, 20, 20, 12
+"Locust Plague ", 4, 0, 8, 5, 1, 10, 17, 200, 0, 0, 7, 130, 32, 10, 47, 2
+"Orc Leader ", 1, 0, 10, 5, 8, 1, 14, 100, 28, 0, 0, 0, 138, 0, 38, 14
+"Rabid Leper ", 4, 0, 5, 0, 3, 1, 11, 100, 0, 0, 0, 137, 0, 0, 16, 65
+"Rotting Corpse ", 6, 0, 8, 2, 4, 2, 3, 100, 0, 128, 7, 137, 0, 0, 16, 65
+"Savage Shrew ", 4, 5, 4, 3, 5, 3, 13, 150, 0, 0, 0, 0, 0, 0, 0, 32
+"Strangling Vine", 10, 0, 1, 3, 3, 4, 6, 100, 40, 0, 3, 134, 0, 0, 51, 47
+"Thief ", 8, 0, 6, 3, 8, 1, 16, 100, 20, 0, 0, 139, 134, 0, 4, 49
+"Troglodyte ", 6, 1, 8, 5, 4, 3, 11, 100, 10, 0, 3, 132, 5, 20, 22, 37
+"Zombie ", 8, 0, 8, 2, 8, 1, 2, 100, 0, 128, 7, 130, 0, 0, 32, 7
+"Acidic Blob ", 6, 0, 8, 1, 8, 2, 8, 300, 0, 0, 127, 140, 6, 20, 118, 20
+"Centaur ", 12, 60, 20, 4, 4, 4, 12, 200, 27, 0, 3, 0, 7, 20, 20, 18
+"Cleric ", 4, 10, 15, 5, 8, 1, 12, 300, 11, 0, 0, 0, 8, 50, 20, 53
+"Minor Devil ", 10, 0, 15, 4, 4, 2, 15, 250, 61, 20, 15, 136, 2, 30, 234, 11
+"Fire Beetle ", 5, 0, 16, 7, 15, 1, 6, 200, 2, 0, 65, 0, 3, 30, 22, 1
+"Gargoyle ", 6, 0, 24, 5, 4, 4, 12, 300, 3, 20, 15, 136, 0, 0, 16, 11
+"Gargantuan Ant ", 6, 0, 18, 8, 12, 1, 9, 200, 24, 0, 3, 0, 0, 0, 160, 0
+"Dinolizard ", 6, 0, 16, 5, 10, 1, 11, 200, 0, 0, 3, 0, 0, 0, 16, 36
+"Giant Spider ", 6, 1, 20, 5, 8, 1, 18, 200, 1, 0, 1, 140, 0, 0, 16, 0
+"Harpy ", 6, 0, 15, 3, 5, 3, 15, 200, 28, 0, 3, 0, 8, 10, 20, 25
+"Hippogriff ", 6, 5, 18, 5, 8, 3, 14, 200, 12, 0, 0, 138, 0, 0, 16, 39
+"Killer Bees ", 4, 0, 10, 10, 2, 10, 16, 300, 0, 0, 7, 132, 32, 20, 42, 2
+"Pegasus ", 6, 90, 25, 4, 8, 3, 20, 250, 27, 10, 15, 135, 9, 10, 4, 38
+"Shadow Beast ", 6, 0, 20, 3, 5, 1, 18, 200, 0, 0, 15, 141, 0, 0, 32, 60
+"Wild Boar ", 6, 5, 15, 3, 12, 1, 14, 200, 0, 0, 0, 0, 0, 0, 16, 32
+"Wolverine ", 3, 0, 10, 5, 5, 3, 12, 250, 10, 0, 1, 0, 0, 0, 16, 29
+"Barbarian ", 10, 5, 50, 8, 12, 2, 15, 400, 12, 20, 1, 0, 140, 0, 170, 23
+"Caryatid Guard ", 6, 2, 20, 5, 10, 1, 15, 400, 1, 25, 255, 142, 9, 10, 54, 64
+"Cockatrice ", 6, 3, 28, 4, 8, 1, 8, 500, 0, 0, 3, 143, 0, 0, 16, 28
+"Cyclops ", 8, 1, 32, 6, 15, 2, 10, 400, 28, 0, 1, 0, 148, 0, 168, 22
+"Druid ", 4, 2, 24, 4, 8, 2, 14, 400, 3, 0, 1, 138, 7, 50, 22, 53
+"Rhino Beetle ", 4, 0, 25, 7, 20, 1, 7, 500, 24, 0, 3, 0, 6, 30, 35, 3
+"Giant Centipede", 4, 0, 15, 5, 4, 8, 9, 500, 2, 0, 3, 136, 0, 0, 32, 1
+"Magician ", 3, 1, 25, 5, 8, 1, 15, 600, 29, 0, 1, 0, 10, 90, 24, 52
+"Militiaman ", 6, 10, 30, 9, 10, 2, 9, 300, 2, 0, 1, 0, 138, 0, 150, 50
+"Orc Chieftain ", 1, 0, 60, 10, 12, 2, 15, 500, 28, 0, 1, 136, 140, 0, 170, 14
+"Ogre ", 6, 0, 45, 7, 10, 2, 12, 350, 12, 0, 1, 0, 140, 0, 170, 19
+"Satyr ", 5, 50, 28, 5, 8, 2, 10, 300, 26, 0, 15, 135, 8, 40, 24, 18
+"Swarming Wasps ", 4, 0, 20, 4, 2, 10, 17, 400, 0, 0, 7, 132, 32, 25, 47, 2
+"Unicorn ", 4, 90, 35, 8, 10, 3, 22, 500, 7, 20, 127, 141, 9, 20, 69, 38
+"Werewolf ", 4, 10, 30, 7, 8, 2, 14, 400, 0, 0, 7, 137, 0, 0, 144, 30
+"Wight ", 6, 0, 20, 6, 10, 1, 12, 500, 0, 128, 7, 142, 0, 0, 160, 60
+"Barbarian Chief", 1, 0, 80, 10, 12, 3, 18, 800, 28, 0, 3, 0, 143, 0, 184, 23
+"Basilisk ", 4, 2, 30, 5, 15, 1, 14, 1000, 0, 0, 3, 143, 11, 30, 163, 45
+"Celestial Stag ", 2, 1, 50, 14, 10, 3, 19, 700, 34, 0, 3, 0, 0, 0, 32, 39
+"Dust Demon ", 3, 0, 30, 9, 12, 3, 15, 600, 1, 0, 15, 7, 7, 20, 154, 34
+"Giant Scorpion ", 4, 0, 30, 7, 8, 3, 13, 600, 0, 0, 3, 12, 0, 0, 32, 0
+"5 Headed hydra ", 1, 0, 80, 7, 8, 5, 12, 1500, 60, 0, 3, 0, 14, 40, 160, 44
+"Warrior Cat ", 4, 5, 40, 6, 6, 4, 17, 600, 0, 0, 3, 0, 0, 0, 16, 33
+"Minotaur ", 2, 0, 55, 7, 35, 1, 15, 1500, 60, 20, 143, 144, 0, 0, 240, 40
+"Ogre Chief ", 1, 0, 64, 9, 15, 2, 15, 750, 28, 0, 131, 0, 148, 0, 160, 19
+"Panthro Mist ", 6, 5, 40, 7, 8, 4, 18, 600, 0, 0, 3, 0, 0, 0, 16, 33
+"Phantom ", 6, 0, 35, 7, 8, 2, 10, 600, 0, 0, 3, 145, 0, 0, 16, 63
+"Swordsman ", 6, 5, 40, 6, 10, 2, 18, 600, 20, 0, 3, 0, 143, 0, 166, 55
+"Troll ", 6, 0, 40, 6, 9, 3, 12, 600, 12, 0, 131, 0, 0, 0, 224, 17
+"Wood Golem ", 3, 0, 30, 5, 15, 2, 5, 800, 1, 0, 191, 0, 0, 0, 176, 16
+"Wraith ", 6, 0, 35, 6, 6, 2, 9, 800, 0, 0, 135, 14, 0, 0, 176, 60
+"Yeti ", 6, 5, 50, 4, 10, 2, 13, 600, 10, 0, 3, 0, 148, 0, 24, 31
+"Deadly Spores ", 15, 0, 10, 2, 1, 1, 10, 600, 0, 0, 3, 4, 12, 90, 54, 48
+"Enchantress ", 2, 1, 30, 6, 6, 2, 15, 1000, 37, 0, 3, 136, 13, 80, 26, 54
+"Fire Lizard ", 4, 1, 40, 7, 10, 3, 12, 800, 0, 0, 67, 0, 3, 20, 166, 36
+"Giant Sloth ", 3, 70, 40, 5, 8, 4, 14, 750, 8, 0, 19, 0, 0, 0, 0, 31
+"Griffin ", 8, 10, 45, 7, 8, 3, 14, 700, 28, 0, 3, 143, 0, 0, 16, 28
+"Pyro Hydra ", 1, 0, 60, 7, 8, 5, 12, 2000, 96, 0, 195, 0, 14, 50, 164, 44
+"Man Eating mare", 4, 0, 42, 6, 8, 3, 14, 600, 52, 0, 3, 0, 0, 0, 32, 39
+"Manticore ", 4, 1, 40, 6, 6, 4, 12, 600, 28, 0, 3, 0, 3, 20, 42, 26
+"Medusa ", 2, 1, 32, 5, 4, 1, 9, 1000, 0, 0, 135, 143, 15, 20, 36, 12
+"Rakshasha ", 4, 5, 40, 14, 5, 3, 14, 3000, 255, 50, 255, 142, 13, 80, 31, 11
+"Stone Golem ", 3, 0, 50, 7, 40, 1, 6, 1500, 1, 20, 255, 0, 0, 0, 48, 16
+"Cave Troll ", 6, 1, 50, 7, 11, 3, 10, 900, 28, 0, 163, 0, 0, 0, 96, 17
+"Hill Troll ", 5, 2, 50, 8, 12, 3, 11, 1100, 10, 0, 179, 0, 0, 0, 96, 17
+"Warlock ", 4, 60, 40, 8, 8, 1, 16, 800, 21, 0, 3, 0, 16, 95, 26, 52
+"Werebear ", 4, 10, 45, 8, 8, 4, 14, 800, 0, 0, 135, 137, 0, 0, 160, 31
+"Wicked Witch ", 4, 50, 30, 4, 6, 2, 14, 1000, 3, 0, 3, 151, 10, 40, 26, 12
+"Assassin ", 4, 0, 45, 6, 8, 1, 19, 2000, 48, 0, 3, 146, 153, 0, 166, 57
+"Banshee ", 2, 1, 40, 10, 10, 1, 12, 3000, 0, 128, 135, 145, 8, 40, 52, 62
+"Cave Giant ", 6, 5, 50, 10, 16, 3, 12, 2000, 60, 0, 3, 0, 158, 0, 42, 17
+"Chimera ", 4, 1, 60, 8, 5, 6, 14, 5000, 28, 0, 127, 0, 14, 40, 35, 26
+"Air Elemental ", 1, 5, 70, 7, 15, 1, 20, 4000, 0, 20, 175, 147, 17, 30, 180, 27
+"Executioner ", 1, 0, 60, 8, 12, 2, 14, 4000, 28, 0, 3, 146, 0, 0, 160, 57
+"Gorgon ", 4, 5, 55, 8, 12, 1, 12, 6000, 0, 0, 3, 143, 11, 40, 35, 45
+"Lesser Demon ", 4, 0, 40, 10, 8, 4, 16, 2500, 125, 20, 255, 145, 9, 15, 244, 59
+"Lesser Devil ", 4, 0, 40, 8, 6, 5, 16, 2500, 125, 20, 255, 145, 9, 25, 244, 59
+"Mummy ", 6, 0, 50, 7, 20, 2, 7, 2000, 96, 128, 191, 9, 0, 0, 48, 61
+"Necromancer ", 4, 1, 35, 7, 8, 2, 17, 2000, 63, 40, 3, 0, 18, 95, 42, 54
+"Specter ", 6, 0, 47, 8, 12, 1, 12, 3000, 0, 128, 143, 17, 0, 0, 48, 58
+"White Wolf ", 6, 0, 42, 10, 12, 3, 14, 2500, 4, 0, 19, 9, 27, 30, 50, 29
+"Wyvern ", 6, 5, 45, 7, 18, 2, 12, 2000, 38, 0, 3, 149, 0, 0, 32, 46
+"Green Dragon ", 2, 0, 55, 8, 8, 3, 12, 6000, 63, 20, 255, 12, 25, 50, 163, 43
+"Blue Dragon ", 3, 5, 50, 8, 10, 3, 13, 6000, 63, 20, 255, 12, 26, 50, 163, 43
+"Evil Eye ", 2, 0, 65, 10, 10, 2, 10, 5000, 103, 20, 255, 143, 21, 60, 38, 21
+"Earth Elemental", 1, 5, 80, 8, 20, 1, 18, 4000, 0, 0, 215, 147, 17, 35, 180, 27
+"Ghost ", 3, 0, 60, 10, 10, 1, 10, 4000, 0, 128, 135, 16, 0, 0, 48, 62
+"Frost Giant ", 6, 0, 70, 10, 24, 1, 12, 5000, 62, 0, 147, 0, 148, 0, 166, 23
+"Stone Giant ", 6, 2, 80, 10, 10, 4, 12, 4000, 62, 0, 131, 0, 148, 0, 166, 19
+"8 Headed hydra ", 1, 0, 75, 10, 8, 8, 13, 7500, 116, 0, 131, 0, 14, 35, 162, 44
+"Lava Beast ", 6, 0, 50, 5, 12, 2, 9, 4000, 0, 0, 231, 0, 14, 20, 35, 20
+"Mantis Warrior ", 3, 0, 70, 8, 12, 4, 16, 4000, 68, 0, 131, 12, 0, 0, 160, 4
+"Naga ", 3, 0, 65, 8, 8, 1, 15, 4000, 60, 25, 131, 136, 8, 40, 22, 35
+"Dinobeetle ", 4, 0, 200, 10, 50, 1, 8, 6000, 28, 0, 131, 0, 0, 0, 160, 3
+"Sphinx ", 2, 50, 60, 11, 10, 3, 18, 5000, 63, 40, 255, 7, 8, 40, 22, 34
+"Vampire ", 4, 0, 55, 9, 12, 2, 14, 5000, 61, 138, 135, 145, 13, 50, 246, 59
+"Warrior ", 4, 1, 75, 12, 12, 2, 14, 4000, 38, 0, 131, 0, 148, 0, 168, 50
+"Wizard ", 2, 1, 60, 8, 6, 2, 18, 7000, 39, 0, 139, 0, 19, 95, 42, 52
+"White Dragon ", 3, 0, 65, 8, 12, 3, 15, 10000, 127, 30, 255, 0, 27, 60, 163, 42
+"Gray Dragon ", 3, 2, 70, 8, 15, 3, 16, 10000, 127, 30, 255, 0, 28, 60, 163, 42
+"Arch Druid ", 1, 5, 65, 10, 8, 2, 18, 15000, 29, 0, 255, 151, 20, 90, 34, 53
+"Chaotic Knight ", 2, 0, 90, 14, 15, 3, 18, 7000, 134, 20, 135, 148, 158, 0, 250, 61
+"Greater Demon ", 2, 0, 60, 15, 8, 7, 19, 10000, 127, 30, 255, 21, 13, 25, 250, 13
+"Greater Devil ", 2, 0, 65, 12, 15, 4, 19, 10000, 127, 30, 255, 21, 13, 35, 250, 13
+"Fire Elemental ", 1, 5, 90, 9, 30, 1, 20, 8000, 0, 0, 199, 147, 17, 40, 180, 27
+"Guardian Spirit", 2, 0, 60, 8, 6, 6, 16, 6000, 0, 128, 135, 17, 0, 0, 48, 64
+"Storm Giant ", 4, 1, 100, 9, 30, 2, 14, 10000, 198, 0, 167, 0, 19, 40, 38, 23
+"12 Headed hydra", 1, 0, 70, 10, 10, 12, 16, 12000, 127, 0, 131, 0, 14, 25, 162, 44
+"Invisible Thing", 4, 2, 50, 14, 10, 3, 25, 6000, 0, 0, 255, 22, 0, 0, 32, 58
+"Mage ", 2, 1, 60, 10, 6, 3, 20, 8000, 39, 20, 143, 0, 21, 95, 42, 52
+"Master Thief ", 2, 1, 65, 12, 8, 2, 20, 5000, 62, 0, 131, 23, 148, 0, 42, 49
+"Steel Golem ", 2, 0, 70, 15, 25, 2, 10, 7500, 129, 30, 255, 0, 0, 0, 176, 61
+"Werephase Mummy", 4, 1, 70, 20, 20, 2, 35, 8000, 1, 50, 255, 9, 0, 0, 240, 61
+"Black Dragon ", 2, 0, 75, 12, 18, 3, 16, 15000, 127, 30, 255, 135, 29, 70, 163, 41
+"Red Dragon ", 2, 2, 80, 12, 20, 3, 15, 15000, 127, 30, 255, 141, 30, 70, 163, 41
+"Xx!xx!xx!xx!xx ", 2, 0, 10, 20, 1, 1, 18, 15000, 0, 50, 255, 151, 0, 0, 0, 9
+"Black Knight ", 1, 0, 150, 16, 50, 3, 20, 10000, 134, 30, 255, 14, 168, 0, 246, 56
+"Demon Lord ", 1, 0, 150, 20, 50, 2, 30, 60000, 255, 50, 255, 24, 23, 20, 246, 13
+"Arch Devil ", 1, 0, 200, 16, 100, 1, 30, 60000, 255, 50, 255, 24, 23, 30, 246, 13
+"Gold Dragon ", 1, 10, 150, 10, 20, 5, 16, 50000, 255, 40, 255, 136, 31, 80, 180, 41
+"Silver Dragon ", 2, 0, 90, 8, 16, 4, 16, 20000, 255, 40, 255, 136, 31, 80, 180, 41
+"Diamond Golem ", 2, 0, 100, 15, 60, 3, 12, 15000, 1, 40, 255, 0, 0, 0, 48, 16
+"16 Headed hydra", 1, 0, 100, 15, 12, 16, 12, 20000, 255, 20, 255, 0, 29, 25, 246, 44
+"High Cleric ", 1, 5, 100, 14, 16, 3, 18, 10000, 127, 20, 131, 0, 22, 80, 36, 54
+"Kirin ", 1, 50, 90, 15, 40, 4, 22, 14000, 135, 30, 255, 25, 9, 25, 42, 26
+"Lich ", 1, 0, 80, 10, 10, 2, 20, 20000, 135, 218, 255, 17, 23, 90, 54, 65
+"Arch Mage ", 1, 0, 70, 12, 8, 2, 25, 25000, 63, 30, 255, 0, 24, 95, 42, 52
+"Master Archer ", 1, 5, 120, 10, 16, 8, 18, 25000, 199, 20, 255, 150, 250, 0, 47, 51
+"Phoenix ", 1, 50, 150, 13, 8, 3, 24, 15000, 129, 10, 255, 144, 14, 60, 42, 27
+"Roc ", 2, 20, 130, 10, 50, 3, 14, 15000, 0, 0, 255, 0, 0, 0, 32, 39
+"Sand Worm ", 3, 1, 200, 7, 200, 1, 8, 15000, 129, 0, 143, 146, 0, 0, 176, 35
+"Titan ", 1, 50, 180, 13, 60, 2, 30, 20000, 255, 95, 255, 0, 250, 0, 122, 36
+"Algae Beast ", 15, 0, 1, 0, 6, 1, 1, 50, 0, 0, 7, 130, 0, 0, 16, 20
+"Water Rat ", 15, 0, 3, 1, 6, 1, 6, 100, 0, 0, 6, 130, 0, 0, 16, 6
+"Lamprey ", 10, 0, 10, 2, 8, 1, 15, 200, 0, 0, 7, 131, 0, 0, 32, 35
+"Giant Leech ", 6, 0, 10, 2, 8, 1, 3, 250, 0, 0, 7, 132, 0, 0, 32, 75
+"Crocodile ", 8, 0, 30, 5, 10, 2, 12, 300, 0, 0, 6, 0, 0, 0, 160, 75
+"Giant Crab ", 6, 0, 25, 9, 10, 2, 12, 300, 0, 0, 7, 0, 0, 0, 32, 0
+"Barracuda ", 15, 0, 20, 5, 20, 1, 16, 350, 0, 0, 7, 0, 0, 0, 48, 75
+"Giant Squid ", 4, 0, 30, 5, 6, 8, 14, 400, 0, 0, 7, 136, 6, 20, 38, 75
+"Electric Eel ", 10, 0, 30, 5, 8, 1, 15, 500, 0, 0, 47, 136, 10, 20, 47, 75
+"Sea Hag ", 6, 0, 40, 8, 6, 3, 12, 500, 0, 20, 15, 12, 15, 30, 102, 12
+"Hippocampus ", 8, 0, 50, 12, 10, 4, 18, 600, 0, 20, 15, 7, 0, 0, 224, 38
+"Shark ", 15, 0, 40, 6, 30, 2, 24, 700, 0, 0, 15, 0, 0, 0, 176, 75
+"Siren ", 8, 0, 30, 8, 8, 2, 13, 700, 0, 20, 255, 143, 7, 20, 102, 64
+"Water Elemental", 6, 0, 80, 12, 50, 1, 30, 1200, 0, 20, 255, 0, 17, 50, 247, 9
+"Sea Serpent ", 3, 32, 100, 10, 100, 1, 20, 3000, 0, 40, 143, 146, 0, 0, 240, 42
+"Sea Dragon ", 3, 32, 150, 15, 50, 4, 32, 20000, 0, 50, 255, 8, 31, 50, 243, 42
+"Scorpion ", 1, 0, 210, 12, 60, 2, 20, 12000, 0, 50, 207, 12, 0, 0, 240, 1
+"Dark Rider ", 1, 0, 210, 15, 50, 4, 30, 12000, 0, 90, 127, 17, 19, 20, 255, 56
+"Winged Beast ", 1, 0, 210, 12, 120, 1, 30, 12000, 0, 50, 159, 8, 0, 0, 240, 46
+"Great Sea beast", 1, 0, 210, 12, 100, 1, 30, 12000, 0, 50, 143, 147, 0, 0, 240, 75
+"Demon King ", 1, 0, 240, 30, 50, 5, 35, 50000, 255, 120, 255, 24, 23, 30, 255, 73
+"Succubus Queen ", 1, 0, 150, 20, 30, 3, 20, 10000, 127, 100, 239, 147, 21, 50, 255, 74
+"Tyrannosaurus ", 3, 0, 240, 10, 200, 1, 12, 5000, 6, 0, 7, 147, 0, 0, 160, 45
+"Alien ", 6, 16, 100, 15, 20, 2, 15, 1000, 1, 40, 7, 149, 24, 30, 35, 4
+"Natives ", 15, 21, 40, 6, 10, 2, 10, 200, 3, 0, 3, 132, 32, 20, 163, 7
+"Volcano God ", 1, 0, 220, 30, 40, 6, 32, 60000, 255, 120, 255, 24, 13, 50, 255, 20
+"Paul Pead ", 1, 0, 100, 10, 30, 1, 19, 2000, 61, 50, 143, 14, 13, 40, 243, 50
+"Pirate ", 15, 0, 40, 8, 20, 1, 17, 500, 7, 10, 135, 138, 0, 0, 176, 58
+"Pirate Captain ", 1, 0, 80, 10, 20, 3, 18, 1000, 15, 30, 135, 11, 7, 20, 51, 58
+"Gray Minotaur ", 1, 0, 150, 13, 30, 4, 20, 15000, 63, 40, 143, 7, 10, 30, 255, 40
+"Lord Archer ", 1, 0, 32, 15, 80, 3, 21, 20000, 63, 100, 207, 6, 250, 0, 255, 51
+"Brontasaurus ", 3, 16, 200, 8, 150, 1, 6, 5000, 6, 0, 7, 147, 0, 0, 160, 45
+"Stegosaurus ", 3, 5, 200, 15, 200, 1, 6, 5000, 6, 0, 7, 147, 0, 0, 160, 45
+"Killer Cadaver ", 3, 1, 50, 8, 12, 3, 15, 1500, 255, 0, 1, 9, 0, 0, 240, 65
+"Okrim ", 2, 1, 80, 11, 6, 4, 18, 20000, 39, 0, 139, 0, 19, 95, 42, 52
Commit: 3b7bb9cfa92af9fe81344d60bc4e336003dc5f28
https://github.com/scummvm/scummvm/commit/3b7bb9cfa92af9fe81344d60bc4e336003dc5f28
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-25T22:24:38-07:00
Commit Message:
MM: MM1: Fix display of combat party names
Changed paths:
engines/mm/mm1/views_enh/combat.cpp
diff --git a/engines/mm/mm1/views_enh/combat.cpp b/engines/mm/mm1/views_enh/combat.cpp
index 153ecbb1ead..dacc1b6eb0a 100644
--- a/engines/mm/mm1/views_enh/combat.cpp
+++ b/engines/mm/mm1/views_enh/combat.cpp
@@ -485,7 +485,7 @@ void Combat::clearArea(const Common::Rect &r) {
void Combat::resetBottom() {
- clearArea(Common::Rect(0, BOTTOM_Y, 320, 200));
+ clearArea(Common::Rect(0, 19 * LINE_H, 320, 200));
_allowFight = _allowShoot = false;
_allowCast = _allowAttack = false;
}
More information about the Scummvm-git-logs
mailing list