mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-18 07:39:08 +00:00
802a301a16
svn-id: r12739
799 lines
21 KiB
C++
799 lines
21 KiB
C++
/* Copyright (C) 1994-2004 Revolution Software Ltd
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*/
|
|
|
|
// WALKER.CPP by James (14nov96)
|
|
|
|
// script functions for moving megas about the place & also for keeping tabs
|
|
// on them
|
|
|
|
#include "common/stdafx.h"
|
|
#include "sword2/sword2.h"
|
|
#include "sword2/defs.h"
|
|
#include "sword2/interpreter.h"
|
|
#include "sword2/logic.h"
|
|
#include "sword2/resman.h"
|
|
#include "sword2/driver/d_draw.h"
|
|
|
|
namespace Sword2 {
|
|
|
|
/**
|
|
* Walk mega to (x,y,dir)
|
|
*/
|
|
|
|
int32 Logic::fnWalk(int32 *params) {
|
|
// params: 0 pointer to object's logic structure
|
|
// 1 pointer to object's graphic structure
|
|
// 2 pointer to object's mega structure
|
|
// 3 pointer to object's walkdata structure
|
|
// 4 target x-coord
|
|
// 5 target y-coord
|
|
// 6 target direction
|
|
|
|
ObjectLogic *ob_logic;
|
|
ObjectGraphic *ob_graph;
|
|
ObjectMega *ob_mega;
|
|
ObjectWalkdata *ob_walkdata;
|
|
int16 target_x;
|
|
int16 target_y;
|
|
uint8 target_dir;
|
|
int32 route;
|
|
int32 walk_pc;
|
|
WalkData *walkAnim;
|
|
|
|
// get the parameters
|
|
|
|
ob_logic = (ObjectLogic *) _vm->_memory->intToPtr(params[0]);
|
|
ob_graph = (ObjectGraphic *) _vm->_memory->intToPtr(params[1]);
|
|
ob_mega = (ObjectMega *) _vm->_memory->intToPtr(params[2]);
|
|
|
|
target_x = (int16) params[4];
|
|
target_y = (int16) params[5];
|
|
target_dir = (uint8) params[6];
|
|
|
|
// if this is the start of the walk, calculate route
|
|
|
|
if (ob_logic->looping == 0) {
|
|
// If we're already there, don't even bother allocating
|
|
// memory and calling the router, just quit back & continue
|
|
// the script! This avoids an embarassing mega stand frame
|
|
// appearing for one cycle when we're already in position for
|
|
// an anim eg. repeatedly clicking on same object to repeat
|
|
// an anim - no mega frame will appear in between runs of the
|
|
// anim.
|
|
|
|
if (ob_mega->feet_x == target_x && ob_mega->feet_y == target_y && ob_mega->current_dir == target_dir) {
|
|
RESULT = 0; // 0 means ok - finished walk
|
|
return IR_CONT; // may as well continue the script
|
|
}
|
|
|
|
// invalid direction (NB. '8' means end walk on ANY direction)
|
|
if (params[6] < 0 || params[6] > 8)
|
|
error("Invalid direction (%d) in fnWalk", params[6]);
|
|
|
|
ob_walkdata = (ObjectWalkdata *) _vm->_memory->intToPtr(params[3]);
|
|
|
|
ob_mega->walk_pc = 0; // always
|
|
|
|
// set up mem for _walkData in route_slots[] & set mega's
|
|
// 'route_slot_id' accordingly
|
|
|
|
_router->allocateRouteMem();
|
|
|
|
route = _router->routeFinder(ob_mega, ob_walkdata, target_x, target_y, target_dir);
|
|
|
|
// 0 = can't make route to target
|
|
// 1 = created route
|
|
// 2 = zero route but may need to turn
|
|
|
|
if (route == 1 || route == 2) {
|
|
// so script fnWalk loop continues until end of
|
|
// walk-anim
|
|
|
|
ob_logic->looping = 1;
|
|
|
|
// need to animate the route now, so don't set result
|
|
// or return yet!
|
|
|
|
// started walk
|
|
ob_mega->currently_walking = 1;
|
|
|
|
// (see fnGetPlayerSaveData() in save_rest.cpp
|
|
} else {
|
|
// free up the walkdata mem block
|
|
_router->freeRouteMem();
|
|
|
|
// 1 means error, no walk created
|
|
RESULT = 1;
|
|
|
|
// may as well continue the script
|
|
return IR_CONT;
|
|
}
|
|
|
|
// ok, walk is about to start, so set the mega's graphic
|
|
// resource
|
|
|
|
ob_graph->anim_resource = ob_mega->megaset_res;
|
|
} else if (EXIT_FADING && _vm->_graphics->getFadeStatus() == RDFADE_BLACK) {
|
|
// double clicked an exit so quit the walk when screen is black
|
|
|
|
// ok, thats it - back to script and change screen
|
|
|
|
ob_logic->looping = 0; // so script loop stops
|
|
_router->freeRouteMem(); // free up the walkdata mem block
|
|
|
|
// must clear in-case on the new screen there's a walk
|
|
// instruction (which would get cut short)
|
|
EXIT_CLICK_ID = 0;
|
|
|
|
// this will be reset when we change screens, so we can use
|
|
// it in script to check if a 2nd-click came along
|
|
// EXIT_FADING = 0;
|
|
|
|
// finished walk
|
|
ob_mega->currently_walking = 0;
|
|
|
|
// (see fnGetPlayerSaveData() in save_rest.cpp
|
|
|
|
RESULT = 0; // 0 means ok
|
|
|
|
// continue the script so that RESULT can be checked!
|
|
return IR_CONT;
|
|
}
|
|
|
|
// get pointer to walkanim & current frame position
|
|
|
|
// lock the _walkData array
|
|
walkAnim = _router->lockRouteMem();
|
|
walk_pc = ob_mega->walk_pc;
|
|
|
|
// if stopping the walk early, overwrite the next step with a
|
|
// slow-out, then finish
|
|
|
|
if (checkEventWaiting()) {
|
|
if (walkAnim[walk_pc].step == 0 && walkAnim[walk_pc + 1].step == 1) {
|
|
// at the beginning of a step
|
|
ob_walkdata = (ObjectWalkdata *) _vm->_memory->intToPtr(params[3]);
|
|
_router->earlySlowOut(ob_mega, ob_walkdata);
|
|
}
|
|
}
|
|
|
|
// get new frame of walk
|
|
|
|
ob_graph->anim_pc = walkAnim[walk_pc].frame;
|
|
ob_mega->current_dir = walkAnim[walk_pc].dir;
|
|
ob_mega->feet_x = walkAnim[walk_pc].x;
|
|
ob_mega->feet_y = walkAnim[walk_pc].y;
|
|
|
|
// check if NEXT frame is in fact the end-marker of the walk sequence
|
|
// so we can return to script just as the final (stand) frame of the
|
|
// walk is set - so that if followed by an anim, the anim's first
|
|
// frame replaces the final stand-frame of the walk (see below)
|
|
|
|
// '512' is end-marker
|
|
if (walkAnim[walk_pc + 1].frame == 512) {
|
|
ob_logic->looping = 0; // so script loop stops
|
|
_router->freeRouteMem(); // free up the walkdata mem block
|
|
|
|
// finished walk
|
|
ob_mega->currently_walking = 0;
|
|
|
|
// (see fnGetPlayerSaveData() in save_rest.cpp
|
|
|
|
// if George's walk has been interrupted to run a new action
|
|
// script for instance or Nico's walk has been interrupted by
|
|
// player clicking on her to talk
|
|
|
|
// There used to be code here for checking if two megas were
|
|
// colliding, but that code had been commented out, and it
|
|
// was only run if a function that always returned zero
|
|
// returned non-zero.
|
|
|
|
if (checkEventWaiting()) {
|
|
startEvent();
|
|
RESULT = 1; // 1 means didn't finish walk
|
|
return IR_TERMINATE;
|
|
} else {
|
|
RESULT = 0; // 0 means ok - finished walk
|
|
|
|
// CONTINUE the script so that RESULT can be checked!
|
|
// Also, if an anim command follows the fnWalk command,
|
|
// the 1st frame of the anim (which is always a stand
|
|
// frame itself) can replace the final stand frame of
|
|
// the walk, to hide the slight difference between the
|
|
// shrinking on the mega frames and the pre-shrunk anim
|
|
// start-frame.
|
|
|
|
return IR_CONT;
|
|
}
|
|
}
|
|
|
|
// increment the walkanim frame number, float the walkanim & come
|
|
// back next cycle
|
|
|
|
ob_mega->walk_pc++;
|
|
|
|
// allow _walkData array to float about memory again
|
|
_router->floatRouteMem();
|
|
return IR_REPEAT;
|
|
}
|
|
|
|
/**
|
|
* Walk mega to start position of anim
|
|
*/
|
|
|
|
int32 Logic::fnWalkToAnim(int32 *params) {
|
|
// params: 0 pointer to object's logic structure
|
|
// 1 pointer to object's graphic structure
|
|
// 2 pointer to object's mega structure
|
|
// 3 pointer to object's walkdata structure
|
|
// 4 anim resource id
|
|
|
|
ObjectLogic *ob_logic;
|
|
uint8 *anim_file;
|
|
AnimHeader *anim_head;
|
|
int32 pars[7];
|
|
|
|
// if this is the start of the walk, read anim file to get start coords
|
|
|
|
ob_logic = (ObjectLogic *) _vm->_memory->intToPtr(params[0]);
|
|
|
|
if (ob_logic->looping == 0) {
|
|
// open anim file
|
|
anim_file = _vm->_resman->openResource(params[4]);
|
|
|
|
// point to animation header
|
|
anim_head = _vm->fetchAnimHeader( anim_file );
|
|
|
|
pars[4] = anim_head->feetStartX; // target_x
|
|
pars[5] = anim_head->feetStartY; // target_y
|
|
pars[6] = anim_head->feetStartDir; // target_dir
|
|
|
|
// close anim file
|
|
_vm->_resman->closeResource(params[4]);
|
|
|
|
// if start coords not yet set in anim header, use the standby
|
|
// coords (which should be set beforehand in the script)
|
|
|
|
if (pars[4] == 0 && pars[5] == 0) {
|
|
pars[4] = _standbyX;
|
|
pars[5] = _standbyY;
|
|
pars[6] = _standbyDir;
|
|
|
|
debug(5, "WARNING: fnWalkToAnim(%s) used standby coords", _vm->fetchObjectName(params[4]));
|
|
}
|
|
|
|
if (pars[6] < 0 || pars[6] > 7)
|
|
error("Invalid direction (%d) in fnWalkToAnim", pars[6]);
|
|
}
|
|
|
|
// set up the rest of the parameters for fnWalk()
|
|
|
|
pars[0] = params[0];
|
|
pars[1] = params[1];
|
|
pars[2] = params[2];
|
|
pars[3] = params[3];
|
|
|
|
// walkdata (param 3) is needed for earlySlowOut if player clicks
|
|
// elsewhere during the walk
|
|
|
|
// call fnWalk() with target coords set to anim start position
|
|
return fnWalk(pars);
|
|
}
|
|
|
|
/**
|
|
* turn mega to <direction>
|
|
* just needs to call fnWalk() with current feet coords, so router can
|
|
* produce anim of turn frames
|
|
*/
|
|
|
|
int32 Logic::fnTurn(int32 *params) {
|
|
// params: 0 pointer to object's logic structure
|
|
// 1 pointer to object's graphic structure
|
|
// 2 pointer to object's mega structure
|
|
// 3 pointer to object's walkdata structure
|
|
// 4 target direction
|
|
|
|
ObjectLogic *ob_logic;
|
|
ObjectMega *ob_mega;
|
|
int32 pars[7];
|
|
|
|
// if this is the start of the turn, get the mega's current feet
|
|
// coords + the required direction
|
|
|
|
ob_logic = (ObjectLogic *) _vm->_memory->intToPtr(params[0]);
|
|
|
|
if (ob_logic->looping == 0) {
|
|
if (params[4] < 0 || params[4] > 7)
|
|
error("Invalid direction (%d) in fnTurn", params[4]);
|
|
|
|
ob_mega = (ObjectMega *) _vm->_memory->intToPtr(params[2]);
|
|
|
|
pars[4] = ob_mega->feet_x;
|
|
pars[5] = ob_mega->feet_y;
|
|
pars[6] = params[4]; // DIRECTION to turn to
|
|
}
|
|
|
|
// set up the rest of the parameters for fnWalk()
|
|
|
|
pars[0] = params[0];
|
|
pars[1] = params[1];
|
|
pars[2] = params[2];
|
|
pars[3] = params[3];
|
|
|
|
// call fnWalk() with target coords set to feet coords
|
|
return fnWalk(pars);
|
|
}
|
|
|
|
/**
|
|
* stand mega at (x,y,dir)
|
|
* sets up the graphic object, but also needs to set the new 'current_dir' in
|
|
* the mega object, so the router knows in future
|
|
*/
|
|
|
|
int32 Logic::fnStandAt(int32 *params) {
|
|
// params: 0 pointer to object's graphic structure
|
|
// 1 pointer to object's mega structure
|
|
// 2 target x-coord
|
|
// 3 target y-coord
|
|
// 4 target direction
|
|
|
|
ObjectMega *ob_mega;
|
|
ObjectGraphic *ob_graph;
|
|
|
|
// check for invalid direction
|
|
|
|
if (params[4] < 0 || params[4] > 7)
|
|
error("Invalid direction (%d) in fnStandAt", params[4]);
|
|
|
|
// set up pointers to the graphic & mega structure
|
|
|
|
ob_graph = (ObjectGraphic *) _vm->_memory->intToPtr(params[0]);
|
|
ob_mega = (ObjectMega *) _vm->_memory->intToPtr(params[1]);
|
|
|
|
// set up the stand frame & set the mega's new direction
|
|
|
|
// mega-set animation file
|
|
ob_graph->anim_resource = ob_mega->megaset_res;
|
|
|
|
ob_mega->feet_x = params[2];
|
|
ob_mega->feet_y = params[3];
|
|
|
|
// dir + first stand frame (always frame 96)
|
|
ob_graph->anim_pc = params[4] + 96;
|
|
|
|
ob_mega->current_dir = params[4];
|
|
|
|
return IR_CONT;
|
|
}
|
|
|
|
// stand mega in <direction> at current feet coords
|
|
// just needs to call fnStandAt() with current feet coords
|
|
|
|
int32 Logic::fnStand(int32 *params) {
|
|
// params: 0 pointer to object's graphic structure
|
|
// 1 pointer to object's mega structure
|
|
// 2 target direction
|
|
|
|
ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->intToPtr(params[1]);
|
|
int32 pars[5];
|
|
|
|
pars[0] = params[0];
|
|
pars[1] = params[1];
|
|
pars[2] = ob_mega->feet_x;
|
|
pars[3] = ob_mega->feet_y;
|
|
pars[4] = params[2]; // DIRECTION to stand in
|
|
|
|
// call fnStandAt() with target coords set to feet coords
|
|
return fnStandAt(pars);
|
|
}
|
|
|
|
/**
|
|
* stand mega at end position of anim
|
|
*/
|
|
|
|
int32 Logic::fnStandAfterAnim(int32 *params) {
|
|
// params: 0 pointer to object's graphic structure
|
|
// 1 pointer to object's mega structure
|
|
// 2 anim resource id
|
|
|
|
uint8 *anim_file;
|
|
AnimHeader *anim_head;
|
|
int32 pars[5];
|
|
|
|
// open the anim file & set up a pointer to the animation header
|
|
|
|
// open anim file
|
|
anim_file = _vm->_resman->openResource(params[2]);
|
|
anim_head = _vm->fetchAnimHeader(anim_file);
|
|
|
|
// set up the parameter list for fnWalkTo()
|
|
|
|
pars[0] = params[0];
|
|
pars[1] = params[1];
|
|
|
|
pars[2] = anim_head->feetEndX;
|
|
pars[3] = anim_head->feetEndY;
|
|
pars[4] = anim_head->feetEndDir;
|
|
|
|
// if start coords not available either use the standby coords (which
|
|
// should be set beforehand in the script)
|
|
|
|
if (pars[2] == 0 && pars[3] == 0) {
|
|
pars[2] = _standbyX;
|
|
pars[3] = _standbyY;
|
|
pars[4] = _standbyDir;
|
|
|
|
debug(5, "WARNING: fnStandAfterAnim(%s) used standby coords", _vm->fetchObjectName(params[2]));
|
|
}
|
|
|
|
if (pars[4] < 0 || pars[4] > 7)
|
|
error("Invalid direction (%d) in fnStandAfterAnim", pars[4]);
|
|
|
|
// close the anim file
|
|
_vm->_resman->closeResource(params[2]);
|
|
|
|
// call fnStandAt() with target coords set to anim end position
|
|
return fnStandAt(pars);
|
|
}
|
|
|
|
// stand mega at start position of anim
|
|
|
|
int32 Logic::fnStandAtAnim(int32 *params) {
|
|
// params: 0 pointer to object's graphic structure
|
|
// 1 pointer to object's mega structure
|
|
// 2 anim resource id
|
|
|
|
uint8 *anim_file;
|
|
AnimHeader *anim_head;
|
|
int32 pars[5];
|
|
|
|
// open the anim file & set up a pointer to the animation header
|
|
|
|
// open anim file
|
|
anim_file = _vm->_resman->openResource(params[2]);
|
|
anim_head = _vm->fetchAnimHeader(anim_file);
|
|
|
|
// set up the parameter list for fnWalkTo()
|
|
|
|
pars[0] = params[0];
|
|
pars[1] = params[1];
|
|
|
|
pars[2] = anim_head->feetStartX;
|
|
pars[3] = anim_head->feetStartY;
|
|
pars[4] = anim_head->feetStartDir;
|
|
|
|
// if start coords not available use the standby coords (which should
|
|
// be set beforehand in the script)
|
|
|
|
if (pars[2] == 0 && pars[3] == 0) {
|
|
pars[2] = _standbyX;
|
|
pars[3] = _standbyY;
|
|
pars[4] = _standbyDir;
|
|
|
|
debug(5, "WARNING: fnStandAtAnim(%s) used standby coords", _vm->fetchObjectName(params[2]));
|
|
}
|
|
|
|
if (pars[4] < 0 || pars[4] > 7)
|
|
error("Invalid direction (%d) in fnStandAfterAnim", pars[4]);
|
|
|
|
// close the anim file
|
|
_vm->_resman->closeResource(params[2]);
|
|
|
|
// call fnStandAt() with target coords set to anim end position
|
|
return fnStandAt(pars);
|
|
}
|
|
|
|
// Code to workout direction from start to dest
|
|
|
|
// used in what_target not valid for all megas
|
|
#define diagonalx 36
|
|
#define diagonaly 8
|
|
|
|
int Logic::whatTarget(int startX, int startY, int destX, int destY) {
|
|
int deltaX = destX - startX;
|
|
int deltaY = destY - startY;
|
|
|
|
// 7 0 1
|
|
// 6 2
|
|
// 5 4 3
|
|
|
|
// Flat route
|
|
|
|
if (ABS(deltaY) * diagonalx < ABS(deltaX) * diagonaly / 2)
|
|
return (deltaX > 0) ? 2 : 6;
|
|
|
|
// Vertical route
|
|
|
|
if (ABS(deltaY) * diagonalx / 2 > ABS(deltaX) * diagonaly)
|
|
return (deltaY > 0) ? 4 : 0;
|
|
|
|
// Diagonal route
|
|
|
|
if (deltaX > 0)
|
|
return (deltaY > 0) ? 3 : 1;
|
|
|
|
return (deltaY > 0) ? 5 : 7;
|
|
}
|
|
|
|
/**
|
|
* turn mega to face point (x,y) on the floor
|
|
* just needs to call fnWalk() with current feet coords & direction computed
|
|
* by whatTarget()
|
|
*/
|
|
|
|
int32 Logic::fnFaceXY(int32 *params) {
|
|
// params: 0 pointer to object's logic structure
|
|
// 1 pointer to object's graphic structure
|
|
// 2 pointer to object's mega structure
|
|
// 3 pointer to object's walkdata structure
|
|
// 4 target x-coord
|
|
// 5 target y-coord
|
|
|
|
ObjectLogic *ob_logic;
|
|
ObjectMega *ob_mega;
|
|
int32 pars[7];
|
|
|
|
// if this is the start of the turn, get the mega's current feet
|
|
// coords + the required direction
|
|
|
|
ob_logic = (ObjectLogic *) _vm->_memory->intToPtr(params[0]);
|
|
|
|
if (ob_logic->looping == 0) {
|
|
ob_mega = (ObjectMega *) _vm->_memory->intToPtr(params[2]);
|
|
|
|
pars[4] = ob_mega->feet_x;
|
|
pars[5] = ob_mega->feet_y;
|
|
pars[6] = whatTarget(ob_mega->feet_x, ob_mega->feet_y, params[4], params[5]);
|
|
}
|
|
|
|
// set up the rest of the parameters for fnWalk()
|
|
|
|
pars[0] = params[0];
|
|
pars[1] = params[1];
|
|
pars[2] = params[2];
|
|
pars[3] = params[3];
|
|
|
|
// call fnWalk() with target coords set to feet coords
|
|
return fnWalk(pars);
|
|
}
|
|
|
|
int32 Logic::fnFaceMega(int32 *params) {
|
|
// params: 0 pointer to object's logic structure
|
|
// 1 pointer to object's graphic structure
|
|
// 2 pointer to object's mega structure
|
|
// 3 pointer to object's walkdata structure
|
|
// 4 id of target mega to face
|
|
|
|
uint32 null_pc = 3; // get ob_mega
|
|
char *raw_script_ad;
|
|
int32 pars[7];
|
|
ObjectLogic *ob_logic;
|
|
ObjectMega *ob_mega;
|
|
StandardHeader *head;
|
|
|
|
ob_mega = (ObjectMega *) _vm->_memory->intToPtr(params[2]);
|
|
ob_logic = (ObjectLogic *) _vm->_memory->intToPtr(params[0]);
|
|
|
|
if (ob_logic->looping == 0) {
|
|
// get targets info
|
|
head = (StandardHeader *) _vm->_resman->openResource(params[4]);
|
|
|
|
if (head->fileType != GAME_OBJECT)
|
|
error("fnFaceMega %d not an object", params[4]);
|
|
|
|
raw_script_ad = (char *) head;
|
|
|
|
//call the base script - this is the graphic/mouse service call
|
|
runScript(raw_script_ad, raw_script_ad, &null_pc);
|
|
|
|
_vm->_resman->closeResource(params[4]);
|
|
|
|
// engineMega is now the ObjectMega of mega we want to turn
|
|
// to face
|
|
|
|
pars[3] = params[3];
|
|
pars[4] = ob_mega->feet_x;
|
|
pars[5] = ob_mega->feet_y;
|
|
pars[6] = whatTarget(ob_mega->feet_x, ob_mega->feet_y, _vm->_engineMega.feet_x, _vm->_engineMega.feet_y);
|
|
}
|
|
|
|
pars[0] = params[0];
|
|
pars[1] = params[1];
|
|
pars[2] = params[2];
|
|
pars[3] = params[3];
|
|
|
|
// call fnWalk() with target coords set to feet coords
|
|
return fnWalk(pars);
|
|
}
|
|
|
|
int32 Logic::fnWalkToTalkToMega(int32 *params) {
|
|
// we route to left or right hand side of target id if possible
|
|
// target is a shrinking mega
|
|
|
|
// params: 0 pointer to object's logic structure
|
|
// 1 pointer to object's graphic structure
|
|
// 2 pointer to object's mega structure
|
|
// 3 pointer to object's walkdata structure
|
|
// 4 id of target mega to face
|
|
// 5 distance
|
|
|
|
ObjectMega *ob_mega;
|
|
ObjectLogic *ob_logic;
|
|
|
|
uint32 null_pc = 3; // 4th script - get mega
|
|
char *raw_script_ad;
|
|
int32 pars[7];
|
|
int scale;
|
|
int mega_separation = params[5];
|
|
StandardHeader *head;
|
|
|
|
ob_logic = (ObjectLogic *) _vm->_memory->intToPtr(params[0]);
|
|
ob_mega = (ObjectMega *) _vm->_memory->intToPtr(params[2]);
|
|
|
|
pars[0] = params[0]; // standard stuff
|
|
pars[1] = params[1];
|
|
pars[2] = params[2];
|
|
pars[3] = params[3]; // walkdata
|
|
|
|
// not been here before so decide where to walk-to
|
|
if (!ob_logic->looping) {
|
|
// first request the targets info
|
|
head = (StandardHeader *) _vm->_resman->openResource(params[4]);
|
|
|
|
if (head->fileType != GAME_OBJECT)
|
|
error("fnWalkToTalkToMega %d not an object", params[4]);
|
|
|
|
raw_script_ad = (char *) head;
|
|
|
|
// call the base script - this is the graphic/mouse service
|
|
// call
|
|
runScript(raw_script_ad, raw_script_ad, &null_pc);
|
|
|
|
_vm->_resman->closeResource(params[4]);
|
|
|
|
// engineMega is now the ObjectMega of mega we want to
|
|
// route to
|
|
|
|
// stand exactly beside the mega, ie. at same y-coord
|
|
pars[5] = _vm->_engineMega.feet_y;
|
|
|
|
// apply scale factor to walk distance
|
|
// Ay+B gives 256 * scale ie. 256 * 256 * true_scale for even
|
|
// better accuracy, ie. scale = (Ay + B) / 256
|
|
|
|
scale = (ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b) / 256;
|
|
|
|
mega_separation= (mega_separation * scale) / 256;
|
|
|
|
debug(5, "separation %d", mega_separation);
|
|
debug(5, " target x %d, y %d", _vm->_engineMega.feet_x, _vm->_engineMega.feet_y);
|
|
|
|
if (_vm->_engineMega.feet_x < ob_mega->feet_x)
|
|
{
|
|
// Target is left of us, so aim to stand to their
|
|
// right. Face down_left
|
|
|
|
pars[4] = _vm->_engineMega.feet_x + mega_separation;
|
|
pars[6] = 5;
|
|
} else {
|
|
// Ok, must be right of us so aim to stand to their
|
|
// left. Face down_right.
|
|
|
|
pars[4] = _vm->_engineMega.feet_x - mega_separation;
|
|
pars[6] = 3;
|
|
}
|
|
}
|
|
|
|
// first cycle builds the route - thereafter merely follows it
|
|
|
|
// Call fnWalk() with target coords set to feet coords. RESULT will
|
|
// be 1 when it finishes, or 0 if it failed to build route.
|
|
return fnWalk(pars);
|
|
}
|
|
|
|
int32 Logic::fnSetWalkGrid(int32 *params) {
|
|
// params: none
|
|
|
|
error("fnSetWalkGrid no longer valid");
|
|
return IR_CONT;
|
|
}
|
|
|
|
// add this walkgrid resource to the list of those used for routing in this
|
|
// location - note this is ignored in the resource is already in the list
|
|
|
|
int32 Logic::fnAddWalkGrid(int32 *params) {
|
|
// params: 0 id of walkgrid resource
|
|
|
|
// all objects that add walkgrids must be restarted whenever we
|
|
// re-enter a location
|
|
|
|
// DON'T EVER KILL GEORGE!
|
|
if (ID != 8) {
|
|
// need to call this in case it wasn't called in script!
|
|
// ('params' just used as dummy param)
|
|
fnAddToKillList(params);
|
|
}
|
|
|
|
_router->addWalkGrid(params[0]);
|
|
|
|
// Touch the grid, getting it into memory.
|
|
_vm->_resman->openResource(params[0]);
|
|
_vm->_resman->closeResource(params[0]);
|
|
|
|
return IR_CONT;
|
|
}
|
|
|
|
// remove this walkgrid resource from the list of those used for routing in
|
|
// this location - note that this is ignored if the resource isn't actually
|
|
// in the list
|
|
|
|
int32 Logic::fnRemoveWalkGrid(int32 *params) {
|
|
// params: 0 id of walkgrid resource
|
|
|
|
_router->removeWalkGrid(params[0]);
|
|
return IR_CONT;
|
|
}
|
|
|
|
int32 Logic::fnRegisterWalkGrid(int32 *params) {
|
|
// params: none
|
|
|
|
error("fnRegisterWalkGrid no longer valid");
|
|
return IR_CONT;
|
|
}
|
|
|
|
int32 Logic::fnSetScaling(int32 *params) {
|
|
// params: 0 pointer to object's mega structure
|
|
// 1 scale constant A
|
|
// 2 scale constant B
|
|
|
|
// 256 * s = A * y + B
|
|
|
|
// where s is system scale, which itself is (256 * actual_scale) ie.
|
|
// s == 128 is half size
|
|
|
|
ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->intToPtr(params[0]);
|
|
|
|
ob_mega->scale_a = params[1];
|
|
ob_mega->scale_b = params[2];
|
|
|
|
return IR_CONT;
|
|
}
|
|
|
|
int32 Logic::fnSetStandbyCoords(int32 *params) {
|
|
// set the standby walk coords to be used by fnWalkToAnim and
|
|
// fnStandAfterAnim when the anim header's start/end coords are zero
|
|
|
|
// useful during development; can stay in final game anyway
|
|
|
|
// params: 0 x-coord
|
|
// 1 y-coord
|
|
// 2 direction (0..7)
|
|
|
|
if (params[2] < 0 || params[2] > 7)
|
|
error("Invalid direction (%d) in fnSetStandbyCoords", params[2]);
|
|
|
|
_standbyX = (int16) params[0];
|
|
_standbyY = (int16) params[1];
|
|
_standbyDir = (uint8) params[2];
|
|
|
|
return IR_CONT;
|
|
}
|
|
|
|
} // End of namespace Sword2
|