Initial commit
This commit is contained in:
428
engines/petka/objects/heroes.cpp
Normal file
428
engines/petka/objects/heroes.cpp
Normal file
@@ -0,0 +1,428 @@
|
||||
/* 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 "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"
|
||||
#include "petka/interfaces/panel.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
QObjectPetka::QObjectPetka()
|
||||
: _walk(nullptr) {
|
||||
_field7C = 1;
|
||||
_reaction = nullptr;
|
||||
_heroReaction = nullptr;
|
||||
_sender = nullptr;
|
||||
_isWalking = false;
|
||||
_x = 574;
|
||||
_y = 444;
|
||||
_z = 200;
|
||||
// _surfId = -5;
|
||||
_surfH = 0;
|
||||
_surfW = 0;
|
||||
_k = 1.0;
|
||||
|
||||
_x_ = _y_ = 0;
|
||||
_destX = _destY = 0;
|
||||
_imageId = 0;
|
||||
_fieldB4 = 0;
|
||||
}
|
||||
|
||||
void QObjectPetka::processMessage(const QMessage &arg) {
|
||||
QMessage msg = arg;
|
||||
if (msg.opcode == kImage) {
|
||||
msg.opcode = kSet;
|
||||
_imageId = msg.arg1;
|
||||
|
||||
_walk.reset(new Walk(_imageId + 10));
|
||||
|
||||
QObjectBG *room = g_vm->getQSystem()->_room;
|
||||
if (room)
|
||||
_walk->setBackground(g_vm->resMgr()->findResourceName(room->_resourceId));
|
||||
}
|
||||
if (msg.opcode == kSaid || msg.opcode == kStand) {
|
||||
msg.opcode = kSet;
|
||||
msg.arg1 = _imageId;
|
||||
msg.arg2 = 1;
|
||||
}
|
||||
if (msg.opcode == kSay) {
|
||||
msg.opcode = kSet;
|
||||
msg.arg1 = _imageId + 1;
|
||||
msg.arg2 = 1;
|
||||
}
|
||||
if (msg.opcode == kSet || msg.opcode == kPlay) {
|
||||
_field7C = msg.arg1 == _imageId || msg.opcode == kPlay;
|
||||
}
|
||||
if (msg.opcode != kWalk) {
|
||||
if (msg.opcode == kWalked && _heroReaction) {
|
||||
QReaction *reaction = _heroReaction;
|
||||
_heroReaction = nullptr;
|
||||
_sender->processReaction(reaction);
|
||||
}
|
||||
QMessageObject::processMessage(msg);
|
||||
if (msg.opcode == kSet || msg.opcode == kPlay) {
|
||||
initSurface();
|
||||
if (!g_vm->getQSystem()->_totalInit) {
|
||||
setPos(Common::Point(_x_, _y_), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectPetka::initSurface() {
|
||||
QManager *resMgr = g_vm->resMgr();
|
||||
FlicDecoder *flc = resMgr->getFlic(_resourceId);
|
||||
_surfW = flc->getWidth() * _k;
|
||||
_surfH = flc->getHeight() * _k;
|
||||
}
|
||||
|
||||
void QObjectPetka::walk(int x, int y) {
|
||||
Common::Point walkPos(x, y);
|
||||
if (!_isShown) {
|
||||
setPos(walkPos, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Common::Point currPos;
|
||||
if (_isWalking) {
|
||||
currPos = _walk->currPos();
|
||||
} else {
|
||||
currPos.x = _x_;
|
||||
currPos.y = _y_;
|
||||
}
|
||||
|
||||
|
||||
if (currPos.sqrDist(walkPos) >= 25) {
|
||||
_walk->init(currPos, walkPos);
|
||||
_destX = x;
|
||||
_destY = y;
|
||||
_resourceId = _imageId + _walk->getSpriteId() + 10;
|
||||
_isWalking = true;
|
||||
_animate = true;
|
||||
|
||||
initSurface();
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
flc->setFrame(1);
|
||||
|
||||
sub_408940();
|
||||
|
||||
g_vm->videoSystem()->makeAllDirty();
|
||||
|
||||
_field7C = 0;
|
||||
_time = 0;
|
||||
_holdMessages = true;
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectPetka::draw() {
|
||||
if (!_isShown || _resourceId == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_animate && _startSound) {
|
||||
if (_sound) {
|
||||
_sound->play(_loopedSound);
|
||||
if (_loopedSound) {
|
||||
_sound = nullptr;
|
||||
}
|
||||
}
|
||||
_startSound = false;
|
||||
}
|
||||
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (!flc) {
|
||||
return;
|
||||
}
|
||||
Graphics::Surface *conv = flc->getCurrentFrame()->convertTo(g_system->getScreenFormat(), flc->getPalette());
|
||||
|
||||
Common::Rect srcRect(0, 0, conv->w, conv->h);
|
||||
Common::Rect dstRect(0, 0, _surfW, _surfH);
|
||||
dstRect.translate(_x - g_vm->getQSystem()->_xOffset, _y);
|
||||
|
||||
g_vm->videoSystem()->transBlitFrom(*conv, srcRect, dstRect, flc->getTransColor(conv->format));
|
||||
conv->free();
|
||||
delete conv;
|
||||
}
|
||||
|
||||
void QObjectPetka::setPos(Common::Point p, bool) {
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
|
||||
int xOff = sys->_xOffset;
|
||||
Common::Rect dirty(_x - xOff, _y, _surfW + _x - xOff, _surfH + _y);
|
||||
g_vm->videoSystem()->addDirtyRect(dirty);
|
||||
|
||||
p.y = MIN<int16>(p.y, 480);
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
|
||||
_k = calcPerspective(p.y);
|
||||
|
||||
_surfH = flc->getHeight() * _k;
|
||||
_surfW = flc->getWidth() * _k;
|
||||
|
||||
_x_ = p.x;
|
||||
_y_ = p.y;
|
||||
|
||||
_x = p.x - _surfW / 2;
|
||||
_y = p.y - _surfH;
|
||||
|
||||
recalcOffset();
|
||||
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Rect(_x - xOff, _y, _surfW + _x - xOff, _surfH + _y));
|
||||
}
|
||||
|
||||
double QObjectPetka::calcPerspective(int y) {
|
||||
QSystem *qsys = g_vm->getQSystem();
|
||||
|
||||
y = MIN(y, 480);
|
||||
|
||||
const Perspective &pers = qsys->_room->_persp;
|
||||
double res = (y - pers.y0) * pers.k / (pers.y1 - pers.y0);
|
||||
if (res < 0.0)
|
||||
res = 0.0;
|
||||
|
||||
if (res + pers.f0 > pers.f1)
|
||||
return pers.f1;
|
||||
return res + pers.f0;
|
||||
}
|
||||
|
||||
void QObjectPetka::updateWalk() {
|
||||
if (!_isWalking)
|
||||
return;
|
||||
|
||||
int v = _walk->sub_423350();
|
||||
|
||||
switch (v) {
|
||||
case 0: {
|
||||
_isWalking = false;
|
||||
setPos(Common::Point(_walk->destX, _walk->destY), false);
|
||||
|
||||
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 + _walk->getSpriteId() + 10;
|
||||
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_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);
|
||||
}
|
||||
_holdMessages = false;
|
||||
g_vm->videoSystem()->makeAllDirty();
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
sub_408940();
|
||||
break;
|
||||
case 2: {
|
||||
_resourceId = _walk->getSpriteId() + _imageId + 10;
|
||||
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
flc->setFrame(1);
|
||||
|
||||
_time = flc->getDelay();
|
||||
|
||||
initSurface();
|
||||
g_vm->videoSystem()->makeAllDirty();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectPetka::setReactionAfterWalk(uint index, QReaction *reaction, QMessageObject *sender, bool deleteReaction) {
|
||||
_heroReaction = nullptr;
|
||||
|
||||
stopWalk();
|
||||
|
||||
QMessage msg(_id, kWalked, 0, 0, 0, sender, 0);
|
||||
g_vm->getQSystem()->addMessage(msg);
|
||||
_heroReaction = new QReaction();
|
||||
_sender = sender;
|
||||
|
||||
for (uint i = index + 1; i < reaction->messages.size(); ++i) {
|
||||
_heroReaction->messages.push_back(reaction->messages[i]);
|
||||
}
|
||||
|
||||
if (deleteReaction) {
|
||||
delete reaction;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QObjectPetka::stopWalk() {
|
||||
_isWalking = false;
|
||||
_holdMessages = false;
|
||||
|
||||
Common::List<QMessage> &list = g_vm->getQSystem()->_messages;
|
||||
for (Common::List<QMessage>::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
if (it->opcode == kWalked && it->objId == _id) {
|
||||
it->objId = (uint16)-1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delete _heroReaction;
|
||||
_heroReaction = nullptr;
|
||||
|
||||
if (!_field7C) {
|
||||
Common::Point p = _walk->sub_4234B0();
|
||||
|
||||
_x = p.x;
|
||||
_y = p.y;
|
||||
|
||||
QMessage msg(_id, kSet, (uint16)_imageId, 1, 0, nullptr, 0);
|
||||
processMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectPetka::update(int time) {
|
||||
if (!_animate || !_isShown)
|
||||
return;
|
||||
if (_isWalking)
|
||||
_time += time * (g_vm->getQSystem()->_panelInterface->getHeroSpeed() + 50) / 50;
|
||||
else
|
||||
_time += time;
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (flc && flc->getFrameCount() != 1) {
|
||||
if (_sound) {
|
||||
Common::Rect bounds = flc->getBounds();
|
||||
_sound->setBalance(bounds.left + bounds.width() / 2 - g_vm->getQSystem()->_xOffset, 640);
|
||||
}
|
||||
|
||||
while (_time >= (int)flc->getDelay()) {
|
||||
if (_sound && flc->getCurFrame() == 0) {
|
||||
_startSound = true;
|
||||
}
|
||||
flc->setFrame(-1);
|
||||
if (flc->getCurFrame() == (int32)flc->getFrameCount() - 1) {
|
||||
g_vm->getQSystem()->addMessage(_id, kEnd, _resourceId, 0, 0, 0, nullptr);
|
||||
}
|
||||
if (flc->getCurFrame() + 1 == (int32)flc->getFrameCount() / 2) {
|
||||
g_vm->getQSystem()->addMessage(_id, kHalf, _resourceId, 0, 0, 0, nullptr);
|
||||
}
|
||||
|
||||
if (_field7C && flc->getCurFrame() == 0)
|
||||
_time = -10000;
|
||||
|
||||
updateWalk();
|
||||
flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
|
||||
_surfH = flc->getHeight() * _k;
|
||||
_surfW = flc->getWidth() * _k;
|
||||
|
||||
_time -= flc->getDelay();
|
||||
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Rect(_x, _y, _surfW + _x, _surfH + _y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QObjectPetka::isInPoint(Common::Point p) {
|
||||
if (!_isActive)
|
||||
return false;
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
const Graphics::Surface *flcSurface = flc->getCurrentFrame();
|
||||
Common::Rect bounds(_surfW, _surfH);
|
||||
Graphics::ManagedSurface s(_surfW, _surfH, flcSurface->format);
|
||||
s.transBlitFrom(*flcSurface, Common::Rect(0, 0, flcSurface->w, flcSurface->h), bounds);
|
||||
p.x -= _x;
|
||||
p.y -= _y;
|
||||
if (!bounds.contains(p.x, p.y))
|
||||
return false;
|
||||
return *(uint16 *)s.getBasePtr(p.x, p.y) != 0;
|
||||
}
|
||||
|
||||
void QObjectPetka::updateZ() {
|
||||
if (_animate && _isShown && _updateZ) {
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (_isWalking) {
|
||||
_z = _walk->currPos().y;
|
||||
} else {
|
||||
_z = _y + flc->getHeight() * _k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectPetka::sub_408940() {
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
|
||||
int xOff = sys->_xOffset;
|
||||
Common::Rect dirty(_x - xOff, _y, _surfW + _x - xOff, _surfH + _y);
|
||||
g_vm->videoSystem()->addDirtyRect(dirty);
|
||||
|
||||
Common::Point currPos = _walk->currPos();
|
||||
_k = calcPerspective(currPos.y);
|
||||
_surfW = flc->getWidth() * _k;
|
||||
_surfH = flc->getHeight() * _k;
|
||||
|
||||
Common::Point p = _walk->sub_4234B0();
|
||||
_x = p.x;
|
||||
_y = p.y;
|
||||
|
||||
_x_ = currPos.x;
|
||||
_y_ = currPos.y;
|
||||
|
||||
recalcOffset();
|
||||
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Rect(_x - xOff, _y, _surfW + _x - xOff, _surfH + _y));
|
||||
}
|
||||
|
||||
void QObjectPetka::recalcOffset() {
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
int xOff = sys->_xOffset;
|
||||
|
||||
if (_x_ < xOff + 160 || _x_ > xOff + 480) {
|
||||
sys->_reqOffset = _x_ - 320;
|
||||
}
|
||||
sys->_reqOffset = CLIP<int>(sys->_reqOffset, 0, sys->_sceneWidth - 640);
|
||||
}
|
||||
|
||||
QObjectChapayev::QObjectChapayev() {
|
||||
_x = 477;
|
||||
_y = 350;
|
||||
// _surfId = -6;
|
||||
}
|
||||
|
||||
}
|
||||
84
engines/petka/objects/heroes.h
Normal file
84
engines/petka/objects/heroes.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PETKA_HEROES_H
|
||||
#define PETKA_HEROES_H
|
||||
|
||||
#include "common/ptr.h"
|
||||
#include "petka/objects/object.h"
|
||||
#include "petka/walk.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
class QObjectPetka : public QObject {
|
||||
public:
|
||||
QObjectPetka();
|
||||
void processMessage(const QMessage &msg) override;
|
||||
void initSurface();
|
||||
|
||||
void walk(int x, int y);
|
||||
void stopWalk();
|
||||
void updateWalk();
|
||||
void setReactionAfterWalk(uint index, QReaction *reaction, QMessageObject *sender, bool deleteReaction);
|
||||
|
||||
void draw() override;
|
||||
bool isInPoint(Common::Point p) override;
|
||||
void update(int time) override;
|
||||
void setPos(Common::Point p, bool ) override;
|
||||
|
||||
double calcPerspective(int y);
|
||||
|
||||
void updateZ() override;
|
||||
|
||||
void sub_408940();
|
||||
|
||||
private:
|
||||
virtual void recalcOffset();
|
||||
|
||||
public:
|
||||
int _field7C;
|
||||
int _surfW;
|
||||
int _surfH;
|
||||
int _x_;
|
||||
int _y_;
|
||||
// int _surfId;
|
||||
int _imageId;
|
||||
double _k;
|
||||
Common::ScopedPtr<Walk> _walk;
|
||||
int _destX;
|
||||
int _destY;
|
||||
bool _isWalking;
|
||||
QReaction *_heroReaction;
|
||||
QMessageObject *_sender;
|
||||
int _fieldB4;
|
||||
};
|
||||
|
||||
class QObjectChapayev : public QObjectPetka {
|
||||
public:
|
||||
QObjectChapayev();
|
||||
|
||||
void recalcOffset() override {}
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Petka
|
||||
|
||||
#endif
|
||||
603
engines/petka/objects/object.cpp
Normal file
603
engines/petka/objects/object.cpp
Normal file
@@ -0,0 +1,603 @@
|
||||
/* 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 "common/formats/ini-file.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/system.h"
|
||||
#include "common/events.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "petka/big_dialogue.h"
|
||||
#include "petka/flc.h"
|
||||
#include "petka/sound.h"
|
||||
#include "petka/petka.h"
|
||||
#include "petka/video.h"
|
||||
#include "petka/q_system.h"
|
||||
#include "petka/q_manager.h"
|
||||
#include "petka/objects/object_star.h"
|
||||
#include "petka/objects/object_cursor.h"
|
||||
#include "petka/interfaces/main.h"
|
||||
#include "petka/objects/heroes.h"
|
||||
#include "petka/objects/object_case.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
QReaction *createReaction(QMessage *messages, QMessage *end) {
|
||||
QReaction *reaction = new QReaction();
|
||||
while (messages != end) {
|
||||
reaction->messages.push_back(*messages++);
|
||||
}
|
||||
return reaction;
|
||||
}
|
||||
|
||||
QVisibleObject::QVisibleObject()
|
||||
: _resourceId(-1), _z(240) {}
|
||||
|
||||
QMessageObject::QMessageObject() {
|
||||
_id = (uint16)-1;
|
||||
_status = 0;
|
||||
_time = 0;
|
||||
_dialogColor = -1;
|
||||
_animate = true;
|
||||
_isShown = true;
|
||||
_isActive = true;
|
||||
_updateZ = false;
|
||||
_holdMessages = false;
|
||||
_loopedSound = false;
|
||||
_startSound = false;
|
||||
_reaction = nullptr;
|
||||
|
||||
_x = _y = _walkX = _walkY = 0;
|
||||
_frame = 0;
|
||||
_sound = nullptr;
|
||||
_reactionId = 0;
|
||||
}
|
||||
|
||||
void QMessageObject::processMessage(const QMessage &msg) {
|
||||
bool reacted = false;
|
||||
int opcode = (msg.opcode == kObjectUse) ? (msg.sender->_id << 16) | kObjectUse : msg.opcode;
|
||||
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)) {
|
||||
continue;
|
||||
}
|
||||
bool fallback;
|
||||
if (g_vm->getBigDialogue()->findHandler(_id, opcode, &fallback) && !fallback) {
|
||||
g_vm->getBigDialogue()->setHandler(_id, opcode);
|
||||
g_vm->getQSystem()->_mainInterface->_dialog.setSender(this);
|
||||
}
|
||||
processReaction(r, &msg);
|
||||
reacted = true;
|
||||
}
|
||||
|
||||
if (reacted || !g_vm->getBigDialogue()->findHandler(_id, opcode, nullptr)) {
|
||||
switch (msg.opcode) {
|
||||
case kAddInv:
|
||||
g_vm->getQSystem()->getCase()->addItem(msg.objId);
|
||||
// original bug fix
|
||||
g_vm->pushMouseMoveEvent();
|
||||
break;
|
||||
case kDelInv:
|
||||
g_vm->getQSystem()->getCase()->removeItem(msg.objId);
|
||||
break;
|
||||
case kSetInv:
|
||||
g_vm->getQSystem()->getCase()->transformItem(msg.sender->_id, msg.objId);
|
||||
break;
|
||||
case kAvi: {
|
||||
Common::String videoName = g_vm->resMgr()->findResourceName((uint16) msg.arg1);
|
||||
g_vm->playVideo(g_vm->openFile(videoName, false));
|
||||
break;
|
||||
}
|
||||
case kContinue:
|
||||
g_vm->getQSystem()->_mainInterface->_dialog.endUserMsg();
|
||||
break;
|
||||
case kCursor:
|
||||
g_vm->getQSystem()->getCursor()->setInvItem(this, msg.arg1);
|
||||
g_vm->videoSystem()->makeAllDirty();
|
||||
break;
|
||||
case kDialog:
|
||||
g_vm->getQSystem()->_mainInterface->_dialog.start(msg.arg1, this);
|
||||
break;
|
||||
case kSetPos:
|
||||
setPos(Common::Point(msg.arg1, msg.arg2), false);
|
||||
break;
|
||||
case kSet:
|
||||
case kPlay:
|
||||
play(msg.arg1, msg.arg2);
|
||||
break;
|
||||
case kAnimate:
|
||||
_animate = msg.arg1;
|
||||
break;
|
||||
case kEnd:
|
||||
if (_reaction && _reactionId == msg.arg1) {
|
||||
QReaction *reaction = _reaction;
|
||||
_reaction = nullptr;
|
||||
processReaction(reaction);
|
||||
}
|
||||
break;
|
||||
case kStatus:
|
||||
_status = (int8) msg.arg1;
|
||||
break;
|
||||
case kOn:
|
||||
_isActive = true;
|
||||
show(true);
|
||||
break;
|
||||
case kOff:
|
||||
_isActive = false;
|
||||
show(false);
|
||||
break;
|
||||
case kStop:
|
||||
g_vm->getQSystem()->getCursor()->show(msg.arg1);
|
||||
g_vm->getQSystem()->getStar()->_isActive = msg.arg1;
|
||||
break;
|
||||
case kShow:
|
||||
show(msg.arg1);
|
||||
break;
|
||||
case kShake:
|
||||
g_vm->videoSystem()->setShake(msg.arg1);
|
||||
break;
|
||||
case kSystem:
|
||||
switch (msg.arg1){
|
||||
case 0:
|
||||
g_vm->getQSystem()->getStar()->_isActive = false;
|
||||
break;
|
||||
case 1:
|
||||
g_vm->getQSystem()->getStar()->_isActive = true;
|
||||
break;
|
||||
case 242:
|
||||
Engine::quitGame();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case kHide:
|
||||
show(false);
|
||||
break;
|
||||
case kZBuffer:
|
||||
_updateZ = msg.arg1;
|
||||
_z = (msg.arg2 != -1) ? msg.arg2 : _z;
|
||||
break;
|
||||
case kActive:
|
||||
_isActive = msg.arg1;
|
||||
break;
|
||||
case kPassive:
|
||||
_isActive = false;
|
||||
break;
|
||||
case kJump: {
|
||||
Common::Point p;
|
||||
p.x = (msg.arg1 == 0xffff ? _walkX : msg.arg1);
|
||||
p.y = (msg.arg2 == -1 ? _walkY : msg.arg2);
|
||||
g_vm->getQSystem()->getPetka()->setPos(p, false);
|
||||
break;
|
||||
}
|
||||
case kJumpVich: {
|
||||
Common::Point p;
|
||||
p.x = (msg.arg1 == 0xffff ? _walkX : msg.arg1);
|
||||
p.y = (msg.arg2 == -1 ? _walkY : msg.arg2);
|
||||
g_vm->getQSystem()->getChapay()->setPos(p, false);
|
||||
break;
|
||||
}
|
||||
case kWalk:
|
||||
if (!reacted) {
|
||||
if (_walkX == -1) {
|
||||
g_vm->getQSystem()->getPetka()->walk(msg.arg1, msg.arg2);
|
||||
|
||||
} else {
|
||||
g_vm->getQSystem()->getPetka()->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()->getPetka()->walk(destX, destY);
|
||||
QReaction *r = g_vm->getQSystem()->getPetka()->_heroReaction;
|
||||
if (r) {
|
||||
for (uint i = 0; i < r->messages.size(); ++i) {
|
||||
if (r->messages[i].opcode == kGoTo) {
|
||||
g_vm->getQSystem()->getChapay()->walk(destX, destY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kWalkVich: {
|
||||
int destX = msg.arg1;
|
||||
int destY = msg.arg2;
|
||||
if (destX == -1 || destY == -1) {
|
||||
destX = _walkX;
|
||||
destY = _walkY;
|
||||
}
|
||||
if (destX != -1)
|
||||
g_vm->getQSystem()->getChapay()->walk(destX, destY);
|
||||
break;
|
||||
}
|
||||
case kDescription: {
|
||||
Common::ScopedPtr<Common::SeekableReadStream> invStream(g_vm->openFile("invntr.txt", true));
|
||||
if (invStream) {
|
||||
Common::String desc;
|
||||
Common::INIFile invIni;
|
||||
|
||||
invIni.allowNonEnglishCharacters();
|
||||
invIni.loadFromStream(*invStream);
|
||||
invIni.getKey(_name, "ALL", desc);
|
||||
|
||||
g_vm->getQSystem()->_mainInterface->setTextDescription(Common::convertToU32String(desc.c_str(), Common::kWindows1251), msg.arg1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kPart:
|
||||
g_vm->loadPartAtNextFrame(msg.arg1);
|
||||
break;
|
||||
case kChapter:
|
||||
g_vm->loadChapter(msg.arg1);
|
||||
break;
|
||||
case kToMap:
|
||||
g_vm->getQSystem()->toggleMapInterface();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
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)) {
|
||||
continue;
|
||||
}
|
||||
g_vm->getQSystem()->_mainInterface->_dialog.setReaction(createReaction(r.messages.data(), r.messages.end()));
|
||||
}
|
||||
g_vm->getBigDialogue()->setHandler(_id, opcode);
|
||||
g_vm->getQSystem()->_mainInterface->_dialog.start(msg.arg1, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QMessageObject::show(bool v) {
|
||||
_isShown = v;
|
||||
}
|
||||
|
||||
void QMessageObject::setReaction(int16 id, QReaction *reaction) {
|
||||
delete _reaction;
|
||||
_reaction = reaction;
|
||||
_reactionId = id;
|
||||
}
|
||||
|
||||
void QMessageObject::processReaction(QReaction *r, const QMessage *msg) {
|
||||
bool deleteReaction = (msg == nullptr);
|
||||
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;
|
||||
}
|
||||
if (msg && rMsg.opcode == kIf &&
|
||||
((rMsg.arg1 != 0xffff && rMsg.arg1 != msg->arg1) ||
|
||||
(rMsg.arg2 != -1 && rMsg.arg2 != msg->arg2) ||
|
||||
(rMsg.arg3 != -1 && rMsg.arg3 != msg->arg3))) {
|
||||
break;
|
||||
}
|
||||
if (msg && rMsg.opcode == kRandom && rMsg.arg2 != -1) {
|
||||
rMsg.arg1 = (int16) g_vm->getRnd().getRandomNumber((uint) (rMsg.arg2 - 1));
|
||||
}
|
||||
g_vm->getQSystem()->addMessage(rMsg.objId, rMsg.opcode, rMsg.arg1, rMsg.arg2, rMsg.arg3, rMsg.unk, this);
|
||||
bool processed = true;
|
||||
switch (rMsg.opcode) {
|
||||
case kDialog: {
|
||||
g_vm->getQSystem()->_mainInterface->_dialog.setReaction(createReaction(r->messages.data() + j + 1, r->messages.end()));
|
||||
break;
|
||||
}
|
||||
case kPlay: {
|
||||
QMessageObject *obj = g_vm->getQSystem()->findObject(rMsg.objId);
|
||||
obj->setReaction(rMsg.arg1, createReaction(r->messages.data() + j + 1, r->messages.end()));
|
||||
break;
|
||||
}
|
||||
case kWalk:
|
||||
case kWalkTo:
|
||||
g_vm->getQSystem()->getPetka()->setReactionAfterWalk(j, r, this, deleteReaction);
|
||||
return;
|
||||
case kWalkVich:
|
||||
g_vm->getQSystem()->getChapay()->setReactionAfterWalk(j, r, this, deleteReaction);
|
||||
return;
|
||||
default:
|
||||
processed = false;
|
||||
break;
|
||||
}
|
||||
if (processed)
|
||||
break;
|
||||
}
|
||||
if (deleteReaction)
|
||||
delete r;
|
||||
}
|
||||
|
||||
void QMessageObject::play(int id, int type) {
|
||||
if (g_vm->getQSystem()->_totalInit) {
|
||||
_resourceId = id;
|
||||
_loopedSound = (type == 5);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_loopedSound || g_vm->isDemo()) {
|
||||
removeSound();
|
||||
}
|
||||
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (flc) {
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), *flc);
|
||||
}
|
||||
|
||||
_resourceId = id;
|
||||
|
||||
loadSound();
|
||||
|
||||
flc = g_vm->resMgr()->getFlic(id);
|
||||
flc->setFrame(1);
|
||||
_time = 0;
|
||||
_loopedSound = (type == 5);
|
||||
}
|
||||
|
||||
void QMessageObject::loadSound() {
|
||||
Common::String name = g_vm->resMgr()->findSoundName(_resourceId);
|
||||
_sound = g_vm->soundMgr()->addSound(name, Audio::Mixer::kSFXSoundType);
|
||||
_startSound = false;
|
||||
}
|
||||
|
||||
void QMessageObject::removeSound() {
|
||||
Common::String name = g_vm->resMgr()->findSoundName(_resourceId);
|
||||
g_vm->soundMgr()->removeSound(name);
|
||||
_sound = nullptr;
|
||||
}
|
||||
|
||||
static Common::String readString(Common::ReadStream &readStream) {
|
||||
uint32 stringSize = readStream.readUint32LE();
|
||||
byte *data = (byte *)malloc(stringSize + 1);
|
||||
readStream.read(data, stringSize);
|
||||
data[stringSize] = '\0';
|
||||
Common::String str((char *)data);
|
||||
free(data);
|
||||
return str;
|
||||
}
|
||||
|
||||
void QMessageObject::readScriptData(Common::SeekableReadStream &stream) {
|
||||
_id = stream.readUint16LE();
|
||||
_name = readString(stream);
|
||||
_reactions.resize(stream.readUint32LE());
|
||||
|
||||
for (uint i = 0; i < _reactions.size(); ++i) {
|
||||
QReaction *reaction = &_reactions[i];
|
||||
reaction->opcode = stream.readUint16LE();
|
||||
reaction->status = stream.readByte();
|
||||
reaction->senderId = stream.readUint16LE();
|
||||
reaction->messages.resize(stream.readUint32LE());
|
||||
for (uint j = 0; j < reaction->messages.size(); ++j) {
|
||||
QMessage *msg = &reaction->messages[j];
|
||||
msg->objId = stream.readUint16LE();
|
||||
msg->opcode = stream.readUint16LE();
|
||||
msg->arg1 = stream.readUint16LE();
|
||||
msg->arg2 = stream.readUint16LE();
|
||||
msg->arg3 = stream.readUint16LE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QMessageObject::readInisData(Common::INIFile &names, Common::INIFile &cast, Common::INIFile *bgs) {
|
||||
names.getKey(_name, "all", _nameOnScreen);
|
||||
Common::String rgbString;
|
||||
if (cast.getKey(_name, "all", rgbString)) {
|
||||
int r, g, b;
|
||||
sscanf(rgbString.c_str(), "%d %d %d", &r, &g, &b);
|
||||
_dialogColor = g_vm->_system->getScreenFormat().RGBToColor((byte)r, (byte)g, (byte)b);
|
||||
}
|
||||
}
|
||||
|
||||
QObject::QObject() {
|
||||
_animate = true;
|
||||
_updateZ = true;
|
||||
_frame = 1;
|
||||
_sound = nullptr;
|
||||
_x = 0;
|
||||
_y = 0;
|
||||
_walkX = -1;
|
||||
_walkY = -1;
|
||||
}
|
||||
|
||||
bool QObject::isInPoint(Common::Point p) {
|
||||
if (!_isActive)
|
||||
return false;
|
||||
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (!flc || !flc->getBounds().contains(p.x - _x, p.y - _y))
|
||||
return false;
|
||||
|
||||
const Graphics::Surface *s = flc->getCurrentFrame();
|
||||
auto format = g_system->getScreenFormat();
|
||||
|
||||
byte index = *(const byte *)s->getBasePtr(p.x - _x, p.y - _y);
|
||||
const byte *pal = flc->getPalette();
|
||||
|
||||
return format.RGBToColor(pal[0], pal[1], pal[2]) != format.RGBToColor(pal[index * 3], pal[index * 3 + 1], pal[index * 3 + 2]);
|
||||
}
|
||||
|
||||
void QObject::draw() {
|
||||
if (!_isShown || _resourceId == -1) {
|
||||
return;
|
||||
}
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (!flc) {
|
||||
return;
|
||||
}
|
||||
if (_animate && _startSound) {
|
||||
if (_sound) {
|
||||
_sound->play(_loopedSound);
|
||||
if (_loopedSound) {
|
||||
_sound = nullptr;
|
||||
}
|
||||
}
|
||||
_startSound = false;
|
||||
}
|
||||
|
||||
int xOff = g_vm->getQSystem()->_xOffset;
|
||||
VideoSystem *videoSys = g_vm->videoSystem();
|
||||
|
||||
Common::Rect screen(640 + xOff, 480);
|
||||
Common::Rect flcBounds(flc->getBounds());
|
||||
Common::Rect objBounds(flcBounds);
|
||||
|
||||
objBounds.translate(_x, _y);
|
||||
|
||||
Common::Rect intersect(screen.findIntersectingRect(objBounds));
|
||||
if (intersect.isEmpty())
|
||||
return;
|
||||
|
||||
Graphics::Surface *surface = flc->getCurrentFrame()->getSubArea(flcBounds).convertTo(g_system->getScreenFormat(), flc->getPalette());
|
||||
|
||||
for (Common::Rect dirty : videoSys->rects()) {
|
||||
dirty.translate(xOff, 0);
|
||||
|
||||
Common::Rect destRect(intersect.findIntersectingRect(dirty));
|
||||
if (destRect.isEmpty())
|
||||
continue;
|
||||
|
||||
Common::Rect srcRect(destRect);
|
||||
|
||||
srcRect.translate(-_x, -_y);
|
||||
srcRect.translate(-flcBounds.left, -flcBounds.top);
|
||||
|
||||
destRect.translate(-xOff, 0);
|
||||
videoSys->transBlitFrom(*surface, srcRect, destRect, flc->getTransColor(surface->format));
|
||||
}
|
||||
|
||||
surface->free();
|
||||
delete surface;
|
||||
}
|
||||
|
||||
void QObject::updateZ() {
|
||||
if (!_animate || !_isShown || !_updateZ)
|
||||
return;
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (flc) {
|
||||
_z = 1;
|
||||
const Common::Array<Common::Rect> &rects = flc->getMskRects();
|
||||
for (uint i = 0; i < rects.size(); ++i) {
|
||||
if (_y + rects[i].bottom > _z)
|
||||
_z = _y + rects[i].bottom;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void QObject::show(bool v) {
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (flc) {
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), *flc);
|
||||
}
|
||||
QMessageObject::show(v);
|
||||
}
|
||||
|
||||
void QObject::update(int time) {
|
||||
if (!_animate || !_isShown)
|
||||
return;
|
||||
_time += time;
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (flc && flc->getFrameCount() != 1) {
|
||||
if (_sound) {
|
||||
Common::Rect bounds = flc->getBounds();
|
||||
_sound->setBalance(bounds.left + bounds.width() / 2 - g_vm->getQSystem()->_xOffset, 640);
|
||||
}
|
||||
|
||||
while (_time >= (int32)flc->getDelay()) {
|
||||
if (_sound && flc->getCurFrame() == 0) {
|
||||
_startSound = true;
|
||||
}
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), *flc);
|
||||
flc->setFrame(-1);
|
||||
if (flc->getCurFrame() == (int32)flc->getFrameCount() - 1) {
|
||||
g_vm->getQSystem()->addMessage(_id, kEnd, _resourceId, 0, 0, 0, nullptr);
|
||||
}
|
||||
if (flc->getCurFrame() + 1 == (int32)flc->getFrameCount() / 2) {
|
||||
g_vm->getQSystem()->addMessage(_id, kHalf, _resourceId, 0, 0, 0, nullptr);
|
||||
}
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), *flc);
|
||||
_time -= flc->getDelay();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QObject::setPos(Common::Point p, bool) {
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (flc) {
|
||||
g_vm->videoSystem()->addDirtyMskRects(Common::Point(_x, _y), *flc);
|
||||
g_vm->videoSystem()->addDirtyMskRects(p, *flc);
|
||||
_x = p.x;
|
||||
_y = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
void QObject::onClick(Common::Point p) {
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
QObjectCursor *cursor = g_vm->getQSystem()->getCursor();
|
||||
|
||||
sys->getPetka()->stopWalk();
|
||||
sys->getChapay()->stopWalk();
|
||||
|
||||
switch (cursor->_actionType) {
|
||||
case kActionLook:
|
||||
g_vm->getQSystem()->addMessage(_id, kLook, 0, 0, 0, 0, this);
|
||||
break;
|
||||
case kActionWalk:
|
||||
g_vm->getQSystem()->addMessage(_id, kWalk, p.x, p.y, 0, 0, this);
|
||||
break;
|
||||
case kActionUse:
|
||||
g_vm->getQSystem()->addMessage(_id, kUse, 0, 0, 0, 0, this);
|
||||
break;
|
||||
case kActionTake:
|
||||
g_vm->getQSystem()->addMessage(_id, kTake, 0, 0, 0, 0, this);
|
||||
break;
|
||||
case kActionTalk:
|
||||
g_vm->getQSystem()->addMessage(_id, kTalk, 0, 0, 0, 0, this);
|
||||
break;
|
||||
case kActionObjUseChapayev:
|
||||
g_vm->getQSystem()->addMessage(_id, kObjectUse, p.x, p.y, 0, 0, g_vm->getQSystem()->getChapay());
|
||||
break;
|
||||
case kActionObjUse:
|
||||
g_vm->getQSystem()->addMessage(_id, kObjectUse, 0, 0, 0, 0, cursor->_invObj);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QObject::onMouseMove(Common::Point p) {
|
||||
g_vm->getQSystem()->_mainInterface->_objUnderCursor = this;
|
||||
}
|
||||
|
||||
}
|
||||
117
engines/petka/objects/object.h
Normal file
117
engines/petka/objects/object.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PETKA_OBJECT_H
|
||||
#define PETKA_OBJECT_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "petka/base.h"
|
||||
|
||||
namespace Common {
|
||||
class INIFile;
|
||||
class SeekableReadStream;
|
||||
}
|
||||
|
||||
namespace Petka {
|
||||
|
||||
class QVisibleObject {
|
||||
public:
|
||||
QVisibleObject();
|
||||
virtual ~QVisibleObject() {};
|
||||
|
||||
virtual void draw() {};
|
||||
virtual void update(int time) {};
|
||||
virtual void updateZ() {};
|
||||
virtual void show(bool v) {};
|
||||
virtual void setPos(Common::Point p, bool center) {};
|
||||
virtual bool isInPoint(Common::Point p) { return false; }
|
||||
virtual void onMouseMove(Common::Point p) {}
|
||||
virtual void onClick(Common::Point p) {}
|
||||
|
||||
public:
|
||||
int32 _resourceId;
|
||||
int32 _z;
|
||||
};
|
||||
|
||||
class Sound;
|
||||
|
||||
class QMessageObject : public QVisibleObject {
|
||||
public:
|
||||
QMessageObject();
|
||||
|
||||
void show(bool v) override;
|
||||
void setReaction(int16 id, QReaction *reaction);
|
||||
virtual void processMessage(const QMessage &msg);
|
||||
void processReaction(QReaction *reaction, const QMessage *msg = nullptr);
|
||||
|
||||
virtual void play(int id, int type);
|
||||
|
||||
void loadSound();
|
||||
void removeSound();
|
||||
|
||||
void readScriptData(Common::SeekableReadStream &stream);
|
||||
virtual void readInisData(Common::INIFile &names, Common::INIFile &cast, Common::INIFile *bgs);
|
||||
|
||||
public:
|
||||
int32 _x;
|
||||
int32 _y;
|
||||
int32 _walkX;
|
||||
int32 _walkY;
|
||||
int32 _time;
|
||||
byte _frame;
|
||||
bool _isShown;
|
||||
bool _animate;
|
||||
bool _updateZ;
|
||||
bool _holdMessages;
|
||||
bool _isActive;
|
||||
bool _startSound;
|
||||
bool _loopedSound;
|
||||
Sound *_sound;
|
||||
int8 _status;
|
||||
uint16 _id;
|
||||
Common::String _name;
|
||||
Common::String _nameOnScreen;
|
||||
int32 _dialogColor;
|
||||
Common::Array<QReaction> _reactions;
|
||||
QReaction *_reaction;
|
||||
int16 _reactionId;
|
||||
};
|
||||
|
||||
|
||||
class QObject : public QMessageObject {
|
||||
public:
|
||||
QObject();
|
||||
|
||||
void draw() override;
|
||||
void update(int time) override;
|
||||
void updateZ() override;
|
||||
bool isInPoint(Common::Point p) override;
|
||||
void setPos(Common::Point p, bool center) override;
|
||||
void show(bool v) override;
|
||||
void onClick(Common::Point p) override;
|
||||
void onMouseMove(Common::Point p) override;
|
||||
};
|
||||
|
||||
} // End of namespace Petka
|
||||
|
||||
#endif
|
||||
175
engines/petka/objects/object_bg.cpp
Normal file
175
engines/petka/objects/object_bg.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/* 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 "common/formats/ini-file.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/system.h"
|
||||
#include "common/events.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "petka/flc.h"
|
||||
#include "petka/walk.h"
|
||||
#include "petka/petka.h"
|
||||
#include "petka/video.h"
|
||||
#include "petka/q_system.h"
|
||||
#include "petka/q_manager.h"
|
||||
#include "petka/interfaces/main.h"
|
||||
#include "petka/interfaces/sequence.h"
|
||||
#include "petka/objects/object_bg.h"
|
||||
#include "petka/objects/heroes.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
QObjectBG::QObjectBG() {
|
||||
_x = 0;
|
||||
_y = 0;
|
||||
_z = 0;
|
||||
|
||||
_showMap = true;
|
||||
|
||||
_fxId = 0;
|
||||
_musicId = 0;
|
||||
}
|
||||
|
||||
void QObjectBG::processMessage(const QMessage &msg) {
|
||||
QMessageObject::processMessage(msg);
|
||||
switch (msg.opcode) {
|
||||
case kSet: {
|
||||
_resourceId = msg.arg1;
|
||||
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
if (g_vm->isPetka2() && !sys->_totalInit && sys->_mainInterface->_roomId == _id) {
|
||||
auto petka = sys->getPetka();
|
||||
auto chapay = sys->getChapay();
|
||||
|
||||
auto bkgName = g_vm->resMgr()->findResourceName(_resourceId);
|
||||
|
||||
petka->_walk->setBackground(bkgName);
|
||||
chapay->_walk->setBackground(bkgName);
|
||||
|
||||
petka->setPos(Common::Point(petka->_x_, petka->_y_), false);
|
||||
chapay->setPos(Common::Point(chapay->_x_, chapay->_y_), false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kMusic:
|
||||
_musicId = msg.arg1;
|
||||
break;
|
||||
case kBGsFX:
|
||||
_fxId = msg.arg1;
|
||||
break;
|
||||
case kMap:
|
||||
_showMap = (msg.arg1 != 0);
|
||||
break;
|
||||
case kNoMap:
|
||||
_showMap = false;
|
||||
break;
|
||||
case kGoTo:
|
||||
goTo();
|
||||
break;
|
||||
case kSetSeq:
|
||||
g_vm->getQSystem()->_sequenceInterface->start(_id);
|
||||
break;
|
||||
case kEndSeq:
|
||||
g_vm->getQSystem()->_sequenceInterface->stop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QObjectBG::draw() {
|
||||
Graphics::Surface *s = g_vm->resMgr()->getSurface(_resourceId);
|
||||
if (!s)
|
||||
return;
|
||||
int xOffset = g_vm->getQSystem()->_xOffset;
|
||||
for (auto rect : g_vm->videoSystem()->rects()) {
|
||||
rect.translate(xOffset, 0);
|
||||
g_vm->videoSystem()->blitFrom(*s, rect, Common::Point(rect.left - xOffset, rect.top));
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectBG::goTo() {
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
|
||||
sys->getPetka()->stopWalk();
|
||||
sys->getChapay()->stopWalk();
|
||||
|
||||
int oldRoomId = sys->_mainInterface->_roomId;
|
||||
sys->_mainInterface->loadRoom(_id, false);
|
||||
|
||||
QMessageObject *oldRoom = sys->findObject(oldRoomId);
|
||||
|
||||
Common::ScopedPtr<Common::SeekableReadStream> bgsStream(g_vm->openFile("BGs.ini", true));
|
||||
Common::INIFile bgsIni;
|
||||
bgsIni.allowNonEnglishCharacters();
|
||||
bgsIni.loadFromStream(*bgsStream);
|
||||
|
||||
Common::String entranceName;
|
||||
if (bgsIni.getKey(oldRoom->_name, _name, entranceName)) {
|
||||
setEntrance(entranceName);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto o : sys->_allObjects) {
|
||||
QObjectBG *bg = dynamic_cast<QObjectBG *>(o);
|
||||
if (bg && bgsIni.getKey(bg->_name, _name, entranceName)) {
|
||||
setEntrance(entranceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectBG::setEntrance(const Common::String &name) {
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
QMessageObject *entrance = sys->findObject(name);
|
||||
if (entrance) {
|
||||
sys->getPetka()->_z = 0;
|
||||
sys->getChapay()->_z = 0;
|
||||
|
||||
sys->getPetka()->setPos(Common::Point(entrance->_walkX, entrance->_walkY), false);
|
||||
sys->getChapay()->setPos(Common::Point(entrance->_walkX, entrance->_walkY - 2), false);
|
||||
|
||||
sys->_xOffset = CLIP<int32>(entrance->_walkX - 320, 0, sys->_sceneWidth - 640);
|
||||
sys->_reqOffset = sys->_xOffset;
|
||||
}
|
||||
g_vm->videoSystem()->makeAllDirty();
|
||||
}
|
||||
|
||||
void QObjectBG::readInisData(Common::INIFile &names, Common::INIFile &cast, Common::INIFile *bgs) {
|
||||
if (bgs) {
|
||||
Common::String perspective;
|
||||
bgs->getKey(_name, "Settings", perspective);
|
||||
if (!perspective.empty()) {
|
||||
sscanf(perspective.c_str(), "%lf %lf %d %d %lf", &_persp.f0, &_persp.k, &_persp.y0, &_persp.y1, &_persp.f1);
|
||||
} else {
|
||||
_persp.f0 = 1.0;
|
||||
_persp.f1 = 1.0;
|
||||
_persp.k = 0.0;
|
||||
_persp.y0 = 0;
|
||||
_persp.y1 = 480;
|
||||
}
|
||||
}
|
||||
QMessageObject::readInisData(names, cast, bgs);
|
||||
}
|
||||
|
||||
} // End of namespace Petka
|
||||
60
engines/petka/objects/object_bg.h
Normal file
60
engines/petka/objects/object_bg.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PETKA_OBJECT_BG_H
|
||||
#define PETKA_OBJECT_BG_H
|
||||
|
||||
#include "petka/objects/object.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
// Linear Interpolation
|
||||
struct Perspective {
|
||||
double f0;
|
||||
double k; // seems to be (f1 - f0) always in files
|
||||
int y0;
|
||||
int y1;
|
||||
double f1;
|
||||
|
||||
Perspective() { f0 = f1 = 1.0; k = 0.0; y0 = 0; y1 = 480; }
|
||||
};
|
||||
|
||||
class QObjectBG : public QMessageObject {
|
||||
public:
|
||||
QObjectBG();
|
||||
void processMessage(const QMessage &msg) override;
|
||||
void draw() override;
|
||||
void goTo();
|
||||
void setEntrance(const Common::String &name);
|
||||
void play(int id, int type) override {}
|
||||
|
||||
void readInisData(Common::INIFile &names, Common::INIFile &cast, Common::INIFile *bgs) override;
|
||||
|
||||
public:
|
||||
bool _showMap;
|
||||
int _fxId;
|
||||
int _musicId;
|
||||
Perspective _persp;
|
||||
};
|
||||
|
||||
} // End of namespace Petka
|
||||
|
||||
#endif
|
||||
292
engines/petka/objects/object_case.cpp
Normal file
292
engines/petka/objects/object_case.cpp
Normal file
@@ -0,0 +1,292 @@
|
||||
/* 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 "common/system.h"
|
||||
|
||||
#include "petka/interfaces/main.h"
|
||||
#include "petka/objects/object_case.h"
|
||||
#include "petka/objects/object_cursor.h"
|
||||
#include "petka/flc.h"
|
||||
#include "petka/petka.h"
|
||||
#include "petka/q_manager.h"
|
||||
#include "petka/video.h"
|
||||
#include "petka/objects/heroes.h"
|
||||
#include "petka/q_system.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
// Полоска в чемодане
|
||||
const char *const kPoloska = "\xCF\xEE\xEB\xEE\xF1\xEA\xE0\x20\xE2\x20\xF7\xE5\xEC\xEE\xE4\xE0\xED\xE5";
|
||||
|
||||
const uint kCaseZ = 980;
|
||||
const uint kItemZ = kCaseZ + 1;
|
||||
const uint kPoloskaZ = kCaseZ + 2;
|
||||
|
||||
const uint kButtonsCount = 6;
|
||||
const uint kItemsOnPage = 6;
|
||||
|
||||
const uint kObjectCaseId = 4099;
|
||||
|
||||
const uint kCaseResourceId = 6000;
|
||||
const uint kFirstButtonResourceId = 6001;
|
||||
const uint kExitCaseResourceId = 6009;
|
||||
|
||||
enum {
|
||||
kChapayevButton = 0,
|
||||
kPanelButton,
|
||||
kMapButton,
|
||||
kCloseButton,
|
||||
kNextPageButton,
|
||||
kPrevPageButton,
|
||||
kInvalidButton
|
||||
};
|
||||
|
||||
QObjectCase::QObjectCase() {
|
||||
_id = kObjectCaseId;
|
||||
_resourceId = kCaseResourceId;
|
||||
|
||||
_z = kCaseZ;
|
||||
|
||||
_itemIndex = 0;
|
||||
_clickedObjIndex = kInvalidButton;
|
||||
|
||||
_isShown = false;
|
||||
_updateZ = false;
|
||||
|
||||
_itemsLocation[0] = Common::Point(120, 145);
|
||||
_itemsLocation[1] = Common::Point(240, 145);
|
||||
_itemsLocation[2] = Common::Point(360, 145);
|
||||
_itemsLocation[3] = Common::Point(100, 220);
|
||||
_itemsLocation[4] = Common::Point(240, 220);
|
||||
_itemsLocation[5] = Common::Point(380, 220);
|
||||
}
|
||||
|
||||
void QObjectCase::update(int time) {
|
||||
if (!_isShown || _clickedObjIndex == kInvalidButton)
|
||||
return;
|
||||
_time += time;
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(kFirstButtonResourceId + _clickedObjIndex);
|
||||
if (flc) {
|
||||
while (_time >= (int32)flc->getDelay()) {
|
||||
flc->setFrame(-1);
|
||||
_time -= flc->getDelay();
|
||||
g_vm->videoSystem()->addDirtyMskRects(*flc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCase::draw() {
|
||||
if (!_isShown)
|
||||
return;
|
||||
QObject::draw();
|
||||
if (_clickedObjIndex != kInvalidButton) {
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(kFirstButtonResourceId + _clickedObjIndex);
|
||||
Graphics::Surface *s = flc->getCurrentFrame()->convertTo(g_system->getScreenFormat(), flc->getPalette());
|
||||
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
|
||||
const Common::List<Common::Rect> &dirty = g_vm->videoSystem()->rects();
|
||||
const Common::Array<Common::Rect> &mskRects = flc->getMskRects();
|
||||
|
||||
for (Common::List<Common::Rect>::const_iterator it = dirty.begin(); it != dirty.end(); ++it) {
|
||||
for (uint i = 0; i < mskRects.size(); ++i) {
|
||||
Common::Rect destRect = mskRects[i].findIntersectingRect(*it);
|
||||
Common::Rect srcRect = destRect;
|
||||
srcRect.translate(-_x + sys->_xOffset, -_y);
|
||||
g_vm->videoSystem()->transBlitFrom(*s, srcRect, destRect, flc->getTransColor(s->format));
|
||||
}
|
||||
}
|
||||
|
||||
s->free();
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCase::show(bool v) {
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
_x = sys->_xOffset;
|
||||
QObject::show(v);
|
||||
if (v) {
|
||||
addItemObjects();
|
||||
|
||||
QMessageObject *obj = sys->findObject(kPoloska);
|
||||
obj->_z = kPoloskaZ;
|
||||
obj->_x = sys->_xOffset;
|
||||
|
||||
sys->_mainInterface->_objs.push_back(obj);
|
||||
} else {
|
||||
removeObjects(true);
|
||||
sys->_currInterface->_startIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool QObjectCase::isInPoint(Common::Point p) {
|
||||
return _isShown;
|
||||
}
|
||||
|
||||
void QObjectCase::onMouseMove(Common::Point p) {
|
||||
p.x -= _x;
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(kExitCaseResourceId);
|
||||
if (*(const byte *)flc->getCurrentFrame()->getBasePtr(p.x, p.y) != 0) {
|
||||
if (_clickedObjIndex != kCloseButton && _clickedObjIndex != kInvalidButton) {
|
||||
flc = g_vm->resMgr()->getFlic(kFirstButtonResourceId + _clickedObjIndex);
|
||||
flc->setFrame(1);
|
||||
g_vm->videoSystem()->addDirtyMskRects(*flc);
|
||||
}
|
||||
_clickedObjIndex = kCloseButton;
|
||||
} else {
|
||||
uint i;
|
||||
for (i = 0; i < kButtonsCount; ++i) {
|
||||
flc = g_vm->resMgr()->getFlic(kFirstButtonResourceId + i);
|
||||
if (flc->getMskRects()[0].contains(p)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_clickedObjIndex != i && _clickedObjIndex != kInvalidButton) {
|
||||
flc = g_vm->resMgr()->getFlic(kFirstButtonResourceId + _clickedObjIndex);
|
||||
flc->setFrame(1);
|
||||
g_vm->videoSystem()->addDirtyMskRects(*flc);
|
||||
}
|
||||
|
||||
if (i == kButtonsCount && _clickedObjIndex != kInvalidButton) {
|
||||
_clickedObjIndex = kInvalidButton;
|
||||
} else if (i != _clickedObjIndex) {
|
||||
if ((i != kChapayevButton || g_vm->getQSystem()->getChapay()->_isShown) && (i != kMapButton || g_vm->getQSystem()->_room->_showMap)) {
|
||||
flc = g_vm->resMgr()->getFlic(kFirstButtonResourceId + i);
|
||||
g_vm->videoSystem()->addDirtyMskRects(*flc);
|
||||
_clickedObjIndex = i;
|
||||
} else {
|
||||
_clickedObjIndex = kInvalidButton;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCase::onClick(Common::Point p) {
|
||||
switch (_clickedObjIndex) {
|
||||
case kChapayevButton:
|
||||
g_vm->getQSystem()->setCursorAction(kActionObjUseChapayev);
|
||||
break;
|
||||
case kPanelButton:
|
||||
g_vm->getQSystem()->togglePanelInterface();
|
||||
break;
|
||||
case kMapButton:
|
||||
g_vm->getQSystem()->toggleMapInterface();
|
||||
break;
|
||||
case kCloseButton:
|
||||
show(false);
|
||||
break;
|
||||
case kNextPageButton:
|
||||
nextPage();
|
||||
break;
|
||||
case kPrevPageButton:
|
||||
prevPage();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCase::addItemObjects() {
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
Common::Array<QVisibleObject *> &objs = sys->_mainInterface->_objs;
|
||||
removeObjects(false);
|
||||
|
||||
for (uint i = 0; i < objs.size(); ++i) {
|
||||
if (objs[i]->_resourceId == kCaseResourceId) {
|
||||
sys->_currInterface->_startIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
const uint size = (_itemIndex + kItemsOnPage >= _items.size()) ? _items.size() : (_itemIndex + kItemsOnPage);
|
||||
for (uint i = _itemIndex; i < size; ++i) {
|
||||
QMessageObject *obj = sys->findObject(_items[i]);
|
||||
obj->_x = sys->_xOffset + _itemsLocation[i - _itemIndex].x;
|
||||
obj->_y = _itemsLocation[i - _itemIndex].y;
|
||||
obj->_z = kItemZ;
|
||||
g_vm->resMgr()->getFlic(obj->_resourceId);
|
||||
objs.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCase::addItem(uint16 id) {
|
||||
_items.push_back(id);
|
||||
reshow();
|
||||
}
|
||||
|
||||
void QObjectCase::removeItem(uint16 id) {
|
||||
for (uint i = 0; i < _items.size(); ++i) {
|
||||
if (_items[i] == id) {
|
||||
_items.remove_at(i);
|
||||
}
|
||||
}
|
||||
|
||||
_itemIndex = (_items.size() < kItemsOnPage) ? 0 : (_items.size() - kItemsOnPage);
|
||||
|
||||
reshow();
|
||||
}
|
||||
|
||||
void QObjectCase::transformItem(uint16 oldItem, uint16 newItem) {
|
||||
for (uint i = 0; i < _items.size(); ++i) {
|
||||
if (_items[i] == oldItem) {
|
||||
_items[i] = newItem;
|
||||
}
|
||||
}
|
||||
|
||||
reshow();
|
||||
}
|
||||
|
||||
void QObjectCase::nextPage() {
|
||||
if (_items.size() > _itemIndex + kItemsOnPage) {
|
||||
_itemIndex += kItemsOnPage;
|
||||
addItemObjects();
|
||||
g_vm->videoSystem()->makeAllDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCase::prevPage() {
|
||||
if (_itemIndex > 0) {
|
||||
_itemIndex = (_itemIndex <= kItemsOnPage) ? 0 : _itemIndex - kItemsOnPage;
|
||||
addItemObjects();
|
||||
g_vm->videoSystem()->makeAllDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCase::removeObjects(bool removePoloska) {
|
||||
Common::Array<QVisibleObject *> &objs = g_vm->getQSystem()->_mainInterface->_objs;
|
||||
for (uint i = 0; i < objs.size();) {
|
||||
if (objs[i]->_z == kItemZ || (removePoloska && objs[i]->_z == kPoloskaZ)) {
|
||||
objs.remove_at(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCase::reshow() {
|
||||
if (_isShown) {
|
||||
show(false);
|
||||
show(true);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Petka
|
||||
61
engines/petka/objects/object_case.h
Normal file
61
engines/petka/objects/object_case.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PETKA_OBJECT_CASE_H
|
||||
#define PETKA_OBJECT_CASE_H
|
||||
|
||||
#include "petka/objects/object.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
class QObjectCase : public QObject {
|
||||
public:
|
||||
QObjectCase();
|
||||
void draw() override;
|
||||
void update(int time) override;
|
||||
void show(bool v) override;
|
||||
bool isInPoint(Common::Point p) override;
|
||||
void onMouseMove(Common::Point p) override;
|
||||
void onClick(Common::Point p) override;
|
||||
|
||||
void addItem(uint16 id);
|
||||
void removeItem(uint16 id);
|
||||
void transformItem(uint16 oldItem, uint16 newItem);
|
||||
|
||||
private:
|
||||
void reshow();
|
||||
|
||||
void nextPage();
|
||||
void prevPage();
|
||||
|
||||
void addItemObjects();
|
||||
void removeObjects(bool removePoloska);
|
||||
|
||||
public:
|
||||
Common::Array<uint16> _items;
|
||||
Common::Point _itemsLocation[6];
|
||||
uint _clickedObjIndex;
|
||||
uint _itemIndex;
|
||||
};
|
||||
|
||||
} // End of namespace Petka
|
||||
|
||||
#endif
|
||||
145
engines/petka/objects/object_cursor.cpp
Normal file
145
engines/petka/objects/object_cursor.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/* 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 "common/formats/ini-file.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/system.h"
|
||||
#include "common/events.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "petka/flc.h"
|
||||
#include "petka/petka.h"
|
||||
#include "petka/video.h"
|
||||
#include "petka/q_system.h"
|
||||
#include "petka/q_manager.h"
|
||||
#include "petka/objects/object_cursor.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
const int kCursorLook = 5002;
|
||||
|
||||
QObjectCursor::QObjectCursor() {
|
||||
_id = 4097;
|
||||
_z = 1000;
|
||||
_resourceId = kCursorLook;
|
||||
Common::Point pos = g_vm->getEventManager()->getMousePos();
|
||||
_x = pos.x;
|
||||
_y = pos.y;
|
||||
g_vm->resMgr()->getFlic(kCursorLook);
|
||||
_actionType = kActionLook;
|
||||
_invObj = nullptr;
|
||||
_name = "Cursor";
|
||||
}
|
||||
|
||||
void QObjectCursor::draw() {
|
||||
if (!_isShown) {
|
||||
return;
|
||||
}
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
const Graphics::Surface *frame = flc->getCurrentFrame();
|
||||
if (frame) {
|
||||
Graphics::Surface *s = frame->convertTo(g_system->getScreenFormat(), flc->getPalette());
|
||||
Common::Rect destRect(flc->getBounds());
|
||||
destRect.translate(_x, _y);
|
||||
destRect.clip(640, 480);
|
||||
|
||||
Common::Rect srcRect(destRect);
|
||||
srcRect.translate(-_x, -_y);
|
||||
|
||||
g_vm->videoSystem()->transBlitFrom(*s, srcRect, destRect, flc->getTransColor(s->format));
|
||||
s->free();
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCursor::update(int time) {
|
||||
if (!_isShown || !_animate)
|
||||
return;
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
_time += time;
|
||||
while (flc && _time >= (int32)flc->getDelay()) {
|
||||
flc->setFrame(-1);
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), flc->getBounds());
|
||||
_time -= flc->getDelay();
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCursor::setPos(Common::Point p, bool center) {
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (!_animate) {
|
||||
flc->setFrame(1);
|
||||
}
|
||||
|
||||
p.x = p.x - g_vm->getQSystem()->_xOffset;
|
||||
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), flc->getBounds());
|
||||
|
||||
if (center) {
|
||||
Common::Rect bounds = flc->getBounds();
|
||||
p.x = p.x - bounds.left - bounds.width() / 2;
|
||||
p.y = p.y - bounds.top - bounds.height() / 2;
|
||||
}
|
||||
|
||||
_x = p.x;
|
||||
_y = p.y;
|
||||
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), flc->getBounds());
|
||||
}
|
||||
|
||||
void QObjectCursor::show(bool v) {
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), flc->getBounds());
|
||||
QMessageObject::show(v);
|
||||
}
|
||||
|
||||
void QObjectCursor::returnInvItem() {
|
||||
if (_actionType == kActionObjUse) {
|
||||
_invObj->show(true);
|
||||
_invObj->_isActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCursor::setInvItem(QMessageObject *item, uint16 resourceId) {
|
||||
returnInvItem();
|
||||
if (resourceId != 0xffff) {
|
||||
_resourceId = resourceId;
|
||||
_actionType = kActionObjUse;
|
||||
_invObj = item;
|
||||
item->_isShown = false;
|
||||
item->_isActive = false;
|
||||
} else {
|
||||
_resourceId = kCursorLook;
|
||||
_actionType = kActionLook;
|
||||
_invObj = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectCursor::setAction(int actionType) {
|
||||
show(false);
|
||||
returnInvItem();
|
||||
_resourceId = kCursorLook + actionType;
|
||||
_actionType = actionType;
|
||||
_invObj = nullptr;
|
||||
show(true);
|
||||
}
|
||||
|
||||
}
|
||||
59
engines/petka/objects/object_cursor.h
Normal file
59
engines/petka/objects/object_cursor.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PETKA_OBJECT_CURSOR_H
|
||||
#define PETKA_OBJECT_CURSOR_H
|
||||
|
||||
#include "petka/objects/object.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
enum ActionType {
|
||||
kActionLook,
|
||||
kActionWalk,
|
||||
kActionUse,
|
||||
kActionTake,
|
||||
kActionTalk,
|
||||
kActionObjUseChapayev,
|
||||
kActionObjUse
|
||||
};
|
||||
|
||||
class QObjectCursor : public QMessageObject {
|
||||
public:
|
||||
QObjectCursor();
|
||||
|
||||
void setPos(Common::Point p, bool center) override;
|
||||
void update(int time) override;
|
||||
void draw() override;
|
||||
void show(bool v) override;
|
||||
bool isInPoint(Common::Point p) override { return false; }
|
||||
void setAction(int actionType);
|
||||
void setInvItem(QMessageObject *item, uint16 resourceId);
|
||||
void returnInvItem();
|
||||
|
||||
public:
|
||||
int _actionType;
|
||||
QMessageObject *_invObj;
|
||||
};
|
||||
|
||||
} // End of namespace Petka
|
||||
|
||||
#endif
|
||||
100
engines/petka/objects/object_star.cpp
Normal file
100
engines/petka/objects/object_star.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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 "common/rect.h"
|
||||
|
||||
#include "petka/objects/object_case.h"
|
||||
#include "petka/objects/object_cursor.h"
|
||||
#include "petka/objects/object_star.h"
|
||||
#include "petka/q_system.h"
|
||||
#include "petka/flc.h"
|
||||
#include "petka/q_manager.h"
|
||||
#include "petka/video.h"
|
||||
#include "petka/petka.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
//const uint kFirstCursorId = 5001;
|
||||
const uint kCaseButtonIndex = 0;
|
||||
|
||||
QObjectStar::QObjectStar() {
|
||||
_isShown = false;
|
||||
_id = 4098;
|
||||
_resourceId = 5000;
|
||||
_z = 999;
|
||||
_updateZ = false;
|
||||
_isActive = true;
|
||||
|
||||
_buttonRects[0] = Common::Rect(70, 74, 112, 112);
|
||||
_buttonRects[1] = Common::Rect(68, 0, 114, 41);
|
||||
_buttonRects[2] = Common::Rect(151, 51, 180, 97);
|
||||
_buttonRects[3] = Common::Rect(138, 125, 179, 166);
|
||||
_buttonRects[4] = Common::Rect(55, 145, 96, 175);
|
||||
_buttonRects[5] = Common::Rect(11, 79, 40, 118);
|
||||
}
|
||||
|
||||
bool QObjectStar::isInPoint(Common::Point p) {
|
||||
return _isShown;
|
||||
}
|
||||
|
||||
void QObjectStar::onMouseMove(Common::Point p) {
|
||||
uint frame = (findButtonIndex(p.x - _x, p.y - _y) + 1) % 7 + 1;
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
if (flc && flc->getCurFrame() + 1 != (int32)frame) {
|
||||
g_vm->videoSystem()->addDirtyRect(Common::Point(_x, _y), *flc);
|
||||
flc->setFrame(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void QObjectStar::onClick(Common::Point p) {
|
||||
uint button = findButtonIndex(p.x - _x, p.y - _y);
|
||||
if (button == kCaseButtonIndex) {
|
||||
g_vm->getQSystem()->getCase()->show(true);
|
||||
} else if (button < ARRAYSIZE(_buttonRects)) {
|
||||
QObjectCursor *cursor = g_vm->getQSystem()->getCursor();
|
||||
cursor->setAction(button - 1);
|
||||
}
|
||||
show(false);
|
||||
}
|
||||
|
||||
uint QObjectStar::findButtonIndex(int16 x, int16 y) const {
|
||||
uint i = 0;
|
||||
for (i = 0; i < ARRAYSIZE(_buttonRects); ++i) {
|
||||
if (_buttonRects[i].contains(x, y))
|
||||
return i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void QObjectStar::setPos(Common::Point p, bool) {
|
||||
if (!_isShown) {
|
||||
QSystem *sys = g_vm->getQSystem();
|
||||
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(_resourceId);
|
||||
p.x = MAX<int16>(p.x - sys->_xOffset - flc->getWidth() / 2, 0);
|
||||
p.y = MAX<int16>(p.y - flc->getHeight() / 2, 0);
|
||||
|
||||
_x = MIN<int16>(p.x, 639 - flc->getWidth()) + sys->_xOffset;
|
||||
_y = MIN<int16>(p.y, 479 - flc->getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
47
engines/petka/objects/object_star.h
Normal file
47
engines/petka/objects/object_star.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PETKA_OBJECT_STAR_H
|
||||
#define PETKA_OBJECT_STAR_H
|
||||
|
||||
#include "petka/objects/object.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
class QObjectStar : public QObject {
|
||||
public:
|
||||
QObjectStar();
|
||||
void update(int time) override {}
|
||||
bool isInPoint(Common::Point p) override;
|
||||
void onMouseMove(Common::Point p) override;
|
||||
void onClick(Common::Point p) override;
|
||||
void setPos(Common::Point p, bool center) override;
|
||||
|
||||
private:
|
||||
uint findButtonIndex(int16 x, int16 y) const;
|
||||
|
||||
private:
|
||||
Common::Rect _buttonRects[6];
|
||||
};
|
||||
|
||||
} // End of namespace Petka
|
||||
|
||||
#endif
|
||||
270
engines/petka/objects/text.cpp
Normal file
270
engines/petka/objects/text.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/* 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 "graphics/fonts/ttf.h"
|
||||
#include "graphics/fontman.h"
|
||||
|
||||
#include "petka/q_manager.h"
|
||||
#include "petka/petka.h"
|
||||
#include "petka/video.h"
|
||||
#include "petka/objects/text.h"
|
||||
#include "petka/q_system.h"
|
||||
#include "petka/interfaces/panel.h"
|
||||
#include "petka/sound.h"
|
||||
#include "petka/interfaces/main.h"
|
||||
#include "petka/flc.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
QText::QText(const Common::U32String &text, uint16 textColor, uint16 outlineColor) {
|
||||
_resourceId = -2;
|
||||
_z = 3000;
|
||||
|
||||
auto *font = g_vm->getTextFont();
|
||||
|
||||
Common::Rect rect = calculateBoundingBoxForText(text, *font);
|
||||
rect.right += 10;
|
||||
rect.bottom += 4;
|
||||
|
||||
_rect = Common::Rect((640 - rect.width()) / 2, 479 - rect.height(), 639 - (640 - rect.width()) / 2, 479);
|
||||
Graphics::Surface *s = g_vm->resMgr()->getSurface((uint32)-2, rect.width(), rect.height());
|
||||
|
||||
drawText(*s, 0, 630, text, textColor, *font, Graphics::kTextAlignCenter);
|
||||
drawOutline(s, outlineColor);
|
||||
}
|
||||
|
||||
void QText::draw() {
|
||||
const Graphics::Surface *s = g_vm->resMgr()->getSurface((uint32)-2);
|
||||
if (s) {
|
||||
g_vm->videoSystem()->transBlitFrom(*s, Common::Point((640 - s->w) / 2, 479 - s->h));
|
||||
}
|
||||
}
|
||||
|
||||
const Common::Rect &QText::getRect() {
|
||||
return _rect;
|
||||
}
|
||||
|
||||
void QText::drawOutline(Graphics::Surface *s, uint16 color) {
|
||||
for (int y = 0; y < s->h; ++y) {
|
||||
for (int x = 1; x < s->w - 1; ++x) {
|
||||
uint16 *pixel = (uint16 *)s->getBasePtr(x, y);
|
||||
if (*pixel && *pixel != color) {
|
||||
if (!pixel[-1])
|
||||
pixel[-1] = (uint16)color;
|
||||
if (!pixel[1])
|
||||
pixel[1] = (uint16)color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < s->w; ++x) {
|
||||
for (int y = 0; y < s->h - 1; ++y) {
|
||||
uint16 *pixel = (uint16 *)s->getBasePtr(x, y);
|
||||
if (*pixel && *pixel != color) {
|
||||
pixel = (uint16 *)s->getBasePtr(x, y - 1);
|
||||
if (*pixel == 0)
|
||||
*pixel = color;
|
||||
pixel = (uint16 *)s->getBasePtr(x, y + 1);
|
||||
if (*pixel == 0)
|
||||
*pixel = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QText::QText() {
|
||||
_resourceId = -2;
|
||||
_z = 3000;
|
||||
}
|
||||
|
||||
void QText::update(int) {
|
||||
g_vm->videoSystem()->addDirtyRect(_rect);
|
||||
}
|
||||
|
||||
QTextPhrase::QTextPhrase(const Common::U32String &text, uint16 textColor, uint16 outlineColor)
|
||||
: QText(text, textColor, outlineColor), _phrase(text), _time(0) {}
|
||||
|
||||
void QTextPhrase::draw() {
|
||||
if (g_vm->getQSystem()->_panelInterface->showSubtitles()) {
|
||||
QText::draw();
|
||||
}
|
||||
}
|
||||
|
||||
void QTextPhrase::update(int time) {
|
||||
DialogInterface &dialog = g_vm->getQSystem()->_mainInterface->_dialog;
|
||||
_time += time;
|
||||
QText::update(time);
|
||||
Sound *sound = dialog.findSound();
|
||||
if (sound) {
|
||||
if (!sound->isPlaying()) {
|
||||
_time = 0;
|
||||
dialog.next(-1);
|
||||
}
|
||||
} else if (_time > _phrase.size() * 30 + 1000 || !g_vm->getQSystem()->_panelInterface->showSubtitles()) {
|
||||
_time = 0;
|
||||
dialog.next(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void QTextPhrase::onClick(Common::Point p) {
|
||||
DialogInterface &dialog = g_vm->getQSystem()->_mainInterface->_dialog;
|
||||
dialog.next(-1);
|
||||
}
|
||||
|
||||
QTextDescription::QTextDescription(const Common::U32String &desc, uint32 frame) {
|
||||
_z = 999;
|
||||
_resourceId = -2;
|
||||
_rect = Common::Rect(0, 0, 640, 480);
|
||||
|
||||
FlicDecoder *flc = g_vm->resMgr()->getFlic(6008);
|
||||
flc->setFrame(frame);
|
||||
|
||||
const Graphics::Surface *frameS = flc->getCurrentFrame();
|
||||
Graphics::Surface *s = g_vm->resMgr()->getSurface((uint32)-2, 640, 480);
|
||||
|
||||
Graphics::Surface *convS = frameS->convertTo(s->format, flc->getPalette());
|
||||
s->copyRectToSurface(*convS, 0, 0, _rect);
|
||||
convS->free();
|
||||
delete convS;
|
||||
|
||||
Common::Rect textArea(160, 275, 598, 376);
|
||||
auto *font = g_vm->getDescriptionFont();
|
||||
auto textSurface = s->getSubArea(textArea);
|
||||
|
||||
drawText(textSurface, 0, textArea.width(), desc, 0, *font, Graphics::kTextAlignLeft);
|
||||
|
||||
g_vm->videoSystem()->addDirtyRect(_rect);
|
||||
}
|
||||
|
||||
void QTextDescription::onClick(Common::Point p) {
|
||||
g_vm->getQSystem()->_mainInterface->removeTextDescription();
|
||||
}
|
||||
|
||||
void QTextDescription::draw() {
|
||||
QManager *resMgr = g_vm->resMgr();
|
||||
VideoSystem *videoSys = g_vm->videoSystem();
|
||||
Graphics::Surface *s = resMgr->getSurface((uint32)-2);
|
||||
FlicDecoder *flc = resMgr->getFlic(6008);
|
||||
|
||||
for (auto &dirty : videoSys->rects()) {
|
||||
videoSys->transBlitFrom(*s, dirty, dirty, flc->getTransColor(s->format));
|
||||
}
|
||||
}
|
||||
|
||||
QTextChoice::QTextChoice(const Common::Array<Common::U32String> &choices, uint16 color, uint16 outlineColor, uint16 selectedColor) {
|
||||
_activeChoice = 0;
|
||||
_choiceColor = color;
|
||||
_outlineColor = outlineColor;
|
||||
_selectedColor = selectedColor;
|
||||
_choices = choices;
|
||||
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
|
||||
auto *font = g_vm->getTextFont();
|
||||
|
||||
_rects.resize(choices.size());
|
||||
for (uint i = 0; i < _choices.size(); ++i) {
|
||||
_rects[i] = calculateBoundingBoxForText(_choices[i], *font);
|
||||
w = MAX<int>(w, _rects[i].width());
|
||||
_rects[i].setWidth(w);
|
||||
_rects[i].setHeight(font->getFontHeight());
|
||||
h += font->getFontHeight();
|
||||
}
|
||||
|
||||
w += 10;
|
||||
h += 4;
|
||||
|
||||
_rect = Common::Rect((640 - w) / 2, 479 - h, 639 - (640 - w) / 2, 479);
|
||||
|
||||
Graphics::Surface *s = g_vm->resMgr()->getSurface((uint32)-2, w, h);
|
||||
|
||||
int y = 0;
|
||||
for (uint i = 0; i < _choices.size(); ++i) {
|
||||
drawText(*s, y, 630, _choices[i], _choiceColor, *font, Graphics::TextAlign::kTextAlignLeft);
|
||||
|
||||
_rects[i].moveTo(0, y);
|
||||
y += font->getFontHeight();
|
||||
}
|
||||
drawOutline(s, outlineColor);
|
||||
}
|
||||
|
||||
void QTextChoice::onMouseMove(Common::Point p) {
|
||||
p.x = p.x - _rect.left - g_vm->getQSystem()->_xOffset;
|
||||
p.y = p.y - _rect.top;
|
||||
uint newChoice;
|
||||
for (newChoice = 0; newChoice < _rects.size(); ++newChoice) {
|
||||
if (_rects[newChoice].contains(p)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newChoice != _activeChoice) {
|
||||
Graphics::Surface *s = g_vm->resMgr()->getSurface((uint32)-2);
|
||||
auto *font = g_vm->getTextFont();
|
||||
|
||||
s->fillRect(Common::Rect(s->w, s->h), 0);
|
||||
for (uint i = 0; i < _choices.size(); ++i) {
|
||||
uint color = (i == newChoice) ? _selectedColor : _choiceColor;
|
||||
drawText(*s, _rects[i].top, 630, _choices[i], color, *font, Graphics::kTextAlignLeft);
|
||||
}
|
||||
drawOutline(s, _outlineColor);
|
||||
_activeChoice = newChoice;
|
||||
}
|
||||
}
|
||||
|
||||
void QTextChoice::onClick(Common::Point p) {
|
||||
if (_activeChoice < _choices.size()) {
|
||||
g_vm->getQSystem()->_mainInterface->_dialog.next(_activeChoice);
|
||||
}
|
||||
}
|
||||
|
||||
Common::Rect QText::calculateBoundingBoxForText(const Common::U32String &text, Graphics::Font &font) {
|
||||
if (text.empty())
|
||||
return {};
|
||||
|
||||
Common::Array<Common::U32String> lines;
|
||||
font.wordWrapText(text, 630, lines);
|
||||
|
||||
Common::Rect rect = font.getBoundingBox(lines[0]);
|
||||
rect.setHeight(font.getFontHeight());
|
||||
for (uint j = 1; j < lines.size(); ++j) {
|
||||
auto box = font.getBoundingBox(lines[j]);
|
||||
rect.setHeight(rect.height() + font.getFontHeight());
|
||||
if (box.width() > rect.width())
|
||||
rect.setWidth(box.width());
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
void QText::drawText(Graphics::Surface &s, int y, int maxWidth, const Common::U32String &text, uint color, Graphics::Font &font, Graphics::TextAlign alignment) {
|
||||
Common::Array<Common::U32String> lines;
|
||||
font.wordWrapText(text, maxWidth, lines);
|
||||
|
||||
int h = 0;
|
||||
for (uint i = 0; i < lines.size(); ++i) {
|
||||
font.drawString(&s, lines[i], 0, y + h, s.w, color, alignment);
|
||||
h += font.getFontHeight();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Petka
|
||||
97
engines/petka/objects/text.h
Normal file
97
engines/petka/objects/text.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PETKA_TEXT_H
|
||||
#define PETKA_TEXT_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/ustr.h"
|
||||
#include "common/str-array.h"
|
||||
|
||||
#include "graphics/font.h"
|
||||
|
||||
#include "petka/objects/object.h"
|
||||
|
||||
namespace Petka {
|
||||
|
||||
class QText : public QVisibleObject {
|
||||
public:
|
||||
QText(const Common::U32String &text, uint16 textColor, uint16 outlineColor);
|
||||
|
||||
void draw();
|
||||
void update(int time);
|
||||
const Common::Rect &getRect();
|
||||
|
||||
protected:
|
||||
QText();
|
||||
|
||||
static void drawOutline(Graphics::Surface *surface, uint16 color);
|
||||
static Common::Rect calculateBoundingBoxForText(const Common::U32String &text, Graphics::Font &font);
|
||||
static void drawText(Graphics::Surface &s, int y, int maxWidth, const Common::U32String &text, uint color, Graphics::Font &font, Graphics::TextAlign alignment);
|
||||
|
||||
protected:
|
||||
Common::Rect _rect;
|
||||
};
|
||||
|
||||
class QTextPhrase : public QText {
|
||||
public:
|
||||
QTextPhrase(const Common::U32String &phrase, uint16 textColor, uint16 outlineColor);
|
||||
|
||||
void draw() override;
|
||||
void update(int time) override;
|
||||
void onClick(Common::Point p) override;
|
||||
bool isInPoint(Common::Point p) override { return true; }
|
||||
|
||||
private:
|
||||
Common::U32String _phrase;
|
||||
uint _time;
|
||||
};
|
||||
|
||||
class QTextDescription : public QText {
|
||||
public:
|
||||
QTextDescription(const Common::U32String &desc, uint32 frame);
|
||||
|
||||
void draw() override;
|
||||
void onClick(Common::Point p) override;
|
||||
bool isInPoint(Common::Point p) override { return true; }
|
||||
void update(int t) override {}
|
||||
};
|
||||
|
||||
class QTextChoice : public QText {
|
||||
public:
|
||||
QTextChoice(const Common::Array<Common::U32String> &choices, uint16 color, uint16 outlineColor, uint16 selectedColor);
|
||||
|
||||
void onMouseMove(Common::Point p) override;
|
||||
void onClick(Common::Point p) override;
|
||||
bool isInPoint(Common::Point p) override { return true; }
|
||||
|
||||
private:
|
||||
Common::Array<Common::Rect> _rects;
|
||||
Common::Array<Common::U32String> _choices;
|
||||
uint _activeChoice;
|
||||
uint16 _outlineColor;
|
||||
uint16 _choiceColor;
|
||||
uint16 _selectedColor;
|
||||
};
|
||||
|
||||
} // End of namespace Petka
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user