606 lines
16 KiB
C++
606 lines
16 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 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 ALCACHOFA_OBJECTS_H
|
|
#define ALCACHOFA_OBJECTS_H
|
|
|
|
#include "alcachofa/shape.h"
|
|
#include "alcachofa/graphics.h"
|
|
|
|
#include "common/serializer.h"
|
|
|
|
namespace Alcachofa {
|
|
|
|
class Room;
|
|
class Process;
|
|
struct Task;
|
|
|
|
class ObjectBase {
|
|
public:
|
|
static constexpr const char *kClassName = "CObjetoBase";
|
|
ObjectBase(Room *room, const char *name);
|
|
ObjectBase(Room *room, Common::ReadStream &stream);
|
|
virtual ~ObjectBase() {}
|
|
|
|
inline const Common::String &name() const { return _name; }
|
|
inline Room *&room() { return _room; }
|
|
inline Room *room() const { return _room; }
|
|
inline bool isEnabled() const { return _isEnabled; }
|
|
|
|
virtual void toggle(bool isEnabled);
|
|
virtual void draw();
|
|
virtual void drawDebug();
|
|
virtual void update();
|
|
virtual void loadResources();
|
|
virtual void freeResources();
|
|
virtual void syncGame(Common::Serializer &serializer);
|
|
virtual Graphic *graphic();
|
|
virtual Shape *shape();
|
|
virtual const char *typeName() const;
|
|
|
|
private:
|
|
Common::String _name;
|
|
bool _isEnabled = true;
|
|
Room *_room = nullptr;
|
|
};
|
|
|
|
class PointObject : public ObjectBase {
|
|
public:
|
|
static constexpr const char *kClassName = "CObjetoPunto";
|
|
PointObject(Room *room, Common::ReadStream &stream);
|
|
|
|
inline Common::Point &position() { return _pos; }
|
|
inline Common::Point position() const { return _pos; }
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
Common::Point _pos;
|
|
};
|
|
|
|
enum class GraphicObjectType : byte
|
|
{
|
|
Normal,
|
|
NormalPosterize, // the posterization is not actually applied in the original engine
|
|
Effect
|
|
};
|
|
|
|
class GraphicObject : public ObjectBase {
|
|
public:
|
|
static constexpr const char *kClassName = "CObjetoGrafico";
|
|
GraphicObject(Room *room, Common::ReadStream &stream);
|
|
~GraphicObject() override {}
|
|
|
|
void draw() override;
|
|
void drawDebug() override;
|
|
void loadResources() override;
|
|
void freeResources() override;
|
|
void syncGame(Common::Serializer &serializer) override;
|
|
Graphic *graphic() override;
|
|
const char *typeName() const override;
|
|
|
|
Task *animate(Process &process);
|
|
|
|
protected:
|
|
GraphicObject(Room *room, const char *name);
|
|
|
|
Graphic _graphic;
|
|
GraphicObjectType _type;
|
|
int32 _posterizeAlpha;
|
|
};
|
|
|
|
class SpecialEffectObject final : public GraphicObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CObjetoGraficoMuare";
|
|
SpecialEffectObject(Room *room, Common::ReadStream &stream);
|
|
|
|
void draw() override;
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
static constexpr const float kShiftSpeed = 1 / 256.0f;
|
|
Common::Point _topLeft, _bottomRight;
|
|
Math::Vector2d _texShift;
|
|
};
|
|
|
|
class ShapeObject : public ObjectBase {
|
|
public:
|
|
ShapeObject(Room *room, Common::ReadStream &stream);
|
|
~ShapeObject() override {}
|
|
|
|
inline int8 order() const { return _order; }
|
|
inline bool isNewlySelected() const { return _isNewlySelected; }
|
|
inline bool wasSelected() const { return _wasSelected; }
|
|
|
|
void update() override;
|
|
void syncGame(Common::Serializer &serializer) override;
|
|
Shape *shape() override;
|
|
virtual CursorType cursorType() const;
|
|
virtual void onHoverStart();
|
|
virtual void onHoverEnd();
|
|
virtual void onHoverUpdate();
|
|
virtual void onClick();
|
|
const char *typeName() const override;
|
|
void markSelected();
|
|
|
|
protected:
|
|
void updateSelection();
|
|
|
|
// original inconsistency: base class has member that is read by the sub classes
|
|
int8 _order = 0;
|
|
private:
|
|
Shape _shape;
|
|
CursorType _cursorType;
|
|
bool _isNewlySelected = false,
|
|
_wasSelected = false;
|
|
};
|
|
|
|
class PhysicalObject : public ShapeObject {
|
|
public:
|
|
PhysicalObject(Room *room, Common::ReadStream &stream);
|
|
const char *typeName() const override;
|
|
};
|
|
|
|
class MenuButton : public PhysicalObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CBotonMenu";
|
|
MenuButton(Room *room, Common::ReadStream &stream);
|
|
~MenuButton() override {}
|
|
|
|
inline int32 actionId() const { return _actionId; }
|
|
inline bool &isInteractable() { return _isInteractable; }
|
|
|
|
void draw() override;
|
|
void update() override;
|
|
void loadResources() override;
|
|
void freeResources() override;
|
|
void onHoverUpdate() override;
|
|
void onClick() override;
|
|
virtual void trigger();
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
bool
|
|
_isInteractable = true,
|
|
_isClicked = false,
|
|
_triggerNextFrame = false;
|
|
int32 _actionId;
|
|
Graphic
|
|
_graphicNormal,
|
|
_graphicHovered,
|
|
_graphicClicked,
|
|
_graphicDisabled;
|
|
FakeLock _interactionLock;
|
|
};
|
|
|
|
// some of the UI elements are only used for the multiplayer menus
|
|
// so are currently not needed
|
|
|
|
class InternetMenuButton final : public MenuButton {
|
|
public:
|
|
static constexpr const char *kClassName = "CBotonMenuInternet";
|
|
InternetMenuButton(Room *room, Common::ReadStream &stream);
|
|
|
|
const char *typeName() const override;
|
|
};
|
|
|
|
class OptionsMenuButton final : public MenuButton {
|
|
public:
|
|
static constexpr const char *kClassName = "CBotonMenuOpciones";
|
|
OptionsMenuButton(Room *room, Common::ReadStream &stream);
|
|
|
|
void update() override;
|
|
void trigger() override;
|
|
const char *typeName() const override;
|
|
};
|
|
|
|
class MainMenuButton final : public MenuButton {
|
|
public:
|
|
static constexpr const char *kClassName = "CBotonMenuPrincipal";
|
|
MainMenuButton(Room *room, Common::ReadStream &stream);
|
|
|
|
void update() override;
|
|
void trigger() override;
|
|
const char *typeName() const override;
|
|
};
|
|
|
|
class PushButton final : public PhysicalObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CPushButton";
|
|
PushButton(Room *room, Common::ReadStream &stream);
|
|
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
bool _alwaysVisible;
|
|
Graphic _graphic1, _graphic2;
|
|
int32 _actionId;
|
|
};
|
|
|
|
class EditBox final : public PhysicalObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CEditBox";
|
|
EditBox(Room *room, Common::ReadStream &stream);
|
|
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
int32 i1;
|
|
Common::Point p1;
|
|
Common::String _labelId;
|
|
bool b1;
|
|
int32 i3, i4, i5,
|
|
_fontId;
|
|
};
|
|
|
|
class CheckBox : public PhysicalObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CCheckBox";
|
|
CheckBox(Room *room, Common::ReadStream &stream);
|
|
~CheckBox() override {}
|
|
|
|
inline bool &isChecked() { return _isChecked; }
|
|
inline int32 actionId() const { return _actionId; }
|
|
|
|
void draw() override;
|
|
void update() override;
|
|
void loadResources() override;
|
|
void freeResources() override;
|
|
void onHoverUpdate() override;
|
|
void onClick() override;
|
|
virtual void trigger();
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
bool
|
|
_isChecked = false,
|
|
_wasClicked = false;
|
|
Graphic
|
|
_graphicUnchecked,
|
|
_graphicChecked,
|
|
_graphicHovered,
|
|
_graphicClicked;
|
|
int32 _actionId = 0;
|
|
uint32 _clickTime = 0;
|
|
};
|
|
|
|
class SlideButton final : public ObjectBase {
|
|
public:
|
|
static constexpr const char *kClassName = "CSlideButton";
|
|
SlideButton(Room *room, Common::ReadStream &stream);
|
|
~SlideButton() override {}
|
|
|
|
inline float &value() { return _value; }
|
|
|
|
void draw() override;
|
|
void update() override;
|
|
void loadResources() override;
|
|
void freeResources() override;
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
bool isMouseOver() const;
|
|
|
|
float _value = 0;
|
|
int32 _valueId;
|
|
Common::Point _minPos, _maxPos;
|
|
Graphic
|
|
_graphicIdle,
|
|
_graphicHovered,
|
|
_graphicClicked;
|
|
};
|
|
|
|
class CheckBoxAutoAdjustNoise final : public CheckBox {
|
|
public:
|
|
static constexpr const char *kClassName = "CCheckBoxAutoAjustarRuido";
|
|
CheckBoxAutoAdjustNoise(Room *room, Common::ReadStream &stream);
|
|
|
|
const char *typeName() const override;
|
|
};
|
|
|
|
class IRCWindow final : public ObjectBase {
|
|
public:
|
|
static constexpr const char *kClassName = "CVentanaIRC";
|
|
IRCWindow(Room *room, Common::ReadStream &stream);
|
|
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
Common::Point _p1, _p2;
|
|
};
|
|
|
|
class MessageBox final : public ObjectBase {
|
|
public:
|
|
static constexpr const char *kClassName = "CMessageBox";
|
|
MessageBox(Room *room, Common::ReadStream &stream);
|
|
~MessageBox() override {}
|
|
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
Graphic
|
|
_graph1,
|
|
_graph2,
|
|
_graph3,
|
|
_graph4,
|
|
_graph5;
|
|
};
|
|
|
|
class VoiceMeter final : public GraphicObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CVuMeter";
|
|
VoiceMeter(Room *room, Common::ReadStream &stream);
|
|
|
|
const char *typeName() const override;
|
|
};
|
|
|
|
class Item : public GraphicObject { //-V690
|
|
public:
|
|
static constexpr const char *kClassName = "CObjetoInventario";
|
|
Item(Room *room, Common::ReadStream &stream);
|
|
Item(const Item &other);
|
|
// no copy-assign operator as it is non-sensical, the copy ctor is a special case for item-handling
|
|
|
|
void draw() override;
|
|
const char *typeName() const override;
|
|
void trigger();
|
|
};
|
|
|
|
class ITriggerableObject {
|
|
public:
|
|
ITriggerableObject(Common::ReadStream &stream);
|
|
virtual ~ITriggerableObject() {}
|
|
|
|
inline Direction interactionDirection() const { return _interactionDirection; }
|
|
inline Common::Point interactionPoint() const { return _interactionPoint; }
|
|
|
|
virtual void trigger(const char *action) = 0;
|
|
|
|
protected:
|
|
void onClick();
|
|
|
|
Common::Point _interactionPoint;
|
|
Direction _interactionDirection = Direction::Right;
|
|
};
|
|
|
|
class InteractableObject : public PhysicalObject, public ITriggerableObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CObjetoTipico";
|
|
InteractableObject(Room *room, Common::ReadStream &stream);
|
|
~InteractableObject() override {}
|
|
|
|
void drawDebug() override;
|
|
void onClick() override;
|
|
void trigger(const char *action) override;
|
|
void toggle(bool isEnabled) override;
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
Common::String _relatedObject;
|
|
};
|
|
|
|
class Door final : public InteractableObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CPuerta";
|
|
Door(Room *room, Common::ReadStream &stream);
|
|
|
|
inline const Common::String &targetRoom() const { return _targetRoom; }
|
|
inline const Common::String &targetObject() const { return _targetObject; }
|
|
inline Direction characterDirection() const { return _characterDirection; }
|
|
|
|
CursorType cursorType() const override;
|
|
void onClick() override;
|
|
void trigger(const char *action) override;
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
Common::String _targetRoom, _targetObject;
|
|
Direction _characterDirection;
|
|
uint32 _lastClickTime = 0;
|
|
};
|
|
|
|
class Character : public ShapeObject, public ITriggerableObject {
|
|
public:
|
|
static constexpr const char *kClassName = "CPersonaje";
|
|
Character(Room *room, Common::ReadStream &stream);
|
|
~Character() override {}
|
|
|
|
void update() override;
|
|
void draw() override;
|
|
void drawDebug() override;
|
|
void loadResources() override;
|
|
void freeResources() override;
|
|
void syncGame(Common::Serializer &serializer) override;
|
|
Graphic *graphic() override;
|
|
void onClick() override;
|
|
void trigger(const char *action) override;
|
|
const char *typeName() const override;
|
|
|
|
Task *sayText(Process &process, int32 dialogId);
|
|
void resetTalking();
|
|
void talkUsing(ObjectBase *talkObject);
|
|
Task *animate(Process &process, ObjectBase *animateObject);
|
|
Task *lerpLodBias(Process &process, float targetLodBias, int32 durationMs);
|
|
inline float &lodBias() { return _lodBias; }
|
|
inline bool &isSpeaking() { return _isSpeaking; }
|
|
|
|
protected:
|
|
friend struct SayTextTask;
|
|
friend struct AnimateCharacterTask;
|
|
void syncObjectAsString(Common::Serializer &serializer, ObjectBase *&object);
|
|
void updateTalkingAnimation();
|
|
|
|
Graphic _graphicNormal, _graphicTalking;
|
|
|
|
bool _isTalking = false; ///< as in "in the process of saying a line"
|
|
bool _isSpeaking = true; ///< as in "actively moving their mouth to produce sounds", used in updateTalkingAnimation
|
|
int _curDialogId = -1;
|
|
float _lodBias = 0.0f;
|
|
ObjectBase
|
|
*_curAnimateObject = nullptr,
|
|
*_curTalkingObject = nullptr;
|
|
};
|
|
|
|
class WalkingCharacter : public Character {
|
|
public:
|
|
static constexpr const char *kClassName = "CPersonajeAnda";
|
|
WalkingCharacter(Room *room, Common::ReadStream &stream);
|
|
~WalkingCharacter() override {}
|
|
|
|
inline bool isWalking() const { return _isWalking; }
|
|
inline Common::Point position() const { return _currentPos; }
|
|
inline float stepSizeFactor() const { return _stepSizeFactor; }
|
|
|
|
void update() override;
|
|
void draw() override;
|
|
void drawDebug() override;
|
|
void loadResources() override;
|
|
void freeResources() override;
|
|
void syncGame(Common::Serializer &serializer) override;
|
|
virtual void walkTo(
|
|
Common::Point target,
|
|
Direction endDirection = Direction::Invalid,
|
|
ITriggerableObject *activateObject = nullptr,
|
|
const char *activateAction = nullptr);
|
|
void stopWalking(Direction direction = Direction::Invalid);
|
|
void setPosition(Common::Point target);
|
|
const char *typeName() const override;
|
|
|
|
Task *waitForArrival(Process &process);
|
|
|
|
protected:
|
|
virtual void onArrived();
|
|
void updateWalking();
|
|
void updateWalkingAnimation();
|
|
|
|
inline Animation *currentAnimationOf(Common::ScopedPtr<Animation> *const animations) {
|
|
Animation *animation = animations[(int)_direction].get();
|
|
if (animation == nullptr)
|
|
animation = animations[0].get();
|
|
assert(animation != nullptr);
|
|
return animation;
|
|
}
|
|
inline Animation *walkingAnimation() { return currentAnimationOf(_walkingAnimations); }
|
|
inline Animation *talkingAnimation() { return currentAnimationOf(_talkingAnimations); }
|
|
|
|
Common::ScopedPtr<Animation>
|
|
_walkingAnimations[kDirectionCount],
|
|
_talkingAnimations[kDirectionCount];
|
|
|
|
int32
|
|
_lastWalkAnimFrame = -1,
|
|
_walkedDistance = 0,
|
|
_curPathPointI = -1;
|
|
float _stepSizeFactor = 0.0f;
|
|
Common::Point
|
|
_sourcePos,
|
|
_currentPos;
|
|
bool _isWalking = false;
|
|
Direction
|
|
_direction = Direction::Right,
|
|
_endWalkingDirection = Direction::Invalid;
|
|
Common::Stack<Common::Point> _pathPoints;
|
|
};
|
|
|
|
struct DialogMenuLine {
|
|
int32 _dialogId = -1;
|
|
int32 _yPosition = 0;
|
|
int32 _returnValue = 0;
|
|
};
|
|
|
|
class MainCharacter final : public WalkingCharacter {
|
|
public:
|
|
static constexpr const char *kClassName = "CPersonajePrincipal";
|
|
MainCharacter(Room *room, Common::ReadStream &stream);
|
|
~MainCharacter() override;
|
|
|
|
inline MainCharacterKind kind() const { return _kind; }
|
|
inline ObjectBase *¤tlyUsing() { return _currentlyUsingObject; }
|
|
inline ObjectBase *currentlyUsing() const { return _currentlyUsingObject; }
|
|
inline Color &color() { return _color; }
|
|
inline uint8 &alphaPremultiplier() { return _alphaPremultiplier; }
|
|
inline FakeSemaphore &semaphore() { return _semaphore; }
|
|
bool isBusy() const;
|
|
|
|
void update() override;
|
|
void draw() override;
|
|
void syncGame(Common::Serializer &serializer) override;
|
|
const char *typeName() const override;
|
|
void walkTo(
|
|
Common::Point target,
|
|
Direction endDirection = Direction::Invalid,
|
|
ITriggerableObject *activateObject = nullptr,
|
|
const char *activateAction = nullptr) override;
|
|
void walkToMouse();
|
|
bool clearTargetIf(const ITriggerableObject *target);
|
|
void clearInventory();
|
|
bool hasItem(const Common::String &name) const;
|
|
void pickup(const Common::String &name, bool putInHand);
|
|
void drop(const Common::String &name);
|
|
void addDialogLine(int32 dialogId);
|
|
void setLastDialogReturnValue(int32 returnValue);
|
|
Task *dialogMenu(Process &process);
|
|
void resetUsingObjectAndDialogMenu();
|
|
|
|
protected:
|
|
void onArrived() override;
|
|
|
|
private:
|
|
friend class Inventory;
|
|
friend struct DialogMenuTask;
|
|
Item *getItemByName(const Common::String &name) const;
|
|
void drawInner();
|
|
|
|
Common::Array<Item *> _items;
|
|
Common::Array<DialogMenuLine> _dialogLines;
|
|
ObjectBase *_currentlyUsingObject = nullptr;
|
|
MainCharacterKind _kind;
|
|
FakeSemaphore _semaphore;
|
|
ITriggerableObject *_activateObject = nullptr;
|
|
const char *_activateAction = nullptr;
|
|
Color _color = kWhite;
|
|
uint8 _alphaPremultiplier = 255;
|
|
};
|
|
|
|
class Background final : public GraphicObject {
|
|
public:
|
|
Background(Room *room, const Common::String &animationFileName, int16 scale);
|
|
const char *typeName() const override;
|
|
};
|
|
|
|
class FloorColor final : public ObjectBase {
|
|
public:
|
|
static constexpr const char *kClassName = "CSueloColor";
|
|
FloorColor(Room *room, Common::ReadStream &stream);
|
|
~FloorColor() override {}
|
|
|
|
void update() override;
|
|
void drawDebug() override;
|
|
Shape *shape() override;
|
|
const char *typeName() const override;
|
|
|
|
private:
|
|
FloorColorShape _shape;
|
|
};
|
|
|
|
}
|
|
|
|
#endif // ALCACHOFA_OBJECTS_H
|