Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,612 @@
/* 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 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<int> *actions);
bool findRightPath(Common::Point source, const Common::Point &destination, Common::Array<int> *actions);
bool findUpPath(Common::Point source, const Common::Point &destination, Common::Array<int> *actions);
bool findDownPath(Common::Point source, const Common::Point &destination, Common::Array<int> *actions);
bool tryDirection(const Common::Point &source, Common::Array<int> *actions, Common::Point *point, ActorDirection direction, const Common::Point &destination, bool *flag);
bool canGetToDest(Common::Array<int> *actions, const Common::Point &point, ActorDirection direction, int16 loopcount);
bool testPolyInLink(const Common::Point &pt, Common::Array<int> *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

View File

@@ -0,0 +1,406 @@
/* 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/textconsole.h"
#include "engines/asylum/detection.h"
#include "engines/asylum/resources/data.h"
namespace Asylum {
SharedData::SharedData() : crowsData(this) {
// Public data
cdNumber = 0;
movieIndex = 0;
sceneCounter = 0;
actorEnableForStatus7 = false;
globalDirection = kDirectionN;
memset(&_ambientFlags, 0, sizeof(_ambientFlags));
memset(&_ambientTicks, 0, sizeof(_ambientTicks));
_globalPoint.x = -1;
_globalPoint.y = -1;
_flagSkipScriptProcessing = false;
_flagIsEncounterRunning = false;
_playerIndex = 0;
_sceneOffset = 0;
_sceneOffsetAdd = 0;
memset(&_cursorResources, kResourceNone, sizeof(_cursorResources));
memset(&_sceneFonts, kResourceNone, sizeof(_sceneFonts));
memset(&_chapter2Data1, 0, sizeof(_chapter2Data1));
_smallCurUp = 0;
_smallCurDown = 0;
_encounterFrameBg = kResourceNone;
_flagSkipDrawScene = false;
_matteVar1 = 0;
_flagActorUpdateEnabledCheck = false;
_matteInitialized = false;
_mattePlaySound = false;
_currentScreenUpdatesCount = 0;
memset(&_chapter2Data2, 0, sizeof(_chapter2Data2));
memset(&_chapter2Counters, 0, sizeof(_chapter2Counters));
memset(&_chapter2Data3, 0, sizeof(_chapter2Data3));
_chapter2FrameIndexOffset = 0;
_chapter2ActorIndex = 0;
_eventUpdate = 0;
memset(&_chapter2Data4, 0, sizeof(_chapter2Data4));
_actorUpdateStatusEnabledCounter = 0;
memset(&_chapter2Data5, 0, sizeof(_chapter2Data5));
_flagEncounterDisablePlayerOnExit = false;
_flag1 = false;
_nextScreenUpdate = 0;
// _moviesViewed
_flagActorUpdateStatus15Check = false;
// Non-saved data
_flag2 = false;
_flag3 = false;
_flagScene1 = false;
_flagRedraw = false;
_matteBarHeight = 0;
_matteVar2 = 0;
}
//////////////////////////////////////////////////////////////////////////
// Saved scene data
//////////////////////////////////////////////////////////////////////////
void SharedData::saveCursorResources(ResourceId *resources, uint32 size) {
memcpy((ResourceId *)&_cursorResources, resources, size);
}
void SharedData::loadCursorResources(ResourceId *resources, uint32 size) const {
memcpy(resources, (const ResourceId *)&_cursorResources, size);
}
void SharedData::saveSceneFonts(ResourceId font1, ResourceId font2, ResourceId font3) {
_sceneFonts[0] = font1;
_sceneFonts[1] = font2;
_sceneFonts[2] = font3;
}
void SharedData::loadSceneFonts(ResourceId *font1, ResourceId *font2, ResourceId *font3) const {
*font1 = _sceneFonts[0];
*font2 = _sceneFonts[1];
*font3 = _sceneFonts[2];
}
void SharedData::saveSmallCursor(int32 smallCurUp, int32 smallCurDown) {
_smallCurUp = smallCurUp;
_smallCurDown = smallCurDown;
}
void SharedData::loadSmallCursor(int32 *smallCurUp, int32 *smallCurDown) const {
*smallCurUp = _smallCurUp;
*smallCurDown = _smallCurDown;
}
//////////////////////////////////////////////////////////////////////////
// Chapter 2 data
//////////////////////////////////////////////////////////////////////////
void SharedData::resetChapter2Data() {
for (int i = 0; i < 9; i++) {
crowsData[i + 11] = 160;
crowsData[i + 39] = 0;
crowsData[i + 73] = 0;
}
}
void SharedData::reset() {
for (int i = 0; i < 9; i++)
crowsData[i + 11] = 160;
_chapter2FrameIndexOffset = 1;
}
//static const uint32 chapter2DataSizes[5] = {5, 9, 23, 18, 9};
int32 &CrowsData::operator[](uint32 index) {
if (index >= ARRAYSIZE(_data))
error("[CrowsData::operator[]] Invalid index (was: %d, valid: [0;%d])", index, ARRAYSIZE(_data) - 1);
// TODO use _chapter2Data*[] instead of a dedicated array
return _data[index];
}
void SharedData::setChapter2Counter(uint32 index, int32 val) {
if (index == 0 || index > 8)
error("[SharedData::setChapter2Counter] Invalid index (was: %d, valid: [1;8])", index);
_chapter2Counters[index - 1] = val;
}
int32 SharedData::getChapter2Counter(uint32 index) const {
if (index == 0 || index > 8)
error("[SharedData::setChapter2Counter] Invalid index (was: %d, valid: [1;8])", index);
return _chapter2Counters[index - 1];
}
//////////////////////////////////////////////////////////////////////////
// Ambient sounds
//////////////////////////////////////////////////////////////////////////
uint32 SharedData::getAmbientTick(uint32 index) const {
if (index >= ARRAYSIZE(_ambientTicks))
error("[SharedData::getAmbientTick] index is outside valid values (was: %d, valid: [0:%d]", index, ARRAYSIZE(_ambientTicks));
return _ambientTicks[index];
}
void SharedData::setAmbientTick(uint32 index, uint32 val) {
if (index >= ARRAYSIZE(_ambientTicks))
error("[SharedData::setAmbientTick] index is outside valid values (was: %d, valid: [0:%d]", index, ARRAYSIZE(_ambientTicks));
_ambientTicks[index] = val;
}
uint32 SharedData::getAmbientFlag(uint32 index) const {
if (index >= ARRAYSIZE(_ambientFlags))
error("[SharedData::getAmbientFlag] index is outside valid values (was: %d, valid: [0:%d]", index, ARRAYSIZE(_ambientFlags));
return _ambientFlags[index];
}
void SharedData::setAmbientFlag(uint32 index, uint32 val) {
if (index >= ARRAYSIZE(_ambientFlags))
error("[SharedData::setAmbientFlag] index is outside valid values (was: %d, valid: [0:%d]", index, ARRAYSIZE(_ambientFlags));
_ambientFlags[index] = val;
}
void SharedData::resetAmbientFlags() {
memset(&_ambientFlags, 0, sizeof(_ambientFlags));
}
//////////////////////////////////////////////////////////////////////////
// Flags
//////////////////////////////////////////////////////////////////////////
bool SharedData::getFlag(GlobalFlag flag) const {
switch (flag) {
default:
error("[SharedData::getFlag] Invalid flag type (%d)!", flag);
case kFlag1:
return _flag1;
case kFlag2:
return _flag2;
case kFlag3:
return _flag3;
case kFlagRedraw:
return _flagRedraw;
case kFlagSkipDrawScene:
return _flagSkipDrawScene;
case kFlagSceneRectChanged:
error("[SharedData::getFlag] Invalid flag type (kFlagSceneRectChanged)!");
case kFlagScene1:
return _flagScene1;
case kFlagSkipScriptProcessing:
return _flagSkipScriptProcessing;
case kFlagIsEncounterRunning:
return _flagIsEncounterRunning;
case kFlagEncounterDisablePlayerOnExit:
return _flagEncounterDisablePlayerOnExit;
case kFlagActorUpdateEnabledCheck:
return _flagActorUpdateEnabledCheck;
case kFlagActorUpdateStatus15Check:
return _flagActorUpdateStatus15Check;
}
}
void SharedData::setFlag(GlobalFlag flag, bool state) {
switch (flag) {
default:
error("[SharedData::setFlag] Invalid flag type (%d)!", flag);
case kFlag1:
_flag1 = state;
break;
case kFlag2:
_flag2 = state;
break;
case kFlag3:
_flag3 = state;
break;
case kFlagRedraw:
_flagRedraw = state;
break;
case kFlagSkipDrawScene:
_flagSkipDrawScene = state;
break;
case kFlagSceneRectChanged:
warning("[SharedData::setFlag] Invalid flag type (kFlagSceneRectChanged)!");
break;
case kFlagScene1:
_flagScene1 = state;
break;
case kFlagSkipScriptProcessing:
_flagSkipScriptProcessing = state;
break;
case kFlagIsEncounterRunning:
_flagIsEncounterRunning = state;
break;
case kFlagEncounterDisablePlayerOnExit:
_flagEncounterDisablePlayerOnExit = state;
break;
case kFlagActorUpdateEnabledCheck:
_flagActorUpdateEnabledCheck = state;
break;
case kFlagActorUpdateStatus15Check:
_flagActorUpdateStatus15Check = state;
break;
}
}
//////////////////////////////////////////////////////////////////////////
// Serializer
//////////////////////////////////////////////////////////////////////////
void SharedData::saveLoadAmbientSoundData(Common::Serializer &s) {
// Ambient sound flags/ticks
for (uint32 i = 0; i < ARRAYSIZE(_ambientFlags); i++)
s.syncAsUint32LE(_ambientFlags[i]);
for (uint32 i = 0; i < ARRAYSIZE(_ambientTicks); i++)
s.syncAsUint32LE(_ambientTicks[i]);
}
void SharedData::saveLoadWithSerializer(Common::Serializer &s) {
debugC(kDebugLevelSavegame, "[SharedData::saveLoadWithSerializer] Saving Chapter 2 actor data is not implemented");
// Global coordinates (original uses int32 for coordinates)
s.syncAsSint32LE(_globalPoint.x);
s.syncAsSint32LE(_globalPoint.y);
// Processing of scripts/encounter
s.syncAsUint32LE(_flagSkipScriptProcessing);
s.syncAsUint32LE(_flagIsEncounterRunning);
// Player index
s.syncAsSint32LE(_playerIndex);
// Scene coordinates
s.syncAsSint32LE(_sceneCoords.x);
s.syncAsSint32LE(_sceneCoords.y);
s.syncAsSint32LE(_sceneOffset);
s.syncAsSint32LE(_sceneOffsetAdd);
// Original skips 4 bytes
s.skip(4);
// Cursor resources
for (uint32 i = 0; i < ARRAYSIZE(_cursorResources); i++)
s.syncAsUint32LE(_cursorResources[i]);
// Fonts
for (uint32 i = 0; i < ARRAYSIZE(_sceneFonts); i++)
s.syncAsUint32LE(_sceneFonts[i]);
// Chapter 2 actor data (Part 1)
for (uint32 i = 0; i < ARRAYSIZE(_chapter2Data1); i++)
s.syncAsUint32LE(_chapter2Data1[i]);
// Scene information
s.syncAsSint32LE(_smallCurUp);
s.syncAsSint32LE(_smallCurDown);
s.syncAsSint32LE(_encounterFrameBg);
s.syncAsUint32LE(_flagSkipDrawScene);
s.syncAsSint32LE(_matteVar1);
s.syncAsUint32LE(_flagActorUpdateEnabledCheck);
s.syncAsUint32LE(_matteInitialized);
s.syncAsUint32LE(_mattePlaySound);
s.syncAsSint32LE(_currentScreenUpdatesCount);
// Chapter 2 actor data (Part 2)
for (uint32 i = 0; i < ARRAYSIZE(_chapter2Data2); i++)
s.syncAsUint32LE(_chapter2Data2[i]);
// Chapter 2 counters (1-4)
s.syncAsSint32LE(_chapter2Counters[0]);
s.syncAsSint32LE(_chapter2Counters[1]);
s.syncAsSint32LE(_chapter2Counters[2]);
s.syncAsSint32LE(_chapter2Counters[3]);
// Chapter 2 actor data (Part 3)
for (uint32 i = 0; i < ARRAYSIZE(_chapter2Data3); i++)
s.syncAsUint32LE(_chapter2Data3[i]);
// Chapter 2 counter (5) and other data
s.syncAsSint32LE(_chapter2Counters[4]);
s.syncAsSint32LE(_chapter2FrameIndexOffset);
s.syncAsSint32LE(_chapter2ActorIndex);
s.syncAsSint32LE(_eventUpdate);
// Chapter 2 counters (6-8)
s.syncAsSint32LE(_chapter2Counters[5]);
s.syncAsSint32LE(_chapter2Counters[6]);
s.syncAsSint32LE(_chapter2Counters[7]);
// Chapter 2 actor data (Part 4)
for (uint32 i = 0; i < ARRAYSIZE(_chapter2Data4); i++)
s.syncAsUint32LE(_chapter2Data4[i]);
// Actor UpdateStatusEnabled Counter
s.syncAsSint32LE(_actorUpdateStatusEnabledCounter);
// Chapter2 actor data (part 5)
for (uint32 i = 0; i < ARRAYSIZE(_chapter2Data5); i++)
s.syncAsUint32LE(_chapter2Data5[i]);
// Encounter disable player on exit
s.syncAsUint32LE(_flagEncounterDisablePlayerOnExit);
// Scene flag 1
s.syncAsUint32LE(_flagScene1);
// Next screen update
s.syncAsUint32LE(_nextScreenUpdate);
// Viewed movies
// (we load it directly from an external file, the original overwrites the data with the one from the external file)
s.skip(196);
// Actor update status 15 check
s.syncAsUint32LE(_flagActorUpdateStatus15Check);
}
} // End of namespace Asylum

View File

@@ -0,0 +1,281 @@
/* 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 ASYLUM_RESOURCES_DATA_H
#define ASYLUM_RESOURCES_DATA_H
#include "common/rect.h"
#include "common/serializer.h"
#include "engines/asylum/shared.h"
namespace Asylum {
//////////////////////////////////////////////////////////////////////////
// Flags
enum GlobalFlag {
kFlag1,
kFlag2,
kFlag3,
kFlagRedraw,
kFlagSkipDrawScene,
kFlagSceneRectChanged,
kFlagScene1,
kFlagSkipScriptProcessing,
kFlagIsEncounterRunning,
kFlagEncounterDisablePlayerOnExit,
kFlagActorUpdateEnabledCheck,
kFlagActorUpdateStatus15Check
};
class SharedData;
class CrowsData {
public:
CrowsData(SharedData *sharedData) : /* _sharedData(sharedData), */_data() { memset(_data, 0, sizeof(_data)); }
int32 &operator [](uint32 index);
private:
int32 _data[84];
//SharedData *_sharedData;
};
/**
* Shared data
* -----------
* uint32 {1} - actorEnableForStatus7
*
* uint32 {1} - global direction
* uint32 {1} - lastScreenUpdate
*
* uint32 {1} - actor update counter
*
* uint32 {1} - matte bar height
*
* Lots of data
*
* -- Scene data (reset on scene load)
* uint32 {15} - ambient flags
* uint32 {15} - ambient ticks
* uint32 {1} - UNUSED
* uint32 {1} - UNUSED (scene updateScreen calls count)
* -- Script queue (stored in ScriptManager)
* uint32 {1} - global Object X
* uint32 {1} - global Object Y
* uint32 {1} - Skip script processing flag
* uint32 {1} - Encounter running flag
* uint32 {1} - Player ActorIndex
* uint32 {1} - scene xLeft
* uint32 {1} - scene yTop
* uint32 {1} - scene offset
* uint32 {1} - scene offsetAdd
* uint32 {1} - UNUSED
* uint32 {13} - cursor resources
* uint32 {3} - scene fonts (3)
* uint32 {5} - Chapter2 actor data (part 1)
* uint32 {1} - small cursor Up
* uint32 {1} - small cursor Down
* uint32 {1} - Encounter frame background
* uint32 {1} - Flag skip draw scene
* uint32 {1} - matte var 1
* uint32 {1} - actorUpdateEnabledCheck
* uint32 {1} - matte Initialized
* uint32 {1} - matte playSound
* uint32 {1} - currentScreenUpdatesCount
* uint32 {9} - Chapter2 actor data (part 2)
* uint32 {1} - Chapter 2 counter 1
* uint32 {1} - Chapter 2 counter 2
* uint32 {1} - Chapter 2 counter 3
* uint32 {1} - Chapter 2 counter 4
* uint32 {23} - Chapter2 actor data (part 3)
* uint32 {1} - Special 2 counter 5
* uint32 {1} - Chapter 2 frameIndex Offset
* uint32 {1} - Chapter 2 Actor index
* uint32 {1} - Event update flag
* uint32 {1} - Chapter 2 counter 6
* uint32 {1} - Chapter 2 counter 7
* uint32 {1} - Chapter 2 counter 8
* uint32 {18} - Chapter2 actor data (part 4)
* uint32 {1} - actorUpdateStatusEnabledCounter
* uint32 {9} - Chapter2 actor data (part 5)
* uint32 {1} - Encounter disablePlayerOnExit
* uint32 {1} - Scene flag 1
* uint32 {1} - nextScreenUpdate
* uint32 {49} - Viewed movies
* uint32 {1} - actorUpdateStatus15Check
* -- Skip opening movie command line flag (not used)
* -- Encounter flag 3
* uint32 {1} - Flag 2
* uint32 {1} - Flag Redraw
* -- scripts (reset on scene load)
* -- polygons (reset on scene load)
*/
class SharedData : public Common::Serializable {
public:
SharedData();
virtual ~SharedData() {};
// Public variables
int32 cdNumber;
uint32 movieIndex;
uint32 sceneCounter;
Common::Point vector1;
Common::Point vector2;
bool actorEnableForStatus7;
ActorDirection globalDirection;
CrowsData crowsData;
// Used by Actor::enableActorsChapter2 (and maybe others)
void resetChapter2Data();
void reset(); // called during game reset
// Flags
bool getFlag(GlobalFlag flag) const;
void setFlag(GlobalFlag flag, bool state);
// Serializer
void saveLoadAmbientSoundData(Common::Serializer &s);
void saveLoadWithSerializer(Common::Serializer &s);
//////////////////////////////////////////////////////////////////////////
// Accessors
//////////////////////////////////////////////////////////////////////////
// Ambient sound data
uint32 getAmbientTick(uint32 index) const;
void setAmbientTick(uint32 index, uint32 val);
uint32 getAmbientFlag(uint32 index) const;
void setAmbientFlag(uint32 index, uint32 val);
void resetAmbientFlags();
/**
* Return the index of the player actor
*/
ActorIndex getPlayerIndex() { return _playerIndex; }
/**
* Sets the player actor index.
*
* @param index index of the player actor
*/
void setPlayerIndex(ActorIndex index) { _playerIndex = index; }
// Coordinates
Common::Point getGlobalPoint() { return _globalPoint; }
void setGlobalPoint(const Common::Point &point) { _globalPoint = point; }
Common::Point getSceneCoords() { return _sceneCoords; }
void setSceneCoords(const Common::Point &point) { _sceneCoords = point; }
int16 getSceneOffset() { return _sceneOffset; }
void setSceneOffset(int16 sceneOffset) { _sceneOffset = sceneOffset; }
int16 getSceneOffsetAdd() { return _sceneOffsetAdd; }
void setSceneOffsetAdd(int16 sceneOffsetAdd) { _sceneOffsetAdd = sceneOffsetAdd; }
// Saved scene data
void saveCursorResources(ResourceId *resources, uint32 size);
void loadCursorResources(ResourceId *resources, uint32 size) const;
void saveSceneFonts(ResourceId font1, ResourceId font2, ResourceId font3);
void loadSceneFonts(ResourceId *font1, ResourceId *font2, ResourceId *font3) const;
void saveSmallCursor(int32 smallCurUp, int32 smallCurDown);
void loadSmallCursor(int32 *smallCurUp, int32 *smallCurDown) const;
void saveEncounterFrameBackground(ResourceId encounterFrameBg) { _encounterFrameBg = encounterFrameBg; }
void loadEncounterFrameBackground(ResourceId *encounterFrameBg) { *encounterFrameBg = _encounterFrameBg; }
// Matte data
int32 getMatteVar1() const { return _matteVar1; }
void setMatteVar1(int32 val) { _matteVar1 = val; }
uint32 getMatteVar2() const { return _matteVar2; }
void setMatteVar2(uint32 val) { _matteVar2 = val; }
int16 getMatteBarHeight() const { return _matteBarHeight; }
void setMatteBarHeight(int16 val) { _matteBarHeight = val; }
bool getMatteInitialized() const { return _matteInitialized; }
void setMatteInitialized(bool val) { _matteInitialized = val; }
bool getMattePlaySound() const { return _mattePlaySound; }
void setMattePlaySound(bool val) { _mattePlaySound = val; }
// Chapter 2 data
void setChapter2Counter(uint32 index, int32 val);
int32 getChapter2Counter(uint32 index) const;
int32 getChapter2FrameIndexOffset() const { return _chapter2FrameIndexOffset; }
void setChapter2FrameIndexOffset(int32 val) { _chapter2FrameIndexOffset = val; }
ActorIndex getChapter2ActorIndex() const { return _chapter2ActorIndex; }
void setChapter2ActorIndex(ActorIndex val) { _chapter2ActorIndex = val; }
// Misc
int32 getActorUpdateStatusEnabledCounter() { return _actorUpdateStatusEnabledCounter; }
void setActorUpdateStatusEnabledCounter(int32 val) { _actorUpdateStatusEnabledCounter = val; }
// Screen updates
int32 getEventUpdate() { return _eventUpdate; }
void setEventUpdate(int32 val) { _eventUpdate = val; }
uint32 getNextScreenUpdate() { return _nextScreenUpdate; }
void setNextScreenUpdate(uint32 nextScreenUpdate) { _nextScreenUpdate = nextScreenUpdate; }
private:
uint32 _ambientFlags[15];
uint32 _ambientTicks[15];
Common::Point _globalPoint; // global point
bool _flagSkipScriptProcessing;
bool _flagIsEncounterRunning;
int32 _playerIndex;
Common::Point _sceneCoords;
int16 _sceneOffset;
int16 _sceneOffsetAdd;
ResourceId _cursorResources[13];
ResourceId _sceneFonts[3];
uint32 _chapter2Data1[5];
int32 _smallCurUp;
int32 _smallCurDown;
ResourceId _encounterFrameBg;
bool _flagSkipDrawScene;
int32 _matteVar1;
bool _flagActorUpdateEnabledCheck;
bool _matteInitialized;
bool _mattePlaySound;
int32 _currentScreenUpdatesCount;
uint32 _chapter2Data2[9];
int32 _chapter2Counters[8];
int32 _chapter2Data3[23];
int32 _chapter2FrameIndexOffset;
ActorIndex _chapter2ActorIndex;
int32 _eventUpdate;
uint32 _chapter2Data4[18];
int32 _actorUpdateStatusEnabledCounter;
uint32 _chapter2Data5[9];
bool _flagEncounterDisablePlayerOnExit;
bool _flag1;
uint32 _nextScreenUpdate;
//byte _moviesViewed[196];
bool _flagActorUpdateStatus15Check;
// Non-saved data
bool _flag2;
bool _flag3;
bool _flagScene1;
bool _flagRedraw;
int16 _matteBarHeight;
uint32 _matteVar2;
friend class CrowsData;
};
} // End of namespace Asylum
#endif // ASYLUM_RESOURCES_DATA_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,337 @@
/* 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 ASYLUM_RESOURCES_ENCOUNTERS_H
#define ASYLUM_RESOURCES_ENCOUNTERS_H
#include "common/array.h"
#include "common/serializer.h"
#include "asylum/eventhandler.h"
#include "asylum/shared.h"
namespace Asylum {
class AsylumEngine;
struct EncounterItem : public Common::Serializable {
uint32 speechResourceId;
ResourceId scriptResourceId;
int16 keywords[50];
byte variable2;
EncounterItem() {
speechResourceId = 0;
scriptResourceId = kResourceNone;
memset(&keywords, 0, sizeof(keywords));
variable2 = 0;
}
virtual ~EncounterItem() {}
// Serializable
void saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(speechResourceId);
s.syncAsSint32LE(scriptResourceId);
for (int32 i = 0; i < ARRAYSIZE(keywords); i++)
s.syncAsSint16LE(keywords[i]);
s.syncAsByte(variable2);
}
};
class EncounterVariables : public Common::Array<int16>, public Common::Serializable {
public:
virtual ~EncounterVariables() {}
// Serializable
void saveLoadWithSerializer(Common::Serializer &s) {
for (uint i = 0; i < _size; i++)
s.syncAsSint16LE(_storage[i]);
}
};
class EncounterItems : public Common::Array<EncounterItem>, public Common::Serializable {
public:
virtual ~EncounterItems() {}
// Serializable
void saveLoadWithSerializer(Common::Serializer &s) {
for (uint i = 0; i < _size; i++)
_storage[i].saveLoadWithSerializer(s);
}
};
class Encounter : public EventHandler {
public:
Encounter(AsylumEngine *engine);
virtual ~Encounter() {};
void run(int32 encounterIndex, ObjectId objectId1, ObjectId objectId2, ActorIndex actorIndex);
bool handleEvent(const AsylumEvent &evt);
void drawScreen();
void setShouldEnablePlayer(bool state) { _shouldEnablePlayer = state; }
bool shouldEnablePlayer() { return _shouldEnablePlayer; }
// Accessors (for saving game)
EncounterItems *items() { return &_items; }
EncounterVariables *variables() { return &_variables; }
private:
AsylumEngine *_vm;
//////////////////////////////////////////////////////////////////////////
// Data
enum KeywordOptions {
kKeywordOptionsDisabled = 0x20,
kKeywordOptionsUnknown = 0x40,
kKeywordOptionsVisible = 0x80
};
struct EncounterGraphic {
uint32 frameIndex;
uint32 frameCount;
Common::Rect rect;
ResourceId resourceId;
int32 transTableNum;
int32 transTableMax;
int32 speech0;
int32 speech1;
int32 speech2;
int32 speech3;
EncounterGraphic() {
frameIndex = 0;
frameCount = 0;
resourceId = kResourceNone;
transTableNum = 0;
transTableMax = 0;
speech0 = 0;
speech1 = 0;
speech2 = 0;
speech3 = 0;
}
};
struct EncounterDrawingStruct {
Common::Point point1;
Common::Point point2;
uint32 frameIndex;
int32 transTableNum;
int32 status;
ResourceId resourceId;
EncounterDrawingStruct() {
frameIndex = 0;
transTableNum = -1;
status = 0;
resourceId = kResourceNone;
}
};
EncounterVariables _variables;
EncounterItems _items;
EncounterDrawingStruct _drawingStructs[2];
int32 _keywordIndexes[50];
// Background & portrait
EncounterGraphic _background;
EncounterGraphic _portrait1;
EncounterGraphic _portrait2;
Common::Point _point;
int32 _rectIndex;
// Running encounter data
int32 _index;
int32 _speechResourceId;
ResourceId _soundResourceId;
EncounterItem *_item;
ObjectId _objectId1;
ObjectId _objectId2;
ObjectId _objectId3;
ActorIndex _actorIndex;
int16 _value1;
uint32 _tick;
// Internal data
int32 _data_455B14;
int16 _data_455B3C;
int16 _data_455B70;
bool _data_455BCC;
bool _isDialogOpen;
bool _shouldCloseDialog;
bool _data_455BD8;
bool _data_455BDC;
bool _data_455BE0;
bool _shouldCloseBackground;
bool _data_455BE8;
int16 _data_455BF0;
uint32 _data_455BF4;
uint32 _keywordStartIndex;
uint32 _keywordsOffset;
// Internal flags
bool _shouldEnablePlayer;
bool _wasPlayerDisabled;
bool _isClosing;
bool _isScriptRunning;
//////////////////////////////////////////////////////////////////////////
// Data
void load();
void initData();
void initBackground();
void initPortraits();
void initDrawStructs();
//////////////////////////////////////////////////////////////////////////
// Message handling
bool init();
bool update();
bool mouse(const AsylumEvent &evt);
bool cancel(const AsylumEvent &evt);
//////////////////////////////////////////////////////////////////////////
// Variables
void setVariable(uint32 index, int16 val);
int16 getVariable(uint32 index);
int16 getVariableInv(int16 index);
/////////////////////////////////////////////////////////////////////////
// Actions
uint32 findKeyword(EncounterItem *item, int16 keyword) const;
int32 getKeywordIndex();
void choose(int32 keywordIndex);
bool checkKeywords() const;
bool checkKeywords2() const;
void updateFromRect(int32 rectIndex);
//////////////////////////////////////////////////////////////////////////
// Speech
void resetSpeech(int16 a1, int16 a2);
void setupPortraits();
void setupSpeechText();
void setupSpeechData(char val, EncounterGraphic *encounterGraphic) const;
void setupSpeech(ResourceId textResourceId, ResourceId fontResourceId);
bool setupSpeechTest(ResourceId id);
bool isSpeaking();
//////////////////////////////////////////////////////////////////////////
// Drawing
bool drawBackground();
bool drawPortraits();
void drawStructs();
void drawDialogOptions();
void drawSubtitle(char *text, ResourceId font, int16 y);
//////////////////////////////////////////////////////////////////////////
// Misc
void exitEncounter();
void setupEntities(bool type4);
int32 findRect();
void updateDrawingStatus();
void updateDrawingStatus1(int32 rectIndex);
void updateDrawingStatus2(int32 rectIndex);
bool updateScreen();
void updatePalette1();
void updatePalette2();
bool isKeywordVisible(int16 keyword) const { return (bool)(BYTE1(keyword) & kKeywordOptionsVisible); }
bool isKeywordDisabled(int16 keyword) const { return (bool)(BYTE1(keyword) & kKeywordOptionsDisabled); }
//////////////////////////////////////////////////////////////////////////
// Scripts
enum EncounterOpcode {
kOpcodeEncounterReturn = 0,
kOpcodeSetScriptVariable = 1,
kOpcodeSetCounterFromVars = 2,
kOpcodeSetOffset = 3,
kOpcodeSetOffsetIfCounterNegative = 4,
kOpcodeSetOffsetIfCounterNegativeOrNull = 5,
kOpcodeSetOffsetIfCounterIsNull = 6,
kOpcodeSetOffsetIfCounterIsNotNull = 7,
kOpcodeSetOffsetIfCounterPositiveOrNull = 8,
kOpcodeSetOffsetIfCounterPositive = 9,
kOpcodeSetCurrentItemOptions = 10,
kOpcodeClearCurrentItemOptions = 11,
kOpcodeSetItemOptions = 12,
kOpcodeCloseDialog = 13,
kOpcodeResetSpeech = 14,
kOpcodeSetVariable = 15,
kOpcodeIncrementScriptVariable = 16,
kOpcodeProcessVariable3 = 17,
kOpcodeAddRemoveInventoryItem = 18,
kOpcodeSetCounterIfInventoryOmits = 21,
kOpcodePrepareMovie = 23,
kOpcodeSetClearGameFlag = 24,
kOpcodeSetCounterFromGameFlag = 25
};
struct ScriptEntry {
byte opcode;
byte param1;
uint16 param2;
ScriptEntry(byte *data) {
opcode = *data;
param1 = *(data + 1);
param2 = READ_LE_UINT16(data + 2);
}
Common::String toString();
};
struct ScriptData {
int32 vars[40];
uint32 offset;
int32 counter;
ResourceId resourceId;
ScriptData() {
reset(kResourceNone);
}
void reset(ResourceId id) {
memset(&vars, 0, sizeof(vars));
offset = 0;
counter = 0;
resourceId = id;
}
};
ScriptData _scriptData;
void initScript(ResourceId resourceId);
ScriptEntry getScriptEntry(ResourceId resourceId, uint32 offset);
void runScript();
friend class Console;
};
} // end of namespace Asylum
#endif // ASYLUM_RESOURCES_ENCOUNTERS_H

View File

@@ -0,0 +1,203 @@
/* 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/serializer.h"
#include "common/stream.h"
#include "asylum/resources/actor.h"
#include "asylum/resources/worldstats.h"
#include "asylum/system/speech.h"
#include "asylum/views/scene.h"
namespace Asylum {
// inventory ring is centered at (-20, 20) and has radius 80
static const int16 inventoryRingPoints[36][2] = {
{ -20, 100},
{ -20, 100}, { -20, -60},
{ -20, 100}, { -89, -20}, { 49, -20},
{ -20, 100}, {-100, 20}, { -20, -60}, { 60, 20},
{ -20, 100}, { -96, 45}, { -67, -45}, { 27, -45}, { 56, 45},
{ -20, 100}, { -89, 60}, { -89, -20}, { -20, -60}, { 49, -20}, { 49, 60},
{ -20, 100}, { -82, 70}, { -98, 3}, { -56, -51}, { 13, -53}, { 57, -1}, { 45, 67},
{ -20, 100}, { -77, 77}, {-100, 20}, { -77, -37}, { -20, -60}, { 37, -37}, { 60, 20}, { 37, 77}
};
// first 8 triangular numbers
static const uint inventoryRingOffsets[8] = {0, 1, 3, 6, 10, 15, 21, 28};
static const int inventoryDescriptionIndices[12][11] = {
{ 61, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{107, 134, 104, 113, -1, 112, 117, 109, 108, 111, 106},
{170, 182, 181, 172, 171, 169, 0, 0, 0, 0, 0},
{ 61, -1, 66, 67, 68, 69, 70, 78, 77, 0, 0},
{197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 59, 81, 60, 84, 88, 54, 74, 139, 97, 121, 0},
{239, 234, 249, 259, 260, 272, 237, 262, 0, 0, 0},
{ 58, 59, 60, 111, 75, 76, 77, 78, 0, 0, 0},
{284, 285, 286, 329, 330, 331, 332, 322, 0, 465, 0},
{ -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0},
{ 69, 70, 78, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
Inventory::Inventory(AsylumEngine *vm, int32 &multiple) : _vm(vm), _selectedItem(0), _multiple(multiple) {
memset(_items, 0, sizeof(_items));
}
void Inventory::load(Common::SeekableReadStream *stream) {
for (int i = 0; i < 8; i++)
_items[i] = stream->readUint32LE();
_selectedItem = stream->readUint32LE();
}
void Inventory::saveLoadWithSerializer(Common::Serializer &s) {
for (int i = 0; i < 8; i++)
s.syncAsUint32LE(_items[i]);
s.syncAsUint32LE(_selectedItem);
}
uint Inventory::find(uint item) const {
int i;
for (i = 0; i < 8; i++)
if (_items[i] == item)
break;
return i;
}
void Inventory::add(uint item, uint multipleIncr) {
if (item > 16)
return;
if (!contains(item, 0)) {
int i = find();
if (i == 8)
return;
_items[i] = item;
}
_multiple += multipleIncr;
getSound()->playSound(MAKE_RESOURCE(kResourcePackSound, 0));
}
void Inventory::remove(uint item, uint multipleDecr) {
if (item > 16)
return;
_multiple = (_multiple >= (int32)multipleDecr) ? _multiple - multipleDecr : 0;
if (!multipleDecr || !_multiple) {
int i = find(item);
if (i == 8)
return;
if (i < 7)
memmove(&_items[i], &_items[i + 1], (7 - i) * 4);
_items[7] = 0;
}
}
bool Inventory::contains(uint item, uint multiple) const {
if (item > 16)
return false;
int i = find(item);
if (i == 8)
return false;
if (multiple)
return (_multiple >= (int32)multiple);
return true;
}
void Inventory::copyFrom(Inventory &inventory) {
for (int i = 0; i < 8; i++)
_items[i] = inventory[i];
}
Common::Point Inventory::getInventoryRingPoint(AsylumEngine *vm, uint nPoints, uint index) {
const int16 (*pointPtr)[2];
if (vm->scene()->worldstats()->chapter == kChapter11)
pointPtr = &inventoryRingPoints[inventoryRingOffsets[7] + index + 3];
else
pointPtr = &inventoryRingPoints[inventoryRingOffsets[nPoints - 1] + index];
return Common::Point((*pointPtr)[0], (*pointPtr)[1]);
}
void Inventory::describe(AsylumEngine *vm, uint itemIndex) {
uint index;
ResourceId resourceId;
ChapterIndex chapter = vm->scene()->worldstats()->chapter;
if (chapter == kChapterNone || itemIndex > 10)
return;
if (chapter == kChapter2 && itemIndex == 4)
index = vm->isGameFlagSet(kGameFlag186) ? 362 : 110;
else if (chapter == kChapter4 && itemIndex == 1)
index = vm->scene()->getActor()->getNumberValue01() != 1 ? 65 : 64;
else if (chapter == kChapter10 && itemIndex < 5)
index = 91 + itemIndex;
else
index = inventoryDescriptionIndices[chapter - 1][itemIndex];
switch (vm->scene()->worldstats()->actorType) {
default:
resourceId = (ResourceId)index;
break;
case kActorMax:
resourceId = MAKE_RESOURCE(kResourcePackSpeech, index < 259 ? index : index - 9);
break;
case kActorSarah:
resourceId = MAKE_RESOURCE(kResourcePackSharedSound, index + 1927);
break;
case kActorCyclops:
resourceId = MAKE_RESOURCE(kResourcePackSharedSound, index + 2084);
break;
case kActorAztec:
resourceId = MAKE_RESOURCE(kResourcePackSharedSound, index + 2234);
break;
}
if (vm->speech()->getSoundResourceId() != resourceId || !vm->sound()->isPlaying(resourceId))
vm->speech()->playPlayer(index);
}
} // End of namespace Asylum

View File

@@ -0,0 +1,62 @@
/* 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 ASYLUM_RESOURCES_INVENTORY_H
#define ASYLUM_RESOURCES_INVENTORY_H
#include "common/serializer.h"
#include "common/stream.h"
#include "asylum/asylum.h"
namespace Asylum {
class Inventory : public Common::Serializable {
public:
Inventory(AsylumEngine *vm, int32 &multiple);
uint find(uint item = 0) const;
void add(uint item, uint multipleIncr);
void remove(uint item, uint multipleDecr);
bool contains(uint item, uint multiple) const;
void copyFrom(Inventory &inventory);
uint getSelectedItem() const { return _selectedItem; }
void selectItem(uint item) { _selectedItem = item; }
void load(Common::SeekableReadStream *stream);
void saveLoadWithSerializer(Common::Serializer &s);
uint32 &operator[](uint index) { return _items[index]; }
static Common::Point getInventoryRingPoint(AsylumEngine *vm, uint nPoints, uint index);
static void describe(AsylumEngine *vm, uint item);
private:
uint32 _items[8];
uint32 _selectedItem;
int32 &_multiple;
AsylumEngine *_vm;
};
} // End of namespace Asylum
#endif // ASYLUM_RESOURCES_INVENTORY_H

View File

@@ -0,0 +1,612 @@
/* 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 "asylum/resources/object.h"
#include "asylum/resources/actor.h"
#include "asylum/resources/special.h"
#include "asylum/resources/worldstats.h"
#include "asylum/system/graphics.h"
#include "asylum/system/screen.h"
#include "asylum/views/scene.h"
#include "asylum/asylum.h"
#include "asylum/respack.h"
namespace Asylum {
Object::Object(AsylumEngine *engine) : x(0), y(0), flags(0), actionType(0),
_vm(engine), /* _index(0), */
_id(kObjectNone), _resourceId(kResourceNone), _field_20(0), _frameIndex(0), _frameCount(0),
_field_2C(0), _field_30(0), _field_34(0), _field_3C(0), _polygonIndex(0), _field_B4(0),
_tickCount(0), _tickCount2(0), _field_C0(0), _priority(0), _scriptIndex(0), _transparency(0),
_field_688(0), _soundResourceId(kResourceNone), _field_6A4(kDirectionN) {
memset(&_name, 0, sizeof(_name));
memset(&_gameFlags, 0, sizeof(_gameFlags));
memset(&_randomResourceIds, 0, sizeof(_randomResourceIds));
}
/////////////////////////////////////////////////////////////////////////
// Loading & destroying
/////////////////////////////////////////////////////////////////////////
void Object::load(Common::SeekableReadStream *stream) {
_id = (ObjectId)stream->readSint32LE();
_resourceId = (ResourceId)stream->readSint32LE();
x = (int16)stream->readSint32LE();
y = (int16)stream->readSint32LE();
_boundingRect.left = (int16)(stream->readSint32LE() & 0xFFFF);
_boundingRect.top = (int16)(stream->readSint32LE() & 0xFFFF);
_boundingRect.right = (int16)(stream->readSint32LE() & 0xFFFF);
_boundingRect.bottom = (int16)(stream->readSint32LE() & 0xFFFF);
_field_20 = stream->readSint32LE();
_frameIndex = stream->readUint32LE();
_frameCount = stream->readUint32LE();
_field_2C = stream->readSint32LE();
_field_30 = stream->readSint32LE();
_field_34 = stream->readSint32LE();
flags = stream->readUint32LE();
_field_3C = stream->readSint32LE();
stream->read(_name, sizeof(_name));
_rect.left = (int16)(stream->readSint32LE());
_rect.top = (int16)(stream->readSint32LE());
_rect.right = (int16)(stream->readSint32LE());
_rect.bottom = (int16)(stream->readSint32LE());
_polygonIndex = stream->readUint32LE();
actionType = stream->readSint32LE();
for (int i = 0; i < 10; i++)
_gameFlags[i] = stream->readSint32LE();
_field_B4 = stream->readSint32LE();
_tickCount = stream->readUint32LE();
_tickCount2 = stream->readUint32LE();
_field_C0 = stream->readUint32LE();
_priority = stream->readSint32LE();
_scriptIndex = stream->readSint32LE();
for (int i = 0; i < 16; i++) {
_soundItems[i].resourceId = (ResourceId)stream->readSint32LE();
_soundItems[i].field_4 = stream->readSint32LE();
_soundItems[i].field_8 = stream->readSint32LE();
_soundItems[i].field_C = stream->readSint32LE();
}
for (int i = 0; i < 50; i++) {
_frameSoundItems[i].resourceId = (ResourceId)stream->readSint32LE();
_frameSoundItems[i].frameIndex = stream->readUint32LE();
_frameSoundItems[i].index = stream->readSint32LE();
_frameSoundItems[i].field_C = stream->readSint32LE();
_frameSoundItems[i].field_10 = stream->readSint32LE();
_frameSoundItems[i].field_14 = stream->readSint32LE();
}
_transparency = stream->readSint32LE();
_soundCoords.x = (int16)stream->readSint32LE();
_soundCoords.y = (int16)stream->readSint32LE();
_field_688 = stream->readSint32LE();
for (int i = 0; i < 5; i++)
_randomResourceIds[i] = (ResourceId)stream->readSint32LE();
_soundResourceId = (ResourceId)stream->readSint32LE();
if (_vm->checkGameVersion("Demo"))
return;
_field_6A4 = (ActorDirection)stream->readSint32LE();
}
void Object::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(_id);
s.syncAsSint32LE(_resourceId);
s.syncAsSint32LE(x);
s.syncAsSint32LE(y);
s.syncAsSint32LE(_boundingRect.left);
s.syncAsSint32LE(_boundingRect.top);
s.syncAsSint32LE(_boundingRect.right);
s.syncAsSint32LE(_boundingRect.bottom);
s.syncAsSint32LE(_field_20);
s.syncAsUint32LE(_frameIndex);
s.syncAsUint32LE(_frameCount);
s.syncAsSint32LE(_field_2C);
s.syncAsSint32LE(_field_30);
s.syncAsSint32LE(_field_34);
s.syncAsUint32LE(flags);
s.syncAsSint32LE(_field_3C);
s.syncBytes((byte *)&_name, sizeof(_name));
s.syncAsSint32LE(_rect.left);
s.syncAsSint32LE(_rect.top);
s.syncAsSint32LE(_rect.right);
s.syncAsSint32LE(_rect.bottom);
s.syncAsUint32LE(_polygonIndex);
s.syncAsSint32LE(actionType);
for (int i = 0; i < ARRAYSIZE(_gameFlags); i++)
s.syncAsSint32LE(_gameFlags[i]);
s.syncAsSint32LE(_field_B4);
s.syncAsUint32LE(_tickCount);
s.syncAsUint32LE(_tickCount2);
s.syncAsUint32LE(_field_C0);
s.syncAsSint32LE(_priority);
s.syncAsSint32LE(_scriptIndex);
for (int i = 0; i < ARRAYSIZE(_soundItems); i++) {
s.syncAsSint32LE(_soundItems[i].resourceId);
s.syncAsSint32LE(_soundItems[i].field_4);
s.syncAsSint32LE(_soundItems[i].field_8);
s.syncAsSint32LE(_soundItems[i].field_C);
}
for (int i = 0; i < ARRAYSIZE(_frameSoundItems); i++) {
s.syncAsSint32LE(_frameSoundItems[i].resourceId);
s.syncAsUint32LE(_frameSoundItems[i].frameIndex);
s.syncAsSint32LE(_frameSoundItems[i].index);
s.syncAsSint32LE(_frameSoundItems[i].field_C);
s.syncAsSint32LE(_frameSoundItems[i].field_10);
s.syncAsSint32LE(_frameSoundItems[i].field_14);
}
s.syncAsSint32LE(_transparency);
s.syncAsSint32LE(_soundCoords.x);
s.syncAsSint32LE(_soundCoords.y);
s.syncAsSint32LE(_field_688);
for (int i = 0; i < ARRAYSIZE(_randomResourceIds); i++)
s.syncAsSint32LE(_randomResourceIds[i]);
s.syncAsSint32LE(_soundResourceId);
s.syncAsSint32LE(_field_6A4);
}
void Object::disable() {
flags &= ~kObjectFlagEnabled;
}
void Object::disableAndRemoveFromQueue() {
disable();
flags |= kObjectFlag20000;
getScreen()->deleteGraphicFromQueue(_resourceId);
}
//////////////////////////////////////////////////////////////////////////
// Visibility
//////////////////////////////////////////////////////////////////////////
bool Object::isOnScreen() {
Common::Rect screenRect = Common::Rect((int16)getWorld()->xLeft, (int16)getWorld()->yTop, (int16)(getWorld()->xLeft + 640), (int16)(getWorld()->yTop + 480));
Common::Rect objectRect = Common::Rect(_boundingRect);
objectRect.translate((int16)x, (int16)y);
return isVisible() && (flags & kObjectFlagEnabled) && screenRect.intersects(objectRect);
}
bool Object::isVisible() const {
if (!(flags & kObjectFlagEnabled))
return false;
// Check each game flag
for (int32 i = 0; i < 10; i++) {
int32 flag = _gameFlags[i];
bool ok = false;
if (flag <= 0)
ok = _vm->isGameFlagNotSet((GameFlag)-flag);
else
ok = _vm->isGameFlagSet((GameFlag)flag);
if (!ok)
return false;
}
// All flags were ok, we are done!
return true;
}
void Object::adjustCoordinates(Common::Point *point) {
if (!point)
error("[Actor::adjustCoordinates] Invalid point parameter!");
point->x += x - getWorld()->xLeft;
point->y += y - getWorld()->yTop;
}
/////////////////////////////////////////////////////////////////////////
// Update
//////////////////////////////////////////////////////////////////////////
void Object::draw() {
if (flags & kObjectFlag4)
return;
if (BYTE1(flags) & kObjectFlag40)
return;
if (!isOnScreen())
return;
// Draw the object
Common::Point point;
adjustCoordinates(&point);
if (_transparency <= 0 || _transparency >= 4 || Config.performance <= 1) {
getScreen()->addGraphicToQueue(_resourceId, _frameIndex, point, (DrawFlags)((flags >> 11) & kDrawFlagMirrorLeftRight), _transparency - 3, _priority);
} else {
getScreen()->addGraphicToQueueCrossfade(_resourceId, _frameIndex, point, getWorld()->backgroundImage, Common::Point(getWorld()->xLeft, getWorld()->yTop), (uint32)(_transparency - 1));
}
}
void Object::update() {
if (_frameCount == 0)
error("[Object::update] Object has no frame!");
bool doPlaySounds = false;
if (_field_3C != 4)
return;
if (!isVisible()) {
updateSoundItems();
return;
}
// Examine flags
if (flags & kObjectFlag20) {
if (_vm->getTick() - _tickCount >= (uint32)Common::Rational(1000, _field_B4).toInt()) {
_frameIndex = (_frameIndex + 1) % _frameCount;
_tickCount = _vm->getTick();
doPlaySounds = true;
}
} else if (flags & kObjectFlag10) {
bool isFirstFrame = (_frameIndex == 0);
if (!_frameIndex) {
if (_vm->getTick() - _tickCount >= 1000 * _tickCount2) {
if (_vm->getRandom(_field_C0) == 1) {
if (_randomResourceIds[0]) {
_resourceId = getRandomResourceId();
_frameCount = GraphicResource::getFrameCount(_vm, _resourceId);
}
_frameIndex++;
}
_tickCount = _vm->getTick();
doPlaySounds = true;
}
isFirstFrame = (_frameIndex == 0);
}
if (!isFirstFrame) {
if (_vm->getTick() - _tickCount >= (uint32)Common::Rational(1000, _field_B4).toInt()) {
_frameIndex = (_frameIndex + 1) % _frameCount;
_tickCount = _vm->getTick();
doPlaySounds = true;
}
}
} else if (BYTE1(flags) & kObjectFlag8) {
if (_vm->getTick() - _tickCount >= 1000 * _tickCount2) {
if (_vm->getRandom(_field_C0) == 1)
_frameIndex = (_frameIndex + 1) % _frameCount;
_tickCount = _vm->getTick();
doPlaySounds = true;
}
} else if (flags & kObjectFlag8) {
if (_vm->getTick() - _tickCount >= (uint32)Common::Rational(1000, _field_B4).toInt()) {
++_frameIndex;
if (_frameIndex < _frameCount - 1) {
if (_field_688 == 1) {
Common::Rect frameRect = GraphicResource::getFrameRect(_vm, _resourceId, _frameIndex);
getSharedData()->setGlobalPoint(Common::Point(x + frameRect.left + (int16)Common::Rational(frameRect.width(), 2).toInt(),
y + frameRect.top + (int16)Common::Rational(frameRect.height(), 2).toInt()));
}
} else {
flags &= ~kObjectFlag8;
if (_field_688 == 1)
getSharedData()->setGlobalPoint(Common::Point(-1, -1));
}
_tickCount = _vm->getTick();
doPlaySounds = true;
}
} else if (!(BYTE1(flags) & kObjectFlag6)) {
if ((flags & kObjectFlag10000) && (_vm->getTick() - _tickCount >= (uint32)Common::Rational(1000, _field_B4).toInt())) {
--_frameIndex;
if (_frameIndex == 0) {
flags &= ~kObjectFlag10000;
if (_field_688 == 1)
getSharedData()->setGlobalPoint(Common::Point(-1, -1));
} else if (_field_688 == 1) {
Common::Rect frameRect = GraphicResource::getFrameRect(_vm, _resourceId, _frameIndex);
getSharedData()->setGlobalPoint(Common::Point(x + frameRect.left + (int16)Common::Rational(frameRect.width(), 2).toInt(),
y + frameRect.top + (int16)Common::Rational(frameRect.height(), 2).toInt()));
}
_tickCount = _vm->getTick();
doPlaySounds = true;
}
} else if (_vm->getTick() - _tickCount >= (uint32)Common::Rational(1000, _field_B4).toInt()) {
if (BYTE1(flags) & kObjectFlag2) {
if (_frameIndex == _frameCount - 1) {
_frameIndex--;
BYTE1(flags) = (BYTE1(flags) & 0xFD) | kObjectFlag4;
} else {
_frameIndex++;
}
} else if (BYTE1(flags) & kObjectFlag4) {
if (_frameIndex) {
_frameIndex--;
} else {
_frameIndex = 1;
BYTE1(flags) = (BYTE1(flags) & 0xFB) | kObjectFlag2;
}
}
_tickCount = _vm->getTick();
doPlaySounds = true;
}
if (flags & kObjectFlag40000) {
if (_frameIndex == _frameCount - 1) {
if (_field_B4 <= 15) {
_field_B4 -= 2;
if (_field_B4 < 0)
_field_B4 = 0;
} else {
_field_B4 = 15;
}
if (!_field_B4)
flags &= ~kObjectFlag10E38;
}
}
if (doPlaySounds)
playSounds();
getSpecial()->run(this, -1);
}
void Object::setNextFrame(uint32 targetFlags) {
flags |= targetFlags | kObjectFlagEnabled;
if (flags & kObjectFlag10000)
_frameIndex = _frameCount - 1;
else
_frameIndex = 0;
}
/////////////////////////////////////////////////////////////////////////
// Misc
/////////////////////////////////////////////////////////////////////////
void Object::playSounds() {
Common::Point point;
if (_soundCoords.x || _soundCoords.y) {
point = _soundCoords;
} else {
if (LOBYTE(flags) & kObjectFlag4) {
// Get object resource
ResourceEntry *resource = getResource()->get(_resourceId);
point.x = x + (int16)Common::Rational(resource->getData(4), 2).toInt();
point.y = y + (int16)Common::Rational(resource->getData(0), 2).toInt();
} else {
Common::Rect rect = GraphicResource::getFrameRect(_vm, _resourceId, _frameIndex);
point.x = (int16)(x + (rect.width() / 2));
point.y = (int16)(y + (rect.height() / 2));
}
}
for (int i = 0; i < ARRAYSIZE(_soundItems); i++) {
SoundItem *item = &_soundItems[i];
if (item->resourceId == kResourceNone)
continue;
if (item->field_4 && !getSound()->isPlaying(item->resourceId)) {
int32 volume = Config.sfxVolume + getSound()->calculateVolumeAdjustement(point, item->field_8, item->field_C);
if (volume > -5000)
getSound()->playSound(item->resourceId, true, volume, getSound()->calculatePanningAtPoint(point));
}
if (getSound()->isPlaying(item->resourceId)) {
int32 volume = Config.sfxVolume + getSound()->calculateVolumeAdjustement(point, item->field_8, item->field_C);
if (volume > -5000) {
if (volume > 0)
volume = 0;
getSound()->setPanning(item->resourceId, getSound()->calculatePanningAtPoint(point));
getSound()->setVolume(item->resourceId, volume);
} else {
getSound()->stop(item->resourceId);
item->resourceId = kResourceNone;
}
}
}
for (int i = 0; i < ARRAYSIZE(_frameSoundItems); i++) {
FrameSoundItem *item = &_frameSoundItems[i];
if (item->frameIndex == _frameIndex) {
if (item->resourceId) {
if (_soundItems[item->index].resourceId && !_soundItems[item->index].field_4) {
getSound()->stop(_soundItems[item->index].resourceId);
_soundItems[item->index].resourceId = kResourceNone;
}
_soundItems[item->index].resourceId = item->resourceId;
_soundItems[item->index].field_4 = item->field_10;
_soundItems[item->index].field_8 = item->field_C;
_soundItems[item->index].field_C = item->field_14;
if (!getSound()->isPlaying(item->resourceId)) {
int32 volume = Config.sfxVolume + getSound()->calculateVolumeAdjustement(point, item->field_C, item->field_14);
if (volume > -5000)
getSound()->playSound(item->resourceId, item->field_10, volume, getSound()->calculatePanningAtPoint(point));
}
}
} else if (item->frameIndex > _frameIndex || !item->resourceId) {
break;
}
}
setVolume();
}
void Object::updateSoundItems() {
for (int32 i = 0; i < ARRAYSIZE(_soundItems); i++) {
SoundItem *item = &_soundItems[i];
if (getSound()->isPlaying(item->resourceId)) {
if (item->field_4) {
getSound()->stop(item->resourceId);
item->resourceId = kResourceNone;
item->field_4 = 0;
}
}
}
stopSound();
}
void Object::stopSound() {
if (getSound()->isPlaying(_soundResourceId))
getSound()->stop(_soundResourceId);
}
void Object::stopAllSounds() {
for (int i = 0; i < ARRAYSIZE(_soundItems); i++)
if (_soundItems[i].resourceId) {
getSound()->stop(_soundItems[i].resourceId);
_soundItems[i].resourceId = kResourceNone;
}
}
void Object::setVolume() {
if (!_soundResourceId || !getSound()->isPlaying(_soundResourceId))
return;
Common::Rect frameRect = GraphicResource::getFrameRect(_vm, _resourceId, _frameIndex);
// Compute volume
Common::Point coords((int16)Common::Rational(frameRect.width(), 2).toInt() + x, (int16)Common::Rational(frameRect.height(), 2).toInt() + y);
int32 volume = Config.voiceVolume + getSound()->calculateVolumeAdjustement(coords, _field_6A4, 0);
if (volume < -10000)
volume = -10000;
getSound()->setVolume(_soundResourceId, volume);
}
ResourceId Object::getRandomResourceId() {
// Initialize random resource id array
ResourceId shuffle[5];
memset(&shuffle, 0, sizeof(shuffle));
uint32 count = 0;
for (int32 i = 0; i < 5; i++) {
if (_randomResourceIds[i]) {
shuffle[count] = _randomResourceIds[i];
count++;
}
}
if (count == 0)
error("[Object::getRandomId] Could not get a random resource id!");
ResourceId id = shuffle[_vm->getRandom(count)];
if (id == kResourceNone)
error("[Object::getRandomId] Got an empty resource id!");
return id;
}
bool Object::checkFlags() const {
return (flags & kObjectFlagEnabled) && ((flags & kObjectFlag8) || (flags & kObjectFlag10000));
}
Common::String Object::toString(bool shortString) {
Common::String output;
output += Common::String::format("Object %d: %s\n", _id, _name);
if (!shortString) {
output += Common::String::format(" resourceId: %u (0x%X) - (pack %d - index %d)\n", _resourceId, _resourceId, RESOURCE_PACK(_resourceId), RESOURCE_INDEX(_resourceId));
output += Common::String::format(" name: %s\n", _name);
output += Common::String::format(" x: %d\n", x);
output += Common::String::format(" y: %d\n", y);
output += Common::String::format(" flags: %d\n", flags);
output += Common::String::format(" actionType: %d\n", actionType);
output += Common::String::format(" boundingRect: top[%d], left[%d], right[%d], bottom[%d]\n", _boundingRect.top, _boundingRect.left, _boundingRect.right, _boundingRect.bottom);
output += Common::String::format(" field_20: %d\n", _field_20);
output += Common::String::format(" frameIndex: %u\n", _frameIndex);
output += Common::String::format(" frameCount: %u\n", _frameCount);
output += Common::String::format(" field_2C: %d\n", _field_2C);
output += Common::String::format(" field_30: %d\n", _field_30);
output += Common::String::format(" field_34: %d\n", _field_34);
output += Common::String::format(" field_3C: %d\n", _field_3C);
output += Common::String::format(" rect: top[%d], left[%d], right[%d], bottom[%d]\n", _rect.top, _rect.left, _rect.right, _rect.bottom);
output += Common::String::format(" polygonIndex: %d\n", _polygonIndex);
output += Common::String::format(" field_B4: %d\n", _field_B4);
output += Common::String::format(" tickCount: %d\n", _tickCount);
output += Common::String::format(" tickCount2: %d\n", _tickCount2);
output += Common::String::format(" field_C0: %d\n", _field_C0);
output += Common::String::format(" priority: %d\n", _priority);
output += Common::String::format(" scriptIndex: %d\n", _scriptIndex);
output += Common::String::format(" transparency %d\n", _transparency);
output += Common::String::format(" soundCoords: (%d, %d)\n", _soundCoords.x, _soundCoords.y);
output += Common::String::format(" field_688: %d\n", _field_688);
output += Common::String::format(" soundResourceId: %d\n", _soundResourceId);
output += Common::String::format(" field_6A4: %d\n", _field_6A4);
}
return output;
}
} // end of namespace Asylum

View File

@@ -0,0 +1,243 @@
/* 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 ASYLUM_RESOURCES_OBJECT_H
#define ASYLUM_RESOURCES_OBJECT_H
#include "common/rect.h"
#include "common/serializer.h"
#include "common/stream.h"
#include "asylum/shared.h"
#include "asylum/system/sound.h"
namespace Asylum {
class Actor;
class AsylumEngine;
class Object : public Common::Serializable {
public:
Object(AsylumEngine *engine);
virtual ~Object() {};
//////////////////////////////////////////////////////////////////////////
// Public variables & accessors
//////////////////////////////////////////////////////////////////////////
int16 x;
int16 y;
uint32 flags;
int32 actionType;
void setFrameIndex(int32 index) { _frameIndex = index; }
void setPriority(int32 priority) { _priority = priority; }
void setSoundResourceId(ResourceId id) { _soundResourceId = id; }
void setTransparency(int32 val) { _transparency = val; }
void setField6A4(ActorDirection val) { _field_6A4 = val; }
Common::Rect *getBoundingRect() { return &_boundingRect; }
uint32 getFrameIndex() { return _frameIndex; }
uint32 getFrameCount() { return _frameCount; }
FrameSoundItem *getFrameSoundItem(uint32 index) { assert(index < ARRAYSIZE(_frameSoundItems)); return &_frameSoundItems[index]; }
ObjectId getId() { return _id; }
uint32 getPolygonIndex() { return _polygonIndex; }
int32 getPriority() { return _priority; }
ResourceId getResourceId() { return _resourceId; }
ResourceId getSoundResourceId() { return _soundResourceId; }
Common::Rect *getRect() { return &_rect; }
int32 getScriptIndex() { return _scriptIndex; }
int32 getSoundY() { return _soundCoords.y; }
int32 getTransparency() { return _transparency; }
int32 getField688() { return _field_688; }
ActorDirection getField6A4() { return _field_6A4; }
/////////////////////////////////////////////////////////////////////////
// Loading & disabling
/////////////////////////////////////////////////////////////////////////
/**
* Loads the object data
*
* @param stream If non-null, the Common::SeekableReadStream to load from
*/
void load(Common::SeekableReadStream *stream);
/**
* Sets the object disabled flag
*/
void disable();
/**
* Sets the object destroyed flag and remove this object from the graphics queue
*/
void disableAndRemoveFromQueue();
/////////////////////////////////////////////////////////////////////////
// Visibility
//////////////////////////////////////////////////////////////////////////
/**
* Query if this object is on screen.
*
* @return true if on screen, false if not.
*/
bool isOnScreen();
/**
* Adjust coordinates.
*
* @param point The point.
*/
void adjustCoordinates(Common::Point *point);
/////////////////////////////////////////////////////////////////////////
// Drawing & update
//////////////////////////////////////////////////////////////////////////
/**
* Draws the object
*/
void draw();
/**
* Updates the object.
*/
void update();
/**
* Sets the next frame.
*
* @param flags The flags.
*/
void setNextFrame(uint32 flags);
/////////////////////////////////////////////////////////////////////////
// Misc
////////////////////////////////////////////////////////////////////////
/**
* Stop the object related sounds
*/
void stopSound();
/**
* Stop all object sounds (called from scripts)
*/
void stopAllSounds();
/**
* Checks the object flags
*
* @return true if it succeeds, false if it fails.
*/
bool checkFlags() const;
char *getName() { return _name; }
/**
* Convert this object into a string representation.
*
* @param shortString toggle for displaying the full dump or just a
* short summary string
* @return A string representation of this object.
*/
Common::String toString(bool shortString = true);
// Serializable
void saveLoadWithSerializer(Common::Serializer &s);
private:
AsylumEngine *_vm;
//int32 _index; ///< our index
//////////////////////////////////////////////////////////////////////////
// Data
//////////////////////////////////////////////////////////////////////////
ObjectId _id;
ResourceId _resourceId;
// x, y
Common::Rect _boundingRect;
int32 _field_20;
uint32 _frameIndex;
uint32 _frameCount;
int32 _field_2C;
int32 _field_30;
int32 _field_34;
// flags
int32 _field_3C;
char _name[52];
Common::Rect _rect;
uint32 _polygonIndex;
// actionType
int32 _gameFlags[10];
int32 _field_B4;
uint32 _tickCount;
uint32 _tickCount2;
uint32 _field_C0;
int32 _priority;
int32 _scriptIndex;
SoundItem _soundItems[16];
FrameSoundItem _frameSoundItems[50];
int32 _transparency;
Common::Point _soundCoords;
int32 _field_688;
ResourceId _randomResourceIds[5];
ResourceId _soundResourceId;
ActorDirection _field_6A4;
/**
* Query if this object is visible.
*
* @return true if visible, false if not.
*/
bool isVisible() const;
/**
* Play object sounds
*/
void playSounds();
/**
* Check if any items in the object sound array are playing,
* and based on their flag values, stop them accordingly
*/
void updateSoundItems();
/**
* Sets the volume.
*/
void setVolume();
/**
* Gets a random resource identifier for this object (using the list in _randomResourceIds)
*
* @return The random resource identifier.
*/
ResourceId getRandomResourceId();
}; // end of class Object
} // end of namespace Asylum
#endif // ASYLUM_RESOURCES_OBJECT_H

View File

@@ -0,0 +1,107 @@
/* 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 "asylum/resources/polygons.h"
namespace Asylum {
//////////////////////////////////////////////////////////////////////////
// Contains
//////////////////////////////////////////////////////////////////////////
bool Polygon::contains(const Common::Point &point) {
// Copied from backends/vkeybd/polygon.cpp
bool yflag0;
bool yflag1;
bool inside_flag = false;
// if no points are defined, an intersect check will fail
// (count - 1 would trigger an assertion in vtx0)
if (points.size() == 0)
return false;
Common::Point *vtx0 = &points[count() - 1];
Common::Point *vtx1 = &points[0];
yflag0 = (vtx0->y > point.y);
for (uint32 pt = 0; pt < count(); pt++, vtx1++) {
if (point == *vtx1)
return true;
yflag1 = (vtx1->y > point.y);
if (yflag0 != yflag1) {
if (((vtx1->y - point.y) * (vtx0->x - vtx1->x) > (vtx1->x - point.x) * (vtx0->y - vtx1->y)) == yflag1) {
inside_flag = !inside_flag;
}
}
yflag0 = yflag1;
vtx0 = vtx1;
}
return inside_flag;
}
//////////////////////////////////////////////////////////////////////////
// Polygons
//////////////////////////////////////////////////////////////////////////
Polygons::Polygons(Common::SeekableReadStream *stream) : _size(0), _numEntries(0) {
load(stream);
}
Polygons::~Polygons() {
_entries.clear();
}
Polygon Polygons::get(uint32 index) {
if (index >= _entries.size())
error("[Polygons::getEntry] Invalid polygon index (was: %d, max: %d)", index, _entries.size() - 1);
return _entries[index];
}
void Polygons::load(Common::SeekableReadStream *stream) {
_size = stream->readSint32LE();
_numEntries = stream->readSint32LE();
for (int32 g = 0; g < _numEntries; g++) {
Polygon poly;
uint32 numPoints = stream->readUint32LE();
for (uint32 i = 0; i < numPoints; i++) {
Common::Point point;
point.x = (int16)(stream->readSint32LE() & 0xFFFF);
point.y = (int16)(stream->readSint32LE() & 0xFFFF);
poly.points.push_back(point);
}
stream->skip((MAX_POLYGONS - numPoints) * 8);
poly.boundingRect.left = (int16)(stream->readSint32LE() & 0xFFFF);
poly.boundingRect.top = (int16)(stream->readSint32LE() & 0xFFFF);
poly.boundingRect.right = (int16)(stream->readSint32LE() & 0xFFFF);
poly.boundingRect.bottom = (int16)(stream->readSint32LE() & 0xFFFF);
_entries.push_back(poly);
}
}
} // end of namespace Asylum

View File

@@ -0,0 +1,69 @@
/* 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 ASYLUM_RESOURCES_POLYGONS_H
#define ASYLUM_RESOURCES_POLYGONS_H
#include "common/array.h"
#include "common/rect.h"
#include "common/stream.h"
#define MAX_POLYGONS 200
namespace Asylum {
class Polygon {
public:
Common::Array<Common::Point> points;
Common::Rect boundingRect;
Polygon() {};
Polygon(Common::Point point1, Common::Point point2, Common::Point point3, Common::Point point4) {
points.push_back(point1);
points.push_back(point2);
points.push_back(point3);
points.push_back(point4);
}
bool contains(const Common::Point &point);
uint32 count() { return points.size(); }
};
class Polygons {
public:
Polygons(Common::SeekableReadStream *stream);
virtual ~Polygons();
Polygon get(uint32 index);
uint32 size() { return _entries.size(); }
private:
int32 _size;
int32 _numEntries;
Common::Array<Polygon> _entries;
void load(Common::SeekableReadStream *stream);
}; // end of class Polygons
} // end of namespace Asylum
#endif // ASYLUM_RESOURCES_POLYGONS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,456 @@
/* 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 ASYLUM_RESOURCES_SCRIPT_H
#define ASYLUM_RESOURCES_SCRIPT_H
#include "common/array.h"
#include "common/func.h"
#include "common/serializer.h"
#include "common/stack.h"
#include "common/stream.h"
#include "asylum/shared.h"
namespace Asylum {
#define MAX_ACTION_COMMANDS 161
#define DECLARE_OPCODE(name) \
void Op##name(ScriptEntry *cmd)
#define IMPLEMENT_OPCODE(name) \
void ScriptManager::Op##name(ScriptEntry *cmd) { \
if (!_currentScript) error("[" #name "] No current script set"); \
if (!_currentQueueEntry) error("[" #name "] Invalid current queue entry"); \
if (!cmd) error("[" #name "] Invalid command parameter");
#define END_OPCODE }
#define ADD_OPCODE(name) { \
Opcode *func = new Opcode(#name, new Common::Functor1Mem<ScriptEntry *, void, ScriptManager>(this, &ScriptManager::Op##name)); \
_opcodes.push_back(func); \
}
class Actor;
class AsylumEngine;
class Scene;
struct ActionArea : public Common::Serializable {
char name[52];
int32 id;
int32 field01;
int32 field02;
int32 field_40;
int32 field_44;
int32 flags;
int32 scriptIndex;
int32 scriptIndex2;
int32 actionType; ///< flag (see ActionType enumeration)
int32 flagNums[10];
int32 field_7C;
uint32 polygonIndex;
ResourceId soundResourceIdFrame;
int32 field_88;
ResourceId soundResourceId;
int32 field_90;
ResourceId paletteResourceId;
int32 paths[5];
int32 volume;
ActionArea() {
memset(&name, 0, sizeof(name));
id = 0;
field01 = 0;
field02 = 0;
field_40 = 0;
field_44 = 0;
flags = 0;
scriptIndex = 0;
scriptIndex2 = 0;
actionType = 0;
memset(&flagNums, 0, sizeof(flagNums));
field_7C = 0;
polygonIndex = 0;
soundResourceIdFrame = kResourceNone;
field_88 = 0;
soundResourceId = kResourceNone;
field_90 = 0;
paletteResourceId = kResourceNone;
memset(&paths, 0, sizeof(paths));
volume = 0;
}
void load(Common::SeekableReadStream *stream);
Common::String toString() {
Common::String output;
output += Common::String::format("Action %d: %s\n", id, name);
output += Common::String::format(" flags=%d scriptIndex=%d scriptIndex2=%d type=%d\n", flags, scriptIndex, scriptIndex2, actionType);
output += Common::String::format(" sound=%d polygon=%d palette=%d volume=%d\n", soundResourceId, polygonIndex, paletteResourceId, volume);
output += Common::String::format(" field01=%d field02=%d field40=%d field44=%d\n", field01, field02, field_40, field_44);
output += Common::String::format(" field7C=%d field84=%d field88=%d field90=%d\n", field_7C, soundResourceIdFrame, field_88, field_90);
return output;
}
// Serializable
void saveLoadWithSerializer(Common::Serializer &s);
};
class ScriptManager : public Common::Serializable {
public:
ScriptManager(AsylumEngine *engine);
virtual ~ScriptManager();
/**
* Loads the script entries
*
* @param stream the script data stream
*/
void load(Common::SeekableReadStream *stream);
/**
* Process the current script
*/
bool process();
/**
* Fully resets script manager state (used while changing scenes)
*/
void resetAll();
/**
* Resets the queue and local variables
*/
void reset(uint32 count = 0);
/**
* Initialize the script element at actionIndex to
* the actor at actorIndex
*/
void queueScript(int32 scriptIndex, ActorIndex actorIndex);
/**
* Query if 'scriptIndex' is in queue.
*
* @param scriptIndex Zero-based index of the script.
*
* @return true if in queue, false if not.
*/
bool isInQueue(int32 scriptIndex) const;
/**
* Remove a script element from the queue
*/
void removeFromQueue(uint32 entryIndex);
/**
* Resets the queue.
*/
void resetQueue();
// Serializable
void saveLoadWithSerializer(Common::Serializer &s);
void saveQueue(Common::Serializer &s);
private:
enum ObjectTransparency {
kObjectEnableType0,
kObjectEnableType1,
kObjectTransparencyOpaque
};
//////////////////////////////////////////////////////////////////////////
// Script Queue
//////////////////////////////////////////////////////////////////////////
struct ScriptQueueEntry : public Common::Serializable {
int32 scriptIndex;
int32 currentLine;
ActorIndex actorIndex;
uint32 next;
uint32 prev;
ScriptQueueEntry() {
reset();
}
void reset() {
scriptIndex = -1;
currentLine = 0;
actorIndex = 0;
next = 0;
prev = 0;
}
void saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(scriptIndex);
s.syncAsSint32LE(currentLine);
s.syncAsUint32LE(actorIndex);
s.syncAsUint32LE(next);
s.syncAsUint32LE(prev);
}
};
struct ScriptQueue : public Common::Serializable {
ScriptQueueEntry entries[10];
uint32 first;
uint32 last;
ScriptQueue() {
reset();
}
void reset() {
for (uint32 i = 0; i < ARRAYSIZE(entries); i++)
entries[i].reset();
first = 0;
last = 0;
}
void saveLoadWithSerializer(Common::Serializer &s) {
for (uint32 i = 0; i < ARRAYSIZE(entries); i++)
entries[i].saveLoadWithSerializer(s);
s.syncAsUint32LE(first);
s.syncAsUint32LE(last);
}
};
//////////////////////////////////////////////////////////////////////////
// Scripts
//////////////////////////////////////////////////////////////////////////
struct ScriptEntry : public Common::Serializable {
int32 numLines; // Only set on the first line of each script
OpcodeType opcode;
int32 param1;
int32 param2;
int32 param3;
int32 param4;
int32 param5;
int32 param6;
int32 param7;
int32 param8;
int32 param9;
ScriptEntry() {
numLines = 0;
opcode = kOpcodeReturn;
param1 = 0;
param2 = 0;
param3 = 0;
param4 = 0;
param5 = 0;
param6 = 0;
param7 = 0;
param8 = 0;
param9 = 0;
}
void saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(numLines);
s.syncAsSint32LE(opcode);
s.syncAsSint32LE(param1);
s.syncAsSint32LE(param2);
s.syncAsSint32LE(param3);
s.syncAsSint32LE(param4);
s.syncAsSint32LE(param5);
s.syncAsSint32LE(param6);
s.syncAsSint32LE(param7);
s.syncAsSint32LE(param8);
s.syncAsSint32LE(param9);
}
};
struct Script : public Common::Serializable {
ScriptEntry commands[MAX_ACTION_COMMANDS];
int32 field_1BAC;
int32 field_1BB0;
int32 counter;
Script() {
field_1BAC = 0;
field_1BB0 = 0;
counter = 0;
}
void saveLoadWithSerializer(Common::Serializer &s) {
for (int32 i = 0; i < ARRAYSIZE(commands); i++)
commands[i].saveLoadWithSerializer(s);
s.syncAsSint32LE(field_1BAC);
s.syncAsSint32LE(field_1BB0);
s.syncAsSint32LE(counter);
}
};
//////////////////////////////////////////////////////////////////////////
// Opcodes
//////////////////////////////////////////////////////////////////////////
typedef Common::Functor1<ScriptEntry *, void> OpcodeFunctor;
struct Opcode {
const char *name;
OpcodeFunctor *func;
Opcode(const char *opcodeName, OpcodeFunctor *functor) {
name = opcodeName;
func = functor;
}
~Opcode() {
delete func;
}
};
// Engine
AsylumEngine *_vm;
// Script queue and data
ScriptQueue _queue;
Common::Array<Opcode *> _opcodes;
Common::Array<Script> _scripts;
bool _done;
bool _exit;
bool _processNextEntry;
ScriptEntry *_lastProcessedCmd; // DEBUGGING
Script *_currentScript;
ScriptQueueEntry *_currentQueueEntry;
// Opcode helper functions
void enableObject(ScriptEntry *cmd, ObjectTransparency type);
void setActionFlag(ScriptEntry *cmd, ActionType flag); //|
void clearActionFlag(ScriptEntry *cmd, ActionType flag); //&
void jumpIfActionFlag(ScriptEntry *cmd, ActionType flag);
void setNextLine(int32 line);
//////////////////////////////////////////////////////////////////////////
// Opcode functions
DECLARE_OPCODE(Return);
DECLARE_OPCODE(SetGameFlag);
DECLARE_OPCODE(ClearGameFlag);
DECLARE_OPCODE(ToggleGameFlag);
DECLARE_OPCODE(JumpIfGameFlag);
DECLARE_OPCODE(HideCursor);
DECLARE_OPCODE(ShowCursor);
DECLARE_OPCODE(PlayAnimation);
DECLARE_OPCODE(MoveScenePosition);
DECLARE_OPCODE(HideActor);
DECLARE_OPCODE(ShowActor);
DECLARE_OPCODE(SetActorPosition);
DECLARE_OPCODE(SetSceneMotionStatus);
DECLARE_OPCODE(DisableActor);
DECLARE_OPCODE(EnableActor);
DECLARE_OPCODE(EnableObjects);
DECLARE_OPCODE(RemoveObject);
DECLARE_OPCODE(JumpActorSpeech);
DECLARE_OPCODE(JumpAndSetDirection);
DECLARE_OPCODE(JumpIfActorCoordinates);
DECLARE_OPCODE(Nop);
DECLARE_OPCODE(ResetAnimation);
DECLARE_OPCODE(DisableObject);
DECLARE_OPCODE(JumpIfSoundPlayingAndPlaySound);
DECLARE_OPCODE(JumpIfActionFind);
DECLARE_OPCODE(SetActionFind);
DECLARE_OPCODE(ClearActionFind);
DECLARE_OPCODE(JumpIfActionGrab);
DECLARE_OPCODE(SetActionGrab);
DECLARE_OPCODE(ClearActionGrab);
DECLARE_OPCODE(JumpIfActionTalk);
DECLARE_OPCODE(SetActionTalk);
DECLARE_OPCODE(ClearActionTalk);
DECLARE_OPCODE(AddToInventory);
DECLARE_OPCODE(RemoveFromInventory);
DECLARE_OPCODE(JumpIfInventoryOmits);
DECLARE_OPCODE(RunEncounter);
DECLARE_OPCODE(JumpIfAction16);
DECLARE_OPCODE(SetAction16);
DECLARE_OPCODE(ClearAction16);
DECLARE_OPCODE(SelectInventoryItem);
DECLARE_OPCODE(JumpIfInventoryItemNotSelected);
DECLARE_OPCODE(ChangeScene);
DECLARE_OPCODE(Interact);
DECLARE_OPCODE(PlayMovie);
DECLARE_OPCODE(StopAllObjectsSounds);
DECLARE_OPCODE(StopProcessing);
DECLARE_OPCODE(ResumeProcessing);
DECLARE_OPCODE(ResetSceneRect);
DECLARE_OPCODE(ChangeMusicById);
DECLARE_OPCODE(StopMusic);
DECLARE_OPCODE(IncrementParam1);
DECLARE_OPCODE(SetVolume);
DECLARE_OPCODE(Jump);
DECLARE_OPCODE(RunPuzzle);
DECLARE_OPCODE(JumpIfAction8);
DECLARE_OPCODE(SetAction8);
DECLARE_OPCODE(ClearAction8);
DECLARE_OPCODE(CreatePalette);
DECLARE_OPCODE(IncrementParam2);
DECLARE_OPCODE(WaitUntilFramePlayed);
DECLARE_OPCODE(UpdateWideScreen);
DECLARE_OPCODE(JumpIfActor);
DECLARE_OPCODE(PlaySpeechScene);
DECLARE_OPCODE(PlaySpeech);
DECLARE_OPCODE(PlaySpeechScene2);
DECLARE_OPCODE(MoveScenePositionFromActor);
DECLARE_OPCODE(PaletteFade);
DECLARE_OPCODE(QueuePaletteFade);
DECLARE_OPCODE(PlaySoundUpdateObject);
DECLARE_OPCODE(ActorFaceTarget);
DECLARE_OPCODE(HideMatteBars);
DECLARE_OPCODE(ShowMatteBars);
DECLARE_OPCODE(JumpIfSoundPlaying);
DECLARE_OPCODE(ChangePlayer);
DECLARE_OPCODE(ChangeActorStatus);
DECLARE_OPCODE(StopSound);
DECLARE_OPCODE(JumpRandom);
DECLARE_OPCODE(ClearScreen);
DECLARE_OPCODE(Quit);
DECLARE_OPCODE(JumpObjectFrame);
DECLARE_OPCODE(DeleteGraphics);
DECLARE_OPCODE(SetActorField944);
DECLARE_OPCODE(SetScriptField1BB0);
DECLARE_OPCODE(OnScriptField1BB0);
DECLARE_OPCODE(WalkToActor);
DECLARE_OPCODE(SetResourcePalette);
DECLARE_OPCODE(SetObjectFrameIndexAndFlags);
DECLARE_OPCODE(SetObjectFlags);
DECLARE_OPCODE(SetActorActionIndex2);
DECLARE_OPCODE(UpdateTransparency);
DECLARE_OPCODE(QueueScript);
DECLARE_OPCODE(ProcessActor);
DECLARE_OPCODE(ClearActorFields);
DECLARE_OPCODE(SetObjectLastFrameIndex);
DECLARE_OPCODE(SetActionAreaFlags);
DECLARE_OPCODE(MorphActor);
DECLARE_OPCODE(ShowMenu);
DECLARE_OPCODE(UpdateGlobalFlags);
friend class Console;
}; // end of class ActionList
} // end of namespace Asylum
#endif // ASYLUM_RESOURCES_SCRIPT_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
/* 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 ASYLUM_RESOURCES_SPECIAL_H
#define ASYLUM_RESOURCES_SPECIAL_H
#include "common/scummsys.h"
#include "common/rect.h"
#include "asylum/shared.h"
#include "asylum/asylum.h"
namespace Asylum {
class Object;
class Special {
public:
Special(AsylumEngine *engine);
~Special() {};
void run(Object *object, ActorIndex index);
void reset(bool resetPaletteTick2);
private:
AsylumEngine *_vm;
// Counters
int32 _chapter5Counter;
bool _paletteFlag;
uint32 _paletteTick1;
uint32 _paletteTick2;
//////////////////////////////////////////////////////////////////////////
// Spec functions
//////////////////////////////////////////////////////////////////////////
void chapter1(Object *object, ActorIndex actorIndex);
void chapter2(Object *object, ActorIndex actorIndex);
void chapter3(Object *object, ActorIndex actorIndex);
void chapter4(Object *object, ActorIndex actorIndex);
void chapter5(Object *object, ActorIndex actorIndex);
void chapter6(Object *object, ActorIndex actorIndex);
void chapter7(Object *object, ActorIndex actorIndex);
void chapter8(Object *object, ActorIndex actorIndex);
void chapter9(Object *object, ActorIndex actorIndex);
void chapter11(Object *object, ActorIndex actorIndex);
void chapter12(Object *object, ActorIndex actorIndex);
void chapter13(Object *object, ActorIndex actorIndex);
//////////////////////////////////////////////////////////////////////////
// Sound logic
//////////////////////////////////////////////////////////////////////////
void playChapterSound(Object *object, ActorIndex actorIndex);
void playSoundChapter1(Object *object, ActorIndex actorIndex);
void playSoundChapter2(Object *object, ActorIndex actorIndex);
void playSoundChapter3(Object *object, ActorIndex actorIndex);
void playSoundChapter4(Object *object, ActorIndex actorIndex);
void playSoundChapter6(Object *object, ActorIndex actorIndex);
void playSoundChapter7(Object *object, ActorIndex actorIndex);
void playSoundChapter8(Object *object, ActorIndex actorIndex);
//////////////////////////////////////////////////////////////////////////
// Misc
//////////////////////////////////////////////////////////////////////////
void setPaletteGamma(ResourceId palette1, ResourceId palette2);
void playSoundPanning(ResourceId resourceId, int32 attenuation, Object *object);
void playSoundPanning(ResourceId resourceId, int32 attenuation, ActorIndex actorIndex);
void updateObjectFlag(ObjectId id);
void checkFlags(ObjectId id, GameFlag flag1, GameFlag flag2, GameFlag flag3, GameFlag flag4, uint32 *val1, uint32 *val2, GameFlag flag5, uint32 *val3);
//////////////////////////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////////////////////////
ResourceId getResourceId(Object *object, ActorIndex actorIndex);
uint32 getCounter(ActorIndex index) const;
bool chance() { return _vm->getRandom(10000) < 30; }
void checkObject(Object *object, GameFlag flagToSet, GameFlag flagToClear, ObjectId objectId = kObjectNone);
void checkOtherObject(Object *object, ObjectId otherObjectId, GameFlag flagToClear, GameFlag flagToSet);
//////////////////////////////////////////////////////////////////////////
// Chapter 11 helpers
//////////////////////////////////////////////////////////////////////////
void tentacle(ActorIndex actorIndex, GameFlag flag1, GameFlag flag2, GameFlag flag3, const int16 (*rectPtr)[4]);
void rock(ActorIndex actorIndex, GameFlag flag1, GameFlag flag2, GameFlag flag3, GameFlag flag4, const int16 (*rectPtr)[4]);
};
} // End of namespace Asylum
#endif // ASYLUM_RESOURCES_SPECIAL_H

View File

@@ -0,0 +1,588 @@
/* 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 "asylum/resources/worldstats.h"
#include "asylum/resources/actor.h"
#include "asylum/resources/object.h"
#include "asylum/resources/script.h"
#include "asylum/asylum.h"
namespace Asylum {
WorldStats::WorldStats(AsylumEngine *engine) : _vm(engine) {
// Init values
size = 0;
numEntries = 0;
chapter = kChapterNone;
xLeft = 0;
yTop = 0;
backgroundImage = kResourceNone;
memset(&cursorResources, kResourceNone, sizeof(cursorResources));
font1 = kResourceNone;
font2 = kResourceNone;
font3 = kResourceNone;
currentPaletteId = kResourceNone;
cellShadeMask1 = 0;
cellShadeMask2 = 0;
cellShadeMask3 = 0;
unused = 0;
smallCurUp = 0;
smallCurDown = 0;
encounterFrameBg = 0;
width = 0;
height = 0;
motionStatus = 0;
field_8C = 0;
memset(&coordinates, 0, sizeof(coordinates));
reverseStereo = 0;
sceneRectIdx = 0;
memset(&field_11D, 0, sizeof(field_11D));
field_120 = 0;
scriptIndex = 0;
memset(&graphicResourceIds, kResourceNone, sizeof(graphicResourceIds));
sceneTitleGraphicResourceId = kResourceNone;
sceneTitlePaletteResourceId = kResourceNone;
actorType = kActorMax;
memset(&soundResourceIds, kResourceNone, sizeof(soundResourceIds));
numAmbientSounds = 0;
musicStatus = 0;
musicCurrentResourceIndex = 0;
musicFlag = 0;
musicResourceIndex = 0;
musicStatusExt = 0;
numScripts = 0;
numPolygons = 0;
memset(&inventoryIconsActive, kResourceNone, sizeof(inventoryIconsActive));
memset(&inventoryIconsNormal, kResourceNone, sizeof(inventoryIconsNormal));
memset(&inventoryCursorsNormal, kResourceNone, sizeof(inventoryCursorsNormal));
memset(&inventoryCursorsBlinking, kResourceNone, sizeof(inventoryCursorsBlinking));
field_E848C = 0;
field_E8490 = 0;
field_E8494 = 0;
field_E8498 = 0;
field_E849C = 0;
memset(&tickValueArray, 0, sizeof(tickValueArray));
field_E8518 = 0;
memset(&field_E851C, 0, sizeof(field_E851C));
memset(&field_E8594, 0, sizeof(field_E8594));
nextPlayer = kActorMax;
memset(&field_E8610, 0, sizeof(field_E8610));
memset(&field_E8628, 0, sizeof(field_E8628));
memset(&wheels, 0, sizeof(wheels));
tickCount1 = 0;
memset(&field_E8660, 0, sizeof(field_E8660));
dword_4563A0 = 1;
}
WorldStats::~WorldStats() {
CLEAR_ARRAY(Object, objects);
CLEAR_ARRAY(Actor, actors);
CLEAR_ARRAY(ActionArea, actions);
}
// Load necessary World Stats content
void WorldStats::load(Common::SeekableReadStream *stream) {
size = stream->readSint32LE();
numEntries = stream->readSint32LE();
chapter = (ChapterIndex)stream->readSint32LE();
xLeft = (int16)stream->readSint32LE();
yTop = (int16)stream->readSint32LE();
boundingRect.left = (int16)(stream->readSint32LE() & 0xFFFF);
boundingRect.top = (int16)(stream->readSint32LE() & 0xFFFF);
boundingRect.right = (int16)(stream->readSint32LE() & 0xFFFF);
boundingRect.bottom = (int16)(stream->readSint32LE() & 0xFFFF);
// read common graphic resources
backgroundImage = (ResourceId)stream->readSint32LE();
for (uint i = 0; i < ARRAYSIZE(cursorResources); i++)
cursorResources[i] = (ResourceId)stream->readSint32LE();
font1 = (ResourceId)stream->readSint32LE();
font2 = (ResourceId)stream->readSint32LE();
font3 = (ResourceId)stream->readSint32LE();
currentPaletteId = (ResourceId)stream->readSint32LE();
cellShadeMask1 = stream->readSint32LE();
cellShadeMask2 = stream->readSint32LE();
cellShadeMask3 = stream->readSint32LE();
unused = stream->readSint32LE();
smallCurUp = stream->readSint32LE();
smallCurDown = stream->readSint32LE();
encounterFrameBg = (ResourceId)stream->readSint32LE();
width = (int16)stream->readSint32LE();
height = (int16)stream->readSint32LE();
motionStatus = stream->readSint32LE();
field_8C = stream->readSint32LE();
uint32 numActions = stream->readUint32LE();
uint32 numObjects = stream->readUint32LE();
for (int32 c = 0; c < 7 + _vm->checkGameVersion("Demo"); c++)
coordinates[c] = (int16)stream->readSint32LE();
uint32 numActors = stream->readUint32LE();
reverseStereo = stream->readSint32LE();
for (int32 r = 0; r < ARRAYSIZE(sceneRects); r++) {
sceneRects[r].left = (int16)(stream->readSint32LE() & 0xFFFF);
sceneRects[r].top = (int16)(stream->readSint32LE() & 0xFFFF);
sceneRects[r].right = (int16)(stream->readSint32LE() & 0xFFFF);
sceneRects[r].bottom = (int16)(stream->readSint32LE() & 0xFFFF);
}
sceneRectIdx = stream->readByte();
field_11D[0] = stream->readByte();
field_11D[1] = stream->readByte();
field_11D[2] = stream->readByte();
field_120 = stream->readSint32LE();
scriptIndex = stream->readSint32LE();
for (int32 gr = 0; gr < ARRAYSIZE(graphicResourceIds); gr++)
graphicResourceIds[gr] = (ResourceId)stream->readSint32LE();
sceneTitleGraphicResourceId = (ResourceId)stream->readSint32LE();
sceneTitlePaletteResourceId = (ResourceId)stream->readSint32LE();
actorType = stream->readUint32LE();
for (int32 s = 0; s < ARRAYSIZE(soundResourceIds); s++)
soundResourceIds[s] = (ResourceId)stream->readSint32LE();
if (_vm->checkGameVersion("Demo")) {
stream->readSint32LE();
stream->readSint32LE();
goto load_objects;
}
for (int32 s = 0; s < ARRAYSIZE(ambientSounds); s++) {
ambientSounds[s].field_0 = stream->readSint32LE();
ambientSounds[s].flags = stream->readSint32LE();
ambientSounds[s].resourceId = (ResourceId)stream->readSint32LE();
ambientSounds[s].delta = stream->readSint32LE();
ambientSounds[s].attenuation = stream->readSint32LE();
ambientSounds[s].nextTick = stream->readSint32LE();
for (int32 i = 0; i < ARRAYSIZE(ambientSounds[s].flagNum); i++)
ambientSounds[s].flagNum[i] = stream->readSint32LE();
ambientSounds[s].point.x = (int16)stream->readSint32LE();
ambientSounds[s].point.y = (int16)stream->readSint32LE();
}
numAmbientSounds = stream->readUint32LE();
musicStatus = stream->readSint32LE();
musicCurrentResourceIndex = stream->readSint32LE();
musicFlag = stream->readSint32LE();
musicResourceIndex = stream->readSint32LE();
musicStatusExt = stream->readSint32LE();
// Patch a flag number which is too big
if (chapter == kChapter8 && ambientSounds[1].flagNum[1] == 99999)
ambientSounds[1].flagNum[1] = 0;
load_objects:
//////////////////////////////////////////////////////////////////////////
// Read Objects
for (uint32 a = 0; a < numObjects; a++) {
Object *object = new Object(_vm);
object->load(stream);
objects.push_back(object);
}
if (_vm->checkGameVersion("Demo"))
stream->seek(0x1C93A, SEEK_SET);
else
stream->seek((OBJECTS_MAX_COUNT - numObjects) * OBJECTS_SIZE, SEEK_CUR);
//////////////////////////////////////////////////////////////////////////
// Read Actors
for (ActorIndex index = 0; index < (int)numActors; index++) {
Actor *actor = new Actor(_vm, index);
actor->load(stream);
actors.push_back(actor);
}
if (_vm->checkGameVersion("Demo")) {
stream->seek(0x1D2AA, SEEK_SET);
goto load_inventory;
}
stream->seek((ACTORS_MAX_COUNT - numActors) * ACTORS_SIZE, SEEK_CUR);
//////////////////////////////////////////////////////////////////////////
// Read actor data
for (ActorIndex index = 0; index < (int)numActors; index++)
actors[index]->getData()->load(stream);
stream->seek((ACTORS_MAX_COUNT - numActors) * ACTORDATA_SIZE, SEEK_CUR);
//////////////////////////////////////////////////////////////////////////
// Read number of scripts and polygons
numScripts = stream->readUint32LE();
numPolygons = stream->readUint32LE();
load_inventory:
// Load inventory resources
for (uint32 i = 0; i < ARRAYSIZE(inventoryIconsActive); i++)
inventoryIconsActive[i] = (ResourceId)stream->readSint32LE();
for (uint32 i = 0; i < ARRAYSIZE(inventoryIconsNormal); i++)
inventoryIconsNormal[i] = (ResourceId)stream->readSint32LE();
for (uint32 i = 0; i < ARRAYSIZE(inventoryCursorsNormal); i++)
inventoryCursorsNormal[i] = (ResourceId)stream->readSint32LE();
for (uint32 i = 0; i < ARRAYSIZE(inventoryCursorsBlinking); i++)
inventoryCursorsBlinking[i] = (ResourceId)stream->readSint32LE();
if (_vm->checkGameVersion("Demo"))
stream->seek(0x1A60A, SEEK_SET);
//////////////////////////////////////////////////////////////////////////
// Read actions
for (uint32 a = 0; a < numActions; a++) {
ActionArea *action = new ActionArea();
action->load(stream);
actions.push_back(action);
}
if (_vm->checkGameVersion("Demo"))
return;
// Patch for Chapter 2 Lockout bug
if (_vm->checkGameVersion("Unpatched") && chapter == kChapter2) {
ActionArea *area978 = actions[getActionAreaIndexById(978)];
area978->flagNums[0] = -556;
area978->flagNums[1] = -368;
area978->flagNums[2] = -50;
}
stream->seek((ACTIONS_MAX_COUNT - numActions) * ACTIONS_SIZE, SEEK_CUR);
field_E848C = stream->readSint32LE();
field_E8490 = stream->readSint32LE();
field_E8494 = stream->readSint32LE();
field_E8498 = stream->readSint32LE();
field_E849C = stream->readSint32LE();
for (int32 i = 0; i < ARRAYSIZE(tickValueArray); i++)
tickValueArray[i] = stream->readSint32LE();
field_E8518 = stream->readSint32LE();
for (int32 i = 0; i < ARRAYSIZE(field_E851C); i++)
field_E851C[i] = stream->readSint32LE();
for (int32 i = 0; i < ARRAYSIZE(field_E8594); i++)
field_E8594[i] = stream->readSint32LE();
nextPlayer = (ActorIndex)stream->readSint32LE();
for (int32 i = 0; i < ARRAYSIZE(field_E8610); i++)
field_E8610[i] = stream->readUint32LE();
for (int32 i = 0; i < ARRAYSIZE(field_E8628); i++)
field_E8628[i] = stream->readUint32LE();
for (int32 i = 0; i < ARRAYSIZE(wheels); i++) {
ObjectId id = (ObjectId)stream->readUint32LE();
if (id == 0)
wheels[i] = nullptr;
else
wheels[i] = getObjectById(id);
}
tickCount1 = stream->readUint32LE();
for (int32 i = 0; i < ARRAYSIZE(field_E8660); i++)
field_E8660[i] = stream->readUint32LE();
}
void WorldStats::saveLoadWithSerializer(Common::Serializer &s) {
s.syncAsSint32LE(chapter);
s.syncAsSint32LE(xLeft);
s.syncAsSint32LE(yTop);
s.syncAsSint32LE(boundingRect.left);
s.syncAsSint32LE(boundingRect.top);
s.syncAsSint32LE(boundingRect.right);
s.syncAsSint32LE(boundingRect.bottom);
// Common graphic resources
s.syncAsSint32LE(backgroundImage);
for (int32 i = 0; i < ARRAYSIZE(cursorResources); i++)
s.syncAsSint32LE(cursorResources[i]);
s.syncAsSint32LE(font1);
s.syncAsSint32LE(font2);
s.syncAsSint32LE(font3);
s.syncAsSint32LE(currentPaletteId);
s.syncAsSint32LE(cellShadeMask1);
s.syncAsSint32LE(cellShadeMask2);
s.syncAsSint32LE(cellShadeMask3);
s.syncAsUint32LE(unused);
s.syncAsSint32LE(smallCurUp);
s.syncAsSint32LE(smallCurDown);
s.syncAsSint32LE(encounterFrameBg);
s.syncAsSint32LE(width);
s.syncAsSint32LE(height);
s.syncAsSint32LE(motionStatus);
s.syncAsSint32LE(field_8C);
uint32 numActions = actions.size();
uint32 numObjects = objects.size();
s.syncAsUint32LE(numActions);
s.syncAsUint32LE(numObjects);
for (int32 i = 0; i < ARRAYSIZE(coordinates); i++)
s.syncAsSint32LE(coordinates[i]);
uint32 numActors = actors.size();
s.syncAsUint32LE(numActors);
s.syncAsUint32LE(reverseStereo);
for (int32 i = 0; i < ARRAYSIZE(sceneRects); i++) {
s.syncAsSint32LE(sceneRects[i].left);
s.syncAsSint32LE(sceneRects[i].top);
s.syncAsSint32LE(sceneRects[i].right);
s.syncAsSint32LE(sceneRects[i].bottom);
}
s.syncAsByte(sceneRectIdx);
for (int32 i = 0; i < ARRAYSIZE(field_11D); i++)
s.syncAsByte(field_11D[i]);
s.syncAsUint32LE(field_120);
s.syncAsUint32LE(scriptIndex);
for (int32 i = 0; i < ARRAYSIZE(graphicResourceIds); i++)
s.syncAsSint32LE(graphicResourceIds[i]);
s.syncAsSint32LE(sceneTitleGraphicResourceId);
s.syncAsSint32LE(sceneTitlePaletteResourceId);
s.syncAsUint32LE(actorType);
for (int32 i = 0; i < ARRAYSIZE(soundResourceIds); i++)
s.syncAsSint32LE(soundResourceIds[i]);
for (int32 i = 0; i < ARRAYSIZE(ambientSounds); i++) {
s.syncAsSint32LE(ambientSounds[i].field_0);
s.syncAsSint32LE(ambientSounds[i].flags);
s.syncAsSint32LE(ambientSounds[i].resourceId);
s.syncAsSint32LE(ambientSounds[i].delta);
s.syncAsSint32LE(ambientSounds[i].attenuation);
s.syncAsSint32LE(ambientSounds[i].nextTick);
for (int32 j = 0; j < ARRAYSIZE(ambientSounds[i].flagNum); j++)
s.syncAsSint32LE(ambientSounds[i].flagNum[j]);
s.syncAsSint32LE(ambientSounds[i].point.x);
s.syncAsSint32LE(ambientSounds[i].point.y);
}
s.syncAsUint32LE(numAmbientSounds);
s.syncAsSint32LE(musicStatus);
s.syncAsSint32LE(musicCurrentResourceIndex);
s.syncAsSint32LE(musicFlag);
s.syncAsSint32LE(musicResourceIndex);
s.syncAsSint32LE(musicStatusExt);
//////////////////////////////////////////////////////////////////////////
// Objects
for (uint32 i = 0; i < numObjects; i++)
objects[i]->saveLoadWithSerializer(s);
s.skip((OBJECTS_MAX_COUNT - numObjects) * OBJECTS_SIZE);
//////////////////////////////////////////////////////////////////////////
// Actors
for (uint32 i = 0; i < numActors; i++)
actors[i]->saveLoadWithSerializer(s);
s.skip((ACTORS_MAX_COUNT - numActors) * ACTORS_SIZE);
//////////////////////////////////////////////////////////////////////////
// Actor data
for (uint32 i = 0; i < numActors; i++)
actors[i]->getData()->saveLoadWithSerializer(s);
s.skip((ACTORS_MAX_COUNT - numActors) * ACTORDATA_SIZE);
//////////////////////////////////////////////////////////////////////////
// Number of scripts and polygons
s.syncAsUint32LE(numScripts);
s.syncAsUint32LE(numPolygons);
// Inventory resources
for (uint32 i = 0; i < ARRAYSIZE(inventoryIconsActive); i++)
s.syncAsSint32LE(inventoryIconsActive[i]);
for (uint32 i = 0; i < ARRAYSIZE(inventoryIconsNormal); i++)
s.syncAsSint32LE(inventoryIconsNormal[i]);
for (uint32 i = 0; i < ARRAYSIZE(inventoryCursorsNormal); i++)
s.syncAsSint32LE(inventoryCursorsNormal[i]);
for (uint32 i = 0; i < ARRAYSIZE(inventoryCursorsBlinking); i++)
s.syncAsSint32LE(inventoryCursorsBlinking[i]);
//////////////////////////////////////////////////////////////////////////
// Read actions
for (uint32 i = 0; i < numActions; i++)
actions[i]->saveLoadWithSerializer(s);
s.skip((ACTIONS_MAX_COUNT - numActions) * ACTIONS_SIZE);
s.syncAsSint32LE(field_E848C);
s.syncAsSint32LE(field_E8490);
s.syncAsSint32LE(field_E8494);
s.syncAsSint32LE(field_E8498);
s.syncAsSint32LE(field_E849C);
for (int32 i = 0; i < ARRAYSIZE(tickValueArray); i++)
s.syncAsSint32LE(tickValueArray[i]);
s.syncAsSint32LE(field_E8518);
for (int32 i = 0; i < ARRAYSIZE(field_E851C); i++)
s.syncAsSint32LE(field_E851C[i]);
for (int32 i = 0; i < ARRAYSIZE(field_E8594); i++)
s.syncAsSint32LE(field_E8594[i]);
s.syncAsSint32LE(nextPlayer);
for (int32 i = 0; i < ARRAYSIZE(field_E8610); i++)
s.syncAsSint32LE(field_E8610[i]);
for (int32 i = 0; i < ARRAYSIZE(field_E8628); i++)
s.syncAsSint32LE(field_E8628[i]);
for (int32 i = 0; i < ARRAYSIZE(wheels); i++) {
ObjectId id = wheels[i] ? wheels[i]->getId() : kObjectNone;
s.syncAsSint32LE(id);
if (s.isLoading()) {
if (id == kObjectNone)
wheels[i] = nullptr;
else
wheels[i] = getObjectById(id);
}
}
s.syncAsUint32LE(tickCount1);
for (int32 i = 0; i < ARRAYSIZE(field_E8660); i++)
s.syncAsUint32LE(field_E8660[i]);
}
//////////////////////////////////////////////////////////////////////////
// Helper methods
//////////////////////////////////////////////////////////////////////////
int32 WorldStats::getActionAreaIndexById(int32 id) {
for (uint32 i = 0; i < actions.size(); i++) {
if (actions[i]->id == id)
return i;
}
return -1;
}
int32 WorldStats::getRandomActionAreaIndexById(int32 id) {
uint count = 0;
int32 indexes[5];
memset(&indexes, 0, sizeof(indexes));
for (uint32 i = 0; i < actions.size(); i++) {
if (actions[i]->id == id && count < 5) {
indexes[count] = i;
++count;
}
}
if (!count)
return -1;
return indexes[_vm->getRandom(count)];
}
ActionArea *WorldStats::getActionAreaById(int32 id) {
int index = getActionAreaIndexById(id);
if (index == -1)
error("[WorldStats::getActionAreaById] action id is invalid");
return actions[index];
}
Object *WorldStats::getObjectById(ObjectId id) {
for (uint32 i = 0; i < objects.size(); i++)
if (objects[i]->getId() == id)
return objects[i];
return nullptr;
}
void WorldStats::setWheelObjects() {
wheels[0] = getObjectById(kObjectWheel1);
wheels[1] = getObjectById(kObjectWheel2);
wheels[2] = getObjectById(kObjectWheel3);
wheels[3] = getObjectById(kObjectWheel4);
wheels[4] = getObjectById(kObjectWheel5);
wheels[5] = getObjectById(kObjectWheel6);
wheels[6] = getObjectById(kObjectWheel7);
}
Common::String WorldStats::toString() {
Common::String output;
output += Common::String::format("Chapter %d\n", chapter);
output += Common::String::format("xLeft: %d\n", xLeft);
output += Common::String::format("yTop: %d\n", yTop);
output += Common::String::format("boundingRect: top[%d] left[%d] right[%d] bottom[%d]: \n", boundingRect.top, boundingRect.left, boundingRect.right, boundingRect.bottom);
output += Common::String::format("width: %d\n", width);
output += Common::String::format("height: %d\n", height);
output += Common::String::format("motionStatus: %d\n", motionStatus);
output += "coordinates: ";
for (int i = 0; i < 7; i++)
output += Common::String::format("%d[%d] ", i, coordinates[i]);
output += "\n";
output += Common::String::format("sceneRectIndex: %d\n", sceneRectIdx);
output += Common::String::format("sceneRects: 0: top[%d] left[%d] right[%d] bottom[%d]\n", sceneRects[0].top, sceneRects[0].left, sceneRects[0].right, sceneRects[0].bottom);
for (int i = 1; i < 6; i++)
output += Common::String::format(" %d: top[%d] left[%d] right[%d] bottom[%d]\n", i, sceneRects[i].top, sceneRects[i].left, sceneRects[i].right, sceneRects[i].bottom);
output += Common::String::format("scriptInex: %d\n", scriptIndex);
output += Common::String::format("actorType: %d\n", actorType);
output += Common::String::format("musicStatus: %d\n", musicStatus);
return output;
}
} // end of namespace Asylum

View File

@@ -0,0 +1,167 @@
/* 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 ASYLUM_RESOURCES_WORLDSTATS_H
#define ASYLUM_RESOURCES_WORLDSTATS_H
#include "common/array.h"
#include "common/rect.h"
#include "common/serializer.h"
#include "asylum/system/sound.h"
namespace Asylum {
#define ACTORS_MAX_COUNT 50
#define OBJECTS_MAX_COUNT 400
#define ACTIONS_MAX_COUNT 400
#define ACTORS_SIZE 2468
#define ACTORDATA_SIZE 1448
#define OBJECTS_SIZE 1704
#define ACTIONS_SIZE 180
class Actor;
class Object;
class AsylumEngine;
struct ActionArea;
enum CursorResourceType {
kCursorResourceScrollUp = 0,
kCursorResourceScrollUpLeft,
kCursorResourceScrollLeft,
kCursorResourceScrollDownLeft,
kCursorResourceScrollDown,
kCursorResourceScrollDownRight,
kCursorResourceScrollRight,
kCursorResourceScrollUpRight,
kCursorResourceHand,
kCursorResourceMagnifyingGlass,
kCursorResourceTalkNPC,
kCursorResourceGrabPointer,
kCursorResourceTalkNPC2
};
class WorldStats : public Common::Serializable {
public:
WorldStats(AsylumEngine *engine);
virtual ~WorldStats();
/**
* Loads the data
*
* @param stream If non-null, the Common::SeekableReadStream * to load from
*/
void load(Common::SeekableReadStream *stream);
int32 size;
int32 numEntries;
ChapterIndex chapter;
int16 xLeft; // scene start x position
int16 yTop; // scene start y position
Common::Rect boundingRect;
ResourceId backgroundImage;
ResourceId cursorResources[13];
ResourceId font1;
ResourceId font2;
ResourceId font3;
ResourceId currentPaletteId;
int32 cellShadeMask1;
int32 cellShadeMask2;
int32 cellShadeMask3;
int32 unused;
int32 smallCurUp;
int32 smallCurDown;
ResourceId encounterFrameBg;
int16 width;
int16 height;
int32 motionStatus;
int32 field_8C;
//uint32 numActions;
//uint32 numObjects;
int16 coordinates[7];
//uint32 numActors;
int32 reverseStereo;
Common::Rect sceneRects[6]; // including scene size rect
uint8 sceneRectIdx;
uint8 field_11D[3];
int32 field_120;
int32 scriptIndex; // actionList start index
ResourceId graphicResourceIds[100];
ResourceId sceneTitleGraphicResourceId;
ResourceId sceneTitlePaletteResourceId;
int32 actorType;
ResourceId soundResourceIds[50];
AmbientSoundItem ambientSounds[15];
uint32 numAmbientSounds;
int32 musicStatus;
int32 musicCurrentResourceIndex;
int32 musicFlag;
int32 musicResourceIndex;
int32 musicStatusExt;
Common::Array<Object *> objects; // maxsize 400
Common::Array<Actor *> actors; // maxsize 50
// ActorData is stored in each actor instance
uint32 numScripts;
uint32 numPolygons;
ResourceId inventoryIconsActive[16];
ResourceId inventoryIconsNormal[16];
ResourceId inventoryCursorsNormal[16];
ResourceId inventoryCursorsBlinking[16];
Common::Array<ActionArea *> actions; // maxsize 400
int32 field_E848C;
int32 field_E8490;
int32 field_E8494;
int32 field_E8498;
int32 field_E849C; // ActorIndex???
int32 tickValueArray[30];
int32 field_E8518;
int32 field_E851C[30];
int32 field_E8594[30];
ActorIndex nextPlayer;
uint32 field_E8610[6];
uint32 field_E8628[6];
Object *wheels[7];
uint32 tickCount1;
uint32 field_E8660[6];
int32 dword_4563A0;
void setWheelObjects();
int32 getActionAreaIndexById(int32 id);
int32 getRandomActionAreaIndexById(int32 id);
ActionArea *getActionAreaById(int32 id);
Object *getObjectById(ObjectId id);
Common::String toString();
// Serializable
void saveLoadWithSerializer(Common::Serializer &s);
private:
AsylumEngine *_vm;
};
} // end of namespace Asylum
#endif // ASYLUM_RESOURCES_WORLDSTATS_H