diff options
Diffstat (limited to 'engines/saga/actor.h')
-rw-r--r-- | engines/saga/actor.h | 778 |
1 files changed, 778 insertions, 0 deletions
diff --git a/engines/saga/actor.h b/engines/saga/actor.h new file mode 100644 index 0000000000..74f1abd689 --- /dev/null +++ b/engines/saga/actor.h @@ -0,0 +1,778 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004-2006 The ScummVM project + * + * The ReInherit Engine is (C)2000-2003 by Daniel Balsom. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Actor management module header file + +#ifndef SAGA_ACTOR_H__ +#define SAGA_ACTOR_H__ + +#include "common/savefile.h" + +#include "saga/sprite.h" +#include "saga/itedata.h" +#include "saga/list.h" +#include "saga/saga.h" +#include "saga/font.h" + +namespace Saga { + +class HitZone; + + +//#define ACTOR_DEBUG //only for actor pathfinding debug! + +#define ACTOR_BARRIERS_MAX 16 + +#define ACTOR_MAX_STEPS_COUNT 32 + +#define ACTOR_DIALOGUE_HEIGHT 100 + +#define ACTOR_LMULT 4 + +#define ACTOR_CLIMB_SPEED 8 + +#define ACTOR_COLLISION_WIDTH 32 +#define ACTOR_COLLISION_HEIGHT 8 + +#define ACTOR_DIRECTIONS_COUNT 4 // for ActorFrameSequence +#define ACTOR_DIRECTION_RIGHT 0 +#define ACTOR_DIRECTION_LEFT 1 +#define ACTOR_DIRECTION_BACK 2 +#define ACTOR_DIRECTION_FORWARD 3 + +#define ACTOR_SPEECH_STRING_MAX 16 // speech const +#define ACTOR_SPEECH_ACTORS_MAX 8 + +#define ACTOR_DRAGON_TURN_MOVES 4 +#define ACTOR_DRAGON_INDEX 133 + +#define ACTOR_NO_ENTRANCE -1 + +#define ACTOR_EXP_KNOCK_RIF 24 + +#define PATH_NODE_EMPTY -1 + +#define ACTOR_INHM_SIZE 228 + +enum ActorActions { + kActionWait = 0, + kActionWalkToPoint = 1, + kActionWalkToLink = 2, + kActionWalkDir = 3, + kActionSpeak = 4, + kActionAccept = 5, + kActionStoop = 6, + kActionLook = 7, + kActionCycleFrames = 8, + kActionPongFrames = 9, + kActionFreeze = 10, + kActionFall = 11, + kActionClimb = 12 +}; + +enum SpeechFlags { + kSpeakNoAnimate = 1, + kSpeakAsync = 2, + kSpeakSlow = 4 +}; + +enum ActorFrameTypes { + kFrameStand, + kFrameWalk, + kFrameSpeak, + kFrameGive, + kFrameGesture, + kFrameWait, + kFramePickUp, + kFrameLook +}; + +enum ActorFlagsEx { + kActorNoCollide = (1 << 0), + kActorNoFollow = (1 << 1), + kActorCollided = (1 << 2), + kActorBackwards = (1 << 3), + kActorContinuous = (1 << 4), + kActorFinalFace = (1 << 5), + kActorFinishLeft = ((1 << 5) | (kDirLeft << 6)), + kActorFinishRight = ((1 << 5) | (kDirRight << 6)), + kActorFinishUp = ((1 << 5) | (kDirUp << 6)), + kActorFinishDown = ((1 << 5) | (kDirDown << 6)), + kActorFacingMask = (0xf << 5), + kActorRandom = (1 << 10) +}; + +enum PathCellType { + kPathCellEmpty = -1, + //kDirUp = 0 .... kDirUpLeft = 7 + kPathCellBarrier = 0x57 +}; + +enum DragonMoveTypes { + kDragonMoveUpLeft = 0, + kDragonMoveUpRight = 1, + kDragonMoveDownLeft = 2, + kDragonMoveDownRight = 3, + kDragonMoveUpLeft_Left = 4, + kDragonMoveUpLeft_Right = 5, + kDragonMoveUpRight_Left = 6, + kDragonMoveUpRight_Right = 7, + kDragonMoveDownLeft_Left = 8, + kDragonMoveDownLeft_Right = 9, + kDragonMoveDownRight_Left = 10, + kDragonMoveDownRight_Right = 11, + kDragonMoveInvalid = 12 +}; + +struct PathDirectionData { + int8 direction; + int16 x; + int16 y; +}; + +struct ActorFrameRange { + int frameIndex; + int frameCount; +}; + +struct ActorFrameSequence { + ActorFrameRange directions[ACTOR_DIRECTIONS_COUNT]; +}; + +int pathLine(Point *pointList, const Point &point1, const Point &point2); + +struct Location { + int32 x; // logical coordinates + int32 y; // + int32 z; // + Location() { + x = y = z = 0; + } + void saveState(Common::OutSaveFile *out) { + out->writeSint32LE(x); + out->writeSint32LE(y); + out->writeSint32LE(z); + } + void loadState(Common::InSaveFile *in) { + x = in->readSint32LE(); + y = in->readSint32LE(); + z = in->readSint32LE(); + } + + int distance(const Location &location) const { + return MAX(ABS(x - location.x), ABS(y - location.y)); + } + int32 &u() { + return x; + } + int32 &v() { + return y; + } + int32 u() const { + return x; + } + int32 v() const { + return y; + } + int32 uv() const { + return u() + v(); + } + void delta(const Location &location, Location &result) const { + result.x = x - location.x; + result.y = y - location.y; + result.z = z - location.z; + } + void addXY(const Location &location) { + x += location.x; + y += location.y; + } + void add(const Location &location) { + x += location.x; + y += location.y; + z += location.z; + } + void fromScreenPoint(const Point &screenPoint) { + x = (screenPoint.x * ACTOR_LMULT); + y = (screenPoint.y * ACTOR_LMULT); + z = 0; + } + void toScreenPointXY(Point &screenPoint) const { + screenPoint.x = x / ACTOR_LMULT; + screenPoint.y = y / ACTOR_LMULT; + } + void toScreenPointUV(Point &screenPoint) const { + screenPoint.x = u(); + screenPoint.y = v(); + } + void toScreenPointXYZ(Point &screenPoint) const { + screenPoint.x = x / ACTOR_LMULT; + screenPoint.y = y / ACTOR_LMULT - z; + } + void fromStream(Common::MemoryReadStream &stream) { + x = stream.readUint16LE(); + y = stream.readUint16LE(); + z = stream.readUint16LE(); + } + + void debugPrint(int debuglevel = 0, const char *loc = "Loc:") const { + debug(debuglevel, "%s %d, %d, %d", loc, x, y, z); + } +}; + +class CommonObjectData { +public: +//constant + bool _disabled; // disabled in init section + int32 _index; // index in local array + uint16 _id; // object id + int32 _scriptEntrypointNumber; // script entrypoint number + +//variables + uint16 _flags; // initial flags + int32 _nameIndex; // index in name string list + int32 _sceneNumber; // scene + int32 _spriteListResourceId; // sprite list resource id + + Location _location; // logical coordinates + Point _screenPosition; // screen coordinates + int32 _screenDepth; // + int32 _screenScale; // + + void saveState(Common::OutSaveFile *out) { + out->writeUint16LE(_flags); + out->writeSint32LE(_nameIndex); + out->writeSint32LE(_sceneNumber); + out->writeSint32LE(_spriteListResourceId); + _location.saveState(out); + out->writeSint16LE(_screenPosition.x); + out->writeSint16LE(_screenPosition.y); + out->writeSint32LE(_screenDepth); + out->writeSint32LE(_screenScale); + } + void loadState(Common::InSaveFile *in) { + _flags = in->readUint16LE(); + _nameIndex = in->readSint32LE(); + _sceneNumber = in->readSint32LE(); + _spriteListResourceId = in->readSint32LE(); + _location.loadState(in); + _screenPosition.x = in->readSint16LE(); + _screenPosition.y = in->readSint16LE(); + _screenDepth = in->readSint32LE(); + _screenScale = in->readSint32LE(); + } +}; + +typedef CommonObjectData *CommonObjectDataPointer; + +typedef SortedList<CommonObjectDataPointer> CommonObjectOrderList; + +class ObjectData: public CommonObjectData { +public: + //constant + uint16 _interactBits; + ObjectData() { + memset(this, 0, sizeof(*this)); + } +}; + +class ActorData: public CommonObjectData { +public: + //constant + SpriteList _spriteList; // sprite list data + + ActorFrameSequence *_frames; // Actor's frames + int _framesCount; // Actor's frames count + int _frameListResourceId; // Actor's frame list resource id + + byte _speechColor; // Actor dialogue color + // + bool _inScene; + + //variables + uint16 _actorFlags; // dynamic flags + int32 _currentAction; // ActorActions type + int32 _facingDirection; // orientation + int32 _actionDirection; + int32 _actionCycle; + uint16 _targetObject; + const HitZone *_lastZone; + + int32 _cycleFrameSequence; + uint8 _cycleDelay; + uint8 _cycleTimeCount; + uint8 _cycleFlags; + + int16 _fallVelocity; + int16 _fallAcceleration; + int16 _fallPosition; + + uint8 _dragonBaseFrame; + uint8 _dragonStepCycle; + uint8 _dragonMoveType; + + int32 _frameNumber; // current frame number + + int32 _tileDirectionsAlloced; + byte *_tileDirections; + + int32 _walkStepsAlloced; + Point *_walkStepsPoints; + + int32 _walkStepsCount; + int32 _walkStepIndex; + + Location _finalTarget; + Location _partialTarget; + int32 _walkFrameSequence; + +public: + void saveState(Common::OutSaveFile *out) { + int i = 0; + CommonObjectData::saveState(out); + out->writeUint16LE(_actorFlags); + out->writeSint32LE(_currentAction); + out->writeSint32LE(_facingDirection); + out->writeSint32LE(_actionDirection); + out->writeSint32LE(_actionCycle); + out->writeUint16LE(_targetObject); + + out->writeSint32LE(_cycleFrameSequence); + out->writeByte(_cycleDelay); + out->writeByte(_cycleTimeCount); + out->writeByte(_cycleFlags); + out->writeSint16LE(_fallVelocity); + out->writeSint16LE(_fallAcceleration); + out->writeSint16LE(_fallPosition); + out->writeByte(_dragonBaseFrame); + out->writeByte(_dragonStepCycle); + out->writeByte(_dragonMoveType); + out->writeSint32LE(_frameNumber); + + out->writeSint32LE(_tileDirectionsAlloced); + for (i = 0; i < _tileDirectionsAlloced; i++) { + out->writeByte(_tileDirections[i]); + } + + out->writeSint32LE(_walkStepsAlloced); + for (i = 0; i < _walkStepsAlloced; i++) { + out->writeSint16LE(_walkStepsPoints[i].x); + out->writeSint16LE(_walkStepsPoints[i].y); + } + + out->writeSint32LE(_walkStepsCount); + out->writeSint32LE(_walkStepIndex); + _finalTarget.saveState(out); + _partialTarget.saveState(out); + out->writeSint32LE(_walkFrameSequence); + } + + void loadState(uint32 version, Common::InSaveFile *in) { + int i = 0; + CommonObjectData::loadState(in); + _actorFlags = in->readUint16LE(); + _currentAction = in->readSint32LE(); + _facingDirection = in->readSint32LE(); + _actionDirection = in->readSint32LE(); + _actionCycle = in->readSint32LE(); + _targetObject = in->readUint16LE(); + + _lastZone = NULL; + _cycleFrameSequence = in->readSint32LE(); + _cycleDelay = in->readByte(); + _cycleTimeCount = in->readByte(); + _cycleFlags = in->readByte(); + if (version > 1) { + _fallVelocity = in->readSint16LE(); + _fallAcceleration = in->readSint16LE(); + _fallPosition = in->readSint16LE(); + } else { + _fallVelocity = _fallAcceleration = _fallPosition = 0; + } + if (version > 2) { + _dragonBaseFrame = in->readByte(); + _dragonStepCycle = in->readByte(); + _dragonMoveType = in->readByte(); + } else { + _dragonBaseFrame = _dragonStepCycle = _dragonMoveType = 0; + } + + _frameNumber = in->readSint32LE(); + + + setTileDirectionsSize(in->readSint32LE(), true); + for (i = 0; i < _tileDirectionsAlloced; i++) { + _tileDirections[i] = in->readByte(); + } + + setWalkStepsPointsSize(in->readSint32LE(), true); + for (i = 0; i < _walkStepsAlloced; i++) { + _walkStepsPoints[i].x = in->readSint16LE(); + _walkStepsPoints[i].y = in->readSint16LE(); + } + + _walkStepsCount = in->readSint32LE(); + _walkStepIndex = in->readSint32LE(); + _finalTarget.loadState(in); + _partialTarget.loadState(in); + _walkFrameSequence = in->readSint32LE(); + } + + void setTileDirectionsSize(int size, bool forceRealloc) { + if ((size <= _tileDirectionsAlloced) && !forceRealloc) { + return; + } + _tileDirectionsAlloced = size; + _tileDirections = (byte*)realloc(_tileDirections, _tileDirectionsAlloced * sizeof(*_tileDirections)); + } + + void cycleWrap(int cycleLimit) { + if (_actionCycle >= cycleLimit) + _actionCycle = 0; + } + + void setWalkStepsPointsSize(int size, bool forceRealloc) { + if ((size <= _walkStepsAlloced) && !forceRealloc) { + return; + } + _walkStepsAlloced = size; + _walkStepsPoints = (Point*)realloc(_walkStepsPoints, _walkStepsAlloced * sizeof(*_walkStepsPoints)); + } + + void addWalkStepPoint(const Point &point) { + setWalkStepsPointsSize(_walkStepsCount + 1, false); + _walkStepsPoints[_walkStepsCount++] = point; + } + + void freeSpriteList() { + _spriteList.freeMem(); + } + + ActorData() { + memset(this, 0, sizeof(*this)); + } + ~ActorData() { + free(_frames); + free(_tileDirections); + free(_walkStepsPoints); + freeSpriteList(); + } +}; + + + +struct SpeechData { + int speechColor[ACTOR_SPEECH_ACTORS_MAX]; + int outlineColor[ACTOR_SPEECH_ACTORS_MAX]; + int speechFlags; + const char *strings[ACTOR_SPEECH_STRING_MAX]; + Rect speechBox; + Rect drawRect; + int stringsCount; + int slowModeCharIndex; + uint16 actorIds[ACTOR_SPEECH_ACTORS_MAX]; + int actorsCount; + int sampleResourceId; + bool playing; + int playingTime; + + SpeechData() { + memset(this, 0, sizeof(*this)); + } + + FontEffectFlags getFontFlags(int i) { + if (outlineColor[i] != 0) { + return kFontOutline; + } else { + return kFontNormal; + } + } +}; + + + +class Actor { + friend class IsoMap; + friend class SagaEngine; + friend class Puzzle; +public: + + Actor(SagaEngine *vm); + ~Actor(); + + void cmdActorWalkTo(int argc, const char **argv); + + bool validActorId(uint16 id) { return (id == ID_PROTAG) || ((id >= objectIndexToId(kGameObjectActor, 0)) && (id < objectIndexToId(kGameObjectActor, _actorsCount))); } + int actorIdToIndex(uint16 id) { return (id == ID_PROTAG ) ? 0 : objectIdToIndex(id); } + uint16 actorIndexToId(int index) { return (index == 0 ) ? ID_PROTAG : objectIndexToId(kGameObjectActor, index); } + ActorData *getActor(uint16 actorId); + +// clarification: Obj - means game object, such Hat, Spoon etc, Object - means Actor,Obj,HitZone,StepZone + + bool validObjId(uint16 id) { return (id >= objectIndexToId(kGameObjectObject, 0)) && (id < objectIndexToId(kGameObjectObject, _objsCount)); } + int objIdToIndex(uint16 id) { return objectIdToIndex(id); } + uint16 objIndexToId(int index) { return objectIndexToId(kGameObjectObject, index); } + ObjectData *getObj(uint16 objId); + + int getObjectScriptEntrypointNumber(uint16 id) { + int objectType; + objectType = objectTypeId(id); + if (!(objectType & (kGameObjectObject | kGameObjectActor))) { + error("Actor::getObjectScriptEntrypointNumber wrong id 0x%X", id); + } + return (objectType == kGameObjectObject) ? getObj(id)->_scriptEntrypointNumber : getActor(id)->_scriptEntrypointNumber; + } + int getObjectFlags(uint16 id) { + int objectType; + objectType = objectTypeId(id); + if (!(objectType & (kGameObjectObject | kGameObjectActor))) { + error("Actor::getObjectFlags wrong id 0x%X", id); + } + return (objectType == kGameObjectObject) ? getObj(id)->_flags : getActor(id)->_flags; + } + + void direct(int msec); + void drawActors(); + void updateActorsScene(int actorsEntrance); // calls from scene loading to update Actors info + + void drawSpeech(); + + void drawPathTest(); + + uint16 hitTest(const Point &testPoint, bool skipProtagonist); + void takeExit(uint16 actorId, const HitZone *hitZone); + bool actorEndWalk(uint16 actorId, bool recurse); + bool actorWalkTo(uint16 actorId, const Location &toLocation); + int getFrameType(ActorFrameTypes frameType); + ActorFrameRange *getActorFrameRange(uint16 actorId, int frameType); + void actorFaceTowardsPoint(uint16 actorId, const Location &toLocation); + void actorFaceTowardsObject(uint16 actorId, uint16 objectId); + + void realLocation(Location &location, uint16 objectId, uint16 walkFlags); + +// speech + void actorSpeech(uint16 actorId, const char **strings, int stringsCount, int sampleResourceId, int speechFlags); + void nonActorSpeech(const Common::Rect &box, const char **strings, int stringsCount, int sampleResourceId, int speechFlags); + void simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount, int speechFlags, int sampleResourceId); + void setSpeechColor(int speechColor, int outlineColor) { + _activeSpeech.speechColor[0] = speechColor; + _activeSpeech.outlineColor[0] = outlineColor; + } + void abortAllSpeeches(); + void abortSpeech(); + bool isSpeaking() { + return _activeSpeech.stringsCount > 0; + } + + void saveState(Common::OutSaveFile *out); + void loadState(Common::InSaveFile *in); + + void setProtagState(int state); + int getProtagState() { return _protagState; } + + void freeActorList(); + void loadActorList(int protagonistIdx, int actorCount, int actorsResourceID, + int protagStatesCount, int protagStatesResourceID); + void freeObjList(); + void loadObjList(int objectCount, int objectsResourceID); + + /* + uint16 _currentFrameIndex; + void frameTest() { + _currentFrameIndex++; + }*/ +protected: + friend class Script; + bool loadActorResources(ActorData *actor); + +private: + void stepZoneAction(ActorData *actor, const HitZone *hitZone, bool exit, bool stopped); + void loadActorSpriteList(ActorData *actor); + + void createDrawOrderList(); + bool calcScreenPosition(CommonObjectData *commonObjectData); + bool getSpriteParams(CommonObjectData *commonObjectData, int &frameNumber, SpriteList *&spriteList); + + bool followProtagonist(ActorData *actor); + void findActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint); + void handleSpeech(int msec); + void handleActions(int msec, bool setup); + bool validPathCellPoint(const Point &testPoint) { + return !((testPoint.x < 0) || (testPoint.x >= _xCellCount) || + (testPoint.y < 0) || (testPoint.y >= _yCellCount)); + } + void setPathCell(const Point &testPoint, int8 value) { + if (!validPathCellPoint(testPoint)) { + error("Actor::setPathCell wrong point"); + } + _pathCell[testPoint.x + testPoint.y * _xCellCount] = value; + } + int8 getPathCell(const Point &testPoint) { + if (!validPathCellPoint(testPoint)) { + error("Actor::getPathCell wrong point"); + } + return _pathCell[testPoint.x + testPoint.y * _xCellCount]; + } + bool scanPathLine(const Point &point1, const Point &point2); + int fillPathArray(const Point &fromPoint, const Point &toPoint, Point &bestPoint); + void setActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint); + void pathToNode(); + void condenseNodeList(); + void removeNodes(); + void nodeToPath(); + void removePathPoints(); + bool validFollowerLocation(const Location &location); + void moveDragon(ActorData *actor); + + +protected: +//constants + int _actorsCount; + ActorData **_actors; + + int _objsCount; + ObjectData **_objs; + + SagaEngine *_vm; + ResourceContext *_actorContext; + + int _lastTickMsec; + CommonObjectOrderList _drawOrderList; + +//variables +public: + ActorData *_centerActor; + ActorData *_protagonist; + int _handleActionDiv; + + Rect _speechBoxScript; + + StringsTable _objectsStrings; + StringsTable _actorsStrings; + +protected: + SpeechData _activeSpeech; + int _protagState; + bool _dragonHunt; + +private: + ActorFrameSequence *_protagStates; + int _protagStatesCount; + +//path stuff + struct PathNode { + Point point; + int link; + }; + + Rect _barrierList[ACTOR_BARRIERS_MAX]; + int _barrierCount; + int8 *_pathCell; + + int _xCellCount; + int _yCellCount; + Rect _pathRect; + + PathDirectionData *_pathDirectionList; + int _pathDirectionListCount; + int _pathDirectionListAlloced; + PathDirectionData * addPathDirectionListData() { + if (_pathDirectionListCount + 1 >= _pathDirectionListAlloced) { + _pathDirectionListAlloced += 100; + _pathDirectionList = (PathDirectionData*) realloc(_pathDirectionList, _pathDirectionListAlloced * sizeof(*_pathDirectionList)); + } + return &_pathDirectionList[_pathDirectionListCount++]; + } + + Point *_pathList; + int _pathListIndex; + int _pathListAlloced; + void addPathListPoint(const Point &point) { + ++_pathListIndex; + if (_pathListIndex >= _pathListAlloced) { + _pathListAlloced += 100; + _pathList = (Point*) realloc(_pathList, _pathListAlloced * sizeof(*_pathList)); + + } + _pathList[_pathListIndex] = point; + } + + int _pathNodeListIndex; + int _pathNodeListAlloced; + PathNode *_pathNodeList; + void addPathNodeListPoint(const Point &point) { + ++_pathNodeListIndex; + if (_pathNodeListIndex >= _pathNodeListAlloced) { + _pathNodeListAlloced += 100; + _pathNodeList = (PathNode*) realloc(_pathNodeList, _pathNodeListAlloced * sizeof(*_pathNodeList)); + + } + _pathNodeList[_pathNodeListIndex].point = point; + } + + int _newPathNodeListIndex; + int _newPathNodeListAlloced; + PathNode *_newPathNodeList; + void incrementNewPathNodeListIndex() { + ++_newPathNodeListIndex; + if (_newPathNodeListIndex >= _newPathNodeListAlloced) { + _newPathNodeListAlloced += 100; + _newPathNodeList = (PathNode*) realloc(_newPathNodeList, _newPathNodeListAlloced * sizeof(*_newPathNodeList)); + + } + } + void addNewPathNodeListPoint(const PathNode &pathNode) { + incrementNewPathNodeListIndex(); + _newPathNodeList[_newPathNodeListIndex] = pathNode; + } + +public: +#ifdef ACTOR_DEBUG +//path debug - use with care + struct DebugPoint { + Point point; + byte color; + }; + DebugPoint *_debugPoints; + int _debugPointsCount; + int _debugPointsAlloced; + void addDebugPoint(const Point &point, byte color) { + if (_debugPointsCount + 1 > _debugPointsAlloced) { + _debugPointsAlloced += 1000; + _debugPoints = (DebugPoint*) realloc(_debugPoints, _debugPointsAlloced * sizeof(*_debugPoints)); + } + _debugPoints[_debugPointsCount].color = color; + _debugPoints[_debugPointsCount++].point = point; + } +#endif +}; + +inline int16 quickDistance(const Point &point1, const Point &point2) { + Point delta; + delta.x = ABS(point1.x - point2.x) / 2; + delta.y = ABS(point1.y - point2.y); + return ((delta.x < delta.y) ? (delta.y + delta.x / 2) : (delta.x + delta.y / 2)); +} +} // End of namespace Saga + +#endif |