PETKA: added heroes implementation without walking system

This commit is contained in:
Andrei Prykhodko 2019-08-25 18:44:00 +03:00 committed by Eugene Sandulenko
parent afa777da2a
commit 1599f21861
7 changed files with 344 additions and 26 deletions

View File

@ -20,10 +20,14 @@
*
*/
#include "common/system.h"
#include "petka/petka.h"
#include "petka/q_manager.h"
#include "petka/q_system.h"
#include "petka/flc.h"
#include "petka/video.h"
#include "petka/sound.h"
#include "petka/objects/heroes.h"
namespace Petka {
@ -40,6 +44,7 @@ QObjectPetka::QObjectPetka() {
_surfId = -5;
_surfH = 0;
_surfW = 0;
_field98 = 1.0;
}
void QObjectPetka::processMessage(const QMessage &arg) {
@ -79,6 +84,229 @@ void QObjectPetka::initSurface() {
_surfH = flc->getHeight() * _field98;
}
void QObjectPetka::walk(int x, int y) {
Common::Point walkPos(x, y);
if (_isShown) {
Common::Point currPos;
if (_isWalking) {
// currPos = _walkObj->currPos();
} else {
currPos.x = _x_;
currPos.y = _y_;
}
if (currPos.sqrDist(walkPos) >= 25 * 25) {
//_walkObj->init(currPos, walkPos);
_destX = x;
_destY = y;
_resourceId = _imageId; // + _walkObj->getResId() + 10;
_isWalking = true;
_animate = true;
initSurface();
FlicDecoder *flc = g_vm->resMgr()->loadFlic(_resourceId);
flc->setFrame(1);
g_vm->videoSystem()->makeAllDirty();
_field7C = 0;
_time = 0;
_msgProcessingPaused = true;
}
} else {
setPos(x, y);
}
}
void QObjectPetka::draw() {
if (!_isShown || _resourceId == -1) {
return;
}
if (_animate && _startSound) {
if (_sound) {
_sound->play(!_notLoopedSound);
}
_startSound = false;
}
FlicDecoder *flc = g_vm->resMgr()->loadFlic(_resourceId);
Graphics::Surface *surf = g_vm->resMgr()->loadBitmap(_surfId);
if (!flc || !surf) {
return;
}
Graphics::Surface *conv = flc->getCurrentFrame()->convertTo(g_system->getScreenFormat(), flc->getPalette());
surf->copyRectToSurface(*conv, 0, 0, Common::Rect(0, 0, flc->getWidth() - 1, flc->getHeight() - 1));
Common::Rect srcRect(0, 0, _surfW, _surfH);
Common::Rect dstRect(srcRect);
dstRect.translate(_x, _y);
g_vm->videoSystem()->screen().transBlitFrom(*surf, srcRect, dstRect, flc->getTransColor(surf->format));
conv->free();
delete conv;
}
void QObjectPetka::setPos(int x, int y) {
y = MIN(y, 480);
FlicDecoder *flc = g_vm->resMgr()->loadFlic(_resourceId);
_field98 = calcSmth(y);
_surfH = flc->getHeight() * _field98;
_surfW = flc->getWidth() * _field98;
_x_ = x;
_y_ = y;
_x = x - _surfW / 2;
_y = y - _surfH;
g_vm->videoSystem()->makeAllDirty();
}
double QObjectPetka::calcSmth(int y) {
QSystem *qsys = g_vm->getQSystem();
y = MIN(y, 480);
if (!qsys->_unkMap.contains(qsys->_room->_name)) {
return 1.0;
}
const UnkStruct &unk = qsys->_unkMap.getVal(qsys->_room->_name);
double res = (y - unk.f3) * unk.f2 / (unk.f4 - unk.f3);
if (res < 0.0)
res = 0.0;
if (res + unk.f1 > unk.f5)
return unk.f5;
return res + unk.f1;
}
void QObjectPetka::updateWalk() {
if (_isWalking) {
_isWalking = false;
setPos(_destX, _destY);
QMessage msg {_id, kSet, (uint16)_imageId, 1, 0, nullptr, 0};
if (_heroReaction) {
uint i;
for (i = 0; i < _heroReaction->messages.size(); ++i) {
if (_heroReaction->messages[i].opcode == kGoTo || _heroReaction->messages[i].opcode == kSetSeq) {
_resourceId = _imageId; // + _walkObj->getResOffset() + 10;
FlicDecoder *flc = g_vm->resMgr()->loadFlic(_resourceId);
flc->setFrame(1);
initSurface();
processMessage(QMessage {_id, kAnimate, 0, 0, 0, nullptr, 0});
_heroReaction->messages.push_back(msg);
_heroReaction->messages.push_back(QMessage {_id, kAnimate, 1, 0, 0, nullptr, 0});
break;
}
}
if (i == _heroReaction->messages.size())
processMessage(msg);
} else {
processMessage(msg);
}
_msgProcessingPaused = false;
g_vm->videoSystem()->makeAllDirty();
}
}
void QObjectPetka::setReactionAfterWalk(uint index, QReaction **reaction, QMessageObject *sender, bool deleteReaction) {
QReaction *r = *reaction;
_heroReaction = nullptr;
stopWalk();
QMessage msg {_id, kWalked, 0, 0, 0, sender, 0};
_heroReaction = new QReaction();
_sender = sender;
for (uint i = index + 1; i < r->messages.size(); ++i) {
_heroReaction->messages.push_back(r->messages[i]);
}
if (deleteReaction) {
if (r == *reaction) {
if (*reaction) {
delete *reaction;
}
*reaction = nullptr;
} else {
delete r;
}
}
}
void QObjectPetka::stopWalk() {
_isWalking = false;
_msgProcessingPaused = false;
Common::List<QMessage> &list = g_vm->getQSystem()->_messages;
for (Common::List<QMessage>::iterator it = list.begin(); it != list.end();) {
if (it->opcode == kWalked && it->objId == _id) {
it->objId = -1;
}
}
delete _heroReaction;
_heroReaction = nullptr;
if (!_field7C) {
QMessage msg {_id, kSet, (uint16)_imageId, 1, 0, nullptr, 0};
processMessage(msg);
}
}
void QObjectPetka::update(int time) {
if (!_animate || !_isShown)
return;
_time += time;
FlicDecoder *flc = g_vm->resMgr()->loadFlic(_resourceId);
if (flc && flc->getFrameCount() != 1) {
while (_time >= flc->getDelay()) {
if (_sound && _hasSound && flc->getCurFrame() == 0) {
_startSound = true;
_hasSound = false;
}
flc->setFrame(-1);
if (flc->getCurFrame() == flc->getFrameCount() - 1) {
if (_notLoopedSound) {
_hasSound = _sound != nullptr;
}
g_vm->getQSystem()->addMessage(_id, kEnd, _resourceId, 0, 0, 0, 0);
}
if (flc->getCurFrame() + 1 == flc->getFrameCount() / 2) {
g_vm->getQSystem()->addMessage(_id, kHalf, _resourceId, 0, 0, 0, 0);
}
if (_field7C && flc->getCurFrame() == 0)
_time = -10000;
updateWalk();
flc = g_vm->resMgr()->loadFlic(_resourceId);
_surfH = flc->getHeight() * _field98;
_surfW = flc->getWidth() * _field98;
_time -= flc->getDelay();
g_vm->videoSystem()->addDirtyRect(Common::Rect(_x, _y, _surfW + _x, _surfH + _y));
}
}
}
QObjectChapayev::QObjectChapayev() {
_x = 477;
_y = 350;

View File

@ -33,7 +33,19 @@ public:
void processMessage(const QMessage &msg) override;
void initSurface();
protected:
void walk(int x, int y);
void stopWalk();
void updateWalk();
void setReactionAfterWalk(uint index, QReaction **reaction, QMessageObject *sender, bool deleteReaction);
void draw() override;
void update(int time) override;
void setPos(int x, int y) override;
double calcSmth(int y);
public:
int _field7C;
int _surfW;
int _surfH;
@ -43,6 +55,8 @@ protected:
int _imageId;
double _field98;
// walkObj
int _destX;
int _destY;
bool _isWalking;
bool _isPetka;
QReaction *_heroReaction;

View File

@ -57,7 +57,7 @@ QMessageObject::QMessageObject() {
_isShown = true;
_isActive = true;
_updateZ = 0;
_field_38 = 0;
_msgProcessingPaused = 0;
_notLoopedSound = true;
_startSound = false;
_hasSound = false;
@ -89,12 +89,13 @@ void processSavedReaction(QReaction **reaction, QMessageObject *sender) {
}
break;
}
/*
case kWalk:
case kWalkTo:
case kWalkVich:
g_vm->getQSystem()->_petka->setReactionAfterWalk(i, &r, sender, 1);
break;
case kWalkVich:
g_vm->getQSystem()->_chapayev->setReactionAfterWalk(i, &r, sender, 1);
break;
*/
default:
processed = false;
break;
@ -113,10 +114,10 @@ void processSavedReaction(QReaction **reaction, QMessageObject *sender) {
void QMessageObject::processMessage(const QMessage &msg) {
bool reacted = false;
for (uint i = 0; i < _reactions.size(); ++i) {
QReaction &r = _reactions[i];
if (r.opcode != msg.opcode ||
(r.status != -1 && r.status != _status) ||
(r.senderId != -1 && r.senderId != msg.sender->_id)) {
QReaction *r = &_reactions[i];
if (r->opcode != msg.opcode ||
(r->status != -1 && r->status != _status) ||
(r->senderId != -1 && r->senderId != msg.sender->_id)) {
continue;
}
bool res;
@ -124,8 +125,8 @@ void QMessageObject::processMessage(const QMessage &msg) {
g_vm->getBigDialogue()->setDialog(_id, msg.opcode, -1);
g_vm->getQSystem()->_mainInterface->_dialog._sender = this;
}
for (uint j = 0; j < r.messages.size(); ++j) {
QMessage &rMsg = r.messages[j];
for (uint j = 0; j < r->messages.size(); ++j) {
QMessage &rMsg = r->messages[j];
if (rMsg.opcode == kCheck && g_vm->getQSystem()->findObject(rMsg.objId)->_status != rMsg.arg1) {
break;
}
@ -145,8 +146,8 @@ void QMessageObject::processMessage(const QMessage &msg) {
case kDialog:
delete g_dialogReaction;
g_dialogReaction = new QReaction();
for (uint z = j + 1; z < r.messages.size(); ++z) {
g_dialogReaction->messages.push_back(r.messages[z]);
for (uint z = j + 1; z < r->messages.size(); ++z) {
g_dialogReaction->messages.push_back(r->messages[z]);
}
break;
case kPlay: {
@ -154,17 +155,19 @@ void QMessageObject::processMessage(const QMessage &msg) {
delete obj->_reaction;
obj->_reaction = new QReaction();
obj->_reactionResId = rMsg.arg1;
for (uint z = j + 1; z < r.messages.size(); ++z) {
obj->_reaction->messages.push_back(r.messages[z]);
for (uint z = j + 1; z < r->messages.size(); ++z) {
obj->_reaction->messages.push_back(r->messages[z]);
}
break;
}
/*
case kWalk:
case kWalkTo:
case kWalkVich:
g_vm->getQSystem()->_petka->setReactionAfterWalk(j, &r, this, 0);
break;
case kWalkVich:
g_vm->getQSystem()->_chapayev->setReactionAfterWalk(j, &r, this, 0);
break;
*/
default:
processed = false;
}
@ -291,6 +294,44 @@ void QMessageObject::processMessage(const QMessage &msg) {
case kJumpVich:
g_vm->getQSystem()->_petka->setPos((msg.arg1 == -1 ? _walkX : msg.arg1), (msg.arg2 == -1 ? _walkY : msg.arg2));
break;
case kWalk:
if (!reacted) {
if (_walkX == -1) {
g_vm->getQSystem()->_petka->walk(msg.arg1, msg.arg2);
} else {
g_vm->getQSystem()->_petka->walk(_walkX, _walkY);
}
}
break;
case kWalkTo: {
int destX = msg.arg1;
int destY = msg.arg2;
if (destX == -1 || destY == -1) {
destX = _walkX;
destY = _walkY;
}
if (destX != -1) {
g_vm->getQSystem()->_petka->walk(destX, destY);
QReaction *r = g_vm->getQSystem()->_petka->_heroReaction;
if (r) {
for (uint i = 0; i < r->messages.size(); ++i) {
if (r->messages[i].opcode == kGoTo) {
g_vm->getQSystem()->_chapayev->walk(_walkX, _walkY);
break;
}
}
}
}
break;
}
case kWalkVich:
if (msg.arg1 == -1 || msg.arg2 == -1) {
g_vm->getQSystem()->_chapayev->walk(msg.arg1, msg.arg2);
} else if (_walkX != -1) {
g_vm->getQSystem()->_chapayev->walk(_walkX, _walkY);
}
break;
}
} else {
g_vm->getBigDialogue()->setDialog(_id, msg.opcode, -1);
@ -335,10 +376,13 @@ bool QObject::isInPoint(int x, int y) {
if (!_isActive)
return false;
FlicDecoder *flc = g_vm->resMgr()->loadFlic(_resourceId);
Common::Rect rect(_x, _y, _x + flc->getWidth(), _y + flc->getHeight());
if (!rect.contains(x, y))
return false;
return *(byte *) flc->getCurrentFrame()->getBasePtr(x - _x, y - _y) != 0;
if (flc) {
Common::Rect rect(_x, _y, _x + flc->getWidth(), _y + flc->getHeight());
if (!rect.contains(x, y))
return false;
return *(byte *) flc->getCurrentFrame()->getBasePtr(x - _x, y - _y) != 0;
}
return false;
}
void QObject::draw() {

View File

@ -69,7 +69,7 @@ public:
int32 _isShown;
int32 _animate;
int _updateZ;
int _field_38;
int _msgProcessingPaused;
int _isActive;
int _startSound;
int _hasSound;

View File

@ -35,6 +35,7 @@
#include "petka/q_manager.h"
#include "petka/interfaces/main.h"
#include "petka/objects/object_bg.h"
#include "petka/objects/heroes.h"
namespace Petka {
@ -59,10 +60,14 @@ void QObjectBG::processMessage(const QMessage &msg) {
case kNoMap:
_showMap = 0;
break;
case kGoTo:
case kGoTo: {
g_vm->getQSystem()->_mainInterface->loadRoom(_id, false);
g_vm->videoSystem()->makeAllDirty();
QMessageObject *obj = g_vm->getQSystem()->findObject(_id);
g_vm->getQSystem()->_petka->setPos(obj->_walkX, obj->_walkY);
g_vm->getQSystem()->_chapayev->setPos(obj->_walkX, obj->_walkY - 2);
break;
}
case kSetSeq:
break;
case kEndSeq:

View File

@ -133,6 +133,21 @@ bool QSystem::init() {
}
for (uint i = 0; i < bgsCount; ++i) {
readObject(_bgs[i], *stream, namesIni, castIni);
Common::String val;
bgsIni.getKey(_bgs[i]._name, "Settings", val);
if (!val.empty()) {
UnkStruct unk;
sscanf(val.c_str(), "%lf %lf %d %d %lf", &unk.f1, &unk.f2, &unk.f3, &unk.f4, &unk.f5);
_unkMap.setVal(_bgs[i]._name, unk);
}
_allObjects.push_back(&_bgs[i]);
}
@ -255,7 +270,7 @@ void QSystem::load(Common::ReadStream *s) {
uint count = s->readUint32LE();
for (uint i = 0; i < count; ++i) {
QMessageObject *obj = findObject(readString(s));
obj->_field_38 = s->readUint32LE();
obj->_msgProcessingPaused = s->readUint32LE();
obj->_status = s->readUint32LE();
obj->_resourceId = s->readUint32LE();
obj->_z = s->readUint32LE();
@ -295,7 +310,7 @@ void QSystem::save(Common::WriteStream *s) {
s->writeUint32LE(_allObjects.size());
for (uint i = 0; i < _allObjects.size(); ++i) {
writeString(s, _allObjects[i]->_name);
s->writeUint32LE(_allObjects[i]->_field_38);
s->writeUint32LE(_allObjects[i]->_msgProcessingPaused);
s->writeUint32LE(_allObjects[i]->_status);
s->writeUint32LE(_allObjects[i]->_resourceId);
s->writeUint32LE(_allObjects[i]->_z);

View File

@ -26,6 +26,8 @@
#include "common/ptr.h"
#include "common/stream.h"
#include "common/list.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "petka/objects/object_bg.h"
@ -44,6 +46,14 @@ class InterfacePanel;
class InterfaceMap;
class Interface;
struct UnkStruct {
double f1;
double f2;
int f3;
int f4;
double f5;
};
class QSystem {
public:
explicit QSystem();
@ -85,6 +95,8 @@ public:
Interface *_currInterface;
Interface *_prevInterface;
Common::HashMap<Common::String, UnkStruct> _unkMap;
int _isIniting;
int _fxId;
int _musicId;