/* 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 . * */ #ifndef ASYLUM_RESOURCES_ACTOR_H #define ASYLUM_RESOURCES_ACTOR_H #include "common/array.h" #include "common/rect.h" #include "common/serializer.h" #include "common/stream.h" #include "asylum/shared.h" #include "asylum/resources/inventory.h" namespace Asylum { class AsylumEngine; class GraphicResource; class Screen; struct ActionArea; struct GraphicFrame; struct ActorData : public Common::Serializable { uint32 count; int32 current; Common::Point points[120]; ActorDirection directions[120]; ActorData() { count = 0; current = 0; memset(&directions, 0, sizeof(directions)); } virtual ~ActorData() {} void load(Common::SeekableReadStream *stream) { count = stream->readUint32LE(); current = stream->readUint32LE(); for (int32 i = 0; i < 120; i++) { points[i].x = stream->readSint32LE(); points[i].y = stream->readSint32LE(); } for (int32 i = 0; i < 120; i++) directions[i] = (ActorDirection)stream->readSint32LE(); } // Serializable void saveLoadWithSerializer(Common::Serializer &s) { s.syncAsUint32LE(count); s.syncAsSint32LE(current); for (int32 i = 0; i < ARRAYSIZE(points); i++) { s.syncAsSint32LE(points[i].x); s.syncAsSint32LE(points[i].y); } for (int32 i = 0; i < ARRAYSIZE(directions); i++) s.syncAsSint32LE(directions[i]); } }; class Actor : public Common::Serializable { public: Actor(AsylumEngine *engine, ActorIndex index); virtual ~Actor() {}; ////////////////////////////////////////////////////////////////////////// // Public variables & accessors ////////////////////////////////////////////////////////////////////////// int32 flags; int32 actionType; // ActionType enum value Inventory inventory; void setActionIndex2(int32 index) { _actionIdx2 = index; } void setObjectIndex(int32 index) { _objectIndex = index; } void setDirection(ActorDirection dir) { _direction = dir; } void setFrameCount(int32 count) { _frameCount = count; } void setFrameIndex(int32 number) { _frameIndex = number; } void setLastScreenUpdate(int32 tick) { _lastScreenUpdate = tick; } void setNumberFlag01(int32 number) { _numberFlag01 = number; } void setPriority(int32 priority) { _priority = priority; } void setResourceId(ResourceId id) { _resourceId = id; } void setSoundResourceId(ResourceId id) { _soundResourceId = id; } void setStatus(ActorStatus status) { _status = status; } void setTransparency(int32 val) { _transparency = val; } void setTickCount(int32 tickCount) { _tickCount = tickCount; } void setField934(int32 val) { _field_934 = val; } void setField938(int32 val) { _field_938 = val; } void setField944(int32 val) { _field_944 = val; } int32 getActionIndex3() { return _actionIdx3; } Common::Rect *getBoundingRect() { return &_boundingRect; } ActorDirection getDirection() { return _direction; } uint32 getFrameCount() { return _frameCount; } uint32 getFrameIndex() { return _frameIndex; } char *getName() { return (char *)&_name; } ActorIndex getNextActorIndex() { return _nextActorIndex; } int32 getNumberValue01() { return _numberValue01; } Common::Point *getPoint() { return &_point; } Common::Point *getPoint1() { return &_point1; } Common::Point *getPoint2() { return &_point2; } int32 getPriority() { return _priority; } ResourceId getResourceId() { return _resourceId; } ResourceId getResourcesId(uint32 index) { return _graphicResourceIds[index]; } int32 getScriptIndex() { return _scriptIndex; } bool shouldInvertPriority() { return _invertPriority; } ResourceId getSoundResourceId() { return _soundResourceId; } ActorStatus getStatus() { return _status; } int32 getTickCount() { return _tickCount; } int32 getField934() { return _field_934; } int32 getField944() { return _field_944; } int32 getField948() { return _field_948; } int32 getField94C() { return _field_94C; } // For saving ActorData *getData() { return &_data; } ///////////////////////////////////////////////////////////////////////// // Data ///////////////////////////////////////////////////////////////////////// /** * Loads the actor * * @param stream If non-null, the Common::SeekableReadStream to load from */ void load(Common::SeekableReadStream *stream); ///////////////////////////////////////////////////////////////////////// // Visibility ///////////////////////////////////////////////////////////////////////// /** * Query if this actor is visible. * * @return true if visible, false if not. */ bool isVisible() { return flags & kActorFlagVisible; } /** * Query if this actor is on screen. * * @return true if on screen, false if not. */ bool isOnScreen(); /** * Shows this actor. */ void show() { setVisible(true); } /** * Hides this actor. */ void hide() { setVisible(false); } ///////////////////////////////////////////////////////////////////////// // Drawing & update ////////////////////////////////////////////////////////////////////////// /** * Draws the actor */ void draw(); /** * Draw number text (called on scene drawing) */ void drawNumber(); /** * Updates the actor. */ void update(); /** * Enables the actor */ void enable() { changeStatus(kActorStatusEnabled); } /** * Changes the actor status. * * @param status The status. */ void changeStatus(ActorStatus status); ///////////////////////////////////////////////////////////////////////// // Direction & position ///////////////////////////////////////////////////////////////////////// /** * Updates the actor's mirror image. */ void updateReflectionData(); /** * Updates resource Id using the actor direction. * * @param direction The direction. */ void changeDirection(ActorDirection direction); /** * Face a target from a certain direction * * @param target Identifier for the target. * @param from direction to face from. */ void faceTarget(uint32 target, DirectionFrom from); /** * Initialize the x1/y1 values of the actor, update the active animation frame and, if the current direction isn't 8, update the actor's direction. * * @param newX The new x coordinate. * @param newY The new y coordinate. * @param newDirection The new direction. * @param frame The frame. */ void setPosition(int16 newX, int16 newY, ActorDirection newDirection, uint32 frame); /** * Query if a graphic resource is present. * * @param index Zero-based index of the graphic resource. * * @return true if the graphic resource is present. */ bool canChangeStatus(int index) const; /** * Adjust coordinates. * * @param point The point. */ void adjustCoordinates(Common::Point *point); ///////////////////////////////////////////////////////////////////////// // Misc ///////////////////////////////////////////////////////////////////////// /** * Stop the actor related sounds */ void stopSound(); /** * Convert this object into a string representation. * * @param shortString toggle whether to output a summary or * detailed view of the actor object * @return A string representation of this object. */ Common::String toString(bool shortString = true); /** * Clears reflection-related data fields */ void clearReflectionData(); bool canReach(const Common::Point &point); void forceTo(int16 actorX, int16 actorY, bool doSpeech); void setupReflectionData(ActorIndex nextActor, int32 actionAreaId, ActorDirection nextDirection, const Common::Point &nextPosition, bool invertPriority, const Common::Point &nextPositionOffset); bool aNicePlaceToTalk(Common::Point *point, int32 *param); bool canMove(Common::Point *point, ActorDirection direction, uint32 count, bool hasDelta); void move(ActorDirection dir, uint32 distance); bool testActorCollision(Common::Point *point, ActorDirection direction); void drawInventory(); void stopWalking(); /** * Query if the object resource is present in the resource table between indices 10 & 20 * * @return true if resource present between 15 & 20, false if not. */ bool checkBoredStatus() const; ////////////////////////////////////////////////////////////////////////// // Static update methods ////////////////////////////////////////////////////////////////////////// static void crowsReturn(AsylumEngine *engine); /** * Updates the player appearance in chapter 9. * * @param [in,out] engine If non-null, the engine. * @param nextPlayer The next player index */ static void morphInto(AsylumEngine *engine, int nextPlayer); /** * Gets a direction using the angle between the two vectors. * * @param vec1 The first vector. * @param vec2 The second vector. * * @return The direction */ static ActorDirection getAngle(const Common::Point &vec1, const Common::Point &vec2); /** * Gets the euclidean distance between two points. * * @param point1 The first point. * @param point2 The second point. * * @return the distance. */ static uint32 euclidianDistance(const Common::Point &point1, const Common::Point &point2); // Serializable void saveLoadWithSerializer(Common::Serializer &s); private: AsylumEngine *_vm; // Our current index ActorIndex _index; ////////////////////////////////////////////////////////////////////////// // Data ////////////////////////////////////////////////////////////////////////// Common::Point _point; ResourceId _resourceId; int32 _objectIndex; uint32 _frameIndex; uint32 _frameCount; Common::Point _point1; Common::Point _point2; Common::Rect _boundingRect; ActorDirection _direction; int32 _field_3C; ActorStatus _status; int32 _field_44; int32 _priority; //flags int32 _field_50; int32 _field_54; int32 _field_58; int32 _field_5C; int32 _field_60; int32 _actionIdx3; // TODO field_68 till field_617 ResourceId _walkingSound1; ResourceId _walkingSound2; ResourceId _walkingSound3; ResourceId _walkingSound4; uint32 _field_64C; uint32 _field_650; ResourceId _graphicResourceIds[55]; char _name[256]; int32 _distancesEO[20]; int32 _distancesNS[20]; int32 _distancesNSEO[20]; int32 _actionIdx2; int32 _field_924; uint32 _lastScreenUpdate; int32 _scriptIndex; //actionType int32 _field_934; int32 _field_938; ResourceId _soundResourceId; // field_93C int32 _numberValue01; int32 _field_944; // has collision ?! int32 _field_948; int32 _field_94C; int32 _numberFlag01; int16 _numberStringWidth; Common::Point _numberPoint; char _numberString01[8]; int32 _field_968; int32 _transparency; bool _processNewDirection; bool _invertPriority; ActorDirection _nextDirection; int32 _nextActionIndex; ActorIndex _nextActorIndex; Common::Point _nextPositionOffset; Common::Point _nextPosition; int32 _field_994; int32 _field_998; int32 _field_99C; int32 _field_9A0; ////////////////////////////////////////////////////////////////////////// // Actor data ////////////////////////////////////////////////////////////////////////// ActorData _data; int32 _tickCount; uint32 _updateCounter; ////////////////////////////////////////////////////////////////////////// // Update methods ////////////////////////////////////////////////////////////////////////// void updateStatusInteracting(); void checkPumpkinDeath(); void updatePumpkin(GameFlag flagToCheck, GameFlag flagToSet, ObjectId objectToUpdate, ObjectId objectToDisable); void updateStatusEnabled(); void updateStatusEnabledProcessStatus(int16 testX, int16 testY, uint32 counter, int16 setX, int16 setY); void updateStatusBored(); void CrowClosesIn(); void ScareCrowClosesIn(); void TentacleRises(); void updateStatusEnabled2(); void CrowHoveringBeforeKill(); void CrowStatusQuo(); void TentacleWigglesForSarah(); void CrowDives(); void MaxGetsHit(); void MaxAttacks(); void checkScareCrowDeath(); bool checkCrowDeath(); void ScareCrowAttacks(); bool actorsIntersect(ActorIndex actorIndex1, ActorIndex actorIndex2); void TentacleWhips(); void SarahAttacks(); void MaxGetsSome(); void SarahGetsSome(); void TentacleDies(); void CrowSwoops(); void ScareCrowRetreats(); void updateStatusMorphing(); void actionAreaCheck(); ////////////////////////////////////////////////////////////////////////// // Path finding functions ////////////////////////////////////////////////////////////////////////// uint32 _frameNumber; bool findLeftPath(Common::Point source, const Common::Point &destination, Common::Array *actions); bool findRightPath(Common::Point source, const Common::Point &destination, Common::Array *actions); bool findUpPath(Common::Point source, const Common::Point &destination, Common::Array *actions); bool findDownPath(Common::Point source, const Common::Point &destination, Common::Array *actions); bool tryDirection(const Common::Point &source, Common::Array *actions, Common::Point *point, ActorDirection direction, const Common::Point &destination, bool *flag); bool canGetToDest(Common::Array *actions, const Common::Point &point, ActorDirection direction, int16 loopcount); bool testPolyInLink(const Common::Point &pt, Common::Array *actions); ////////////////////////////////////////////////////////////////////////// // Misc ////////////////////////////////////////////////////////////////////////// /** * Sets actor visibility * * @param value true to set to visible, false to set to hidden. */ void setVisible(bool value); /** * Sets the volume. */ void setVolume(); void TentacleBlocksSarah(const Common::Point &vec1, Common::Point vec2); void SarahDies(); /** * Updates the actor "number" data if the item is "1". * * @param item The item. * @param point The coordinates */ void updateNumbers(uint item, const Common::Point &point); /** * Determine if the supplied point is in the action area * * @param pt The point. * @param [in,out] area If non-null, the area. * * @return true if in the action area, false otherwise */ bool isInActionArea(const Common::Point &pt, ActionArea *area); ////////////////////////////////////////////////////////////////////////// // Helper methods ////////////////////////////////////////////////////////////////////////// /** * Updates the actor graphic information * * @param offset The offset used to get the id from the _graphicResourceIds table */ void updateGraphicData(uint32 offset); /** * Gets the graphics flag for queuing the actor graphics (mirrored or normal) * * @return The graphics flag. */ DrawFlags getGraphicsFlags(); /** * Gets the absolute value of the walk increment for a frame. * * @param direction The direction. * @param frameIndex Zero-based index of the frame. * * @return The absolute value of the walk increment. */ int32 getStride(ActorDirection direction, uint32 frameIndex) const; /** * Gets the walk increment for a frame. * * @param direction The direction. * @param frameIndex Zero-based index of the frame. * * @return The walk increment. */ int32 getWalkIncrement(ActorDirection direction, uint32 frameIndex) const; /** * Updates the coordinates depending on the direction. * * @param direction The direction. * @param delta The delta. * @param [in,out] point If non-null, the point. */ static void incPosition(ActorDirection direction, int16 delta, Common::Point *point); /** * Get the angle between the two vectors * * @param p1 The first vector. * @param p2 The second vector. * * @return the angle */ static int32 getAngleOfVector(const Common::Point &vec1, const Common::Point &vec2); /** * Computes the Scare Crow's strike zone. * * @param rect The strike zone. * @param direction The direction. * @param point The point. */ static void getCrowStrikeZone(Common::Rect *rect, ActorDirection direction, const Common::Point &point); /** * Determines the direction of the shortest rotation between two vectors. * * @param vec1 The first vector. * @param vec2 The second vector. * * @return true if CCW, false if CW. */ static bool determineLeftOrRight(const Common::Point &vec1, const Common::Point &vec2); /** * Gets the adjustment for the X-coordinate of the supplied point. * * @param rect The rectangle. * @param point The test point. * * @return value depending on the horizontal position of the point relative to the rectangle. */ static int16 pointInRectXAdjust(const Common::Rect &rect, const Common::Point &point); /** * Gets the adjustment for the Y-coordinate of the supplied point. * * @param rect The rectangle. * @param point The test point. * * @return value depending on the vertical position of the point relative to the rectangle. */ static int16 pointInRectYAdjust(const Common::Rect &rect, const Common::Point &point); }; // end of class MainActor } // end of namespace Asylum #endif // ASYLUM_RESOURCES_ACTOR_H