2014-02-18 02:39:35 +01:00

259 lines
5.8 KiB
C++

/* 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 "lastexpress/fight/fighter.h"
#include "lastexpress/data/sequence.h"
#include "lastexpress/game/scenes.h"
#include "lastexpress/sound/sound.h"
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
namespace LastExpress {
Fighter::Fighter(LastExpressEngine *engine) : _engine(engine) {
_opponent = NULL;
_fight = NULL;
_sequenceIndex = 0;
_sequence = NULL;
_frame = NULL;
_frameIndex = 0;
_field_24 = 0;
_action = kFightAction101;
_sequenceIndex2 = 0;
_countdown = 1;
_field_34 = 0;
}
Fighter::~Fighter() {
// The original game resets the function pointers to default values, just before deleting the struct
getScenes()->removeAndRedraw(&_frame, false);
// Free sequences
for (uint i = 0; i < _sequences.size(); i++)
SAFE_DELETE(_sequences[i]);
// Zero-out passed pointers
_sequence = NULL;
_opponent = NULL;
_fight = NULL;
_engine = NULL;
}
//////////////////////////////////////////////////////////////////////////
// Drawing
//////////////////////////////////////////////////////////////////////////
void Fighter::setSequenceAndDraw(uint32 sequenceIndex, FightSequenceType type) {
if (_sequences.size() < sequenceIndex)
return;
switch (type) {
default:
break;
case kFightSequenceType0:
if (_sequenceIndex)
return;
_sequence = _sequences[sequenceIndex];
_sequenceIndex = sequenceIndex;
draw();
break;
case kFightSequenceType1:
_sequence = _sequences[sequenceIndex];
_sequenceIndex = sequenceIndex;
_sequenceIndex2 = 0;
draw();
break;
case kFightSequenceType2:
_sequenceIndex2 = sequenceIndex;
break;
}
}
void Fighter::draw() {
getScenes()->removeAndRedraw(&_frame, false);
_frameIndex = 0;
_field_24 = 0;
}
//////////////////////////////////////////////////////////////////////////
// Processing
//////////////////////////////////////////////////////////////////////////
void Fighter::process() {
if (!_fight)
error("[Fighter::handleAction] Fighter not initialized properly");
if (!_sequence) {
if (_frame) {
getScenes()->removeFromQueue(_frame);
getScenes()->setCoordinates(_frame);
}
SAFE_DELETE(_frame);
return;
}
if (_sequence->count() <= _frameIndex) {
switch(_action) {
default:
break;
case kFightAction101:
setSequenceAndDraw(_sequenceIndex2, kFightSequenceType1);
_sequenceIndex2 = 0;
break;
case kFightActionResetFrame:
_frameIndex = 0;
break;
case kFightAction103:
setSequenceAndDraw(0, kFightSequenceType1);
handleAction(kFightAction101);
_opponent->setSequenceAndDraw(0, kFightSequenceType1);
_opponent->handleAction(kFightAction101);
_opponent->update();
break;
case kFightActionWin:
_fight->bailout(Fight::kFightEndWin);
break;
case kFightActionLost:
_fight->bailout(Fight::kFightEndLost);
break;
}
}
if (_fight->isRunning()) {
// Get the current sequence frame
SequenceFrame *frame = new SequenceFrame(_sequence, (uint16)_frameIndex);
frame->getInfo()->location = 1;
if (_frame == frame) {
delete frame;
return;
}
getSound()->playFightSound(frame->getInfo()->soundAction, frame->getInfo()->field_31);
// Add current frame to queue and advance
getScenes()->addToQueue(frame);
_frameIndex++;
if (_frame) {
getScenes()->removeFromQueue(_frame);
if (!frame->getInfo()->field_2E)
getScenes()->setCoordinates(_frame);
}
// Replace by new frame
delete _frame;
_frame = frame;
}
}
//////////////////////////////////////////////////////////////////////////
// Default actions
//////////////////////////////////////////////////////////////////////////
void Fighter::handleAction(FightAction action) {
if (!_opponent || !_fight)
error("[Fighter::handleAction] Fighter not initialized properly");
switch (action) {
default:
return;
case kFightAction101:
break;
case kFightActionResetFrame:
_countdown--;
break;
case kFightAction103:
_opponent->handleAction(kFightActionResetFrame);
break;
case kFightActionWin:
_fight->setEndType(Fight::kFightEndWin);
_opponent->handleAction(kFightActionResetFrame);
break;
case kFightActionLost:
_fight->setEndType(Fight::kFightEndLost);
_opponent->handleAction(kFightActionResetFrame);
break;
}
// Update action
_action = action;
}
bool Fighter::canInteract(FightAction /*action = kFightActionNone*/ ) {
return (_action == kFightAction101 && !_sequenceIndex);
}
void Fighter::update() {
process();
if (_frame)
_frame->getInfo()->location = (_action == kFightActionResetFrame ? 2 : 0);
}
void Opponent::update() {
process();
if (_field_38 && !_sequenceIndex)
_field_38--;
if (_frame)
_frame->getInfo()->location = 1;
}
//////////////////////////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////////////////////////
bool Fighter::checkFrame(uint32 val) {
if (!_frame)
error("[Fighter::checkFrame] Invalid current frame");
return (bool)(_frame->getInfo()->field_33 & val);
}
} // End of namespace LastExpress