scummvm/engines/fullpipe/statics.cpp
2013-09-06 14:51:08 +03:00

750 lines
16 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 "fullpipe/fullpipe.h"
#include "fullpipe/objects.h"
#include "fullpipe/ngiarchive.h"
#include "fullpipe/statics.h"
#include "fullpipe/messages.h"
#include "fullpipe/gameobj.h"
#include "fullpipe/objectnames.h"
namespace Fullpipe {
CStepArray::CStepArray() {
_points = 0;
_maxPointIndex = 0;
_currPointIndex = 0;
_pointsCount = 0;
_isEos = 0;
}
CStepArray::~CStepArray() {
if (_pointsCount) {
for (int i = 0; i < _pointsCount; i++)
delete _points[i];
delete _points;
_points = 0;
}
}
void CStepArray::clear() {
_currPointIndex = 0;
_maxPointIndex = 0;
_isEos = 0;
for (int i = 0; i < _pointsCount; i++) {
_points[i]->x = 0;
_points[i]->y = 0;
}
}
StaticANIObject::StaticANIObject() {
_shadowsOn = 1;
_field_30 = 0;
_field_34 = 1;
_initialCounter = 0;
_messageQueueId = 0;
_animExFlag = 0;
_counter = 0;
_movement = 0;
_statics = 0;
_flags = 0;
_callback1 = 0;
_callback2 = 0;
_sceneId = -1;
_someDynamicPhaseIndex = -1;
}
bool StaticANIObject::load(MfcArchive &file) {
debug(5, "StaticANIObject::load()");
GameObject::load(file);
int count = file.readUint16LE();
for (int i = 0; i < count; i++) {
Statics *st = new Statics();
st->load(file);
_staticsList.push_back(st);
}
count = file.readUint16LE();
debug(7, "Movements: %d", count);
for (int i = 0; i < count; i++) {
int movNum = file.readUint16LE();
char *movname = genFileName(_id, movNum, "mov");
Common::SeekableReadStream *f = g_fullpipe->_currArchive->createReadStreamForMember(movname);
Movement *mov = new Movement();
MfcArchive archive(f);
mov->load(archive, this);
_movements.push_back(mov);
delete f;
free(movname);
}
Common::Point pt;
if (count) { // We have movements
((Movement *)_movements[0])->getCurrDynamicPhaseXY(pt);
} else {
pt.x = pt.y = 100;
}
setOXY(pt.x, pt.y);
return true;
}
void StaticANIObject::setOXY(int x, int y) {
_ox = x;
_oy = y;
if (_movement)
_movement->setOXY(x, y);
}
void StaticANIObject::clearFlags() {
_flags = 0;
deleteFromGlobalMessageQueue();
_messageQueueId = 0;
_movement = 0;
_statics = 0;
_animExFlag = 0;
_counter = 0;
_messageNum = 0;
_stepArray.clear();
}
void StaticANIObject::deleteFromGlobalMessageQueue() {
while (_messageQueueId) {
if (g_fullpipe->_globalMessageQueueList->getMessageQueueById(_messageQueueId)) {
if (!isIdle())
return;
g_fullpipe->_globalMessageQueueList->deleteQueueById(_messageQueueId);
} else {
_messageQueueId = 0;
}
}
}
bool StaticANIObject::isIdle() {
if (_messageQueueId) {
MessageQueue *m = g_fullpipe->_globalMessageQueueList->getMessageQueueById(_messageQueueId);
if (m && m->getFlags() & 1)
return false;
}
return true;
}
Statics *StaticANIObject::getStaticsById(int itemId) {
for (uint i = 0; i < _staticsList.size(); i++)
if (((Statics *)_staticsList[i])->_staticsId == itemId)
return (Statics *)_staticsList[i];
return 0;
}
Movement *StaticANIObject::getMovementById(int itemId) {
for (uint i = 0; i < _movements.size(); i++)
if (((Movement *)_movements[i])->_id == itemId)
return (Movement *)_movements[i];
return 0;
}
Movement *StaticANIObject::getMovementByName(char *name) {
for (uint i = 0; i < _movements.size(); i++)
if (!strcmp(((Movement *)_movements[i])->_objectName, name))
return (Movement *)_movements[i];
return 0;
}
void Movement::draw(bool flipFlag, int angle) {
warning("STUB: Movement::draw(%d, %d)", flipFlag, angle);
}
void StaticANIObject::loadMovementsPixelData() {
for (uint i = 0; i < _movements.size(); i++)
((Movement *)_movements[i])->loadPixelData();
}
Statics *StaticANIObject::addReverseStatics(Statics *st) {
Statics *res = getStaticsById(st->_staticsId ^ 0x4000);
if (!res) {
res = new Statics(st, true);
_staticsList.push_back(res);
}
return res;
}
void StaticANIObject::draw() {
if (_flags & 4 == 0)
return;
Common::Point point;
Common::Rect rect;
debug(0, "StaticANIObject::draw()");
if (_shadowsOn && g_fullpipe->_currentScene && g_fullpipe->_currentScene->_shadows
&& (getCurrDimensions(point)->x != 1 || getCurrDimensions(point)->y != 1)) {
DynamicPhase *dyn;
if (!_movement || _flags & 0x20 )
dyn = _statics;
else
dyn = _movement->_currDynamicPhase;
if (dyn->getDynFlags() & 4) {
rect = *dyn->_rect;
DynamicPhase *shd = g_fullpipe->_currentScene->_shadows->findSize(rect.width(), rect.height());
if (shd) {
shd->getDimensions(&point);
int midx = _ox - shd->_x / 2 - dyn->_someX;
int midy = _oy - shd->_y / 2 - dyn->_someY + rect.bottom - 3;
int shdy = shd->_y;
int px;
if (!_movement || _flags & 0x20 )
px = _statics->getCenter(&point)->x;
else
px = _movement->getCenter(&point)->x;
if (_shadowsOn != 1)
midy = _shadowsOn - shdy / 2;
shd->draw(px + midx, midy, 0, 0);
}
}
}
int angle = 0;
if (_field_30 & 0xC000) {
if (_field_30 & 0x8000)
angle = -(_field_30 ^ 0x8000);
else
angle = _field_30 ^ 0x4000;
}
if (!_movement || _flags & 0x20) {
_statics->getSomeXY(point);
_statics->_x = _ox - point.x;
_statics->_y = _oy - point.y;
_statics->draw(_statics->_x, _statics->_y, 0, angle);
} else {
_movement->draw(0, angle);
}
}
void StaticANIObject::draw2() {
debug(0, "StatciANIObject::draw2()");
if ((_flags & 4) && (_flags & 0x10)) {
if (_movement) {
_movement->draw(1, 0);
} else {
Common::Point point;
_statics->getSomeXY(point);
_statics->draw(_ox - point.x, _oy - point.y, 1, 0);
}
}
}
MovTable *StaticANIObject::countMovements() {
CGameVar *preloadSubVar = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(getName())->getSubVarByName("PRELOAD");
if (preloadSubVar || preloadSubVar->getSubVarsCount() == 0)
return 0;
MovTable *movTable = new MovTable;
movTable->count = _movements.size();
movTable->movs = (int16 *)calloc(_movements.size(), sizeof(int16));
for (uint i = 0; i < _movements.size(); i++) {
GameObject *obj = (GameObject *)_movements[i];
movTable->movs[i] = 2;
for (CGameVar *sub = preloadSubVar->_subVars; sub; sub = sub->_nextVarObj) {
if (scumm_stricmp(obj->getName(), sub->_varName) == 0) {
movTable->movs[i] = 1;
break;
}
}
}
return movTable;
}
void StaticANIObject::setSpeed(int speed) {
warning("STUB: StaticANIObject::setSpeed(%d)", speed);
}
void StaticANIObject::initMovements() {
for (uint i = 0; i < _movements.size(); i++)
((Movement *)_movements[i])->removeFirstPhase();
}
Common::Point *StaticANIObject::getCurrDimensions(Common::Point &p) {
Picture *pic;
if (_movement)
pic = _movement->_currDynamicPhase;
else
pic = _statics;
if (pic) {
Common::Point point;
pic->getDimensions(&point);
p.x = point.x;
p.y = point.y;
} else {
p.x = 0;
p.y = 0;
}
return &p;
}
Statics::Statics() {
_staticsId = 0;
_picture = 0;
_staticsName = 0;
}
Statics::Statics(Statics *src, bool reverse) : DynamicPhase(src, reverse) {
_staticsId = src->_staticsId;
if (reverse) {
_staticsId ^= 0x4000;
int newlen = strlen(src->_staticsName) + strlen(sO_MirroredTo) + 1;
_staticsName = (char *)calloc(newlen, 1);
snprintf(_staticsName, newlen, "%s%s", sO_MirroredTo, src->_staticsName);
} else {
_staticsName = (char *)calloc(strlen(src->_staticsName) + 1, 1);
strncpy(_staticsName, src->_staticsName, strlen(src->_staticsName) + 1);
}
_memfilename = (char *)calloc(strlen(src->_memfilename) + 1, 1);
strncpy(_memfilename, src->_memfilename, strlen(src->_memfilename) + 1);
_picture = new Picture();
}
bool Statics::load(MfcArchive &file) {
debug(5, "Statics::load()");
DynamicPhase::load(file);
_staticsId = file.readUint16LE();
_staticsName = file.readPascalString();
debug(7, "statics: <%s> id: %d (%x)", transCyrillic((byte *)_staticsName), _staticsId, _staticsId);
_picture = new Picture();
_picture->load(file);
return true;
}
Common::Point *Statics::getSomeXY(Common::Point &p) {
p.x = _someX;
p.y = _someY;
return &p;
}
Common::Point *Statics::getCenter(Common::Point *p) {
Common::Rect rect;
rect = *_rect;
if (_staticsId & 0x4000) {
Common::Point point;
getDimensions(&point);
rect.moveTo(point.x - _rect->right, _rect->top);
}
p->x = rect.left + _rect->width() / 2;
p->y = rect.top + _rect->height() / 2;
return p;
}
Movement::Movement() {
_lastFrameSpecialFlag = 0;
_flipFlag = 0;
_updateFlag1 = 0;
_staticsObj1 = 0;
_staticsObj2 = 0;
_mx = 0;
_my = 0;
_m2x = 0;
_m2y = 0;
_field_50 = 1;
_field_78 = 0;
_framePosOffsets = 0;
_field_84 = 0;
_currDynamicPhase = 0;
_field_8C = 0;
_currDynamicPhaseIndex = 0;
_field_94 = 0;
_currMovement = 0;
_counter = 0;
_counterMax = 83;
}
bool Movement::load(MfcArchive &file) {
warning("STUB: Movement::load");
return true;
}
bool Movement::load(MfcArchive &file, StaticANIObject *ani) {
GameObject::load(file);
int dynCount = file.readUint16LE();
debug(7, "dynCount: %d _id: %d", dynCount, _id);
if (dynCount != 0xffff || _id == MV_MAN_TURN_LU) {
_framePosOffsets = (Common::Point **)calloc(dynCount + 2, sizeof(Common::Point *));
for (int i = 0; i < dynCount + 2; i++)
_framePosOffsets[i] = new Common::Point();
for (int i = 0; i < dynCount; i++) {
DynamicPhase *ph = new DynamicPhase();
ph->load(file);
_dynamicPhases.push_back(ph);
_framePosOffsets[i]->x = ph->_x;
_framePosOffsets[i]->y = ph->_y;
}
int staticsid = file.readUint16LE();
_staticsObj1 = ani->getStaticsById(staticsid);
if (!_staticsObj1 && (staticsid & 0x4000)) {
Statics *s = ani->getStaticsById(staticsid ^ 0x4000);
_staticsObj1 = ani->addReverseStatics(s);
}
_mx = file.readUint32LE();
_my = file.readUint32LE();
staticsid = file.readUint16LE();
_staticsObj2 = ani->getStaticsById(staticsid);
if (!_staticsObj2 && (staticsid & 0x4000)) {
Statics *s = ani->getStaticsById(staticsid ^ 0x4000);
_staticsObj2 = ani->addReverseStatics(s);
}
_m2x = file.readUint32LE();
_m2y = file.readUint32LE();
if (_staticsObj2) {
_dynamicPhases.push_back(_staticsObj2);
_framePosOffsets[_dynamicPhases.size() - 1]->x = _m2x;
_framePosOffsets[_dynamicPhases.size() - 1]->y = _m2y;
}
} else {
int movid = file.readUint16LE();
_currMovement = ani->getMovementById(movid);
_staticsObj1 = 0;
_staticsObj2 = 0;
initStatics(ani);
}
if (_staticsObj1 && _staticsObj2) {
if ((_staticsObj1->_staticsId ^ _staticsObj2->_staticsId) & 0x4000)
_flipFlag = 1;
}
if (g_fullpipe->_gameProjectVersion >= 8)
_field_50 = file.readUint32LE();
if (g_fullpipe->_gameProjectVersion < 12)
_counterMax = 83;
else
_counterMax = file.readUint32LE();
_counter = 0;
updateCurrDynamicPhase();
return true;
}
Common::Point *Movement::getCurrDynamicPhaseXY(Common::Point &p) {
p.x = _currDynamicPhase->_x;
p.y = _currDynamicPhase->_y;
return &p;
}
Common::Point *Movement::getDimensionsOfPhase(Common::Point *p, int phaseIndex) {
int idx = phaseIndex;
if (idx == -1)
idx = _currDynamicPhaseIndex;
DynamicPhase *dyn;
if (_currMovement)
dyn = (DynamicPhase *)_currMovement->_dynamicPhases[idx];
else
dyn = (DynamicPhase *)_dynamicPhases[idx];
Common::Point point;
dyn->getDimensions(&point);
*p = point;
return p;
}
void Movement::initStatics(StaticANIObject *ani) {
warning("STUB: Movement::initStatics");
}
void Movement::updateCurrDynamicPhase() {
if (_dynamicPhases.size() == 0)
return;
if (_dynamicPhases[_currDynamicPhaseIndex]) {
_currDynamicPhase = (DynamicPhase *)_dynamicPhases[_currDynamicPhaseIndex];
}
}
void Movement::loadPixelData() {
Movement *mov = this;
for (Movement *i = _currMovement; i; i = i->_currMovement)
mov = i;
for (uint i = 0; i < _dynamicPhases.size(); i++) {
if ((Statics *)_dynamicPhases[i] != mov->_staticsObj2 || !(mov->_staticsObj2->_staticsId & 0x4000) )
((Statics *)_dynamicPhases[i])->getPixelData();
}
if (!(mov->_staticsObj1->_staticsId & 0x4000))
mov->_staticsObj1->getPixelData();
}
void Movement::removeFirstPhase() {
if (_updateFlag1) {
if (!_currDynamicPhaseIndex)
gotoNextFrame(0, 0);
if (!_currMovement) {
_dynamicPhases.remove_at(0);
for (uint i = 0; i < _dynamicPhases.size(); i++) {
_framePosOffsets[i - 1]->x = _framePosOffsets[i]->x;
_framePosOffsets[i - 1]->y = _framePosOffsets[i]->y;
}
}
_currDynamicPhaseIndex--;
}
updateCurrDynamicPhase();
_updateFlag1 = 0;
}
void Movement::gotoNextFrame(int callback1, int callback2) {
warning("STUB: Movement::gotoNextFrame()");
}
Common::Point *Movement::getCenter(Common::Point *p) {
Common::Rect rect;
rect = *_currDynamicPhase->_rect;
if (_currMovement) {
Common::Point point;
getDimensionsOfPhase(&point, _currDynamicPhaseIndex);
rect.moveTo(point.x - _currDynamicPhase->_rect->right, _currDynamicPhase->_rect->top);
}
p->x = rect.left + _currDynamicPhase->_rect->width() / 2;
p->y = rect.top + _currDynamicPhase->_rect->height() / 2;
return p;
}
DynamicPhase::DynamicPhase() {
_someX = 0;
_rect = 0;
_field_7C = 0;
_dynFlags = 0;
_someY = 0;
}
DynamicPhase::DynamicPhase(DynamicPhase *src, bool reverse) {
_field_7C = src->_field_7C;
_rect = new Common::Rect();
if (reverse) {
if (!src->_bitmap)
src->init();
_bitmap = src->_bitmap->reverseImage();
_data = _bitmap->_pixels;
_dataSize = src->_dataSize;
if (g_fullpipe->_currArchive) {
_field_14 = 0;
_libHandle = g_fullpipe->_currArchive;
}
_flags |= 1;
_someX = src->_someX;
_someY = src->_someY;
} else {
_field_14 = src->_field_14;
_field_8 = src->_field_8;
_flags = src->_flags;
_memfilename = (char *)calloc(strlen(src->_memfilename) + 1, 1);
strncpy(_memfilename, src->_memfilename, strlen(src->_memfilename) + 1);
_dataSize = src->_dataSize;
_field_10 = src->_field_10;
_libHandle = src->_libHandle;
_bitmap = src->_bitmap;
if (_bitmap)
_field_54 = 1;
_someX = src->_someX;
_someY = src->_someY;
}
*_rect = *src->_rect;
_width = src->_width;
_height = src->_height;
_field_7C = src->_field_7C;
if (src->getExCommand())
_exCommand = new ExCommand(src->getExCommand());
else
_exCommand = 0;
_initialCountdown = src->_initialCountdown;
_field_6A = src->_field_6A;
_dynFlags = src->_dynFlags;
setPaletteData(getPaletteData());
copyMemoryObject2(src);
}
bool DynamicPhase::load(MfcArchive &file) {
debug(5, "DynamicPhase::load()");
StaticPhase::load(file);
_field_7C = file.readUint16LE();
_rect = new Common::Rect();
_rect->left = file.readUint32LE();
_rect->top = file.readUint32LE();
_rect->right = file.readUint32LE();
_rect->bottom = file.readUint32LE();
assert (g_fullpipe->_gameProjectVersion >= 1);
_someX = file.readUint32LE();
_someY = file.readUint32LE();
assert (g_fullpipe->_gameProjectVersion >= 12);
_dynFlags = file.readUint32LE();
return true;
}
StaticPhase::StaticPhase() {
_field_6A = 1;
_initialCountdown = 0;
_countdown = 0;
_field_68 = 0;
_exCommand = 0;
}
bool StaticPhase::load(MfcArchive &file) {
debug(5, "StaticPhase::load()");
Picture::load(file);
_initialCountdown = file.readUint16LE();
_field_6A = file.readUint16LE();
if (g_fullpipe->_gameProjectVersion >= 12) {
_exCommand = (ExCommand *)file.readClass();
return true;
}
assert (g_fullpipe->_gameProjectVersion >= 12);
return true;
}
} // End of namespace Fullpipe