XEEN: Implementing more combat logic

This commit is contained in:
Paul Gilbert 2015-02-16 19:58:53 -05:00
parent 30d94950be
commit c045adae76
18 changed files with 755 additions and 16 deletions

View file

@ -818,6 +818,9 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsByte(_currentCombatSpell);
}
/**
* Returns the worst condition the character is suffering from
*/
Condition Character::worstCondition() const {
for (int cond = ERADICATED; cond >= CURSED; --cond) {
if (_conditions[cond])
@ -827,6 +830,28 @@ Condition Character::worstCondition() const {
return NO_CONDITION;
}
/**
* Returns whether the given character has a disabling condition, but still alive
*/
bool Character::isDisabled() const {
Condition condition = worstCondition();
return condition == ASLEEP || condition == PARALYZED || condition == UNCONSCIOUS
|| condition == STONED || condition == ERADICATED;
}
/**
* Returns whether the given character has a disabling condition, or is dead
*/
bool Character::isDisabledOrDead() const {
Condition condition = worstCondition();
return condition == ASLEEP || (condition >= PARALYZED && condition <= ERADICATED);
}
/**
* Get the character's age
*/
int Character::getAge(bool ignoreTemp) const {
int year = MIN(Party::_vm->_party->_year - _birthYear, (uint)254);

View file

@ -270,6 +270,10 @@ public:
Condition worstCondition() const;
bool isDisabled() const;
bool isDisabledOrDead() const;
int getAge(bool ignoreTemp = false) const;
int getMaxHP() const;

View file

@ -96,6 +96,10 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
_itemFlag = false;
_monstersAttacking = false;
_combatMode = 0;
_monsterIndex = 0;
_partyRan = false;
_monster2Attack = -1;
_whosSpeed = 0;
}
void Combat::clear() {
@ -412,9 +416,7 @@ void Combat::monstersAttack() {
if (_vm->_mode != MODE_COMBAT) {
// Combat wasn't previously active, but it is now. Set up
// the combat party from the currently active party
_combatParty.clear();
for (uint idx = 0; idx < party._activeParty.size(); ++idx)
_combatParty.push_back(&party._activeParty[idx]);
setupCombatParty();
}
for (int idx = 0; idx < 36; ++idx) {
@ -575,4 +577,150 @@ bool Combat::stopAttack(const Common::Point &diffPt) {
return false;
}
/**
* Setup the combat party with a copy of the currently active party
*/
void Combat::setupCombatParty() {
Party &party = *_vm->_party;
_combatParty.clear();
for (uint idx = 0; idx < party._activeParty.size(); ++idx)
_combatParty.push_back(&party._activeParty[idx]);
}
void Combat::setSpeedTable() {
Map &map = *_vm->_map;
Common::Array<int> charSpeeds;
bool flag = _whosSpeed != -1;
int oldSpeed = (_whosSpeed == -1) ? 0 : _speedTable[_whosSpeed];
Common::fill(&_speedTable[0], &_speedTable[12], -1);
Common::fill(&charSpeeds[0], &charSpeeds[12], -1);
// Set up speeds for party membres
int maxSpeed = 0;
for (uint charNum = 0; charNum < _combatParty.size(); ++charNum) {
Character &c = *_combatParty[charNum];
charSpeeds.push_back(c.getStat(SPEED));
maxSpeed = MAX(charSpeeds[charNum], maxSpeed);
}
// Add in speeds of attacking monsters
for (int monsterNum = 0; monsterNum < 3; ++monsterNum) {
if (_attackMonsters[monsterNum] != -1) {
MazeMonster &monster = map._mobData._monsters[_attackMonsters[monsterNum]];
MonsterStruct &monsterData = map._monsterData[monster._spriteId];
charSpeeds.push_back(monsterData._speed);
maxSpeed = MAX(maxSpeed, monsterData._speed);
} else {
charSpeeds.push_back(0);
}
}
_speedTable.clear();
for (; maxSpeed >= 0; --maxSpeed) {
for (uint idx = 0; idx < charSpeeds.size(); ++idx) {
if (charSpeeds[idx] == maxSpeed)
_speedTable.push_back(idx);
}
}
if (flag) {
if (_speedTable[_whosSpeed] != oldSpeed) {
for (uint idx = 0; idx < charSpeeds.size(); ++idx) {
if (oldSpeed == _speedTable[idx]) {
_whosSpeed = idx;
break;
}
}
}
}
}
/**
* Returns true if all participants in the combat are disabled
*/
bool Combat::allHaveGone() const {
for (uint idx = 0; idx < _charsGone.size(); ++idx) {
if (!_charsGone[idx]) {
if (idx >= _combatParty.size()) {
return false;
} else {
Condition condition = _combatParty[idx]->worstCondition();
if (condition < PARALYZED || condition == NO_CONDITION)
return false;
}
}
}
return true;
}
bool Combat::charsCantAct() const {
for (uint idx = 0; idx < _combatParty.size(); ++idx) {
Condition condition = _combatParty[idx]->worstCondition();
if (!(condition == ASLEEP || (condition >= PARALYZED && condition != NO_CONDITION)))
return false;
}
return true;
}
Common::String Combat::getMonsterDescriptions() {
Map &map = *_vm->_map;
Common::String lines[3];
// Get names of monsters attacking, if any
for (int idx = 0; idx < 3; ++idx) {
if (_attackMonsters[idx] != -1) {
MazeMonster &monster = map._mobData._monsters[_attackMonsters[idx]];
MonsterStruct &monsterData = map._monsterData[monster._spriteId];
Common::String format = "\n\v020\f%2u%s\fd";
format.setChar('2' + idx, 3);
lines[idx] = Common::String::format(format.c_str(), monsterData._name.c_str());
}
}
if (_monsterIndex == 2 && _attackMonsters[2] != -1) {
_monster2Attack = _attackMonsters[2];
} if (_monsterIndex == 1 && _attackMonsters[1] != -1) {
_monster2Attack = _attackMonsters[1];
} else {
_monster2Attack = _attackMonsters[0];
_monsterIndex = 0;
}
return Common::String::format(COMBAT_DETAILS, lines[0].c_str(),
lines[1].c_str(), lines[2].c_str());
}
void Combat::attack(Character &c, int v2) {
error("TODO");
}
void Combat::block() {
_charsBlocked[_whosTurn] = true;
}
bool Combat::castSpell(bool flag) {
error("TODO: castSpell");
}
void Combat::quickFight() {
error("TODO: quickFight");
}
void Combat::giveTreasure() {
error("TODO: giveTreasure");
}
void Combat::run() {
error("TODO: run");
}
} // End of namespace Xeen

View file

@ -57,15 +57,17 @@ private:
XeenEngine *_vm;
public:
Common::Array<Character *> _combatParty;
Common::Array<int> _charsBlocked;
Common::Array<bool> _charsBlocked;
Common::Array<int> _charsGone;
SpriteResource _powSprites;
int _attackMonsters[26];
int _monster2Attack;
int _charsArray1[12];
bool _monPow[12];
int _monsterScale[12];
int _elemPow[12];
int _elemScale[12];
Common::Array<int> _speedTable;
int _shooting[8];
int _globalCombat;
int _whosTurn;
@ -76,6 +78,9 @@ public:
int _gmonHit[36];
bool _monstersAttacking;
int _combatMode;
int _monsterIndex;
bool _partyRan;
int _whosSpeed;
void monstersAttack();
@ -101,6 +106,28 @@ public:
void giveCharDamage(int damage, DamageType attackType, int charIndex);
void moveMonsters();
void setupCombatParty();
void setSpeedTable();
bool allHaveGone() const;
bool charsCantAct() const;
Common::String getMonsterDescriptions();
void attack(Character &c, int v2);
void block();
bool castSpell(bool flag);
void quickFight();
void giveTreasure();
void run();
};
} // End of namespace Xeen

View file

@ -0,0 +1,42 @@
/* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "xeen/dialogs_control_panel.h"
#include "xeen/party.h"
#include "xeen/resources.h"
#include "xeen/xeen.h"
namespace Xeen {
int ControlPanel::show(XeenEngine *vm) {
ControlPanel *dlg = new ControlPanel(vm);
int result = dlg->execute();
delete dlg;
return result;
}
int ControlPanel::execute() {
error("TODO: ControlPanel");
}
} // End of namespace Xeen

View file

@ -0,0 +1,43 @@
/* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef XEEN_DIALOGS_CONTROL_PANEL_H
#define XEEN_DIALOGS_CONTROL_PANEL_H
#include "xeen/dialogs.h"
namespace Xeen {
class ControlPanel : public ButtonContainer {
private:
XeenEngine *_vm;
ControlPanel(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
int execute();
public:
static int show(XeenEngine *vm);
};
} // End of namespace Xeen
#endif /* XEEN_DIALOGS_CONTROL_PANEL_H */

View file

@ -0,0 +1,39 @@
/* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "xeen/dialogs_fight_options.h"
#include "xeen/resources.h"
#include "xeen/xeen.h"
namespace Xeen {
void FightOptions::show(XeenEngine *vm) {
FightOptions *dlg = new FightOptions(vm);
dlg->execute();
delete dlg;
}
void FightOptions::execute() {
error("TODO: FightOptions");
}
} // End of namespace Xeen

View file

@ -0,0 +1,43 @@
/* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef XEEN_DIALOGS_FIGHT_OPTIONS_H
#define XEEN_DIALOGS_FIGHT_OPTIONS_H
#include "xeen/dialogs.h"
namespace Xeen {
class FightOptions : public ButtonContainer {
private:
XeenEngine *_vm;
FightOptions(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
void execute();
public:
static void show(XeenEngine *vm);
};
} // End of namespace Xeen
#endif /* XEEN_DIALOGS_FIGHT_OPTIONS_H */

View file

@ -21,10 +21,13 @@
*/
#include "xeen/interface.h"
#include "xeen/dialogs_char_info.h"
#include "xeen/dialogs_error.h"
#include "xeen/dialogs_automap.h"
#include "xeen/dialogs_char_info.h"
#include "xeen/dialogs_control_panel.h"
#include "xeen/dialogs_error.h"
#include "xeen/dialogs_fight_options.h"
#include "xeen/dialogs_info.h"
#include "xeen/dialogs_items.h"
#include "xeen/dialogs_query.h"
#include "xeen/dialogs_quests.h"
#include "xeen/dialogs_quick_ref.h"
@ -121,6 +124,9 @@ void PartyDrawer::unhighlightChar() {
}
}
void PartyDrawer::resetHighlight() {
_hiliteChar = -1;
}
/*------------------------------------------------------------------------*/
Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm),
@ -320,7 +326,11 @@ void Interface::perform() {
case Common::KEYCODE_TAB:
// Stop mosters doing any movement
_vm->_moveMonsters = false;
warning("TODO: showControlPanel");
if (ControlPanel::show(_vm) == -1) {
_vm->_quitMode = 2;
} else {
_vm->_moveMonsters = 1;
}
break;
case Common::KEYCODE_SPACE:
@ -1811,9 +1821,13 @@ void Interface::assembleBorder() {
void Interface::doCombat() {
Combat &combat = *_vm->_combat;
EventsManager &events = *_vm->_events;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Screen &screen = *_vm->_screen;
bool isDarkCc = _vm->_files->_isDarkCc;
Scripts &scripts = *_vm->_scripts;
SoundManager &sound = *_vm->_sound;
bool upDoorText = _upDoorText;
bool reloadMap = false;
_upDoorText = false;
combat._combatMode = 2;
@ -1827,9 +1841,345 @@ void Interface::doCombat() {
setMainButtons(true);
mainIconsPrint();
combat._combatParty.clear();
combat._charsGone.clear();
combat._charsBlocked.clear();
combat._charsArray1[0] = 0;
combat._charsArray1[1] = 0;
combat._charsArray1[2] = 0;
combat._monstersAttacking = 0;
combat._partyRan = false;
// Set up the combat party
combat.setupCombatParty();
combat.setSpeedTable();
combat._whosSpeed = -1;
combat._whosTurn = -1;
resetHighlight();
error("TODO");
nextChar();
if (!party._dead) {
combat.setSpeedTable();
if (_tillMove) {
combat.moveMonsters();
draw3d(true);
}
Window &w = screen._windows[2];
w.open();
bool breakFlag = false;
while (!_vm->shouldQuit() && !breakFlag) {
highlightChar(combat._whosTurn);
combat.setSpeedTable();
// Write out the description of the monsters being battled
w.writeString(combat.getMonsterDescriptions());
_iconSprites.draw(screen, 32, Common::Point(233, combat._monsterIndex * 10 + 27),
0x8010000);
w.update();
// Wait for keypress
int index = 0;
do {
events.updateGameCounter();
draw3d(true);
if (++index == 5 && combat._attackMonsters[0] != -1) {
MazeMonster &monster = map._mobData._monsters[combat._monster2Attack];
MonsterStruct &monsterData = map._monsterData[monster._spriteId];
sound.playFX(monsterData._fx);
}
do {
events.pollEventsAndWait();
checkEvents(_vm);
} while (!_vm->shouldQuit() && events.timeElapsed() < 1 && !_buttonValue);
} while (!_vm->shouldQuit() && !_buttonValue);
if (_vm->shouldQuit())
return;
switch (_buttonValue) {
case Common::KEYCODE_TAB:
// Show the control panel
if (ControlPanel::show(_vm) == 2) {
reloadMap = true;
breakFlag = true;
} else {
highlightChar(combat._whosTurn);
}
break;
case Common::KEYCODE_1:
case Common::KEYCODE_2:
case Common::KEYCODE_3:
_buttonValue -= Common::KEYCODE_1;
if (combat._attackMonsters[_buttonValue] != -1) {
combat._monster2Attack = combat._attackMonsters[_buttonValue];
combat._monsterIndex = _buttonValue;
}
break;
case Common::KEYCODE_a:
// Attack
combat.attack(*combat._combatParty[combat._whosTurn], 0);
nextChar();
break;
case Common::KEYCODE_b:
// Block
combat.block();
nextChar();
break;
case Common::KEYCODE_c:
// Cast Spell
if (combat.castSpell(false)) {
nextChar();
} else {
highlightChar(combat._combatParty[combat._whosTurn]->_rosterId);
}
break;
case Common::KEYCODE_f:
// Quick Fight
combat.quickFight();
nextChar();
break;
case Common::KEYCODE_i:
// Info dialog
InfoDialog::show(_vm);
highlightChar(combat._whosTurn);
break;
case Common::KEYCODE_o:
// Fight Options
FightOptions::show(_vm);
highlightChar(combat._whosTurn);
break;
case Common::KEYCODE_q:
// Quick Reference dialog
QuickReferenceDialog::show(_vm);
highlightChar(combat._whosTurn);
break;
case Common::KEYCODE_r:
// Run from combat
combat.run();
nextChar();
if (_vm->_mode == MODE_1) {
warning("TODO: loss of treasure");
party.moveToRunLocation();
breakFlag = true;
}
break;
case Common::KEYCODE_u: {
int whosTurn = combat._whosTurn;
ItemsDialog::show(_vm, combat._combatParty[combat._whosTurn], ITEMMODE_COMBAT);
if (combat._whosTurn == whosTurn) {
highlightChar(combat._whosTurn);
} else {
combat._whosTurn = whosTurn;
nextChar();
}
break;
}
case Common::KEYCODE_F1:
case Common::KEYCODE_F2:
case Common::KEYCODE_F3:
case Common::KEYCODE_F4:
case Common::KEYCODE_F5:
case Common::KEYCODE_F6:
// Show character info
_buttonValue -= Common::KEYCODE_F1;
if (_buttonValue < (int)combat._combatParty.size()) {
CharacterInfo::show(_vm, _buttonValue);
}
highlightChar(combat._whosTurn);
break;
case Common::KEYCODE_LEFT:
case Common::KEYCODE_RIGHT:
// Rotate party direction left or right
if (_buttonValue == Common::KEYCODE_LEFT) {
party._mazeDirection = (party._mazeDirection == DIR_NORTH) ?
DIR_WEST : (Direction)((int)party._mazeDirection - 1);
} else {
party._mazeDirection = (party._mazeDirection == DIR_WEST) ?
DIR_NORTH : (Direction)((int)party._mazeDirection + 1);
}
_flipSky ^= 1;
if (_tillMove)
combat.moveMonsters();
party._stepped = true;
break;
}
// Handling for if the combat turn is complete
if (combat.allHaveGone()) {
Common::fill(&combat._charsGone[0], &combat._charsGone[combat._charsGone.size()], false);
Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[combat._charsBlocked.size()], false);
combat.setSpeedTable();
combat._whosTurn = -1;
combat._whosSpeed = -1;
nextChar();
for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
MazeMonster &monster = map._mobData._monsters[idx];
if (monster._spriteId == 53) {
warning("TODO: Monster 53's HP is altered here?!");
}
}
combat.moveMonsters();
setIndoorsMonsters();
party.changeTime(1);
}
if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1
&& combat._attackMonsters[2] == -1) {
party.changeTime(1);
draw3d(true);
if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1
&& combat._attackMonsters[2] == -1)
break;
}
party.checkPartyDead();
if (party._dead || _vm->_mode != MODE_COMBAT)
break;
}
_vm->_mode = MODE_1;
if (combat._partyRan && (combat._attackMonsters[0] != -1 ||
combat._attackMonsters[1] != -1 || combat._attackMonsters[2] != -1)) {
party.checkPartyDead();
if (!party._dead) {
party.moveToRunLocation();
for (uint idx = 0; idx < combat._combatParty.size(); ++idx) {
Character &c = *combat._combatParty[idx];
if (c.isDisabled())
c._conditions[DEAD] = 1;
}
}
}
w.close();
events.clearEvents();
_vm->_mode = MODE_COMBAT;
draw3d(true);
combat.giveTreasure();
_vm->_mode = MODE_1;
party._stepped = true;
unhighlightChar();
combat.setupCombatParty();
drawParty(true);
}
_iconSprites.load("main.icn");
for (int idx = 1; idx < 16; ++idx)
_mainList[idx]._sprites = &_iconSprites;
setMainButtons();
mainIconsPrint();
combat._monster2Attack = -1;
if (upDoorText) {
map.cellFlagLookup(party._mazePosition);
if (map._currentIsEvent)
scripts.checkEvents();
}
if (reloadMap) {
sound.playFX(51);
map._loadDarkSide = _vm->getGameID() != GType_WorldOfXeen;
map.load(_vm->getGameID() == GType_WorldOfXeen ? 28 : 29);
party._mazeDirection = _vm->getGameID() == GType_WorldOfXeen ?
DIR_EAST : DIR_SOUTH;
}
combat._combatMode = 1;
}
/**
* Select next character or monster to be attacking
*/
void Interface::nextChar() {
Combat &combat = *_vm->_combat;
Party &party = *_vm->_party;
if (combat.allHaveGone())
return;
if ((combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1 &&
combat._attackMonsters[2] == -1) || combat._combatParty.size() == 0) {
_vm->_mode = MODE_1;
return;
}
for (;;) {
// Check if party is dead
party.checkPartyDead();
if (party._dead) {
_vm->_mode = MODE_1;
break;
}
if (combat._whosTurn < (int)combat._combatParty.size()) {
if (!combat.allHaveGone())
highlightChar(combat._whosTurn);
break;
} else {
combat.attackMonster(0);
if (!party._dead)
party.checkPartyDead();
if (party._dead)
break;
}
// Check the combat participants
bool resetFlag = false;
for (uint idx = 0; idx < combat._speedTable.size(); ++idx) {
// Mark the given character as haven taken their turn
if (combat._whosTurn != -1) {
combat._charsGone[combat._whosTurn] = true;
}
combat._whosSpeed %= combat._speedTable.size();
combat._whosTurn = combat._speedTable[combat._whosSpeed];
if (combat.allHaveGone()) {
if (combat.charsCantAct()) {
combat.setSpeedTable();
combat._whosTurn = -1;
combat._whosSpeed = -1;
combat._charsGone.resize(combat._speedTable.size());
Common::fill(&combat._charsGone[0], &combat._charsGone[combat._charsGone.size()], 0);
resetFlag = true;
break;
}
return;
} else if (combat._whosTurn >= (int)combat._combatParty.size() ||
!combat._combatParty[combat._whosTurn]->isDisabledOrDead()) {
break;
}
}
if (party._dead)
break;
}
}
} // End of namespace Xeen

View file

@ -54,6 +54,8 @@ public:
void highlightChar(int charId);
void unhighlightChar();
void resetHighlight();
};
/**
@ -103,6 +105,8 @@ private:
void shake(int time);
void drawMiniMap();
void nextChar();
public:
int _intrIndex1;
Common::String _interfaceText;

View file

@ -67,7 +67,7 @@ MonsterStruct::MonsterStruct() {
_imageNumber = 0;
_loopAnimation = 0;
_animationEffect = 0;
_field32 = 0;
_fx = 0;
}
MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int accuracy,
@ -78,7 +78,7 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac
int poisonResistence, int energyResistence, int magicResistence,
int phsyicalResistence, int field29, int gold, int gems, int itemDrop,
bool flying, int imageNumber, int loopAnimation, int animationEffect,
int field32, Common::String attackVoc):
int fx, Common::String attackVoc):
_name(name), _experience(experience), _hp(hp), _accuracy(accuracy),
_speed(speed), _numberOfAttacks(numberOfAttacks), _hatesClass(hatesClass),
_strikes(strikes), _dmgPerStrike(dmgPerStrike), _attackType(attackType),
@ -89,10 +89,9 @@ MonsterStruct::MonsterStruct(Common::String name, int experience, int hp, int ac
_magicResistence(magicResistence), _phsyicalResistence(phsyicalResistence),
_field29(field29), _gold(gold), _gems(gems), _itemDrop(itemDrop),
_flying(flying), _imageNumber(imageNumber), _loopAnimation(loopAnimation),
_animationEffect(animationEffect), _field32(field32), _attackVoc(attackVoc) {
_animationEffect(animationEffect), _fx(fx), _attackVoc(attackVoc) {
}
void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
char name[16];
s.read(name, 16);
@ -127,7 +126,7 @@ void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
_imageNumber = s.readByte();
_loopAnimation = s.readByte();
_animationEffect = s.readByte();
_field32 = s.readByte();
_fx = s.readByte();
char attackVoc[10];
s.read(attackVoc, 9);

View file

@ -77,7 +77,7 @@ public:
int _imageNumber;
int _loopAnimation;
int _animationEffect;
int _field32;
int _fx;
Common::String _attackVoc;
public:
MonsterStruct();

View file

@ -12,9 +12,11 @@ MODULE_OBJS := \
automap.o \
dialogs_automap.o \
dialogs_char_info.o \
dialogs_control_panel.o \
dialogs_dismiss.o \
dialogs_error.o \
dialogs_exchange.o \
dialogs_fight_options.o \
dialogs_options.o \
dialogs_info.o \
dialogs_input.o \

View file

@ -545,4 +545,11 @@ void Party::checkPartyDead() {
_dead = true;
}
/**
* Move party position to the run destination on the current map
*/
void Party::moveToRunLocation() {
_mazePosition = _vm->_map->mazeData()._runPosition;
}
} // End of namespace Xeen

View file

@ -150,6 +150,8 @@ public:
void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
void checkPartyDead();
void moveToRunLocation();
};
} // End of namespace Xeen

View file

@ -1496,4 +1496,6 @@ const int NEW_CHARACTER_SPELLS[10][4] = {
{ 20, 1, -1, -1 }
};
const char *const COMBAT_DETAILS = "\r\f00\x03c\v000\t000\x02Combat%s%s%s\x1";
} // End of namespace Xeen

View file

@ -522,6 +522,8 @@ extern const int RACE_ENERGY_RESISTENCES[5];
extern const int RACE_POISON_RESISTENCES[5];
extern const int NEW_CHARACTER_SPELLS[10][4];
extern const char *const COMBAT_DETAILS;
} // End of namespace Xeen
#endif /* XEEN_RESOURCES_H */

View file

@ -378,7 +378,7 @@ void Scripts::cmdTeleport(Common::Array<byte> &params) {
}
if (pt.x == 999) {
party._mazePosition = map.mazeData()._runPosition;
party.moveToRunLocation();
} else {
party._mazePosition = pt;
}