Initial commit
This commit is contained in:
398
engines/lastexpress/fight/fight.cpp
Normal file
398
engines/lastexpress/fight/fight.cpp
Normal file
@@ -0,0 +1,398 @@
|
||||
/* 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 "lastexpress/fight/fight.h"
|
||||
#include "lastexpress/fight/fighter.h"
|
||||
|
||||
#include "lastexpress/lastexpress.h"
|
||||
|
||||
namespace LastExpress {
|
||||
|
||||
int LastExpressEngine::doFight(int fightId) {
|
||||
int fightNode;
|
||||
TBM *tbm;
|
||||
|
||||
if (_fightSkipCounter >= 5 && (fightId == 2004 || fightId == 2005)) {
|
||||
_fightSkipCounter = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
getLogicManager()->displayWaitIcon();
|
||||
getMessageManager()->clearClickEvents();
|
||||
|
||||
getLogicManager()->_doubleClickFlag = false;
|
||||
mouseSetLeftClicked(false);
|
||||
mouseSetRightClicked(false);
|
||||
|
||||
getOtisManager()->wipeAllGSysInfo();
|
||||
|
||||
switch (fightId) {
|
||||
case 2001:
|
||||
fightNode = 44 - (getLogicManager()->getModel(1) == 2);
|
||||
break;
|
||||
case 2002:
|
||||
fightNode = 45;
|
||||
break;
|
||||
case 2003:
|
||||
fightNode = 46;
|
||||
break;
|
||||
case 2004:
|
||||
fightNode = 47;
|
||||
break;
|
||||
case 2005:
|
||||
fightNode = 48;
|
||||
break;
|
||||
default:
|
||||
fightNode = 820;
|
||||
break;
|
||||
}
|
||||
|
||||
if (getGraphicsManager()->canDrawMouse()) {
|
||||
getGraphicsManager()->setMouseDrawable(false);
|
||||
getGraphicsManager()->burstMouseArea();
|
||||
}
|
||||
|
||||
char sceneName[12];
|
||||
Common::strcpy_s(sceneName, getLogicManager()->_trainData[fightNode].sceneFilename);
|
||||
|
||||
int bgResult = getArchiveManager()->loadBG(sceneName);
|
||||
if (bgResult <= 0) {
|
||||
if (bgResult)
|
||||
return 1;
|
||||
|
||||
tbm = &getGraphicsManager()->_renderBox1;
|
||||
} else {
|
||||
tbm = &getGraphicsManager()->_renderBox2;
|
||||
}
|
||||
|
||||
getLogicManager()->_activeNode = fightNode;
|
||||
|
||||
(_characters->characters[kCharacterCath]).characterPosition = getLogicManager()->_trainData[fightNode].nodePosition;
|
||||
getSoundManager()->_scanAnySoundLoopingSection = true;
|
||||
|
||||
if (getGraphicsManager()->acquireSurface()) {
|
||||
getGraphicsManager()->copy(getGraphicsManager()->_frontBuffer, (PixMap *)getGraphicsManager()->_screenSurface.getPixels(), tbm->x, tbm->y, tbm->width, tbm->height);
|
||||
getGraphicsManager()->unlockSurface();
|
||||
}
|
||||
|
||||
getMemoryManager()->freeFX();
|
||||
|
||||
_fight = new CFight(this, fightId);
|
||||
|
||||
_fight->timer(0, 0);
|
||||
|
||||
getGraphicsManager()->burstBox(tbm->x, tbm->y, tbm->width, tbm->height);
|
||||
getLogicManager()->restoreEggIcon();
|
||||
|
||||
int outcome = _fight->process();
|
||||
|
||||
delete _fight;
|
||||
_fight = nullptr;
|
||||
|
||||
getMemoryManager()->lockFX();
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
void LastExpressEngine::abortFight() {
|
||||
if (_fight)
|
||||
_fight->setFightHappening(false);
|
||||
}
|
||||
|
||||
CFight::CFight(LastExpressEngine *engine, int fightId) {
|
||||
_engine = engine;
|
||||
|
||||
_currentSeqIdx = 0;
|
||||
|
||||
switch (fightId) {
|
||||
case 2001: // Cath vs Milos
|
||||
_cath = new CCath1(_engine, this);
|
||||
_opponent = new COpponent1(_engine, this);
|
||||
break;
|
||||
case 2002: // Cath vs Vesna (when saving Anna)
|
||||
_cath = new CCath2(_engine, this);
|
||||
_opponent = new COpponent2(_engine, this);
|
||||
break;
|
||||
case 2003: // Cath vs Ivo
|
||||
_cath = new CCath3(_engine, this);
|
||||
_opponent = new COpponent3(_engine, this);
|
||||
break;
|
||||
case 2004: // Cath vs Salko
|
||||
_cath = new CCath4(_engine, this);
|
||||
_opponent = new COpponent4(_engine, this);
|
||||
break;
|
||||
case 2005: // Cath vs Vesna (final fight)
|
||||
_cath = new CCath5(_engine, this);
|
||||
_opponent = new COpponent5(_engine, this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_cath || !_opponent) {
|
||||
error("Out of memory");
|
||||
}
|
||||
|
||||
if (_cath->init(_opponent) && _opponent->init(_cath)) {
|
||||
_fightIsHappening = true;
|
||||
if (_engine->_fightSkipCounter >= 5) {
|
||||
switch (fightId) {
|
||||
case 2001:
|
||||
_opponent->setHitPoints(1);
|
||||
_cath->doAction(4, 0);
|
||||
_opponent->doAction(0, 0);
|
||||
break;
|
||||
case 2003:
|
||||
_opponent->setHitPoints(1);
|
||||
_cath->doAction(3, 0);
|
||||
_opponent->doAction(6, 0);
|
||||
break;
|
||||
case 2005:
|
||||
_opponent->setHitPoints(1);
|
||||
_cath->doAction(0, 0);
|
||||
_cath->doAction(3, 2);
|
||||
_opponent->doAction(5, 0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
_cath->doAction(0, 0);
|
||||
_opponent->doAction(0, 0);
|
||||
}
|
||||
} else {
|
||||
endFight(0);
|
||||
}
|
||||
|
||||
_savedMouseEventHandle = _engine->getMessageManager()->getEventHandle(1);
|
||||
_savedTimerEventHandle = _engine->getMessageManager()->getEventHandle(3);
|
||||
|
||||
_engine->getMessageManager()->setEventHandle(kEventChannelMouse, &LastExpressEngine::fightMouseWrapper);
|
||||
_engine->getMessageManager()->setEventHandle(kEventChannelTimer, &LastExpressEngine::fightTimerWrapper);
|
||||
|
||||
_engine->setEventTickInternal(false);
|
||||
}
|
||||
|
||||
CFight::~CFight() {
|
||||
if (_cath) {
|
||||
delete _cath;
|
||||
_cath = nullptr;
|
||||
}
|
||||
|
||||
if (_opponent) {
|
||||
delete _opponent;
|
||||
_opponent = nullptr;
|
||||
}
|
||||
|
||||
_engine->getMessageManager()->setEventHandle(kEventChannelMouse, _savedMouseEventHandle);
|
||||
_engine->getMessageManager()->setEventHandle(kEventChannelTimer, _savedTimerEventHandle);
|
||||
}
|
||||
|
||||
int CFight::process() {
|
||||
setOutcome(1);
|
||||
|
||||
while (_fightIsHappening) {
|
||||
do {
|
||||
_engine->getSoundManager()->soundThread();
|
||||
} while (_engine->getMessageManager()->process());
|
||||
|
||||
// Only wait and handle events if we've processed all messages, unlike the original which had a separate thread for input...
|
||||
_engine->waitForTimer(5);
|
||||
}
|
||||
|
||||
return _outcome;
|
||||
}
|
||||
|
||||
void CFight::setOutcome(int outcome) {
|
||||
_outcome = outcome;
|
||||
}
|
||||
|
||||
void CFight::endFight(int outcome) {
|
||||
_engine->_fightSkipCounter = 0;
|
||||
setOutcome(outcome);
|
||||
_engine->abortFight();
|
||||
}
|
||||
|
||||
void CFight::timer(Event *event, bool isProcessing) {
|
||||
_engine->setEventTickInternal(false);
|
||||
|
||||
if (_engine->_gracePeriodTimer) {
|
||||
if ((_engine->getLogicManager()->_globals[kGlobalJacket] < 2 ? 225 : 450) == _engine->_gracePeriodTimer || _engine->_gracePeriodTimer == 900) {
|
||||
_eggIconBrightness = 0;
|
||||
_eggIconBrightnessStep = 1;
|
||||
}
|
||||
|
||||
if (!_engine->_lockGracePeriod) // Gets set to true only by the debugger only...
|
||||
_engine->_gracePeriodTimer--;
|
||||
|
||||
if (_engine->_gracePeriodTimer <= 500 ||
|
||||
!(_engine->_gracePeriodTimer % 5)) {
|
||||
|
||||
if ((_engine->_gracePeriodTimer <= 500 && !(_engine->_gracePeriodTimer % ((_engine->_gracePeriodTimer + 100) / 100))) ||
|
||||
(_engine->_gracePeriodTimer > 500 && !(_engine->_gracePeriodTimer % 5))) {
|
||||
if (_eggIconBrightness) {
|
||||
_engine->getGraphicsManager()->drawItemDim(_engine->_currentGameFileColorId + 39, 608, 448, _eggIconBrightness);
|
||||
} else {
|
||||
_engine->getGraphicsManager()->drawItem(_engine->_currentGameFileColorId + 39, 608, 448);
|
||||
}
|
||||
|
||||
_engine->getGraphicsManager()->burstBox(608, 448, 32, 32);
|
||||
_eggIconBrightness += _eggIconBrightnessStep;
|
||||
|
||||
if (!_eggIconBrightness || _eggIconBrightness == 3)
|
||||
_eggIconBrightnessStep = -_eggIconBrightnessStep;
|
||||
}
|
||||
}
|
||||
|
||||
if (_engine->_gracePeriodTimer == 90) {
|
||||
_engine->getSoundManager()->playSoundFile("TIMER.SND", kSoundTypeMenu | kVolumeFull, 0, 0);
|
||||
}
|
||||
|
||||
if (_engine->_gracePeriodTimer < 90 && !_engine->getLogicManager()->dialogRunning("TIMER"))
|
||||
_engine->_gracePeriodTimer = 0;
|
||||
|
||||
if (!_engine->_gracePeriodTimer) {
|
||||
if (_engine->_cursorX < 608 || _engine->_cursorY < 448 || _engine->_cursorX >= 640 || _engine->_cursorY >= 480) {
|
||||
_engine->getGraphicsManager()->drawItemDim(_engine->_currentGameFileColorId + 39, 608, 448, 1);
|
||||
} else {
|
||||
_engine->getGraphicsManager()->drawItem(_engine->_currentGameFileColorId + 39, 608, 448);
|
||||
}
|
||||
|
||||
_engine->getGraphicsManager()->burstBox(608, 448, 32, 32);
|
||||
_engine->getVCR()->makePermanent();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_currentSeqIdx) {
|
||||
Link *link = nullptr;
|
||||
uint8 location = 0;
|
||||
|
||||
for (Link *i = _engine->getLogicManager()->_trainData[_engine->getLogicManager()->_activeNode].link; i; i = i->next) {
|
||||
if (_engine->getLogicManager()->pointIn(_engine->_cursorX, _engine->_cursorY, i) && location <= i->location) {
|
||||
location = i->location;
|
||||
link = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!link || (_engine->_cursorType = link->cursor, !_cath->actionAvailable(link->action)))
|
||||
_engine->_cursorType = 0;
|
||||
|
||||
_cath->timer();
|
||||
_opponent->timer();
|
||||
|
||||
if (_fightIsHappening) {
|
||||
if (isProcessing) {
|
||||
_engine->getSpriteManager()->drawCycle();
|
||||
} else if (_engine->getGraphicsManager()->acquireSurface()) {
|
||||
_engine->getSpriteManager()->drawCycleSimple((PixMap *)_engine->getGraphicsManager()->_screenSurface.getPixels());
|
||||
_engine->getGraphicsManager()->unlockSurface();
|
||||
}
|
||||
|
||||
if (_currentSeqIdx) {
|
||||
_currentSeqIdx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CFight::mouse(Event *event) {
|
||||
if (_currentSeqIdx == 0) {
|
||||
_engine->mouseSetLeftClicked(false);
|
||||
_engine->getGraphicsManager()->setMouseDrawable(false);
|
||||
_engine->mouseSetRightClicked(false);
|
||||
|
||||
_engine->getGraphicsManager()->burstMouseArea(false); // The original updated the screen, we don't to avoid flickering...
|
||||
|
||||
_engine->_cursorX = event->x;
|
||||
_engine->_cursorY = event->y;
|
||||
|
||||
if (_engine->_cursorX < 608 || _engine->_cursorY < 448 || _engine->_cursorX >= 640 || _engine->_cursorY >= 480) {
|
||||
if ((event->flags & kMouseFlagRightDown) != 0) {
|
||||
_engine->getLogicManager()->endDialog(kCharacterTableA);
|
||||
_engine->abortFight();
|
||||
|
||||
if (_engine->_gracePeriodTimer) {
|
||||
_engine->_fightSkipCounter = 0;
|
||||
} else {
|
||||
_engine->_fightSkipCounter++;
|
||||
}
|
||||
|
||||
_engine->mouseSetRightClicked(true);
|
||||
}
|
||||
|
||||
if (_lowIconToggle) {
|
||||
if (!_engine->_gracePeriodTimer) {
|
||||
_engine->getGraphicsManager()->drawItemDim(_engine->_currentGameFileColorId + 39, 608, 448, 1);
|
||||
_engine->getGraphicsManager()->burstBox(608, 448, 32, 32);
|
||||
}
|
||||
|
||||
_lowIconToggle = false;
|
||||
}
|
||||
|
||||
uint8 location = 0;
|
||||
Link *link = nullptr;
|
||||
|
||||
for (Link *i = _engine->getLogicManager()->_trainData[_engine->getLogicManager()->_activeNode].link; i; i = i->next) {
|
||||
if (_engine->getLogicManager()->pointIn(_engine->_cursorX, _engine->_cursorY, i) && location <= i->location) {
|
||||
location = i->location;
|
||||
link = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (link) {
|
||||
_engine->_cursorType = link->cursor;
|
||||
|
||||
if (_cath->actionAvailable(link->action)) {
|
||||
if ((event->flags & kMouseFlagLeftDown) != 0)
|
||||
_cath->send(link->action);
|
||||
} else {
|
||||
_engine->_cursorType = 0;
|
||||
}
|
||||
} else {
|
||||
_engine->_cursorType = 0;
|
||||
}
|
||||
} else {
|
||||
if (!_lowIconToggle) {
|
||||
if (!_engine->_gracePeriodTimer) {
|
||||
_engine->getGraphicsManager()->drawItem(_engine->_currentGameFileColorId + 39, 608, 448);
|
||||
_engine->getGraphicsManager()->burstBox(608, 448, 32, 32);
|
||||
}
|
||||
|
||||
_lowIconToggle = true;
|
||||
}
|
||||
|
||||
if ((event->flags & kMouseFlagLeftDown) != 0) {
|
||||
_lowIconToggle = false;
|
||||
_engine->getLogicManager()->endDialog(kCharacterTableA);
|
||||
endFight(2);
|
||||
} else if ((event->flags & kMouseFlagRightDown) != 0 && _engine->_gracePeriodTimer) {
|
||||
if (_engine->getLogicManager()->dialogRunning("TIMER"))
|
||||
_engine->getLogicManager()->endDialog("TIMER");
|
||||
|
||||
_engine->_gracePeriodTimer = 900;
|
||||
}
|
||||
}
|
||||
|
||||
_engine->getGraphicsManager()->setMouseDrawable(true);
|
||||
_engine->getGraphicsManager()->newMouseLoc();
|
||||
_engine->getGraphicsManager()->burstMouseArea();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace LastExpress
|
||||
Reference in New Issue
Block a user