mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 09:21:08 +00:00
c441c5261f
svn-id: r33230
709 lines
17 KiB
C++
709 lines
17 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 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$
|
|
*
|
|
* Should really be called "moving actors.c"
|
|
*/
|
|
|
|
#include "tinsel/actors.h"
|
|
#include "tinsel/anim.h"
|
|
#include "tinsel/background.h"
|
|
#include "tinsel/config.h"
|
|
#include "tinsel/dw.h"
|
|
#include "tinsel/film.h"
|
|
#include "tinsel/handle.h"
|
|
#include "tinsel/inventory.h"
|
|
#include "tinsel/move.h"
|
|
#include "tinsel/multiobj.h" // multi-part object defintions etc.
|
|
#include "tinsel/object.h"
|
|
#include "tinsel/pcode.h"
|
|
#include "tinsel/pid.h"
|
|
#include "tinsel/rince.h"
|
|
#include "tinsel/sched.h"
|
|
#include "tinsel/timers.h"
|
|
#include "tinsel/token.h"
|
|
|
|
#include "common/util.h"
|
|
|
|
namespace Tinsel {
|
|
|
|
//----------------- LOCAL GLOBAL DATA --------------------
|
|
|
|
static MACTOR Movers[MAX_MOVERS];
|
|
|
|
|
|
/**
|
|
* RebootMovers
|
|
*/
|
|
void RebootMovers(void) {
|
|
memset(Movers, 0, sizeof(Movers));
|
|
}
|
|
|
|
/**
|
|
* Given an actor number, return pointer to its moving actor structure,
|
|
* if it is a moving actor.
|
|
*/
|
|
PMACTOR GetMover(int ano) {
|
|
int i;
|
|
|
|
// Slot 0 is reserved for lead actor
|
|
if (ano == LeadId() || ano == LEAD_ACTOR)
|
|
return &Movers[0];
|
|
|
|
for (i = 1; i < MAX_MOVERS; i++)
|
|
if (Movers[i].actorID == ano)
|
|
return &Movers[i];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Register an actor as being a moving one.
|
|
*/
|
|
PMACTOR SetMover(int ano) {
|
|
int i;
|
|
|
|
// Slot 0 is reserved for lead actor
|
|
if (ano == LeadId() || ano == LEAD_ACTOR) {
|
|
Movers[0].actorToken = TOKEN_LEAD;
|
|
Movers[0].actorID = LeadId();
|
|
return &Movers[0];
|
|
}
|
|
|
|
// Check it hasn't already been declared
|
|
for (i = 1; i < MAX_MOVERS; i++) {
|
|
if (Movers[i].actorID == ano) {
|
|
// Actor is already a moving actor
|
|
return &Movers[i];
|
|
}
|
|
}
|
|
|
|
// Find an empty slot
|
|
for (i = 1; i < MAX_MOVERS; i++)
|
|
if (!Movers[i].actorID) {
|
|
Movers[i].actorToken = TOKEN_LEAD + i;
|
|
Movers[i].actorID = ano;
|
|
return &Movers[i];
|
|
}
|
|
|
|
error("Too many moving actors");
|
|
}
|
|
|
|
/**
|
|
* Given an index, returns the associated moving actor.
|
|
*
|
|
* At the time of writing, used by the effect process.
|
|
*/
|
|
PMACTOR GetLiveMover(int index) {
|
|
assert(index >= 0 && index < MAX_MOVERS); // out of range
|
|
|
|
if (Movers[index].MActorState == NORM_MACTOR)
|
|
return &Movers[index];
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
bool IsMAinEffectPoly(int index) {
|
|
assert(index >= 0 && index < MAX_MOVERS); // out of range
|
|
|
|
return Movers[index].InEffect;
|
|
}
|
|
|
|
void SetMAinEffectPoly(int index, bool tf) {
|
|
assert(index >= 0 && index < MAX_MOVERS); // out of range
|
|
|
|
Movers[index].InEffect = tf;
|
|
}
|
|
|
|
/**
|
|
* Remove a moving actor from the current scene.
|
|
*/
|
|
void KillMActor(PMACTOR pActor) {
|
|
if (pActor->MActorState == NORM_MACTOR) {
|
|
pActor->MActorState = NO_MACTOR;
|
|
MultiDeleteObject(GetPlayfieldList(FIELD_WORLD), pActor->actorObj);
|
|
pActor->actorObj = NULL;
|
|
assert(CurrentProcess() != pActor->pProc);
|
|
ProcessKill(pActor->pProc);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* getMActorState
|
|
*/
|
|
MAS getMActorState(PMACTOR pActor) {
|
|
return pActor->MActorState;
|
|
}
|
|
|
|
/**
|
|
* If the actor's object exists, move it behind the background.
|
|
* MultiHideObject() is deliberately not used, as StepAnimScript() calls
|
|
* cause the object to re-appear.
|
|
*/
|
|
void hideMActor(PMACTOR pActor, int sf) {
|
|
assert(pActor); // Hiding null moving actor
|
|
|
|
pActor->aHidden = true;
|
|
pActor->SlowFactor = sf;
|
|
|
|
if (pActor->actorObj)
|
|
MultiSetZPosition(pActor->actorObj, -1);
|
|
}
|
|
|
|
/**
|
|
* getMActorHideState
|
|
*/
|
|
bool getMActorHideState(PMACTOR pActor) {
|
|
if (pActor)
|
|
return pActor->aHidden;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* unhideMActor
|
|
*/
|
|
void unhideMActor(PMACTOR pActor) {
|
|
assert(pActor); // unHiding null moving actor
|
|
|
|
pActor->aHidden = false;
|
|
|
|
// Make visible on the screen
|
|
if (pActor->actorObj) {
|
|
// If no path, just use first path in the scene
|
|
if (pActor->hCpath != NOPOLY)
|
|
MAsetZPos(pActor, pActor->objy, getPolyZfactor(pActor->hCpath));
|
|
else
|
|
MAsetZPos(pActor, pActor->objy, getPolyZfactor(FirstPathPoly()));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get it into our heads that there's nothing doing.
|
|
* Called at the end of a scene.
|
|
*/
|
|
void DropMActors(void) {
|
|
for (int i = 0; i < MAX_MOVERS; i++) {
|
|
Movers[i].MActorState = NO_MACTOR;
|
|
Movers[i].objx = 0;
|
|
Movers[i].objy = 0;
|
|
Movers[i].actorObj = NULL; // No moving actor objects
|
|
|
|
Movers[i].hCpath = NOPOLY; // No moving actor path
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Reposition a moving actor.
|
|
*/
|
|
void MoveMActor(PMACTOR pActor, int x, int y) {
|
|
int z;
|
|
int node;
|
|
HPOLYGON hPath;
|
|
|
|
assert(pActor); // Moving null moving actor
|
|
assert(pActor->actorObj);
|
|
|
|
pActor->objx = x;
|
|
pActor->objy = y;
|
|
MultiSetAniXY(pActor->actorObj, x, y);
|
|
|
|
hPath = InPolygon(x, y, PATH);
|
|
if (hPath != NOPOLY) {
|
|
pActor->hCpath = hPath;
|
|
if (PolySubtype(hPath) == NODE) {
|
|
node = NearestNodeWithin(hPath, x, y);
|
|
getNpathNode(hPath, node, &pActor->objx, &pActor->objy);
|
|
pActor->hFnpath = hPath;
|
|
pActor->line = node;
|
|
pActor->npstatus = GOING_UP;
|
|
} else {
|
|
pActor->hFnpath = NOPOLY;
|
|
pActor->npstatus = NOT_IN;
|
|
}
|
|
|
|
z = GetScale(hPath, pActor->objy);
|
|
pActor->scale = z;
|
|
SetMActorStanding(pActor);
|
|
} else {
|
|
pActor->bNoPath = true;
|
|
|
|
pActor->hFnpath = NOPOLY; // Ain't in one
|
|
pActor->npstatus = NOT_IN;
|
|
|
|
// Ensure legal reel and scale
|
|
if (pActor->dirn < 0 || pActor->dirn > 3)
|
|
pActor->dirn = FORWARD;
|
|
if (pActor->scale < 0 || pActor->scale > TOTAL_SCALES)
|
|
pActor->scale = 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get position of a moving actor.
|
|
*/
|
|
void GetMActorPosition(PMACTOR pActor, int *paniX, int *paniY) {
|
|
assert(pActor); // Getting null moving actor's position
|
|
|
|
if (pActor->actorObj != NULL)
|
|
GetAniPosition(pActor->actorObj, paniX, paniY);
|
|
else {
|
|
*paniX = 0;
|
|
*paniY = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Moving actor's mid-top position.
|
|
*/
|
|
void GetMActorMidTopPosition(PMACTOR pActor, int *aniX, int *aniY) {
|
|
assert(pActor); // Getting null moving actor's mid-top position
|
|
assert(pActor->actorObj); // Getting null moving actor's mid-top position
|
|
|
|
*aniX = (MultiLeftmost(pActor->actorObj) + MultiRightmost(pActor->actorObj))/2;
|
|
*aniY = MultiHighest(pActor->actorObj);
|
|
}
|
|
|
|
/**
|
|
* Moving actor's left-most co-ordinate.
|
|
*/
|
|
int GetMActorLeft(PMACTOR pActor) {
|
|
assert(pActor); // Getting null moving actor's leftmost position
|
|
assert(pActor->actorObj); // Getting null moving actor's leftmost position
|
|
|
|
return MultiLeftmost(pActor->actorObj);
|
|
}
|
|
|
|
/**
|
|
* Moving actor's right-most co-ordinate.
|
|
*/
|
|
int GetMActorRight(PMACTOR pActor) {
|
|
assert(pActor); // Getting null moving actor's rightmost position
|
|
assert(pActor->actorObj); // Getting null moving actor's rightmost position
|
|
|
|
return MultiRightmost(pActor->actorObj);
|
|
}
|
|
|
|
/**
|
|
* See if moving actor is stood within a polygon.
|
|
*/
|
|
bool MActorIsInPolygon(PMACTOR pActor, HPOLYGON hp) {
|
|
assert(pActor); // Checking if null moving actor is in polygon
|
|
assert(pActor->actorObj); // Checking if null moving actor is in polygon
|
|
|
|
int aniX, aniY;
|
|
GetAniPosition(pActor->actorObj, &aniX, &aniY);
|
|
|
|
return IsInPolygon(aniX, aniY, hp);
|
|
}
|
|
|
|
/**
|
|
* Change which reel is playing for a moving actor.
|
|
*/
|
|
void AlterMActor(PMACTOR pActor, SCNHANDLE film, AR_FUNCTION fn) {
|
|
const FILM *pfilm;
|
|
|
|
assert(pActor->actorObj); // Altering null moving actor's animation script
|
|
|
|
if (fn == AR_POPREEL) {
|
|
film = pActor->pushedfilm; // Use the saved film
|
|
}
|
|
if (fn == AR_PUSHREEL) {
|
|
// Save the one we're replacing
|
|
pActor->pushedfilm = (pActor->TagReelRunning) ? pActor->lastfilm : 0;
|
|
}
|
|
|
|
if (film == 0) {
|
|
if (pActor->TagReelRunning) {
|
|
// Revert to 'normal' actor
|
|
SetMActorWalkReel(pActor, pActor->dirn, pActor->scale, true);
|
|
pActor->TagReelRunning = false;
|
|
}
|
|
} else {
|
|
pActor->lastfilm = film; // Remember this one
|
|
|
|
pfilm = (const FILM *)LockMem(film);
|
|
assert(pfilm != NULL);
|
|
|
|
InitStepAnimScript(&pActor->actorAnim, pActor->actorObj, FROM_LE_32(pfilm->reels[0].script), ONE_SECOND / FROM_LE_32(pfilm->frate));
|
|
pActor->scount = 0;
|
|
|
|
// If no path, just use first path in the scene
|
|
if (pActor->hCpath != NOPOLY)
|
|
MAsetZPos(pActor, pActor->objy, getPolyZfactor(pActor->hCpath));
|
|
else
|
|
MAsetZPos(pActor, pActor->objy, getPolyZfactor(FirstPathPoly()));
|
|
|
|
if (fn == AR_WALKREEL) {
|
|
pActor->TagReelRunning = false;
|
|
pActor->walkReel = true;
|
|
} else {
|
|
pActor->TagReelRunning = true;
|
|
pActor->walkReel = false;
|
|
|
|
#ifdef DEBUG
|
|
assert(StepAnimScript(&pActor->actorAnim) != ScriptFinished); // Actor reel has finished!
|
|
#else
|
|
StepAnimScript(&pActor->actorAnim); // 04/01/95
|
|
#endif
|
|
}
|
|
|
|
// Hang on, we may not want him yet! 04/01/95
|
|
if (pActor->aHidden)
|
|
MultiSetZPosition(pActor->actorObj, -1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the actor's direction.
|
|
*/
|
|
DIRREEL GetMActorDirection(PMACTOR pActor) {
|
|
return pActor->dirn;
|
|
}
|
|
|
|
/**
|
|
* Return the actor's scale.
|
|
*/
|
|
int GetMActorScale(PMACTOR pActor) {
|
|
return pActor->scale;
|
|
}
|
|
|
|
/**
|
|
* Point actor in specified derection
|
|
*/
|
|
void SetMActorDirection(PMACTOR pActor, DIRREEL dirn) {
|
|
pActor->dirn = dirn;
|
|
}
|
|
|
|
/**
|
|
* MAmoving
|
|
*/
|
|
bool MAmoving(PMACTOR pActor) {
|
|
return pActor->bMoving;
|
|
}
|
|
|
|
/**
|
|
* Return an actor's walk ticket.
|
|
*/
|
|
int GetActorTicket(PMACTOR pActor) {
|
|
return pActor->ticket;
|
|
}
|
|
|
|
/**
|
|
* Get actor to adopt its appropriate standing reel.
|
|
*/
|
|
void SetMActorStanding(PMACTOR pActor) {
|
|
assert(pActor->actorObj);
|
|
AlterMActor(pActor, pActor->StandReels[pActor->scale-1][pActor->dirn], AR_NORMAL);
|
|
}
|
|
|
|
/**
|
|
* Get actor to adopt its appropriate walking reel.
|
|
*/
|
|
void SetMActorWalkReel(PMACTOR pActor, DIRREEL reel, int scale, bool force) {
|
|
SCNHANDLE whichReel;
|
|
const FILM *pfilm;
|
|
|
|
// Kill off any play that may be going on for this actor
|
|
// and restore the real actor
|
|
storeActorReel(pActor->actorID, NULL, 0, NULL, 0, 0, 0);
|
|
unhideMActor(pActor);
|
|
|
|
// Don't do it if using a special walk reel
|
|
if (pActor->walkReel)
|
|
return;
|
|
|
|
if (force || pActor->scale != scale || pActor->dirn != reel) {
|
|
assert(reel >= 0 && reel <= 3 && scale > 0 && scale <= TOTAL_SCALES); // out of range scale or reel
|
|
|
|
// If scale change and both are regular scales
|
|
// and there's a scaling reel in the right direction
|
|
if (pActor->scale != scale
|
|
&& scale <= NUM_MAINSCALES && pActor->scale <= NUM_MAINSCALES
|
|
&& (whichReel = ScalingReel(pActor->actorID, pActor->scale, scale, reel)) != 0) {
|
|
// error("Cripes!");
|
|
; // Use what is now in 'whichReel'
|
|
} else {
|
|
whichReel = pActor->WalkReels[scale-1][reel];
|
|
assert(whichReel); // no reel
|
|
}
|
|
|
|
pfilm = (const FILM *)LockMem(whichReel);
|
|
assert(pfilm != NULL); // no film
|
|
|
|
InitStepAnimScript(&pActor->actorAnim, pActor->actorObj, FROM_LE_32(pfilm->reels[0].script), 1);
|
|
|
|
// Synchronised walking reels
|
|
SkipFrames(&pActor->actorAnim, pActor->scount);
|
|
|
|
pActor->scale = scale;
|
|
pActor->dirn = reel;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sort some stuff out at actor start-up time.
|
|
*/
|
|
static void InitialPathChecks(PMACTOR pActor, int xpos, int ypos) {
|
|
HPOLYGON hPath;
|
|
int node;
|
|
int z;
|
|
|
|
pActor->objx = xpos;
|
|
pActor->objy = ypos;
|
|
|
|
/*--------------------------------------
|
|
| If Actor is in a follow nodes path, |
|
|
| position it at the nearest node. |
|
|
--------------------------------------*/
|
|
hPath = InPolygon(xpos, ypos, PATH);
|
|
|
|
if (hPath != NOPOLY) {
|
|
pActor->hCpath = hPath;
|
|
if (PolySubtype(hPath) == NODE) {
|
|
node = NearestNodeWithin(hPath, xpos, ypos);
|
|
getNpathNode(hPath, node, &pActor->objx, &pActor->objy);
|
|
pActor->hFnpath = hPath;
|
|
pActor->line = node;
|
|
pActor->npstatus = GOING_UP;
|
|
}
|
|
|
|
z = GetScale(hPath, pActor->objy);
|
|
} else {
|
|
pActor->bNoPath = true;
|
|
|
|
z = GetScale(FirstPathPoly(), pActor->objy);
|
|
}
|
|
SetMActorWalkReel(pActor, FORWARD, z, false);
|
|
}
|
|
|
|
/**
|
|
* Clear everything out at actor start-up time.
|
|
*/
|
|
static void InitMActor(PMACTOR pActor) {
|
|
|
|
pActor->objx = pActor->objy = 0;
|
|
pActor->targetX = pActor->targetY = -1;
|
|
pActor->ItargetX = pActor->ItargetY = -1;
|
|
pActor->hIpath = NOPOLY;
|
|
pActor->UtargetX = pActor->UtargetY = -1;
|
|
pActor->hUpath = NOPOLY;
|
|
pActor->hCpath = NOPOLY;
|
|
|
|
pActor->over = false;
|
|
pActor->InDifficulty = NO_PROB;
|
|
|
|
pActor->hFnpath = NOPOLY;
|
|
pActor->npstatus = NOT_IN;
|
|
pActor->line = 0;
|
|
|
|
pActor->Tline = 0;
|
|
|
|
pActor->TagReelRunning = false;
|
|
|
|
if (pActor->dirn != FORWARD || pActor->dirn != AWAY
|
|
|| pActor->dirn != LEFTREEL || pActor->dirn != RIGHTREEL)
|
|
pActor->dirn = FORWARD;
|
|
|
|
if (pActor->scale < 0 || pActor->scale > TOTAL_SCALES)
|
|
pActor->scale = 1;
|
|
|
|
pActor->scount = 0;
|
|
|
|
pActor->fromx = pActor->fromy = 0;
|
|
|
|
pActor->bMoving = false;
|
|
pActor->bNoPath = false;
|
|
pActor->bIgPath = false;
|
|
pActor->walkReel = false;
|
|
|
|
pActor->actorObj = NULL;
|
|
|
|
pActor->lastfilm = 0;
|
|
pActor->pushedfilm = 0;
|
|
|
|
pActor->InEffect = false;
|
|
pActor->aHidden = false; // 20/2/95
|
|
}
|
|
|
|
static void MActorProcessHelper(int X, int Y, int id, PMACTOR pActor) {
|
|
const FILM *pfilm;
|
|
const MULTI_INIT *pmi;
|
|
const FRAME *pFrame;
|
|
PIMAGE pim;
|
|
|
|
|
|
assert(BackPal()); // Can't start actor without a background palette
|
|
assert(pActor->WalkReels[0][FORWARD]); // Starting actor process without walk reels
|
|
|
|
InitMActor(pActor);
|
|
InitialPathChecks(pActor, X, Y);
|
|
|
|
pfilm = (const FILM *)LockMem(pActor->WalkReels[0][FORWARD]);
|
|
pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(pfilm->reels[0].mobj));
|
|
|
|
//---
|
|
pFrame = (const FRAME *)LockMem(FROM_LE_32(pmi->hMulFrame));
|
|
|
|
// get pointer to image
|
|
pim = (PIMAGE)LockMem(READ_LE_UINT32(pFrame)); // handle to image
|
|
pim->hImgPal = TO_LE_32(BackPal());
|
|
//---
|
|
pActor->actorObj = MultiInitObject(pmi);
|
|
|
|
/**/ assert(pActor->actorID == id);
|
|
pActor->actorID = id;
|
|
|
|
// add it to display list
|
|
MultiInsertObject(GetPlayfieldList(FIELD_WORLD), pActor->actorObj);
|
|
storeActorReel(id, NULL, 0, pActor->actorObj, 0, 0, 0);
|
|
|
|
InitStepAnimScript(&pActor->actorAnim, pActor->actorObj, FROM_LE_32(pfilm->reels[0].script), ONE_SECOND / FROM_LE_32(pfilm->frate));
|
|
pActor->scount = 0;
|
|
|
|
MultiSetAniXY(pActor->actorObj, pActor->objx, pActor->objy);
|
|
|
|
// If no path, just use first path in the scene
|
|
if (pActor->hCpath != NOPOLY)
|
|
MAsetZPos(pActor, pActor->objy, getPolyZfactor(pActor->hCpath));
|
|
else
|
|
MAsetZPos(pActor, pActor->objy, getPolyZfactor(FirstPathPoly()));
|
|
|
|
// Make him the right size
|
|
SetMActorStanding(pActor);
|
|
|
|
//**** if added 18/11/94, am
|
|
if (X != MAGICX && Y != MAGICY) {
|
|
hideMActor(pActor, 0); // Allows a play to come in before this appears
|
|
pActor->aHidden = false; // ...but don't stay hidden
|
|
}
|
|
|
|
pActor->MActorState = NORM_MACTOR;
|
|
}
|
|
|
|
/**
|
|
* Moving actor process - 1 per moving actor in current scene.
|
|
*/
|
|
void MActorProcess(CORO_PARAM) {
|
|
// COROUTINE
|
|
CORO_BEGIN_CONTEXT;
|
|
CORO_END_CONTEXT(_ctx);
|
|
|
|
PMACTOR pActor = *(PMACTOR *)ProcessGetParamsSelf();
|
|
|
|
CORO_BEGIN_CODE(_ctx);
|
|
|
|
while (1) {
|
|
if (pActor->TagReelRunning) {
|
|
if (!pActor->aHidden)
|
|
#ifdef DEBUG
|
|
assert(StepAnimScript(&pActor->actorAnim) != ScriptFinished); // Actor reel has finished!
|
|
#else
|
|
StepAnimScript(&pActor->actorAnim);
|
|
#endif
|
|
} else
|
|
DoMoveActor(pActor);
|
|
|
|
CORO_SLEEP(1); // allow rescheduling
|
|
|
|
}
|
|
|
|
CORO_END_CODE;
|
|
}
|
|
|
|
void MActorProcessCreate(int X, int Y, int id, PMACTOR pActor) {
|
|
MActorProcessHelper(X, Y, id, pActor);
|
|
pActor->pProc = CoroutineInstall(PID_MACTOR, MActorProcess, &pActor, sizeof(PMACTOR));
|
|
}
|
|
|
|
|
|
/**
|
|
* Check for moving actor collision.
|
|
*/
|
|
PMACTOR InMActorBlock(PMACTOR pActor, int x, int y) {
|
|
int caX; // Calling actor's pos'n
|
|
int caL, caR; // Calling actor's left and right
|
|
int taX, taY; // Test actor's pos'n
|
|
int taL, taR; // Test actor's left and right
|
|
|
|
caX = pActor->objx;
|
|
if (pActor->hFnpath != NOPOLY || bNoBlocking)
|
|
return NULL;
|
|
|
|
caL = GetMActorLeft(pActor) + x - caX;
|
|
caR = GetMActorRight(pActor) + x - caX;
|
|
|
|
for (int i = 0; i < MAX_MOVERS; i++) {
|
|
if (pActor == &Movers[i] || Movers[i].MActorState == NO_MACTOR)
|
|
continue;
|
|
|
|
// At around the same height?
|
|
GetMActorPosition(&Movers[i], &taX, &taY);
|
|
if (Movers[i].hFnpath != NOPOLY)
|
|
continue;
|
|
|
|
if (ABS(y - taY) > 2) // 2 was 8
|
|
continue;
|
|
|
|
// To the left?
|
|
taL = GetMActorLeft(&Movers[i]);
|
|
if (caR <= taL)
|
|
continue;
|
|
|
|
// To the right?
|
|
taR = GetMActorRight(&Movers[i]);
|
|
if (caL >= taR)
|
|
continue;
|
|
|
|
return &Movers[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Copies key information for savescn.c to store away.
|
|
*/
|
|
void SaveMovers(SAVED_MOVER *sMoverInfo) {
|
|
for (int i = 0; i < MAX_MOVERS; i++) {
|
|
sMoverInfo[i].MActorState= Movers[i].MActorState;
|
|
sMoverInfo[i].actorID = Movers[i].actorID;
|
|
sMoverInfo[i].objx = Movers[i].objx;
|
|
sMoverInfo[i].objy = Movers[i].objy;
|
|
sMoverInfo[i].lastfilm = Movers[i].lastfilm;
|
|
|
|
memcpy(sMoverInfo[i].WalkReels, Movers[i].WalkReels, TOTAL_SCALES*4*sizeof(SCNHANDLE));
|
|
memcpy(sMoverInfo[i].StandReels, Movers[i].StandReels, TOTAL_SCALES*4*sizeof(SCNHANDLE));
|
|
memcpy(sMoverInfo[i].TalkReels, Movers[i].TalkReels, TOTAL_SCALES*4*sizeof(SCNHANDLE));
|
|
}
|
|
}
|
|
|
|
void RestoreAuxScales(SAVED_MOVER *sMoverInfo) {
|
|
for (int i = 0; i < MAX_MOVERS; i++) {
|
|
memcpy(Movers[i].WalkReels, sMoverInfo[i].WalkReels, TOTAL_SCALES*4*sizeof(SCNHANDLE));
|
|
memcpy(Movers[i].StandReels, sMoverInfo[i].StandReels, TOTAL_SCALES*4*sizeof(SCNHANDLE));
|
|
memcpy(Movers[i].TalkReels, sMoverInfo[i].TalkReels, TOTAL_SCALES*4*sizeof(SCNHANDLE));
|
|
}
|
|
}
|
|
|
|
} // end of namespace Tinsel
|