XEEN: Implementing more combat logic
This commit is contained in:
parent
30d94950be
commit
c045adae76
18 changed files with 755 additions and 16 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -270,6 +270,10 @@ public:
|
|||
|
||||
Condition worstCondition() const;
|
||||
|
||||
bool isDisabled() const;
|
||||
|
||||
bool isDisabledOrDead() const;
|
||||
|
||||
int getAge(bool ignoreTemp = false) const;
|
||||
|
||||
int getMaxHP() const;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
42
engines/xeen/dialogs_control_panel.cpp
Normal file
42
engines/xeen/dialogs_control_panel.cpp
Normal 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
|
43
engines/xeen/dialogs_control_panel.h
Normal file
43
engines/xeen/dialogs_control_panel.h
Normal 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 */
|
39
engines/xeen/dialogs_fight_options.cpp
Normal file
39
engines/xeen/dialogs_fight_options.cpp
Normal 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
|
43
engines/xeen/dialogs_fight_options.h
Normal file
43
engines/xeen/dialogs_fight_options.h
Normal 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 */
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
int _imageNumber;
|
||||
int _loopAnimation;
|
||||
int _animationEffect;
|
||||
int _field32;
|
||||
int _fx;
|
||||
Common::String _attackVoc;
|
||||
public:
|
||||
MonsterStruct();
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -150,6 +150,8 @@ public:
|
|||
void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
|
||||
|
||||
void checkPartyDead();
|
||||
|
||||
void moveToRunLocation();
|
||||
};
|
||||
|
||||
} // End of namespace Xeen
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -378,7 +378,7 @@ void Scripts::cmdTeleport(Common::Array<byte> ¶ms) {
|
|||
}
|
||||
|
||||
if (pt.x == 999) {
|
||||
party._mazePosition = map.mazeData()._runPosition;
|
||||
party.moveToRunLocation();
|
||||
} else {
|
||||
party._mazePosition = pt;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue