scummvm/sword2/function.cpp

460 lines
11 KiB
C++
Raw Normal View History

2003-07-28 01:44:38 +00:00
/* Copyright (C) 1994-2003 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$
*/
2003-07-28 03:12:49 +00:00
#include "stdafx.h"
2003-10-28 19:51:30 +00:00
#include "sword2/driver/driver96.h"
#include "sword2/build_display.h"
#include "sword2/credits.h"
#include "sword2/debug.h"
#include "sword2/defs.h"
#include "sword2/interpreter.h"
#include "sword2/layers.h" // for '_thisScreen' structure
2003-10-28 19:51:30 +00:00
#include "sword2/logic.h"
#include "sword2/protocol.h"
#include "sword2/resman.h"
#include "sword2/sound.h"
#include "sword2/sword2.h"
2003-07-28 01:44:38 +00:00
2003-10-04 00:52:27 +00:00
namespace Sword2 {
int32 Logic::fnTestFunction(int32 *params) {
// params: 0 address of a flag
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnTestFlags(int32 *params) {
// params: 0 value of flag
2003-09-17 13:03:13 +00:00
return IR_CONT;
}
2003-07-28 01:44:38 +00:00
int32 Logic::fnGosub(int32 *params) {
2003-09-17 13:03:13 +00:00
// hurray, script subroutines
2003-07-28 01:44:38 +00:00
// params: 0 id of script
logicUp(params[0]);
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// logic goes up - pc is saved for current level
return IR_GOSUB;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnNewScript(int32 *params) {
2003-09-17 13:03:13 +00:00
// change current script - must be followed by a TERMINATE script
// directive
2003-07-28 01:44:38 +00:00
// params: 0 id of script
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// must clear this
PLAYER_ACTION = 0;
2003-07-28 01:44:38 +00:00
logicReplace(params[0]);
2003-07-28 01:44:38 +00:00
// drop out no pc save - and around again
2003-09-17 13:03:13 +00:00
return IR_TERMINATE;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnInteract(int32 *params) {
2003-09-17 13:03:13 +00:00
// run targets action on a subroutine
// called by player on his base level 0 idle, for example
2003-07-28 01:44:38 +00:00
// params: 0 id of target from which we derive action script
// reference
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// must clear this
PLAYER_ACTION = 0;
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// 3rd script of clicked on id
2003-11-02 22:38:04 +00:00
logicUp((params[0] < 16) + 2);
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// out, up and around again - pc is saved for current level to be
// returned to
return IR_GOSUB;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnPreLoad(int32 *params) {
2003-09-17 13:03:13 +00:00
// Open & close a resource.
2003-09-17 13:03:13 +00:00
// Forces a resource into memory before it's "officially" opened for
// use. eg. if an anim needs to run on smoothly from another,
// "preloading" gets it into memory in advance to avoid the cacheing
// delay that normally occurs before the first frame.
2003-07-28 01:44:38 +00:00
// params: 0 resource to preload
res_man->openResource(params[0]);
res_man->closeResource(params[0]);
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnPreFetch(int32 *params) {
2003-09-17 13:03:13 +00:00
// Go fetch resource in the background.
2003-07-28 01:44:38 +00:00
// params: 0 resource to fetch [guess]
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnFetchWait(int32 *params) {
2003-09-17 13:03:13 +00:00
// Fetches a resource in the background but prevents the script from
// continuing until the resource is in memory.
2003-07-28 01:44:38 +00:00
// params: 0 resource to fetch [guess]
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnRelease(int32 *params) {
2003-09-17 13:03:13 +00:00
// Releases a resource from memory. Used for freeing memory for
// sprites that have just been used and will not be used again.
// Sometimes it is better to kick out a sprite straight away so that
// the memory can be used for more frequent animations.
2003-07-28 01:44:38 +00:00
// params: 0 resource to release [guess]
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnRandom(int32 *params) {
2003-09-17 13:03:13 +00:00
// Generates a random number between 'min' & 'max' inclusive, and
// sticks it in the script flag 'result'
2003-07-28 01:44:38 +00:00
// params: 0 min
// 1 max
2003-07-28 01:44:38 +00:00
RESULT = _vm->_rnd.getRandomNumberRng(params[0], params[1]);
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
2003-09-17 13:03:13 +00:00
int32 Logic::fnPause(int32 *params) {
2003-07-28 01:44:38 +00:00
// params: 0 pointer to object's logic structure
2003-09-17 13:03:13 +00:00
// 1 number of game-cycles to pause
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// NB. Pause-value of 0 causes script to continue, 1 causes a 1-cycle
// quit, 2 gives 2 cycles, etc.
2003-07-28 01:44:38 +00:00
Object_logic *ob_logic = (Object_logic *) memory->intToPtr(params[0]);
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
if (ob_logic->looping == 0) {
// start the pause
2003-07-28 01:44:38 +00:00
ob_logic->looping = 1;
2003-09-17 13:03:13 +00:00
// no. of game cycles
ob_logic->pause = params[1];
2003-07-28 01:44:38 +00:00
}
2003-09-17 13:03:13 +00:00
if (ob_logic->pause) {
// decrement the pause count
ob_logic->pause--;
// drop out of script, but call this again next cycle
return IR_REPEAT;
} else {
2003-07-28 01:44:38 +00:00
ob_logic->looping = 0;
2003-09-17 13:03:13 +00:00
// continue script
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
}
2003-09-17 13:03:13 +00:00
int32 Logic::fnRandomPause(int32 *params) {
2003-07-28 01:44:38 +00:00
// params: 0 pointer to object's logic structure
2003-09-17 13:03:13 +00:00
// 1 minimum number of game-cycles to pause
// 2 maximum number of game-cycles to pause
2003-07-28 01:44:38 +00:00
Object_logic *ob_logic = (Object_logic *) memory->intToPtr(params[0]);
2003-07-28 01:44:38 +00:00
int32 pars[2];
2003-09-17 13:03:13 +00:00
if (ob_logic->looping == 0) {
pars[0] = params[1];
pars[1] = params[2];
2003-07-28 01:44:38 +00:00
fnRandom(pars);
2003-09-17 13:03:13 +00:00
pars[1] = RESULT;
2003-07-28 01:44:38 +00:00
}
pars[0] = params[0];
return fnPause(pars);
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnPassGraph(int32 *params) {
2003-09-17 13:03:13 +00:00
// makes an engine local copy of passed graphic_structure and
// mega_structure - run script 4 of an object to request this
// used by fnTurnTo(id) etc
2003-09-17 13:03:13 +00:00
//
// remember, we cannot simply read a compact any longer but instead
// must request it from the object itself
2003-07-28 01:44:38 +00:00
// params: 0 pointer to a graphic structure (might not need this?)
2003-07-28 01:44:38 +00:00
memcpy(&_vm->_engineGraph, memory->intToPtr(params[0]), sizeof(Object_graphic));
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// makes no odds
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnPassMega(int32 *params) {
2003-09-17 13:03:13 +00:00
// makes an engine local copy of passed graphic_structure and
// mega_structure - run script 4 of an object to request this
// used by fnTurnTo(id) etc
2003-09-17 13:03:13 +00:00
//
// remember, we cannot simply read a compact any longer but instead
// must request it from the object itself
2003-07-28 01:44:38 +00:00
// params: 0 pointer to a mega structure
2003-07-28 01:44:38 +00:00
memcpy(&_vm->_engineMega, memory->intToPtr(params[0]), sizeof(Object_mega));
2003-07-28 01:44:38 +00:00
// makes no odds
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnSetValue(int32 *params) {
2003-09-17 13:03:13 +00:00
// temp. function!
2003-09-17 13:03:13 +00:00
// used for setting far-referenced megaset resource field in mega
// object, from start script
2003-07-28 01:44:38 +00:00
// params: 0 pointer to object's mega structure
2003-09-17 13:03:13 +00:00
// 1 value to set it to
2003-07-28 01:44:38 +00:00
Object_mega *ob_mega = (Object_mega *) memory->intToPtr(params[0]);
2003-07-28 01:44:38 +00:00
ob_mega->megaset_res = params[1];
2003-09-17 13:03:13 +00:00
// continue script
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
2003-09-17 13:03:13 +00:00
#ifdef _SWORD2_DEBUG
2003-07-28 01:44:38 +00:00
#define BLACK 0
#define WHITE 1
2003-09-17 13:03:13 +00:00
#define RED 2
2003-07-28 01:44:38 +00:00
#define GREEN 3
#define BLUE 4
static uint8 black[4] = { 0, 0, 0, 0 };
static uint8 white[4] = { 255, 255, 255, 0 };
static uint8 red[4] = { 255, 0, 0, 0 };
static uint8 green[4] = { 0, 255, 0, 0 };
static uint8 blue[4] = { 0, 0, 255, 0 };
#endif
2003-09-17 13:03:13 +00:00
int32 Logic::fnFlash(int32 *params) {
2003-09-17 13:03:13 +00:00
// flash colour 0 (ie. border) - useful during script development
// eg. fnFlash(BLUE) where a text line is missed; RED when some code
2003-09-17 13:03:13 +00:00
// missing, etc
2003-07-28 01:44:38 +00:00
// params: 0 colour to flash
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
#ifdef _SWORD2_DEBUG
// what colour?
switch (params[0]) {
case WHITE:
g_graphics->setPalette(0, 1, white, RDPAL_INSTANT);
break;
case RED:
g_graphics->setPalette(0, 1, red, RDPAL_INSTANT);
break;
case GREEN:
g_graphics->setPalette(0, 1, green, RDPAL_INSTANT);
break;
case BLUE:
g_graphics->setPalette(0, 1, blue, RDPAL_INSTANT);
break;
2003-07-28 01:44:38 +00:00
}
2003-09-17 13:03:13 +00:00
// There used to be a busy-wait loop here, so I don't know how long
// the delay was meant to be. Probably doesn't matter much.
2003-07-28 01:44:38 +00:00
g_graphics->updateDisplay();
2003-09-17 13:03:13 +00:00
g_system->delay_msecs(250);
g_graphics->setPalette(0, 1, black, RDPAL_INSTANT);
2003-09-17 13:03:13 +00:00
#endif
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
2003-09-17 13:03:13 +00:00
int32 Logic::fnColour(int32 *params) {
2003-09-17 13:03:13 +00:00
// set border colour - useful during script development
// eg. set to colour during a timer situation, then black when timed
// out
2003-07-28 01:44:38 +00:00
// params 0: colour (see defines above)
#ifdef _SWORD2_DEBUG
2003-09-17 13:03:13 +00:00
// what colour?
switch (params[0]) {
case BLACK:
g_graphics->setPalette(0, 1, black, RDPAL_INSTANT);
break;
case WHITE:
g_graphics->setPalette(0, 1, white, RDPAL_INSTANT);
break;
case RED:
g_graphics->setPalette(0, 1, red, RDPAL_INSTANT);
break;
case GREEN:
g_graphics->setPalette(0, 1, green, RDPAL_INSTANT);
break;
case BLUE:
g_graphics->setPalette(0, 1, blue, RDPAL_INSTANT);
break;
2003-07-28 01:44:38 +00:00
}
2003-09-17 13:03:13 +00:00
#endif
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnDisplayMsg(int32 *params) {
2003-09-17 13:03:13 +00:00
// Display a message to the user on the screen.
// params: 0 Text number of message to be displayed.
2003-09-17 13:03:13 +00:00
uint32 local_text = params[0] & 0xffff;
uint32 text_res = params[0] / SIZE;
2003-07-28 01:44:38 +00:00
// Display message for three seconds.
2003-09-17 13:03:13 +00:00
// +2 to skip the encoded text number in the first 2 chars; 3 is
// duration in seconds
_vm->displayMsg(_vm->fetchTextLine(res_man->openResource(text_res), local_text) + 2, 3);
res_man->closeResource(text_res);
_vm->removeMsg();
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
int32 Logic::fnResetGlobals(int32 *params) {
// fnResetGlobals is used by the demo - so it can loop back & restart
// itself
// params: none
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
int32 size;
uint32 *globals;
size = res_man->fetchLen(1);
2003-09-17 13:03:13 +00:00
size -= sizeof(_standardHeader);
2003-07-28 01:44:38 +00:00
debug(5, "globals size: %d", size);
2003-07-28 01:44:38 +00:00
globals = (uint32 *) ((uint8 *) res_man->openResource(1) + sizeof(_standardHeader));
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// blank each global variable
memset(globals, 0, size);
2003-07-28 01:44:38 +00:00
res_man->closeResource(1);
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// all objects but george
res_man->killAllObjects(false);
2003-07-28 01:44:38 +00:00
// FOR THE DEMO - FORCE THE SCROLLING TO BE RESET!
// - this is taken from fnInitBackground
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
// switch on scrolling (2 means first time on screen)
_vm->_thisScreen.scroll_flag = 2;
2003-07-28 01:44:38 +00:00
2003-09-17 13:03:13 +00:00
return IR_CONT;
}
2003-07-28 01:44:38 +00:00
int32 Logic::fnPlayCredits(int32 *params) {
2003-09-17 13:03:13 +00:00
// This function just quits the game if this is the playable demo, ie.
// credits are NOT played in the demo any more!
2003-07-28 01:44:38 +00:00
// params: none
2003-09-17 13:03:13 +00:00
if (!DEMO) {
uint8 oldPal[1024];
uint8 tmpPal[1024];
int32 music_length;
int32 pars[2];
g_sound->saveMusicState();
g_sound->muteFx(true);
g_sound->muteSpeech(true);
g_sound->stopMusic();
memcpy(oldPal, g_graphics->_palCopy, 1024);
memset(tmpPal, 0, 1024);
g_graphics->waitForFade();
g_graphics->fadeDown();
g_graphics->waitForFade();
tmpPal[4] = 255;
tmpPal[5] = 255;
tmpPal[6] = 255;
g_graphics->setPalette(0, 256, tmpPal, RDPAL_INSTANT);
// Play the credits music. Is it enough with just one
// repetition of it?
pars[0] = 309;
pars[1] = FX_SPOT;
fnPlayMusic(pars);
music_length = 1000 * g_sound->musicTimeRemaining();
debug(0, "Credits music length: ~%d ms", music_length);
g_graphics->closeMenuImmediately();
while (g_sound->musicTimeRemaining()) {
g_graphics->clearScene();
g_graphics->setNeedFullRedraw();
// FIXME: Draw the credits text. The actual text
// messages are stored in credits.clu, and I'm guessing
// that credits.bmp or font.clu may be the font.
g_graphics->updateDisplay();
_keyboardEvent ke;
if (g_input->readKey(&ke) == RD_OK && ke.keycode == 27)
break;
g_system->delay_msecs(30);
2003-09-17 13:03:13 +00:00
}
2003-07-28 01:44:38 +00:00
fnStopMusic(NULL);
g_sound->restoreMusicState();
g_graphics->setPalette(0, 256, oldPal, RDPAL_FADE);
g_graphics->fadeUp();
g_graphics->updateDisplay();
_vm->buildDisplay();
g_graphics->waitForFade();
2003-07-28 01:44:38 +00:00
g_sound->muteFx(false);
g_sound->muteSpeech(false);
2003-09-17 13:03:13 +00:00
}
if (_vm->_features & GF_DEMO) {
_vm->closeGame();
2003-07-28 01:44:38 +00:00
}
2003-09-17 13:03:13 +00:00
return IR_CONT;
2003-07-28 01:44:38 +00:00
}
2003-10-04 00:52:27 +00:00
} // End of namespace Sword2