Permalink
Cannot retrieve contributors at this time
Fetching contributors…

/* | |
** ACROOM - AGS main header file | |
** Copyright (C) 1995-2003, Chris Jones | |
** All Rights Reserved. | |
** | |
** This is UNPUBLISHED PROPRIETARY SOURCE CODE; | |
** the contents of this file may not be disclosed to third parties, | |
** copied or duplicated in any form, in whole or in part, without | |
** prior express permission from Chris Jones. | |
** | |
** INTERNAL WORKING COPY: This file should NEVER leave my computer - if | |
** you have this file then you are in breach of the license agreement | |
** and must delete it at once. | |
*/ | |
#ifndef __CROOM_H | |
#define __CROOM_H | |
#ifndef CROOM_NOFUNCTIONS | |
extern FILE *clibfopen(char *, char *); | |
#include "compress.h" | |
#endif | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include "cscomp.h" | |
// MACPORT FIX: endian support | |
#include "bigend.h" | |
// 64 bit: Hackish way to read value in a struct | |
short int __getshort__bigendian(FILE* file); | |
#define EXIT_NORMAL 91 | |
#define EXIT_CRASH 92 | |
#define ROOM_FILE_VERSION 29 | |
/* room file versions history | |
8: final v1.14 release | |
9: intermediate v2 alpha releases | |
10: v2 alpha-7 release | |
11: final v2.00 release | |
12: v2.08, to add colour depth byte | |
13: v2.14, add walkarea light levels | |
14: v2.4, fixed so it saves walkable area 15 | |
15: v2.41, supports NewInteraction | |
16: v2.5 | |
17: v2.5 - just version change to force room re-compile for new charctr struct | |
18: v2.51 - vector scaling | |
19: v2.53 - interaction variables | |
20: v2.55 - shared palette backgrounds | |
21: v2.55 - regions | |
22: v2.61 - encrypt room messages | |
23: v2.62 - object flags | |
24: v2.7 - hotspot script names | |
25: v2.72 - game id embedded | |
26: v3.0 - new interaction format, and no script source | |
27: v3.0 - store Y of bottom of object, not top | |
28: v3.0.3 - remove hotspot name length limit | |
29: v3.0.3 - high-res coords for object x/y, edges and hotspot walk-to point | |
*/ | |
#define MAX_INIT_SPR 40 | |
#define MAX_OBJ 16 // max walk-behinds | |
#define NUM_MISC 20 | |
#define MAXMESS 100 | |
#define NUMOTCON 7 // number of conditions before standing on | |
#define NUM_CONDIT (120 + NUMOTCON) | |
#define MAX_HOTSPOTS 50 // v2.62 increased from 20 to 30; v2.8 to 50 | |
#define MAX_REGIONS 16 | |
#define MAX_SCRIPT_NAME_LEN 20 | |
//const int MISC_COND = MAX_OBJ * 4 + NUMOTCON + MAX_INIT_SPR * 4; | |
// NUMCONDIT : whataction[0]: Char walks off left | |
// [1]: Char walks off right | |
// [2]: Char walks off bottom | |
// [3]: Char walks off top | |
// [4]: First enters screen | |
// [5]: Every time enters screen | |
// [6]: execute every loop | |
// [5]...[19]: Char stands on lookat type | |
// [20]...[35]: Look at type | |
// [36]...[49]: Action on type | |
// [50]...[65]: Use inv on type | |
// [66]...[75]: Look at object | |
// [76]...[85]: Action on object | |
// [86]...[95]: Speak to object | |
// [96]...[105]: Use inv on object | |
// [106]...[124]: Misc conditions 1-20 | |
// game ver whataction[]= | |
// v1.00 0 : Go to screen | |
// 1 : Don't do anything | |
// 2 : Can't walk | |
// 3 : Man dies | |
// 4 : Run animation | |
// 5 : Display message | |
// 6 : Remove an object (set object.on=0) | |
// 7 : Remove object & add Val2 to inventory | |
// 8 : Add Val1 to inventory (Val2=num times) | |
// 9 : Run a script | |
// v1.00 SR-1 10 : Run graphical script | |
// v1.1 11 : Play sound effect SOUND%d.WAV | |
// v1.12 12 : Play FLI/FLC animation FLIC%d.FLC or FLIC%d.FLI | |
// 13 : Turn object on | |
// v2.00 14 : Run conversation | |
#define NUMRESPONSE 14 | |
#define NUMCOMMANDS 15 | |
#define GO_TO_SCREEN 0 | |
#define NO_ACTION 1 | |
#define NO_WALK 2 | |
#define MAN_DIES 3 | |
#define RUN_ANIMATE 4 | |
#define SHOW_MESSAGE 5 | |
#define OBJECT_OFF 6 | |
#define OBJECT_INV 7 | |
#define ADD_INV 8 | |
#define RUNSCRIPT 9 | |
#define GRAPHSCRIPT 10 | |
#define PLAY_SOUND 11 | |
#define PLAY_FLI 12 | |
#define OBJECT_ON 13 | |
#define RUN_DIALOG 14 | |
#ifdef DJGPP | |
#include <unistd.h> | |
#endif | |
#ifdef _MSC_VER | |
#undef VTA_LEFT | |
#undef VTA_RIGHT | |
#endif | |
// thisroom.options[0] = startup music | |
// thisroom.options[1] = can save/load on screen (0=yes, 1=no) | |
// thisroom.options[2] = player character disabled? (0=no, 1=yes) | |
// thisroom.options[3] = player special view (0=normal) | |
// [4] = music volume (0=normal, <0 quiter, >0 louder) | |
const int ST_TUNE = 0, ST_SAVELOAD = 1, ST_MANDISABLED = 2, ST_MANVIEW = 3, ST_VOLUME = 4; | |
#ifndef CROOM_NOFUNCTIONS | |
char *croom_h_copyright = "ChrisRoom v2.00 - CRM reader/writer copyright (c) 1995, 1998, 1999 by Chris Jones."; | |
char *game_file_sig = "Adventure Creator Game File v2"; | |
#define GAME_FILE_VERSION 42 | |
block backups[5]; | |
int cunpackbitl(unsigned char *, int size, FILE *infile); | |
/*long cloadcompfile(FILE*outpt,block tobesaved,color*pal,long poot=0) { | |
fseek(outpt,poot,SEEK_SET); | |
int widt,hit,hh; | |
for (hh=0;hh<4;hh++) *tobesaved++=fgetc(outpt); | |
tobesaved-=4; | |
widt=*tobesaved++; widt+=(*tobesaved++)*256; | |
hit=*tobesaved++; hit+=(*tobesaved++)*256; | |
unsigned char* ress=(unsigned char*)malloc(widt+1); | |
for (int ww=0;ww<hit;ww++) { | |
cunpackbitl(ress,widt,outpt); | |
for (int ss=0;ss<widt;ss++) (*tobesaved++)=ress[ss]; | |
} | |
for (ww=0;ww<256;ww++) { | |
pal[ww].r=fgetc(outpt); | |
pal[ww].g=fgetc(outpt); | |
pal[ww].b=fgetc(outpt); | |
} | |
poot=ftell(outpt); free(ress); tobesaved-=(widt*hit+4); | |
return poot; | |
}*/ | |
#endif | |
void quit(char *); | |
#ifdef DJGPP | |
#define PCKD __attribute__((packed)) | |
#else | |
#define PCKD | |
#endif | |
#pragma pack(1) | |
struct sprstruc { | |
short sprnum PCKD; // number from array | |
short x,y PCKD; // x,y co-ords | |
short room PCKD; // room number | |
short on PCKD; | |
sprstruc() { on = 0; } | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
sprnum = __getshort__bigendian(fp); | |
x = __getshort__bigendian(fp); | |
y = __getshort__bigendian(fp); | |
room = __getshort__bigendian(fp); | |
on = __getshort__bigendian(fp); | |
} | |
#endif | |
}; | |
#define MSG_DISPLAYNEXT 1 // supercedes using alt-200 at end of message | |
#define MSG_TIMELIMIT 2 | |
struct MessageInfo { | |
char displayas PCKD; // 0 = normal window, 1 = as speech | |
char flags PCKD; // combination of MSG_xxx flags | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
displayas = getc(fp); | |
flags = getc(fp); | |
} | |
#endif | |
}; | |
#pragma pack() | |
#define AE_WAITFLAG 0x80000000 | |
#define MAXANIMSTAGES 10 | |
struct AnimationStruct { | |
int x, y; | |
int data; | |
int object; | |
int speed; | |
char action; | |
char wait; | |
AnimationStruct() { action = 0; object = 0; wait = 1; speed = 5; } | |
}; | |
struct FullAnimation { | |
AnimationStruct stage[MAXANIMSTAGES]; | |
int numstages; | |
FullAnimation() { numstages = 0; } | |
}; | |
struct _Point { | |
short x, y; | |
}; | |
#define MAXCOMMANDS 8 | |
struct EventBlock { | |
int list[MAXCOMMANDS]; | |
int respond[MAXCOMMANDS]; | |
int respondval[MAXCOMMANDS]; | |
int data[MAXCOMMANDS]; | |
int numcmd; | |
short score[MAXCOMMANDS]; | |
}; | |
// careful with this - the shadinginfo[] array needs to be | |
// MAX_WALK_AREAS + 1 if this gets changed | |
#define MAX_WALK_AREAS 15 | |
#define MAXPOINTS 30 | |
struct PolyPoints { | |
int x[MAXPOINTS]; | |
int y[MAXPOINTS]; | |
int numpoints; | |
void add_point(int xxx,int yyy) { | |
x[numpoints] = xxx; | |
y[numpoints] = yyy; | |
numpoints++; | |
if (numpoints >= MAXPOINTS) | |
quit("too many poly points added"); | |
} | |
PolyPoints() { numpoints = 0; } | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
fread(x, sizeof(int), MAXPOINTS, fp); | |
fread(y, sizeof(int), MAXPOINTS, fp); | |
numpoints = getw(fp); | |
} | |
#endif | |
}; | |
#define POPUP_NONE 0 | |
#define POPUP_MOUSEY 1 | |
#define POPUP_SCRIPT 2 | |
#define POPUP_NOAUTOREM 3 // don't remove automatically during cutscene | |
#define POPUP_NONEINITIALLYOFF 4 // normal GUI, initially off | |
#define VTA_LEFT 0 | |
#define VTA_RIGHT 1 | |
#define VTA_CENTRE 2 | |
#define IFLG_TEXTWINDOW 1 | |
#define MAXBUTTON 20 | |
#define IBACT_SETMODE 1 | |
#define IBACT_SCRIPT 2 | |
#define IBFLG_ENABLED 1 | |
#define IBFLG_INVBOX 2 | |
struct InterfaceButton { | |
int x, y, pic, overpic, pushpic, leftclick; | |
int rightclick; // if inv, then leftclick = wid, rightclick = hit | |
int reserved_for_future; | |
char flags; | |
void set(int xx, int yy, int picc, int overpicc, int actionn) { | |
x = xx; y = yy; pic = picc; overpic = overpicc; leftclick = actionn; pushpic = 0; | |
rightclick = 0; flags = IBFLG_ENABLED; | |
reserved_for_future = 0; | |
} | |
}; | |
// this struct should go in a Game struct, not the room structure. | |
struct InterfaceElement { | |
int x, y, x2, y2; | |
int bgcol, fgcol, bordercol; | |
int vtextxp, vtextyp, vtextalign; // X & Y relative to topleft of interface | |
char vtext[40]; | |
int numbuttons; | |
InterfaceButton button[MAXBUTTON]; | |
int flags; | |
int reserved_for_future; | |
int popupyp; // pops up when mousey < this | |
char popup; // does it pop up? (like sierra icon bar) | |
char on; | |
InterfaceElement() { | |
vtextxp = 0; vtextyp = 1; strcpy(vtext,"@SCORETEXT@$r@GAMENAME@"); | |
numbuttons = 0; bgcol = 8; fgcol = 15; bordercol = 0; on = 1; flags = 0; | |
} | |
}; | |
/*struct InterfaceStyle { | |
int playareax1,playareay1,playareax2,playareay2; // where the game takes place | |
int vtextxp,vtextyp; | |
char vtext[40]; | |
int numbuttons,popupbuttons; | |
InterfaceButton button[MAXBUTTON]; | |
int invx1,invy1,invx2,invy2; // set invx1=-1 for Sierra-style inventory | |
InterfaceStyle() { // sierra interface | |
playareax1=0; playareay1=13; playareax2=319; playareay2=199; | |
vtextxp=160; vtextyp=2; strcpy(vtext,"@SCORETEXT@$r@GAMENAME@"); | |
invx1=-1; numbuttons=2; popupbuttons=1; | |
button[0].set(0,13,3,-1,0); | |
} | |
};*/ | |
#define MAX_PARSER_WORD_LENGTH 30 | |
#define ANYWORD 29999 | |
#define RESTOFLINE 30000 | |
struct WordsDictionary { | |
int num_words; | |
char**word; | |
short*wordnum; | |
void allocate_memory(int wordCount) | |
{ | |
num_words = wordCount; | |
if (num_words > 0) | |
{ | |
word = (char**)malloc(wordCount * sizeof(char*)); | |
word[0] = (char*)malloc(wordCount * MAX_PARSER_WORD_LENGTH); | |
wordnum = (short*)malloc(wordCount * sizeof(short)); | |
for (int i = 1; i < wordCount; i++) | |
{ | |
word[i] = word[0] + MAX_PARSER_WORD_LENGTH * i; | |
} | |
} | |
} | |
void free_memory() | |
{ | |
if (num_words > 0) | |
{ | |
free(word[0]); | |
free(word); | |
free(wordnum); | |
word = NULL; | |
wordnum = NULL; | |
num_words = 0; | |
} | |
} | |
void sort(); | |
int find_index (const char *); | |
}; | |
#define MAX_CUSTOM_PROPERTIES 30 | |
#define MAX_CUSTOM_PROPERTY_VALUE_LENGTH 500 | |
#define PROP_TYPE_BOOL 1 | |
#define PROP_TYPE_INT 2 | |
#define PROP_TYPE_STRING 3 | |
struct CustomPropertySchema { | |
char propName[MAX_CUSTOM_PROPERTIES][20]; | |
char propDesc[MAX_CUSTOM_PROPERTIES][100]; | |
char *defaultValue[MAX_CUSTOM_PROPERTIES]; | |
int propType[MAX_CUSTOM_PROPERTIES]; | |
int numProps; | |
// Find the index of the specified property | |
int findProperty (const char *pname) { | |
for (int ii = 0; ii < numProps; ii++) { | |
if (stricmp (pname, propName[ii]) == 0) | |
return ii; | |
} | |
return -1; | |
} | |
void deleteProperty (int idx) { | |
if ((idx < 0) || (idx >= numProps)) | |
return; | |
if (defaultValue[idx]) | |
delete defaultValue[idx]; | |
numProps--; | |
for (int qq = idx; qq < numProps; qq++) { | |
strcpy (propName[qq], propName[qq+1]); | |
strcpy (propDesc[qq], propDesc[qq+1]); | |
propType[qq] = propType[qq+1]; | |
defaultValue[qq] = defaultValue[qq+1]; | |
} | |
defaultValue[numProps] = NULL; | |
} | |
void resetProperty (int idx) { | |
propName[idx][0] = 0; | |
propDesc[idx][0] = 0; | |
if (defaultValue[idx]) | |
delete defaultValue[idx]; | |
propType[idx] = PROP_TYPE_BOOL; | |
defaultValue[idx] = new char[MAX_CUSTOM_PROPERTY_VALUE_LENGTH]; | |
defaultValue[idx][0] = 0; | |
} | |
CustomPropertySchema () { | |
numProps = 0; | |
for (int kk = 0; kk < MAX_CUSTOM_PROPERTIES; kk++) { | |
defaultValue[kk] = NULL; | |
} | |
} | |
void Serialize (FILE *outto); | |
int UnSerialize (FILE *infrom); | |
}; | |
struct CustomProperties { | |
char *propName[MAX_CUSTOM_PROPERTIES]; | |
char *propVal[MAX_CUSTOM_PROPERTIES]; | |
int numProps; | |
CustomProperties() { | |
numProps = 0; | |
} | |
const char *getPropertyValue (const char *pname) { | |
int idxx = findProperty(pname); | |
if (idxx < 0) | |
return NULL; | |
return propVal[idxx]; | |
} | |
// Find the index of the specified property | |
int findProperty (const char *pname) { | |
for (int ii = 0; ii < numProps; ii++) { | |
if (stricmp (pname, propName[ii]) == 0) | |
return ii; | |
} | |
return -1; | |
} | |
void reset () { | |
for (int ii = 0; ii < numProps; ii++) { | |
free (propName[ii]); | |
free (propVal[ii]); | |
} | |
numProps = 0; | |
} | |
void addProperty (const char *newname, const char *newval) { | |
if (numProps >= MAX_CUSTOM_PROPERTIES) { | |
return; | |
} | |
propName[numProps] = (char*)malloc(200); | |
propVal[numProps] = (char*)malloc(MAX_CUSTOM_PROPERTY_VALUE_LENGTH); | |
strcpy (propName[numProps], newname); | |
strcpy (propVal[numProps], newval); | |
numProps++; | |
} | |
void Serialize (FILE *outto); | |
int UnSerialize (FILE *infrom); | |
}; | |
#ifndef CROOM_NOFUNCTIONS | |
// ** SCHEMA LOAD/SAVE FUNCTIONS | |
void CustomPropertySchema::Serialize (FILE *outto) { | |
putw (1, outto); // version 1 at present | |
putw (numProps, outto); | |
for (int jj = 0; jj < numProps; jj++) { | |
fputstring (propName[jj], outto); | |
fputstring (propDesc[jj], outto); | |
fputstring (defaultValue[jj], outto); | |
putw (propType[jj], outto); | |
} | |
} | |
int CustomPropertySchema::UnSerialize (FILE *infrom) { | |
if (getw(infrom) != 1) | |
return -1; | |
numProps = getw(infrom); | |
for (int kk = 0; kk < numProps; kk++) { | |
this->resetProperty (kk); | |
fgetstring_limit (propName[kk], infrom, 20); | |
fgetstring_limit (propDesc[kk], infrom, 100); | |
fgetstring_limit (defaultValue[kk], infrom, MAX_CUSTOM_PROPERTY_VALUE_LENGTH); | |
propType[kk] = getw(infrom); | |
} | |
return 0; | |
} | |
// ** OBJECT PROPERTIES LOAD/SAVE FUNCTIONS | |
void CustomProperties::Serialize (FILE *outto) { | |
putw (1, outto); | |
putw (numProps, outto); | |
for (int ee = 0; ee < numProps; ee++) { | |
fputstring (propName[ee], outto); | |
fputstring (propVal[ee], outto); | |
} | |
} | |
int CustomProperties::UnSerialize (FILE *infrom) { | |
if (getw(infrom) != 1) | |
return -1; | |
numProps = getw(infrom); | |
for (int ee = 0; ee < numProps; ee++) { | |
propName[ee] = (char*)malloc(200); | |
propVal[ee] = (char*)malloc(MAX_CUSTOM_PROPERTY_VALUE_LENGTH); | |
fgetstring_limit (propName[ee], infrom, 200); | |
fgetstring_limit (propVal[ee], infrom, MAX_CUSTOM_PROPERTY_VALUE_LENGTH); | |
} | |
return 0; | |
} | |
#endif // NOFUNCTIONS | |
/* THE WAY THIS WORKS: | |
* | |
* NewInteraction (Hotspot 1) | |
* | | |
* +-- eventTypes [NUM_EVENTS] | |
* +-- NewInteractionCommandList [NUM_EVENTS] (Look at hotspot) | |
* | | |
* +-- NewInteractionCommand [NUM_COMMANDS] (Display message) | |
* | | |
* +-- NewInteractionValue [NUM_ARGUMENTS] (5) | |
*/ | |
#define LOCAL_VARIABLE_OFFSET 10000 | |
#define MAX_GLOBAL_VARIABLES 100 | |
#define MAX_ACTION_ARGS 5 | |
#define MAX_NEWINTERACTION_EVENTS 30 | |
#define MAX_COMMANDS_PER_LIST 40 | |
#define int32 int | |
#define VALTYPE_LITERALINT 1 | |
#define VALTYPE_VARIABLE 2 | |
#define VALTYPE_BOOLEAN 3 | |
#define VALTYPE_CHARNUM 4 | |
struct NewInteractionValue { | |
unsigned char valType; | |
int val; | |
int extra; | |
NewInteractionValue() { | |
valType = VALTYPE_LITERALINT; | |
val = 0; | |
extra = 0; | |
} | |
void ReadFromFile(FILE *fp) | |
{ | |
fread(&valType, sizeof(char), 1, fp); | |
char pad[3]; fread(pad, sizeof(char), 3, fp); | |
val = getw(fp); | |
extra = getw(fp); | |
} | |
void WriteToFile(FILE *fp) | |
{ | |
fwrite(&valType, sizeof(char), 1, fp); | |
char pad[3]; fwrite(pad, sizeof(char), 3, fp); | |
putw(val, fp); | |
putw(extra, fp); | |
} | |
}; | |
struct NewInteractionAction { | |
virtual void reset() = 0; | |
}; | |
struct NewInteractionCommandList; | |
struct NewInteractionCommand: public NewInteractionAction { | |
int32 type; | |
NewInteractionValue data[MAX_ACTION_ARGS]; | |
NewInteractionAction * children; | |
NewInteractionCommandList *parent; | |
NewInteractionCommand() { | |
type = 0; | |
children = NULL; | |
parent = NULL; | |
} | |
NewInteractionCommandList *get_child_list() { | |
return (NewInteractionCommandList*)children; | |
} | |
void remove(); | |
void reset() { remove(); } | |
void ReadFromFile(FILE *fp) | |
{ | |
getw(fp); // skip the vtbl ptr | |
type = getw(fp); | |
for (int i = 0; i < MAX_ACTION_ARGS; ++i) | |
{ | |
data[i].ReadFromFile(fp); | |
} | |
// all that matters is whether or not these are null... | |
children = (NewInteractionAction *)(long)getw(fp); | |
parent = (NewInteractionCommandList *)(long)getw(fp); | |
} | |
void WriteToFile(FILE *fp) | |
{ | |
putw(0, fp); // write dummy vtbl ptr | |
putw(type, fp); | |
for (int i = 0; i < MAX_ACTION_ARGS; ++i) | |
{ | |
data[i].WriteToFile(fp); | |
} | |
putw((long)children, fp); | |
putw((long)parent, fp); | |
} | |
}; | |
struct NewInteractionCommandList : public NewInteractionAction { | |
int32 numCommands; | |
NewInteractionCommand command[MAX_COMMANDS_PER_LIST]; | |
int32 timesRun; // used by engine to track score changes | |
NewInteractionCommandList () { | |
numCommands = 0; | |
timesRun = 0; | |
} | |
void reset(); | |
}; | |
struct NewInteraction { | |
int numEvents; | |
// the first few event types depend on the item - ID's of 100+ are | |
// custom events (used for subroutines) | |
int eventTypes[MAX_NEWINTERACTION_EVENTS]; | |
int timesRun[MAX_NEWINTERACTION_EVENTS]; | |
NewInteractionCommandList *response[MAX_NEWINTERACTION_EVENTS]; | |
NewInteraction() { | |
numEvents = 0; | |
// NULL all the pointers | |
memset (response, 0, sizeof(NewInteractionCommandList*) * MAX_NEWINTERACTION_EVENTS); | |
memset (×Run[0], 0, sizeof(int) * MAX_NEWINTERACTION_EVENTS); | |
} | |
void copy_timesrun_from (NewInteraction *nifrom) { | |
memcpy (×Run[0], &nifrom->timesRun[0], sizeof(int) * MAX_NEWINTERACTION_EVENTS); | |
} | |
void reset() { | |
for (int i = 0; i < numEvents; i++) { | |
if (response[i] != NULL) { | |
response[i]->reset(); | |
delete response[i]; | |
response[i] = NULL; | |
} | |
} | |
numEvents = 0; | |
} | |
~NewInteraction() { | |
reset(); | |
} | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
// it's all ints! | |
fread(&numEvents, sizeof(int), sizeof(NewInteraction)/sizeof(int), fp); | |
} | |
void WriteToFile(FILE *fp) | |
{ | |
fwrite(&numEvents, sizeof(int), sizeof(NewInteraction)/sizeof(int), fp); | |
} | |
#endif | |
}; | |
#define NUM_ACTION_TYPES 48 | |
#define ARG_TYPE_INT 1 | |
#define ARG_TYPE_INV 2 | |
#define ARG_TYPE_MSG 3 | |
#define ARG_TYPE_CHAR 4 | |
#define ARG_TYPE_BOOL 5 | |
#define ARG_TYPE_VARONLY 6 // must be variable, no literal values | |
#define AFLG_COND 1 | |
#define AFLG_RUNSCRIPT 2 | |
#define AFLG_INVCHECK 4 | |
#define AFLG_MESSAGE 8 | |
struct ActionTypes { | |
char name[80]; | |
short flags; | |
char numArgs; | |
char argTypes[MAX_ACTION_ARGS]; | |
char argNames[MAX_ACTION_ARGS][25]; | |
char description[200]; | |
char textscript[80]; | |
}; | |
extern ActionTypes actions[NUM_ACTION_TYPES]; | |
struct InteractionVariable { | |
char name[23]; | |
char type; | |
int value; | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
fread(name, sizeof(char), 23, fp); | |
type = getc(fp); | |
value = getw(fp); | |
} | |
#endif | |
}; | |
extern InteractionVariable globalvars[]; | |
extern int numGlobalVars; | |
struct InteractionScripts { | |
int numEvents; | |
char *scriptFuncNames[MAX_NEWINTERACTION_EVENTS]; | |
InteractionScripts() { | |
numEvents = 0; | |
} | |
~InteractionScripts() { | |
for (int i = 0; i < numEvents; i++) | |
delete[] scriptFuncNames[i]; | |
} | |
}; | |
#define AUCL_BUNDLE_EXE 1 | |
#define AUCL_BUNDLE_VOX 2 | |
enum AudioFileType { | |
eAudioFileOGG = 1, | |
eAudioFileMP3 = 2, | |
eAudioFileWAV = 3, | |
eAudioFileVOC = 4, | |
eAudioFileMIDI = 5, | |
eAudioFileMOD = 6 | |
}; | |
struct ScriptAudioClip { | |
int id; // not used by editor, set in engine only | |
char scriptName[30]; | |
char fileName[15]; | |
char bundlingType; | |
char type; | |
char fileType; | |
char defaultRepeat; | |
short defaultPriority; | |
short defaultVolume; | |
int reserved; | |
}; | |
#define AUDIO_CLIP_TYPE_SOUND 1 | |
struct AudioClipType { | |
int id; | |
int reservedChannels; | |
int volume_reduction_while_speech_playing; | |
int crossfadeSpeed; | |
int reservedForFuture; | |
}; | |
#define MAX_ROOMS 300 | |
// object flags (currently only a char) | |
#define OBJF_NOINTERACT 1 // not clickable | |
#define OBJF_NOWALKBEHINDS 2 // ignore walk-behinds | |
#define OBJF_HASTINT 4 // the tint_* members are valid | |
#define OBJF_USEREGIONTINTS 8 // obey region tints/light areas | |
#define OBJF_USEROOMSCALING 0x10 // obey room scaling areas | |
#define OBJF_SOLID 0x20 // blocks characters from moving | |
#define OBJF_DELETED 0x40 // object has been deleted | |
#define MAXANIMS 10 | |
#define MAX_FLAGS 15 | |
#define MAXOBJNAMELEN 30 | |
#define MAX_BSCENE 5 // max number of frames in animating bg scene | |
#define NOT_VECTOR_SCALED -10000 | |
#define TINT_IS_ENABLED 0x80000000 | |
struct roomstruct { | |
block walls, object, lookat; // 'object' is the walk-behind | |
block regions; | |
color pal[256]; | |
short numobj; // num hotspots, not sprites | |
short objyval[MAX_OBJ]; // baselines of walkbehind areas | |
// obsolete v2.00 action editor stuff below | |
short whataction[NUM_CONDIT+3]; // what to do if condition appears | |
short val1[NUM_CONDIT+3]; // variable, eg. screen number to go to | |
short val2[NUM_CONDIT+3]; // 2nd var, optional, eg. which side of screen to come on | |
short otcond[NUM_CONDIT+3]; // do extra misc condition | |
char points[NUM_CONDIT+3]; // extra points for doing it | |
// end obsolete v2.00 action editor | |
short left,right,top,bottom; // to walk off screen | |
short numsprs,nummes; // number of initial sprites and messages | |
sprstruc sprs[MAX_INIT_SPR]; // structures for each sprite | |
NewInteraction *intrObject[MAX_INIT_SPR]; | |
InteractionScripts **objectScripts; | |
int objbaseline[MAX_INIT_SPR]; // or -1 (use bottom of object graphic) | |
short objectFlags[MAX_INIT_SPR]; | |
char objectnames[MAX_INIT_SPR][MAXOBJNAMELEN]; | |
char objectscriptnames[MAX_INIT_SPR][MAX_SCRIPT_NAME_LEN]; | |
CustomProperties objProps[MAX_INIT_SPR]; | |
char password[11]; | |
char options[10]; // [0]=startup music | |
char *message[MAXMESS]; | |
MessageInfo msgi[MAXMESS]; | |
short wasversion; // when loaded from file | |
short flagstates[MAX_FLAGS]; | |
FullAnimation anims[MAXANIMS]; | |
short numanims; | |
short shadinginfo[16]; // walkable area-specific view number | |
// new version 2 roommake stuff below | |
int numwalkareas; | |
PolyPoints wallpoints[MAX_WALK_AREAS]; | |
int numhotspots; | |
_Point hswalkto[MAX_HOTSPOTS]; | |
char* hotspotnames[MAX_HOTSPOTS]; | |
char hotspotScriptNames[MAX_HOTSPOTS][MAX_SCRIPT_NAME_LEN]; | |
NewInteraction *intrHotspot[MAX_HOTSPOTS]; | |
NewInteraction *intrRoom; | |
NewInteraction *intrRegion[MAX_REGIONS]; | |
InteractionScripts **hotspotScripts; | |
InteractionScripts **regionScripts; | |
InteractionScripts *roomScripts; | |
int numRegions; | |
short regionLightLevel[MAX_REGIONS]; | |
int regionTintLevel[MAX_REGIONS]; | |
short width,height; // in 320x200 terms (scrolling room size) | |
short resolution; // 1 = 320x200, 2 = 640x400 | |
short walk_area_zoom[MAX_WALK_AREAS + 1]; // 0 = 100%, 1 = 101%, -1 = 99% | |
short walk_area_zoom2[MAX_WALK_AREAS + 1]; // for vector scaled areas | |
short walk_area_light[MAX_WALK_AREAS + 1]; // 0 = normal, + lighter, - darker | |
short walk_area_top[MAX_WALK_AREAS + 1]; // top YP of area | |
short walk_area_bottom[MAX_WALK_AREAS + 1]; // bottom YP of area | |
char *scripts; | |
ccScript *compiled_script; | |
int cscriptsize; | |
int num_bscenes, bscene_anim_speed; | |
int bytes_per_pixel; | |
block ebscene[MAX_BSCENE]; | |
color bpalettes[MAX_BSCENE][256]; | |
InteractionVariable *localvars; | |
int numLocalVars; | |
char ebpalShared[MAX_BSCENE]; // used internally by engine atm | |
CustomProperties roomProps; | |
CustomProperties hsProps[MAX_HOTSPOTS]; | |
int gameId; | |
int lastLoadNumHotspots; | |
int lastLoadNumObjects; | |
int lastLoadNumRegions; | |
roomstruct() { | |
ebscene[0] = NULL; walls = NULL; object = NULL; lookat = NULL; nummes = 0; | |
left = 0; right = 317; top = 40; bottom = 199; numobj = MAX_OBJ; numsprs = 0; password[0] = 0; | |
wasversion = ROOM_FILE_VERSION; numanims = 0; regions = NULL; numwalkareas = 0; | |
numhotspots = 0; | |
memset(&objbaseline[0], 0xff, sizeof(int) * MAX_INIT_SPR); | |
memset(&objectFlags[0], 0, sizeof(short) * MAX_INIT_SPR); | |
width = 320; height = 200; scripts = NULL; compiled_script = NULL; | |
cscriptsize = 0; | |
memset(&walk_area_zoom[0], 0, sizeof(short) * (MAX_WALK_AREAS + 1)); | |
memset(&walk_area_light[0], 0, sizeof(short) * (MAX_WALK_AREAS + 1)); | |
resolution = 1; num_bscenes = 1; ebscene[0] = NULL; | |
bscene_anim_speed = 5; bytes_per_pixel = 1; | |
numLocalVars = 0; | |
localvars = NULL; | |
lastLoadNumHotspots = 0; | |
lastLoadNumRegions = 0; | |
lastLoadNumObjects = 0; | |
int i; | |
for (i = 0; i <= MAX_WALK_AREAS; i++) { | |
walk_area_zoom2[i] = NOT_VECTOR_SCALED; | |
walk_area_top[i] = -1; | |
walk_area_bottom[i] = -1; | |
} | |
for (i = 0; i < MAX_HOTSPOTS; i++) { | |
intrHotspot[i] = new NewInteraction(); | |
hotspotnames[i] = NULL; | |
hotspotScriptNames[i][0] = 0; | |
} | |
for (i = 0; i < MAX_INIT_SPR; i++) | |
intrObject[i] = new NewInteraction(); | |
for (i = 0; i < MAX_REGIONS; i++) | |
intrRegion[i] = new NewInteraction(); | |
intrRoom = new NewInteraction(); | |
gameId = 0; | |
numRegions = 0; | |
hotspotScripts = NULL; | |
regionScripts = NULL; | |
objectScripts = NULL; | |
roomScripts = NULL; | |
} | |
//void allocall(); | |
//void freeall(); | |
void freemessage(); | |
}; | |
extern int in_interaction_editor; // whether to remove script functions/etc | |
#ifndef CROOM_NOFUNCTIONS | |
int in_interaction_editor = 0; | |
void WordsDictionary::sort () { | |
int aa, bb; | |
for (aa = 0; aa < num_words; aa++) { | |
for (bb = aa + 1; bb < num_words; bb++) { | |
if (((wordnum[aa] == wordnum[bb]) && (stricmp(word[aa], word[bb]) > 0)) | |
|| (wordnum[aa] > wordnum[bb])) { | |
short temp = wordnum[aa]; | |
char tempst[30]; | |
wordnum[aa] = wordnum[bb]; | |
wordnum[bb] = temp; | |
strcpy(tempst, word[aa]); | |
strcpy(word[aa], word[bb]); | |
strcpy(word[bb], tempst); | |
bb = aa; | |
} | |
} | |
} | |
} | |
int WordsDictionary::find_index (const char*wrem) { | |
int aa; | |
for (aa = 0; aa < num_words; aa++) { | |
if (stricmp (wrem, word[aa]) == 0) | |
return aa; | |
} | |
return -1; | |
} | |
// {name, flags, numArgs, {argTypes}, {argNames}, description, textscript} | |
ActionTypes actions[NUM_ACTION_TYPES] = { | |
{"Do nothing", 0, 0, {NULL}, {NULL}, "Does nothing.", ""}, | |
{"Run script", AFLG_RUNSCRIPT, 0, {NULL}, {NULL}, "Runs a text script. Click the 'Edit Script' button to modify the script.", ""}, | |
{"Game - Add score on first execution", 0, 1, {ARG_TYPE_INT}, {"Points to add"}, | |
"Gives the player $$1 extra points the first time this action is run.", | |
""}, | |
{"Game - Add score", 0, 1, {ARG_TYPE_INT}, {"Points to add"}, | |
"Gives the player $$1 extra points every time this action is run.", | |
"GiveScore($$1);"}, | |
{"Game - Display a message", AFLG_MESSAGE, 1, {ARG_TYPE_MSG}, {"Message number"}, | |
"Displays message $$1 to the player.", | |
"DisplayMessage($$1);"}, | |
{"Game - Play music", 0, 1, {ARG_TYPE_INT}, {"Music number"}, | |
"Changes the current background music to MUSIC$$1.MP3, WAV, MID or MOD", | |
"PlayMusic($$1);"}, | |
{"Game - Stop music", 0, 0, {NULL}, {NULL}, | |
"Stops the currently playing background music.", | |
"StopMusic();"}, | |
{"Game - Play sound effect", 0, 1, {ARG_TYPE_INT}, {"Sound number"}, | |
"Plays SOUND$$1.MP3 or SOUND$$1.WAV", | |
"PlaySound($$1);"}, | |
{"Game - Play Flic animation", 0, 2, {ARG_TYPE_INT, ARG_TYPE_BOOL}, {"Flic number", "Player can skip"}, | |
"Plays FLIC$$1.FLC or FLIC$$1.FLI", | |
"PlayFlic($$1, $$2);"}, | |
{"Game - Run dialog", 0, 1, {ARG_TYPE_INT}, {"Dialog topic number"}, | |
"Starts a conversation using dialog topic $$1.", | |
"dialog[$$1].Start();"}, | |
{"Game - Enable dialog option", 0, 2, {ARG_TYPE_INT, ARG_TYPE_INT}, {"Dialog topic number", "Option number"}, | |
"Enables dialog option $$2 in topic $$1 to be visible to the player.", | |
"dialog[$$1].SetOptionState($$2, eOptionOn);"}, | |
{"Game - Disable dialog option", 0, 2, {ARG_TYPE_INT, ARG_TYPE_INT}, {"Dialog topic number", "Option number"}, | |
"Stops dialog option $$2 in topic $$1 from being visible to the player.", | |
"dialog[$$1].SetOptionState($$2, eOptionOff);"}, | |
{"Player - Go to a different room", 0, 2, {ARG_TYPE_INT, ARG_TYPE_INT}, {"New room number", "Edge+offset value"}, | |
"Takes the player to room $$1, optionally choosing position using old-style Data column value $$2", | |
"player.ChangeRoom($$1);"}, | |
{"Player - Give the player an inventory item", 0, 1, {ARG_TYPE_INV}, {"Inventory item number"}, | |
"Adds inventory item $$1 to the player character's inventory.", | |
"player.AddInventory(inventory[$$1]);"}, | |
{"Object - Move object", 0, 5, {ARG_TYPE_INT, ARG_TYPE_INT, ARG_TYPE_INT, ARG_TYPE_INT, ARG_TYPE_BOOL}, | |
{"Object number", "Destination X location", "Destination Y location", "Move speed", "Wait for move to finish"}, | |
"Starts object $$1 moving towards ($$2, $$3), at speed $$4.", | |
"object[$$1].Move($$2, $$3, $$4);"}, | |
{"Object - Remove an object from the room", 0, 1, {ARG_TYPE_INT}, {"Object number"}, | |
"Switches room object $$1 off so the player cannot see or interact with it.", | |
"object[$$1].Visible = false;"}, | |
{"Object - Switch an object back on", 0, 1, {ARG_TYPE_INT}, {"Object number"}, | |
"Switches room object $$1 on, so that the player can see and interact with it.", | |
"object[$$1].Visible = true;"}, | |
{"Object - Set object view number", 0, 2, {ARG_TYPE_INT, ARG_TYPE_INT}, {"Object number", "New view number"}, | |
"Changes object $$1's view number to $$2", | |
"object[$$1].SetView($$2);"}, | |
{"Object - Start object animating", 0, 4, {ARG_TYPE_INT, ARG_TYPE_INT, ARG_TYPE_INT, ARG_TYPE_BOOL}, | |
{"Object number", "Loop number", "Speed", "Repeat"}, | |
"Starts object $$1 animating, using loop $$2 of its current view, and animating at speed $$3.", | |
"object[$$1].Animate($$2, $$3);"}, | |
{"Character - Move character", 0, 4, {ARG_TYPE_CHAR, ARG_TYPE_INT, ARG_TYPE_INT, ARG_TYPE_BOOL}, | |
{"Character", "Destination X location", "Destination Y location", "Wait for move to finish"}, | |
"Starts character $$1 moving towards ($$2, $$3).", | |
"character[$$1].Walk($$2, $$3);"}, | |
{"Conditional - If inventory item was used", AFLG_COND | AFLG_INVCHECK, 1, {ARG_TYPE_INV}, {"Inventory item number"}, | |
"Performs child actions if the player just used inventory item $$1 on this interaction.", | |
"if (player.ActiveInventory == inventory[$$1]) {"}, | |
{"Conditional - If the player has an inventory item", AFLG_COND, 1, {ARG_TYPE_INV}, {"Inventory item number"}, | |
"Performs child actions if the player character has inventory item $$1 in their current inventory.", | |
"if (player.InventoryQuantity[$$1] > 0) {"}, | |
{"Conditional - If a character is moving", AFLG_COND, 1, {ARG_TYPE_CHAR}, {"Character number"}, | |
"Performs child actions if character $$1 is currently moving", | |
"if (character[$$1].Moving) {"}, | |
{"Conditional - If a variable is set to a certain value", AFLG_COND, 2, {ARG_TYPE_INT, ARG_TYPE_INT}, {"Variable", "Value"}, | |
"Performs child actions if $$1 == $$2", | |
"if (GetGraphicalVariable(\"$$1\") == $$2) { "}, | |
{"Character - Stop character walking", 0, 1, {ARG_TYPE_CHAR}, {"Character"}, | |
"Immediately stops character $$1 from moving.", | |
"character[$$1].StopMoving();"}, | |
{"Player - Go to a different room (at specific co-ordinates)", 0, 3, {ARG_TYPE_INT, ARG_TYPE_INT, ARG_TYPE_INT}, | |
{"New room number", "X co-ordinate", "Y co-ordinate"}, | |
"Takes the player to room $$1, and places him at ($$2, $$3)", | |
"player.ChangeRoom($$1, $$2, $$3);"}, | |
{"Character - Move NPC to different room", 0, 2, {ARG_TYPE_CHAR, ARG_TYPE_INT}, | |
{"Character", "New room number"}, | |
"Places non-player character $$1 into room $$2.", | |
"character[$$1].ChangeRoom($$2);"}, | |
{"Character - Set character view", 0, 2, {ARG_TYPE_CHAR, ARG_TYPE_INT}, | |
{"Character", "View number"}, | |
"Locks character $$1's view to view $$2, in preparation for doing an animation. Use 'Release Character View' afterwards to release it.", | |
"character[$$1].LockView($$2);"}, | |
{"Character - Release character view", 0, 1, {ARG_TYPE_CHAR}, {"Character"}, | |
"Reverts character $$1's view back to its normal view and enables standard engine processing.", | |
"character[$$1].UnlockView();"}, | |
{"Character - Follow another character", 0, 2, {ARG_TYPE_CHAR, ARG_TYPE_CHAR}, | |
{"Character", "Follow Character"}, | |
"Makes character $$1 follow $$2 around the screen.", | |
"character[$$1].FollowCharacter($$2);"}, | |
{"Character - Stop following", 0, 1, {ARG_TYPE_CHAR}, {"Character"}, | |
"Stops character $$1 following any other characters.", | |
"character[$$1].FollowCharacter(null);"}, | |
{"Room - Disable hotspot", 0, 1, {ARG_TYPE_INT}, {"Hotspot number"}, | |
"Disables hotspot $$1 in the current room.", | |
"hotspot[$$1].Enabled = false;"}, | |
{"Room - Enable hotspot", 0, 1, {ARG_TYPE_INT}, {"Hotspot number"}, | |
"Re-enables hotspot $$1 in the current room.", | |
"hotspot[$$1].Enabled = true;"}, | |
{"Game - Set variable value", 0, 2, {ARG_TYPE_VARONLY, ARG_TYPE_INT}, {"Variable", "New value"}, | |
"Sets variable $$1 to have the value $$2", | |
"SetGraphicalVariable(\"$$1\", $$2);"}, | |
{"Character - Run animation loop", 0, 3, {ARG_TYPE_CHAR, ARG_TYPE_INT, ARG_TYPE_INT}, | |
{"Character", "Loop number", "Speed"}, | |
"Runs character $$1 through loop $$2 of its current view, animating at speed $$3. Waits for animation to finish before continuing.", | |
""}, | |
{"Character - Quick animation", 0, 4, {ARG_TYPE_CHAR, ARG_TYPE_INT, ARG_TYPE_INT, ARG_TYPE_INT}, | |
{"Character", "View number", "Loop number", "Speed"}, | |
"Does SetCharacterView($$1, $$2), AnimateCharacter($$1, $$3, $$4), ReleaseCharacterView($$1) in order.", | |
""}, | |
{"Character - Set idle animation", 0, 3, {ARG_TYPE_CHAR, ARG_TYPE_INT, ARG_TYPE_INT}, | |
{"Character", "View number", "Delay"}, | |
"Sets character $$1 to use view $$2 as its idle animation, with a timeout of $$3 seconds of inactivity before the animation is played.", | |
"character[$$1].SetIdleView($$2, $$3);"}, | |
{"Character - Disable idle animation", 0, 1, {ARG_TYPE_CHAR}, | |
{"Character"}, | |
"Disables character $$1's idle animation, so it will no longer be played.", | |
"character[$$1].SetIdleView(-1, -1);"}, | |
{"Player - Remove an item from the inventory", 0, 1, {ARG_TYPE_INV}, {"Inventory item number"}, | |
"Removes inventory item $$1 from the player character's inventory.", | |
"player.LoseInventory(inventory[$$1]);"}, | |
{"Game - Show GUI", 0, 1, {ARG_TYPE_INT}, {"GUI number"}, | |
"Switches on GUI number $$1 so the player can see it.", | |
"gui[$$1].Visible = true;"}, | |
{"Game - Hide GUI", 0, 1, {ARG_TYPE_INT}, {"GUI number"}, | |
"Switches off GUI number $$1 so the player can no longer see it.", | |
"gui[$$1].Visible = false;"}, | |
{"Stop running more commands", 0, 0, {NULL}, {NULL}, | |
"Stops running the interaction list at this point. Useful at the end of a block of actions inside a conditional.", | |
"return;"}, | |
{"Character - Face location", 0, 3, {ARG_TYPE_CHAR, ARG_TYPE_INT, ARG_TYPE_INT}, | |
{"Character", "X co-ordinate", "Y co-ordinate"}, | |
"Turns character $$1 so that they are facing the room co-ordinates ($$2, $$3).", | |
"character[$$1].FaceLocation($$2, $$3);"}, | |
{"Game - Pause command processor for a set time", 0, 1, {ARG_TYPE_INT}, | |
{"Loops to wait"}, | |
"Stops processing actions here and lets the game continue execution for $$1 game loops (default 40 per second) before continuing with the next command.", | |
"Wait($$1);"}, | |
{"Character - Change character view", 0, 2, {ARG_TYPE_CHAR, ARG_TYPE_INT}, | |
{"Character", "New view number"}, | |
"Changes character $$1's normal walking view to View $$2 permanently, until you call this command again.", | |
"character[$$1].ChangeView($$2);"}, | |
{"Conditional - If the player character is", AFLG_COND, 1, {ARG_TYPE_CHAR}, | |
{"Character"}, | |
"Performs child actions if the player character is currently $$1. Useful in games where the player can control multiple characters.", | |
"if (player.ID == $$1) {"}, | |
{"Conditional - If mouse cursor mode is", AFLG_COND, 1, {ARG_TYPE_INT}, | |
{"Mouse cursor"}, | |
"Performs child actions if the current cursor mode is mode $$1 (from the Cursors pane).", | |
"if (mouse.Mode == $$1) {"}, | |
{"Conditional - If the player has been in room", AFLG_COND, 1, {ARG_TYPE_INT}, | |
{"Room number"}, | |
"Performs child actions if the player has been to room $$1 during the game.", | |
"if (HasPlayerBeenInRoom($$1)) {"} | |
}; | |
InteractionVariable globalvars[MAX_GLOBAL_VARIABLES] = {{"Global 1", 0, 0}}; | |
int numGlobalVars = 1; | |
void serialize_command_list (NewInteractionCommandList *nicl, FILE*ooo) { | |
if (nicl == NULL) | |
return; | |
putw (nicl->numCommands, ooo); | |
putw (nicl->timesRun, ooo); | |
#ifndef ALLEGRO_BIG_ENDIAN | |
fwrite (&nicl->command[0], sizeof(NewInteractionCommand), nicl->numCommands, ooo); | |
#else | |
for (int iteratorCount = 0; iteratorCount < nicl->numCommands; ++iteratorCount) | |
{ | |
nicl->command[iteratorCount].WriteToFile(ooo); | |
} | |
#endif // ALLEGRO_BIG_ENDIAN | |
for (int k = 0; k < nicl->numCommands; k++) { | |
if (nicl->command[k].children != NULL) | |
serialize_command_list (nicl->command[k].get_child_list(), ooo); | |
} | |
} | |
void serialize_new_interaction (NewInteraction *nint, FILE*ooo) { | |
int a; | |
putw (1, ooo); // Version | |
putw (nint->numEvents, ooo); | |
fwrite (&nint->eventTypes[0], sizeof(int), nint->numEvents, ooo); | |
// 64 bit: The pointer is only checked against NULL to determine whether the event exists | |
for (a = 0; a < nint->numEvents; a++) | |
putw ((long)nint->response[a], ooo); | |
for (a = 0; a < nint->numEvents; a++) { | |
if (nint->response[a] != NULL) | |
serialize_command_list (nint->response[a], ooo); | |
} | |
} | |
NewInteractionCommandList *deserialize_command_list (FILE *ooo) { | |
NewInteractionCommandList *nicl = new NewInteractionCommandList; | |
nicl->numCommands = getw(ooo); | |
nicl->timesRun = getw(ooo); | |
for (int iteratorCount = 0; iteratorCount < nicl->numCommands; ++iteratorCount) | |
{ | |
nicl->command[iteratorCount].ReadFromFile(ooo); | |
} | |
for (int k = 0; k < nicl->numCommands; k++) { | |
if (nicl->command[k].children != NULL) { | |
nicl->command[k].children = deserialize_command_list (ooo); | |
} | |
nicl->command[k].parent = nicl; | |
} | |
return nicl; | |
} | |
NewInteraction *nitemp; | |
NewInteraction *deserialize_new_interaction (FILE *ooo) { | |
int a; | |
if (getw(ooo) != 1) | |
return NULL; | |
nitemp = new NewInteraction; | |
nitemp->numEvents = getw(ooo); | |
if (nitemp->numEvents > MAX_NEWINTERACTION_EVENTS) { | |
quit("Error: this interaction was saved with a newer version of AGS"); | |
return NULL; | |
} | |
fread (&nitemp->eventTypes[0], sizeof(int), nitemp->numEvents, ooo); | |
//fread (&nitemp->response[0], sizeof(void*), nitemp->numEvents, ooo); | |
// 64 bit: The pointer is only checked against NULL to determine whether the event exists | |
for (a = 0; a < nitemp->numEvents; a++) | |
nitemp->response[a] = (NewInteractionCommandList*)getw(ooo); | |
for (a = 0; a < nitemp->numEvents; a++) { | |
if (nitemp->response[a] != NULL) | |
nitemp->response[a] = deserialize_command_list (ooo); | |
nitemp->timesRun[a] = 0; | |
} | |
return nitemp; | |
} | |
void NewInteractionCommandList::reset () { | |
int j; | |
for (j = 0; j < numCommands; j++) { | |
if (command[j].children != NULL) { | |
// using this Reset crashes it for some reason | |
//command[j].reset (); | |
command[j].get_child_list()->reset(); | |
delete command[j].children; | |
command[j].children = NULL; | |
} | |
command[j].remove(); | |
} | |
numCommands = 0; | |
timesRun = 0; | |
} | |
int ff; | |
/*void roomstruct::allocall() { | |
// These all get recreated when a room is loaded anyway | |
walls = create_bitmap_ex(8, 320, 200); | |
object = create_bitmap_ex(8, 320, 200); | |
lookat = create_bitmap_ex(8, 320, 200); | |
bscene = create_bitmap_ex(8, 320, 200); | |
shading = create_bitmap_ex(8, 320, 200); | |
if (shading == NULL) | |
quit("roomstruct::allocall: out of memory"); | |
// printf("Before %ld\n",farcoreleft()); | |
for (ff=0;ff<5;ff++) { //backups[ff]=wnewblock(0,0,319,199); | |
backups[ff]=wallocblock(320,200); | |
// printf("%d ",ff); if (kbhit()) break; | |
if (backups[ff]==NULL) quit("ROOM.C, AllocMem: Out of memory"); } | |
walls=::backups[0]; // this is because blocks in a struct don't work | |
object=::backups[1]; // properly | |
lookat=::backups[2]; | |
bscene=::backups[3]; | |
shading=::backups[4]; | |
// printf("After %ld\n",farcoreleft()); | |
} | |
*/ | |
void roomstruct::freemessage() { | |
for (int f = 0; f < nummes; f++) { | |
if (message[f] != NULL) | |
free(message[f]); | |
} | |
} | |
/*void roomstruct::freeall() { | |
// for (int f=0;f<4;f++) wfreeblock(::backups[f]); | |
wfreeblock(walls); | |
wfreeblock(lookat); | |
wfreeblock(ebscene[0]); | |
wfreeblock(object); | |
if (shading != NULL) | |
wfreeblock(shading); | |
freemessage(); | |
}*/ | |
/*void roomstruct::freeall() { wfreeblock(walls); wfreeblock(bscene); | |
wfreeblock(object); wfreeblock(lookat); | |
for (int f=0;f<nummes;f++) if (message[f]!=NULL) free(message[f]); }*/ | |
struct room_file_header { | |
short version PCKD; | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
version = __getshort__bigendian(fp); | |
} | |
#endif | |
}; | |
int _acroom_bpp = 1; // bytes per pixel of currently loading room | |
// returns bytes per pixel for bitmap's color depth | |
int bmp_bpp(BITMAP*bmpt) { | |
if (bitmap_color_depth(bmpt) == 15) | |
return 2; | |
return bitmap_color_depth(bmpt) / 8; | |
} | |
#ifdef LOADROOM_DO_POLL | |
extern void update_polled_stuff(); | |
#else | |
static void update_polled_stuff() { } | |
#endif | |
#if defined(LINUX_VERSION) || defined(MAC_VERSION) || defined(DJGPP) || defined(_MSC_VER) | |
extern void lzwcompress(FILE *,FILE *); | |
extern void lzwexpand(FILE *,FILE *); | |
extern unsigned char *lzwexpand_to_mem(FILE *); | |
extern long maxsize, outbytes, putbytes; | |
char *lztempfnm = "~aclzw.tmp"; | |
long save_lzw(char *fnn, BITMAP *bmpp, color *pall, long offe) { | |
FILE *ooo, *iii; | |
long fll, toret, gobacto; | |
ooo = ci_fopen(lztempfnm, "wb"); | |
putw(bmpp->w * bmp_bpp(bmpp), ooo); | |
putw(bmpp->h, ooo); | |
fwrite(&bmpp->line[0][0], bmpp->w * bmp_bpp(bmpp), bmpp->h, ooo); | |
fclose(ooo); | |
iii = ci_fopen(fnn, "r+b"); | |
fseek(iii, offe, SEEK_SET); | |
ooo = ci_fopen(lztempfnm, "rb"); | |
fll = filelength(fileno(ooo)); | |
fwrite(&pall[0], sizeof(color), 256, iii); | |
fwrite(&fll, 4, 1, iii); | |
gobacto = ftell(iii); | |
// reserve space for compressed size | |
fwrite(&fll, 4, 1, iii); | |
lzwcompress(ooo, iii); | |
toret = ftell(iii); | |
fseek(iii, gobacto, SEEK_SET); | |
fll = (toret - gobacto) - 4; | |
fwrite(&fll, 4, 1, iii); // write compressed size | |
fclose(ooo); | |
fclose(iii); | |
unlink(lztempfnm); | |
return toret; | |
} | |
BITMAP *recalced; | |
/*long load_lzw(char*fnn,BITMAP*bmm,color*pall,long ooff) { | |
recalced=bmm; | |
FILE*iii=clibfopen(fnn,"rb"); | |
fseek(iii,ooff,SEEK_SET);*/ | |
long load_lzw(FILE *iii, BITMAP *bmm, color *pall) { | |
int uncompsiz, *loptr; | |
unsigned char *membuffer; | |
int arin; | |
recalced = bmm; | |
// MACPORT FIX (HACK REALLY) | |
fread(&pall[0], 1, sizeof(color)*256, iii); | |
fread(&maxsize, 4, 1, iii); | |
fread(&uncompsiz,4,1,iii); | |
uncompsiz += ftell(iii); | |
outbytes = 0; putbytes = 0; | |
update_polled_stuff(); | |
membuffer = lzwexpand_to_mem(iii); | |
update_polled_stuff(); | |
loptr = (int *)&membuffer[0]; | |
membuffer += 8; | |
#ifdef ALLEGRO_BIG_ENDIAN | |
loptr[0] = __int_swap_endian(loptr[0]); | |
loptr[1] = __int_swap_endian(loptr[1]); | |
int bitmapNumPixels = loptr[0]*loptr[1]/_acroom_bpp; | |
switch (_acroom_bpp) // bytes per pixel! | |
{ | |
case 1: | |
{ | |
// all done | |
break; | |
} | |
case 2: | |
{ | |
short *sp = (short *)membuffer; | |
for (int i = 0; i < bitmapNumPixels; ++i) | |
{ | |
sp[i] = __short_swap_endian(sp[i]); | |
} | |
// all done | |
break; | |
} | |
case 4: | |
{ | |
int *ip = (int *)membuffer; | |
for (int i = 0; i < bitmapNumPixels; ++i) | |
{ | |
ip[i] = __int_swap_endian(ip[i]); | |
} | |
// all done | |
break; | |
} | |
} | |
#endif | |
if (bmm!=NULL) | |
destroy_bitmap(bmm); | |
update_polled_stuff(); | |
bmm = create_bitmap_ex(_acroom_bpp * 8, (loptr[0] / _acroom_bpp), loptr[1]); | |
if (bmm == NULL) | |
quit("!load_room: not enough memory to load room background"); | |
update_polled_stuff(); | |
acquire_bitmap (bmm); | |
recalced = bmm; | |
for (arin = 0; arin < loptr[1]; arin++) | |
memcpy(&bmm->line[arin][0], &membuffer[arin * loptr[0]], loptr[0]); | |
release_bitmap (bmm); | |
update_polled_stuff(); | |
free(membuffer-8); | |
if (ftell(iii) != uncompsiz) | |
fseek(iii, uncompsiz, SEEK_SET); | |
update_polled_stuff(); | |
return uncompsiz; | |
} | |
long savecompressed_allegro(char *fnn, BITMAP *bmpp, color *pall, long ooo) { | |
unsigned char *wgtbl = (unsigned char *)malloc(bmpp->w * bmpp->h + 4); | |
short *sss = (short *)wgtbl; | |
long toret; | |
sss[0] = bmpp->w; | |
sss[1] = bmpp->h; | |
memcpy(&wgtbl[4], &bmpp->line[0][0], bmpp->w * bmpp->h); | |
toret = csavecompressed(fnn, wgtbl, pall, ooo); | |
free(wgtbl); | |
return toret; | |
} | |
long loadcompressed_allegro(FILE *fpp, BITMAP **bimpp, color *pall, long ooo) { | |
short widd,hitt; | |
int ii; | |
BITMAP *bim = *bimpp; | |
if (bim != NULL) | |
destroy_bitmap(bim); | |
fread(&widd,2,1,fpp); | |
fread(&hitt,2,1,fpp); | |
bim = create_bitmap_ex(8, widd, hitt); | |
if (bim == NULL) | |
quit("!load_room: not enough memory to decompress masks"); | |
*bimpp = bim; | |
for (ii = 0; ii < hitt; ii++) { | |
cunpackbitl(&bim->line[ii][0], widd, fpp); | |
if (ii % 20 == 0) | |
update_polled_stuff(); | |
} | |
fseek(fpp, 768, SEEK_CUR); // skip palette | |
return ftell(fpp); | |
} | |
#endif | |
#define BLOCKTYPE_MAIN 1 | |
#define BLOCKTYPE_SCRIPT 2 | |
#define BLOCKTYPE_COMPSCRIPT 3 | |
#define BLOCKTYPE_COMPSCRIPT2 4 | |
#define BLOCKTYPE_OBJECTNAMES 5 | |
#define BLOCKTYPE_ANIMBKGRND 6 | |
#define BLOCKTYPE_COMPSCRIPT3 7 // new CSCOMP script instead of SeeR | |
#define BLOCKTYPE_PROPERTIES 8 | |
#define BLOCKTYPE_OBJECTSCRIPTNAMES 9 | |
#define BLOCKTYPE_EOF 0xff | |
extern void load_script_configuration(FILE *); | |
extern void save_script_configuration(FILE *); | |
extern void load_graphical_scripts(FILE *, roomstruct *); | |
extern void save_graphical_scripts(FILE *, roomstruct *); | |
static char *passwencstring = "Avis Durgan"; | |
void decrypt_text(char*toenc) { | |
int adx = 0; | |
while (1) { | |
toenc[0] -= passwencstring[adx]; | |
if (toenc[0] == 0) | |
break; | |
adx++; | |
toenc++; | |
if (adx > 10) | |
adx = 0; | |
} | |
} | |
#ifndef NO_SAVE_FUNCTIONS | |
void encrypt_text(char *toenc) { | |
int adx = 0, tobreak = 0; | |
while (tobreak == 0) { | |
if (toenc[0] == 0) | |
tobreak = 1; | |
toenc[0] += passwencstring[adx]; | |
adx++; | |
toenc++; | |
if (adx > 10) | |
adx = 0; | |
} | |
} | |
void write_string_encrypt(FILE *ooo, char *sss) { | |
int stlent = (int)strlen(sss) + 1; | |
putw(stlent, ooo); | |
encrypt_text(sss); | |
fwrite(sss, stlent, 1, ooo); | |
decrypt_text(sss); | |
} | |
void write_dictionary (WordsDictionary *dict, FILE *writeto) { | |
int ii; | |
putw(dict->num_words, writeto); | |
for (ii = 0; ii < dict->num_words; ii++) { | |
write_string_encrypt (writeto, dict->word[ii]); | |
#ifndef ALLEGRO_BIG_ENDIAN | |
fwrite(&dict->wordnum[ii], sizeof(short), 1, writeto); | |
#else | |
__putshort__lilendian(dict->wordnum[ii], writeto); | |
#endif // ALLEGRO_BIG_ENDIAN | |
} | |
} | |
#endif // NO_SAVE_FUCNTIONS | |
void read_string_decrypt(FILE *ooo, char *sss) { | |
int newlen = getw(ooo); | |
if ((newlen < 0) || (newlen > 5000000)) | |
quit("ReadString: file is corrupt"); | |
// MACPORT FIX: swap as usual | |
fread(sss, sizeof(char), newlen, ooo); | |
sss[newlen] = 0; | |
decrypt_text(sss); | |
} | |
void read_dictionary (WordsDictionary *dict, FILE *writeto) { | |
int ii; | |
dict->allocate_memory(getw(writeto)); | |
for (ii = 0; ii < dict->num_words; ii++) { | |
read_string_decrypt (writeto, dict->word[ii]); | |
fread(&dict->wordnum[ii], sizeof(short), 1, writeto); | |
} | |
} | |
void freadmissout(short *pptr, FILE *opty) { | |
fread(&pptr[0], 2, 5, opty); | |
fread(&pptr[7], 2, NUM_CONDIT - 7, opty); | |
pptr[5] = pptr[6] = 0; | |
} | |
#define HS_STANDON 0 | |
#define HS_LOOKAT 1 | |
#define HS_INTERACT 2 | |
#define HS_USEINV 3 | |
#define HS_TALKTO 4 | |
#define OBJ_LOOKAT 0 | |
#define OBJ_INTERACT 1 | |
#define OBJ_TALKTO 2 | |
#define OBJ_USEINV 3 | |
void add_to_eventblock(EventBlock *evpt, int evnt, int whatac, int val1, int data, short scorr) { | |
evpt->list[evpt->numcmd] = evnt; | |
evpt->respond[evpt->numcmd] = whatac; | |
evpt->respondval[evpt->numcmd] = val1; | |
evpt->data[evpt->numcmd] = data; | |
evpt->score[evpt->numcmd] = scorr; | |
evpt->numcmd++; | |
} | |
int usesmisccond = 0; | |
void deserialize_interaction_scripts(FILE *iii, InteractionScripts *scripts) | |
{ | |
int numEvents = getw(iii); | |
if (numEvents > MAX_NEWINTERACTION_EVENTS) | |
quit("Too many interaction script events"); | |
scripts->numEvents = numEvents; | |
char buffer[200]; | |
for (int i = 0; i < numEvents; i++) | |
{ | |
fgetstring_limit(buffer, iii, sizeof(buffer)); | |
scripts->scriptFuncNames[i] = new char[strlen(buffer) + 1]; | |
strcpy(scripts->scriptFuncNames[i], buffer); | |
} | |
} | |
void load_main_block(roomstruct *rstruc, char *files, FILE *opty, room_file_header rfh) { | |
int f, gsmod, NUMREAD; | |
char buffre[3000]; | |
long tesl; | |
usesmisccond = 0; | |
rstruc->width = 320; | |
rstruc->height = 200; | |
rstruc->resolution = 1; | |
rstruc->numwalkareas = 0; | |
rstruc->numhotspots = 0; | |
memset(&rstruc->shadinginfo[0], 0, sizeof(short) * 16); | |
memset(&rstruc->sprs[0], 0, sizeof(sprstruc) * MAX_INIT_SPR); | |
memset(&rstruc->objbaseline[0], 0xff, sizeof(int) * MAX_INIT_SPR); | |
memset(&rstruc->objectFlags[0], 0, sizeof(short) * MAX_INIT_SPR); | |
memset(&rstruc->hswalkto[0], 0, sizeof(_Point) * MAX_HOTSPOTS); | |
memset(&rstruc->walk_area_zoom[0], 0, sizeof(short) * (MAX_WALK_AREAS + 1)); | |
memset(&rstruc->walk_area_light[0], 0, sizeof(short) * (MAX_WALK_AREAS + 1)); | |
for (f = 0; f < MAX_HOTSPOTS; f++) { | |
rstruc->hotspotScriptNames[f][0] = 0; | |
if (rstruc->hotspotnames[f] != NULL) | |
free(rstruc->hotspotnames[f]); | |
rstruc->hotspotnames[f] = (char*)malloc(20); | |
sprintf(rstruc->hotspotnames[f], "Hotspot %d", f); | |
if (f == 0) | |
strcpy(rstruc->hotspotnames[f], "No hotspot"); | |
} | |
/* memset(&rstruc->hscond[0], 0, sizeof(EventBlock) * MAX_HOTSPOTS); | |
memset(&rstruc->objcond[0], 0, sizeof(EventBlock) * MAX_INIT_SPR); | |
memset(&rstruc->misccond, 0, sizeof(EventBlock));*/ | |
if (rfh.version >= 12) | |
_acroom_bpp = getw(opty); | |
else | |
_acroom_bpp = 1; | |
if (_acroom_bpp < 1) | |
_acroom_bpp = 1; | |
rstruc->bytes_per_pixel = _acroom_bpp; | |
fread(&rstruc->numobj, 2, 1, opty); | |
if (rstruc->numobj > MAX_OBJ) | |
quit("!room newer than this version - too many walk-behinds"); | |
NUMREAD = NUM_CONDIT; | |
fread(&rstruc->objyval[0], 2, rstruc->numobj, opty); | |
gsmod = 0; | |
fread(&rstruc->numhotspots, sizeof(int), 1, opty); | |
if (rstruc->numhotspots == 0) | |
rstruc->numhotspots = 20; | |
if (rstruc->numhotspots > MAX_HOTSPOTS) | |
quit("room has too many hotspots: need newer version of AGS?"); | |
#ifndef ALLEGRO_BIG_ENDIAN | |
fread(&rstruc->hswalkto[0], sizeof(_Point), rstruc->numhotspots, opty); | |
#else | |
// Points are a pair of shorts | |
fread(&rstruc->hswalkto[0], sizeof(short), 2*rstruc->numhotspots, opty); | |
#endif | |
for (f = 0; f < rstruc->numhotspots; f++) | |
{ | |
free(rstruc->hotspotnames[f]); | |
if (rfh.version >= 28) | |
{ | |
fgetstring_limit(buffre, opty, 2999); | |
rstruc->hotspotnames[f] = (char*)malloc(strlen(buffre) + 1); | |
strcpy(rstruc->hotspotnames[f], buffre); | |
} | |
else | |
{ | |
rstruc->hotspotnames[f] = (char*)malloc(30); | |
fread(rstruc->hotspotnames[f], 30, 1, opty); | |
} | |
} | |
if (rfh.version >= 24) | |
fread(&rstruc->hotspotScriptNames[0], MAX_SCRIPT_NAME_LEN, rstruc->numhotspots, opty); | |
fread(&rstruc->numwalkareas, 4, 1, opty); | |
// MACPORT FIX: read polypoints | |
#ifndef ALLEGRO_BIG_ENDIAN | |
fread(&rstruc->wallpoints[0], sizeof(PolyPoints), rstruc->numwalkareas, opty); | |
#else | |
for (int iteratorCount = 0; iteratorCount < rstruc->numwalkareas; ++iteratorCount) | |
{ | |
rstruc->wallpoints[iteratorCount].ReadFromFile(opty); | |
} | |
#endif | |
update_polled_stuff(); | |
fread(&rstruc->top, 2, 1, opty); | |
fread(&rstruc->bottom, 2, 1, opty); | |
fread(&rstruc->left, 2, 1, opty); | |
fread(&rstruc->right, 2, 1, opty); | |
fread(&rstruc->numsprs, 2, 1, opty); | |
// MACPORT FIX: read sprstrucs | |
#ifndef ALLEGRO_BIG_ENDIAN | |
fread(&rstruc->sprs[0], sizeof(sprstruc), rstruc->numsprs, opty); | |
#else | |
for (int iteratorCount = 0; iteratorCount < rstruc->numsprs; ++iteratorCount) | |
{ | |
rstruc->sprs[iteratorCount].ReadFromFile(opty); | |
} | |
#endif | |
if (rfh.version >= 19) { | |
rstruc->numLocalVars = getw(opty); | |
if (rstruc->numLocalVars > 0) { | |
rstruc->localvars = (InteractionVariable*)malloc (sizeof(InteractionVariable) * rstruc->numLocalVars); | |
#ifndef ALLEGRO_BIG_ENDIAN | |
fread (&rstruc->localvars[0], sizeof(InteractionVariable), rstruc->numLocalVars, opty); | |
#else | |
for (int iteratorCount = 0; iteratorCount < rstruc->numLocalVars; ++iteratorCount) | |
{ | |
rstruc->localvars[iteratorCount].ReadFromFile(opty); | |
} | |
#endif | |
} | |
} | |
rstruc->numRegions = 0; | |
if (rfh.version >= 15) { | |
if ((rstruc->numhotspots > MAX_HOTSPOTS) || (rstruc->numsprs > MAX_INIT_SPR)) | |
quit("load_room: room file created with newer version (too many hotspots/objects)"); | |
// free all of the old interactions | |
for (f = 0; f < MAX_HOTSPOTS; f++) { | |
if (rstruc->intrHotspot[f] != NULL) { | |
delete rstruc->intrHotspot[f]; | |
rstruc->intrHotspot[f] = NULL; | |
} | |
if (rfh.version < 26) | |
{ | |
if (f < rstruc->numhotspots) | |
rstruc->intrHotspot[f] = deserialize_new_interaction (opty); | |
else | |
rstruc->intrHotspot[f] = new NewInteraction(); | |
} | |
} | |
for (f = 0; f < MAX_INIT_SPR; f++) { | |
if (rstruc->intrObject[f] != NULL) { | |
delete rstruc->intrObject[f]; | |
rstruc->intrObject[f] = NULL; | |
} | |
if (rfh.version < 26) | |
{ | |
if (f < rstruc->numsprs) | |
rstruc->intrObject[f] = deserialize_new_interaction (opty); | |
else | |
rstruc->intrObject[f] = new NewInteraction(); | |
} | |
} | |
if (rfh.version < 26) | |
{ | |
delete rstruc->intrRoom; | |
rstruc->intrRoom = deserialize_new_interaction (opty); | |
} | |
for (f = 0; f < MAX_REGIONS; f++) { | |
if (rstruc->intrRegion[f] != NULL) | |
delete rstruc->intrRegion[f]; | |
rstruc->intrRegion[f] = new NewInteraction(); | |
} | |
if (rfh.version >= 21) { | |
rstruc->numRegions = getw (opty); | |
if (rstruc->numRegions > MAX_REGIONS) | |
quit("load_room: needs newer version of AGS - too many regions"); | |
if (rfh.version < 26) | |
{ | |
for (f = 0; f < rstruc->numRegions; f++) { | |
delete rstruc->intrRegion[f]; | |
rstruc->intrRegion[f] = deserialize_new_interaction (opty); | |
} | |
} | |
} | |
if (rfh.version >= 26) | |
{ | |
rstruc->hotspotScripts = new InteractionScripts*[rstruc->numhotspots]; | |
rstruc->objectScripts = new InteractionScripts*[rstruc->numsprs]; | |
rstruc->regionScripts = new InteractionScripts*[rstruc->numRegions]; | |
rstruc->roomScripts = new InteractionScripts(); | |
deserialize_interaction_scripts(opty, rstruc->roomScripts); | |
int bb; | |
for (bb = 0; bb < rstruc->numhotspots; bb++) { | |
rstruc->hotspotScripts[bb] = new InteractionScripts(); | |
deserialize_interaction_scripts(opty, rstruc->hotspotScripts[bb]); | |
} | |
for (bb = 0; bb < rstruc->numsprs; bb++) { | |
rstruc->objectScripts[bb] = new InteractionScripts(); | |
deserialize_interaction_scripts(opty, rstruc->objectScripts[bb]); | |
} | |
for (bb = 0; bb < rstruc->numRegions; bb++) { | |
rstruc->regionScripts[bb] = new InteractionScripts(); | |
deserialize_interaction_scripts(opty, rstruc->regionScripts[bb]); | |
} | |
} | |
} | |
if (rfh.version >= 9) { | |
fread(&rstruc->objbaseline[0], sizeof(int), rstruc->numsprs, opty); | |
fread(&rstruc->width, 2, 1, opty); | |
fread(&rstruc->height, 2, 1, opty); | |
} | |
if (rfh.version >= 23) | |
fread(&rstruc->objectFlags[0], sizeof(short), rstruc->numsprs, opty); | |
if (rfh.version >= 11) | |
fread(&rstruc->resolution, 2, 1, opty); | |
int num_walk_areas = MAX_WALK_AREAS; | |
if (rfh.version >= 14) | |
num_walk_areas = getw (opty); | |
if (num_walk_areas > MAX_WALK_AREAS + 1) | |
quit("load_room: Too many walkable areas, need newer version"); | |
if (rfh.version >= 10) | |
fread(&rstruc->walk_area_zoom[0], sizeof(short), num_walk_areas, opty); | |
if (rfh.version >= 13) | |
fread(&rstruc->walk_area_light[0], sizeof(short), num_walk_areas, opty); | |
if (rfh.version >= 18) { | |
fread(&rstruc->walk_area_zoom2[0], sizeof(short), num_walk_areas, opty); | |
fread(&rstruc->walk_area_top[0], sizeof(short), num_walk_areas, opty); | |
fread(&rstruc->walk_area_bottom[0], sizeof(short), num_walk_areas, opty); | |
for (f = 0; f < num_walk_areas; f++) { | |
// if they set a contiuously scaled area where the top | |
// and bottom zoom levels are identical, set it as a normal | |
// scaled area | |
if (rstruc->walk_area_zoom[f] == rstruc->walk_area_zoom2[f]) | |
rstruc->walk_area_zoom2[f] = NOT_VECTOR_SCALED; | |
} | |
} | |
fread(&rstruc->password[0], 11, 1, opty); | |
fread(&rstruc->options[0], 10, 1, opty); | |
fread(&rstruc->nummes, 2, 1, opty); | |
if (rfh.version >= 25) | |
rstruc->gameId = getw(opty); | |
if (rfh.version >= 3) | |
#ifndef ALLEGRO_BIG_ENDIAN | |
fread(&rstruc->msgi[0], sizeof(MessageInfo), rstruc->nummes, opty); | |
#else | |
{ | |
for (int iteratorCount = 0; iteratorCount < rstruc->nummes; ++iteratorCount) | |
{ | |
rstruc->msgi[iteratorCount].ReadFromFile(opty); | |
} | |
} | |
#endif | |
else | |
memset(&rstruc->msgi[0], 0, sizeof(MessageInfo) * MAXMESS); | |
for (f = 0;f < rstruc->nummes; f++) { | |
if (rfh.version >= 22) | |
read_string_decrypt(opty, buffre); | |
else | |
fgetstring_limit(buffre, opty, 2999); | |
rstruc->message[f] = (char *)malloc(strlen(buffre) + 2); | |
strcpy(rstruc->message[f], buffre); | |
if (buffre[strlen(buffre)-1] == (char)200) { | |
rstruc->message[f][strlen(buffre)-1] = 0; | |
rstruc->msgi[f].flags |= MSG_DISPLAYNEXT; | |
} | |
} | |
rstruc->numanims = 0; | |
if (rfh.version >= 6) { | |
fread(&rstruc->numanims, 2, 1, opty); | |
if (rstruc->numanims > 0) | |
fseek (opty, sizeof(FullAnimation) * rstruc->numanims, SEEK_CUR); | |
// fread(&rstruc->anims[0], sizeof(FullAnimation), rstruc->numanims, opty); | |
} | |
else { | |
rstruc->numanims = 0; | |
memset(&rstruc->anims[0], 0, sizeof(FullAnimation) * MAXANIMS); | |
} | |
if ((rfh.version >= 4) && (rfh.version < 16)) { | |
load_script_configuration(opty); | |
load_graphical_scripts(opty, rstruc); | |
} | |
if (rfh.version >= 8) | |
fread(&rstruc->shadinginfo[0], sizeof(short), 16, opty); | |
if (rfh.version >= 21) { | |
fread (&rstruc->regionLightLevel[0], sizeof(short), rstruc->numRegions, opty); | |
fread (&rstruc->regionTintLevel[0], sizeof(int), rstruc->numRegions, opty); | |
} | |
update_polled_stuff(); | |
if (rfh.version >= 5) { | |
tesl = load_lzw(opty, rstruc->ebscene[0], rstruc->pal); | |
rstruc->ebscene[0] = recalced; | |
} | |
else | |
tesl = loadcompressed_allegro(opty, &rstruc->ebscene[0], rstruc->pal, ftell(opty)); | |
if ((rstruc->ebscene[0]->w > 320) & (rfh.version < 11)) | |
rstruc->resolution = 2; | |
update_polled_stuff(); | |
if (rfh.version >= 21) | |
tesl = loadcompressed_allegro(opty, &rstruc->regions, rstruc->pal, tesl); | |
else if (rfh.version >= 8) { | |
tesl = loadcompressed_allegro(opty, &rstruc->regions, rstruc->pal, tesl); | |
// an old version - clear the 'shadow' area into a blank regions bmp | |
wfreeblock (rstruc->regions); | |
rstruc->regions = NULL; | |
} | |
update_polled_stuff(); | |
tesl = loadcompressed_allegro(opty, &rstruc->walls, rstruc->pal, tesl); | |
update_polled_stuff(); | |
tesl = loadcompressed_allegro(opty, &rstruc->object, rstruc->pal, tesl); | |
update_polled_stuff(); | |
tesl = loadcompressed_allegro(opty, &rstruc->lookat, rstruc->pal, tesl); | |
if (rfh.version < 21) { | |
// Old version - copy walkable areas to Regions | |
if (rstruc->regions == NULL) | |
rstruc->regions = create_bitmap_ex (8, rstruc->walls->w, rstruc->walls->h); | |
clear (rstruc->regions); | |
blit (rstruc->walls, rstruc->regions, 0, 0, 0, 0, rstruc->regions->w, rstruc->regions->h); | |
for (f = 0; f <= 15; f++) { | |
rstruc->regionLightLevel[f] = rstruc->walk_area_light[f]; | |
rstruc->regionTintLevel[f] = 0; | |
} | |
} | |
if (rfh.version < 9) { | |
for (f = 0; f < 11; f++) | |
rstruc->password[f] += 60; | |
} | |
else { | |
for (f = 0; f < 11; f++) | |
rstruc->password[f] += passwencstring[f]; | |
} | |
} | |
void load_room(char *files, roomstruct *rstruc, bool gameIsHighRes) { | |
FILE *opty; | |
room_file_header rfh; | |
int i; | |
rstruc->freemessage(); | |
if (rstruc->scripts != NULL) { | |
free(rstruc->scripts); | |
rstruc->scripts = NULL; | |
} | |
if (rstruc->compiled_script != NULL) | |
ccFreeScript(rstruc->compiled_script); | |
rstruc->compiled_script = NULL; | |
if (rstruc->num_bscenes > 1) { | |
int ff; | |
for (ff = 1; ff < rstruc->num_bscenes; ff++) { | |
wfreeblock(rstruc->ebscene[ff]); | |
rstruc->ebscene[ff] = NULL; | |
} | |
update_polled_stuff(); | |
} | |
rstruc->num_bscenes = 1; | |
rstruc->bscene_anim_speed = 5; | |
memset (&rstruc->objectnames[0][0], 0, MAX_INIT_SPR * MAXOBJNAMELEN); | |
memset (&rstruc->objectscriptnames[0][0], 0, MAX_INIT_SPR * MAX_SCRIPT_NAME_LEN); | |
memset (&rstruc->regionLightLevel[0], 0, sizeof(short) * MAX_REGIONS); | |
memset (&rstruc->regionTintLevel[0], 0, sizeof(int) * MAX_REGIONS); | |
for (i = 0; i <= MAX_WALK_AREAS; i++) { | |
rstruc->walk_area_zoom2[i] = NOT_VECTOR_SCALED; | |
rstruc->walk_area_top[i] = -1; | |
rstruc->walk_area_bottom[i] = -1; | |
} | |
for (i = 0; i < rstruc->numhotspots; i++) | |
rstruc->hsProps[i].reset(); | |
for (i = 0; i < rstruc->numsprs; i++) | |
rstruc->objProps[i].reset(); | |
rstruc->roomProps.reset(); | |
if (rstruc->roomScripts != NULL) | |
{ | |
delete rstruc->roomScripts; | |
rstruc->roomScripts = NULL; | |
} | |
if (rstruc->hotspotScripts != NULL) | |
{ | |
for (i = 0; i < rstruc->lastLoadNumHotspots; i++) | |
{ | |
delete rstruc->hotspotScripts[i]; | |
} | |
delete[] rstruc->hotspotScripts; | |
rstruc->hotspotScripts = NULL; | |
} | |
if (rstruc->objectScripts != NULL) | |
{ | |
for (i = 0; i < rstruc->lastLoadNumObjects; i++) | |
{ | |
delete rstruc->objectScripts[i]; | |
} | |
delete[] rstruc->objectScripts; | |
rstruc->objectScripts = NULL; | |
} | |
if (rstruc->regionScripts != NULL) | |
{ | |
for (i = 0; i < rstruc->lastLoadNumRegions; i++) | |
{ | |
delete rstruc->regionScripts[i]; | |
} | |
delete[] rstruc->regionScripts; | |
rstruc->regionScripts = NULL; | |
} | |
if (rstruc->localvars != NULL) | |
free (rstruc->localvars); | |
rstruc->localvars = NULL; | |
rstruc->numLocalVars = 0; | |
memset(&rstruc->ebpalShared[0], 0, MAX_BSCENE); | |
update_polled_stuff(); | |
opty = clibfopen(files, "rb"); | |
if (opty == NULL) { | |
char errbuffr[500]; | |
sprintf(errbuffr,"Load_room: Unable to load the room file '%s'\n" | |
"Make sure that you saved the room to the correct folder (it should be\n" | |
"in your game's sub-folder of the AGS directory).\n" | |
"Also check that the player character's starting room is set correctly.\n",files); | |
quit(errbuffr); | |
} | |
update_polled_stuff(); // it can take a while to load the file sometimes | |
#ifndef ALLEGRO_BIG_ENDIAN | |
fread(&rfh, sizeof(rfh), 1, opty); | |
#else | |
rfh.ReadFromFile(opty); | |
#endif | |
//fclose(opty); | |
rstruc->wasversion = rfh.version; | |
#ifdef THIS_IS_THE_ENGINE | |
if ((rstruc->wasversion < 17) | (rstruc->wasversion > ROOM_FILE_VERSION)) | |
#else | |
if ((rstruc->wasversion < 15) || (rstruc->wasversion > ROOM_FILE_VERSION)) | |
#endif | |
{ | |
fclose(opty); | |
quit("Load_Room: Bad packed file. Either the file requires a newer or older version of\n" | |
"this program or the file is corrupt.\n"); | |
} | |
int thisblock = 0; | |
int bloklen; | |
FILE *optywas; | |
while (thisblock != BLOCKTYPE_EOF) { | |
update_polled_stuff(); | |
thisblock = fgetc(opty); | |
if (thisblock == BLOCKTYPE_EOF) | |
break; | |
fread(&bloklen, 4, 1, opty); | |
bloklen += ftell(opty); // make it the new position for after block read | |
optywas = opty; | |
if (thisblock == BLOCKTYPE_MAIN) | |
load_main_block(rstruc, files, opty, rfh); | |
else if (thisblock == BLOCKTYPE_SCRIPT) { | |
int lee; | |
int hh; | |
fread(&lee, 4, 1, opty); | |
rstruc->scripts = (char *)malloc(lee + 5); | |
// MACPORT FIX: swap | |
fread(rstruc->scripts, sizeof(char), lee, opty); | |
rstruc->scripts[lee] = 0; | |
for (hh = 0; hh < lee; hh++) | |
rstruc->scripts[hh] += passwencstring[hh % 11]; | |
} | |
else if (thisblock == BLOCKTYPE_COMPSCRIPT3) { | |
rstruc->compiled_script = fread_script(opty); | |
if (rstruc->compiled_script == NULL) | |
quit("Load_room: Script load failed; need newer version?"); | |
} | |
else if ((thisblock == BLOCKTYPE_COMPSCRIPT) || (thisblock == BLOCKTYPE_COMPSCRIPT2)) | |
#ifdef LOADROOM_ALLOWOLD | |
rstruc->compiled_script = NULL; | |
#else | |
quit("Load_room: old room format. Please upgrade the room."); | |
#endif | |
else if (thisblock == BLOCKTYPE_OBJECTNAMES) { | |
if (fgetc(opty) != rstruc->numsprs) | |
quit("Load_room: inconsistent blocks for object names"); | |
fread(&rstruc->objectnames[0][0], MAXOBJNAMELEN, rstruc->numsprs, opty); | |
} | |
else if (thisblock == BLOCKTYPE_OBJECTSCRIPTNAMES) { | |
if (fgetc(opty) != rstruc->numsprs) | |
quit("Load_room: inconsistent blocks for object script names"); | |
fread(&rstruc->objectscriptnames[0][0], MAX_SCRIPT_NAME_LEN, rstruc->numsprs, opty); | |
} | |
else if (thisblock == BLOCKTYPE_ANIMBKGRND) { | |
int ct; | |
long fpos; | |
rstruc->num_bscenes = fgetc(opty); | |
rstruc->bscene_anim_speed = fgetc(opty); | |
if (rfh.version >= 20) | |
fread(&rstruc->ebpalShared[0], 1, rstruc->num_bscenes, opty); | |
else | |
memset (&rstruc->ebpalShared[0], 0, rstruc->num_bscenes); | |
fpos = ftell(opty); | |
// fclose(opty); | |
for (ct = 1; ct < rstruc->num_bscenes; ct++) { | |
update_polled_stuff(); | |
// fpos = load_lzw(files,rstruc->ebscene[ct],rstruc->pal,fpos); | |
fpos = load_lzw(opty, rstruc->ebscene[ct], rstruc->bpalettes[ct]); | |
rstruc->ebscene[ct] = recalced; | |
} | |
// opty = clibfopen(files, "rb"); | |
// fseek(opty, fpos, SEEK_SET); | |
} | |
else if (thisblock == BLOCKTYPE_PROPERTIES) { | |
// Read custom properties | |
if (getw(opty) != 1) | |
quit("LoadRoom: unknown Custom Properties block encounreted"); | |
int errors = 0, gg; | |
if (rstruc->roomProps.UnSerialize (opty)) | |
quit("LoadRoom: error reading custom properties block"); | |
for (gg = 0; gg < rstruc->numhotspots; gg++) | |
errors += rstruc->hsProps[gg].UnSerialize (opty); | |
for (gg = 0; gg < rstruc->numsprs; gg++) | |
errors += rstruc->objProps[gg].UnSerialize (opty); | |
if (errors > 0) | |
quit("LoadRoom: errors encountered reading custom props"); | |
} | |
else if (thisblock == -1) | |
{ | |
fclose(opty); | |
quit("LoadRoom: unexpected end of file while loading room"); | |
return; | |
} | |
else { | |
char tempbfr[90]; | |
sprintf(tempbfr, "LoadRoom: unknown block type %d encountered in '%s'", thisblock, files); | |
quit(tempbfr); | |
} | |
// The ftell call below has caused crashes | |
if (ftell(opty) != bloklen) | |
fseek(opty, bloklen, SEEK_SET); | |
} | |
// sync bpalettes[0] with room.pal | |
memcpy (&rstruc->bpalettes[0][0], &rstruc->pal[0], sizeof(color) * 256); | |
fclose(opty); | |
if ((rfh.version < 29) && (gameIsHighRes)) | |
{ | |
// Pre-3.0.3, multiply up co-ordinates | |
// If you change this, also change convert_room_coordinates_to_low_res | |
// function in the engine | |
int f; | |
for (f = 0; f < rstruc->numsprs; f++) | |
{ | |
rstruc->sprs[f].x *= 2; | |
rstruc->sprs[f].y *= 2; | |
if (rstruc->objbaseline[f] > 0) | |
{ | |
rstruc->objbaseline[f] *= 2; | |
} | |
} | |
for (f = 0; f < rstruc->numhotspots; f++) | |
{ | |
rstruc->hswalkto[f].x *= 2; | |
rstruc->hswalkto[f].y *= 2; | |
} | |
for (f = 0; f < rstruc->numobj; f++) | |
{ | |
rstruc->objyval[f] *= 2; | |
} | |
rstruc->left *= 2; | |
rstruc->top *= 2; | |
rstruc->bottom *= 2; | |
rstruc->right *= 2; | |
rstruc->width *= 2; | |
rstruc->height *= 2; | |
} | |
} | |
#endif // NOFUNCTIONS | |
#pragma pack(1) | |
struct ScriptEvent { | |
long type PCKD; // eg. display message, or if is less | |
char sort PCKD; | |
long _using PCKD; // ^var1 | |
long with PCKD; // number 3 than 9 | |
long data PCKD; | |
long branchto PCKD; | |
long screeny PCKD; | |
void settype(long); | |
}; | |
#define MAXINBLOCK 10 | |
struct ScriptBlock { | |
long numevents PCKD; | |
ScriptEvent events[MAXINBLOCK] PCKD; | |
}; | |
#pragma pack() | |
#define VFLG_FLIPSPRITE 1 | |
struct ViewFrame { | |
int pic; | |
short xoffs, yoffs; | |
short speed; | |
int flags; | |
int sound; // play sound when this frame comes round | |
int reserved_for_future[2]; | |
ViewFrame() { pic = 0; xoffs = 0; yoffs = 0; speed = 0; } | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
pic = getw(fp); | |
xoffs = __getshort__bigendian(fp); | |
yoffs = __getshort__bigendian(fp); | |
speed = __getshort__bigendian(fp); | |
fseek(fp, 2, SEEK_CUR); | |
flags = getw(fp); | |
sound = getw(fp); | |
reserved_for_future[0] = getw(fp); | |
reserved_for_future[1] = getw(fp); | |
} | |
#else | |
void ReadFromFile(FILE *fp) | |
{ | |
pic = getw(fp); | |
fread(&xoffs, 2, 1, fp); | |
fread(&yoffs, 2, 1, fp); | |
fread(&speed, 2, 1, fp); | |
fseek(fp, 2, SEEK_CUR); | |
flags = getw(fp); | |
sound = getw(fp); | |
reserved_for_future[0] = getw(fp); | |
reserved_for_future[1] = getw(fp); | |
} | |
#endif | |
}; | |
#define LOOPFLAG_RUNNEXTLOOP 1 | |
struct ViewLoopNew | |
{ | |
short numFrames; | |
int flags; | |
ViewFrame *frames; | |
bool RunNextLoop() | |
{ | |
return (flags & LOOPFLAG_RUNNEXTLOOP); | |
} | |
void Initialize(int frameCount); | |
void Dispose(); | |
void WriteToFile(FILE *ooo); | |
void ReadFromFile(FILE *iii); | |
}; | |
struct ViewStruct | |
{ | |
short numLoops; | |
ViewLoopNew *loops; | |
void Initialize(int loopCount); | |
void Dispose(); | |
void WriteToFile(FILE *ooo); | |
void ReadFromFile(FILE *iii); | |
}; | |
#ifndef CROOM_NOFUNCTIONS | |
void ViewStruct::Initialize(int loopCount) | |
{ | |
numLoops = loopCount; | |
if (numLoops > 0) | |
{ | |
loops = (ViewLoopNew*)calloc(numLoops, sizeof(ViewLoopNew)); | |
} | |
} | |
void ViewStruct::Dispose() | |
{ | |
if (numLoops > 0) | |
{ | |
free(loops); | |
numLoops = 0; | |
} | |
} | |
void ViewStruct::WriteToFile(FILE *ooo) | |
{ | |
putshort(numLoops, ooo); | |
for (int i = 0; i < numLoops; i++) | |
{ | |
loops[i].WriteToFile(ooo); | |
} | |
} | |
void ViewStruct::ReadFromFile(FILE *iii) | |
{ | |
#ifdef ALLEGRO_BIG_ENDIAN | |
Initialize(__getshort__bigendian(fp)); | |
#else | |
Initialize(getshort(iii)); | |
#endif | |
for (int i = 0; i < numLoops; i++) | |
{ | |
loops[i].ReadFromFile(iii); | |
} | |
} | |
void ViewLoopNew::Initialize(int frameCount) | |
{ | |
numFrames = frameCount; | |
flags = 0; | |
frames = (ViewFrame*)calloc(numFrames + 1, sizeof(ViewFrame)); | |
} | |
void ViewLoopNew::Dispose() | |
{ | |
if (frames != NULL) | |
{ | |
free(frames); | |
frames = NULL; | |
numFrames = 0; | |
} | |
} | |
void ViewLoopNew::WriteToFile(FILE *ooo) | |
{ | |
fwrite(&numFrames, sizeof(short), 1, ooo); | |
fwrite(&flags, sizeof(int), 1, ooo); | |
fwrite(frames, sizeof(ViewFrame), numFrames, ooo); | |
} | |
void ViewLoopNew::ReadFromFile(FILE *iii) | |
{ | |
#ifdef ALLEGRO_BIG_ENDIAN | |
STEVE PLEASE VALIDATE THAT THIS CODE IS OK | |
Initialize(__getshort__bigendian(fp)); | |
flags = getw(iii); | |
for (int i = 0; i < numFrames; ++i) | |
{ | |
frames[i].ReadFromFile(iii); | |
} | |
#else | |
Initialize(getshort(iii)); | |
flags = getw(iii); | |
fread(frames, sizeof(ViewFrame), numFrames, iii); | |
#endif | |
// an extra frame is allocated in memory to prevent | |
// crashes with empty loops -- set its picture to teh BLUE CUP!! | |
frames[numFrames].pic = 0; | |
} | |
#endif | |
struct ViewStruct272 { | |
short numloops; | |
short numframes[16]; | |
int loopflags[16]; | |
ViewFrame frames[16][20]; | |
ViewStruct272() { numloops = 0; numframes[0] = 0; } | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
numloops = __getshort__bigendian(fp); | |
for (int i = 0; i < 16; ++i) | |
{ | |
numframes[i] = __getshort__bigendian(fp); | |
} | |
// skip padding if there is any | |
fseek(fp, 2*(2 - ((16+1)%2)), SEEK_CUR); | |
fread(loopflags, sizeof(int), 16, fp); | |
for (int j = 0; j < 16; ++j) | |
{ | |
for (int i = 0; i < 20; ++i) | |
{ | |
frames[j][i].ReadFromFile(fp); | |
} | |
} | |
} | |
#else | |
void ReadFromFile(FILE *fp) | |
{ | |
fread(&numloops, 2, 1, fp); | |
for (int i = 0; i < 16; ++i) | |
{ | |
fread(&numframes[i], 2, 1, fp); | |
} | |
fseek(fp, 2*(2 - ((16+1)%2)), SEEK_CUR); | |
fread(loopflags, sizeof(int), 16, fp); | |
for (int j = 0; j < 16; ++j) | |
{ | |
for (int i = 0; i < 20; ++i) | |
{ | |
frames[j][i].ReadFromFile(fp); | |
} | |
} | |
} | |
#endif | |
}; | |
#define MCF_ANIMMOVE 1 | |
#define MCF_DISABLED 2 | |
#define MCF_STANDARD 4 | |
#define MCF_HOTSPOT 8 // only animate when over hotspot | |
// this struct is also in the plugin header file | |
struct MouseCursor { | |
int pic; | |
short hotx, hoty; | |
short view; | |
char name[10]; | |
char flags; | |
MouseCursor() { pic = 2054; hotx = 0; hoty = 0; name[0] = 0; flags = 0; view = -1; } | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
pic = getw(fp); | |
hotx = __getshort__bigendian(fp); | |
hoty = __getshort__bigendian(fp); | |
view = __getshort__bigendian(fp); | |
// may need to read padding? | |
fread(name, sizeof(char), 10, fp); | |
flags = getc(fp); | |
fseek(fp, 3, SEEK_CUR); | |
} | |
#endif | |
}; | |
#define MAX_INV 301 | |
#define CHF_MANUALSCALING 1 | |
#define CHF_FIXVIEW 2 // between SetCharView and ReleaseCharView | |
#define CHF_NOINTERACT 4 | |
#define CHF_NODIAGONAL 8 | |
#define CHF_ALWAYSIDLE 0x10 | |
#define CHF_NOLIGHTING 0x20 | |
#define CHF_NOTURNING 0x40 | |
#define CHF_NOWALKBEHINDS 0x80 | |
#define CHF_FLIPSPRITE 0x100 // ?? Is this used?? | |
#define CHF_NOBLOCKING 0x200 | |
#define CHF_SCALEMOVESPEED 0x400 | |
#define CHF_NOBLINKANDTHINK 0x800 | |
#define CHF_SCALEVOLUME 0x1000 | |
#define CHF_HASTINT 0x2000 // engine only | |
#define CHF_BEHINDSHEPHERD 0x4000 // engine only | |
#define CHF_AWAITINGMOVE 0x8000 // engine only | |
#define CHF_MOVENOTWALK 0x10000 // engine only - do not do walk anim | |
#define CHF_ANTIGLIDE 0x20000 | |
// Speechcol is no longer part of the flags as of v2.5 | |
#define OCHF_SPEECHCOL 0xff000000 | |
#define OCHF_SPEECHCOLSHIFT 24 | |
#define UNIFORM_WALK_SPEED 0 | |
#define FOLLOW_ALWAYSONTOP 0x7ffe | |
// remember - if change this struct, also change AGSDEFNS.SH and | |
// plugin header file struct | |
struct CharacterInfo { | |
int defview; | |
int talkview; | |
int view; | |
int room, prevroom; | |
int x, y, wait; | |
int flags; | |
short following; | |
short followinfo; | |
int idleview; // the loop will be randomly picked | |
short idletime, idleleft; // num seconds idle before playing anim | |
short transparency; // if character is transparent | |
short baseline; | |
int activeinv; | |
int talkcolor; | |
int thinkview; | |
short blinkview, blinkinterval; // design time | |
short blinktimer, blinkframe; // run time | |
short walkspeed_y, pic_yoffs; | |
int z; // z-location, for flying etc | |
int walkwait; | |
short speech_anim_speed, reserved1; // only 1 reserved left!! | |
short blocking_width, blocking_height; | |
int index_id; // used for object functions to know the id | |
short pic_xoffs, walkwaitcounter; | |
short loop, frame; | |
short walking, animating; | |
short walkspeed, animspeed; | |
short inv[MAX_INV]; | |
short actx, acty; | |
char name[40]; | |
char scrname[MAX_SCRIPT_NAME_LEN]; | |
char on; | |
int get_effective_y(); // return Y - Z | |
int get_baseline(); // return baseline, or Y if not set | |
int get_blocking_top(); // return Y - BlockingHeight/2 | |
int get_blocking_bottom(); // return Y + BlockingHeight/2 | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
defview = getw(fp); | |
talkview = getw(fp); | |
view = getw(fp); | |
room = getw(fp); | |
prevroom = getw(fp); | |
x = getw(fp); | |
y = getw(fp); | |
wait = getw(fp); | |
flags = getw(fp); | |
following = __getshort__bigendian(fp); | |
followinfo = __getshort__bigendian(fp); | |
idleview = getw(fp); | |
idletime = __getshort__bigendian(fp); | |
idleleft = __getshort__bigendian(fp); | |
transparency = __getshort__bigendian(fp); | |
baseline = __getshort__bigendian(fp); | |
activeinv = getw(fp); | |
talkcolor = getw(fp); | |
thinkview = getw(fp); | |
blinkview = __getshort__bigendian(fp); | |
blinkinterval = __getshort__bigendian(fp); | |
blinktimer = __getshort__bigendian(fp); | |
blinkframe = __getshort__bigendian(fp); | |
walkspeed_y = __getshort__bigendian(fp); | |
pic_yoffs = __getshort__bigendian(fp); | |
z = getw(fp); | |
reserved[0] = getw(fp); | |
reserved[1] = getw(fp); | |
blocking_width = __getshort__bigendian(fp); | |
blocking_height = __getshort__bigendian(fp);; | |
index_id = getw(fp); | |
pic_xoffs = __getshort__bigendian(fp); | |
walkwaitcounter = __getshort__bigendian(fp); | |
loop = __getshort__bigendian(fp); | |
frame = __getshort__bigendian(fp); | |
walking = __getshort__bigendian(fp); | |
animating = __getshort__bigendian(fp); | |
walkspeed = __getshort__bigendian(fp); | |
animspeed = __getshort__bigendian(fp); | |
fread(inv, sizeof(short), MAX_INV, fp); | |
actx = __getshort__bigendian(fp); | |
acty = __getshort__bigendian(fp); | |
fread(name, sizeof(char), 40, fp); | |
fread(scrname, sizeof(char), MAX_SCRIPT_NAME_LEN, fp); | |
on = getc(fp); | |
// MAX_INV is odd, so need to sweep up padding | |
// skip over padding that makes struct a multiple of 4 bytes long | |
fseek(fp, 4 - (((MAX_INV+2)*sizeof(short)+40+MAX_SCRIPT_NAME_LEN+1)%4), SEEK_CUR); | |
} | |
#endif | |
}; | |
struct OldCharacterInfo { | |
int defview; | |
int talkview; | |
int view; | |
int room, prevroom; | |
int x, y, wait; | |
int flags; | |
short following; | |
short followinfo; | |
int idleview; // the loop will be randomly picked | |
short idletime, idleleft; // num seconds idle before playing anim | |
short transparency; // if character is transparent | |
short baseline; | |
int activeinv; // this is an INT to support SeeR (no signed shorts) | |
short loop, frame; | |
short walking, animating; | |
short walkspeed, animspeed; | |
short inv[100]; | |
short actx, acty; | |
char name[30]; | |
char scrname[16]; | |
char on; | |
}; | |
#define IFLG_STARTWITH 1 | |
struct InventoryItemInfo { | |
char name[25]; | |
int pic; | |
int cursorPic, hotx, hoty; | |
int reserved[5]; | |
char flags; | |
#ifdef ALLEGRO_BIG_ENDIAN | |
void ReadFromFile(FILE *fp) | |
{ | |
fread(name, sizeof(char), 25, fp); | |
fseek(fp, 3, SEEK_CUR); | |
pic = getw(fp); | |
cursor = getw(fp); | |
hotx = getw(fp); | |
hoty = getw(fp); | |
fread(reserved, sizeof(int), 5, fp); | |
flags = getc(fp); | |
fseek(fp, 3, SEEK_CUR); | |
} | |
#endif | |
}; | |
#define MAXTOPICOPTIONS 30 | |
#define DFLG_ON 1 // currently enabled | |
#define DFLG_OFFPERM 2 // off forever (can't be trurned on) | |
#define DFLG_NOREPEAT 4 // character doesn't repeat it when clicked | |
#define DFLG_HASBEENCHOSEN 8 // dialog option is 'read' | |
#define DTFLG_SHOWPARSER 1 // show parser in this topic | |
#define DCMD_SAY 1 | |
#define DCMD_OPTOFF 2 | |
#define DCMD_OPTON 3 | |
#define DCMD_RETURN 4 | |
#define DCMD_STOPDIALOG 5 | |
#define DCMD_OPTOFFFOREVER 6 | |
#define DCMD_RUNTEXTSCRIPT 7 | |
#define DCMD_GOTODIALOG 8 | |
#define DCMD_PLAYSOUND 9 | |
#define DCMD_ADDINV 10 | |
#define DCMD_SETSPCHVIEW 11 | |
#define DCMD_NEWROOM 12 | |
#define DCMD_SETGLOBALINT 13 | |
#define DCMD_GIVESCORE 14 | |
#define DCMD_GOTOPREVIOUS 15 | |
#define DCMD_LOSEINV 16 | |
#define DCMD_ENDSCRIPT 0xff | |
#define DCHAR_NARRATOR 999 | |
#define DCHAR_PLAYER 998 | |
#define MAX_DIALOG 500 | |
struct DialogTopic { | |
char optionnames[MAXTOPICOPTIONS][150]; | |
int optionflags[MAXTOPICOPTIONS]; | |
unsigned char *optionscripts; | |
short entrypoints[MAXTOPICOPTIONS]; | |
short startupentrypoint; | |
short codesize; | |
int numoptions; | |
int topicFlags; | |
void ReadFromFile(FILE *fp) | |
{ | |
fread(optionnames, 150*sizeof(char), MAXTOPICOPTIONS, fp); | |
fread(optionflags, sizeof(int), MAXTOPICOPTIONS, fp); | |
optionscripts = (unsigned char *) getw(fp); | |
fread(entrypoints, sizeof(short), MAXTOPICOPTIONS, fp); | |
startupentrypoint = __getshort__bigendian(fp); | |
codesize = __getshort__bigendian(fp); | |
numoptions = getw(fp); | |
topicFlags = getw(fp); | |
} | |
}; | |
#define MAX_SPRITES 30000 | |
#define MAX_CURSOR 20 | |
#define PAL_GAMEWIDE 0 | |
#define PAL_LOCKED 1 | |
#define PAL_BACKGROUND 2 | |
#define MAXGLOBALMES 500 | |
#define MAXLANGUAGE 5 | |
#define MAX_FONTS 15 | |
#define OPT_DEBUGMODE 0 | |
#define OPT_SCORESOUND 1 | |
#define OPT_WALKONLOOK 2 | |
#define OPT_DIALOGIFACE 3 | |
#define OPT_ANTIGLIDE 4 | |
#define OPT_TWCUSTOM 5 | |
#define OPT_DIALOGGAP 6 | |
#define OPT_NOSKIPTEXT 7 | |
#define OPT_DISABLEOFF 8 | |
#define OPT_ALWAYSSPCH 9 | |
#define OPT_SPEECHTYPE 10 | |
#define OPT_PIXPERFECT 11 | |
#define OPT_NOWALKMODE 12 | |
#define OPT_LETTERBOX 13 | |
#define OPT_FIXEDINVCURSOR 14 | |
#define OPT_NOLOSEINV 15 | |
#define OPT_NOSCALEFNT 16 | |
#define OPT_SPLITRESOURCES 17 | |
#define OPT_ROTATECHARS 18 | |
#define OPT_FADETYPE 19 | |
#define OPT_HANDLEINVCLICKS 20 | |
#define OPT_MOUSEWHEEL 21 | |
#define OPT_DIALOGNUMBERED 22 | |
#define OPT_DIALOGUPWARDS 23 | |
#define OPT_CROSSFADEMUSIC 24 | |
#define OPT_ANTIALIASFONTS 25 | |
#define OPT_THOUGHTGUI 26 | |
#define OPT_TURNTOFACELOC 27 | |
#define OPT_RIGHTLEFTWRITE 28 // right-to-left text writing | |
#define OPT_DUPLICATEINV 29 // if they have 2 of the item, draw it twice | |
#define OPT_SAVESCREENSHOT 30 | |
#define OPT_PORTRAITSIDE 31 | |
#define OPT_STRICTSCRIPTING 32 // don't allow MoveCharacter-style commands | |
#define OPT_LEFTTORIGHTEVAL 33 // left-to-right operator evaluation | |
#define OPT_COMPRESSSPRITES 34 | |
#define OPT_STRICTSTRINGS 35 // don't allow old-style strings | |
#define OPT_NEWGUIALPHA 36 | |
#define OPT_RUNGAMEDLGOPTS 37 | |
#define OPT_NATIVECOORDINATES 38 | |
#define OPT_OLDTALKANIMSPD 39 | |
#define OPT_HIGHESTOPTION 39 | |
#define OPT_NOMODMUSIC 98 | |
#define OPT_LIPSYNCTEXT 99 | |
#define PORTRAIT_LEFT 0 | |
#define PORTRAIT_RIGHT 1 | |
#define PORTRAIT_ALTERNATE 2 | |
#define PORTRAIT_XPOSITION 3 | |
#define FADE_NORMAL 0 | |
#define FADE_INSTANT 1 | |
#define FADE_DISSOLVE 2 | |
#define FADE_BOXOUT 3 | |
#define FADE_CROSSFADE 4 | |
#define FADE_LAST 4 // this should equal the last one | |
#define SPF_640x400 1 | |
#define SPF_HICOLOR 2 | |
#define SPF_DYNAMICALLOC 4 | |
#define SPF_TRUECOLOR 8 | |
#define SPF_ALPHACHANNEL 0x10 | |
#define SPF_HADALPHACHANNEL 0x80 // the saved sprite on disk has one | |
//#define FFLG_NOSCALE 1 | |
#define FFLG_SIZEMASK 0x003f | |
#define FONT_OUTLINE_AUTO -10 | |
#define MAX_FONT_SIZE 63 | |
struct OriGameSetupStruct { | |
char gamename[30]; | |
char options[20]; | |
unsigned char paluses[256]; | |
color defpal[256]; | |
InterfaceElement iface[10]; | |
int numiface; | |
int numviews; | |
MouseCursor mcurs[10]; | |
char *globalscript; | |
int numcharacters; | |
OldCharacterInfo *chars; | |
EventBlock __charcond[50]; | |
EventBlock __invcond[100]; | |
ccScript *compiled_script; | |
int playercharacter; | |
unsigned char __old_spriteflags[2100]; | |
int totalscore; | |
short numinvitems; | |
InventoryItemInfo invinfo[100]; | |
int numdialog, numdlgmessage; | |
int numfonts; | |
int color_depth; // in bytes per pixel (ie. 1 or 2) | |
int target_win; | |
int dialog_bullet; // 0 for none, otherwise slot num of bullet point | |
short hotdot, hotdotouter; // inv cursor hotspot dot | |
int uniqueid; // random key identifying the game | |
int reserved[2]; | |
short numlang; | |
char langcodes[MAXLANGUAGE][3]; | |
char *messages[MAXGLOBALMES]; | |
}; | |
struct OriGameSetupStruct2 : public OriGameSetupStruct { | |
unsigned char fontflags[10]; | |
char fontoutline[10]; | |
int numgui; | |
WordsDictionary *dict; | |
int reserved2[8]; | |
}; | |
struct OldGameSetupStruct : public OriGameSetupStruct2 { | |
unsigned char spriteflags[6000]; | |
}; | |
// This struct is written directly to the disk file | |
// The GameSetupStruct subclass parts are written individually | |
struct GameSetupStructBase { | |
char gamename[50]; | |
int32 options[100]; | |
unsigned char paluses[256]; | |
color defpal[256]; | |
int32 numviews; | |
int32 numcharacters; | |
int32 playercharacter; | |
int32 totalscore; | |
short numinvitems; | |
int32 numdialog, numdlgmessage; | |
int32 numfonts; | |
int32 color_depth; // in bytes per pixel (ie. 1 or 2) | |
int32 target_win; | |
int32 dialog_bullet; // 0 for none, otherwise slot num of bullet point | |
unsigned short hotdot, hotdotouter; // inv cursor hotspot dot | |
int32 uniqueid; // random key identifying the game | |
int32 numgui; | |
int32 numcursors; | |
int32 default_resolution; // 0=undefined, 1=320x200, 2=320x240, 3=640x400 etc | |
int32 default_lipsync_frame; // used for unknown chars | |
int32 invhotdotsprite; | |
int32 reserved[17]; | |
char *messages[MAXGLOBALMES]; | |
WordsDictionary *dict; | |
char *globalscript; | |
CharacterInfo *chars; | |
ccScript *compiled_script; | |
void ReadFromFile(FILE *fp) | |
{ | |
fread(&gamename[0], sizeof(char), 50, fp); | |
fseek(fp, 2, SEEK_CUR); // skip the array padding | |
fread(options, sizeof(int), 100, fp); | |
fread(&paluses[0], sizeof(unsigned char), 256, fp); | |
// colors are an array of chars | |
fread(&defpal[0], sizeof(char), sizeof(color)*256, fp); | |
numviews = getw(fp); | |
numcharacters = getw(fp); | |
playercharacter = getw(fp); | |
totalscore = getw(fp); | |
numinvitems = __getshort__bigendian(fp); | |
fseek(fp, 2, SEEK_CUR); // skip the padding | |
numdialog = getw(fp); | |
numdlgmessage = getw(fp); | |
numfonts = getw(fp); | |
color_depth = getw(fp); | |
target_win = getw(fp); | |
dialog_bullet = getw(fp); | |
hotdot = __getshort__bigendian(fp); | |
hotdotouter = __getshort__bigendian(fp); | |
uniqueid = getw(fp); | |
numgui = getw(fp); | |
numcursors = getw(fp); | |
default_resolution = getw(fp); | |
default_lipsync_frame = getw(fp); | |
invhotdotsprite = getw(fp); | |
fread(reserved, sizeof(int), 17, fp); | |
// read the final ptrs so we know to load dictionary, scripts etc | |
// 64 bit: Read 4 byte values into array of 8 byte | |
int i; | |
for (i = 0; i < MAXGLOBALMES; i++) | |
messages[i] = (char*)getw(fp); | |
dict = (WordsDictionary *) getw(fp); | |
globalscript = (char *) getw(fp); | |
chars = (CharacterInfo *) getw(fp); | |
compiled_script = (ccScript *) getw(fp); | |
} | |
}; | |
#define MAXVIEWNAMELENGTH 15 | |
#define MAXLIPSYNCFRAMES 20 | |
#define MAX_GUID_LENGTH 40 | |
#define MAX_SG_EXT_LENGTH 20 | |
#define MAX_SG_FOLDER_LEN 50 | |
struct GameSetupStruct: public GameSetupStructBase { | |
unsigned char fontflags[MAX_FONTS]; | |
char fontoutline[MAX_FONTS]; | |
unsigned char spriteflags[MAX_SPRITES]; | |
InventoryItemInfo invinfo[MAX_INV]; | |
MouseCursor mcurs[MAX_CURSOR]; | |
NewInteraction **intrChar; | |
NewInteraction *intrInv[MAX_INV]; | |
InteractionScripts **charScripts; | |
InteractionScripts **invScripts; | |
int filever; // just used by editor | |
char lipSyncFrameLetters[MAXLIPSYNCFRAMES][50]; | |
CustomPropertySchema propSchema; | |
CustomProperties *charProps, invProps[MAX_INV]; | |
char **viewNames; | |
char invScriptNames[MAX_INV][MAX_SCRIPT_NAME_LEN]; | |
char dialogScriptNames[MAX_DIALOG][MAX_SCRIPT_NAME_LEN]; | |
char guid[MAX_GUID_LENGTH]; | |
char saveGameFileExtension[MAX_SG_EXT_LENGTH]; | |
char saveGameFolderName[MAX_SG_FOLDER_LEN]; | |
int roomCount; | |
int *roomNumbers; | |
char **roomNames; | |
int audioClipCount; | |
ScriptAudioClip *audioClips; | |
int audioClipTypeCount; | |
AudioClipType *audioClipTypes; | |
}; | |
struct SpeechLipSyncLine { | |
char filename[14]; | |
int *endtimeoffs; | |
short*frame; | |
short numPhenomes; | |
}; | |
// permission flags | |
#define SMP_NOEDITINFO 1 | |
#define SMP_NOEDITSCRIPTS 2 | |
struct ScriptModule { | |
char *name; | |
char *author; | |
char *version; | |
char *description; | |
char *scriptHeader; | |
char *script; | |
int uniqueKey; | |
int permissions; | |
int weAreOwner; | |
ccScript *compiled; | |
void init() { | |
name = NULL; | |
author = NULL; | |
version = NULL; | |
description = NULL; | |
script = NULL; | |
scriptHeader = NULL; | |
uniqueKey = 0; | |
permissions = 0; | |
weAreOwner = 1; | |
compiled = NULL; | |
} | |
ScriptModule() { init(); } | |
}; | |
#ifndef CROOM_NOFUNCTIONS | |
int CharacterInfo::get_effective_y() { | |
return y - z; | |
} | |
int CharacterInfo::get_baseline() { | |
if (baseline < 1) | |
return y; | |
return baseline; | |
} | |
int CharacterInfo::get_blocking_top() { | |
if (blocking_height > 0) | |
return y - blocking_height / 2; | |
return y - 2; | |
} | |
int CharacterInfo::get_blocking_bottom() { | |
// the blocking_bottom should be 1 less than the top + height | |
// since the code does <= checks on it rather than < checks | |
if (blocking_height > 0) | |
return (y + (blocking_height + 1) / 2) - 1; | |
return y + 3; | |
} | |
#define COPY_CHAR_VAR(name) ci->name = oci->name | |
void ConvertOldCharacterToNew (OldCharacterInfo *oci, CharacterInfo *ci) { | |
COPY_CHAR_VAR (defview); | |
COPY_CHAR_VAR (talkview); | |
COPY_CHAR_VAR (view); | |
COPY_CHAR_VAR (room); | |
COPY_CHAR_VAR (prevroom); | |
COPY_CHAR_VAR (x); | |
COPY_CHAR_VAR (y); | |
COPY_CHAR_VAR (wait); | |
COPY_CHAR_VAR (flags); | |
COPY_CHAR_VAR (following); | |
COPY_CHAR_VAR (followinfo); | |
COPY_CHAR_VAR (idleview); | |
COPY_CHAR_VAR (idletime); | |
COPY_CHAR_VAR (idleleft); | |
COPY_CHAR_VAR (transparency); | |
COPY_CHAR_VAR (baseline); | |
COPY_CHAR_VAR (activeinv); | |
COPY_CHAR_VAR (loop); | |
COPY_CHAR_VAR (frame); | |
COPY_CHAR_VAR (walking); | |
COPY_CHAR_VAR (animating); | |
COPY_CHAR_VAR (walkspeed); | |
COPY_CHAR_VAR (animspeed); | |
COPY_CHAR_VAR (actx); | |
COPY_CHAR_VAR (acty); | |
COPY_CHAR_VAR (on); | |
strcpy (ci->name, oci->name); | |
strcpy (ci->scrname, oci->scrname); | |
memcpy (&ci->inv[0], &oci->inv[0], sizeof(short) * 100); | |
// move the talking colour into the struct and remove from flags | |
ci->talkcolor = (oci->flags & OCHF_SPEECHCOL) >> OCHF_SPEECHCOLSHIFT; | |
ci->flags = ci->flags & (~OCHF_SPEECHCOL); | |
} | |
void ConvertOldGameStruct (OldGameSetupStruct *ogss, GameSetupStruct *gss) { | |
int i; | |
strcpy (gss->gamename, ogss->gamename); | |
for (i = 0; i < 20; i++) | |
gss->options[i] = ogss->options[i]; | |
memcpy (&gss->paluses[0], &ogss->paluses[0], 256); | |
memcpy (&gss->defpal[0], &ogss->defpal[0], 256 * sizeof(color)); | |
gss->numviews = ogss->numviews; | |
gss->numcharacters = ogss->numcharacters; | |
gss->playercharacter = ogss->playercharacter; | |
gss->totalscore = ogss->totalscore; | |
gss->numinvitems = ogss->numinvitems; | |
gss->numdialog = ogss->numdialog; | |
gss->numdlgmessage = ogss->numdlgmessage; | |
gss->numfonts = ogss->numfonts; | |
gss->color_depth = ogss->color_depth; | |
gss->target_win = ogss->target_win; | |
gss->dialog_bullet = ogss->dialog_bullet; | |
gss->hotdot = ogss->hotdot; | |
gss->hotdotouter = ogss->hotdotouter; | |
gss->uniqueid = ogss->uniqueid; | |
gss->numgui = ogss->numgui; | |
memcpy (&gss->fontflags[0], &ogss->fontflags[0], 10); | |
memcpy (&gss->fontoutline[0], &ogss->fontoutline[0], 10); | |
memcpy (&gss->spriteflags[0], &ogss->spriteflags[0], 6000); | |
memcpy (&gss->invinfo[0], &ogss->invinfo[0], 100 * sizeof(InventoryItemInfo)); | |
memcpy (&gss->mcurs[0], &ogss->mcurs[0], 10 * sizeof(MouseCursor)); | |
for (i = 0; i < MAXGLOBALMES; i++) | |
gss->messages[i] = ogss->messages[i]; | |
gss->dict = ogss->dict; | |
gss->globalscript = ogss->globalscript; | |
gss->chars = NULL; //ogss->chars; | |
gss->compiled_script = ogss->compiled_script; | |
gss->numcursors = 10; | |
} | |
void Convert272ViewsToNew (int numof, ViewStruct272 *oldv, ViewStruct *newv) { | |
for (int a = 0; a < numof; a++) { | |
newv[a].Initialize(oldv[a].numloops); | |
for (int b = 0; b < oldv[a].numloops; b++) | |
{ | |
newv[a].loops[b].Initialize(oldv[a].numframes[b]); | |
if ((oldv[a].numframes[b] > 0) && | |
(oldv[a].frames[b][oldv[a].numframes[b] - 1].pic == -1)) | |
{ | |
newv[a].loops[b].flags = LOOPFLAG_RUNNEXTLOOP; | |
newv[a].loops[b].numFrames--; | |
} | |
else | |
newv[a].loops[b].flags = 0; | |
for (int c = 0; c < newv[a].loops[b].numFrames; c++) | |
newv[a].loops[b].frames[c] = oldv[a].frames[b][c]; | |
} | |
} | |
} | |
#endif | |
#ifndef ROOMEDIT | |
#define MAXNEEDSTAGES 40 | |
struct MoveList { | |
int pos[MAXNEEDSTAGES]; | |
int numstage; | |
fixed xpermove[MAXNEEDSTAGES], ypermove[MAXNEEDSTAGES]; | |
int fromx, fromy; | |
int onstage, onpart; | |
int lastx, lasty; | |
char doneflag; | |
char direct; // MoveCharDirect was used or not | |
}; | |
#endif | |
#endif // __CROOM_H |