1 /*
2  * OpenBOR - http://www.LavaLit.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2011 OpenBOR Team
7  */
8 
9 /* This file include all script methods used by openbor engine
10 
11  Notice: Make sure to null *pretvar when you about to return E_FAIL,
12 		 Or the engine might crash.
13 
14  Notice: Every new ScriptVariant must be initialized when you first alloc it by
15 		 ScriptVariant_Init immediately, memset it all to zero should also work by now,
16 		 unless VT_EMPTY is changed.
17 
18 		 If you want to reset a ScriptVariant to empty, you must use ScriptVariant_Clear instead.
19 		 ScriptVariant_Init or memset must be called only ONCE, later you should use ScriptVariant_Clear.
20 
21 		 Besure to call ScriptVariant_Clear if you want to use free to delete those variants.
22 
23 		 If you want to copy a ScriptVariant from another, use ScriptVariant_Copy instead of assignment,
24 		 not because it is faster, but this method is neccessary for string types.
25 
26 		 If you want to change types of an ScriptVariant, use ScriptVariant_ChangeType, don't change vt directly.
27 
28 */
29 
30 #include "openborscript.h"
31 #include "openbor.h"
32 #include "soundmix.h"
33 #include "globals.h"
34 #include "ImportCache.h"
35 #include "models.h"
36 
37 // Define macro for string mapping
38 #define MAPSTRINGS(VAR, LIST, MAXINDEX, FAILMSG) \
39 if(VAR->vt == VT_STR) { \
40 	propname = (char*)StrCache_Get(VAR->strVal); \
41 	prop = searchList(LIST, propname, MAXINDEX); \
42 	if(prop >= 0) { \
43 		ScriptVariant_ChangeType(VAR, VT_INTEGER); \
44 		VAR->lVal = prop; \
45 	} else { printf(FAILMSG, propname); } \
46 }
47 
48 extern int			  PLAYER_MIN_Z;
49 extern int			  PLAYER_MAX_Z;
50 extern int			  BGHEIGHT;
51 extern int            MAX_WALL_HEIGHT;
52 extern int			  SAMPLE_GO;
53 extern int			  SAMPLE_BEAT;
54 extern int			  SAMPLE_BLOCK;
55 extern int			  SAMPLE_INDIRECT;
56 extern int			  SAMPLE_GET;
57 extern int			  SAMPLE_GET2;
58 extern int			  SAMPLE_FALL;
59 extern int			  SAMPLE_JUMP;
60 extern int			  SAMPLE_PUNCH;
61 extern int			  SAMPLE_1UP;
62 extern int			  SAMPLE_TIMEOVER;
63 extern int			  SAMPLE_BEEP;
64 extern int			  SAMPLE_BEEP2;
65 extern int			  SAMPLE_BIKE;
66 extern int            current_palette;
67 extern s_player       player[4];
68 extern s_savedata     savedata;
69 extern s_savelevel*   savelevel;
70 extern s_savescore    savescore;
71 extern s_level        *level;
72 extern s_filestream   filestreams[LEVEL_MAX_FILESTREAMS];
73 extern entity         *self;
74 extern int            *animspecials;
75 extern int            *animattacks;
76 extern int            *animfollows;
77 extern int            *animpains;
78 extern int            *animfalls;
79 extern int            *animrises;
80 extern int            *animriseattacks;
81 extern int            *animdies;
82 extern int            *animidles;
83 extern int            *animwalks;
84 extern int            *animbackwalks;
85 extern int            *animups;
86 extern int            *animdowns;
87 extern int            noshare;
88 extern int            credits;
89 extern char           musicname[128];
90 extern float          musicfade[2];
91 extern int            musicloop;
92 extern u32            musicoffset;
93 extern int            models_cached;
94 
95 
96 extern s_sprite_list *sprite_list;
97 extern s_sprite_map *sprite_map;
98 
99 extern unsigned char* blendings[MAX_BLENDINGS];
100 extern int            current_palette;
101 s_variantnode** global_var_list = NULL;
102 Script* pcurrentscript = NULL;//used by local script functions
103 List theFunctionList;
104 static List   scriptheap;
105 static s_spawn_entry spawnentry;
106 extern const s_drawmethod plainmethod;
107 static s_drawmethod drawmethod;
108 //fake 3d draw
109 static gfx_entry	texture;
110 #define	vert_buf_size	256
111 static  vert2d		verts[vert_buf_size];
112 
113 
114 int max_global_var_index = -1;
115 
116 ScriptVariant* indexed_var_list = NULL;
117 int            max_global_vars = MAX_GLOBAL_VAR;
118 int            max_indexed_vars = 0;
119 int            max_entity_vars = 0;
120 int            max_script_vars = 0;
121 
122 
123 //this function should be called before all script methods, for once
Script_Global_Init()124 void Script_Global_Init()
125 {
126 	ptrdiff_t i;
127 	size_t csize, psize;
128 	if(max_global_vars>0)
129 	{
130 		psize = (sizeof(s_variantnode*) * max_global_vars);
131 		csize = psize + (sizeof(s_variantnode) * max_global_vars);
132 		global_var_list = calloc(1, csize);
133 		assert(global_var_list != NULL);
134 		for (i=0; i < max_global_vars; i++) {
135 			global_var_list[i] = (s_variantnode*) (((char*) global_var_list) + psize + (i * sizeof(s_variantnode)));
136 		}
137 	}
138 	/*
139 	for(i=0; i<max_global_vars; i++)
140 	{
141 		global_var_list[i] = malloc(sizeof(s_variantnode));
142 		assert(global_var_list[i] != NULL);
143 		memset(global_var_list[i], 0, sizeof(s_variantnode));
144 	} */
145 	max_global_var_index = -1;
146 	memset(&spawnentry, 0, sizeof(s_spawn_entry));//clear up the spawn entry
147 	drawmethod = plainmethod;
148 
149 	if(max_indexed_vars>0)
150 	{
151 		csize = sizeof(ScriptVariant)*(max_indexed_vars + 1);
152 		indexed_var_list = (ScriptVariant*)calloc(1, csize);
153 		assert(indexed_var_list != NULL);
154 	}
155 	List_Init(&theFunctionList);
156 	Script_LoadSystemFunctions();
157 	List_Init(&scriptheap);
158 	ImportCache_Init();
159 }
160 
_freeheapnode(void * ptr)161 void _freeheapnode(void* ptr){
162 	if(((Script*)ptr)->magic==script_magic) {
163 		Script_Clear((Script*)ptr,2);
164 	}
165 	free(ptr);
166 }
167 
168 //this function should only be called when the engine is shutting down
Script_Global_Clear()169 void Script_Global_Clear()
170 {
171 	int i, size;
172 	List_Clear(&theFunctionList);
173 	// dump all un-freed variants
174 	size = List_GetSize(&scriptheap);
175 	if(size>0) printf("\nWarning: %d script variants are not freed, dumping...\n", size);
176 	for(i=0, List_Reset(&scriptheap); i<size; List_GotoNext(&scriptheap), i++)
177 	{
178 		printf("%s\n", List_GetName(&scriptheap));
179 		_freeheapnode(List_Retrieve(&scriptheap));
180 	}
181 	List_Clear(&scriptheap);
182 	// clear the global list
183 	if(global_var_list)
184 	{
185 		for(i=0; i<max_global_vars; i++)
186 		{
187 			if(global_var_list[i] != NULL) {
188 				ScriptVariant_Clear(&(global_var_list[i]->value));
189 				//free(global_var_list[i]);
190 			}
191 			//global_var_list[i] = NULL;
192 		}
193 		free(global_var_list);
194 		global_var_list = NULL;
195 	}
196 	if(indexed_var_list)
197 	{
198 		for(i=0; i<max_indexed_vars; i++) ScriptVariant_Clear(indexed_var_list+i);
199 		free(indexed_var_list);
200 	}
201 	indexed_var_list = NULL;
202 	max_global_var_index = -1;
203 	memset(&spawnentry, 0, sizeof(s_spawn_entry));//clear up the spawn entry
204 	StrCache_Clear();
205 	ImportCache_Clear();
206 }
207 
208 
Script_Get_Global_Variant(char * theName)209 ScriptVariant* Script_Get_Global_Variant(char* theName)
210 {
211 	int i;
212 
213 	if(!theName || !theName[0]) return NULL;
214 
215 	for(i=0; i<=max_global_var_index; i++){
216 		if(!global_var_list[i]->owner &&
217 		   strcmp(theName, global_var_list[i]->key)==0)
218 			return &(global_var_list[i]->value);
219 	}
220 
221 	return NULL;
222 }
223 
224 // local function
_set_var(char * theName,ScriptVariant * var,Script * owner)225 int _set_var(char* theName, ScriptVariant* var, Script* owner)
226 {
227 	int i;
228 	s_variantnode* tempnode;
229 	if(!theName[0] || !theName || (owner && !owner->initialized)) return 0;
230 	// search the name
231 	for(i=0; i<=max_global_var_index; i++)
232 	{
233 		if(global_var_list[i]->owner == owner &&
234 		   !strcmp(theName, global_var_list[i]->key))
235 		{
236 			if(var->vt != VT_EMPTY)
237 				ScriptVariant_Copy(&(global_var_list[i]->value), var);
238 			else // set to null, so remove this value
239 			{
240 				/// re-adjust bounds, swap with last node
241 				if(i!=max_global_var_index)
242 				{
243 					tempnode = global_var_list[i];
244 					global_var_list[i] = global_var_list[max_global_var_index];
245 					global_var_list[max_global_var_index] = tempnode;
246 				}
247 				max_global_var_index--;
248 			}
249 			return 1;
250 		}
251 	}
252 	if(var->vt == VT_EMPTY) return 1;
253 	// all slots are taken
254 	if(max_global_var_index >= max_global_vars-1)
255 		return 0;
256 	// so out of bounds, find another slot
257 	else
258 	{
259 		++max_global_var_index;
260 		ScriptVariant_Copy(&(global_var_list[max_global_var_index]->value), var);
261 		global_var_list[max_global_var_index]->owner = owner;
262 		strcpy(global_var_list[max_global_var_index]->key, theName);
263 		return 1;
264 	}
265 }// end of _set_var
266 
Script_Set_Global_Variant(char * theName,ScriptVariant * var)267 int Script_Set_Global_Variant(char* theName, ScriptVariant* var)
268 {
269 	return _set_var(theName, var, NULL);
270 }
271 
Script_Local_Clear(Script * cs)272 void Script_Local_Clear(Script* cs)
273 {
274 	int i;
275 	//s_variantnode* tempnode;
276 	if(!cs) return;
277 	for(i=0; i<=max_global_var_index; i++)
278 	{
279 		if(global_var_list[i]->owner == cs)
280 		{
281 			/*
282 			printf("local var %s cleared\n", global_var_list[i]->key);
283 			if(i!=max_global_var_index)
284 			{
285 				tempnode = global_var_list[i];
286 				global_var_list[i] = global_var_list[max_global_var_index];
287 				global_var_list[max_global_var_index] = tempnode;
288 			}
289 			max_global_var_index--;*/
290 			ScriptVariant_Clear(&global_var_list[i]->value);
291 		}
292 	}
293 	if(cs->vars)
294 		for(i=0; i<max_script_vars; i++) ScriptVariant_Clear(cs->vars+i);
295 }
296 
297 
Script_Get_Local_Variant(Script * cs,char * theName)298 ScriptVariant* Script_Get_Local_Variant(Script* cs, char* theName)
299 {
300 	int i;
301 
302 	if(!cs || !cs->initialized ||
303 	   !theName || !theName[0]) return NULL;
304 
305 	for(i=0; i<=max_global_var_index; i++)
306 	{
307 		if(global_var_list[i]->owner == cs &&
308 		   strcmp(theName, global_var_list[i]->key)==0)
309 			return &(global_var_list[i]->value);
310 	}
311 
312 	return NULL;
313 }
314 
Script_Set_Local_Variant(Script * cs,char * theName,ScriptVariant * var)315 int Script_Set_Local_Variant(Script* cs, char* theName, ScriptVariant* var)
316 {
317 	if(!cs) return 0;
318 	return _set_var(theName, var, cs);
319 }
320 
alloc_script()321 Script* alloc_script()
322 {
323 	int i;
324 	Script* pscript = (Script*)calloc(1, sizeof(Script));
325 	pscript->magic = script_magic;
326 	if(max_script_vars>0)
327 	{
328 		pscript->vars = (ScriptVariant*)calloc(max_script_vars, sizeof(ScriptVariant));
329 		for(i=0; i<max_script_vars; i++) ScriptVariant_Init(pscript->vars+i);
330 	}
331 	return pscript;
332 }
333 
Script_Init(Script * pscript,char * theName,char * comment,int first)334 void Script_Init(Script* pscript, char* theName, char* comment, int first)
335 {
336 	int i;
337 	if(first)
338 	{
339 		memset(pscript, 0, sizeof(Script));
340 		pscript->magic = script_magic;
341 		if(max_script_vars>0)
342 		{
343 			pscript->vars = (ScriptVariant*)calloc(max_script_vars, sizeof(ScriptVariant));
344 			for(i=0; i<max_script_vars; i++) ScriptVariant_Init(pscript->vars+i);
345 		}
346 	}
347 	if(!theName || !theName[0])  return; // if no name specified, only alloc the variants
348 
349 	pscript->pinterpreter = (Interpreter*)malloc(sizeof(Interpreter));
350 	Interpreter_Init(pscript->pinterpreter, theName, &theFunctionList);
351 	pscript->interpreterowner = 1; // this is the owner, important
352 	pscript->initialized = 1;
353 	if(comment){
354 		pscript->comment = (char*)malloc(sizeof(char)*(strlen(comment)+1));
355 		strcpy(pscript->comment, comment);
356 	}
357 }
358 
359 //safe copy method
Script_Copy(Script * pdest,Script * psrc,int localclear)360 void Script_Copy(Script* pdest, Script* psrc, int localclear)
361 {
362 	if(!psrc->initialized) return;
363 	if(pdest->initialized) Script_Clear(pdest, localclear);
364 	pdest->pinterpreter = psrc->pinterpreter;
365 	pdest->comment = psrc->comment;
366 	pdest->interpreterowner = 0; // dont own it
367 	pdest->initialized = psrc->initialized; //just copy, it should be 1
368 }
369 
Script_Clear(Script * pscript,int localclear)370 void Script_Clear(Script* pscript, int localclear)
371 {
372 	Script* temp;
373 	int i;
374 	ScriptVariant* pvars;
375 
376 	ScriptVariant tempvar;
377 	//Execute clear method
378 	if(pscript->initialized && pscript->pinterpreter->pClearEntry){
379 		temp = pcurrentscript;
380 		pcurrentscript = pscript;
381 
382 		ScriptVariant_Init(&tempvar);
383 		ScriptVariant_ChangeType(&tempvar, VT_INTEGER);
384 		tempvar.lVal = (LONG)localclear;
385 		Script_Set_Local_Variant(pscript, "localclear", &tempvar);
386 		Interpreter_Reset(pscript->pinterpreter);
387 		pscript->pinterpreter->pCurrentInstruction = pscript->pinterpreter->pClearEntry;
388 		if(FAILED( Interpreter_EvaluateCall(pscript->pinterpreter))){
389 			shutdown(1, "Fatal: failed to execute 'clear' in script %s %s", pscript->pinterpreter->theSymbolTable.name, pscript->comment?pscript->comment:"");
390 		}
391 		pscript->pinterpreter->bReset = FALSE; // not needed, perhaps
392 		ScriptVariant_Clear(&tempvar);
393 		Script_Set_Local_Variant(pscript, "localclear", &tempvar);
394 		pcurrentscript = temp;
395 	}
396 
397 	if(localclear==2 && pscript->vars)
398 	{
399 		for(i=0; i<max_script_vars; i++)
400 		{
401 			ScriptVariant_Clear(pscript->vars+i);
402 		}
403 		free(pscript->vars);
404 		pscript->vars = NULL;
405 	}
406 	if(!pscript->initialized) return;
407 
408 	//if it is the owner, free the interpreter
409 	if(pscript->pinterpreter && pscript->interpreterowner){
410 		Interpreter_Clear(pscript->pinterpreter);
411 		free(pscript->pinterpreter);
412 		pscript->pinterpreter = NULL;
413 		if(pscript->comment) free(pscript->comment);
414 		pscript->comment = NULL;
415 	}
416 	if(localclear) Script_Local_Clear(pscript);
417 	pvars = pscript->vars; // in game clear(localclear!=2) just keep this value
418 	memset(pscript, 0, sizeof(Script));
419 	pscript->vars = pvars; // copy it back
420 }
421 
422 //append part of the script
423 //Because the script might not be initialized in 1 time.
Script_AppendText(Script * pscript,char * text,char * path)424 int Script_AppendText(Script* pscript, char* text, char* path)
425 {
426 	int success;
427 
428 	//printf(text);
429 	Interpreter_Reset(pscript->pinterpreter);
430 
431 	success = SUCCEEDED(Interpreter_ParseText(pscript->pinterpreter, text, 1, path));
432 
433 	return success;
434 }
435 
436 //return name of function from pointer to function
Script_GetFunctionName(void * functionRef)437 const char* Script_GetFunctionName(void* functionRef)
438 {
439 	if (functionRef==((void*)system_isempty)) return "isempty";
440 	else if (functionRef==((void*)system_NULL)) return "NULL";
441 	else if (functionRef==((void*)system_rand)) return "rand";
442 	else if (functionRef==((void*)system_maxglobalvarindex)) return "maxglobalvarindex";
443 	else if (functionRef==((void*)system_getglobalvar)) return "getglobalvar";
444 	else if (functionRef==((void*)system_setglobalvar)) return "setglobalvar";
445 	else if (functionRef==((void*)system_getlocalvar)) return "getlocalvar";
446 	else if (functionRef==((void*)system_setlocalvar)) return "setlocalvar";
447 	else if (functionRef==((void*)system_clearglobalvar)) return "clearglobalvar";
448 	else if (functionRef==((void*)system_clearindexedvar)) return "clearindexedvar";
449 	else if (functionRef==((void*)system_clearlocalvar)) return "clearlocalvar";
450 	else if (functionRef==((void*)system_free)) return "free";
451 	else if (functionRef==((void*)openbor_systemvariant)) return "openborvariant";
452 	else if (functionRef==((void*)openbor_changesystemvariant)) return "changeopenborvariant";
453 	else if (functionRef==((void*)openbor_drawstring)) return "drawstring";
454 	else if (functionRef==((void*)openbor_drawstringtoscreen)) return "drawstringtoscreen";
455 	else if (functionRef==((void*)openbor_log)) return "log";
456 	else if (functionRef==((void*)openbor_drawbox)) return "drawbox";
457 	else if (functionRef==((void*)openbor_drawboxtoscreen)) return "drawboxtoscreen";
458 	else if (functionRef==((void*)openbor_drawline)) return "drawline";
459 	else if (functionRef==((void*)openbor_drawlinetoscreen)) return "drawlinetoscreen";
460 	else if (functionRef==((void*)openbor_drawsprite)) return "drawsprite";
461 	else if (functionRef==((void*)openbor_drawspritetoscreen)) return "drawspritetoscreen";
462 	else if (functionRef==((void*)openbor_drawdot)) return "drawdot";
463 	else if (functionRef==((void*)openbor_drawdottoscreen)) return "drawdottoscreen";
464 	else if (functionRef==((void*)openbor_drawscreen)) return "drawscreen";
465 	else if (functionRef==((void*)openbor_changeplayerproperty)) return "changeplayerproperty";
466 	else if (functionRef==((void*)openbor_changeentityproperty)) return "changeentityproperty";
467 	else if (functionRef==((void*)openbor_getplayerproperty)) return "getplayerproperty";
468 	else if (functionRef==((void*)openbor_getentityproperty)) return "getentityproperty";
469 	else if (functionRef==((void*)openbor_tossentity)) return "tossentity";
470 	else if (functionRef==((void*)openbor_clearspawnentry)) return "clearspawnentry";
471 	else if (functionRef==((void*)openbor_setspawnentry)) return "setspawnentry";
472 	else if (functionRef==((void*)openbor_spawn)) return "spawn";
473 	else if (functionRef==((void*)openbor_projectile)) return "projectile";
474 	else if (functionRef==((void*)openbor_transconst)) return "openborconstant";
475 	else if (functionRef==((void*)openbor_playmusic)) return "playmusic";
476 	else if (functionRef==((void*)openbor_fademusic)) return "fademusic";
477 	else if (functionRef==((void*)openbor_setmusicvolume)) return "setmusicvolume";
478 	else if (functionRef==((void*)openbor_setmusictempo)) return "setmusictempo";
479 	else if (functionRef==((void*)openbor_pausemusic)) return "pausemusic";
480 	else if (functionRef==((void*)openbor_playsample)) return "playsample";
481 	else if (functionRef==((void*)openbor_loadsample)) return "loadsample";
482 	else if (functionRef==((void*)openbor_unloadsample)) return "unloadsample";
483 	else if (functionRef==((void*)openbor_fadeout)) return "fadeout";
484 	else if (functionRef==((void*)openbor_playerkeys)) return "playerkeys";
485 	else if (functionRef==((void*)openbor_changepalette)) return "changepalette";
486 	else if (functionRef==((void*)openbor_damageentity)) return "damageentity";
487 	else if (functionRef==((void*)openbor_killentity)) return "killentity";
488 	else if (functionRef==((void*)openbor_findtarget)) return "findtarget";
489 	else if (functionRef==((void*)openbor_checkrange)) return "checkrange";
490 	else if (functionRef==((void*)openbor_gettextobjproperty)) return "gettextobjproperty";
491 	else if (functionRef==((void*)openbor_changetextobjproperty)) return "changetextobjproperty";
492 	else if (functionRef==((void*)openbor_settextobj)) return "settextobj";
493 	else if (functionRef==((void*)openbor_cleartextobj)) return "cleartextobj";
494 	else if (functionRef==((void*)openbor_getlayerproperty)) return "getlayerproperty";
495 	else if (functionRef==((void*)openbor_changelayerproperty)) return "changelayerproperty";
496 	else if (functionRef==((void*)openbor_getlevelproperty)) return "getlevelproperty";
497 	else if (functionRef==((void*)openbor_changelevelproperty)) return "changelevelproperty";
498 	else if (functionRef==((void*)openbor_checkhole)) return "checkhole";
499 	else if (functionRef==((void*)openbor_checkwall)) return "checkwall";
500 	else if (functionRef==((void*)openbor_checkplatformbelow)) return "checkplatformbelow";
501 	else if (functionRef==((void*)openbor_openfilestream)) return "openfilestream";
502 	else if (functionRef==((void*)openbor_getfilestreamline)) return "getfilestreamline";
503 	else if (functionRef==((void*)openbor_getfilestreamargument)) return "getfilestreamargument";
504 	else if (functionRef==((void*)openbor_filestreamnextline)) return "filestreamnextline";
505 	else if (functionRef==((void*)openbor_getfilestreamposition)) return "getfilestreamposition";
506 	else if (functionRef==((void*)openbor_setfilestreamposition)) return "setfilestreamposition";
507 	else if (functionRef==((void*)openbor_filestreamappend)) return "filestreamappend";
508 	else if (functionRef==((void*)openbor_createfilestream)) return "createfilestream";
509 	else if (functionRef==((void*)openbor_closefilestream)) return "closefilestream";
510 	else if (functionRef==((void*)openbor_savefilestream)) return "savefilestream";
511 	else if (functionRef==((void*)openbor_getindexedvar)) return "getindexedvar";
512 	else if (functionRef==((void*)openbor_setindexedvar)) return "setindexedvar";
513 	else if (functionRef==((void*)openbor_getscriptvar)) return "getscriptvar";
514 	else if (functionRef==((void*)openbor_setscriptvar)) return "setscriptvar";
515 	else if (functionRef==((void*)openbor_getentityvar)) return "getentityvar";
516 	else if (functionRef==((void*)openbor_setentityvar)) return "setentityvar";
517 	else if (functionRef==((void*)openbor_shutdown)) return "shutdown";
518 	else if (functionRef==((void*)openbor_jumptobranch)) return "jumptobranch";
519 	else if (functionRef==((void*)openbor_changelight)) return "changelight";
520 	else if (functionRef==((void*)openbor_changeshadowcolor)) return "changeshadowcolor";
521 	else if (functionRef==((void*)openbor_bindentity)) return "bindentity";
522 	else if (functionRef==((void*)openbor_array)) return "array";
523 	else if (functionRef==((void*)openbor_size)) return "size";
524 	else if (functionRef==((void*)openbor_get)) return "get";
525 	else if (functionRef==((void*)openbor_set)) return "set";
526 	else if (functionRef==((void*)openbor_allocscreen)) return "allocscreen";
527 	else if (functionRef==((void*)openbor_clearscreen)) return "clearscreen";
528 	else if (functionRef==((void*)openbor_setdrawmethod)) return "setdrawmethod";
529 	else if (functionRef==((void*)openbor_changedrawmethod)) return "changedrawmethod";
530 	else if (functionRef==((void*)openbor_updateframe)) return "updateframe";
531 	else if (functionRef==((void*)openbor_performattack)) return "performattack";
532 	else if (functionRef==((void*)openbor_setidle)) return "setidle";
533 	else if (functionRef==((void*)openbor_getentity)) return "getentity";
534 	else if (functionRef==((void*)openbor_loadmodel)) return "loadmodel";
535 	else if (functionRef==((void*)openbor_loadsprite)) return "loadsprite";
536 	else if (functionRef==((void*)openbor_options)) return "options";
537 	else if (functionRef==((void*)openbor_playgif)) return "playgif";
538 	else if (functionRef==((void*)openbor_strinfirst)) return "strinfirst";
539 	else if (functionRef==((void*)openbor_strinlast)) return "strinlast";
540 	else if (functionRef==((void*)openbor_strleft)) return "strleft";
541 	else if (functionRef==((void*)openbor_strlength)) return "strlength";
542 	else if (functionRef==((void*)openbor_strwidth)) return "strwidth";
543 	else if (functionRef==((void*)openbor_strright)) return "strright";
544 	else if (functionRef==((void*)openbor_getmodelproperty)) return "getmodelproperty";
545 	else if (functionRef==((void*)openbor_changemodelproperty)) return "changemodelproperty";
546 	else if (functionRef==((void*)openbor_rgbcolor)) return "rgbcolor";
547 	else if (functionRef==((void*)openbor_settexture)) return "settexture";
548 	else if (functionRef==((void*)openbor_setvertex)) return "setvertex";
549 	else if (functionRef==((void*)openbor_trianglelist)) return "trianglelist";
550 	else if (functionRef==((void*)openbor_aicheckwarp)) return "aicheckwarp";
551 	else if (functionRef==((void*)openbor_aichecklie)) return "aichecklie";
552 	else if (functionRef==((void*)openbor_aicheckgrabbed)) return "aicheckgrabbed";
553 	else if (functionRef==((void*)openbor_aicheckgrab)) return "aicheckgrab";
554 	else if (functionRef==((void*)openbor_aicheckescape)) return "aicheckescape";
555 	else if (functionRef==((void*)openbor_aicheckbusy)) return "aicheckbusy";
556 	else if (functionRef==((void*)openbor_aicheckattack)) return "aicheckattack";
557 	else if (functionRef==((void*)openbor_aicheckmove)) return "aicheckmove";
558 	else if (functionRef==((void*)openbor_aicheckjump)) return "aicheckjump";
559 	else if (functionRef==((void*)openbor_aicheckpathblocked)) return "aicheckpathblocked";
560 	else if (functionRef==((void*)openbor_adjustwalkanimation)) return "adjustwalkanimation";
561 	else if (functionRef==((void*)openbor_finditem)) return "finditem";
562 	else if (functionRef==((void*)openbor_pickup)) return "pickup";
563 	else if (functionRef==((void*)openbor_waypoints)) return "waypoints";
564 	else if (functionRef==((void*)openbor_drawspriteq)) return "drawspriteq";
565 	else if (functionRef==((void*)openbor_clearspriteq)) return "clearspriteq";
566 	else if (functionRef==((void*)openbor_getgfxproperty)) return "getgfxproperty";
567 	else if (functionRef==((void*)openbor_allocscript)) return "allocscript";
568 	else if (functionRef==((void*)openbor_loadscript)) return "loadscript";
569 	else if (functionRef==((void*)openbor_compilescript)) return "compilescript";
570 	else if (functionRef==((void*)openbor_executescript)) return "executescript";
571 	else return "<unknown function>";
572 }
573 
574 //return string mapping function corresponding to a given function
Script_GetStringMapFunction(void * functionRef)575 void* Script_GetStringMapFunction(void* functionRef)
576 {
577 	if (functionRef==((void*)openbor_systemvariant)) return (void*)mapstrings_systemvariant;
578 	else if (functionRef==((void*)openbor_changesystemvariant)) return (void*)mapstrings_systemvariant;
579 	else if (functionRef==((void*)openbor_getentityproperty)) return (void*)mapstrings_getentityproperty;
580 	else if (functionRef==((void*)openbor_changeentityproperty)) return (void*)mapstrings_changeentityproperty;
581 	else if (functionRef==((void*)openbor_getplayerproperty)) return (void*)mapstrings_playerproperty;
582 	else if (functionRef==((void*)openbor_changeplayerproperty)) return (void*)mapstrings_playerproperty;
583 	else if (functionRef==((void*)openbor_setspawnentry)) return (void*)mapstrings_setspawnentry;
584 	else if (functionRef==((void*)openbor_transconst)) return (void*)mapstrings_transconst;
585 	else if (functionRef==((void*)openbor_playerkeys)) return (void*)mapstrings_playerkeys;
586 	else if (functionRef==((void*)openbor_gettextobjproperty)) return (void*)mapstrings_gettextobjproperty;
587 	else if (functionRef==((void*)openbor_changetextobjproperty)) return (void*)mapstrings_changetextobjproperty;
588 	else if (functionRef==((void*)openbor_getlayerproperty)) return (void*)mapstrings_layerproperty;
589 	else if (functionRef==((void*)openbor_changelayerproperty)) return (void*)mapstrings_layerproperty;
590 	else if (functionRef==((void*)openbor_changedrawmethod)) return (void*)mapstrings_drawmethodproperty;
591 	else if (functionRef==((void*)openbor_getgfxproperty)) return (void*)mapstrings_gfxproperty;
592 	else if (functionRef==((void*)openbor_getlevelproperty)) return (void*)mapstrings_levelproperty;
593 	else if (functionRef==((void*)openbor_changelevelproperty)) return (void*)mapstrings_levelproperty;
594 	else return NULL;
595 }
596 
597 /* Replace string constants with enum constants at compile time to speed up
598    script execution. */
Script_MapStringConstants(Script * pscript)599 int Script_MapStringConstants(Script* pscript)
600 {
601 	Interpreter* pinterpreter = pscript->pinterpreter;
602 	Instruction* pInstruction, *pInstruction2;
603 	ScriptVariant** params;
604 	//ScriptVariant* var;
605 	void (*pMapstrings)(ScriptVariant**, int);
606 	int i, j, k, size, paramCount;
607 
608 	size = List_GetSize(&(pinterpreter->theInstructionList));
609 	for(i=0; i<size; i++)
610 	{
611 		pInstruction = (Instruction*)(pinterpreter->theInstructionList.solidlist[i]);
612 		if(pInstruction->functionRef)
613 		{
614 			params = (ScriptVariant**)pInstruction->theRefList->solidlist;
615 			paramCount = (int)pInstruction->theRef->lVal;
616 
617 			// Get the pointer to the correct mapstrings function, if one exists.
618 			pMapstrings = Script_GetStringMapFunction(pInstruction->functionRef);
619 			if(pMapstrings)
620 			{
621 				// Call the mapstrings function.
622 				pMapstrings(params, paramCount);
623 
624 				// Find the instruction containing each constant and update its value.
625 				for(j=0; j<paramCount; j++)
626 				{
627 					for(k=i; k>0; k--)
628 					{
629 						pInstruction2 = (Instruction*)(pinterpreter->theInstructionList.solidlist[k]);
630 						if(pInstruction2->theVal2 == params[j])
631 						{
632 							ScriptVariant_Copy(pInstruction2->theVal, pInstruction2->theVal2);
633 							break;
634 						}
635 					}
636 					if(k<0) return 0;
637 				}
638 			}
639 		}
640 	}
641 
642 	return 1;
643 }
644 
645 // replaces the entire instruction list with a new instruction list after optimization
Script_ReplaceInstructionList(Interpreter * pInterpreter,List * newList)646 int Script_ReplaceInstructionList(Interpreter* pInterpreter, List* newList)
647 {
648 	int i, j, newSize = List_GetSize(newList);
649 	Instruction* pInstruction, *pTarget;
650 	Instruction** oldList = (Instruction**)pInterpreter->theInstructionList.solidlist;
651 	List_Solidify(newList);
652 
653 	char buf[256];
654 
655 	for(i=0; i<newSize; i++)
656 	{
657 		pInstruction = (Instruction*)newList->solidlist[i];
658 		if(pInstruction->theJumpTargetIndex >= 0)
659 		{
660 			pTarget = (Instruction*)oldList[pInstruction->theJumpTargetIndex];
661 			for(j=0; j<newSize; j++)
662 			{
663 				if(newList->solidlist[j] == pTarget)
664 				{
665 					pInstruction->theJumpTargetIndex = j;
666 					break;
667 				}
668 			}
669 			// if the jump target isn't found, it must have been removed in an optimization - whoops!
670 			if(j == newSize)
671 			{
672 				Instruction_ToString(pTarget, buf);
673 				printf("Error: jump target %i (%s) not found - overzealous optimization!\n", pInstruction->theJumpTargetIndex, buf);
674 				return 0;
675 			}
676 		}
677 	}
678 
679 	// replace new list with old list
680 	List_Clear(&(pInterpreter->theInstructionList));
681 	memcpy(&(pInterpreter->theInstructionList), newList, sizeof(List));
682 
683 	return 1;
684 }
685 
686 // prints lots of debugging stuff about optimizations that can be made
Script_LowerConstants(Script * pscript)687 void Script_LowerConstants(Script* pscript)
688 {
689 	Interpreter* pinterpreter = pscript->pinterpreter;
690 	Instruction* pInstruction, *pInstruction2;
691 	List* newInstructionList = malloc(sizeof(List));
692 	int i, j, size;
693 
694 	List_Init(newInstructionList);
695 
696 	size = List_GetSize(&(pinterpreter->theInstructionList));
697 
698 	for(i=0; i<size; i++)
699 	{
700 		pInstruction = (Instruction*)(pinterpreter->theInstructionList.solidlist[i]);
701 		if(pInstruction->OpCode == DATA)
702 		{
703 			int numRefs = 0;
704 			for(j=0; j<size; j++)
705 			{
706 				pInstruction2 = (Instruction*)(pinterpreter->theInstructionList.solidlist[j]);
707 				if(pInstruction2->OpCode == LOAD && pInstruction2->theRef == pInstruction->theVal)
708 					numRefs++;
709 			}
710 			//printf("Variable declared, %i references\n", numRefs, pInstruction->theToken->theSource);
711 			//printf("DATA (theVal=0x%08X, theRef=0x%08X)\n", pInstruction->theVal, pInstruction->theRef);
712 			if(numRefs > 0) List_InsertAfter(newInstructionList, pInstruction, NULL);
713 			else
714 			{
715 				printf("Unused variable\n");
716 				free(pInstruction);
717 			}
718 		}
719 		else List_InsertAfter(newInstructionList, pInstruction, NULL);
720 #define ISCONST(x) ((x) && ((x->OpCode==CONSTINT)||(x->OpCode==CONSTSTR)||(x->OpCode==CONSTDBL)))
721 		// Look for constant binary ops
722 		if(pInstruction->OpCode == ADD)
723 		{
724 			Instruction *pSrc1 = NULL, *pSrc2 = NULL;
725 			char buf[1024], buf2[1024], buf3[1024];
726 			for(j=0; j<size; j++)
727 			{
728 				Instruction* tmp = (Instruction*)(pinterpreter->theInstructionList.solidlist[j]);
729 				if(tmp->theVal == pInstruction->theRef || tmp->theVal2 == pInstruction->theRef)   pSrc1 = tmp;
730 				if(tmp->theVal == pInstruction->theRef2 || tmp->theVal2 == pInstruction->theRef2) pSrc2 = tmp;
731 			}
732 
733 			if(ISCONST(pSrc1) && ISCONST(pSrc2))
734 			{
735 				ScriptVariant* sum = ScriptVariant_Add(pSrc1->theVal2, pSrc2->theVal2);
736 				ScriptVariant_ToString(pSrc1->theVal2, buf);
737 		    	ScriptVariant_ToString(pSrc2->theVal2, buf2);
738 		    	ScriptVariant_ToString(sum, buf3);
739 		    	//printf("ADD 0x%08X: %s + %s = %s\n", pInstruction, buf, buf2, buf3);
740 			}
741 #if 0
742 			else if(pSrc1 && pSrc2)
743 			{
744 		    	Instruction_ToString(pSrc1, buf);
745 		    	Instruction_ToString(pSrc2, buf2);
746 		    	printf("ADD 0x%08X: %s + %s\n", pInstruction, buf, buf2);
747 		    }
748 		    else printf("ADD 0x%08X: Non-constant addition?\n");
749 #endif
750 		}
751 #undef ISCONST
752 	}
753 
754 	// replace old instruction list with optimized one (TODO: enable when this function actually does optimizations)
755 	//Script_ReplaceInstructionList(pinterpreter, &newInstructionList);
756 }
757 
758 // detect unused functions in scripts (to save memory)
Script_DetectUnusedFunctions(Script * pScript)759 int Script_DetectUnusedFunctions(Script* pScript)
760 {
761 	Interpreter* pInterpreter = pScript->pinterpreter;
762 	Instruction* pInstruction, *pInstruction2, **instructionList = (Instruction**)pInterpreter->theInstructionList.solidlist;
763 	List newInstructionList;
764 	int i, size = List_GetSize(&(pInterpreter->theInstructionList));
765 
766 	List_Init(&newInstructionList);
767 
768 	for(i=0; i<size; i++)
769 	{
770 		pInstruction = instructionList[i];
771 		// detect function declarations (FIXME: should have an opcode for function declarations other than NOOP)
772 		if(pInstruction->OpCode == NOOP && pInstruction->theToken && strlen(pInstruction->theToken->theSource) > 0)
773 		{
774 			int j, numCalls = 0;
775 
776 			// find all calls to this function
777 			for(j=0; j<size; j++)
778 			{
779 				pInstruction2 = instructionList[j];
780 				if(pInstruction2->OpCode == CALL && pInstruction2->theJumpTargetIndex == i) numCalls++;
781 			}
782 
783 			if(numCalls == 0 && strcmp(pInstruction->theToken->theSource, "main") != 0)
784 			{
785 				printf("Unused function %s()\n", pInstruction->theToken->theSource);
786 				while(instructionList[i]->OpCode != RET) // skip function without adding to new instruction list
787 				{
788 					free(instructionList[i++]);
789 					if(i >= size) {List_Clear(&newInstructionList); return 0;} // this shouldn't happen!
790 				}
791 				free(instructionList[i]); // free the final RET instruction too
792 			}
793 			else List_InsertAfter(&newInstructionList, pInstruction, NULL);
794 		}
795 		else List_InsertAfter(&newInstructionList, pInstruction, NULL);
796 
797 		List_InsertAfter(&newInstructionList, pInstruction, NULL);
798 
799 		//if(pInstruction->theToken) {free(pInstruction->theToken); pInstruction->theToken=NULL;} // TODO: move somewhere else
800 	}
801 
802 	return Script_ReplaceInstructionList(pInterpreter, &newInstructionList);
803 }
804 
805 //should be called only once after parsing text
Script_Compile(Script * pscript)806 int Script_Compile(Script* pscript)
807 {
808 	int result;
809 	if(!pscript || !pscript->pinterpreter) return 1;
810 	//Interpreter_OutputPCode(pscript->pinterpreter, "code");
811 	result = SUCCEEDED(Interpreter_CompileInstructions(pscript->pinterpreter));
812 	if(!result) {Script_Clear(pscript, 1);shutdown(1, "Can't compile script!\n");}
813 	result = Script_MapStringConstants(pscript);
814 	if(!result) {Script_Clear(pscript, 1);shutdown(1, "Can't compile script!\n");}
815 
816 	//result = Script_DetectUnusedFunctions(pscript);
817 	//if(!result) {Script_Clear(pscript, 1);shutdown(1, "Script optimization failed!\n");}
818 	//Script_LowerConstants(pscript);
819 
820 	return result;
821 }
822 
Script_IsInitialized(Script * pscript)823 int Script_IsInitialized(Script* pscript)
824 {
825 	//if(pscript && pscript->initialized) pcurrentscript = pscript; //used by local script functions
826 	return pscript->initialized;
827 }
828 
829 //execute the script
Script_Execute(Script * pscript)830 int Script_Execute(Script* pscript)
831 {
832 	int result=S_OK;
833 	Script* temp = pcurrentscript;
834 	pcurrentscript = pscript; //used by local script functions
835 	Interpreter_Reset(pscript->pinterpreter);
836 	result = (int)SUCCEEDED(Interpreter_EvaluateImmediate(pscript->pinterpreter));
837 	pcurrentscript = temp;
838 	if(!result) shutdown(1, "There's an exception while executing script '%s' %s", pscript->pinterpreter->theSymbolTable.name, pscript->comment?pscript->comment:"");
839 	return result;
840 }
841 
842 #ifndef COMPILED_SCRIPT
843 //this method is for debug purpose
Script_Call(Script * pscript,char * method,ScriptVariant * pretvar)844 int Script_Call(Script* pscript, char* method, ScriptVariant* pretvar)
845 {
846 	int result;
847 	Script* temp = pcurrentscript;
848 	pcurrentscript = pscript; //used by local script functions
849 	Interpreter_Reset(pscript->pinterpreter);
850 	result = (int)SUCCEEDED(Interpreter_Call(pscript->pinterpreter, method, pretvar));
851 	pcurrentscript = temp;
852 	return result;
853 }
854 #endif
855 
856 //used by Script_Global_Init
Script_LoadSystemFunctions()857 void Script_LoadSystemFunctions()
858 {
859 	//printf("Loading system script functions....");
860 	//load system functions if we need
861 	List_Reset(&theFunctionList);
862 
863 	List_InsertAfter(&theFunctionList,
864 					  (void*)system_isempty, "isempty");
865 	List_InsertAfter(&theFunctionList,
866 					  (void*)system_NULL, "NULL");
867 	List_InsertAfter(&theFunctionList,
868 					  (void*)system_rand, "rand");
869 	List_InsertAfter(&theFunctionList,
870 					  (void*)system_maxglobalvarindex, "maxglobalvarindex");
871 	List_InsertAfter(&theFunctionList,
872 					  (void*)system_getglobalvar, "getglobalvar");
873 	List_InsertAfter(&theFunctionList,
874 					  (void*)system_setglobalvar, "setglobalvar");
875 	List_InsertAfter(&theFunctionList,
876 					  (void*)system_getlocalvar, "getlocalvar");
877 	List_InsertAfter(&theFunctionList,
878 					  (void*)system_setlocalvar, "setlocalvar");
879 	List_InsertAfter(&theFunctionList,
880 					  (void*)system_clearglobalvar, "clearglobalvar");
881 	List_InsertAfter(&theFunctionList,
882 					  (void*)system_clearindexedvar, "clearindexedvar");
883 	List_InsertAfter(&theFunctionList,
884 					  (void*)system_clearlocalvar, "clearlocalvar");
885 	List_InsertAfter(&theFunctionList,
886 					  (void*)system_free, "free");
887 	List_InsertAfter(&theFunctionList,
888 					  (void*)openbor_systemvariant, "openborvariant");
889 	List_InsertAfter(&theFunctionList,
890 					  (void*)openbor_changesystemvariant, "changeopenborvariant");
891 	List_InsertAfter(&theFunctionList,
892 					  (void*)openbor_drawstring, "drawstring");
893 	List_InsertAfter(&theFunctionList,
894 					  (void*)openbor_drawstringtoscreen, "drawstringtoscreen");
895 	List_InsertAfter(&theFunctionList,
896 					  (void*)openbor_log, "log");
897 	List_InsertAfter(&theFunctionList,
898 					  (void*)openbor_drawbox, "drawbox");
899 	List_InsertAfter(&theFunctionList,
900 					  (void*)openbor_drawboxtoscreen, "drawboxtoscreen");
901 	List_InsertAfter(&theFunctionList,
902 					  (void*)openbor_drawline, "drawline");
903 	List_InsertAfter(&theFunctionList,
904 					  (void*)openbor_drawlinetoscreen, "drawlinetoscreen");
905 	List_InsertAfter(&theFunctionList,
906 					  (void*)openbor_drawsprite, "drawsprite");
907 	List_InsertAfter(&theFunctionList,
908 					  (void*)openbor_drawspritetoscreen, "drawspritetoscreen");
909 	List_InsertAfter(&theFunctionList,
910 					  (void*)openbor_drawdot, "drawdot");
911 	List_InsertAfter(&theFunctionList,
912 					  (void*)openbor_drawdottoscreen, "drawdottoscreen");
913 	List_InsertAfter(&theFunctionList,
914 					  (void*)openbor_drawscreen, "drawscreen");
915 	List_InsertAfter(&theFunctionList,
916 					  (void*)openbor_changeplayerproperty, "changeplayerproperty");
917 	List_InsertAfter(&theFunctionList,
918 					  (void*)openbor_changeentityproperty, "changeentityproperty");
919 	List_InsertAfter(&theFunctionList,
920 					  (void*)openbor_getplayerproperty, "getplayerproperty");
921 	List_InsertAfter(&theFunctionList,
922 					  (void*)openbor_getentityproperty, "getentityproperty");
923 	List_InsertAfter(&theFunctionList,
924 					  (void*)openbor_tossentity, "tossentity");
925 	List_InsertAfter(&theFunctionList,
926 					  (void*)openbor_clearspawnentry, "clearspawnentry");
927 	List_InsertAfter(&theFunctionList,
928 					  (void*)openbor_setspawnentry, "setspawnentry");
929 	List_InsertAfter(&theFunctionList,
930 					  (void*)openbor_spawn, "spawn");
931 	List_InsertAfter(&theFunctionList,
932 					  (void*)openbor_projectile, "projectile");
933 	List_InsertAfter(&theFunctionList,
934 					  (void*)openbor_transconst, "openborconstant");
935 	List_InsertAfter(&theFunctionList,
936 					  (void*)openbor_playmusic, "playmusic");
937 	List_InsertAfter(&theFunctionList,
938 					  (void*)openbor_fademusic, "fademusic");
939 	List_InsertAfter(&theFunctionList,
940 					  (void*)openbor_setmusicvolume, "setmusicvolume");
941 	List_InsertAfter(&theFunctionList,
942 					  (void*)openbor_setmusictempo, "setmusictempo");
943 	List_InsertAfter(&theFunctionList,
944 					  (void*)openbor_pausemusic, "pausemusic");
945 	List_InsertAfter(&theFunctionList,
946 					  (void*)openbor_playsample, "playsample");
947 	List_InsertAfter(&theFunctionList,
948 					  (void*)openbor_loadsample, "loadsample");
949 	List_InsertAfter(&theFunctionList,
950 					  (void*)openbor_unloadsample, "unloadsample");
951 	List_InsertAfter(&theFunctionList,
952 					  (void*)openbor_fadeout, "fadeout");
953 	List_InsertAfter(&theFunctionList,
954 					  (void*)openbor_playerkeys, "playerkeys");
955 	List_InsertAfter(&theFunctionList,
956 					  (void*)openbor_changepalette, "changepalette");
957 	List_InsertAfter(&theFunctionList,
958 					  (void*)openbor_damageentity, "damageentity");
959 	List_InsertAfter(&theFunctionList,
960 					  (void*)openbor_killentity, "killentity");
961 	List_InsertAfter(&theFunctionList,
962 					  (void*)openbor_findtarget, "findtarget");
963 	List_InsertAfter(&theFunctionList,
964 					  (void*)openbor_checkrange, "checkrange");
965 	List_InsertAfter(&theFunctionList,
966 					  (void*)openbor_gettextobjproperty, "gettextobjproperty");
967 	List_InsertAfter(&theFunctionList,
968 					  (void*)openbor_changetextobjproperty, "changetextobjproperty");
969 	List_InsertAfter(&theFunctionList,
970 					  (void*)openbor_settextobj, "settextobj");
971 	List_InsertAfter(&theFunctionList,
972 					  (void*)openbor_cleartextobj, "cleartextobj");
973 	List_InsertAfter(&theFunctionList,
974 					  (void*)openbor_getlayerproperty, "getlayerproperty");
975 	List_InsertAfter(&theFunctionList,
976 					  (void*)openbor_changelayerproperty, "changelayerproperty");
977 	List_InsertAfter(&theFunctionList,
978 					  (void*)openbor_getlevelproperty, "getlevelproperty");
979 	List_InsertAfter(&theFunctionList,
980 					  (void*)openbor_changelevelproperty, "changelevelproperty");
981 	List_InsertAfter(&theFunctionList,
982 					  (void*)openbor_checkhole, "checkhole");
983 	List_InsertAfter(&theFunctionList,
984 					  (void*)openbor_checkwall, "checkwall");
985 	List_InsertAfter(&theFunctionList,
986 					  (void*)openbor_checkplatformbelow, "checkplatformbelow");
987 	List_InsertAfter(&theFunctionList,
988 					  (void*)openbor_openfilestream, "openfilestream");
989 	List_InsertAfter(&theFunctionList,
990 					  (void*)openbor_getfilestreamline, "getfilestreamline");
991 	List_InsertAfter(&theFunctionList,
992 					  (void*)openbor_getfilestreamargument, "getfilestreamargument");
993 	List_InsertAfter(&theFunctionList,
994 					  (void*)openbor_filestreamnextline, "filestreamnextline");
995 	List_InsertAfter(&theFunctionList,
996 					  (void*)openbor_getfilestreamposition, "getfilestreamposition");
997 	List_InsertAfter(&theFunctionList,
998 					  (void*)openbor_setfilestreamposition, "setfilestreamposition");
999 	List_InsertAfter(&theFunctionList,
1000 					  (void*)openbor_filestreamappend, "filestreamappend");
1001 	List_InsertAfter(&theFunctionList,
1002 					  (void*)openbor_createfilestream, "createfilestream");
1003 	List_InsertAfter(&theFunctionList,
1004 					  (void*)openbor_closefilestream, "closefilestream");
1005 	List_InsertAfter(&theFunctionList,
1006 					  (void*)openbor_savefilestream, "savefilestream");
1007 	List_InsertAfter(&theFunctionList,
1008 					  (void*)openbor_getindexedvar, "getindexedvar");
1009 	List_InsertAfter(&theFunctionList,
1010 					  (void*)openbor_setindexedvar, "setindexedvar");
1011 	List_InsertAfter(&theFunctionList,
1012 					  (void*)openbor_getscriptvar, "getscriptvar");
1013 	List_InsertAfter(&theFunctionList,
1014 					  (void*)openbor_setscriptvar, "setscriptvar");
1015 	List_InsertAfter(&theFunctionList,
1016 					  (void*)openbor_getentityvar, "getentityvar");
1017 	List_InsertAfter(&theFunctionList,
1018 					  (void*)openbor_setentityvar, "setentityvar");
1019 	List_InsertAfter(&theFunctionList,
1020 					  (void*)openbor_shutdown, "shutdown");
1021 	List_InsertAfter(&theFunctionList,
1022 					  (void*)openbor_jumptobranch, "jumptobranch");
1023 	List_InsertAfter(&theFunctionList,
1024 					  (void*)openbor_changelight, "changelight");
1025 	List_InsertAfter(&theFunctionList,
1026 					  (void*)openbor_changeshadowcolor, "changeshadowcolor");
1027 	List_InsertAfter(&theFunctionList,
1028 					  (void*)openbor_bindentity, "bindentity");
1029 	List_InsertAfter(&theFunctionList,
1030 					  (void*)openbor_array, "array");
1031 	List_InsertAfter(&theFunctionList,
1032 					  (void*)openbor_size, "size");
1033 	List_InsertAfter(&theFunctionList,
1034 					  (void*)openbor_get, "get");
1035 	List_InsertAfter(&theFunctionList,
1036 					  (void*)openbor_set, "set");
1037 	List_InsertAfter(&theFunctionList,
1038 					  (void*)openbor_allocscreen, "allocscreen");
1039 	List_InsertAfter(&theFunctionList,
1040 					  (void*)openbor_clearscreen, "clearscreen");
1041 	List_InsertAfter(&theFunctionList,
1042 					  (void*)openbor_setdrawmethod, "setdrawmethod");
1043 	List_InsertAfter(&theFunctionList,
1044 					  (void*)openbor_changedrawmethod, "changedrawmethod");
1045 	List_InsertAfter(&theFunctionList,
1046 					  (void*)openbor_updateframe, "updateframe");
1047 	List_InsertAfter(&theFunctionList,
1048 					  (void*)openbor_performattack, "performattack");
1049 	List_InsertAfter(&theFunctionList,
1050 					  (void*)openbor_setidle, "setidle");
1051 	List_InsertAfter(&theFunctionList,
1052 					  (void*)openbor_getentity, "getentity");
1053 	List_InsertAfter(&theFunctionList,
1054 					  (void*)openbor_loadmodel, "loadmodel");
1055 	List_InsertAfter(&theFunctionList,
1056 					  (void*)openbor_loadsprite, "loadsprite");
1057 	List_InsertAfter(&theFunctionList,
1058 					  (void*)openbor_options, "options");
1059 	List_InsertAfter(&theFunctionList,
1060 					  (void*)openbor_playgif, "playgif");
1061 	List_InsertAfter(&theFunctionList,
1062 					  (void*)openbor_strinfirst, "strinfirst");
1063 	List_InsertAfter(&theFunctionList,
1064 					  (void*)openbor_strinlast, "strinlast");
1065 	List_InsertAfter(&theFunctionList,
1066 					  (void*)openbor_strleft, "strleft");
1067 	List_InsertAfter(&theFunctionList,
1068 					  (void*)openbor_strlength, "strlength");
1069 	List_InsertAfter(&theFunctionList,
1070 					  (void*)openbor_strwidth, "strwidth");
1071 	List_InsertAfter(&theFunctionList,
1072 					  (void*)openbor_strright, "strright");
1073 	List_InsertAfter(&theFunctionList,
1074 					  (void*)openbor_getmodelproperty, "getmodelproperty");
1075 	List_InsertAfter(&theFunctionList,
1076 					  (void*)openbor_changemodelproperty, "changemodelproperty");
1077 	List_InsertAfter(&theFunctionList,
1078 					  (void*)openbor_rgbcolor, "rgbcolor");
1079 	List_InsertAfter(&theFunctionList,
1080 					  (void*)openbor_settexture, "settexture");
1081 	List_InsertAfter(&theFunctionList,
1082 					  (void*)openbor_setvertex, "setvertex");
1083 	List_InsertAfter(&theFunctionList,
1084 					  (void*)openbor_trianglelist, "trianglelist");
1085 
1086 	List_InsertAfter(&theFunctionList,
1087 					  (void*)openbor_aicheckwarp, "aicheckwarp");
1088 	List_InsertAfter(&theFunctionList,
1089 					  (void*)openbor_aichecklie, "aichecklie");
1090 	List_InsertAfter(&theFunctionList,
1091 					  (void*)openbor_aicheckgrabbed, "aicheckgrabbed");
1092 	List_InsertAfter(&theFunctionList,
1093 					  (void*)openbor_aicheckgrab, "aicheckgrab");
1094 	List_InsertAfter(&theFunctionList,
1095 					  (void*)openbor_aicheckescape, "aicheckescape");
1096 	List_InsertAfter(&theFunctionList,
1097 					  (void*)openbor_aicheckbusy, "aicheckbusy");
1098 	List_InsertAfter(&theFunctionList,
1099 					  (void*)openbor_aicheckattack, "aicheckattack");
1100 	List_InsertAfter(&theFunctionList,
1101 					  (void*)openbor_aicheckmove, "aicheckmove");
1102 	List_InsertAfter(&theFunctionList,
1103 					  (void*)openbor_aicheckjump, "aicheckjump");
1104 	List_InsertAfter(&theFunctionList,
1105 					  (void*)openbor_aicheckpathblocked, "aicheckpathblocked");
1106 
1107 	List_InsertAfter(&theFunctionList,
1108 					  (void*)openbor_adjustwalkanimation, "adjustwalkanimation");
1109 	List_InsertAfter(&theFunctionList,
1110 					  (void*)openbor_finditem, "finditem");
1111 	List_InsertAfter(&theFunctionList,
1112 					  (void*)openbor_pickup, "pickup");
1113 	List_InsertAfter(&theFunctionList,
1114 					  (void*)openbor_waypoints, "waypoints");
1115 	List_InsertAfter(&theFunctionList,
1116 					  (void*)openbor_drawspriteq, "drawspriteq");
1117 	List_InsertAfter(&theFunctionList,
1118 					  (void*)openbor_clearspriteq, "clearspriteq");
1119 	List_InsertAfter(&theFunctionList,
1120 					  (void*)openbor_getgfxproperty, "getgfxproperty");
1121 	List_InsertAfter(&theFunctionList,
1122 					  (void*)openbor_allocscript, "allocscript");
1123 	List_InsertAfter(&theFunctionList,
1124 					  (void*)openbor_loadscript, "loadscript");
1125 	List_InsertAfter(&theFunctionList,
1126 					  (void*)openbor_compilescript, "compilescript");
1127 	List_InsertAfter(&theFunctionList,
1128 					  (void*)openbor_executescript, "executescript");
1129 
1130 	//printf("Done!\n");
1131 
1132 }
1133 
1134 //////////////////////////////////////////////////////////
1135 ////////////   system functions
1136 //////////////////////////////////////////////////////////
1137 //isempty(var);
system_isempty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1138 HRESULT system_isempty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1139 {
1140 	*pretvar = NULL;
1141 	if(paramCount != 1) return E_FAIL;
1142 
1143 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1144 	(*pretvar)->lVal = (LONG)((varlist[0])->vt == VT_EMPTY );
1145 
1146 	return S_OK;
1147 }
1148 //NULL();
system_NULL(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1149 HRESULT system_NULL(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1150 {
1151 	ScriptVariant_Clear(*pretvar);
1152 
1153 	return S_OK;
1154 }
system_rand(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1155 HRESULT system_rand(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1156 {
1157 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1158 	(*pretvar)->lVal = (LONG)rand32();
1159 	return S_OK;
1160 }
1161 //getglobalvar(varname);
system_getglobalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1162 HRESULT system_getglobalvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1163 {
1164 	ScriptVariant * ptmpvar;
1165 	if(paramCount != 1)
1166 	{
1167 		*pretvar = NULL;
1168 		return E_FAIL;
1169 	}
1170 	if(varlist[0]->vt != VT_STR)
1171 	{
1172 		printf("Function getglobalvar must have a string parameter.\n");
1173 		*pretvar = NULL;
1174 		return E_FAIL;
1175 	}
1176 	ptmpvar = Script_Get_Global_Variant(StrCache_Get(varlist[0]->strVal));
1177 	if(ptmpvar) ScriptVariant_Copy(*pretvar, ptmpvar);
1178 	else ScriptVariant_ChangeType(*pretvar, VT_EMPTY);
1179 	return S_OK;
1180 }
1181 //maxglobalvarindex();
system_maxglobalvarindex(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1182 HRESULT system_maxglobalvarindex(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1183 {
1184 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1185 	(*pretvar)->lVal = (LONG)max_global_var_index;
1186 	return S_OK;
1187 }
1188 //setglobalvar(varname, value);
system_setglobalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1189 HRESULT system_setglobalvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1190 {
1191 	if(paramCount != 2) {
1192 		*pretvar = NULL;
1193 		return E_FAIL;
1194 	}
1195 	if(varlist[0]->vt != VT_STR)
1196 	{
1197 		printf("Function setglobalvar's first parameter must be a string value.\n");
1198 		*pretvar = NULL;
1199 		return E_FAIL;
1200 	}
1201 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1202 
1203 	(*pretvar)->lVal = (LONG)Script_Set_Global_Variant(StrCache_Get(varlist[0]->strVal), (varlist[1]));
1204 
1205 	return S_OK;
1206 }
1207 //getlocalvar(varname);
system_getlocalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1208 HRESULT system_getlocalvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1209 {
1210 	ScriptVariant *ptmpvar;
1211 
1212 	if(paramCount != 1) {
1213 		*pretvar = NULL;
1214 		return E_FAIL;
1215 	}
1216 	if(varlist[0]->vt != VT_STR)
1217 	{
1218 		printf("Function getlocalvar must have a string parameter.\n");
1219 		*pretvar = NULL;
1220 		return E_FAIL;
1221 	}
1222 	ptmpvar = Script_Get_Local_Variant(pcurrentscript, StrCache_Get(varlist[0]->strVal));
1223 	if(ptmpvar) ScriptVariant_Copy(*pretvar,  ptmpvar);
1224 	else        ScriptVariant_ChangeType(*pretvar, VT_EMPTY);
1225 	return S_OK;
1226 }
1227 //setlocalvar(varname, value);
system_setlocalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1228 HRESULT system_setlocalvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1229 {
1230 	if(paramCount < 2) {
1231 		*pretvar = NULL;
1232 		return E_FAIL;
1233 	}
1234 	if(varlist[0]->vt != VT_STR)
1235 	{
1236 		printf("Function setlocalvar's first parameter must be a string value.\n");
1237 		*pretvar = NULL;
1238 		return E_FAIL;
1239 	}
1240 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1241 
1242 	(*pretvar)->lVal = (LONG)Script_Set_Local_Variant(pcurrentscript, StrCache_Get(varlist[0]->strVal), varlist[1]);
1243 
1244 	return S_OK;;
1245 }
1246 //clearlocalvar();
system_clearlocalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1247 HRESULT system_clearlocalvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1248 {
1249 	*pretvar = NULL;
1250 	Script_Local_Clear(pcurrentscript);
1251 	return S_OK;
1252 }
1253 //clearglobalvar();
system_clearglobalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1254 HRESULT system_clearglobalvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1255 {
1256 	*pretvar = NULL;
1257 	max_global_var_index = -1;
1258 	return S_OK;
1259 }
1260 
1261 //clearindexedvar();
system_clearindexedvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1262 HRESULT system_clearindexedvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1263 {
1264 	int i;
1265 	*pretvar = NULL;
1266 	for(i=0; i<max_indexed_vars; i++) ScriptVariant_Clear(indexed_var_list+i);
1267 	return S_OK;
1268 }
1269 
1270 //free();
system_free(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1271 HRESULT system_free(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1272 {
1273 	*pretvar = NULL;
1274 	if(paramCount<1) return E_FAIL;
1275 	if(List_Includes(&scriptheap, varlist[0]->ptrVal))
1276 	{
1277 		_freeheapnode(List_Retrieve(&scriptheap));
1278 		List_Remove(&scriptheap);
1279 		return S_OK;
1280 	}
1281 	return E_FAIL;
1282 }
1283 //////////////////////////////////////////////////////////
1284 ////////////   openbor functions
1285 //////////////////////////////////////////////////////////
1286 
1287 //check openborscript.h for systemvariant_enum
1288 
1289 // arranged list, for searching
1290 static const char* svlist[] = {
1291 "background",
1292 "blockade",
1293 "branchname",
1294 "count_enemies",
1295 "count_entities",
1296 "count_npcs",
1297 "count_players",
1298 "current_branch",
1299 "current_level",
1300 "current_palette",
1301 "current_scene",
1302 "current_set",
1303 "current_stage",
1304 "effectvol",
1305 "elapsed_time",
1306 "ent_max",
1307 "freeram",
1308 "game_paused",
1309 "game_speed",
1310 "gfx_x_offset",
1311 "gfx_y_offset",
1312 "gfx_y_offset_adj",
1313 "hResolution",
1314 "in_gameoverscreen",
1315 "in_halloffamescreen",
1316 "in_level",
1317 "in_menuscreen",
1318 "in_selectscreen",
1319 "in_showcomplete",
1320 "in_titlescreen",
1321 "lasthita",
1322 "lasthitc",
1323 "lasthitt",
1324 "lasthitx",
1325 "lasthitz",
1326 "levelheight",
1327 "levelpos",
1328 "levelwidth",
1329 "lightx",
1330 "lightz",
1331 "maxanimations",
1332 "maxattacktypes",
1333 "maxentityvars",
1334 "maxglobalvars",
1335 "maxindexedvars",
1336 "maxplayers",
1337 "maxscriptvars",
1338 "models_cached",
1339 "models_loaded",
1340 "musicvol",
1341 "nofadeout",
1342 "nopause",
1343 "nosave",
1344 "noscreenshot",
1345 "numpalettes",
1346 "pakname",
1347 "pause",
1348 "pixelformat",
1349 "player",
1350 "player1",
1351 "player2",
1352 "player3",
1353 "player4",
1354 "player_max_z",
1355 "player_min_z",
1356 "scrollmaxz",
1357 "scrollminz",
1358 "self",
1359 "shadowalpha",
1360 "shadowcolor",
1361 "skiptoset",
1362 "slowmotion",
1363 "slowmotion_duration",
1364 "smartbomber",
1365 "soundvol",
1366 "textbox",
1367 "ticks",
1368 "totalram",
1369 "usedram",
1370 "usesave",
1371 "vResolution",
1372 "viewporth",
1373 "viewportw",
1374 "viewportx",
1375 "viewporty",
1376 "vscreen",
1377 "waiting",
1378 "xpos",
1379 "ypos",
1380  };
1381 
1382 
1383 // ===== openborvariant =====
mapstrings_systemvariant(ScriptVariant ** varlist,int paramCount)1384 void mapstrings_systemvariant(ScriptVariant** varlist, int paramCount)
1385 {
1386 	char* propname;
1387 	int prop;
1388 
1389 
1390 	MAPSTRINGS(varlist[0], svlist, _sv_the_end,
1391 		"openborvariant: System variable name not found: '%s'\n");
1392 }
1393 
1394 //sample function, used for getting a system variant
1395 //openborvariant(varname);
openbor_systemvariant(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1396 HRESULT openbor_systemvariant(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1397 {
1398 	//used for getting the index from the enum of properties
1399 	int variantindex = -1;
1400 	//the paramCount used for checking.
1401 	//check it first so the engine wont crash if the list is empty
1402 	if(paramCount != 1)  goto systemvariant_error;
1403 	//call this function's mapstrings function to map string constants to enum values
1404 	mapstrings_systemvariant(varlist, paramCount);
1405 	//the variant name should be here
1406 	//you can check the argument type if you like
1407 	if(varlist[0]->vt == VT_INTEGER)
1408 		variantindex = varlist[0]->lVal;
1409 	else  goto systemvariant_error;
1410 	///////these should be your get method, ///////
1411 	ScriptVariant_Clear(*pretvar);
1412 	if(getsyspropertybyindex(*pretvar, variantindex))
1413 	{
1414 		return S_OK;
1415 	}
1416 	//else if
1417 	//////////////////////////////////////////////
1418 systemvariant_error:
1419 	*pretvar = NULL;
1420 	// we have finshed, so return
1421 	return E_FAIL;
1422 }
1423 
1424 
1425 //used for changing a system variant
1426 //changeopenborvariant(varname, value);
openbor_changesystemvariant(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1427 HRESULT openbor_changesystemvariant(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1428 {
1429 	//used for getting the enum constant corresponding to the desired variable
1430 	int variantindex = 0;
1431 	//reference to the arguments
1432 	ScriptVariant* arg = NULL;
1433 	//the paramCount used for checking.
1434 	//check it first so the engine wont crash if the list is empty
1435 	if(paramCount != 2)   goto changesystemvariant_error;
1436 	// map string constants to enum constants for speed
1437 	mapstrings_systemvariant(varlist, paramCount);
1438 	//get the 1st argument
1439 	arg = varlist[0];
1440 	//the variant name should be here
1441 	//you can check the argument type if you like
1442 	if(arg->vt == VT_INTEGER)
1443 		variantindex = arg->lVal;
1444 	else goto changesystemvariant_error;
1445 
1446 	if(changesyspropertybyindex(variantindex, varlist[1]))
1447 	{
1448 		return S_OK;
1449 	}
1450 changesystemvariant_error:
1451 	*pretvar = NULL;
1452 	// we have finshed, so return
1453 	return E_FAIL;
1454 
1455 }
1456 
1457 // use font_printf to draw string
1458 //drawstring(x, y, font, string, z);
openbor_drawstring(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1459 HRESULT openbor_drawstring(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1460 {
1461 	int i;
1462 	char buf[256];
1463 	LONG value[4];
1464 	*pretvar = NULL;
1465 
1466 	if(paramCount < 4) goto drawstring_error;
1467 
1468 	for(i=0; i<3; i++)
1469 	{
1470 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i)))
1471 			goto drawstring_error;
1472 	}
1473 	if(paramCount>4)
1474 	{
1475 		if(FAILED(ScriptVariant_IntegerValue(varlist[4], value+3)))
1476 			goto drawstring_error;
1477 	}
1478 	else value[3] = 0;
1479 	ScriptVariant_ToString(varlist[3], buf);
1480 	font_printf((int)value[0], (int)value[1], (int)value[2], (int)value[3], "%s", buf);
1481 	return S_OK;
1482 
1483 drawstring_error:
1484 	printf("First 3 values must be integer values and 4th value a string: drawstring(int x, int y, int font, value)\n");
1485 	return E_FAIL;
1486 }
1487 
1488 //use screen_printf
1489 //drawstringtoscreen(screen, x, y, font, string);
openbor_drawstringtoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1490 HRESULT openbor_drawstringtoscreen(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1491 {
1492 	int i;
1493 	s_screen* scr;
1494 	char buf[256];
1495 	LONG value[3];
1496 	*pretvar = NULL;
1497 
1498 	if(paramCount != 5) goto drawstring_error;
1499 
1500 	if(varlist[0]->vt!=VT_PTR) goto drawstring_error;
1501 	scr = (s_screen*)varlist[0]->ptrVal;
1502 	if(!scr)  goto drawstring_error;
1503 
1504 	for(i=0; i<3; i++)
1505 	{
1506 		if(FAILED(ScriptVariant_IntegerValue(varlist[i+1], value+i)))
1507 			goto drawstring_error;
1508 	}
1509 
1510 	ScriptVariant_ToString(varlist[4], buf);
1511 	screen_printf(scr, (int)value[0], (int)value[1], (int)value[2], "%s", buf);
1512 	return S_OK;
1513 
1514 drawstring_error:
1515 	printf("Function needs a valid screen handle, 3 integers and a string value: drawstringtoscreen(screen, int font, value)\n");
1516 	return E_FAIL;
1517 }
1518 
1519 // debug purpose
1520 //log(string);
openbor_log(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1521 HRESULT openbor_log(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1522 {
1523 	char buf[256];
1524 	*pretvar = NULL;
1525 
1526 	if(paramCount != 1) goto drawstring_error;
1527 
1528 	ScriptVariant_ToString(varlist[0], buf);
1529 	printf("%s", buf);
1530 	return S_OK;
1531 
1532 drawstring_error:
1533 	printf("Function needs 1 parameter: log(value)\n");
1534 	return E_FAIL;
1535 }
1536 
1537 //drawbox(x, y, width, height, z, color, lut);
openbor_drawbox(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1538 HRESULT openbor_drawbox(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1539 {
1540 	int i;
1541 	LONG value[6], l;
1542 	*pretvar = NULL;
1543 
1544 	if(paramCount < 6) goto drawbox_error;
1545 
1546 	for(i=0; i<6; i++)
1547 	{
1548 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i)))
1549 			goto drawbox_error;
1550 	}
1551 
1552 	if(paramCount > 6)
1553 	{
1554 		if(FAILED(ScriptVariant_IntegerValue(varlist[6], &l)))
1555 			goto drawbox_error;
1556 	}
1557 	else l = -1;
1558 
1559 	if(l >= 0)
1560 	{
1561 		l %= MAX_BLENDINGS+1;
1562 	}
1563 	spriteq_add_box((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], (int)value[5], l);
1564 
1565 	return S_OK;
1566 
1567 drawbox_error:
1568 	printf("Function requires 6 integer values: drawbox(int x, int y, int width, int height, int z, int color, int lut)\n");
1569 	return E_FAIL;
1570 }
1571 
1572 //drawboxtoscreen(screen, x, y, width, height, color, lut);
openbor_drawboxtoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1573 HRESULT openbor_drawboxtoscreen(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1574 {
1575 	int i;
1576 	s_screen* s;
1577 	LONG value[5], l;
1578 	*pretvar = NULL;
1579 
1580 	if(paramCount < 6) goto drawbox_error;
1581 
1582 	s = (s_screen*)varlist[0]->ptrVal;
1583 
1584 	if(!s) goto drawbox_error;
1585 
1586 	for(i=1; i<6; i++)
1587 	{
1588 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-1)))
1589 			goto drawbox_error;
1590 	}
1591 
1592 	if(paramCount > 6)
1593 	{
1594 		if(FAILED(ScriptVariant_IntegerValue(varlist[6], &l)))
1595 			goto drawbox_error;
1596 	}
1597 	else l = -1;
1598 
1599 	if(l >= 0)
1600 	{
1601 		l %= MAX_BLENDINGS+1;
1602 	}
1603 	switch(s->pixelformat)
1604 	{
1605 	case PIXEL_8:
1606 		drawbox((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], s, l);
1607 		break;
1608 	case PIXEL_16:
1609 		drawbox16((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], s, l);
1610 		break;
1611 	case PIXEL_32:
1612 		drawbox32((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], s, l);
1613 		break;
1614 	}
1615 
1616 	return S_OK;
1617 
1618 drawbox_error:
1619 	printf("Function requires a screen handle and 5 integer values, 7th integer value is optional: drawboxtoscreen(screen, int x, int y, int width, int height, int color, int lut)\n");
1620 	return E_FAIL;
1621 }
1622 
1623 //drawline(x1, y1, x2, y2, z, color, lut);
openbor_drawline(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1624 HRESULT openbor_drawline(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1625 {
1626 	int i;
1627 	LONG value[6], l;
1628 	*pretvar = NULL;
1629 
1630 	if(paramCount < 6) goto drawline_error;
1631 
1632 	for(i=0; i<6; i++)
1633 	{
1634 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i)))
1635 			goto drawline_error;
1636 	}
1637 
1638 	if(paramCount > 6)
1639 	{
1640 		if(FAILED(ScriptVariant_IntegerValue(varlist[6], &l)))
1641 			goto drawline_error;
1642 	}
1643 	else l = -1;
1644 
1645 	if(l >=0 )
1646 	{
1647 		l %= MAX_BLENDINGS+1;
1648 	}
1649 	spriteq_add_line((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], (int)value[5], l);
1650 
1651 	return S_OK;
1652 
1653 drawline_error:
1654 	printf("Function requires 6 integer values, 7th integer value is optional: drawline(int x1, int y1, int x2, int y2, int z, int color, int lut)\n");
1655 	return E_FAIL;
1656 }
1657 
1658 //drawlinetoscreen(screen, x1, y1, x2, y2, color, lut);
openbor_drawlinetoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1659 HRESULT openbor_drawlinetoscreen(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1660 {
1661 	int i;
1662 	LONG value[5], l;
1663 	s_screen *s;
1664 	*pretvar = NULL;
1665 
1666 	if(paramCount < 6) goto drawline_error;
1667 
1668 	s = (s_screen*)varlist[0]->ptrVal;
1669 
1670 	if(!s) goto drawline_error;
1671 
1672 	for(i=1; i<6; i++)
1673 	{
1674 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-1)))
1675 			goto drawline_error;
1676 	}
1677 
1678 	if(paramCount > 6)
1679 	{
1680 		if(FAILED(ScriptVariant_IntegerValue(varlist[6], &l)))
1681 			goto drawline_error;
1682 	}
1683 	else l = -1;
1684 
1685 	if(l >=0 )
1686 	{
1687 		l %= MAX_BLENDINGS+1;
1688 	}
1689 	switch(s->pixelformat)
1690 	{
1691 	case PIXEL_8:
1692 		line((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], s, l);
1693 		break;
1694 	case PIXEL_16:
1695 		line16((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], s, l);
1696 		break;
1697 	case PIXEL_32:
1698 		line32((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], s, l);
1699 		break;
1700 	}
1701 
1702 	return S_OK;
1703 drawline_error:
1704 	printf("Function requires a screen handle and 5 integer values, 7th integer value is optional: drawlinetoscreen(screen, int x1, int y1, int x2, int y2, int color, int lut)\n");
1705 	return E_FAIL;
1706 }
1707 
1708 //drawsprite(sprite, x, y, z, sortid);
openbor_drawsprite(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1709 HRESULT openbor_drawsprite(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1710 {
1711 	int i;
1712 	LONG value[4];
1713 	s_sprite* spr;
1714 	*pretvar = NULL;
1715 
1716 	if(paramCount < 4) goto drawsprite_error;
1717 	if(varlist[0]->vt!=VT_PTR) goto drawsprite_error;
1718 
1719 	spr = varlist[0]->ptrVal;
1720 	if(!spr) goto drawsprite_error;
1721 
1722 	value[3] = (LONG)0;
1723 	for(i=1; i<paramCount && i<5; i++)
1724 	{
1725 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-1)))
1726 			goto drawsprite_error;
1727 	}
1728 
1729 	spriteq_add_frame((int)value[0], (int)value[1], (int)value[2], spr, &drawmethod, (int)value[3]);
1730 
1731 	return S_OK;
1732 
1733 drawsprite_error:
1734 	printf("Function requires a valid sprite handle 3 integer values, 5th integer value is optional: drawsprite(sprite, int x, int y, int z, int sortid)\n");
1735 	return E_FAIL;
1736 }
1737 
1738 //drawspritetoscreen(sprite, screen, x, y);
openbor_drawspritetoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1739 HRESULT openbor_drawspritetoscreen(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1740 {
1741 	int i;
1742 	LONG value[2];
1743 	s_sprite* spr;
1744 	s_screen* scr;
1745 	*pretvar = NULL;
1746 
1747 	if(paramCount < 4) goto drawsprite_error;
1748 	if(varlist[0]->vt!=VT_PTR) goto drawsprite_error;
1749 	spr = varlist[0]->ptrVal;
1750 	if(!spr) goto drawsprite_error;
1751 
1752 	if(varlist[1]->vt!=VT_PTR) goto drawsprite_error;
1753 	scr = varlist[1]->ptrVal;
1754 	if(!scr) goto drawsprite_error;
1755 
1756 	for(i=2; i<paramCount && i<4; i++)
1757 	{
1758 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-2)))
1759 			goto drawsprite_error;
1760 	}
1761 
1762 	putsprite((int)value[0], (int)value[1], spr, scr, &drawmethod);
1763 
1764 	return S_OK;
1765 
1766 drawsprite_error:
1767 	printf("Function requires a valid sprite handle, a valid screen handle and 2 integer values: drawspritetoscreen(sprite, screen, int x, int y)\n");
1768 	return E_FAIL;
1769 }
1770 
1771 //setvertex(index, x, y, tx, ty)
openbor_setvertex(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1772 HRESULT openbor_setvertex(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1773 {
1774 	LONG value[5], i;
1775 	*pretvar = NULL;
1776 
1777 	if(paramCount<5) goto vertex_error;
1778 
1779 	for(i=0; i<5; i++)
1780 	{
1781 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i)))
1782 			goto vertex_error;
1783 	}
1784 
1785 	if(value[0]<0 || value[0]>=vert_buf_size) goto vertex_error2;
1786 
1787 	verts[value[0]].x = value[1];
1788 	verts[value[0]].y = value[2];
1789 	verts[value[0]].tx = value[3];
1790 	verts[value[0]].ty = value[4];
1791 
1792 	return S_OK;
1793 
1794 vertex_error:
1795 	printf("Function requires 5 integer values: setvertex(index, x, y, tx, ty)\n");
1796 	return E_FAIL;
1797 
1798 vertex_error2:
1799 	printf("Index out of range in function setvertext: range from 0 to %d, %ld is given.\n", vert_buf_size-1, value[0]);
1800 	return E_FAIL;
1801 }
1802 
1803 //settexture(handle, type)
openbor_settexture(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1804 HRESULT openbor_settexture(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1805 {
1806 	LONG	type;
1807 	*pretvar = NULL;
1808 
1809 	if(paramCount<2) goto texture_error;
1810 
1811 	if(varlist[0]->vt!=VT_PTR) goto texture_error;
1812 
1813 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &type)))
1814 		goto texture_error;
1815 
1816 	switch(type){
1817 	case 0:
1818 		texture.screen = (s_screen*)varlist[0]->ptrVal;
1819 		break;
1820 	case 1:
1821 		texture.bitmap = (s_bitmap*)varlist[0]->ptrVal;
1822 		break;
1823 	case 2:
1824 		texture.sprite = (s_sprite*)varlist[0]->ptrVal;
1825 		break;
1826 	default:
1827 		goto texture_error2;
1828 		break;
1829 	}
1830 
1831 	return S_OK;
1832 
1833 texture_error:
1834 	printf("Function requires a valid texture handle and a integer values: settexture(handle, type)\n");
1835 	return E_FAIL;
1836 
1837 texture_error2:
1838 	printf("Invalid texture type for function settexture: %ld\n", type);
1839 	return E_FAIL;
1840 }
1841 
1842 // TODO: add a new entry type to the sprite queue (may not happen since you can always use a buffer screen)
1843 //trianglelist(screen, start, count);  //screen could be NULL
openbor_trianglelist(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1844 HRESULT openbor_trianglelist(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1845 {
1846 	s_screen* scr = NULL;
1847 	extern s_screen* vscreen;
1848 	LONG triangle_start = 0;
1849 	LONG triangle_count = 2;
1850 	*pretvar = NULL;
1851 
1852 	if(paramCount<3) goto trianglelist_error;
1853 
1854 	if(varlist[0]->vt!=VT_PTR && varlist[0]->vt!=VT_EMPTY) goto trianglelist_error;
1855 	scr = (s_screen*)varlist[0]->ptrVal;
1856 
1857 	if(!scr) scr = vscreen;
1858 
1859 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &triangle_start)))
1860 		goto trianglelist_error;
1861 
1862 	if(FAILED(ScriptVariant_IntegerValue(varlist[2], &triangle_count)))
1863 		goto trianglelist_error;
1864 
1865 	if(triangle_count<=0) return S_OK; // though we does nothing
1866 
1867 	 //check for overflow
1868 	if(triangle_start<0) triangle_start = 0;
1869 	else if(triangle_start>vert_buf_size-3) triangle_start = vert_buf_size-3;
1870 	//check for overflow
1871 	if(triangle_count>vert_buf_size-triangle_start-2) triangle_count = vert_buf_size-triangle_start-2;
1872 
1873 	//go ahead and draw
1874 	draw_triangle_list(verts + triangle_start, scr, &texture, &drawmethod, triangle_count);
1875 
1876 	return S_OK;
1877 
1878 trianglelist_error:
1879 	printf("Function requires a valid screen handle(can be NULL) and two integer values: trianglelist(screen, start, count)\n");
1880 	return E_FAIL;
1881 }
1882 
1883 
1884 //drawdot(x, y, z, color, lut);
openbor_drawdot(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1885 HRESULT openbor_drawdot(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1886 {
1887 	int i;
1888 	LONG value[4], l;
1889 	*pretvar = NULL;
1890 
1891 	if(paramCount < 4) goto drawdot_error;
1892 
1893 	for(i=0; i<4; i++)
1894 	{
1895 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i)))
1896 			goto drawdot_error;
1897 	}
1898 
1899 	if(paramCount > 4)
1900 	{
1901 		if(FAILED(ScriptVariant_IntegerValue(varlist[4], &l)))
1902 			goto drawdot_error;
1903 	}
1904 	else l = -1;
1905 
1906 	if(l >=0 )
1907 	{
1908 		l %= MAX_BLENDINGS+1;
1909 	}
1910 	spriteq_add_dot((int)value[0], (int)value[1], (int)value[2], (int)value[3], l);
1911 
1912 	return S_OK;
1913 
1914 drawdot_error:
1915 	printf("Function requires 4 integer values, 5th integer value is optional: drawdot(int x, int y, int z, int color, int lut)\n");
1916 	return E_FAIL;
1917 }
1918 
1919 //drawdottoscreen(screen, x, y, color, lut);
openbor_drawdottoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1920 HRESULT openbor_drawdottoscreen(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1921 {
1922 	int i;
1923 	LONG value[3], l;
1924 	s_screen* s;
1925 	*pretvar = NULL;
1926 
1927 	if(paramCount < 4) goto drawdot_error;
1928 
1929 	s = (s_screen*)varlist[0]->ptrVal;
1930 
1931 	if(!s) goto drawdot_error;
1932 
1933 	for(i=1; i<4; i++)
1934 	{
1935 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-1)))
1936 			goto drawdot_error;
1937 	}
1938 
1939 	if(paramCount > 4)
1940 	{
1941 		if(FAILED(ScriptVariant_IntegerValue(varlist[4], &l)))
1942 			goto drawdot_error;
1943 	}
1944 	else l = -1;
1945 
1946 	if(l >=0 )
1947 	{
1948 		l %= MAX_BLENDINGS+1;
1949 	}
1950 	switch(s->pixelformat)
1951 	{
1952 	case PIXEL_8:
1953 		putpixel((int)value[0], (int)value[1], (int)value[2], s, l);
1954 		break;
1955 	case PIXEL_16:
1956 		putpixel16((int)value[0], (int)value[1], (int)value[2], s, l);
1957 		break;
1958 	case PIXEL_32:
1959 		putpixel32((int)value[0], (int)value[1], (int)value[2], s, l);
1960 		break;
1961 	}
1962 
1963 	return S_OK;
1964 
1965 drawdot_error:
1966 	printf("Function requires a screen handle and 3 integer values, 5th integer value is optional: dottoscreen(screen, int x, int y, int color, int lut)\n");
1967 	return E_FAIL;
1968 }
1969 
1970 
1971 //drawscreen(screen, x, y, z, lut);
openbor_drawscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1972 HRESULT openbor_drawscreen(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
1973 {
1974 	int i;
1975 	LONG value[3], l;
1976 	s_screen* s;
1977 	s_drawmethod screenmethod;
1978 	*pretvar = NULL;
1979 
1980 	if(paramCount < 4) goto drawscreen_error;
1981 
1982 	s = (s_screen*)varlist[0]->ptrVal;
1983 
1984 	if(!s) goto drawscreen_error;
1985 
1986 	for(i=1; i<4; i++)
1987 	{
1988 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-1)))
1989 			goto drawscreen_error;
1990 	}
1991 
1992 	if(paramCount > 4)
1993 	{
1994 		if(FAILED(ScriptVariant_IntegerValue(varlist[4], &l)))
1995 			goto drawscreen_error;
1996 	}
1997 	else l = -1;
1998 
1999 	if(l >=0 )
2000 	{
2001 		l %= MAX_BLENDINGS+1;
2002 	}
2003 	if(paramCount<=4) screenmethod = drawmethod;
2004 	else
2005 	{
2006 		screenmethod = plainmethod;
2007 		screenmethod.alpha = l;
2008 		screenmethod.transbg = 1;
2009 	}
2010 
2011 	spriteq_add_screen((int)value[0], (int)value[1], (int)value[2], s, &screenmethod, 0);
2012 
2013 	return S_OK;
2014 
2015 drawscreen_error:
2016 	printf("Function requires a screen handle and 3 integer values, 5th integer value is optional: drawscreen(screen, int x, int y, int z, int lut)\n");
2017 	return E_FAIL;
2018 }
2019 
2020 //getindexedvar(int index);
openbor_getindexedvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2021 HRESULT openbor_getindexedvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2022 {
2023 	LONG ind;
2024 
2025 	if(paramCount < 1 || max_indexed_vars<=0)
2026 	{
2027 		*pretvar = NULL;
2028 		return E_FAIL;
2029 	}
2030 
2031 	ScriptVariant_Clear(*pretvar);
2032 
2033 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
2034 	{
2035 		printf("Function requires 1 numberic value: getindexedvar(int index)\n");
2036 		*pretvar = NULL;
2037 		return E_FAIL;
2038 	}
2039 
2040 	if(ind<0 || ind>=max_indexed_vars) return S_OK;
2041 
2042 	ScriptVariant_Copy(*pretvar, indexed_var_list+ind);
2043 
2044 	return S_OK;
2045 }
2046 
2047 //setindexedvar(int index, var);
openbor_setindexedvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2048 HRESULT openbor_setindexedvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2049 {
2050 	LONG ind;
2051 
2052 	if(paramCount < 2 || max_indexed_vars<=0)
2053 	{
2054 		*pretvar = NULL;
2055 		return E_FAIL;
2056 	}
2057 
2058 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
2059 	{
2060 		printf("Function's 1st argument must be a numberic value: setindexedvar(int index, var)\n");
2061 		*pretvar = NULL;
2062 		return E_FAIL;
2063 	}
2064 
2065 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2066 
2067 	if(ind<0 || ind>=max_indexed_vars)
2068 	{
2069 		(*pretvar)->lVal = 0;
2070 		return S_OK;
2071 	}
2072 
2073 	ScriptVariant_Copy(indexed_var_list+ind, varlist[1]);
2074 	(*pretvar)->lVal = 1;
2075 
2076 	return S_OK;
2077 }
2078 
2079 //getscriptvar(int index);
openbor_getscriptvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2080 HRESULT openbor_getscriptvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2081 {
2082 	LONG ind;
2083 
2084 	if(paramCount < 1 || max_script_vars<=0 || !pcurrentscript || !pcurrentscript->vars)
2085 	{
2086 		*pretvar = NULL;
2087 		return E_FAIL;
2088 	}
2089 
2090 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
2091 	{
2092 		printf("Function requires 1 numberic value: getscriptvar(int index)\n");
2093 		*pretvar = NULL;
2094 		return E_FAIL;
2095 	}
2096 
2097 	ScriptVariant_Clear(*pretvar);
2098 
2099 	if(ind<0 || ind>=max_script_vars) return S_OK;
2100 
2101 	ScriptVariant_Copy(*pretvar, pcurrentscript->vars+ind);
2102 
2103 	return S_OK;
2104 }
2105 
2106 //setscriptvar(int index, var);
openbor_setscriptvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2107 HRESULT openbor_setscriptvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2108 {
2109 	LONG ind;
2110 
2111 	if(paramCount < 2 || max_script_vars<=0 || !pcurrentscript || !pcurrentscript->vars)
2112 	{
2113 		*pretvar = NULL;
2114 		return E_FAIL;
2115 	}
2116 
2117 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
2118 	{
2119 		printf("Function's 1st argument must be a numberic value: setscriptvar(int index, var)\n");
2120 		*pretvar = NULL;
2121 		return E_FAIL;
2122 	}
2123 
2124 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2125 
2126 	if(ind<0 || ind>=max_script_vars)
2127 	{
2128 		(*pretvar)->lVal = 0;
2129 		return S_OK;
2130 	}
2131 
2132 	ScriptVariant_Copy(pcurrentscript->vars+ind, varlist[1]);
2133 	(*pretvar)->lVal = 1;
2134 
2135 	return S_OK;
2136 }
2137 
2138 //getentityvar(entity, int index);
openbor_getentityvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2139 HRESULT openbor_getentityvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2140 {
2141 	ScriptVariant* arg = NULL;
2142 	LONG ind;
2143 	entity* ent;
2144 
2145 	if(paramCount < 2 || max_entity_vars<=0 )
2146 	{
2147 		*pretvar = NULL;
2148 		return E_FAIL;
2149 	}
2150 
2151 
2152 	arg = varlist[0];
2153 
2154 	ScriptVariant_Clear(*pretvar);
2155 	if(arg->vt == VT_EMPTY) ent= NULL;
2156 	else if(arg->vt == VT_PTR) ent = (entity*)arg->ptrVal;
2157 	else
2158 	{
2159 		printf("Function's 1st argument must be a valid entity handle value or empty value: getentityvar(entity, int index)\n");
2160 		*pretvar = NULL;
2161 		return E_FAIL;
2162 	}
2163 	if(!ent || !ent->entvars) return S_OK;
2164 
2165 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &ind)))
2166 	{
2167 		printf("Function's 2nd argument must be a numberic value: getentityvar(entity, int index)\n");
2168 		*pretvar = NULL;
2169 		return E_FAIL;
2170 	}
2171 
2172 	if(ind<0 || ind>=max_entity_vars) return S_OK;
2173 
2174 	ScriptVariant_Copy(*pretvar, ent->entvars+ind);
2175 
2176 	return S_OK;
2177 }
2178 
2179 //setentityvar(int index, var);
openbor_setentityvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2180 HRESULT openbor_setentityvar(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2181 {
2182 	ScriptVariant* arg = NULL;
2183 	LONG ind;
2184 	entity* ent;
2185 
2186 	if(paramCount < 3 || max_entity_vars<=0)
2187 	{
2188 		*pretvar = NULL;
2189 		return E_FAIL;
2190 	}
2191 
2192 	arg = varlist[0];
2193 
2194 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2195 	(*pretvar)->lVal = 0;
2196 
2197 	if(arg->vt == VT_EMPTY) ent = NULL;
2198 	else if(arg->vt == VT_PTR)
2199 		ent = (entity*)arg->ptrVal;
2200 	else
2201 	{
2202 		printf("Function's 1st argument must be a valid entity handle value or empty value: setentityvar(entity, int index, var)\n");
2203 		*pretvar = NULL;
2204 		return E_FAIL;
2205 	}
2206 	if(!ent || !ent->entvars) return S_OK;
2207 
2208 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &ind)))
2209 	{
2210 		printf("Function's 2nd argument must be a numberic value: setentityvar(entity, int index, var)\n");
2211 		*pretvar = NULL;
2212 		return E_FAIL;
2213 	}
2214 
2215 	if(ind<0 || ind>=max_entity_vars) return S_OK;
2216 
2217 	ScriptVariant_Copy(ent->entvars+ind, varlist[2]);
2218 	(*pretvar)->lVal = 1;
2219 
2220 	return S_OK;
2221 }
2222 
2223 //strinfirst(char string, char search_string);
openbor_strinfirst(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2224 HRESULT openbor_strinfirst(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2225 {
2226 	char* tempstr = NULL;
2227 
2228 	if(paramCount < 2)
2229 	{
2230 		*pretvar = NULL;
2231 		return E_FAIL;
2232 	}
2233 
2234 	ScriptVariant_Clear(*pretvar);
2235 
2236 	if(varlist[0]->vt!=VT_STR || varlist[1]->vt!=VT_STR)
2237 	{
2238 		printf("\n Error, strinfirst({string}, {search string}): Strinfirst must be passed valid {string} and {search string}. \n");
2239 	}
2240 
2241 	tempstr = strstr((char*)StrCache_Get(varlist[0]->strVal), (char*)StrCache_Get(varlist[1]->strVal));
2242 
2243 	if (tempstr != NULL)
2244 	{
2245 		ScriptVariant_ChangeType(*pretvar, VT_STR);
2246 		strcpy(StrCache_Get((*pretvar)->strVal), tempstr);
2247 	}
2248 	else
2249 	{
2250 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2251 		(*pretvar)->lVal = -1;
2252 	}
2253 	return S_OK;
2254 }
2255 
2256 //strinlast(char string, char search_string);
openbor_strinlast(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2257 HRESULT openbor_strinlast(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2258 {
2259 	char* tempstr = NULL;
2260 
2261 	if(paramCount < 2)
2262 	{
2263 		*pretvar = NULL;
2264 		return E_FAIL;
2265 	}
2266 
2267 	ScriptVariant_Clear(*pretvar);
2268 
2269 	if(varlist[0]->vt!=VT_STR || varlist[1]->vt!=VT_STR)
2270 	{
2271 		printf("\n Error, strinlast({string}, {search string}): Strinlast must be passed valid {string} and {search string}. \n");
2272 	}
2273 
2274 	tempstr = strrchr((char*)StrCache_Get(varlist[0]->strVal), varlist[1]->strVal);
2275 
2276 	if (tempstr != NULL)
2277 	{
2278 		ScriptVariant_ChangeType(*pretvar, VT_STR);
2279 		strcpy(StrCache_Get((*pretvar)->strVal), tempstr);
2280 	}
2281 	else
2282 	{
2283 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2284 		(*pretvar)->lVal = -1;
2285 	}
2286 	return S_OK;
2287 }
2288 
2289 //strleft(char string, int i);
openbor_strleft(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2290 HRESULT openbor_strleft(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2291 {
2292 	char tempstr[66] = {0};
2293 
2294 	if(paramCount < 2)
2295 	{
2296 		*pretvar = NULL;
2297 		return E_FAIL;
2298 	}
2299 	if(varlist[0]->vt!=VT_STR || varlist[1]->vt!=VT_INTEGER)
2300 	{
2301 		printf("\n Error, strleft({string}, {characters}): Invalid or missing parameter. Strleft must be passed valid {string} and number of {characters}.\n");
2302 	}
2303 
2304 	strncpy(tempstr, (char*)StrCache_Get(varlist[0]->strVal), varlist[1]->lVal);
2305 	ScriptVariant_Clear(*pretvar);
2306 
2307 	if (tempstr != NULL)
2308 	{
2309 		ScriptVariant_ChangeType(*pretvar, VT_STR);
2310 		strcpy(StrCache_Get((*pretvar)->strVal),tempstr);
2311 	}
2312 	else
2313 	{
2314 		 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2315 		(*pretvar)->lVal = -1;
2316 	}
2317 
2318 	return S_OK;
2319 }
2320 
2321 //strlength(char string);
openbor_strlength(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2322 HRESULT openbor_strlength(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2323 {
2324 	if(paramCount < 1 || varlist[0]->vt!=VT_STR) goto strlength_error;
2325 
2326 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2327 	(*pretvar)->lVal = strlen((char*)StrCache_Get(varlist[0]->strVal));
2328 	return S_OK;
2329 
2330 strlength_error:
2331 	printf("Error, strlength({string}): Invalid or missing parameter. Strlength must be passed a valid {string}.\n");
2332 	*pretvar = NULL;
2333 	return E_FAIL;
2334 }
2335 
2336 //strwidth(char string, int font);
openbor_strwidth(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2337 HRESULT openbor_strwidth(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2338 {
2339 	LONG ltemp;
2340 	if(paramCount < 2 || varlist[0]->vt!=VT_STR ||
2341 		FAILED(ScriptVariant_IntegerValue(varlist[1], &ltemp))) goto strwidth_error;
2342 
2343 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2344 	(*pretvar)->lVal = font_string_width((int)ltemp, (char*)StrCache_Get(varlist[0]->strVal));
2345 	return S_OK;
2346 
2347 strwidth_error:
2348 	printf("Error, strwidth({string}, {font}): Invalid or missing parameter.\n");
2349 	*pretvar = NULL;
2350 	return E_FAIL;
2351 }
2352 
2353 //strright(char string, int i);
openbor_strright(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2354 HRESULT openbor_strright(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2355 {
2356 	char* tempstr = NULL;
2357 
2358 	if(paramCount < 2)
2359 	{
2360 		*pretvar = NULL;
2361 		return E_FAIL;
2362 	}
2363 
2364 	if(varlist[0]->vt!=VT_STR || varlist[1]->vt!=VT_INTEGER)
2365 	{
2366 		printf("\n Error, strright({string}, {characters}): Invalid or missing parameter. Strright must be passed valid {string} and number of {characters}.\n");
2367 	}
2368 
2369 	ScriptVariant_Clear(*pretvar);
2370 	tempstr = (char*)StrCache_Get(varlist[0]->strVal);
2371 
2372 	if (tempstr != NULL || strlen(tempstr)>0)
2373 	{
2374 		ScriptVariant_ChangeType(*pretvar, VT_STR);
2375 		strcpy(StrCache_Get((*pretvar)->strVal), &tempstr[varlist[1]->lVal]);
2376 	}
2377 	else
2378 	{
2379 		 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2380 		(*pretvar)->lVal = -1;
2381 	}
2382 
2383 	return S_OK;
2384 }
2385 
openbor_getmodelproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2386 HRESULT openbor_getmodelproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2387 {
2388 	int iArg;
2389 
2390 	if(paramCount < 2)
2391 	{
2392 		*pretvar = NULL;
2393 		return E_FAIL;
2394 	}
2395 
2396 	if(varlist[0]->vt!=VT_INTEGER || varlist[1]->vt!=VT_INTEGER)
2397 	{
2398 		printf("\n Error, getmodelproperty({model}, {property}): Invalid or missing parameter. Getmodelproperty must be passed valid {model} and {property} indexes.\n");
2399 	}
2400 
2401 	iArg = varlist[0]->lVal;
2402 
2403 	switch (varlist[1]->lVal)
2404 	{
2405 		case 0:                                                    //Loaded?
2406 		{
2407 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2408 			(*pretvar)->lVal = (LONG)model_cache[iArg].loadflag;
2409 			break;
2410 		}
2411 		case 1:
2412 		{
2413 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
2414 			(*pretvar)->ptrVal = (VOID*)model_cache[iArg].model;
2415 		}
2416 		case 2:
2417 		{
2418 			ScriptVariant_ChangeType(*pretvar, VT_STR);
2419 			strcpy(StrCache_Get((*pretvar)->strVal), model_cache[iArg].name);
2420 			break;
2421 		}
2422 		case 3:
2423 		{
2424 			ScriptVariant_ChangeType(*pretvar, VT_STR);
2425 			strcpy(StrCache_Get((*pretvar)->strVal), model_cache[iArg].path);
2426 			break;
2427 		}
2428 		case 4:                                                    //Loaded?
2429 		{
2430 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2431 			(*pretvar)->lVal = (LONG)model_cache[iArg].selectable;
2432 			break;
2433 		}
2434 	}
2435 
2436 	return S_OK;
2437 }
2438 
openbor_changemodelproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2439 HRESULT openbor_changemodelproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
2440 {
2441 	int iArg;
2442 	LONG ltemp;
2443 
2444 	if(paramCount < 2)
2445 	{
2446 		*pretvar = NULL;
2447 		return E_FAIL;
2448 	}
2449 
2450 	if(varlist[0]->vt!=VT_INTEGER || varlist[1]->vt!=VT_INTEGER)
2451 	{
2452 		printf("\n Error, changemodelproperty({model}, {property}, {value}): Invalid or missing parameter. Changemodelproperty must be passed valid {model}, {property} and {value}.\n");
2453 	}
2454 
2455 	iArg = varlist[0]->lVal;
2456 
2457 	switch (varlist[1]->lVal)
2458 	{
2459 		case 0:                                                    //Loaded?
2460 		{
2461 			/*
2462 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
2463 				model_cache[iArg].loadflag = (int)ltemp;
2464 			else (*pretvar)->lVal = (LONG)0;
2465 			break;
2466 			*/
2467 		}
2468 		case 1:
2469 		{
2470 			/*
2471 			if(varlist[2]->vt != VT_STR)
2472 			{
2473 				printf("You must give a string value for {value}.\n");
2474 				goto changeentityproperty_error;
2475 			}
2476 			strcpy(model_cache[iArg].model, (char*)StrCache_Get(varlist[2]->strVal));
2477 			(*pretvar)->lVal = (LONG)1;
2478 			break;
2479 			*/
2480 		}
2481 		case 2:
2482 		{
2483 			/*
2484 			if(varlist[2]->vt != VT_STR)
2485 			{
2486 				printf("You must give a string value for {value}.\n");
2487 				goto changeentityproperty_error;
2488 			}
2489 			strcpy(model_cache[iArg].name, (char*)StrCache_Get(varlist[2]->strVal));
2490 			(*pretvar)->lVal = (LONG)1;
2491 			break;
2492 			*/
2493 		}
2494 		case 3:
2495 		{
2496 			/*
2497 			if(varlist[2]->vt != VT_STR)
2498 			{
2499 				printf("You must give a string value for {value}.\n");
2500 				goto changeentityproperty_error;
2501 			}
2502 			strcpy(model_cache[iArg].path, (char*)StrCache_Get(varlist[2]->strVal));
2503 			(*pretvar)->lVal = (LONG)1;
2504 			break;
2505 			*/
2506 		}
2507 		case 4:
2508 		{
2509 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
2510 				model_cache[iArg].selectable = (int)ltemp;
2511 			else (*pretvar)->lVal = (LONG)0;
2512 			break;
2513 		}
2514 	}
2515 
2516 	return S_OK;
2517 }
2518 
2519 // ===== getentityproperty =====
2520 enum entityproperty_enum {
2521 _ep_a,
2522 _ep_aggression,
2523 _ep_aiattack,
2524 _ep_aiflag,
2525 _ep_aimove,
2526 _ep_alpha,
2527 _ep_animal,
2528 _ep_animating,
2529 _ep_animation,
2530 _ep_animationid,
2531 _ep_animheight,
2532 _ep_animhits,
2533 _ep_animnum,
2534 _ep_animpos,
2535 _ep_animvalid,
2536 _ep_antigrab,
2537 _ep_antigravity,
2538 _ep_attack,
2539 _ep_attackid,
2540 _ep_attacking,
2541 _ep_attackthrottle,
2542 _ep_attackthrottletime,
2543 _ep_autokill,
2544 _ep_base,
2545 _ep_bbox,
2546 _ep_blink,
2547 _ep_blockback,
2548 _ep_blockodds,
2549 _ep_blockpain,
2550 _ep_boss,
2551 _ep_bounce,
2552 _ep_bound,
2553 _ep_candamage,
2554 _ep_chargerate,
2555 _ep_colourmap,
2556 _ep_colourtable,
2557 _ep_combostep,
2558 _ep_combotime,
2559 _ep_damage_on_landing,
2560 _ep_dead,
2561 _ep_defaultmodel,
2562 _ep_defaultname,
2563 _ep_defense,
2564 _ep_detect,
2565 _ep_direction,
2566 _ep_dot,
2567 _ep_dropframe,
2568 _ep_edelay,
2569 _ep_energycost,
2570 _ep_escapecount,
2571 _ep_escapehits,
2572 _ep_exists,
2573 _ep_falldie,
2574 _ep_flash,
2575 _ep_freezetime,
2576 _ep_frozen,
2577 _ep_gfxshadow,
2578 _ep_grabbing,
2579 _ep_grabforce,
2580 _ep_guardpoints,
2581 _ep_health,
2582 _ep_height,
2583 _ep_hitbyid,
2584 _ep_hmapl,
2585 _ep_hmapu,
2586 _ep_hostile,
2587 _ep_icon,
2588 _ep_iconposition,
2589 _ep_invincible,
2590 _ep_invinctime,
2591 _ep_jugglepoints,
2592 _ep_knockdowncount,
2593 _ep_komap,
2594 _ep_landframe,
2595 _ep_lifeposition,
2596 _ep_lifespancountdown,
2597 _ep_link,
2598 _ep_map,
2599 _ep_mapcount,
2600 _ep_mapdefault,
2601 _ep_maps,
2602 _ep_maptime,
2603 _ep_maxguardpoints,
2604 _ep_maxhealth,
2605 _ep_maxjugglepoints,
2606 _ep_maxmp,
2607 _ep_model,
2608 _ep_mp,
2609 _ep_mpdroprate,
2610 _ep_mprate,
2611 _ep_mpset,
2612 _ep_mpstable,
2613 _ep_mpstableval,
2614 _ep_name,
2615 _ep_nameposition,
2616 _ep_nextanim,
2617 _ep_nextthink,
2618 _ep_no_adjust_base,
2619 _ep_noaicontrol,
2620 _ep_nodieblink,
2621 _ep_nodrop,
2622 _ep_nograb,
2623 _ep_nolife,
2624 _ep_nopain,
2625 _ep_offense,
2626 _ep_opponent,
2627 _ep_owner,
2628 _ep_pain_time,
2629 _ep_parent,
2630 _ep_path,
2631 _ep_pathfindstep,
2632 _ep_playerindex,
2633 _ep_position,
2634 _ep_projectile,
2635 _ep_projectilehit,
2636 _ep_range,
2637 _ep_running,
2638 _ep_rush_count,
2639 _ep_rush_tally,
2640 _ep_rush_time,
2641 _ep_score,
2642 _ep_scroll,
2643 _ep_seal,
2644 _ep_sealtime,
2645 _ep_setlayer,
2646 _ep_spawntype,
2647 _ep_speed,
2648 _ep_sprite,
2649 _ep_spritea,
2650 _ep_stalltime,
2651 _ep_stats,
2652 _ep_staydown,
2653 _ep_staydownatk,
2654 _ep_stealth,
2655 _ep_subentity,
2656 _ep_subject_to_gravity,
2657 _ep_subject_to_hole,
2658 _ep_subject_to_maxz,
2659 _ep_subject_to_minz,
2660 _ep_subject_to_obstacle,
2661 _ep_subject_to_platform,
2662 _ep_subject_to_screen,
2663 _ep_subject_to_wall,
2664 _ep_subtype,
2665 _ep_takeaction,
2666 _ep_think,
2667 _ep_thold,
2668 _ep_throwdamage,
2669 _ep_throwdist,
2670 _ep_throwframewait,
2671 _ep_throwheight,
2672 _ep_tosstime,
2673 _ep_tossv,
2674 _ep_trymove,
2675 _ep_type,
2676 _ep_velocity,
2677 _ep_vulnerable,
2678 _ep_weapent,
2679 _ep_weapon,
2680 _ep_x,
2681 _ep_xdir,
2682 _ep_z,
2683 _ep_zdir,
2684 _ep_the_end,
2685 };
2686 
2687 // arranged list, for searching
2688 static const char* eplist[] = {
2689 "a",
2690 "aggression",
2691 "aiattack",
2692 "aiflag",
2693 "aimove",
2694 "alpha",
2695 "animal",
2696 "animating",
2697 "animation",
2698 "animationid",
2699 "animheight",
2700 "animhits",
2701 "animnum",
2702 "animpos",
2703 "animvalid",
2704 "antigrab",
2705 "antigravity",
2706 "attack",
2707 "attackid",
2708 "attacking",
2709 "attackthrottle",
2710 "attackthrottletime",
2711 "autokill",
2712 "base",
2713 "bbox",
2714 "blink",
2715 "blockback",
2716 "blockodds",
2717 "blockpain",
2718 "boss",
2719 "bounce",
2720 "bound",
2721 "candamage",
2722 "chargerate",
2723 "colourmap",
2724 "colourtable",
2725 "combostep",
2726 "combotime",
2727 "damage_on_landing",
2728 "dead",
2729 "defaultmodel",
2730 "defaultname",
2731 "defense",
2732 "detect",
2733 "direction",
2734 "dot",
2735 "dropframe",
2736 "edelay",
2737 "energycost",
2738 "escapecount",
2739 "escapehits",
2740 "exists",
2741 "falldie",
2742 "flash",
2743 "freezetime",
2744 "frozen",
2745 "gfxshadow",
2746 "grabbing",
2747 "grabforce",
2748 "guardpoints",
2749 "health",
2750 "height",
2751 "hitbyid",
2752 "hmapl",
2753 "hmapu",
2754 "hostile",
2755 "icon",
2756 "iconposition",
2757 "invincible",
2758 "invinctime",
2759 "jugglepoints",
2760 "knockdowncount",
2761 "komap",
2762 "landframe",
2763 "lifeposition",
2764 "lifespancountdown",
2765 "link",
2766 "map",
2767 "mapcount",
2768 "mapdefault",
2769 "maps",
2770 "maptime",
2771 "maxguardpoints",
2772 "maxhealth",
2773 "maxjugglepoints",
2774 "maxmp",
2775 "model",
2776 "mp",
2777 "mpdroprate",
2778 "mprate",
2779 "mpset",
2780 "mpstable",
2781 "mpstableval",
2782 "name",
2783 "nameposition",
2784 "nextanim",
2785 "nextthink",
2786 "no_adjust_base",
2787 "noaicontrol",
2788 "nodieblink",
2789 "nodrop",
2790 "nograb",
2791 "nolife",
2792 "nopain",
2793 "offense",
2794 "opponent",
2795 "owner",
2796 "pain_time",
2797 "parent",
2798 "path",
2799 "pathfindstep",
2800 "playerindex",
2801 "position",
2802 "projectile",
2803 "projectilehit",
2804 "range",
2805 "running",
2806 "rush_count",
2807 "rush_tally",
2808 "rush_time",
2809 "score",
2810 "scroll",
2811 "seal",
2812 "sealtime",
2813 "setlayer",
2814 "spawntype",
2815 "speed",
2816 "sprite",
2817 "spritea",
2818 "stalltime",
2819 "stats",
2820 "staydown",
2821 "staydownatk",
2822 "stealth",
2823 "subentity",
2824 "subject_to_gravity",
2825 "subject_to_hole",
2826 "subject_to_maxz",
2827 "subject_to_minz",
2828 "subject_to_obstacle",
2829 "subject_to_platform",
2830 "subject_to_screen",
2831 "subject_to_wall",
2832 "subtype",
2833 "takeaction",
2834 "think",
2835 "thold",
2836 "throwdamage",
2837 "throwdist",
2838 "throwframewait",
2839 "throwheight",
2840 "tosstime",
2841 "tossv",
2842 "trymove",
2843 "type",
2844 "velocity",
2845 "vulnerable",
2846 "weapent",
2847 "weapon",
2848 "x",
2849 "xdir",
2850 "z",
2851 "zdir",
2852 };
2853 
2854 enum aiflag_enum {
2855 	_ep_aiflag_animating,
2856 	_ep_aiflag_attacking,
2857 	_ep_aiflag_autokill,
2858 	_ep_aiflag_blink,
2859 	_ep_aiflag_blocking,
2860 	_ep_aiflag_charging,
2861 	_ep_aiflag_dead,
2862 	_ep_aiflag_drop,
2863 	_ep_aiflag_falling,
2864 	_ep_aiflag_freezetime,
2865 	_ep_aiflag_frozen,
2866 	_ep_aiflag_getting,
2867 	_ep_aiflag_idling,
2868 	_ep_aiflag_inpain,
2869 	_ep_aiflag_invincible,
2870 	_ep_aiflag_jumpid,
2871 	_ep_aiflag_jumping,
2872 	_ep_aiflag_pain_time,
2873 	_ep_aiflag_projectile,
2874 	_ep_aiflag_running,
2875 	_ep_aiflag_toexplode,
2876 	_ep_aiflag_turning,
2877 	_ep_aiflag_walking,
2878 	_ep_aiflag_the_end,
2879 };
2880 
2881 
2882 static const char* eplist_aiflag[] = {
2883 	"animating",
2884 	"attacking",
2885 	"autokill",
2886 	"blink",
2887 	"blocking",
2888 	"charging",
2889 	"dead",
2890 	"drop",
2891 	"falling",
2892 	"freezetime",
2893 	"frozen",
2894 	"getting",
2895 	"idling",
2896 	"inpain",
2897 	"invincible",
2898 	"jumpid",
2899 	"jumping",
2900 	"pain_time",
2901 	"projectile",
2902 	"running",
2903 	"toexplode",
2904 	"turning",
2905 	"walking",
2906 };
2907 
2908 enum gep_attack_enum {
2909 	_gep_attack_blast,
2910 	_gep_attack_blockflash,
2911 	_gep_attack_blocksound,
2912 	_gep_attack_coords,
2913 	_gep_attack_counterattack,
2914 	_gep_attack_direction,
2915 	_gep_attack_dol,
2916 	_gep_attack_dot,
2917 	_gep_attack_dotforce,
2918 	_gep_attack_dotindex,
2919 	_gep_attack_dotrate,
2920 	_gep_attack_dottime,
2921 	_gep_attack_drop,
2922 	_gep_attack_dropv,
2923 	_gep_attack_force,
2924 	_gep_attack_forcemap,
2925 	_gep_attack_freeze,
2926 	_gep_attack_freezetime,
2927 	_gep_attack_grab,
2928 	_gep_attack_grabdistance,
2929 	_gep_attack_guardcost,
2930 	_gep_attack_hitflash,
2931 	_gep_attack_hitsound,
2932 	_gep_attack_jugglecost,
2933 	_gep_attack_maptime,
2934 	_gep_attack_noblock,
2935 	_gep_attack_noflash,
2936 	_gep_attack_nokill,
2937 	_gep_attack_nopain,
2938 	_gep_attack_otg,
2939 	_gep_attack_pause,
2940 	_gep_attack_seal,
2941 	_gep_attack_sealtime,
2942 	_gep_attack_staydown,
2943 	_gep_attack_steal,
2944 	_gep_attack_type,
2945 	_gep_attack_the_end,
2946 };
2947 
2948 enum _gep_defense_enum {
2949     _gep_defense_blockpower,
2950     _gep_defense_blockratio,
2951     _gep_defense_blockthreshold,
2952     _gep_defense_blocktype,
2953     _gep_defense_factor,
2954     _gep_defense_knockdown,
2955 	_gep_defense_pain,
2956 	_gep_defense_the_end,
2957 };
2958 
2959 enum gep_dot_enum {
2960 	_gep_dot_force,
2961 	_gep_dot_mode,
2962 	_gep_dot_owner,
2963 	_gep_dot_rate,
2964 	_gep_dot_time,
2965 	_gep_dot_type,
2966 	_gep_dot_the_end,
2967 };
2968 
2969 enum gep_edelay_enum {
2970 	_gep_edelay_cap_max,
2971 	_gep_edelay_cap_min,
2972 	_gep_edelay_factor,
2973 	_gep_edelay_mode,
2974 	_gep_edelay_range_max,
2975 	_gep_edelay_range_min,
2976 	_gep_edelay_the_end,
2977 };
2978 
2979 enum gep_energycost_enum {
2980     _gep_energycost_cost,
2981     _gep_energycost_disable,
2982     _gep_energycost_mponly,
2983     _gep_energycost_the_end,
2984 };
2985 
2986 enum gep_flash_enum {
2987     _gep_flash_block,
2988     _gep_flash_def,
2989     _gep_flash_noattack,
2990     _gep_flash_the_end,
2991 };
2992 
2993 enum gep_icon_enum {
2994     _gep_icon_def,
2995     _gep_icon_die,
2996     _gep_icon_get,
2997     _gep_icon_mphigh,
2998     _gep_icon_mplow,
2999     _gep_icon_mpmed,
3000     _gep_icon_pain,
3001     _gep_icon_weapon,
3002     _gep_icon_x,
3003     _gep_icon_y,
3004     _gep_icon_the_end,
3005 };
3006 
3007 enum _gep_knockdowncount_enum {
3008     _gep_knockdowncount_current,
3009     _gep_knockdowncount_max,
3010     _gep_knockdowncount_time,
3011     _gep_knockdowncount_the_end,
3012 };
3013 
3014 enum gep_landframe_enum {
3015     _gep_landframe_ent,
3016     _gep_landframe_frame,
3017     _gep_landframe_the_end,
3018 };
3019 
3020 enum gep_maps_enum {
3021     _gep_maps_count,
3022     _gep_maps_current,
3023     _gep_maps_default,
3024     _gep_maps_dying,
3025     _gep_maps_dying_critical,
3026     _gep_maps_dying_low,
3027     _gep_maps_frozen,
3028     _gep_maps_hide_end,
3029     _gep_maps_hide_start,
3030     _gep_maps_ko,
3031     _gep_maps_kotype,
3032     _gep_maps_table,
3033     _gep_maps_time,
3034     _gep_maps_the_end,
3035 };
3036 
3037 enum gep_range_enum {
3038     _gep_range_amax,
3039     _gep_range_amin,
3040     _gep_range_bmax,
3041     _gep_range_bmin,
3042     _gep_range_xmax,
3043     _gep_range_xmin,
3044     _gep_range_zmax,
3045     _gep_range_zmin,
3046     _gep_range_the_end,
3047 };
3048 
3049 enum gep_running_enum {
3050 	_gep_running_jumpx,
3051 	_gep_running_jumpy,
3052 	_gep_running_land,
3053 	_gep_running_movez,
3054 	_gep_running_speed,
3055 	_gep_running_the_end,
3056 };
3057 
3058 enum gep_spritea_enum {
3059     _gep_spritea_centerx,
3060     _gep_spritea_centery,
3061     _gep_spritea_file,
3062     _gep_spritea_offsetx,
3063     _gep_spritea_offsety,
3064     _gep_spritea_sprite,
3065     _gep_spritea_the_end,
3066 };
3067 
3068 enum gep_staydown_enum {
3069     _gep_staydown_rise,
3070     _gep_staydown_riseattack,
3071     _gep_staydown_riseattack_stall,
3072     _gep_staydown_the_end,
3073 };
3074 
mapstrings_getentityproperty(ScriptVariant ** varlist,int paramCount)3075 void mapstrings_getentityproperty(ScriptVariant** varlist, int paramCount)
3076 {
3077 	char* propname;
3078 	int prop;
3079 
3080     static const char* proplist_attack[] = {
3081 		"blast",
3082 		"blockflash",
3083 		"blocksound",
3084 		"coords",
3085 		"counterattack",
3086 		"direction",
3087 		"dol",
3088 		"dot",
3089 		"dotforce",
3090 		"dotindex",
3091 		"dotrate",
3092 		"dottime",
3093 		"drop",
3094 		"dropv",
3095 		"force",
3096 		"forcemap",
3097 		"freeze",
3098 		"freezetime",
3099 		"grab",
3100 		"grabdistance",
3101 		"guardcost",
3102 		"hitflash",
3103 		"hitsound",
3104 		"jugglecost",
3105 		"maptime",
3106 		"noblock",
3107 		"noflash",
3108 		"nokill",
3109 		"nopain",
3110 		"otg",
3111 		"pause",
3112 		"seal",
3113 		"sealtime",
3114 		"staydown",
3115 		"steal",
3116 		"type",
3117 	};
3118 
3119 	static const char* proplist_defense[] = {
3120 		"blockpower",
3121 		"blockratio",
3122 		"blockthreshold",
3123 		"blocktype",
3124 		"factor",
3125 		"knockdown",
3126 		"pain",
3127 	};
3128 
3129     static const char* proplist_dot[] = {
3130 		"force",
3131 		"mode",
3132 		"owner",
3133 		"rate",
3134 		"time",
3135 		"type",
3136 	};
3137 
3138     static const char* proplist_edelay[] = {
3139 		"cap_max",
3140 		"cap_min",
3141 		"factor",
3142 		"mode",
3143 		"range_max",
3144 		"range_min",
3145 	};
3146 
3147     static const char* proplist_energycost[] = {
3148 		"cost",
3149 		"disable",
3150 		"mponly",
3151 	};
3152 
3153     static const char* proplist_flash[] = {
3154         "block",
3155         "default",
3156         "noattack",
3157     };
3158 
3159     static const char* proplist_icon[] = {
3160         "default",
3161         "die",
3162         "get",
3163         "mphigh",
3164         "mplow",
3165         "mpmed",
3166         "pain",
3167         "weapon",
3168         "x",
3169         "y",
3170     };
3171 
3172     static const char* proplist_knockdowncount[] = {
3173         "current",
3174         "max",
3175         "time",
3176     };
3177 
3178     static const char* proplist_landframe[] = {
3179         "ent",
3180         "frame",
3181 	};
3182 
3183     static const char* proplist_maps[] = {
3184         "count",
3185         "current",
3186         "default",
3187         "dying",
3188         "dying_critical",
3189         "dying_low",
3190         "frozen",
3191         "hide_end",
3192         "hide_start",
3193         "ko",
3194         "kotype",
3195         "table",
3196         "time",
3197     };
3198 
3199 	static const char* proplist_range[] = {
3200 		"amax",
3201 		"amin",
3202 		"bmax",
3203 		"bmin",
3204 		"xmax",
3205 		"xmin",
3206 		"zmax",
3207 		"zmin",
3208 	};
3209 
3210 	static const char* proplist_running[] = {
3211 		"jumpx",
3212 		"jumpy",
3213 		"land",
3214 		"movez",
3215 		"speed",
3216 	};
3217 
3218     static const char* proplist_spritea[] = {
3219         "centerx",
3220         "centery",
3221         "file",
3222         "offsetx",
3223         "offsety",
3224         "sprite",
3225 	};
3226 
3227     static const char* proplist_staydown[] = {
3228         "rise",
3229         "riseattack",
3230         "riseattack_stall",
3231     };
3232 
3233 	if(paramCount < 2) return;
3234 
3235 	// map entity properties
3236 	MAPSTRINGS(varlist[1], eplist, _ep_the_end,
3237 		"Property name '%s' is not supported by function getentityproperty.\n");
3238 
3239 	if(paramCount < 3) return;
3240 
3241 	// map subproperties of aiflag property
3242 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_aiflag))
3243 	{
3244 		MAPSTRINGS(varlist[2], eplist_aiflag, _ep_aiflag_the_end,
3245 			"'%s' is not a known subproperty of 'aiflag'.\n");
3246 	}
3247 
3248 	// map subproperties of Attack
3249 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_attack))
3250 	{
3251 		MAPSTRINGS(varlist[2], proplist_attack, _gep_attack_the_end,
3252 			"Property name '%s' is not a known subproperty of 'attack'.\n");
3253 	}
3254 
3255 	// map subproperties of defense property
3256 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_defense))
3257 	{
3258 		if(paramCount >= 4)
3259 		{
3260 			MAPSTRINGS(varlist[3], proplist_defense, _gep_defense_the_end,
3261 				"'%s' is not a known subproperty of 'defense'.\n");
3262 		}
3263 	}
3264 
3265     // map subproperties of DOT
3266 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_dot))
3267 	{
3268 		MAPSTRINGS(varlist[2], proplist_dot, _gep_dot_the_end,
3269 			"Property name '%s' is not a known subproperty of 'dot'.\n");
3270 	}
3271 
3272     // map subproperties of Edelay property
3273 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_edelay))
3274 	{
3275 		MAPSTRINGS(varlist[2], proplist_edelay, _gep_edelay_the_end,
3276 			"'%s' is not a known subproperty of 'edelay'.\n");
3277 	}
3278 
3279 	// map subproperties of Energycost
3280 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_energycost))
3281 	{
3282 		MAPSTRINGS(varlist[2], proplist_energycost, _gep_energycost_the_end,
3283 			"Property name '%s' is not a known subproperty of 'energycost'.\n");
3284 	}
3285 
3286 	// map subproperties of Flash
3287 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_flash))
3288 	{
3289 		MAPSTRINGS(varlist[2], proplist_flash, _gep_flash_the_end,
3290 			"Property name '%s' is not a known subproperty of 'flash'.\n");
3291 	}
3292 
3293     // map subproperties of Icon
3294 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_icon))
3295 	{
3296 		MAPSTRINGS(varlist[2], proplist_icon, _gep_icon_the_end,
3297 			"Property name '%s' is not a known subproperty of 'icon'.\n");
3298 	}
3299 
3300 	// map subproperties of Knockdowncount
3301 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_knockdowncount))
3302 	{
3303 		MAPSTRINGS(varlist[2], proplist_knockdowncount, _gep_knockdowncount_the_end,
3304 			"Property name '%s' is not a known subproperty of 'knockdowncount'.\n");
3305 	}
3306 
3307 	// map subproperties of Landframe
3308 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_landframe))
3309 	{
3310 		MAPSTRINGS(varlist[2], proplist_landframe, _gep_landframe_the_end,
3311 			"Property name '%s' is not a known subproperty of 'landframe'.\n");
3312 	}
3313 
3314 	// map subproperties of Maps
3315 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_maps))
3316 	{
3317 		MAPSTRINGS(varlist[2], proplist_maps, _gep_maps_the_end,
3318 			"Property name '%s' is not a known subproperty of 'maps'.\n");
3319 	}
3320 
3321 	// map subproperties of Range
3322 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_range))
3323 	{
3324 		MAPSTRINGS(varlist[2], proplist_range, _gep_range_the_end,
3325 			"Property name '%s' is not a known subproperty of 'range'.\n");
3326 	}
3327 
3328 	// map subproperties of Running
3329 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_running))
3330 	{
3331 		MAPSTRINGS(varlist[2], proplist_running, _gep_running_the_end,
3332 			"Property name '%s' is not a known subproperty of 'running'.\n");
3333 	}
3334 
3335 	// map subproperties of Spritea
3336 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_spritea))
3337 	{
3338 		MAPSTRINGS(varlist[2], proplist_spritea, _gep_spritea_the_end,
3339 			"Property name '%s' is not a known subproperty of 'spritea'.\n");
3340 	}
3341 
3342 	// map subproperties of Staydown
3343 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_staydown))
3344 	{
3345 		MAPSTRINGS(varlist[2], proplist_staydown, _gep_running_the_end,
3346 			"Property name '%s' is not a known subproperty of 'staydown'.\n");
3347 	}
3348 }
3349 
3350 //getentityproperty(pentity, propname);
openbor_getentityproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)3351 HRESULT openbor_getentityproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
3352 {
3353 	entity* ent			= NULL;
3354 	char* tempstr		= NULL;
3355 	ScriptVariant* arg	= NULL;
3356 	ScriptVariant* arg1	= NULL;
3357 	s_sprite* spr;
3358 	s_attack* attack;
3359 	LONG ltemp, ltemp2;
3360 	int i				= 0;
3361 	int propind ;
3362 	int tempint			= 0;
3363 	short *coords;
3364 
3365 	if(paramCount < 2)  {
3366 		*pretvar = NULL;
3367 		return E_FAIL;
3368 	}
3369 
3370 	ScriptVariant_Clear(*pretvar);
3371 	mapstrings_getentityproperty(varlist, paramCount);
3372 
3373 	arg = varlist[0];
3374 	if(arg->vt != VT_PTR && arg->vt != VT_EMPTY)
3375 	{
3376 		printf("Function getentityproperty must have a valid entity handle.\n");
3377 		*pretvar = NULL;
3378 		return E_FAIL;
3379 	}
3380 	ent = (entity*)arg->ptrVal; //retrieve the entity
3381 	if(!ent) return S_OK;
3382 
3383 	arg = varlist[1];
3384 	if(arg->vt!=VT_INTEGER)
3385 	{
3386 		printf("Function getentityproperty must have a string property name.\n");
3387 	}
3388 
3389 	propind = arg->lVal;
3390 
3391 	switch(propind)
3392 	{
3393     case _ep_a:
3394 	{
3395 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
3396 		(*pretvar)->dblVal = (DOUBLE)ent->a;
3397 		break;
3398 	}
3399 	case _ep_aggression:
3400 	{
3401 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3402 		(*pretvar)->lVal = (LONG)ent->modeldata.aggression;
3403 		break;
3404 	}
3405 	case _ep_aiattack:
3406 	{
3407 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3408 		(*pretvar)->lVal = (LONG)ent->modeldata.aiattack;
3409 		break;
3410 	}
3411 	case _ep_aiflag:
3412 	{
3413 		if(paramCount<3) break;
3414 		arg = varlist[2];
3415 		if(arg->vt != VT_INTEGER)
3416 		{
3417 			printf("You must give a string name for aiflag.\n");
3418 			return E_FAIL;
3419 		}
3420 		ltemp = arg->lVal;
3421 		switch(ltemp)
3422 		{
3423 		case _ep_aiflag_dead:
3424 		{
3425 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3426 			 (*pretvar)->lVal = (LONG)ent->dead;
3427 			 break;
3428 		}
3429 		case _ep_aiflag_jumpid:
3430 		{
3431 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3432 			 (*pretvar)->lVal = (LONG)ent->jumpid;
3433 			 break;
3434 		}
3435 		case _ep_aiflag_jumping:
3436 		{
3437 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3438 			 (*pretvar)->lVal = (LONG)ent->jumping;
3439 			 break;
3440 		}
3441 		case _ep_aiflag_idling:
3442 		{
3443 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3444 			 (*pretvar)->lVal = (LONG)ent->idling;
3445 			 break;
3446 		}
3447 		case _ep_aiflag_drop:
3448 		{
3449 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3450 			 (*pretvar)->lVal = (LONG)ent->drop;
3451 			 break;
3452 		}
3453 		case _ep_aiflag_attacking:
3454 		{
3455 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3456 			(*pretvar)->lVal = (LONG)ent->attacking;
3457 			break;
3458 		}
3459 		case _ep_aiflag_getting:
3460 		{
3461 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3462 			 (*pretvar)->lVal = (LONG)ent->getting;
3463 			 break;
3464 		}
3465 		case _ep_aiflag_turning:
3466 		{
3467 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3468 			 (*pretvar)->lVal = (LONG)ent->turning;
3469 			 break;
3470 		}
3471 		case _ep_aiflag_charging:
3472 		{
3473 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3474 			 (*pretvar)->lVal = (LONG)ent->charging;
3475 			 break;
3476 		}
3477 		case _ep_aiflag_blocking:
3478 		{
3479 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3480 			 (*pretvar)->lVal = (LONG)ent->blocking;
3481 			 break;
3482 		}
3483 		case _ep_aiflag_falling:
3484 		{
3485 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3486 			 (*pretvar)->lVal = (LONG)ent->falling;
3487 			 break;
3488 		}
3489 		case _ep_aiflag_running:
3490 		{
3491 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3492 			 (*pretvar)->lVal = (LONG)ent->running;
3493 			 break;
3494 		}
3495 		case _ep_aiflag_inpain:
3496 		{
3497 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3498 			 (*pretvar)->lVal = (LONG)ent->inpain;
3499 			 break;
3500 		}
3501 		case _ep_aiflag_pain_time:
3502 		{
3503 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3504 			 (*pretvar)->lVal = (LONG)ent->pain_time;
3505 			 break;
3506 		}
3507 		case _ep_aiflag_projectile:
3508 		{
3509 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3510 			 (*pretvar)->lVal = (LONG)ent->projectile;
3511 			 break;
3512 		}
3513 		case _ep_aiflag_frozen:
3514 		{
3515 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3516 			(*pretvar)->lVal = (LONG)ent->frozen;
3517 			break;
3518 		}
3519 		case _ep_aiflag_freezetime:
3520 		{
3521 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3522 			(*pretvar)->lVal = (LONG)ent->freezetime;
3523 			break;
3524 		}
3525 		case _ep_aiflag_toexplode:
3526 		{
3527 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3528 			 (*pretvar)->lVal = (LONG)ent->toexplode;
3529 			 break;
3530 		}
3531 		case _ep_aiflag_animating:
3532 		{
3533 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3534 			 (*pretvar)->lVal = (LONG)ent->animating;
3535 			 break;
3536 		}
3537 		case _ep_aiflag_blink:
3538 		{
3539 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3540 			 (*pretvar)->lVal = (LONG)ent->blink;
3541 			 break;
3542 		}
3543 		case _ep_aiflag_invincible:
3544 		{
3545 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3546 			 (*pretvar)->lVal = (LONG)ent->invincible;
3547 			 break;
3548 		}
3549 		case _ep_aiflag_autokill:
3550 		{
3551 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3552 			 (*pretvar)->lVal = (LONG)ent->autokill;
3553 			 break;
3554 		}
3555 		case _ep_aiflag_walking:
3556 		{
3557 			 ScriptVariant_Clear(*pretvar); // depracated, just don't let it crash
3558 			 break;
3559 		}
3560 		default:
3561 			ScriptVariant_Clear(*pretvar);
3562 			return E_FAIL;
3563 		}
3564 		break;
3565 	}
3566 	case _ep_aimove:
3567 	{
3568 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3569 		(*pretvar)->lVal = (LONG)ent->modeldata.aimove;
3570 		break;
3571 	}
3572     case _ep_alpha:
3573 	{
3574 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3575 		(*pretvar)->lVal = (LONG)ent->modeldata.alpha;
3576 		break;
3577 	}
3578     case _ep_animal:
3579 	{
3580 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3581 		(*pretvar)->lVal = (LONG)ent->modeldata.animal;
3582 		break;
3583 	}
3584 	case _ep_animating:
3585 	{
3586 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3587 		(*pretvar)->lVal = (LONG)ent->animating;
3588 		break;
3589 	}
3590 	case _ep_animation:
3591 	{
3592 		ScriptVariant_ChangeType(*pretvar, VT_PTR);
3593 		(*pretvar)->ptrVal = (VOID*)ent->animation;
3594 		break;
3595 	}
3596 
3597 	/*
3598 	case _gep_animationid: See animnum.
3599 	*/
3600 
3601 	case _ep_animheight:
3602 	{
3603 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3604 		(*pretvar)->lVal = (LONG)ent->animation->height;
3605 		break;
3606 	}
3607 	case _ep_animhits:
3608 	{
3609 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3610 		(*pretvar)->lVal = (LONG)ent->animation->animhits;
3611 		break;
3612 	}
3613 	case _ep_animnum:
3614 	case _ep_animationid:
3615 	{
3616 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3617 		(*pretvar)->lVal = (LONG)ent->animnum;
3618 		break;
3619 	}
3620 	case _ep_animpos:
3621 	{
3622 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3623 		(*pretvar)->lVal = (LONG)ent->animpos;
3624 		break;
3625 	}
3626 	case _ep_animvalid:
3627 	{
3628 		ltemp = 0;
3629 		if(paramCount == 3)
3630 		{
3631 			arg = varlist[2];
3632 			if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
3633 			ltemp = (LONG)0;
3634 		}
3635 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3636 		(*pretvar)->lVal = (LONG)validanim(ent, ltemp);
3637 		break;
3638 	}
3639 	case _ep_antigrab:
3640 	{
3641 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
3642 		(*pretvar)->dblVal = (DOUBLE)ent->modeldata.antigrab;
3643 		break;
3644 	}
3645 	case _ep_antigravity:
3646 	{
3647 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
3648 		(*pretvar)->dblVal = (DOUBLE)ent->antigravity;
3649 		break;
3650 	}
3651 	case _ep_attack:
3652 	{
3653 		if(paramCount<6) break;
3654 		arg = varlist[2];
3655 		if(arg->vt != VT_INTEGER)
3656 		{
3657 			printf("Error, getentityproperty({ent}, 'attack', {sub property}, {index}, {animation}, {frame}): You must give a string name for {sub property}.\n");
3658 			return E_FAIL;
3659 		}
3660 		ltemp = arg->lVal;
3661 
3662 		if(varlist[3]->vt != VT_INTEGER
3663 			|| varlist[4]->vt != VT_INTEGER
3664 			|| varlist[5]->vt != VT_INTEGER)
3665 		{
3666 			printf("\n Error, getentityproperty({ent}, 'attack', {sub property}, {index}, {animation}, {frame}): {Animation} or {frame} parameter is missing or invalid. \n");
3667 			return E_FAIL;
3668 		}
3669 
3670 		//varlist[3]->lval														//Attack box index (multiple attack boxes).
3671 		i		= varlist[4]->lVal;												//Animation parameter.
3672 		tempint	= varlist[5]->lVal;												//Frame parameter.
3673 
3674 		if(!validanim(ent,i) || !ent->modeldata.animation[i]->attacks || !ent->modeldata.animation[i]->attacks[tempint])	//Verify animation and active attack on frame.
3675 		{
3676 			break;
3677 		}
3678 
3679 		attack = ent->modeldata.animation[i]->attacks[tempint];					//Get attack struct.
3680 
3681 		switch(ltemp)
3682 		{
3683 			case _gep_attack_blockflash:
3684 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3685 				 (*pretvar)->lVal = (LONG)attack->blockflash;
3686 				 break;
3687 			case _gep_attack_blocksound:
3688 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3689 				 (*pretvar)->lVal = (LONG)attack->blocksound;
3690 				 break;
3691 			case _gep_attack_coords:
3692 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3693 				 (*pretvar)->lVal = (LONG)attack->attack_coords[varlist[6]->lVal];
3694 				 break;
3695 			case _gep_attack_counterattack:
3696 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3697 				 (*pretvar)->lVal = (LONG)attack->counterattack;
3698 				 break;
3699 			case _gep_attack_direction:
3700 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3701 				 (*pretvar)->lVal = (LONG)attack->force_direction;
3702 				 break;
3703 			case _gep_attack_dol:
3704 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3705 				 (*pretvar)->lVal = (LONG)attack->damage_on_landing;
3706 				 break;
3707 			case _gep_attack_dot:
3708 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3709 				 (*pretvar)->lVal = (LONG)attack->dot;
3710 				 break;
3711 			case _gep_attack_dotforce:
3712 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3713 				 (*pretvar)->lVal = (LONG)attack->dot_force;
3714 				 break;
3715 			case _gep_attack_dotindex:
3716 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3717 				 (*pretvar)->lVal = (LONG)attack->dot_index;
3718 				 break;
3719 			case _gep_attack_dotrate:
3720 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3721 				 (*pretvar)->lVal = (LONG)attack->dot_rate;
3722 				 break;
3723 			case _gep_attack_dottime:
3724 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3725 				 (*pretvar)->lVal = (LONG)attack->dot_time;
3726 				 break;
3727 			case _gep_attack_drop:
3728 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3729 				 (*pretvar)->lVal = (LONG)attack->attack_drop;
3730 				 break;
3731 			case _gep_attack_dropv:
3732 				 ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
3733 				 (*pretvar)->dblVal = (DOUBLE)attack->dropv[varlist[6]->lVal];
3734 				 break;
3735 			case _gep_attack_force:
3736 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3737 				 (*pretvar)->lVal = (LONG)attack->attack_force;
3738 				 break;
3739 			case _gep_attack_forcemap:
3740 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3741 				 (*pretvar)->lVal = (LONG)attack->forcemap;
3742 				 break;
3743 			case _gep_attack_freeze:
3744 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3745 				 (*pretvar)->lVal = (LONG)attack->freeze;
3746 				 break;
3747 			case _gep_attack_freezetime:
3748 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3749 				 (*pretvar)->lVal = (LONG)attack->freezetime;
3750 				 break;
3751 			case _gep_attack_grab:
3752 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3753 				 (*pretvar)->lVal = (LONG)attack->grab;
3754 				 break;
3755 			case _gep_attack_grabdistance:
3756 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3757 				 (*pretvar)->lVal = (LONG)attack->grab_distance;
3758 				 break;
3759 			case _gep_attack_guardcost:
3760 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3761 				 (*pretvar)->lVal = (LONG)attack->guardcost;
3762 				 break;
3763 			case _gep_attack_hitflash:
3764 				ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3765 				(*pretvar)->lVal = (LONG)attack->hitflash;
3766 				break;
3767 			case _gep_attack_hitsound:
3768 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3769 				 (*pretvar)->lVal = (LONG)attack->hitsound;
3770 				 break;
3771 			case _gep_attack_jugglecost:
3772 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3773 				 (*pretvar)->lVal = (LONG)attack->jugglecost;
3774 				 break;
3775 			case _gep_attack_maptime:
3776 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3777 				 (*pretvar)->lVal = (LONG)attack->maptime;
3778 				 break;
3779 			case _gep_attack_noblock:
3780 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3781 				 (*pretvar)->lVal = (LONG)attack->no_block;
3782 				 break;
3783 			case _gep_attack_noflash:
3784 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3785 				 (*pretvar)->lVal = (LONG)attack->no_flash;
3786 				 break;
3787 			case _gep_attack_nokill:
3788 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3789 				 (*pretvar)->lVal = (LONG)attack->no_kill;
3790 				 break;
3791 			case _gep_attack_nopain:
3792 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3793 				 (*pretvar)->lVal = (LONG)attack->no_pain;
3794 				 break;
3795 			case _gep_attack_otg:
3796 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3797 				 (*pretvar)->lVal = (LONG)attack->otg;
3798 				 break;
3799 			case _gep_attack_pause:
3800 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3801 				 (*pretvar)->lVal = (LONG)attack->pause_add;
3802 				 break;
3803 			case _gep_attack_seal:
3804 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3805 				 (*pretvar)->lVal = (LONG)attack->seal;
3806 				 break;
3807 			case _gep_attack_sealtime:
3808 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3809 				 (*pretvar)->lVal = (LONG)attack->sealtime;
3810 				 break;
3811 			case _gep_attack_staydown:
3812 				 ScriptVariant_ChangeType(*pretvar, VT_PTR);
3813 				 (*pretvar)->ptrVal = (VOID*)attack->staydown;
3814 				 break;
3815 			case _gep_attack_steal:
3816 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3817 				 (*pretvar)->lVal = (LONG)attack->steal;
3818 				 break;
3819 			case _gep_attack_type:
3820 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3821 				 (*pretvar)->lVal = (LONG)attack->attack_type;
3822 				 break;
3823 			default:
3824 				ScriptVariant_Clear(*pretvar);
3825 				return E_FAIL;
3826 		}
3827 		break;
3828 	}
3829 	case _ep_attacking:
3830 	{
3831 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3832 		(*pretvar)->lVal = (LONG)ent->attacking;
3833 		break;
3834 	}
3835 	case _ep_attackid:
3836 	{
3837 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3838 		(*pretvar)->lVal = (LONG)ent->attack_id;
3839 		break;
3840 	}
3841 	case _ep_autokill:
3842 	{
3843 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3844 		(*pretvar)->lVal = (LONG)ent->autokill;
3845 		break;
3846 	}
3847 	case _ep_base:
3848 	{
3849 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
3850 		(*pretvar)->dblVal = (DOUBLE)ent->base;
3851 		break;
3852 	}
3853 	case _ep_vulnerable:
3854 	{
3855 		if(paramCount==2){
3856 			i		= ent->animnum;
3857 			tempint	= ent->animpos;
3858 		}
3859 		else if(paramCount<4
3860 			|| varlist[2]->vt != VT_INTEGER
3861 			|| varlist[3]->vt != VT_INTEGER)
3862 		{
3863 			printf("\n Error, getentityproperty({ent}, \"vulnerable\", {animation}, {frame}): parameters missing or invalid. \n");
3864 			return E_FAIL;
3865 		}else{
3866 			i		= varlist[2]->lVal;												//Animation parameter.
3867 			tempint	= varlist[3]->lVal;												//Frame parameter.
3868 		}
3869 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3870 		(*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->vulnerable[tempint];
3871 		break;
3872 	}
3873 	case _ep_bbox:
3874 	{
3875 		if(paramCount<6
3876 			|| varlist[2]->vt != VT_INTEGER
3877 			|| varlist[3]->vt != VT_INTEGER
3878 			|| varlist[4]->vt != VT_INTEGER
3879 			|| varlist[5]->vt != VT_INTEGER)
3880 		{
3881 			printf("\n Error, getentityproperty({ent}, \"bbox\", {index}, {animation}, {frame}, {arg}): parameters  missing or invalid. \n");
3882 			return E_FAIL;
3883 		}
3884 
3885 		//varlist[2]->lval;														//bbox index (multiple bbox support).
3886 		i		= varlist[3]->lVal;												//Animation parameter.
3887 		tempint	= varlist[4]->lVal;												//Frame parameter.
3888 
3889 		if(!ent->modeldata.animation[i]->vulnerable[tempint])
3890 		{
3891 
3892 			ScriptVariant_Clear(*pretvar);
3893 			break;
3894 		}
3895 
3896 		coords = ent->modeldata.animation[i]->bbox_coords[tempint];
3897 
3898 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3899 		(*pretvar)->lVal = (LONG)coords[varlist[5]->lVal];
3900 		break;
3901 	}
3902 	case _ep_blink:
3903 	{
3904 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3905 		(*pretvar)->lVal = (LONG)ent->blink;
3906 		break;
3907 	}
3908 	case _ep_blockback:
3909 	{
3910 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
3911 			ent->modeldata.blockback = (int)ltemp;
3912 		break;
3913 	}
3914 	case _ep_blockodds:
3915 	{
3916 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3917 		(*pretvar)->lVal = (LONG)ent->modeldata.blockodds;
3918 		break;
3919 	}
3920 	case _ep_blockpain:
3921 	{
3922 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
3923 			ent->modeldata.blockpain = (int)ltemp;
3924 		break;
3925 	}
3926 	case _ep_boss:
3927 	{
3928 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3929 		(*pretvar)->lVal = (LONG)ent->boss;
3930 		break;
3931 	}
3932 	case _ep_bounce:
3933 	{
3934 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3935 		(*pretvar)->lVal = (LONG)ent->modeldata.bounce;
3936 		break;
3937 	}
3938 	case _ep_bound:
3939 	{
3940 		ScriptVariant_ChangeType(*pretvar, VT_PTR);
3941 		(*pretvar)->ptrVal = (VOID*)ent->bound;
3942 		break;
3943 	}
3944 	case _ep_candamage:
3945 	{
3946 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3947 		(*pretvar)->lVal = (LONG)ent->modeldata.candamage;
3948 		break;
3949 	}
3950 	case _ep_combostep:
3951 	{
3952 		if(paramCount >= 3){
3953 			if(FAILED(ScriptVariant_IntegerValue(varlist[3], &ltemp2))){
3954 				*pretvar = NULL;
3955 				return E_FAIL;
3956 			}
3957 		}else ltemp2=0;
3958 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3959 		(*pretvar)->lVal = (LONG)ent->combostep[(int)ltemp2];
3960 		break;
3961 	}
3962 	case _ep_combotime:
3963 	{
3964 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3965 		(*pretvar)->lVal = (LONG)ent->combotime;
3966 		break;
3967 	}
3968 	case _ep_hostile:
3969 	{
3970 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3971 		(*pretvar)->lVal = (LONG)ent->modeldata.hostile;
3972 		 break;
3973 	}
3974     case _ep_projectilehit:
3975 	{
3976 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3977 		(*pretvar)->lVal = (LONG)ent->modeldata.projectilehit;
3978 		break;
3979 	}
3980 	case _ep_chargerate:
3981 	{
3982 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3983 		(*pretvar)->lVal = (LONG)ent->modeldata.chargerate;
3984 		break;
3985 	}
3986 	case _ep_colourmap:
3987 	{
3988 		ScriptVariant_ChangeType(*pretvar, VT_PTR);
3989 		(*pretvar)->ptrVal = (VOID*)(ent->colourmap);
3990 		break;
3991 	}
3992 	case _ep_colourtable:
3993 	{
3994 		ScriptVariant_ChangeType(*pretvar, VT_PTR);
3995 		(*pretvar)->ptrVal = (VOID*)(ent->modeldata.colourmap[varlist[2]->lVal]);
3996 		break;
3997 	}
3998 	case _ep_damage_on_landing:
3999 	{
4000 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4001 		(*pretvar)->lVal = (LONG)ent->damage_on_landing;
4002 		break;
4003 	}
4004 	case _ep_dead:
4005 	{
4006 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4007 		(*pretvar)->lVal = (LONG)ent->dead;
4008 		break;
4009 	}
4010 	case _ep_defaultmodel:
4011 	case _ep_defaultname:
4012 	{
4013 		ScriptVariant_ChangeType(*pretvar, VT_STR);
4014 		strcpy(StrCache_Get((*pretvar)->strVal), ent->defaultmodel->name);
4015 		break;
4016 	}
4017 	case _ep_defense:
4018 	{
4019 		ltemp = 0;
4020 		if(paramCount >= 3)
4021 		{
4022 			if(FAILED(ScriptVariant_IntegerValue(varlist[2], &ltemp))){
4023 				printf("You must specify an attack type for your defense property.\n");
4024 				return E_FAIL;
4025 			}
4026 			ltemp2 = _gep_defense_factor;
4027 		}
4028 
4029 		if(paramCount >= 4){
4030 			if(FAILED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
4031 				return E_FAIL;
4032 		}
4033 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4034 
4035 		switch(ltemp2)
4036 		{
4037 		case _gep_defense_factor:
4038 		{
4039 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.defense[(int)ltemp].factor;
4040 			break;
4041 		}
4042 		case _gep_defense_blockpower:
4043 		{
4044 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.defense[(int)ltemp].blockpower;
4045 			break;
4046 		}
4047 		case _gep_defense_blockratio:
4048 		{
4049 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.defense[(int)ltemp].blockratio;
4050 			break;
4051 		}
4052 		case _gep_defense_blockthreshold:
4053 		{
4054 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.defense[(int)ltemp].blockthreshold;
4055 			break;
4056 		}
4057 		case _gep_defense_blocktype:
4058 		{
4059 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.defense[(int)ltemp].blocktype;
4060 			break;
4061 		}
4062 		case _gep_defense_knockdown:
4063 		{
4064 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.defense[(int)ltemp].knockdown;
4065 			break;
4066 		}
4067 		case _gep_defense_pain:
4068 		{
4069 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.defense[(int)ltemp].pain;
4070 			break;
4071 		}
4072 		default:
4073 			return E_FAIL;
4074 		}
4075 		break;
4076 	}
4077 	case _ep_detect:
4078 	{
4079 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4080 		(*pretvar)->lVal = (LONG)ent->modeldata.stealth.detect;
4081 		break;
4082 	}
4083 	case _ep_direction:
4084 	{
4085 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4086 		(*pretvar)->lVal = (LONG)ent->direction;
4087 		break;
4088 	}
4089 	case _ep_dot:
4090 	{
4091 		if(paramCount<4) break;
4092 
4093 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
4094 			i = (int)ltemp;
4095 
4096 		arg = varlist[3];
4097 		if(arg->vt != VT_INTEGER)
4098 		{
4099 			if(arg->vt != VT_STR)
4100 				printf("You must provide a string name for dot subproperty.\n\
4101                         ~'time'\n\
4102                         ~'mode'\n\
4103                         ~'force'\n\
4104                         ~'rate'\n\
4105                         ~'type'\n\
4106                         ~'owner'\n");
4107 			return E_FAIL;
4108 		}
4109 		switch(arg->lVal)
4110 		{
4111 		case _gep_dot_time:
4112 		{
4113 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4114 			 (*pretvar)->lVal = (LONG)ent->dot_time[i];
4115 			 break;
4116 		}
4117 		case _gep_dot_mode:
4118 		{
4119 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4120 			 (*pretvar)->lVal = (LONG)ent->dot[i];
4121 			 break;
4122 		}
4123 		case _gep_dot_force:
4124 
4125 		{
4126 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4127 			 (*pretvar)->lVal = (LONG)ent->dot_force[i];
4128 			 break;
4129 		}
4130 		case _gep_dot_rate:
4131 		{
4132 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4133 			 (*pretvar)->lVal = (LONG)ent->dot_rate[i];
4134 			 break;
4135 		}
4136 		case _gep_dot_type:
4137 		{
4138 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4139 			 (*pretvar)->lVal = (LONG)ent->dot_atk[i];
4140 			 break;
4141 		}
4142 		case _gep_dot_owner:
4143 		{
4144 			 ScriptVariant_ChangeType(*pretvar, VT_PTR);
4145 			 (*pretvar)->ptrVal = (VOID*)ent->dot_owner[i];
4146 			 break;
4147 		}
4148 		break;
4149 		}
4150 	}
4151 	case _ep_dropframe:
4152 	{
4153 		ltemp = 0;
4154 		if(paramCount == 3)
4155 		{
4156 			arg = varlist[2];
4157 			if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
4158 			ltemp = (LONG)0;
4159 		}
4160 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4161 		(*pretvar)->lVal = (LONG)ent->modeldata.animation[ltemp]->dropframe;
4162 		break;
4163 	}
4164 	case _ep_edelay:
4165 	{
4166 		arg = varlist[2];
4167 		if(arg->vt != VT_INTEGER)
4168 		{
4169 			if(arg->vt != VT_STR)
4170 				printf("You must provide a string name for edelay subproperty.\n\
4171                         ~'cap_max'\n\
4172                         ~'cap_min'\n\
4173                         ~'factor'\n\
4174                         ~'mode'\n\
4175                         ~'range_max'\n\
4176                         ~'range_min'\n");
4177 			return E_FAIL;
4178 		}
4179 		ltemp = arg->lVal;
4180 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4181 
4182 		switch(ltemp)
4183 		{
4184 		case _gep_edelay_mode:
4185 		{
4186 			(*pretvar)->lVal = (LONG)ent->modeldata.edelay.mode;
4187 			break;
4188 		}
4189 		case _gep_edelay_factor:
4190 		{
4191 			(*pretvar)->dblVal = (float)ent->modeldata.edelay.factor;
4192 			break;
4193 		}
4194 		case _gep_edelay_cap_min:
4195 		{
4196 			(*pretvar)->lVal = (LONG)ent->modeldata.edelay.cap_min;
4197 			break;
4198 		}
4199 		case _gep_edelay_cap_max:
4200 		{
4201 			(*pretvar)->lVal = (LONG)ent->modeldata.edelay.cap_max;
4202 			break;
4203 		}
4204 		case _gep_edelay_range_min:
4205 		{
4206 			(*pretvar)->lVal = (LONG)ent->modeldata.edelay.range_min;
4207 			break;
4208 		}
4209 		case _gep_edelay_range_max:
4210 		{
4211 			(*pretvar)->lVal = (LONG)ent->modeldata.edelay.range_max;
4212 			break;
4213 		}
4214 		default:
4215 			ScriptVariant_Clear(*pretvar);
4216 			return E_FAIL;
4217 		}
4218 		break;
4219 	}
4220 	case _ep_energycost:
4221 	{
4222 		if(paramCount<4) break;
4223 
4224 		if(varlist[2]->vt != VT_INTEGER)
4225 		{
4226 			if(varlist[2]->vt != VT_STR)
4227 				printf("You must provide a string name for energycost.\n\
4228                         ~'cost'\n\
4229                         ~'disable'\n\
4230                         ~'mponly'\n");
4231 			return E_FAIL;
4232 		}
4233 		ltemp	= varlist[2]->lVal;												//Subproperty.
4234 		i		= varlist[3]->lVal;												//Animation.
4235 
4236 		if(!validanim(ent,i))													//Verify animation.
4237 		{
4238 			break;
4239 		}
4240 
4241 		switch(ltemp)
4242 		{
4243 			case _gep_energycost_cost:
4244 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4245 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->energycost.cost;
4246 				 break;
4247 			case _gep_energycost_disable:
4248 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4249 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->energycost.disable;
4250 				 break;
4251 			case _gep_energycost_mponly:
4252 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4253 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->energycost.mponly;
4254 				 break;
4255 			default:
4256 				ScriptVariant_Clear(*pretvar);
4257 				return E_FAIL;
4258 		}
4259 		break;
4260 	}
4261 	case _ep_escapecount:
4262 	{
4263 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4264 		(*pretvar)->lVal = (LONG)ent->escapecount;
4265 		break;
4266 	}
4267 	case _ep_escapehits:
4268 	{
4269 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4270 		(*pretvar)->lVal = (LONG)ent->modeldata.escapehits;
4271 		break;
4272 	}
4273 	case _ep_exists:
4274 	{
4275 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4276 		(*pretvar)->lVal = (LONG)ent->exists;
4277 		break;
4278 	}
4279 	case _ep_falldie:
4280 	{
4281 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4282 		(*pretvar)->lVal = (LONG)ent->modeldata.falldie;
4283 		break;
4284 	}
4285 	case _ep_flash:
4286 	{
4287 		arg = varlist[2];
4288 		if(arg->vt != VT_INTEGER)
4289 		{
4290 			if(arg->vt != VT_STR)
4291 				printf("You must give a string name for flash property.\n");
4292 			return E_FAIL;
4293 		}
4294 		ltemp = arg->lVal;
4295 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4296 
4297 		switch(ltemp)
4298 		{
4299             case _gep_flash_block:
4300             {
4301                 i = ent->modeldata.bflash;
4302                 break;
4303             }
4304             case _gep_flash_def:
4305             {
4306                 i = ent->modeldata.flash;
4307                 break;
4308             }
4309             case _gep_flash_noattack:
4310             {
4311                 i = ent->modeldata.noatflash;
4312                 break;
4313             }
4314             default:
4315 			{
4316                 ScriptVariant_Clear(*pretvar);
4317                 return E_FAIL;
4318             }
4319 		}
4320 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4321 		(*pretvar)->lVal = (LONG)i;
4322 		break;
4323 	}
4324 	case _ep_pain_time:
4325 	{
4326 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4327 		(*pretvar)->lVal = (LONG)ent->pain_time;
4328 		break;
4329 	}
4330 	case _ep_freezetime:
4331 	{
4332 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4333 		(*pretvar)->lVal = (LONG)ent->freezetime;
4334 		break;
4335 	}
4336 	case _ep_frozen:
4337 	{
4338 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4339 		(*pretvar)->lVal = (LONG)ent->frozen;
4340 		break;
4341 	}
4342 	case _ep_gfxshadow:
4343 	{
4344 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4345 		(*pretvar)->lVal = (LONG)ent->modeldata.gfxshadow;
4346 		break;
4347 	}
4348 	case _ep_grabbing:
4349 	{
4350 		if(ent->grabbing) // always return an empty var if it is NULL
4351 		{
4352 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
4353 			(*pretvar)->ptrVal = (VOID*)ent->grabbing;
4354 		}
4355 		break;
4356 	}
4357 	case _ep_grabforce:
4358 	{
4359 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4360 		(*pretvar)->lVal = (LONG)ent->modeldata.grabforce;
4361 		break;
4362 	}
4363 	case _ep_guardpoints:
4364 	{
4365 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4366 		(*pretvar)->lVal = (LONG)ent->modeldata.guardpoints.current;
4367 		break;
4368 	}
4369 	case _ep_health:
4370 	{
4371 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4372 		(*pretvar)->lVal = (LONG)ent->health;
4373 		break;
4374 	}
4375 	case _ep_height:
4376 	{
4377 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4378 		(*pretvar)->lVal = (LONG)ent->modeldata.height;
4379 		break;
4380 	}
4381 	case _ep_hitbyid:
4382 	{
4383 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4384 		(*pretvar)->lVal = (LONG)ent->hit_by_attack_id;
4385 		break;
4386 	}
4387 	case _ep_hmapl:
4388 	{
4389 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4390 		(*pretvar)->lVal = (LONG)ent->modeldata.maps.hide_start;
4391 		 break;
4392 	}
4393 	case _ep_hmapu:
4394 	{
4395 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4396 		(*pretvar)->lVal = (LONG)ent->modeldata.maps.hide_end;
4397 		 break;
4398 	}
4399 	case _ep_icon:
4400 	{
4401 	    arg = varlist[2];
4402 		if(arg->vt != VT_INTEGER)
4403 		{
4404 			if(arg->vt != VT_STR)
4405 				printf("You must provide a string name for icon subproperty:\n\
4406                         getentityproperty({ent}, 'icon', {subproperty});\n\
4407                         ~'default'\n\
4408                         ~'die'\n\
4409                         ~'get'\n\
4410                         ~'mphigh'\n\
4411                         ~'mplow'\n\
4412                         ~'mpmed'\n\
4413                         ~'pain'\n\
4414                         ~'weapon'\n\
4415                         ~'x'\n\
4416                         ~'y'\n");
4417 			return E_FAIL;
4418 		}
4419 		ltemp = arg->lVal;
4420 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4421 
4422 		switch(ltemp)
4423 		{
4424             case _gep_icon_def:
4425             {
4426                 i = ent->modeldata.icon.def;
4427                 break;
4428             }
4429             case _gep_icon_die:
4430             {
4431                 i = ent->modeldata.icon.die;
4432                 break;
4433             }
4434             case _gep_icon_get:
4435             {
4436                 i = ent->modeldata.icon.get;
4437                 break;
4438             }
4439             case _gep_icon_mphigh:
4440             {
4441                 i = ent->modeldata.icon.mphigh;
4442                 break;
4443             }
4444             case _gep_icon_mplow:
4445             {
4446                 i = ent->modeldata.icon.mplow;
4447                 break;
4448             }
4449             case _gep_icon_mpmed:
4450             {
4451                 i = ent->modeldata.icon.mpmed;
4452                 break;
4453             }
4454             case _gep_icon_pain:
4455             {
4456                 i = ent->modeldata.icon.pain;
4457                 break;
4458             }
4459             case _gep_icon_weapon:
4460             {
4461                 i = ent->modeldata.icon.weapon;
4462                 break;
4463             }
4464             case _gep_icon_x:
4465             {
4466                 i = ent->modeldata.icon.x;
4467                 break;
4468             }
4469             case _gep_icon_y:
4470             {
4471                 i = ent->modeldata.icon.y;
4472                 break;
4473             }
4474             default:
4475             {
4476                 ScriptVariant_Clear(*pretvar);
4477                 return E_FAIL;
4478             }
4479 		}
4480 
4481 		if (i >= 0)
4482 		{
4483 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
4484 			spr = sprite_map[i].node->sprite;
4485 			spr->centerx = sprite_map[i].centerx;
4486 			spr->centery = sprite_map[i].centery;
4487 			(*pretvar)->ptrVal = (VOID*)(spr);
4488 		}
4489 		else
4490 		{
4491 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4492 			(*pretvar)->lVal = -1;
4493 		}
4494 		break;
4495 	}
4496 	case _ep_invincible:
4497 	{
4498 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4499 		(*pretvar)->lVal = (LONG)ent->invincible;
4500 		break;
4501 	}
4502 	case _ep_invinctime:
4503 	{
4504 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4505 		(*pretvar)->lVal = (LONG)ent->invinctime;
4506 		break;
4507 	}
4508 	case _ep_jugglepoints:
4509 	{
4510 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4511 		(*pretvar)->lVal = (LONG)ent->modeldata.jugglepoints.current;
4512 		break;
4513 	}
4514 	case _ep_knockdowncount:
4515 	{
4516 	    /*
4517 	    2011_04_14, DC: Backward compatability; default to current if subproperty not provided.
4518 	    */
4519 	    if(paramCount<3)
4520 	    {
4521             ltemp = _gep_knockdowncount_current;
4522 	    }
4523 	    else
4524 	    {
4525             arg = varlist[2];
4526 
4527             if(arg->vt != VT_INTEGER)
4528             {
4529                 if(arg->vt != VT_STR)
4530                 {
4531                     printf("You must provide a string name for knockdowncount subproperty:\n\
4532                             getentityproperty({ent}, 'knockdowncount', {subproperty})\n\
4533                             ~'current'\n\
4534                             ~'max'\n\
4535                             ~'time'\n");
4536                     return E_FAIL;
4537                 }
4538             }
4539 
4540             ltemp = arg->lVal;
4541 	    }
4542 
4543 		switch(ltemp)
4544 		{
4545 			case _gep_knockdowncount_current:
4546                 ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4547                 (*pretvar)->dblVal = (DOUBLE)ent->knockdowncount;
4548 				break;
4549 			case _gep_knockdowncount_max:
4550                 ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4551                 (*pretvar)->dblVal = (DOUBLE)ent->modeldata.knockdowncount;
4552 				 break;
4553             case _gep_knockdowncount_time:
4554                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4555                 (*pretvar)->lVal = (LONG)ent->knockdowncount;
4556 				break;
4557 			default:
4558 				ScriptVariant_Clear(*pretvar);
4559 				return E_FAIL;
4560 		}
4561 		break;
4562 	}
4563 	case _ep_komap:
4564 	{
4565 		if(paramCount<2) break;
4566 
4567 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4568 		(*pretvar)->lVal = (LONG)ent->modeldata.maps.ko;
4569 		break;
4570 	}
4571 	case _ep_landframe:
4572 	{
4573 	    if(paramCount<4) break;
4574 
4575 		if(varlist[2]->vt != VT_INTEGER
4576 			|| varlist[3]->vt != VT_INTEGER)
4577 		{
4578 			printf("\n Error, getentityproperty({ent}, 'landframe', {sub property}, {animation}): {Sub property} or {Animation} parameter is missing or invalid. \n");
4579 			return E_FAIL;
4580 		}
4581 		ltemp	= varlist[2]->lVal;												//Subproperty.
4582 		i		= varlist[3]->lVal;												//Animation.
4583 
4584 		if(!validanim(ent,i))													//Verify animation.
4585 		{
4586 			break;
4587 		}
4588 
4589 		switch(ltemp)
4590 		{
4591 			case _gep_landframe_ent:
4592 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4593 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->landframe.ent;
4594 				 break;
4595 			case _gep_landframe_frame:
4596 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4597 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->landframe.frame;
4598 				 break;
4599 			default:
4600 				ScriptVariant_Clear(*pretvar);
4601 				return E_FAIL;
4602 		}
4603 		break;
4604 	}
4605 	case _ep_lifespancountdown:
4606 	{
4607 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4608 		(*pretvar)->dblVal = (DOUBLE)ent->lifespancountdown;
4609 		break;
4610 	}
4611 	case _ep_attackthrottle:
4612 	{
4613 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4614 		(*pretvar)->dblVal = (DOUBLE)ent->modeldata.attackthrottle;
4615 		break;
4616 	}
4617 	case _ep_attackthrottletime:
4618 	{
4619 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4620 		(*pretvar)->dblVal = (DOUBLE)ent->modeldata.attackthrottletime;
4621 		break;
4622 	}
4623 	case _ep_link:
4624 	{
4625 		if(ent->link) // always return an empty var if it is NULL
4626 		{
4627 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
4628 			(*pretvar)->ptrVal = (VOID*)ent->link;
4629 		}
4630 		break;
4631 	}
4632 	case _ep_map:
4633 	{
4634 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4635 		(*pretvar)->lVal = (LONG)0;
4636 		for(i=0;i<ent->modeldata.maps_loaded;i++)
4637 		{
4638 			if(ent->colourmap == ent->modeldata.colourmap[i])
4639 			{
4640 				(*pretvar)->lVal = (LONG)(i+1);
4641 				break;
4642 			}
4643 		}
4644 		break;
4645 	}
4646 	case _ep_mapcount:
4647 	{
4648 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4649 		(*pretvar)->lVal = (LONG)(ent->modeldata.maps_loaded+1);
4650 		 break;
4651 	}
4652 	case _ep_mapdefault:
4653 	{
4654 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4655 		(*pretvar)->lVal = (LONG)(ent->map);
4656 		 break;
4657 	}
4658 	case _ep_maps:
4659 	{
4660 	    arg = varlist[2];
4661 		if(arg->vt != VT_INTEGER)
4662 		{
4663 			if(arg->vt != VT_STR)
4664 				printf("You must give a string name for maps property.\n");
4665 			return E_FAIL;
4666 		}
4667 		ltemp = arg->lVal;
4668 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4669 
4670 		switch(ltemp)
4671 		{
4672 		    case _gep_maps_count:
4673             {
4674                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4675                 (*pretvar)->lVal = (LONG)(ent->modeldata.maps_loaded+1);
4676                 break;
4677             }
4678 
4679             case _gep_maps_current:
4680             {
4681                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4682                 (*pretvar)->lVal = (LONG)0;
4683                 for(i=0;i<ent->modeldata.maps_loaded;i++)
4684                 {
4685                     if(ent->colourmap == ent->modeldata.colourmap[i])
4686                     {
4687                         (*pretvar)->lVal = (LONG)(i+1);
4688                         break;
4689                     }
4690                 }
4691                 break;
4692             }
4693             case _gep_maps_dying:
4694             {
4695                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4696                 (*pretvar)->lVal = (LONG)(ent->dying);
4697                 break;
4698             }
4699             case _gep_maps_dying_critical:
4700             {
4701                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4702                 (*pretvar)->lVal = (LONG)(ent->per2);
4703                 break;
4704             }
4705             case _gep_maps_dying_low:
4706             {
4707                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4708                 (*pretvar)->lVal = (LONG)(ent->per1);
4709                 break;
4710             }
4711             case _gep_maps_frozen:
4712             {
4713                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4714                 (*pretvar)->lVal = (LONG)(ent->modeldata.maps.frozen);
4715                 break;
4716             }
4717             case _gep_maps_hide_end:
4718             {
4719                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4720                 (*pretvar)->lVal = (LONG)(ent->modeldata.maps.hide_end);
4721                 break;
4722             }
4723             case _gep_maps_hide_start:
4724             {
4725                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4726                 (*pretvar)->lVal = (LONG)(ent->modeldata.maps.hide_start);
4727                 break;
4728             }
4729             case _gep_maps_ko:
4730             {
4731                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4732                 (*pretvar)->lVal = (LONG)(ent->modeldata.maps.ko);
4733                 break;
4734             }
4735             case _gep_maps_kotype:
4736             {
4737                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4738                 (*pretvar)->lVal = (LONG)(ent->modeldata.maps.kotype);
4739                 break;
4740             }
4741             case _gep_maps_table:
4742             {
4743                 ScriptVariant_ChangeType(*pretvar, VT_PTR);
4744                 (*pretvar)->ptrVal = (VOID*)(ent->colourmap);
4745                 break;
4746             }
4747             case _gep_maps_time:
4748             {
4749                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4750                 (*pretvar)->lVal = (LONG)(ent->maptime);
4751                 break;
4752             }
4753             default:
4754             {
4755                 ScriptVariant_Clear(*pretvar);
4756                 return E_FAIL;
4757             }
4758 		}
4759 		break;
4760 	}
4761 	case _ep_maxguardpoints:
4762 	{
4763 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4764 		(*pretvar)->lVal = (LONG)ent->modeldata.guardpoints.maximum;
4765 		break;
4766 	}
4767 	case _ep_maxhealth:
4768 	{
4769 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4770 		(*pretvar)->lVal = (LONG)ent->modeldata.health;
4771 		break;
4772 	}
4773 	case _ep_maxjugglepoints:
4774 	{
4775 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4776 		(*pretvar)->lVal = (LONG)ent->modeldata.jugglepoints.maximum;
4777 		break;
4778 	}
4779 	case _ep_maxmp:
4780 	{
4781 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4782 		(*pretvar)->lVal = (LONG)ent->modeldata.mp;
4783 		break;
4784 	}
4785 	case _ep_model:
4786 	{
4787 		ScriptVariant_ChangeType(*pretvar, VT_STR);
4788 		strcpy(StrCache_Get((*pretvar)->strVal), ent->model->name);
4789 		break;
4790 	}
4791 	case _ep_mp:
4792 	{
4793 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4794 		(*pretvar)->lVal = (LONG)ent->mp;
4795 		break;
4796 	}
4797 	case _ep_mpdroprate:
4798 	{
4799 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4800 		(*pretvar)->lVal = (LONG)ent->modeldata.mpdroprate;
4801 		break;
4802 	}
4803 	case _ep_mprate:
4804 	{
4805 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4806 		(*pretvar)->lVal = (LONG)ent->modeldata.mprate;
4807 		break;
4808 	}
4809 	case _ep_mpstable:
4810 	{
4811 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4812 		(*pretvar)->lVal = (LONG)ent->modeldata.mpstable;
4813 		break;
4814 	}
4815 	case _ep_mpstableval:
4816 	{
4817 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4818 		(*pretvar)->lVal = (LONG)ent->modeldata.mpstableval;
4819 		break;
4820 	}
4821 	case _ep_name:
4822 	{
4823 		ScriptVariant_ChangeType(*pretvar, VT_STR);
4824 		strcpy(StrCache_Get((*pretvar)->strVal), ent->name);
4825 		break;
4826 	}
4827 	case _ep_nextanim:
4828 	{
4829 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4830 		(*pretvar)->lVal = (LONG)ent->nextanim;
4831 		break;
4832 	}
4833 	case _ep_nextthink:
4834 	{
4835 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4836 		(*pretvar)->lVal = (LONG)ent->nextthink;
4837 		break;
4838 	}
4839 	case _ep_no_adjust_base:
4840 	{
4841 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4842 		(*pretvar)->lVal = (LONG)ent->modeldata.no_adjust_base;
4843 		break;
4844 	}
4845 	case _ep_noaicontrol:
4846 	{
4847 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4848 		(*pretvar)->lVal = (LONG)ent->noaicontrol;
4849 		break;
4850 	}
4851 	case _ep_nodieblink:
4852 	{
4853 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4854 		(*pretvar)->lVal = (LONG)ent->modeldata.nodieblink;
4855 		break;
4856 	}
4857 	case _ep_nodrop:
4858 	{
4859 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4860 		(*pretvar)->lVal = (LONG)ent->modeldata.nodrop;
4861 		break;
4862 	}
4863 	case _ep_nograb:
4864 	{
4865 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4866 		(*pretvar)->lVal = (LONG)ent->nograb;
4867 		break;
4868 	}
4869 	case _ep_nolife:
4870 	{
4871 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4872 		(*pretvar)->lVal = (LONG)ent->modeldata.nolife;
4873 		break;
4874 	}
4875 	case _ep_nopain:
4876 	{
4877 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4878 		(*pretvar)->lVal = (LONG)ent->modeldata.nopain;
4879 		break;
4880 	}
4881 	case _ep_offense:
4882 	{
4883 		ltemp = 0;
4884 		if(paramCount >= 3)
4885 		{
4886 			arg = varlist[2];
4887 			if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
4888 				ltemp = (LONG)0;
4889 		}
4890 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4891 		(*pretvar)->dblVal = (DOUBLE)ent->offense_factors[(int)ltemp];
4892 		break;
4893 	}
4894 	case _ep_opponent:
4895 	{
4896 		if(ent->opponent) // always return an empty var if it is NULL
4897 		{
4898 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
4899 			(*pretvar)->ptrVal = (VOID*)ent->opponent;
4900 		}
4901 		break;
4902 	}
4903 	case _ep_owner:
4904 	{
4905 		if(ent->owner) // always return an empty var if it is NULL
4906 		{
4907 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
4908 			(*pretvar)->ptrVal = (VOID*)ent->owner;
4909 		}
4910 		break;
4911 	}
4912 	case _ep_parent:
4913 	{
4914 		if(ent->parent) // always return an empty var if it is NULL
4915 		{
4916 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
4917 			(*pretvar)->ptrVal = (VOID*)ent->parent;
4918 		}
4919 		break;
4920 	}
4921 	case _ep_path:
4922 	{
4923 		ScriptVariant_ChangeType(*pretvar, VT_STR);
4924 		tempstr = ent->modeldata.path;
4925 
4926 		strcpy(StrCache_Get((*pretvar)->strVal), tempstr);
4927 		break;
4928 	}
4929 	case _ep_pathfindstep:
4930 	{
4931 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4932 		(*pretvar)->dblVal = (DOUBLE)ent->modeldata.pathfindstep;
4933 		//printf("%d %s %d\n", ent->sortid, ent->name, ent->playerindex);
4934 		break;
4935 	}
4936 	case _ep_playerindex:
4937 	{
4938 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4939 		(*pretvar)->lVal = (LONG)ent->playerindex;
4940 		//printf("%d %s %d\n", ent->sortid, ent->name, ent->playerindex);
4941 		break;
4942 	}
4943     case _ep_projectile:
4944 	{
4945 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4946 		(*pretvar)->lVal = (LONG)ent->projectile;
4947 		break;
4948 	}
4949 	case _ep_range:
4950 	{
4951 		if(paramCount<4) break;
4952 
4953 		if(varlist[2]->vt != VT_INTEGER
4954 			|| varlist[3]->vt != VT_INTEGER)
4955 		{
4956 			printf("\n Error, getentityproperty({ent}, 'range', {sub property}, {animation}): {Sub property} or {Animation} parameter is missing or invalid. \n");
4957 			return E_FAIL;
4958 		}
4959 		ltemp	= varlist[2]->lVal;												//Subproperty.
4960 		i		= varlist[3]->lVal;												//Animation.
4961 
4962 		if(!validanim(ent,i))													//Verify animation.
4963 		{
4964 			break;
4965 		}
4966 
4967 		switch(ltemp)
4968 		{
4969 			case _gep_range_amax:
4970 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4971 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.amax;
4972 				 break;
4973 			case _gep_range_amin:
4974 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4975 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.amin;
4976 				 break;
4977 			case _gep_range_bmax:
4978 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4979 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.bmax;
4980 				 break;
4981 			case _gep_range_bmin:
4982 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4983 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.bmin;
4984 				 break;
4985 			case _gep_range_xmax:
4986 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4987 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.xmax;
4988 				 break;
4989 			case _gep_range_xmin:
4990 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4991 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.xmin;
4992 				 break;
4993 			case _gep_range_zmax:
4994 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4995 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.zmax;
4996 				 break;
4997 			case _gep_range_zmin:
4998 				 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4999 				 (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.zmin;
5000 				 break;
5001 			default:
5002 				ScriptVariant_Clear(*pretvar);
5003 				return E_FAIL;
5004 		}
5005 		break;
5006 
5007 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5008 		(*pretvar)->lVal = (LONG)coords[varlist[4]->lVal];
5009 		break;
5010 	}
5011 	case _ep_running:
5012 	{
5013 		if(paramCount<3) break;
5014 		arg = varlist[2];
5015 		if(arg->vt != VT_INTEGER)
5016 		{
5017 			if(arg->vt != VT_STR)
5018 				printf("You must give a string name for running property.\n");
5019 			return E_FAIL;
5020 		}
5021 		ltemp = arg->lVal;
5022 		switch(ltemp)
5023 		{
5024 		case _gep_running_speed:
5025 		{
5026 			 ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5027 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.runspeed;
5028 			break;
5029 		}
5030 		case _gep_running_jumpy:
5031 		{
5032 			 ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5033 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.runjumpheight;
5034 			break;
5035 		}
5036 		case _gep_running_jumpx:
5037 		{
5038 			 ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5039 			(*pretvar)->dblVal = (DOUBLE)ent->modeldata.runjumpdist;
5040 			break;
5041 		}
5042 		case _gep_running_land:
5043 		{
5044 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5045 			(*pretvar)->lVal = (LONG)ent->modeldata.runhold;
5046 			break;
5047 		}
5048 		case _gep_running_movez:
5049 		{
5050 			 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5051 			 (*pretvar)->lVal = (LONG)ent->modeldata.runupdown;
5052 			 break;
5053 		}
5054 		}
5055 		break;
5056 	}
5057 	case _ep_rush_count:
5058 	{
5059 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5060 		(*pretvar)->lVal = (LONG)ent->rush[0];
5061 		break;
5062 	}
5063 	case _ep_rush_tally:
5064 	{
5065 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5066 		(*pretvar)->lVal = (LONG)ent->rush[1];
5067 		break;
5068 	}
5069 	case _ep_rush_time:
5070 	{
5071 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5072 		(*pretvar)->lVal = (LONG)ent->rushtime;
5073 		break;
5074 	}
5075 	case _ep_score:
5076 	{
5077 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5078 		(*pretvar)->lVal = (LONG)ent->modeldata.score;
5079 		break;
5080 	}
5081 	case _ep_scroll:
5082 	{
5083 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5084 		(*pretvar)->dblVal = (DOUBLE)ent->modeldata.scroll;
5085 		break;
5086 	}
5087 	case _ep_seal:
5088 	{
5089 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5090 		(*pretvar)->lVal = (LONG)ent->seal;
5091 		break;
5092 	}
5093 	case _ep_sealtime:
5094 	{
5095 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5096 		(*pretvar)->lVal = (LONG)ent->sealtime;
5097 		break;
5098 	}
5099 	case _ep_setlayer:
5100 	{
5101 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5102 		(*pretvar)->lVal = (LONG)ent->modeldata.setlayer;
5103 		break;
5104 	}
5105 	case _ep_spawntype:
5106 	{
5107 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5108 		(*pretvar)->lVal = (LONG)ent->spawntype;
5109 		break;
5110 	}
5111 	case _ep_speed:
5112 	{
5113 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5114 		(*pretvar)->dblVal = (DOUBLE)ent->modeldata.speed;
5115 		break;
5116 	}
5117 	case _ep_sprite:
5118 	{
5119 		ScriptVariant_ChangeType(*pretvar, VT_PTR);
5120 		i = ent->animation->sprite[ent->animpos];
5121 		spr = sprite_map[i].node->sprite;
5122 		spr->centerx = sprite_map[i].centerx;
5123 		spr->centery = sprite_map[i].centery;
5124 		(*pretvar)->ptrVal = (VOID*)(spr);
5125 		break;
5126 	}
5127 	case _ep_spritea:
5128 	{
5129 		/*
5130 	    2011_04_17, DC: Modder can now specify animation and frame to return sprite from.
5131 	    To retain backward compatibility, sprite from current animation/frame is returned
5132 	    when animation and/or frame parameters are not provided.
5133 	    */
5134 
5135         ltemp   = varlist[2]->lVal;
5136         arg     = varlist[3];
5137         arg1    = varlist[4];
5138 
5139         /*
5140         Request from animation or frame that doesn't exist = shutdown.
5141         Let's be more user friendly then that; return empty so modder can evaluate
5142         and take action accordingly.*/
5143         if(!validanim(ent, arg->lVal) || !(ent->modeldata.animation[arg->lVal]->numframes >= arg1->lVal))
5144         {
5145             break;
5146         }
5147 
5148         i = ent->modeldata.animation[arg->lVal]->sprite[arg1->lVal];
5149 
5150 		switch(ltemp)
5151 		{
5152            case _gep_spritea_centerx:
5153             {
5154                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5155                 (*pretvar)->lVal = (LONG)sprite_map[i].centerx;
5156                 break;
5157             }
5158             case _gep_spritea_centery:
5159             {
5160                 ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5161                 (*pretvar)->lVal = (LONG)sprite_map[i].centery;
5162                 break;
5163             }
5164             case _gep_spritea_file:
5165             {
5166                 ScriptVariant_ChangeType(*pretvar, VT_STR);
5167                 strcpy(StrCache_Get((*pretvar)->strVal), sprite_map[i].node->filename);
5168                 break;
5169             }
5170             case _gep_spritea_sprite:
5171             {
5172                 ScriptVariant_ChangeType(*pretvar, VT_PTR);
5173                 spr = sprite_map[i].node->sprite;
5174                 spr->centerx = sprite_map[i].centery;
5175                 spr->centery = sprite_map[i].centery;
5176                 (*pretvar)->ptrVal = (VOID*)(spr);
5177                 break;
5178             }
5179             default:
5180 			{
5181                 ScriptVariant_Clear(*pretvar);
5182                 return E_FAIL;
5183             }
5184 		}
5185 
5186 		break;
5187 
5188 	}
5189 	case _ep_stalltime:
5190 	{
5191 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5192 		(*pretvar)->lVal = (LONG)ent->stalltime;
5193 		break;
5194 	}
5195 	case _ep_stats:
5196 	{
5197 		if(paramCount<4) break;
5198 		arg = varlist[2];
5199 		arg1 = varlist[3];
5200 
5201 		if(arg->vt != VT_INTEGER || arg1->vt != VT_INTEGER)
5202 		{
5203 			printf("Incorrect parameters: getentityproperty({ent}, 'stats', {type}, {index}) \n {type}: \n 0 = Model. \n 1 = Entity. \n");
5204 			return E_FAIL;
5205 		}
5206 
5207 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5208 
5209 		switch(arg->lVal)
5210 		{
5211 			default:
5212 				if (ent->modeldata.stats[arg1->lVal])
5213 					(*pretvar)->dblVal = (DOUBLE)ent->modeldata.stats[arg1->lVal];
5214 				break;
5215 			case 1:
5216 				if (ent->stats[arg1->lVal])
5217 					(*pretvar)->dblVal = (DOUBLE)ent->stats[arg1->lVal];
5218 				break;
5219 		}
5220 		break;
5221 	}
5222 	case _ep_staydown:
5223 	{
5224 		arg = varlist[2];
5225 		if(arg->vt != VT_INTEGER)
5226 		{
5227 			if(arg->vt != VT_STR)
5228 				printf("You must provide a string name for staydown property:\n\
5229                         getentityproperty({ent}, 'staydown', {subproperty})\n\
5230                         ~'rise'\n\
5231                         ~'riseattack'\n\
5232                         ~'riseattack_stall' \n");
5233 			return E_FAIL;
5234 		}
5235 		ltemp = arg->lVal;
5236 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5237 
5238 		switch(ltemp)
5239 		{
5240             case _gep_staydown_rise:
5241             {
5242                 i = ent->staydown.rise;
5243                 break;
5244             }
5245             case _gep_staydown_riseattack:
5246             {
5247                 i = ent->staydown.riseattack;
5248                 break;
5249             }
5250             case _gep_staydown_riseattack_stall:
5251             {
5252                 i = ent->staydown.riseattack_stall;
5253                 break;
5254             }
5255             default:
5256 			{
5257                 ScriptVariant_Clear(*pretvar);
5258                 return E_FAIL;
5259             }
5260 		}
5261 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5262 		(*pretvar)->lVal = (LONG)i;
5263 		break;
5264 	}
5265 	case _ep_stealth:
5266 	{
5267 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5268 		(*pretvar)->lVal = (LONG)ent->modeldata.stealth.hide;
5269 		break;
5270 	}
5271 	case _ep_subentity:
5272 	{
5273 		if(ent->subentity) // always return an empty var if it is NULL
5274 		{
5275 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
5276 			(*pretvar)->ptrVal = (VOID*)ent->subentity;
5277 		}
5278 		break;
5279 	}
5280 	case _ep_subject_to_gravity:
5281 	{
5282 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5283 		(*pretvar)->lVal = (LONG)ent->modeldata.subject_to_gravity;
5284 		break;
5285 	}
5286 	case _ep_subject_to_hole:
5287 	{
5288 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5289 		(*pretvar)->lVal = (LONG)ent->modeldata.subject_to_hole;
5290 		break;
5291 	}
5292 	case _ep_subject_to_maxz:
5293 	{
5294 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5295 		(*pretvar)->lVal = (LONG)ent->modeldata.subject_to_maxz;
5296 		break;
5297 	}
5298 	case _ep_subject_to_minz:
5299 	{
5300 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5301 		(*pretvar)->lVal = (LONG)ent->modeldata.subject_to_minz;
5302 		break;
5303 	}
5304 	case _ep_subject_to_obstacle:
5305 	{
5306 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5307 		(*pretvar)->lVal = (LONG)ent->modeldata.subject_to_obstacle;
5308 		break;
5309 	}
5310 	case _ep_subject_to_platform:
5311 	{
5312 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5313 		(*pretvar)->lVal = (LONG)ent->modeldata.subject_to_platform;
5314 		break;
5315 	}
5316 	case _ep_subject_to_screen:
5317 	{
5318 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5319 		(*pretvar)->lVal = (LONG)ent->modeldata.subject_to_screen;
5320 		break;
5321 	}
5322 	case _ep_subject_to_wall:
5323 	{
5324 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5325 		(*pretvar)->lVal = (LONG)ent->modeldata.subject_to_wall;
5326 		break;
5327 	}
5328 	case _ep_subtype:
5329 	{
5330 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5331 		(*pretvar)->lVal = (LONG)ent->modeldata.subtype;
5332 		break;
5333 	}
5334 	case _ep_thold:
5335 	{
5336 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5337 		(*pretvar)->lVal = (LONG)ent->modeldata.thold;
5338 		break;
5339 	}
5340 	case _ep_throwdamage:
5341 	{
5342 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5343 		(*pretvar)->lVal = (LONG)ent->modeldata.throwdamage;
5344 		break;
5345 	}
5346 	case _ep_throwdist:
5347 	{
5348 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5349 		(*pretvar)->dblVal = (DOUBLE)ent->modeldata.throwdist;
5350 		break;
5351 	}
5352 	case _ep_throwframewait:
5353 	{
5354 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5355 		(*pretvar)->lVal = (LONG)ent->modeldata.throwframewait;
5356 		break;
5357 	}
5358 	case _ep_throwheight:
5359 	{
5360 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5361 		(*pretvar)->dblVal = (DOUBLE)ent->modeldata.throwheight;
5362 		break;
5363 	}
5364 	case _ep_tosstime:
5365 	{
5366 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5367 		(*pretvar)->lVal = (LONG)ent->toss_time;
5368 		break;
5369 	}
5370 	case _ep_tossv:
5371 	{
5372 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5373 		(*pretvar)->dblVal = (DOUBLE)ent->tossv;
5374 		break;
5375 	}
5376 	case _ep_type:
5377 	{
5378 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5379 		(*pretvar)->lVal = (LONG)ent->modeldata.type;
5380 		break;
5381 	}
5382 	case _ep_weapent:
5383 	{
5384         ScriptVariant_ChangeType(*pretvar, VT_PTR);
5385         (*pretvar)->ptrVal = (VOID*)ent->weapent;
5386         break;
5387 	}
5388 	case _ep_x:
5389 	{
5390 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5391 		(*pretvar)->dblVal = (DOUBLE)ent->x;
5392 		break;
5393 	}
5394 	case _ep_xdir:
5395 	{
5396 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5397 		(*pretvar)->dblVal = (DOUBLE)ent->xdir;
5398 		break;
5399 	}
5400 	case _ep_z:
5401 	{
5402 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5403 		(*pretvar)->dblVal = (DOUBLE)ent->z;
5404 		break;
5405 	}
5406 	case _ep_zdir:
5407 	{
5408 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5409 		(*pretvar)->dblVal = (DOUBLE)ent->zdir;
5410 		break;
5411 	}
5412 	default:
5413 		//printf("Property name '%s' is not supported by function getentityproperty.\n", propname);
5414 		*pretvar = NULL;
5415 		return E_FAIL;
5416 		break;
5417 	}
5418 
5419 	return S_OK;
5420 }
5421 
5422 
5423 enum cep_energycost_enum {
5424     _cep_energycost_cost,
5425     _cep_energycost_disable,
5426     _cep_energycost_mponly,
5427     _cep_energycost_the_end,
5428 };
5429 
5430 enum cep_hostile_candamage_enum {
5431 	_cep_hcd_ground,
5432 	_cep_hcd_type_enemy,
5433 	_cep_hcd_type_npc,
5434 	_cep_hcd_type_obstacle,
5435 	_cep_hcd_type_player,
5436 	_cep_hcd_type_shot,
5437 	_cep_hcd_the_end,
5438 };
5439 
5440 enum cep_knockdowncount_enum {
5441     _cep_knockdowncount_current,
5442     _cep_knockdowncount_max,
5443     _cep_knockdowncount_time,
5444     _cep_knockdowncount_the_end,
5445 };
5446 
5447 enum cep_spritea_enum {
5448     _cep_spritea_centerx,
5449     _cep_spritea_centery,
5450     _cep_spritea_file,
5451     _cep_spritea_offsetx,
5452     _cep_spritea_offsety,
5453     _cep_spritea_sprite,
5454     _cep_spritea_the_end,
5455 };
5456 
5457 enum cep_staydown_enum {
5458     _cep_staydown_rise,
5459     _cep_staydown_riseattack,
5460     _cep_staydown_riseattack_stall,
5461     _cep_staydown_the_end,
5462 };
5463 
5464 enum cep_takeaction_enum {
5465 	_cep_ta_bomb_explode,
5466 	_cep_ta_common_attack_proc,
5467 	_cep_ta_common_block,
5468 	_cep_ta_common_drop,
5469 	_cep_ta_common_fall,
5470 	_cep_ta_common_get,
5471 	_cep_ta_common_grab,
5472 	_cep_ta_common_grabattack,
5473 	_cep_ta_common_grabbed,
5474 	_cep_ta_common_jump,
5475 	_cep_ta_common_land,
5476 	_cep_ta_common_lie,
5477 	_cep_ta_common_pain,
5478 	_cep_ta_common_prejump,
5479 	_cep_ta_common_rise,
5480 	_cep_ta_common_spawn,
5481 	_cep_ta_common_turn,
5482 	_cep_ta_common_vault,
5483 	_cep_ta_normal_prepare,
5484 	_cep_ta_npc_warp,
5485 	_cep_ta_player_blink,
5486 	_cep_ta_suicide,
5487 	_cep_ta_the_end,
5488 };
5489 
5490 enum cep_think_enum { // 2011_03_03, DC: Think types.
5491     _cep_th_common_think,
5492     _cep_th_player_think,
5493     _cep_th_steam_think,
5494     _cep_th_steamer_think,
5495     _cep_th_text_think,
5496     _cep_th_trap_think,
5497     _cep_th_the_end,
5498 };
5499 
mapstrings_changeentityproperty(ScriptVariant ** varlist,int paramCount)5500 void mapstrings_changeentityproperty(ScriptVariant** varlist, int paramCount)
5501 {
5502 	char* propname;
5503 	int prop, i;
5504 
5505     static const char* proplist_energycost[] = {
5506         "cost",
5507         "disable",
5508         "mponly",
5509     };
5510 
5511     static const char* proplist_hostile_candamage[] = {
5512         "ground",
5513         "type_enemy",
5514         "type_npc",
5515         "type_obstacle",
5516         "type_player",
5517         "type_shot",
5518     };
5519 
5520     static const char* proplist_knockdowncount[] = { //2011_04_14, DC: Knockdowncount colleciton.
5521 	    "current",
5522 	    "max",
5523 	    "time",
5524 	};
5525 
5526     static const char* proplist_spritea[] = {       //2011_05_15, DC: Sprite array.
5527         "centerx",
5528         "centery",
5529         "file",
5530         "offsetx",
5531         "offsety",
5532         "sprite",
5533 	};
5534 
5535     static const char* proplist_staydown[] = { //2011_04_08, DC: Staydown colleciton.
5536 	    "rise",
5537 	    "riseattack",
5538 	    "riseattack_stall",
5539 	};
5540 
5541 	static const char* proplist_takeaction[] = {
5542 		"bomb_explode",
5543 		"common_attack_proc",
5544 		"common_block",
5545 		"common_drop",
5546 		"common_fall",
5547 		"common_get",
5548 		"common_grab",
5549 		"common_grabattack",
5550 		"common_grabbed",
5551 		"common_jump",
5552 		"common_land",
5553 		"common_lie",
5554 		"common_pain",
5555 		"common_prejump",
5556 		"common_rise",
5557 		"common_spawn",
5558 		"common_turn",
5559 		"common_vault",
5560 		"normal_prepare",
5561 		"npc_warp",
5562 		"player_blink",
5563 		"suicide",
5564 	};
5565 
5566 	static const char* proplist_think[] = { // 2011_03_03, DC: Think types.
5567 		"common_think",
5568 		"player_think",
5569 		"steam_think",
5570 		"steamer_think",
5571 		"text_think",
5572 		"trap_think",
5573 	};
5574 
5575 	// property name
5576 	MAPSTRINGS(varlist[1], eplist, _ep_the_end,
5577 		"Property name '%s' is not supported by function changeentityproperty.\n");
5578 
5579     // AI flag name for aiflag
5580 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_aiflag))
5581 	{
5582 		MAPSTRINGS(varlist[2], eplist_aiflag, _ep_aiflag_the_end,
5583 			"Flag '%s' is not supported by 'aiflag'.\n");
5584 	}
5585 
5586 	//2011_03_31, DC: Energycost
5587 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_energycost))
5588 	{
5589 		MAPSTRINGS(varlist[2], proplist_energycost, _cep_energycost_the_end,
5590 			"Flag '%s' is not supported by 'energycost'.\n");
5591 	}
5592 
5593     // entity type(s) for hostile, candamage, and projectilehit.
5594 	if((varlist[1]->vt == VT_INTEGER) &&
5595 		((varlist[1]->lVal == _ep_hostile) || (varlist[1]->lVal == _ep_candamage) || (varlist[1]->lVal == _ep_projectilehit)))
5596 	{
5597 		for(i=2; i<paramCount; i++)
5598 		{
5599 			MAPSTRINGS(varlist[i], proplist_hostile_candamage, _cep_hcd_the_end,
5600 				"Entity type '%s' is not supported by 'hostile', 'candamage', or 'projectilehit'\n");
5601 		}
5602 	}
5603 
5604 	// 2011_04_14, DC: Knockdowncount
5605 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_knockdowncount))
5606 	{
5607 		MAPSTRINGS(varlist[2], proplist_knockdowncount, _cep_knockdowncount_the_end,
5608 			"Subproperty '%s' is not supported by 'knockdowncount'.\n");
5609 	}
5610 
5611 	// 2011_05_15, DC: Sprite array
5612 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_spritea))
5613 	{
5614 		MAPSTRINGS(varlist[2], proplist_spritea, _cep_spritea_the_end,
5615 			"Property name '%s' is not a known subproperty of 'spritea'.\n");
5616 	}
5617 
5618     // 2011_04_08, DC: Staydown
5619 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_staydown))
5620 	{
5621 		MAPSTRINGS(varlist[2], proplist_staydown, _cep_staydown_the_end,
5622 			"Subproperty '%s' is not supported by 'staydown'.\n");
5623 	}
5624 
5625 	// action for takeaction
5626 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_takeaction))
5627 	{
5628 		MAPSTRINGS(varlist[2], proplist_takeaction, _cep_ta_the_end,
5629 			"Action '%s' is not supported by 'takeaction'.\n");
5630 	}
5631 
5632     // 2011_03_13, DC: Think sets for think.
5633 	if((varlist[1]->vt == VT_INTEGER) && (varlist[1]->lVal == _ep_think))
5634 	{
5635 		MAPSTRINGS(varlist[2], proplist_think, _cep_th_the_end,
5636 			"Set '%s' is not supported by 'think'.\n");
5637 	}
5638 }
5639 
5640 //changeentityproperty(pentity, propname, value1[ ,value2, value3, ...]);
openbor_changeentityproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)5641 HRESULT openbor_changeentityproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
5642 {
5643 	entity* ent = NULL;
5644 	s_model* tempmodel ;
5645 	char* tempstr = NULL;
5646 	LONG ltemp, ltemp2;
5647 	DOUBLE dbltemp;
5648 	int propind;
5649 	int i = 0;
5650 
5651 	static const void* actions[] = { // for takeaction
5652 		bomb_explode,
5653 		common_attack_proc,
5654 		common_block,
5655 		common_drop,
5656 		common_fall,
5657 		common_get,
5658 		common_grab,
5659 		common_grabattack,
5660 		common_grabbed,
5661 		common_jump,
5662 		common_land,
5663 		common_lie,
5664 		common_pain,
5665 		common_prejump,
5666 		common_rise,
5667 		common_spawn,
5668 		common_turn,
5669 		common_vault,
5670 		normal_prepare,
5671 		npc_warp,
5672 		player_blink,
5673 		suicide,
5674 	};
5675 
5676 	static const int entitytypes[] = {
5677         0, // "ground"; not a real entity type
5678         TYPE_ENEMY,
5679         TYPE_NPC,
5680         TYPE_OBSTACLE,
5681         TYPE_PLAYER,
5682         TYPE_SHOT,
5683 
5684     };
5685 
5686 	static const void* think[] = { // 2011_03_03, DC: Think types.
5687 		common_think,
5688 		player_think,
5689 		steam_think,
5690 		steamer_think,
5691 		text_think,
5692 		trap_think,
5693 	};
5694 
5695 	*pretvar = NULL;
5696 
5697 	if(paramCount < 3)
5698 	{
5699 		printf("Function changeentityproperty must have have at least 3 parameters.");
5700 		goto changeentityproperty_error;
5701 	}
5702 
5703 	mapstrings_changeentityproperty(varlist, paramCount);
5704 
5705 	if(varlist[0]->vt != VT_PTR && varlist[0]->vt != VT_EMPTY)
5706 	{
5707 		printf("Function changeentityproperty must have a valid entity handle.");
5708 		goto changeentityproperty_error;
5709 	}
5710 	ent = (entity*)varlist[0]->ptrVal; //retrieve the entity
5711 	if(!ent)
5712 	{
5713 		return S_OK;
5714 	}
5715 
5716 	if(varlist[1]->vt != VT_INTEGER)
5717 	{
5718 		if(varlist[1]->vt != VT_STR)
5719 			printf("Function changeentityproperty must have a string property name.\n");
5720 		goto changeentityproperty_error;
5721 	}
5722 
5723 	propind = varlist[1]->lVal;
5724 
5725 	switch(propind)
5726 	{
5727     case _ep_aggression:
5728 	{
5729 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5730 			ent->modeldata.aggression = (int)ltemp;
5731 		break;
5732 	}
5733 	case _ep_aiattack:
5734 	{
5735 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5736 			ent->modeldata.aiattack = (int)ltemp;
5737 		break;
5738 	}
5739 	case _ep_aiflag:
5740 	{
5741 		if(varlist[2]->vt != VT_INTEGER)
5742 		{
5743 			if(varlist[2]->vt != VT_STR)
5744 				printf("You must give a string value for AI flag name.\n");
5745 			goto changeentityproperty_error;
5746 		}
5747 		if(paramCount<4) break;
5748 
5749 		switch(varlist[2]->lVal)
5750 		{
5751 		case _ep_aiflag_dead:
5752 		{
5753 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5754 				ent->dead = (int)ltemp;
5755 			break;
5756 		}
5757 		case _ep_aiflag_jumpid:
5758 		{
5759 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5760 				ent->jumpid = (int)ltemp;
5761 			break;
5762 		}
5763 		case _ep_aiflag_jumping:
5764 		{
5765 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5766 				ent->jumping = (int)ltemp;
5767 			break;
5768 		}
5769 		case _ep_aiflag_idling:
5770 		{
5771 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5772 				ent->idling = (int)ltemp;
5773 			break;
5774 		}
5775 		case _ep_aiflag_drop:
5776 		{
5777 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5778 				ent->drop = (int)ltemp;
5779 			break;
5780 		}
5781 		case _ep_aiflag_attacking:
5782 		{
5783 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5784 				ent->attacking = (int)ltemp;
5785 			break;
5786 		}
5787 		case _ep_aiflag_getting:
5788 		{
5789 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5790 				ent->getting = (int)ltemp;
5791 			break;
5792 		}
5793 		case _ep_aiflag_turning:
5794 		{
5795 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5796 				 ent->turning = (int)ltemp;
5797 			 break;
5798 		}
5799 		case _ep_aiflag_charging:
5800 		{
5801 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5802 				 ent->charging = (int)ltemp;
5803 			 break;
5804 		}
5805 		case _ep_aiflag_blocking:
5806 		{
5807 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5808 				 ent->blocking = (int)ltemp;
5809 			 break;
5810 		}
5811 		case _ep_aiflag_falling:
5812 		{
5813 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5814 				 ent->falling = (int)ltemp;
5815 			 break;
5816 		}
5817 		case _ep_aiflag_running:
5818 		{
5819 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5820 				  ent->running = (int)ltemp;
5821 			 break;
5822 		}
5823 		case _ep_aiflag_inpain:
5824 		{
5825 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5826 				  ent->inpain = (int)ltemp;
5827 			 break;
5828 		}
5829 		case _ep_aiflag_projectile:
5830 		{
5831 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5832 				  ent->projectile = (int)ltemp;
5833 			 break;
5834 		}
5835 		case _ep_aiflag_frozen:
5836 		{
5837 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5838 				  ent->frozen = (int)ltemp;
5839 			 break;
5840 		}
5841 		case _ep_aiflag_toexplode:
5842 		{
5843 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5844 				  ent->toexplode = (int)ltemp;
5845 			 break;
5846 		}
5847 		case _ep_aiflag_animating:
5848 		{
5849 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5850 				  ent->animating = (int)ltemp;
5851 			 break;
5852 		}
5853 		case _ep_aiflag_blink:
5854 		{
5855 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5856 				  ent->blink = (int)ltemp;
5857 			 break;
5858 		}
5859 		case _ep_aiflag_invincible:
5860 		{
5861 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5862 				  ent->invincible = (int)ltemp;
5863 			 break;
5864 		}
5865 		case _ep_aiflag_autokill:
5866 		{
5867 			 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
5868 				  ent->autokill = (int)ltemp;
5869 			 break;
5870 		}
5871 		case _ep_aiflag_walking:
5872 		{
5873 			 // do nothing, deprecated property
5874 			 break;
5875 		}
5876 		default:
5877 			printf("Unknown AI flag.\n");
5878 			goto changeentityproperty_error;
5879 		}
5880 		break;
5881 	}
5882 	case _ep_aimove:
5883 	{
5884 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5885 			ent->modeldata.aimove = (int)ltemp;
5886 		break;
5887 	}
5888 	case _ep_alpha:
5889 	{
5890 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5891 			ent->modeldata.alpha = (int)ltemp;
5892 		break;
5893 	}
5894     case _ep_animation:
5895 	{
5896 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5897 		{
5898 			ltemp2 = (LONG)1;
5899 			if(paramCount < 4 || SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
5900 				ent_set_anim(ent, (int)ltemp, (int)ltemp2);
5901 		}
5902 		break;
5903 	}
5904 	case _ep_animhits:
5905 	{
5906 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5907 			ent->animation->animhits = (int)ltemp;
5908 		break;
5909 	}
5910 	case _ep_animpos:
5911 	{
5912 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5913 			ent->animpos = (int)ltemp;
5914 		break;
5915 	}
5916 	case _ep_antigrab:
5917 	{
5918 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5919 			ent->modeldata.antigrab = (int)ltemp;
5920 		break;
5921 	}
5922     case _ep_antigravity:
5923 	{
5924 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
5925 			ent->modeldata.antigravity = (float)dbltemp;
5926 		break;
5927 	}
5928 	case _ep_attacking:
5929 	{
5930 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5931 		   ent->attacking = (int)ltemp;
5932 		break;
5933 	}
5934 	case _ep_attackid:
5935 	{
5936 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5937 			ent->attack_id = (int)ltemp;
5938 		break;
5939 	}
5940     case _ep_autokill:
5941 	{
5942 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5943 			ent->autokill = (int)ltemp;
5944 		break;
5945 	}
5946 	case _ep_base:
5947 	{
5948 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
5949 			ent->base = (float)dbltemp;
5950 		break;
5951 	}
5952 	case _ep_blink:
5953 	{
5954 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5955 			ent->blink = (int)ltemp;
5956 		break;
5957 	}
5958 	case _ep_blockback:
5959 	{
5960 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5961 			ent->modeldata.blockback = (int)ltemp;
5962 		break;
5963 	}
5964     case _ep_blockodds:
5965 	{
5966 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5967 			ent->modeldata.blockodds = (int)ltemp;
5968 		break;
5969 	}
5970 	case _ep_blockpain:
5971 	{
5972 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5973 			ent->modeldata.blockpain = (int)ltemp;
5974 		break;
5975 	}
5976 	case _ep_boss:
5977 	{
5978 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5979 			ent->boss = (int)ltemp;
5980 		break;
5981 	}
5982 	case _ep_bounce:
5983 	{
5984 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
5985 			ent->modeldata.bounce = (int)ltemp;
5986 		break;
5987 	}
5988 	case _ep_candamage:
5989 	{
5990 		if(varlist[2]->vt == VT_INTEGER && paramCount==3 && (varlist[2]->lVal&TYPE_RESERVED)){ //trick for those who don't use string map
5991 			ent->modeldata.candamage = varlist[2]->lVal;
5992 			break;
5993 		}
5994 
5995 		ent->modeldata.candamage = 0;
5996 
5997 		for(i=2; i<paramCount; i++)
5998 		{
5999 			if(varlist[i]->vt == VT_INTEGER) // known entity type
6000 			{
6001 				ltemp = varlist[i]->lVal;
6002 				if(ltemp==_cep_hcd_ground) // "ground" - not needed?
6003 					ent->modeldata.ground = 1;
6004 				else
6005 					ent->modeldata.candamage |= entitytypes[(int)ltemp];
6006 			}
6007 			else
6008 			{
6009 				printf("You must pass one or more string constants for candamage entity type.\n");
6010 				goto changeentityproperty_error;
6011 			}
6012 		}
6013 		break;
6014 	}
6015 	case _ep_combostep:
6016 	{
6017 		if(paramCount >= 4 &&
6018 		  SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) &&
6019 		  SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
6020 			ent->combostep[(int)ltemp]=(int)ltemp2;
6021 		break;
6022 	}
6023 	case _ep_combotime:
6024 	{
6025 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6026 			ent->combotime = (int)ltemp;
6027 		break;
6028 	}
6029 	case _ep_colourmap:
6030 	{
6031 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6032 			self->colourmap = self->modeldata.colourmap[ltemp-1];
6033 		break;
6034 	}
6035 	case _ep_damage_on_landing:
6036 	{
6037 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6038 			ent->damage_on_landing = (int)ltemp;
6039 		break;
6040 	}
6041     case _ep_dead:
6042 	{
6043 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6044 			ent->dead = (int)ltemp;
6045 		break;
6046 	}
6047     case _ep_defaultname:
6048 	{
6049 		if(varlist[2]->vt != VT_STR)
6050 		{
6051 			printf("You must give a string value for entity name.\n");
6052 			goto changeentityproperty_error;
6053 		}
6054 		tempmodel = findmodel((char*)StrCache_Get(varlist[2]->strVal));
6055 		if(!tempmodel)
6056 		{
6057 			printf("Use must give an existing model's name for entity's default model name.\n");
6058 			goto changeentityproperty_error;
6059 		}
6060 		ent->defaultmodel = tempmodel;
6061 		break;
6062 	}
6063 	case _ep_defense:
6064 	{
6065 		if((ltemp2 =
6066 		  (paramCount >= 4 &&
6067 		   SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) &&
6068 		   ltemp < (LONG)MAX_ATKS && ltemp >= (LONG)0 &&
6069 			SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6070 		))
6071 			ent->modeldata.defense[(int)ltemp].factor = (float)dbltemp;
6072 
6073 		if(paramCount >= 5 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp))))
6074 			ent->modeldata.defense[(int)ltemp].pain = (float)dbltemp;
6075 		if(paramCount >= 6 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp))))
6076 			ent->modeldata.defense[(int)ltemp].knockdown = (float)dbltemp;
6077 		if(paramCount >= 7 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[6], &dbltemp))))
6078 			ent->modeldata.defense[(int)ltemp].blockpower = (float)dbltemp;
6079 		if(paramCount >= 8 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[7], &dbltemp))))
6080 			ent->modeldata.defense[(int)ltemp].blockthreshold = (float)dbltemp;
6081 		if(paramCount >= 9 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[8], &dbltemp))))
6082 			ent->modeldata.defense[(int)ltemp].blockratio = (float)dbltemp;
6083 		if(paramCount >= 10 && ltemp2 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[9], &dbltemp)))
6084 			ent->modeldata.defense[(int)ltemp].blocktype = (float)dbltemp;
6085 
6086 		break;
6087 	}
6088     case _ep_detect:
6089 	{
6090 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6091 			ent->modeldata.stealth.detect = (int)ltemp;
6092 		break;
6093 	}
6094 	case _ep_direction:
6095 	{
6096 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6097 			ent->direction = (int)dbltemp;
6098 		break;
6099 	}
6100 	case _ep_dot:
6101 	{
6102 		if((SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp))))
6103 		{
6104 			i = (int)ltemp;
6105 			if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6106 				ent->dot_time[i] = (int)dbltemp;
6107 			if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
6108 				ent->dot[i] = (int)dbltemp;
6109 			if(paramCount >= 6 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp)))
6110 				ent->dot_force[i] = (int)dbltemp;
6111 			if(paramCount >= 7 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[6], &dbltemp)))
6112 				ent->dot_rate[i] = (int)dbltemp;
6113 			if(paramCount >= 8 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[7], &dbltemp)))
6114 				ent->dot_atk[i] = (int)dbltemp;
6115 			if(paramCount >= 9)
6116 				ent->dot_owner[i] = (entity*)varlist[8]->ptrVal;
6117 		}
6118 		break;
6119 	}
6120 	case _ep_edelay:
6121 	{
6122 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6123 			ent->modeldata.edelay.mode = (int)ltemp;
6124 		if(paramCount >= 3 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6125 			ent->modeldata.edelay.factor = (float)dbltemp;
6126 		if(paramCount >= 4 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
6127 			ent->modeldata.edelay.cap_min = (int)ltemp;
6128 		if(paramCount >= 5 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
6129 			ent->modeldata.edelay.cap_max = (int)ltemp;
6130 		if(paramCount >= 6 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[6], &ltemp)))
6131 			ent->modeldata.edelay.range_min = (int)ltemp;
6132 		if(paramCount >= 7 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[7], &ltemp)))
6133 			ent->modeldata.edelay.range_max = (int)ltemp;
6134 
6135 		break;
6136 	}
6137 	case _ep_energycost:
6138 	{
6139 		if(paramCount != 5)
6140 		{
6141 			printf("\n Error, changeentityproperty({ent}, 'energycost', {subproperty}, {animation}, {value}): Invalid or missing parameter. \n");
6142 			goto changeentityproperty_error;
6143 		}
6144 
6145 		if(FAILED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6146 		{
6147 			printf("\n Error, changeentityproperty has invalid animation id.\n");
6148 			goto changeentityproperty_error;
6149 		}
6150 
6151 		i = (int)ltemp;
6152 
6153 		if(!validanim(ent,i))
6154 		{
6155 			printf("\n Error, changeentityproperty({ent}, 'energycost', {subproperty}, {animation}, {value}): {animation} parameter invalid. Make sure the animation exists. \n");
6156 			goto changeentityproperty_error;
6157 		}
6158 
6159 		if(varlist[2]->vt != VT_INTEGER)
6160 		{
6161 			printf("You must give a string value for energycost flag name.\n");
6162 			goto changeentityproperty_error;
6163 		}
6164 
6165 		switch(varlist[2]->lVal)
6166 		{
6167 		case _cep_energycost_cost:
6168 		{
6169 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
6170 				ent->modeldata.animation[i]->energycost.cost = (int)ltemp;
6171 			break;
6172 		}
6173 		case _cep_energycost_disable:
6174 		{
6175 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
6176 				ent->modeldata.animation[i]->energycost.disable = (int)ltemp;
6177 			break;
6178 		}
6179 		case _cep_energycost_mponly:
6180 		{
6181 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
6182 				ent->modeldata.animation[i]->energycost.mponly = (int)ltemp;
6183 			break;
6184 		}
6185 		default:
6186 			printf("Unknown Energycost flag.\n");
6187 			goto changeentityproperty_error;
6188 		}
6189 		break;
6190 	}
6191 	case _ep_escapecount:
6192 	{
6193 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6194 			ent->escapecount = (int)ltemp;
6195 		break;
6196 	}
6197 	case _ep_escapehits:
6198 	{
6199 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6200 			ent->modeldata.escapehits = (int)ltemp;
6201 		break;
6202 	}
6203     case _ep_falldie:
6204 	{
6205 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6206 			ent->modeldata.falldie = (int)ltemp;
6207 		break;
6208 	}
6209 	case _ep_playerindex:
6210 	{
6211 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6212 			ent->playerindex = (int)ltemp;
6213 		break;
6214 	}
6215 	case _ep_pain_time:
6216 	{
6217 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6218 			ent->pain_time = (int)ltemp;
6219 		break;
6220 	}
6221 	case _ep_freezetime:
6222 	{
6223 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6224 			ent->freezetime = (int)ltemp;
6225 		break;
6226 	}
6227 	case _ep_frozen:
6228 	{
6229 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6230 			ent->frozen = (int)ltemp;
6231 		break;
6232 	}
6233     case _ep_gfxshadow:
6234 	{
6235 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6236 			ent->modeldata.gfxshadow = (int)ltemp;
6237 		break;
6238 	}
6239     case _ep_grabforce:
6240 	{
6241 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6242 			ent->modeldata.grabforce = (int)ltemp;
6243 		break;
6244 	}
6245 	case _ep_guardpoints:
6246 	{
6247 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6248 			ent->modeldata.guardpoints.current = (int)ltemp;
6249 		break;
6250 	}
6251     case _ep_health:
6252 	{
6253 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6254 		{
6255 			ent->health = (int)ltemp;
6256 			if(ent->health > ent->modeldata.health) ent->health = ent->modeldata.health;
6257 			else if(ent->health < 0) ent->health = 0;
6258 		}
6259 		break;
6260 	}
6261     case _ep_hitbyid:
6262 	{
6263 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6264 			ent->hit_by_attack_id = (int)ltemp;
6265 		break;
6266 	}
6267     case _ep_hmapl:
6268 	{
6269 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6270 			self->modeldata.maps.hide_start = ltemp;
6271 		break;
6272 	}
6273 	case _ep_hmapu:
6274 	{
6275 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6276 			self->modeldata.maps.hide_end = ltemp;
6277 		break;
6278 	}
6279     case _ep_hostile:
6280 	{
6281 
6282 		if(varlist[2]->vt == VT_INTEGER && paramCount==3 && (varlist[2]->lVal&TYPE_RESERVED)){ //trick for those who don't use string map
6283 			ent->modeldata.hostile = varlist[2]->lVal;
6284 			break;
6285 		}
6286 
6287 		ent->modeldata.hostile = 0;
6288 		for(i=2; i<paramCount; i++)
6289 		{
6290 			if(varlist[i]->vt == VT_INTEGER) // known entity type
6291 			{
6292 				ltemp = varlist[i]->lVal;
6293 				ent->modeldata.hostile |= entitytypes[(int)ltemp];
6294 			}
6295 			else
6296 			{
6297 				printf("You must pass one or more string constants for hostile entity type.\n");
6298 				goto changeentityproperty_error;
6299 			}
6300 		}
6301 
6302 		break;
6303 	}
6304 	case _ep_iconposition:
6305 	{
6306 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6307 			ent->modeldata.icon.x = (int)ltemp;
6308 		if(paramCount>3 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6309 			ent->modeldata.icon.y = (int)ltemp;
6310 		break;
6311 	}
6312 	case _ep_invincible:
6313 	{
6314 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6315 			ent->invincible = (int)ltemp;
6316 		break;
6317 	}
6318 	case _ep_invinctime:
6319 	{
6320 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6321 			ent->invinctime = (int)ltemp;
6322 		break;
6323 	}
6324 	case _ep_jugglepoints:
6325 	{
6326 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6327 			ent->modeldata.jugglepoints.current = (int)ltemp;
6328 		break;
6329 	}
6330 	case _ep_knockdowncount:
6331 	{
6332 		if(varlist[2]->vt != VT_INTEGER)
6333 		{
6334 			if(varlist[2]->vt != VT_STR)
6335 				printf("You must provide a string value for Knockdowncount subproperty:\n\
6336                         changeentityproperty({ent}, 'knockdowncount', {subproperty}, {value})\n\
6337                         ~'current'\n\
6338                         ~'max'\n\
6339                         ~'time'\n");
6340 			goto changeentityproperty_error;
6341 		}
6342 
6343 		switch(varlist[2]->lVal)
6344 		{
6345             case _cep_knockdowncount_current:
6346             {
6347                 if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6348                     ent->knockdowncount = (float)dbltemp;
6349 				break;
6350             }
6351             case _cep_knockdowncount_max:
6352             {
6353                 if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6354                     ent->modeldata.knockdowncount = (float)dbltemp;
6355 				break;
6356             case _cep_knockdowncount_time:
6357                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6358                     ent->knockdowntime = (int)ltemp;
6359 				break;
6360             }
6361             default:
6362                 printf("Unknown knockdowncount subproperty.\n");
6363                 goto changeentityproperty_error;
6364 		}
6365 		break;
6366 	}
6367     case _ep_komap:
6368 	{
6369 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6370 			ent->modeldata.maps.ko = (int)ltemp;
6371 		if(paramCount >= 4 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6372 			ent->modeldata.maps.kotype = (int)ltemp;
6373 		break;
6374 	}
6375     case _ep_lifeposition:
6376 	{
6377 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6378 			ent->modeldata.hpx = (int)ltemp;
6379 		if(paramCount>3 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6380 			ent->modeldata.hpy = (int)ltemp;
6381 		break;
6382 	}
6383     case _ep_lifespancountdown:
6384 	{
6385 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6386 			ent->lifespancountdown = (float)dbltemp;
6387 		break;
6388 	}
6389     case _ep_attackthrottle:
6390 	{
6391 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6392 			ent->modeldata.attackthrottle = (float)dbltemp;
6393 		break;
6394 	}
6395     case _ep_attackthrottletime:
6396 	{
6397 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6398 			ent->modeldata.attackthrottletime = (float)dbltemp;
6399 		break;
6400 	}
6401     case _ep_map:
6402 	{
6403 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6404 			ent_set_colourmap(ent, (int)ltemp);
6405 		break;
6406 	}
6407     case _ep_maptime:
6408 	{
6409 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6410 			ent->maptime = (int)ltemp;
6411 		break;
6412 	}
6413     case _ep_maxguardpoints:
6414 	{
6415 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6416 			ent->modeldata.guardpoints.maximum = (int)ltemp;
6417 		break;
6418 	}
6419 	case _ep_maxhealth:
6420 	{
6421 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6422 		{
6423 			ent->modeldata.health = (int)ltemp;
6424 			if(ent->modeldata.health < 0) ent->modeldata.health = 0; //OK, no need to have ot below 0
6425 		}
6426 		break;
6427 	}
6428 	case _ep_maxjugglepoints:
6429 	{
6430 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6431 			ent->modeldata.jugglepoints.maximum = (int)ltemp;
6432 		break;
6433 	}
6434     case _ep_maxmp:
6435 	{
6436 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6437 		{
6438 			ent->modeldata.mp = (int)ltemp;
6439 			if(ent->modeldata.mp < 0) ent->modeldata.mp = 0; //OK, no need to have ot below 0
6440 		}
6441 		break;
6442 	}
6443     case _ep_model:
6444 	{
6445 		if(varlist[2]->vt != VT_STR)
6446 		{
6447 			printf("You must give a string value for model name.\n");
6448 			goto changeentityproperty_error;
6449 		}
6450 		tempstr = (char*)StrCache_Get(varlist[2]->strVal);
6451 		if(paramCount > 3 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6452 		{
6453 			set_model_ex(ent, tempstr, -1, NULL, (int)ltemp);
6454 			if(!ent->weapent) ent->weapent = ent;
6455 		}
6456 		break;
6457 	}
6458     case _ep_mp:
6459 	{
6460 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6461 		{
6462 			ent->mp = (int)ltemp;
6463 			if(ent->mp > ent->modeldata.mp) ent->mp = ent->modeldata.mp;
6464 			else if(ent->mp < 0) ent->mp = 0;
6465 		}
6466 		break;
6467 	}
6468     case _ep_mpset:
6469 	{
6470 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6471 			ent->modeldata.mp = (int)dbltemp;
6472 		if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6473 			ent->modeldata.mpstable = (int)dbltemp;
6474 		if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
6475 			ent->modeldata.mpstableval = (int)dbltemp;
6476 		if(paramCount >= 6 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp)))
6477 			ent->modeldata.mprate = (int)dbltemp;
6478 		if(paramCount >= 7 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[6], &dbltemp)))
6479 			ent->modeldata.mpdroprate = (int)dbltemp;
6480 		if(paramCount >= 8 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[7], &dbltemp)))
6481 			ent->modeldata.chargerate = (int)dbltemp;
6482 		break;
6483 	}
6484     case _ep_name:
6485 	{
6486 		if(varlist[2]->vt != VT_STR)
6487 		{
6488 			printf("You must give a string value for entity name.\n");
6489 			goto changeentityproperty_error;
6490 		}
6491 		strcpy(ent->name, (char*)StrCache_Get(varlist[2]->strVal));
6492 		break;
6493 	}
6494     case _ep_nameposition:
6495 	{
6496 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6497 			ent->modeldata.namex = (int)ltemp;
6498 		if(paramCount>3 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6499 			ent->modeldata.namey = (int)ltemp;
6500 		break;
6501 	}
6502     case _ep_nextanim:
6503 	{
6504 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6505 			ent->nextanim = (int)ltemp;
6506 		break;
6507 	}
6508 	case _ep_nextthink:
6509 	{
6510 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6511 			ent->nextthink = (int)ltemp;
6512 		break;
6513 	}
6514     case _ep_no_adjust_base:
6515 	{
6516 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6517 			ent->modeldata.no_adjust_base = (int)ltemp;
6518 		break;
6519 	}
6520 	case _ep_noaicontrol:
6521 	{
6522 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6523 			ent->noaicontrol = (int)ltemp;
6524 		break;
6525 	}
6526 	case _ep_nodieblink:
6527 	{
6528 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6529 			ent->modeldata.nodieblink = (int)ltemp;
6530 		break;
6531 	}
6532     case _ep_nodrop:
6533 	{
6534 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6535 			ent->modeldata.nodrop = (int)ltemp;
6536 		break;
6537 	}
6538 	case _ep_nograb:
6539 	{
6540 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6541 			ent->nograb = (int)ltemp;
6542 		break;
6543 	}
6544 	case _ep_nolife:
6545 	{
6546 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6547 			ent->modeldata.nolife = (int)ltemp;
6548 		break;
6549 	}
6550 	case _ep_nopain:
6551 	{
6552 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6553 			ent->modeldata.nopain = (int)ltemp;
6554 		break;
6555 	}
6556     case _ep_offense:
6557 	{
6558 		if(paramCount >= 4 &&
6559 		   SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) &&
6560 		   ltemp < (LONG)MAX_ATKS && ltemp >= (LONG)0 &&
6561 			SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6562 				ent->offense_factors[(int)ltemp] = (float)dbltemp;
6563 		break;
6564 	}
6565     case _ep_opponent:
6566 	{
6567 		ent->opponent = (entity*)varlist[2]->ptrVal;
6568 		break;
6569 	}
6570     case _ep_owner:
6571 	{
6572 		ent->owner = (entity*)varlist[2]->ptrVal;
6573 		break;
6574 	}
6575 	case _ep_parent:
6576 	{
6577 		ent->parent = (entity*)varlist[2]->ptrVal;
6578 		break;
6579 	}
6580 	case _ep_pathfindstep:
6581 	{
6582 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6583 			ent->modeldata.pathfindstep = (float)dbltemp;
6584 		break;
6585 	}
6586     case _ep_position:
6587 	{
6588 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6589 			ent->x = (float)dbltemp;
6590 		if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6591 			ent->z = (float)dbltemp;
6592 		if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
6593 			ent->a = (float)dbltemp;
6594 		break;
6595 	}
6596     case _ep_projectile:
6597 	{
6598 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6599 			ent->projectile = (int)ltemp;
6600 		break;
6601 	}
6602     case _ep_projectilehit:
6603 	{
6604 		if(varlist[2]->vt == VT_INTEGER && paramCount==3 && (varlist[2]->lVal&TYPE_RESERVED)){ //trick for those who don't use string map
6605 			ent->modeldata.projectilehit = varlist[2]->lVal;
6606 			break;
6607 		}
6608 
6609 		ent->modeldata.projectilehit = 0;
6610 
6611 		for(i=2; i<paramCount; i++)
6612 		{
6613 			if(varlist[i]->vt == VT_INTEGER) // known entity type
6614 			{
6615 				ltemp = varlist[i]->lVal;
6616 				ent->modeldata.projectilehit |= entitytypes[(int)ltemp];
6617 			}
6618 			else
6619 			{
6620 				printf("You must pass one or more string constants for projectilehit entity type.\n");
6621 				goto changeentityproperty_error;
6622 			}
6623 		}
6624 
6625 		break;
6626 	}
6627     case _ep_running:
6628 	{
6629 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6630 			ent->modeldata.runspeed = (float)dbltemp;
6631 		if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6632 			ent->modeldata.runjumpheight = (float)dbltemp;
6633 		if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
6634 			ent->modeldata.runjumpdist = (float)dbltemp;
6635 		if(paramCount >= 6 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp)))
6636 			ent->modeldata.runhold = (int)dbltemp;
6637 		if(paramCount >= 7 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[6], &dbltemp)))
6638 			ent->modeldata.runupdown = (int)dbltemp;
6639 
6640 		break;
6641 	}
6642     case _ep_rush_count:
6643 	{
6644 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6645 			ent->rush[0] = (int)ltemp;
6646 		break;
6647 	}
6648 	case _ep_rush_tally:
6649 	{
6650 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6651 			ent->rush[1] = (int)ltemp;
6652 		break;
6653 	}
6654 	case _ep_rush_time:
6655 	{
6656 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6657 			ent->rushtime = (int)ltemp;
6658 		break;
6659 	}
6660 	case _ep_score:
6661 	{
6662 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6663 			ent->modeldata.score = (int)ltemp;
6664 		break;
6665 	}
6666     case _ep_scroll:
6667 	{
6668 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6669 			ent->modeldata.scroll = (float)dbltemp;
6670 		break;
6671 	}
6672     case _ep_seal:
6673 	{
6674 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6675 			ent->seal = (int)ltemp;
6676 		break;
6677 	}
6678 	case _ep_sealtime:
6679 	{
6680 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6681 			ent->sealtime = (int)ltemp;
6682 		break;
6683 	}
6684     case _ep_setlayer:
6685 	{
6686 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6687 			ent->modeldata.setlayer = (int)ltemp;
6688 		break;
6689 	}
6690 	case _ep_speed:
6691 	{
6692 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6693 			ent->modeldata.speed = (float)dbltemp;
6694 		break;
6695 	}
6696 	case _ep_spritea:
6697 	{
6698 	    if(varlist[2]->vt != VT_INTEGER)
6699 		{
6700 			if(varlist[2]->vt != VT_STR)
6701 				printf("You must provide a string value for Sprite Array subproperty:\n\
6702                         changeentityproperty({ent}, 'spritea', {subproperty}, {animation ID}, {frame}, {value})\n\
6703                         ~'centerx'\n\
6704                         ~'centery'\n\
6705                         ~'file'\n\
6706                         ~'offsetx'\n\
6707                         ~'sprite'\n");
6708 			goto changeentityproperty_error;
6709 		}
6710 
6711         ltemp   = varlist[2]->lVal;
6712 
6713         /*
6714         Failsafe checks. Any attempt to access a sprite property on invalid frame would cause instant shutdown.
6715         */
6716         if(!validanim(ent, varlist[3]->lVal) || !(ent->modeldata.animation[varlist[3]->lVal]->numframes >= varlist[4]->lVal) || paramCount<5)
6717         {
6718             break;
6719         }
6720 
6721         i = ent->modeldata.animation[varlist[3]->lVal]->sprite[varlist[4]->lVal];   //Get sprite index.
6722 
6723 		switch(ltemp)
6724 		{
6725             case _cep_spritea_centerx:
6726             {
6727                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
6728                     sprite_map[i].centerx = (int)ltemp;
6729 
6730                 break;
6731             }
6732             case _cep_spritea_centery:
6733             {
6734                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
6735                     sprite_map[i].centery = (int)ltemp;
6736                 break;
6737             }
6738             case _cep_spritea_file:
6739             {
6740                 if(varlist[5]->vt != VT_STR)
6741                 {
6742                     printf("You must provide a string value for file name.\n");
6743                     goto changeentityproperty_error;
6744                 }
6745                 strcpy(sprite_map[i].node->filename, (char*)StrCache_Get(varlist[5]->strVal));
6746                 break;
6747             }
6748 			/*
6749             case _cep_spritea_offsetx:
6750             {
6751                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
6752                 {
6753                     sprite_map[i].ofsx = (int)ltemp;
6754                     (*pretvar)->lVal = (LONG)1;
6755                 }
6756                 break;
6757             }
6758             case _cep_spritea_offsety:
6759             {
6760                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6761                 {
6762                     sprite_map[i].ofsy = (int)ltemp;
6763                     (*pretvar)->lVal = (LONG)1;
6764                 }
6765                 break;
6766             }*/
6767             case _cep_spritea_sprite:
6768             {
6769                 sprite_map[i].node->sprite = (VOID*)varlist[5]->ptrVal;
6770 
6771                 break;
6772             }
6773             default:
6774                 printf("Unknown Sprite Array subproperty.\n");
6775                 goto changeentityproperty_error;
6776 		}
6777 		break;
6778 	}
6779     case _ep_stalltime:
6780 	{
6781 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6782 			ent->stalltime = (int)ltemp;
6783 		break;
6784 	}
6785 	case _ep_stats:
6786 	{
6787 		if(paramCount<4) break;
6788 
6789 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6790 		{
6791 			if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
6792 			{
6793 				switch(varlist[2]->lVal)
6794 				{
6795 					default:
6796 						ent->modeldata.stats[(int)ltemp] = (float)dbltemp;
6797 						break;
6798 					case 1:
6799 						ent->stats[(int)ltemp] = (float)dbltemp;
6800 						break;
6801 				}
6802 			}
6803 		}
6804 		break;
6805 	}
6806 	case _ep_staydown:
6807 	{
6808 		if(varlist[2]->vt != VT_INTEGER)
6809 		{
6810 			if(varlist[2]->vt != VT_STR)
6811 				printf("You must provide a string value for Staydown subproperty:\n\
6812                         changeentityproperty({ent}, 'staydown', {subproperty}, {value})\n\
6813                         ~'rise'\n\
6814                         ~'riseattack'\n\
6815                         ~'riseattack_stall'\n");
6816 			goto changeentityproperty_error;
6817 		}
6818 		if(paramCount<4) break;
6819 
6820 		switch(varlist[2]->lVal)
6821 		{
6822             case _cep_staydown_rise:
6823             {
6824                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6825                     ent->staydown.rise = (int)ltemp;
6826                 break;
6827             }
6828             case _cep_staydown_riseattack:
6829             {
6830                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6831                     ent->staydown.riseattack = (int)ltemp;
6832                 break;
6833             }
6834             case _cep_staydown_riseattack_stall:
6835             {
6836                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6837                     ent->staydown.riseattack_stall = (int)ltemp;
6838                 break;
6839             }
6840             default:
6841                 printf("Unknown Staydown subproperty.\n");
6842                 goto changeentityproperty_error;
6843 		}
6844 		break;
6845 	}
6846     case _ep_stealth:
6847 	{
6848 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6849 			ent->modeldata.stealth.hide = (int)ltemp;
6850 		break;
6851 	}
6852     case _ep_subentity:
6853 	{
6854 		if(ent->subentity) ent->subentity->parent = NULL;
6855 		ent->subentity = (entity*)varlist[2]->ptrVal;
6856 		if(ent->subentity) ent->subentity->parent = ent;
6857 		break;
6858 	}
6859     case _ep_subject_to_gravity:
6860 	{
6861 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6862 			ent->modeldata.subject_to_gravity = (int)ltemp;
6863 		break;
6864 	}
6865 	case _ep_subject_to_hole:
6866 	{
6867 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6868 			ent->modeldata.subject_to_hole = (int)ltemp;
6869 		break;
6870 	}
6871 	case _ep_subject_to_maxz:
6872 	{
6873 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6874 			ent->modeldata.subject_to_maxz = (int)ltemp;
6875 		break;
6876 	}
6877 	case _ep_subject_to_minz:
6878 	{
6879 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6880 			ent->modeldata.subject_to_minz = (int)ltemp;
6881 		break;
6882 	}
6883 	case _ep_subject_to_obstacle:
6884 	{
6885 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6886 			ent->modeldata.subject_to_obstacle = (int)ltemp;
6887 		break;
6888 	}
6889 	case _ep_subject_to_platform:
6890 	{
6891 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6892 			ent->modeldata.subject_to_platform = (int)ltemp;
6893 		break;
6894 	}
6895 	case _ep_subject_to_screen:
6896 	{
6897 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6898 			ent->modeldata.subject_to_screen = (int)ltemp;
6899 		break;
6900 	}
6901 	case _ep_subject_to_wall:
6902 	{
6903 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6904 			ent->modeldata.subject_to_wall = (int)ltemp;
6905 		break;
6906 	}
6907 	case _ep_takeaction:
6908 	{
6909 		if(varlist[2]->vt == VT_STR)
6910 		{ // not a known action; if it were it would been mapped by mapstrings
6911 			ent->takeaction = NULL;
6912 			break;
6913 		}
6914 		else if(varlist[2]->vt != VT_INTEGER)
6915 		{
6916 			printf("You must give a string value for action type.\n");
6917 			goto changeentityproperty_error;
6918 		}
6919 
6920 		// otherwise, the parameter is a known action
6921 		ltemp = varlist[2]->lVal;
6922 		if((ltemp >= 0) && (ltemp < _cep_ta_the_end))
6923 		{
6924 			ent->takeaction = actions[(int)ltemp];
6925 		}
6926 
6927 		break;
6928 	}
6929 	case _ep_think:
6930 	{
6931 		if(varlist[2]->vt == VT_STR)
6932 		{ // not a known action; if it were it would been mapped by mapstrings
6933 			//ent->think = NULL;
6934 			break;
6935 		}
6936 		else if(varlist[2]->vt != VT_INTEGER)
6937 		{
6938 			printf("You must give a string value for think type.\n");
6939 			goto changeentityproperty_error;
6940 		}
6941 
6942 		// otherwise, the parameter is a known action
6943 		ltemp = varlist[2]->lVal;
6944 		if((ltemp >= 0) && (ltemp < _cep_th_the_end))
6945 		{
6946 			ent->think = think[(int)ltemp];
6947 		}
6948 
6949 		break;
6950 	}
6951 	case _ep_thold:
6952 	{
6953 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6954 			ent->modeldata.thold = (int)ltemp;
6955 		break;
6956 	}
6957     case _ep_throwdamage:
6958 	{
6959 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6960 			ent->modeldata.throwdamage = (int)ltemp;
6961 		break;
6962 	}
6963 	case _ep_throwdist:
6964 	{
6965 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6966 			ent->modeldata.throwdist = (float)dbltemp;
6967 		break;
6968 	}
6969 	case _ep_throwframewait:
6970 	{
6971 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6972 			ent->modeldata.throwframewait = (int)ltemp;
6973 		break;
6974 	}
6975 	case _ep_throwheight:
6976 	{
6977 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6978 			ent->modeldata.throwheight = (float)dbltemp;
6979 		break;
6980 	}
6981     case _ep_tosstime:
6982 	{
6983 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6984 			ent->toss_time = (int)ltemp;
6985 		break;
6986 	}
6987     case _ep_trymove:
6988 	{
6989 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6990 		{
6991 			if(ltemp == 1)
6992 				 ent->trymove = common_trymove;
6993 			else if(ltemp == 2)
6994 				 ent->trymove = player_trymove;
6995 			else
6996 				 ent->trymove = NULL;
6997 		}
6998 		break;
6999 	}
7000 	case _ep_type:
7001 	{
7002 		if(varlist[2]->vt != VT_INTEGER)
7003 		{
7004 			printf("You must provide a type constant for type.\n");
7005 			goto changeentityproperty_error;
7006 		}
7007 
7008 		ltemp = varlist[2]->lVal;
7009         ent->modeldata.type = (int)ltemp;
7010 
7011 		break;
7012 	}
7013     case _ep_velocity:
7014 	{
7015 		if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7016 			ent->xdir = (float)dbltemp;
7017 		if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
7018 			ent->zdir = (float)dbltemp;
7019 		if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
7020 			ent->tossv = (float)dbltemp;
7021 		break;
7022 	}
7023 	case _ep_weapon:
7024 	{
7025 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7026 		{
7027 			ltemp2 = (LONG)0;
7028 			if(paramCount < 4 ||  SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
7029 				set_weapon(ent, (int)ltemp, (int)ltemp2);
7030 		}
7031 		break;
7032 	}
7033 	default:
7034 		//printf("Property name '%s' is not supported by function changeentityproperty.\n", propname);
7035 		goto changeentityproperty_error;
7036 		break;
7037 	}
7038 
7039 	return S_OK;
7040 changeentityproperty_error:
7041 	return E_FAIL;
7042 }
openbor_tossentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7043 
7044 //tossentity(entity, height, speedx, speedz)
7045 HRESULT openbor_tossentity(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7046 {
7047 	entity* ent = NULL;
7048 	DOUBLE height=0, speedx=0, speedz=0;
7049 
7050 	if(paramCount < 1) goto toss_error;
7051 
7052 	ent = (entity*)varlist[0]->ptrVal; //retrieve the entity
7053 	if(!ent) goto toss_error;
7054 
7055 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7056 	(*pretvar)->lVal = (LONG)1;
7057 
7058 	if(paramCount >= 2) ScriptVariant_DecimalValue(varlist[1], &height);
7059 	if(paramCount >= 3) ScriptVariant_DecimalValue(varlist[2], &speedx);
7060 	if(paramCount >= 4) ScriptVariant_DecimalValue(varlist[3], &speedz);
7061 
7062 	ent->xdir = (float)speedx;
7063 	ent->zdir = (float)speedz;
7064 	toss(ent, (float)height);
7065 	return S_OK;
7066 
7067 toss_error:
7068 	printf("Function tossentity(entity,height, speedx, speedz) requires at least a valid entity handle.\n");
7069 	*pretvar = NULL;
7070 	return E_FAIL;
7071 }
7072 
7073 // ===== getplayerproperty =====
7074 enum playerproperty_enum {
7075 	_pp_colourmap,
7076 	_pp_credits,
7077 	_pp_ent,
7078 	_pp_entity,
7079 	_pp_keys,
7080 	_pp_lives,
7081 	_pp_name,
7082 	_pp_playkeys,
7083 	_pp_score,
7084 	_pp_weapon,
7085 	_pp_weaponum,
7086 	_pp_the_end,
mapstrings_playerproperty(ScriptVariant ** varlist,int paramCount)7087 };
7088 
7089 void mapstrings_playerproperty(ScriptVariant** varlist, int paramCount)
7090 {
7091 	char* propname;
7092 	int prop;
7093 
7094 	static const char* proplist[] = {
7095 		"colourmap",
7096 		"credits",
7097 		"ent",
7098 		"entity",
7099 		"keys",
7100 		"lives",
7101 		"name",
7102 		"playkeys",
7103 		"score",
7104 		"weapon",
7105 		"weaponum",
7106 	};
7107 
7108 	if(paramCount < 2) return;
7109 
7110 	// property name
7111 	MAPSTRINGS(varlist[1], proplist, _pp_the_end,
7112 		"Player property name '%s' is not supported yet.\n");
7113 }
openbor_getplayerproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7114 
7115 //getplayerproperty(index, propname);
7116 HRESULT openbor_getplayerproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7117 {
7118 	LONG ltemp;
7119 	int index;
7120 	entity* ent = NULL;
7121 	int prop = -1;
7122 	ScriptVariant* arg = NULL;
7123 
7124 	if(paramCount < 2)
7125 	{
7126 		*pretvar = NULL;
7127 		return E_FAIL;
7128 	}
7129 
7130 	mapstrings_playerproperty(varlist, paramCount);
7131 	ScriptVariant_Clear(*pretvar);
7132 
7133 	arg = varlist[0];
7134 	if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
7135 	{
7136 		index = 0;
7137 	} else index = (int)ltemp;
7138 
7139 
7140 	ent = player[index].ent;
7141 
7142 	arg = varlist[1];
7143 	if(arg->vt!=VT_INTEGER)
7144 	{
7145 		if(arg->vt!=VT_STR)
7146 			printf("Function call getplayerproperty has invalid propery name parameter, it must be a string value.\n");
7147 		*pretvar = NULL;
7148 		return E_FAIL;
7149 	}
7150 	prop = arg->lVal;
7151 
7152 	switch(prop)
7153 	{
7154 	case _pp_ent:
7155 	case _pp_entity:
7156 	{
7157 		if(!ent) ScriptVariant_Clear(*pretvar); // player not spawned
7158 		else {
7159 			ScriptVariant_ChangeType(*pretvar, VT_PTR);
7160 			(*pretvar)->ptrVal = (VOID*)ent;
7161 		}
7162 		break;
7163 	}
7164 	case _pp_name:
7165 	{
7166 		ScriptVariant_ChangeType(*pretvar, VT_STR);
7167 		strncpy(StrCache_Get((*pretvar)->strVal), (char*)player[index].name, MAX_STR_VAR_LEN);
7168 		break;
7169 	}
7170 	case _pp_colourmap:
7171 	{
7172 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7173 		(*pretvar)->lVal = (LONG)player[index].colourmap;
7174 		break;
7175 	}
7176 	case _pp_score:
7177 	{
7178 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7179 		(*pretvar)->lVal = (LONG)player[index].score;
7180 		break;
7181 	}
7182 	case _pp_lives:
7183 	{
7184 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7185 		(*pretvar)->lVal = (LONG)player[index].lives;
7186 		break;
7187 	}
7188 	case _pp_playkeys:
7189 	{
7190 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7191 		(*pretvar)->lVal = (LONG)player[index].playkeys;
7192 		break;
7193 	}
7194 	case _pp_keys:
7195 	{
7196 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7197 		(*pretvar)->lVal = (LONG)player[index].keys;
7198 		break;
7199 	}
7200 	case _pp_credits:
7201 	{
7202 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7203 		if(noshare) (*pretvar)->lVal = (LONG)player[index].credits;
7204 		else        (*pretvar)->lVal = credits;
7205 		break;
7206 	}
7207 	case _pp_weaponum:
7208 	{
7209 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7210 		(*pretvar)->lVal = (LONG)player[index].weapnum;
7211 		break;
7212 	}
7213 	//this property is not known
7214 	//default:{
7215 	//  .....
7216 	//}
7217 	}
7218 	return S_OK;
7219 }
7220 
openbor_changeplayerproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7221 
7222 //changeplayerproperty(index, propname, value[, value2, value3,...]);
7223 HRESULT openbor_changeplayerproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7224 {
7225 	LONG ltemp, ltemp2;
7226 	int index;
7227 	entity* ent = NULL;
7228 	int prop = -1;
7229 	char* tempstr = NULL;
7230 	ScriptVariant* arg = NULL;
7231 
7232 	if(paramCount < 3)
7233 	{
7234 		*pretvar = NULL;
7235 		return E_FAIL;
7236 	}
7237 
7238 	mapstrings_playerproperty(varlist, paramCount);
7239 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7240 	(*pretvar)->lVal = (LONG)1;
7241 	arg = varlist[0];
7242 	if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
7243 	{
7244 		index = 0;
7245 	} else index = (int)ltemp;
7246 
7247 	ent = player[index].ent;
7248 
7249 	if(varlist[1]->vt != VT_INTEGER)
7250 	{
7251 		if(varlist[1]->vt != VT_STR)
7252 			printf("You must give a string value for player property name.\n");
7253 		return E_FAIL;
7254 	}
7255 	prop = varlist[1]->lVal;
7256 
7257 	arg = varlist[2];
7258 
7259 	//change the model
7260 	switch(prop)
7261 	{
7262 	case _pp_ent:
7263 	case _pp_entity:
7264 	{
7265 		if(arg->vt==VT_PTR)
7266 		{
7267 			player[index].ent = (entity*)arg->ptrVal;
7268 			(*pretvar)->lVal = (LONG)1;
7269 		}
7270 		else (*pretvar)->lVal = (LONG)0;
7271 		break;
7272 	}
7273 	case _pp_weapon:
7274 	{
7275 		if(!ent) {
7276 			(*pretvar)->lVal = (LONG)0;
7277 		}
7278 		else if(SUCCEEDED(ScriptVariant_IntegerValue(arg,&ltemp))){
7279 			if(paramCount > 3)
7280 			{
7281 				arg = varlist[3];
7282 				if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp2)))
7283 					(*pretvar)->lVal = (LONG)1;
7284 			}
7285 			else
7286 			{
7287 				ltemp2 = (LONG)0;
7288 				(*pretvar)->lVal = (LONG)1;
7289 			}
7290 			set_weapon(player[index].ent, (int)ltemp, (int)ltemp2);
7291 			(*pretvar)->lVal = (LONG)1;
7292 		}
7293 		else (*pretvar)->lVal = (LONG)0;
7294 		break;
7295 	}
7296 	case _pp_name:
7297 	{
7298 		if(arg->vt != VT_STR)
7299 		{
7300 			//printf();
7301 			return E_FAIL;
7302 		}
7303 		tempstr = (char*)StrCache_Get(arg->strVal);
7304 		strcpy(player[index].name, tempstr);
7305 		(*pretvar)->lVal = (LONG)1;
7306 		break;
7307 	}
7308 	case _pp_colourmap:
7309 	{
7310 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg,&ltemp)))
7311 			player[index].colourmap = (int)ltemp;
7312 		else (*pretvar)->lVal = (LONG)0;
7313 		break;
7314 	}
7315 	case _pp_score:
7316 	{
7317 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg,&ltemp)))
7318 		{
7319 			if(ltemp < 0) ltemp = 0;
7320 			else if(ltemp > 999999999) ltemp = 999999999;
7321 			player[index].score = (unsigned int)ltemp;
7322 		}
7323 		else (*pretvar)->lVal = (LONG)0;
7324 		break;
7325 	}
7326 	case _pp_lives:
7327 	{
7328 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg,&ltemp)))
7329 			player[index].lives = (int)ltemp;
7330 		else (*pretvar)->lVal = (LONG)0;
7331 		break;
7332 	}
7333 	case _pp_playkeys:
7334 	{
7335 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg,&ltemp)))
7336 			player[index].playkeys = (int)ltemp;
7337 		else (*pretvar)->lVal = (LONG)0;
7338 		break;
7339 	}
7340 	case _pp_credits:
7341 	{
7342 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg,&ltemp)))
7343 		{
7344 		   	if(noshare) player[index].credits = (int)ltemp;
7345 			else        credits = (int)ltemp;
7346 		}
7347 		else (*pretvar)->lVal = (LONG)0;
7348 		break;
7349 	}
7350 	//this property is not known, so return 0
7351 	//default:
7352 	//    (*pretvar)->lVal = (LONG)0;
7353 	}
7354 
7355 	return S_OK;
7356 }
openbor_checkhole(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7357 
7358 //checkhole(x,z), return 1 if there's hole here
7359 HRESULT openbor_checkhole(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7360 {
7361 	ScriptVariant* arg = NULL;
7362 	DOUBLE x, z;
7363 
7364 	if(paramCount < 2)
7365 	{
7366 		*pretvar = NULL;
7367 		return E_FAIL;
7368 	}
7369 
7370 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7371 	(*pretvar)->lVal = (LONG)0;
7372 
7373 	arg = varlist[0];
7374 	if(FAILED(ScriptVariant_DecimalValue(arg, &x)))
7375 		return S_OK;
7376 
7377 	arg = varlist[1];
7378 	if(FAILED(ScriptVariant_DecimalValue(arg, &z)))
7379 		return S_OK;
7380 
7381 	(*pretvar)->lVal = (LONG)(checkhole((float)x, (float)z) && checkwall((float)x, (float)z)<0);
7382 	return S_OK;
7383 }
openbor_checkwall(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7384 
7385 //checkwall(x,z), return wall height, or 0
7386 HRESULT openbor_checkwall(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7387 {
7388 	ScriptVariant* arg = NULL;
7389 	DOUBLE x, z;
7390 	int wall;
7391 
7392 	if(paramCount < 2)
7393 	{
7394 		*pretvar = NULL;
7395 		return E_FAIL;
7396 	}
7397 
7398 	ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
7399 	(*pretvar)->dblVal = (DOUBLE)0;
7400 
7401 	arg = varlist[0];
7402 	if(FAILED(ScriptVariant_DecimalValue(arg, &x)))
7403 		return S_OK;
7404 
7405 	arg = varlist[1];
7406 	if(FAILED(ScriptVariant_DecimalValue(arg, &z)))
7407 		return S_OK;
7408 
7409 	if((wall=checkwall_below((float)x, (float)z, 100000))>=0)
7410 	{
7411 		(*pretvar)->dblVal = (DOUBLE)level->walls[wall][7];
7412 	}
7413 	return S_OK;
7414 }
openbor_checkplatformbelow(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7415 
7416 //checkplatformbelow(x,z,a), return the highest platfrom entity below
7417 HRESULT openbor_checkplatformbelow(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7418 {
7419 	ScriptVariant* arg = NULL;
7420 	DOUBLE x, z, a;
7421 
7422 	if(paramCount < 3)
7423 	{
7424 		*pretvar = NULL;
7425 		return E_FAIL;
7426 	}
7427 
7428 	ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
7429 	(*pretvar)->dblVal = (DOUBLE)0;
7430 
7431 	arg = varlist[0];
7432 	if(FAILED(ScriptVariant_DecimalValue(arg, &x)))
7433 		return S_OK;
7434 
7435 	arg = varlist[1];
7436 	if(FAILED(ScriptVariant_DecimalValue(arg, &z)))
7437 		return S_OK;
7438 
7439 	arg = varlist[2];
7440 	if(FAILED(ScriptVariant_DecimalValue(arg, &a)))
7441 		return S_OK;
7442 
7443 	ScriptVariant_ChangeType(*pretvar, VT_PTR);
7444 	(*pretvar)->ptrVal = (VOID*)check_platform_below((float)x,(float)z,(float)a, NULL);
7445 	return S_OK;
7446 }
7447 
7448 HRESULT openbor_openfilestream(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7449 {
7450 	char* filename = NULL;
7451 	ScriptVariant* arg = NULL;
7452 	LONG location = 0;
7453 	int fsindex;
7454 
7455 	FILE *handle = NULL;
7456 	char path[256] = {""};
7457 	char tmpname[256] = {""};
7458 	long size;
7459 
7460 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7461 
7462 	if(paramCount < 1)
7463 	{
7464 		*pretvar = NULL;
7465 		return E_FAIL;
7466 	}
7467 
7468 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7469 
7470 	arg = varlist[0];
7471 	if(arg->vt!=VT_STR)
7472 	{
7473 		printf("Filename for openfilestream must be a string.\n");
7474 		*pretvar = NULL;
7475 		return E_FAIL;
7476 	}
7477 
7478 	filename = (char*)StrCache_Get(arg->strVal);
7479 
7480 	if(paramCount > 1)
7481 	{
7482 		arg = varlist[1];
7483 		if(FAILED(ScriptVariant_IntegerValue(arg, &location))){
7484 			*pretvar = NULL;
7485 			return E_FAIL;
7486 		}
7487 	}
7488 
7489 	for(fsindex=0; fsindex<LEVEL_MAX_FILESTREAMS; fsindex++){
7490 		if(filestreams[fsindex].buf==NULL){
7491 			break;
7492 		}
7493 	}
7494 
7495 	if(fsindex == LEVEL_MAX_FILESTREAMS)
7496 	{
7497 		printf("Maximum file streams exceeded.\n");
7498 		*pretvar = NULL;
7499 		return E_FAIL;
7500 	}
7501 
7502 	// Load file from saves directory if specified
7503 	if(location)
7504 	{
7505 		getBasePath(path, "Saves", 0);
7506 		getPakName(tmpname, -1);
7507 		strcat(path, tmpname);
7508 		strcat(path, "/");
7509 		strcat(path, filename);
7510 		//printf("open path: %s", path);
7511 #ifndef DC
7512 		if(!(fileExists(path)))
7513 		{
7514 		    /*
7515 		    2011_03_27, DC: Let's be a little more friendly about missing files; this will let a function evaluate if file exists and decide what to do.
7516 
7517 			printf("Openfilestream - file specified does not exist.\n"); //Keep this for possible debug mode in the future.
7518 			*/
7519             (*pretvar)->lVal = -1;
7520 
7521 			return S_OK;
7522 		}
7523 #endif
7524 		handle = fopen(path, "rb");
7525 		if(handle == NULL) {
7526             (*pretvar)->lVal = -1;
7527 			return S_OK;
7528 		}
7529 		//printf("\nfile opened\n");
7530 		fseek(handle, 0, SEEK_END);
7531 		size = ftell(handle);
7532 		//printf("\n file size %d fsindex %d\n", size, fsindex);
7533 		rewind(handle);
7534 		filestreams[fsindex].buf = (char*)malloc(sizeof(char)*(size+1));
7535 		if(filestreams[fsindex].buf == NULL) {
7536             (*pretvar)->lVal = -1;
7537 			return S_OK;
7538 		}
7539 		fread(filestreams[fsindex].buf, 1, size, handle);
7540 		filestreams[fsindex].buf[size] = 0;
7541 	}
7542 	else if(buffer_pakfile(filename, &filestreams[fsindex].buf, &filestreams[fsindex].size)!=1)
7543 	{
7544 		printf("Invalid filename used in openfilestream.\n");
7545 		(*pretvar)->lVal = -1;
7546 		return S_OK;
7547 	}
7548 
7549 	(*pretvar)->lVal = (LONG)fsindex;
7550 
7551 	filestreams[fsindex].pos = 0;
7552 	return S_OK;
openbor_getfilestreamline(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7553 }
7554 
7555 HRESULT openbor_getfilestreamline(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7556 {
7557 	char line[MAX_STR_VAR_LEN];
7558 	int length;
7559 	ScriptVariant* arg = NULL;
7560 	LONG filestreamindex;
7561 
7562 	if(paramCount < 1)
7563 	{
7564 		*pretvar = NULL;
7565 		return E_FAIL;
7566 	}
7567 
7568 	arg = varlist[0];
7569 	if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
7570 		return S_OK;
7571 
7572 	ScriptVariant_Clear(*pretvar);
7573 	ScriptVariant_ChangeType(*pretvar, VT_STR);
7574 
7575 	length = 0;
7576 	strncpy(line, "it's initialized now", MAX_STR_VAR_LEN);
7577 
7578 	while(filestreams[filestreamindex].buf[filestreams[filestreamindex].pos+length] && filestreams[filestreamindex].buf[filestreams[filestreamindex].pos+length]!='\n' && filestreams[filestreamindex].buf[filestreams[filestreamindex].pos+length]!='\r') ++length;
7579 	if(length >= MAX_STR_VAR_LEN)
7580 		strncpy(StrCache_Get((*pretvar)->strVal), (char*)(filestreams[filestreamindex].buf+filestreams[filestreamindex].pos), MAX_STR_VAR_LEN);
7581 	else
7582 	{
7583 		strncpy(line, (char*)(filestreams[filestreamindex].buf+filestreams[filestreamindex].pos), length);
7584 		line[length] = '\0';
7585 		strncpy(StrCache_Get((*pretvar)->strVal), line, MAX_STR_VAR_LEN);
7586 	}
7587 	return S_OK;
7588 }
7589 
7590 HRESULT openbor_getfilestreamargument(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7591 {
7592 	ScriptVariant* arg = NULL;
7593 	LONG filestreamindex, argument;
7594 	char* argtype = NULL;
7595 
7596 	if(paramCount < 3)
7597 	{
7598 		*pretvar = NULL;
7599 		return E_FAIL;
7600 	}
7601 
7602 	arg = varlist[0];
7603 	if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
7604 		return S_OK;
7605 
7606 	arg = varlist[1];
7607 	if(FAILED(ScriptVariant_IntegerValue(arg, &argument)))
7608 		return S_OK;
7609 	ScriptVariant_Clear(*pretvar);
7610 
7611 	if(varlist[2]->vt != VT_STR)
7612 	{
7613 		printf("You must give a string value specifying what kind of value you want the argument converted to.\n");
7614 		return E_FAIL;
7615 	}
7616 	argtype = (char*)StrCache_Get(varlist[2]->strVal);
7617 
7618 	if(stricmp(argtype, "string")==0)
7619 	{
7620 		ScriptVariant_ChangeType(*pretvar, VT_STR);
7621 		strncpy(StrCache_Get((*pretvar)->strVal), (char*)findarg(filestreams[filestreamindex].buf+filestreams[filestreamindex].pos, argument), MAX_STR_VAR_LEN);
7622 	}
7623 	else if(stricmp(argtype, "int")==0)
7624 	{
7625 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7626 		(*pretvar)->lVal = (LONG)atoi(findarg(filestreams[filestreamindex].buf+filestreams[filestreamindex].pos, argument));
7627 	}
7628 	else if(stricmp(argtype, "float")==0)
7629 	{
7630 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
7631 		(*pretvar)->dblVal = (DOUBLE)atof(findarg(filestreams[filestreamindex].buf+filestreams[filestreamindex].pos, argument));
7632 	}
7633 	else
7634 	{
7635 		printf("Invalid type for argument converted to (getfilestreamargument).\n");
7636 		return E_FAIL;
7637 	}
7638 
7639 	return S_OK;
openbor_filestreamnextline(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7640 }
7641 
7642 HRESULT openbor_filestreamnextline(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7643 {
7644 	ScriptVariant* arg = NULL;
7645 	LONG filestreamindex;
7646 
7647 	if(paramCount < 1)
7648 	{
7649 		*pretvar = NULL;
7650 		return E_FAIL;
7651 	}
7652 
7653 	arg = varlist[0];
7654 	if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
7655 		return S_OK;
7656 	while(filestreams[filestreamindex].buf[filestreams[filestreamindex].pos] && filestreams[filestreamindex].buf[filestreams[filestreamindex].pos]!='\n' && filestreams[filestreamindex].buf[filestreams[filestreamindex].pos]!='\r') ++filestreams[filestreamindex].pos;
7657 	while(filestreams[filestreamindex].buf[filestreams[filestreamindex].pos]=='\n' || filestreams[filestreamindex].buf[filestreams[filestreamindex].pos]=='\r') ++filestreams[filestreamindex].pos;
7658 
7659 	return S_OK;
7660 }
7661 
7662 HRESULT openbor_getfilestreamposition(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7663 {
7664 	ScriptVariant* arg = NULL;
7665 	LONG filestreamindex;
7666 
7667 	if(paramCount < 1)
7668 	{
7669 		*pretvar = NULL;
7670 		return E_FAIL;
7671 	}
7672 
7673 	arg = varlist[0];
7674 	if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
7675 		return S_OK;
7676 
7677 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7678 	(*pretvar)->lVal = (LONG)filestreams[filestreamindex].pos;
7679 	return S_OK;
openbor_setfilestreamposition(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7680 }
7681 
7682 HRESULT openbor_setfilestreamposition(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7683 {
7684 	ScriptVariant* arg = NULL;
7685 	LONG filestreamindex, position;
7686 
7687 
7688 	if(paramCount < 2)
7689 	{
7690 		*pretvar = NULL;
7691 		return E_FAIL;
7692 	}
7693 
7694 	arg = varlist[0];
7695 	if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
7696 		return S_OK;
7697 
7698 	arg = varlist[1];
7699 	if(FAILED(ScriptVariant_IntegerValue(arg, &position)))
7700 		return S_OK;
7701 
7702 	filestreams[filestreamindex].pos = position;
7703 	return S_OK;
7704 }
7705 
7706 HRESULT openbor_filestreamappend(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7707 {
7708 	LONG filestreamindex;
7709 	ScriptVariant* arg = NULL;
7710 	LONG appendtype;
7711 	LONG ltemp;
7712 	DOUBLE dbltemp;
7713 	char* temp;
7714 	char append[MAX_STR_VAR_LEN];
7715 
7716 
7717 	if(paramCount < 3)
7718 	{
7719 		*pretvar = NULL;
7720 		return E_FAIL;
7721 	}
7722 
7723 	ScriptVariant_Clear(*pretvar);
7724 
7725 	arg = varlist[0];
7726 	if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
7727 		return S_OK;
7728 
7729 	arg = varlist[1];
7730 	if(arg->vt==VT_STR)
7731 	{
7732 		strcpy(append, StrCache_Get(arg->strVal));
7733 	}
7734 	else if(arg->vt==VT_INTEGER)
7735 	{
7736 		if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
7737 			return S_OK;
7738 		sprintf(append, "%d", (int)ltemp);
7739 	}
7740 	else if(arg->vt==VT_DECIMAL)
7741 	{
7742 		if(FAILED(ScriptVariant_DecimalValue(arg, &dbltemp)))
7743 			return S_OK;
7744 		sprintf(append, "%f", dbltemp);
7745 	}
7746 	else
7747 	{
7748 		printf("Filename for filestreamappend must be a string.\n");
7749 		*pretvar = NULL;
7750 		return E_FAIL;
7751 	}
7752 
7753 
7754 
7755 	arg = varlist[2];
7756 	if(FAILED(ScriptVariant_IntegerValue(arg, &appendtype)))
7757 		return S_OK;
7758 
7759 	temp = (char*)malloc(sizeof(char)*(strlen(filestreams[filestreamindex].buf) + strlen(append) + 4));
7760 	strcpy(temp, filestreams[filestreamindex].buf);
7761 
7762 	if(appendtype == 0)
7763 	{
7764 		strcat(temp, "\r\n");
7765 		strcat(temp, append);
7766 		temp[strlen(filestreams[filestreamindex].buf) + strlen(append) + 2] = ' ';
7767 		temp[strlen(filestreams[filestreamindex].buf) + strlen(append) + 3] = '\0';
7768 	}
7769 	else if(appendtype == 1)
7770 	{
7771 		strcat(temp, append);
7772 		temp[strlen(filestreams[filestreamindex].buf) + strlen(append)] = ' ';
7773 		temp[strlen(filestreams[filestreamindex].buf) + strlen(append) + 1] = '\0';
7774 	}
7775 	free(filestreams[filestreamindex].buf);
7776 	filestreams[filestreamindex].buf = temp;
7777 
7778 	return S_OK;
openbor_createfilestream(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7779 }
7780 
7781 HRESULT openbor_createfilestream(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7782 {
7783 	int fsindex;
7784 	ScriptVariant_Clear(*pretvar);
7785 
7786 	for(fsindex=0; fsindex<LEVEL_MAX_FILESTREAMS; fsindex++){
7787 		if(filestreams[fsindex].buf==NULL){
7788 			break;
7789 		}
7790 	}
7791 
7792 	if(fsindex == LEVEL_MAX_FILESTREAMS)
7793 	{
7794 		printf("Maximum file streams exceeded.\n");
7795 		*pretvar = NULL;
7796 		return E_FAIL;
7797 	}
7798 
7799 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7800 	(*pretvar)->lVal = (LONG)fsindex;
7801 
7802 	// Initialize the new filestream
7803 	filestreams[fsindex].pos = 0;
7804 	filestreams[fsindex].buf = (char*)malloc(sizeof(char)*128);
7805 	filestreams[fsindex].buf[0] = '\0';
7806 	return S_OK;
7807 }
7808 
7809 HRESULT openbor_savefilestream(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7810 {
7811 	int i;
7812 	LONG filestreamindex;
7813 	ScriptVariant* arg = NULL;
7814 	FILE *handle = NULL;
7815 	char path[256] = {""};
7816 	char tmpname[256] = {""};
7817 
7818 	*pretvar = NULL;
7819 
7820 	if(paramCount < 1)
7821 	{
7822 		return E_FAIL;
7823 	}
7824 
7825 	arg = varlist[0];
7826 	if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex))){
7827 		printf("You must give a valid filestrema handle for savefilestream!\n");
7828 		return E_FAIL;
7829 	}
7830 
7831 	arg = varlist[1];
7832 	if(arg->vt!=VT_STR)
7833 	{
7834 		printf("Filename for savefilestream must be a string.\n");
7835 		return E_FAIL;
7836 	}
7837 
7838 	// Get the saves directory
7839 	getBasePath(path, "Saves", 0);
7840 	getPakName(tmpname, -1);
7841 	strcat(path, tmpname);
7842 
7843 	// Add user's filename to path and write the filestream to it
7844 	strcat(path, "/");
7845 	strcat(path, (char*)StrCache_Get(arg->strVal));
7846 
7847 	for(i=strlen(path)-1; i>=0; i--){
7848 
7849 		if(path[i]=='/' || path[i]=='\\'){
7850 			path[i] = 0;
7851 			// Make folder if it doesn't exist
7852 #ifndef DC
7853 			dirExists(path, 1);
7854 #endif
7855 			path[i] = '/';
7856 			break;
7857 		}
7858 	}
7859 
7860 	//printf("save path: %s", path);
7861 	handle = fopen(path, "wb");
7862 	if(handle==NULL) return E_FAIL;
7863 	fwrite(filestreams[filestreamindex].buf, 1, strlen(filestreams[filestreamindex].buf), handle);
7864 
7865 	// add blank line so it can be read successfully
7866 	fwrite("\r\n", 1, 2, handle);
7867 	fclose(handle);
7868 
7869 	return S_OK;
openbor_closefilestream(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7870 }
7871 
7872 HRESULT openbor_closefilestream(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7873 {
7874 	LONG filestreamindex;
7875 	ScriptVariant* arg = NULL;
7876 
7877 	*pretvar = NULL;
7878 
7879 	if(paramCount < 1)
7880 		return E_FAIL;
7881 
7882 	arg = varlist[0];
7883 	if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
7884 		return E_FAIL;
7885 
7886 
7887 	if(filestreams[filestreamindex].buf){
7888 		free(filestreams[filestreamindex].buf);
7889 		filestreams[filestreamindex].buf = NULL;
7890 	}
7891 	return S_OK;
7892 }
openbor_damageentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7893 
7894 //damageentity(entity, other, force, drop, type)
7895 HRESULT openbor_damageentity(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7896 {
7897 	entity* ent = NULL;
7898 	entity* other = NULL;
7899 	entity* temp = NULL;
7900 	LONG force, drop, type;
7901 	s_attack attack;
7902 	extern s_attack emptyattack;
7903 
7904 	if(paramCount < 1)
7905 	{
7906 		*pretvar = NULL;
7907 		return E_FAIL;
7908 	}
7909 
7910 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7911 	(*pretvar)->lVal = (LONG)0;
7912 
7913 	ent = (entity*)(varlist[0])->ptrVal; //retrieve the entity
7914 	if(!ent)  return S_OK;
7915 
7916 	other = ent;
7917 	force = (LONG)1;
7918 	drop = (LONG)0;
7919 	type = (LONG)ATK_NORMAL;
7920 
7921 	if(paramCount >= 2)
7922 	{
7923 		other = (entity*)(varlist[1])->ptrVal;
7924 		if(!other)
7925 			return S_OK;
7926 	}
7927 	if(paramCount >= 3)
7928 	{
7929 		if(FAILED(ScriptVariant_IntegerValue((varlist[2]), &force)))
7930 			return S_OK;
7931 	}
7932 
7933 	if(!ent->takedamage)
7934 	{
7935 		ent->health -= force;
7936 		if(ent->health <= 0) kill(ent);
7937 		(*pretvar)->lVal = (LONG)1;
7938 		return S_OK;
7939 	}
7940 
7941 	if(paramCount >= 4)
7942 	{
7943 		if(FAILED(ScriptVariant_IntegerValue((varlist[3]), &drop)))
7944 			return S_OK;
7945 	}
7946 	if(paramCount >= 5)
7947 	{
7948 		if(FAILED(ScriptVariant_IntegerValue((varlist[4]), &type)))
7949 			return S_OK;
7950 	}
7951 
7952 	temp = self; self = ent;
7953 	attack = emptyattack;
7954 	attack.attack_force = force;
7955 	attack.attack_drop = drop;
7956 	if(drop) {attack.dropv[0] = (float)3; attack.dropv[1] = (float)1.2; attack.dropv[2] = (float)0;}
7957 	attack.attack_type = type;
7958 	self->takedamage(other, &attack);
7959 	self = temp;
7960 	return S_OK;
7961 }
openbor_killentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7962 
7963 //killentity(entity)
7964 HRESULT openbor_killentity(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7965 {
7966 	entity* ent = NULL;
7967 
7968 	if(paramCount < 1)
7969 	{
7970 		*pretvar = NULL;
7971 		return E_FAIL;
7972 	}
7973 
7974 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
7975 
7976 	ent = (entity*)(varlist[0])->ptrVal; //retrieve the entity
7977 	if(!ent)
7978 	{
7979 		(*pretvar)->lVal = (LONG)0;
7980 		return S_OK;
7981 	}
7982 	kill(ent);
7983 	(*pretvar)->lVal = (LONG)1;
7984 	return S_OK;
7985 }
openbor_findtarget(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)7986 
7987 //findtarget(entity, int animation);
7988 HRESULT openbor_findtarget(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
7989 {
7990 	int i = 0;
7991 	entity* ent = NULL;
7992 	entity* tempself, *target;
7993 	LONG anim = -1;
7994 
7995     if(paramCount>2) ScriptVariant_IntegerValue(varlist[2], &i);
7996 
7997 	if(paramCount < 1)
7998 	{
7999 		*pretvar = NULL;
8000 		return E_FAIL;
8001 	}
8002 
8003 	ScriptVariant_ChangeType(*pretvar, VT_PTR);
8004 
8005 	ent = (entity*)(varlist[0])->ptrVal; //retrieve the entity
8006 	if(!ent)
8007 	{
8008 		ScriptVariant_Clear(*pretvar);
8009 		return S_OK;
8010 	}
8011 	if(paramCount>1 && FAILED(ScriptVariant_IntegerValue(varlist[1], &anim))) return E_FAIL;
8012 	tempself = self;
8013 	self = ent;
8014 	target = normal_find_target((int)anim, i);
8015 	if(!target) ScriptVariant_Clear(*pretvar);
8016 	else (*pretvar)->ptrVal = (VOID*)target;
8017 	self = tempself;
8018 	return S_OK;
8019 }
openbor_checkrange(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8020 
8021 //checkrange(entity, target, int ani);
8022 HRESULT openbor_checkrange(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
8023 {
8024 	entity* ent = NULL, *target = NULL;
8025 	LONG ani = 0;
8026 	extern int max_animations;
8027 
8028 	if(paramCount < 2) goto checkrange_error;
8029 
8030 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8031 
8032 	if(varlist[0]->vt !=VT_PTR || varlist[1]->vt!=VT_PTR) goto checkrange_error;
8033 
8034 	ent = (entity*)(varlist[0])->ptrVal; //retrieve the entity
8035 	target = (entity*)(varlist[1])->ptrVal; //retrieve the target
8036 
8037 	if(!ent || !target) goto checkrange_error;
8038 
8039 	if(paramCount >2 && FAILED(ScriptVariant_IntegerValue(varlist[2], &ani))) goto checkrange_error;
8040 	else if(paramCount<=2) ani = ent->animnum;
8041 
8042 	if(ani<0 || ani>=max_animations)
8043 	{
8044 		printf("Animation id out of range: %d / %d.\n", (int)ani, max_animations);
8045 		goto checkrange_error;
8046 	}
8047 
8048 	(*pretvar)->lVal = check_range(ent, target, ani);
8049 
8050 	return S_OK;
8051 
8052 checkrange_error:
8053 	printf("Function needs at least 2 valid entity handles, the third parameter is optional: checkrange(entity, target, int animnum)\n");
8054 	*pretvar = NULL;
8055 	return E_FAIL;
8056 }
openbor_clearspawnentry(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8057 
8058 //clearspawnentry();
8059 HRESULT openbor_clearspawnentry(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
8060 {
8061 	*pretvar = NULL;
8062 	memset(&spawnentry, 0, sizeof(s_spawn_entry));
8063 	spawnentry.index = spawnentry.itemindex = spawnentry.weaponindex = -1;
8064 	return S_OK;
8065 }
8066 
8067 // ===== setspawnentry =====
8068 enum setspawnentry_enum
8069 {
8070 	_sse_2phealth,
8071 	_sse_2pitem,
8072 	_sse_3phealth,
8073 	_sse_3pitem,
8074 	_sse_4phealth,
8075 	_sse_4pitem,
8076 	_sse_aggression,
8077 	_sse_alias,
8078 	_sse_alpha,
8079 	_sse_boss,
8080 	_sse_coords,
8081 	_sse_credit,
8082 	_sse_dying,
8083 	_sse_flip,
8084 	_sse_health,
8085 	_sse_item,
8086 	_sse_itemalias,
8087 	_sse_itemhealth,
8088 	_sse_itemmap,
8089 	_sse_map,
8090 	_sse_mp,
8091 	_sse_multiple,
8092 	_sse_name,
8093 	_sse_nolife,
8094 	_sse_weapon,
8095 	_sse_the_end,
mapstrings_setspawnentry(ScriptVariant ** varlist,int paramCount)8096 };
8097 
8098 void mapstrings_setspawnentry(ScriptVariant** varlist, int paramCount)
8099 {
8100 	char* propname;
8101 	int prop;
8102 	static const char* proplist[] =
8103 	{
8104 		"2phealth",
8105 		"2pitem",
8106 		"3phealth",
8107 		"3pitem",
8108 		"4phealth",
8109 		"4pitem",
8110 		"aggression",
8111 		"alias",
8112 		"alpha",
8113 		"boss",
8114 		"coords",
8115 		"credit",
8116 		"dying",
8117 		"flip",
8118 		"health",
8119 		"item",
8120 		"itemalias",
8121 		"itemhealth",
8122 		"itemmap",
8123 		"map",
8124 		"mp",
8125 		"multiple",
8126 		"name",
8127 		"nolife",
8128 		"weapon",
8129 	};
8130 
8131 	MAPSTRINGS(varlist[0], proplist, _sse_the_end,
8132 		"Property name '%s' is not supported by setspawnentry.\n");
8133 }
openbor_setspawnentry(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8134 
8135 //setspawnentry(propname, value1[, value2, value3, ...]);
8136 HRESULT openbor_setspawnentry(ScriptVariant** varlist, ScriptVariant** pretvar, int paramCount)
8137 {
8138 	LONG ltemp;
8139 	s_model* tempmodel;
8140 	DOUBLE dbltemp;
8141 	int temp, prop;
8142 	ScriptVariant* arg = NULL;
8143 
8144 	if(paramCount < 2)
8145 	{
8146 		*pretvar = NULL;
8147 		return E_FAIL;
8148 	}
8149 
8150 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8151 	(*pretvar)->lVal = (LONG)1;
8152 
8153 	mapstrings_setspawnentry(varlist, paramCount);
8154 	if(varlist[0]->vt != VT_INTEGER)
8155 	{
8156 		if(varlist[0]->vt != VT_STR)
8157 			printf("You must give a string value for spawn entry property name.\n");
8158 		*pretvar = NULL;
8159 		return E_FAIL;
8160 	}
8161 
8162 	prop = varlist[0]->lVal;
8163 
8164 	arg = varlist[1];
8165 
8166 	switch(prop)
8167 	{
8168 	case _sse_name:
8169 		if(arg->vt != VT_STR)
8170 		{
8171 			printf("You must use a string value for spawn entry's name property: function setspawnentry.\n");
8172 			goto setspawnentry_error;
8173 		}
8174 		spawnentry.model = findmodel((char*)StrCache_Get(arg->strVal));
8175 		break;
8176 	case _sse_alias:
8177 		if(arg->vt != VT_STR) goto setspawnentry_error;
8178 		strcpy(spawnentry.alias, (char*)StrCache_Get(arg->strVal));
8179 		break;
8180 	case _sse_item:
8181 		if(arg->vt != VT_STR) goto setspawnentry_error;
8182 		spawnentry.itemmodel = findmodel((char*)StrCache_Get(arg->strVal));
8183 		spawnentry.item = spawnentry.itemmodel->name;
8184 		spawnentry.itemindex = get_cached_model_index(spawnentry.item);
8185 		spawnentry.itemplayer_count = 0;
8186 		break;
8187 	case _sse_2pitem:
8188 		if(arg->vt != VT_STR) goto setspawnentry_error;
8189 		tempmodel = findmodel((char*)StrCache_Get(arg->strVal));
8190 		if(!tempmodel) spawnentry.item = NULL;
8191 		else spawnentry.item = tempmodel->name;
8192 		spawnentry.itemplayer_count = 1;
8193 		break;
8194 	case _sse_3pitem:
8195 		if(arg->vt != VT_STR) goto setspawnentry_error;
8196 		spawnentry.itemmodel = findmodel((char*)StrCache_Get(arg->strVal));
8197 		spawnentry.itemplayer_count = 2;
8198 		break;
8199 	case _sse_4pitem:
8200 		if(arg->vt != VT_STR) goto setspawnentry_error;
8201 		spawnentry.itemmodel = findmodel((char*)StrCache_Get(arg->strVal));
8202 		spawnentry.itemplayer_count = 3;
8203 		break;
8204 	case _sse_health:
8205 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8206 			spawnentry.health[0] = (int)ltemp;
8207 		else (*pretvar)->lVal = (LONG)0;
8208 		break;
8209 	case _sse_itemhealth:
8210 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8211 			spawnentry.itemhealth = (int)ltemp;
8212 		else (*pretvar)->lVal = (LONG)0;
8213 		break;
8214 	case _sse_itemalias:
8215 		if(arg->vt != VT_STR) return E_FAIL;
8216 		strcpy(spawnentry.itemalias, (char*)StrCache_Get(arg->strVal));
8217 		break;
8218 	case _sse_2phealth:
8219 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8220 			spawnentry.health[1] = (int)ltemp;
8221 		else (*pretvar)->lVal = (LONG)0;
8222 		break;
8223 	case _sse_3phealth:
8224 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8225 			spawnentry.health[2] = (int)ltemp;
8226 		else (*pretvar)->lVal = (LONG)0;
8227 		break;
8228 	case _sse_4phealth:
8229 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8230 			spawnentry.health[3] = (int)ltemp;
8231 		else (*pretvar)->lVal = (LONG)0;
8232 		break;
8233 	case _sse_coords:
8234 		temp = 1;
8235 		if(SUCCEEDED(ScriptVariant_DecimalValue(arg, &dbltemp))) spawnentry.x = (float)dbltemp;
8236 		else temp = 0;
8237 		if(paramCount >= 3 && temp)
8238 		{
8239 			if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp))) spawnentry.z = (float)dbltemp;
8240 			else temp = 0;
8241 		}
8242 		if(paramCount >= 4 && temp)
8243 		{
8244 			if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp))) spawnentry.a = (float)dbltemp;
8245 			else temp = 0;
8246 		}
8247 		(*pretvar)->lVal = (LONG)temp;
8248 		break;
8249 	case _sse_mp:
8250 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8251 			spawnentry.mp = (int)ltemp;
8252 		else (*pretvar)->lVal = (LONG)0;
8253 		break;
8254 	case _sse_map:
8255 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8256 			spawnentry.colourmap = (int)ltemp;
8257 		else (*pretvar)->lVal = (LONG)0;
8258 		break;
8259 	case _sse_itemmap:
8260 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8261 			spawnentry.itemmap = (int)ltemp;
8262 		else (*pretvar)->lVal = (LONG)0;
8263 		break;
8264 	case _sse_alpha:
8265 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8266 			spawnentry.alpha = (int)ltemp;
8267 		else (*pretvar)->lVal = (LONG)0;
8268 		break;
8269 	case _sse_multiple:
8270 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8271 			spawnentry.multiple = (int)ltemp;
8272 		else (*pretvar)->lVal = (LONG)0;
8273 		break;
8274 	case _sse_dying:
8275 		temp = 1;
8276 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8277 			spawnentry.dying = (int)ltemp;
8278 		else temp = 0;
8279 		if(paramCount >= 3 && temp)
8280 		{
8281 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
8282 				spawnentry.per1 = (int)ltemp;
8283 			else temp = 0;
8284 		}
8285 		if(paramCount >= 4 && temp)
8286 		{
8287 			if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
8288 				spawnentry.per2 = (int)ltemp;
8289 			else temp = 0;
8290 		}
8291 		(*pretvar)->lVal = (LONG)temp;
8292 		break;
8293 	case _sse_nolife:
8294 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8295 			spawnentry.nolife = (int)ltemp;
8296 		else (*pretvar)->lVal = (LONG)0;
8297 		break;
8298 	case _sse_boss:
8299 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8300 			spawnentry.boss = (int)ltemp;
8301 		else (*pretvar)->lVal = (LONG)0;
8302 		break;
8303 	case _sse_flip:
8304 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8305 			spawnentry.flip = (int)ltemp;
8306 		else (*pretvar)->lVal = (LONG)0;
8307 		break;
8308 	case _sse_credit:
8309 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8310 			spawnentry.credit = (int)ltemp;
8311 		else (*pretvar)->lVal = (LONG)0;
8312 		break;
8313 	case _sse_aggression:
8314 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8315 			spawnentry.aggression = (int)ltemp;
8316 		else (*pretvar)->lVal = (LONG)0;
8317 		break;
8318 	case _sse_weapon:
8319 		if(arg->vt != VT_STR) goto setspawnentry_error;
8320 		spawnentry.weaponmodel = findmodel((char*)StrCache_Get(arg->strVal));
8321 		break;
8322 	default:
8323 		//printf("Property name '%s' is not supported by setspawnentry.\n", propname);
8324 		goto setspawnentry_error;
8325 	}
8326 
8327 	return S_OK;
8328 setspawnentry_error:
8329 	*pretvar = NULL;
8330 	return E_FAIL;
8331 }
openbor_spawn(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8332 
8333 //spawn();
8334 HRESULT openbor_spawn(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
8335 {
8336 	entity* ent;
8337 
8338 	if(spawnentry.boss && level) level->bosses++;
8339 
8340 	ent = smartspawn(&spawnentry);
8341 
8342 	if(ent)
8343 	{
8344 		ScriptVariant_ChangeType(*pretvar, VT_PTR);
8345 		(*pretvar)->ptrVal = (VOID*) ent;
8346 	}
8347 	else     ScriptVariant_Clear(*pretvar);
8348 
8349 	return S_OK;
8350 }
openbor_projectile(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8351 
8352 //entity * projectile([0/1], char *name, float x, float z, float a, int direction, int pytype, int type, int map);
8353 HRESULT openbor_projectile(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
8354 {
8355 	DOUBLE temp = 0;
8356 	LONG ltemp=0;
8357 	entity* ent;
8358 	char *name = NULL;
8359 	float x=0,z=0,a=0;
8360 	int direction = 0;
8361 	int type = 0;
8362 	int ptype = 0;
8363 	int map = 0;
8364 
8365 	int relative;
8366 
8367 	if(paramCount>=1 && varlist[0]->vt==VT_INTEGER && varlist[0]->lVal){
8368 		relative = 1;
8369 		paramCount--;
8370 		varlist++;
8371 	}else relative = 0;
8372 
8373 	if(paramCount>=1 && varlist[0]->vt == VT_STR) name = StrCache_Get(varlist[0]->strVal);
8374 
8375 	if(paramCount>=2 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[1], &temp))) x = (float)temp;
8376 	else if(relative) x = 0;
8377 	else x = self->x;
8378 	if(paramCount>=3 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &temp))) z = (float)temp;
8379 	else if(relative) z = 0;
8380 	else z = self->z;
8381 	if(paramCount>=4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &temp))) a = (float)temp;
8382 	else if(relative) a  = self->animation->throwa;
8383 	else a = self->a + self->animation->throwa;
8384 	if(paramCount>=5 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp))) direction = (int)ltemp;
8385 	else if(relative) direction  =1;
8386 	else direction = self->direction;
8387 	if(paramCount>=6 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp))) ptype = (int)ltemp;
8388 	if(paramCount>=7 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[6], &ltemp))) type = (int)ltemp;
8389 	if(paramCount>=8 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[7], &ltemp))) map = (int)ltemp;
8390 
8391 	if(relative) {
8392 		if(self->direction) x += self->x;
8393 		else {
8394 			x = self->x-x;
8395 			direction = !direction;
8396 		}
8397 		z += self->z;
8398 		a += self->a;
8399 	}
8400 
8401 	switch(type)
8402 	{
8403 		default:
8404 		case 0:
8405 			ent = knife_spawn(name, -1, x, z, a, direction, ptype, map);
8406 			break;
8407 		case 1:
8408 			ent = bomb_spawn(name, -1, x, z, a, direction, map);
8409 			break;
8410 	}
8411 
8412 	ScriptVariant_ChangeType(*pretvar, VT_PTR);
8413 	(*pretvar)->ptrVal = (VOID*) ent;
8414 
8415 	return S_OK;
8416 }
8417 
8418 
8419 // ===== openborconstant =====
8420 #define ICMPCONST(x) \
8421 if(stricmp(#x, constname)==0) {\
8422 	ScriptVariant_ChangeType(varlist[0], VT_INTEGER);\
8423 	varlist[0]->lVal = (LONG)x;\
mapstrings_transconst(ScriptVariant ** varlist,int paramCount)8424 	return;\
8425 }
8426 void mapstrings_transconst(ScriptVariant** varlist, int paramCount)
8427 {
8428 	char* constname = NULL;
8429 
8430 	if(paramCount < 1) return;
8431 
8432 	if(varlist[0]->vt == VT_STR)
8433 	{
8434 		constname = (char*)StrCache_Get(varlist[0]->strVal);
8435 
8436 		ICMPCONST(COMPATIBLEVERSION)
8437 		ICMPCONST(MIN_INT)
8438 		ICMPCONST(MAX_INT)
8439 		ICMPCONST(PIXEL_8)
8440 		ICMPCONST(PIXEL_x8)
8441 		ICMPCONST(PIXEL_16)
8442 		ICMPCONST(PIXEL_32)
8443 		ICMPCONST(CV_SAVED_GAME)
8444 		ICMPCONST(CV_HIGH_SCORE)
8445 		ICMPCONST(THINK_SPEED)
8446 		ICMPCONST(COUNTER_SPEED)
8447 		ICMPCONST(MAX_ENTS)
8448 		ICMPCONST(MAX_PANELS)
8449 		ICMPCONST(MAX_WEAPONS)
8450 		ICMPCONST(MAX_COLOUR_MAPS)
8451 		ICMPCONST(MAX_NAME_LEN)
8452 		ICMPCONST(LEVEL_MAX_SPAWNS)
8453 		ICMPCONST(LEVEL_MAX_PANELS)
8454 		ICMPCONST(LEVEL_MAX_HOLES)
8455 		ICMPCONST(LEVEL_MAX_WALLS)
8456 		ICMPCONST(MAX_LEVELS)
8457 		ICMPCONST(MAX_DIFFICULTIES)
8458 		ICMPCONST(MAX_SPECIALS)
8459 		ICMPCONST(MAX_ATCHAIN)
8460 		ICMPCONST(MAX_ATTACKS)
8461 		ICMPCONST(MAX_FOLLOWS)
8462 		ICMPCONST(MAX_PLAYERS)
8463 		ICMPCONST(MAX_ARG_LEN)
8464 		ICMPCONST(FLAG_ESC)
8465 		ICMPCONST(FLAG_START)
8466 		ICMPCONST(FLAG_MOVELEFT)
8467 		ICMPCONST(FLAG_MOVERIGHT)
8468 		ICMPCONST(FLAG_MOVEUP)
8469 		ICMPCONST(FLAG_MOVEDOWN)
8470 		ICMPCONST(FLAG_ATTACK)
8471 		ICMPCONST(FLAG_ATTACK2)
8472 		ICMPCONST(FLAG_ATTACK3)
8473 		ICMPCONST(FLAG_ATTACK4)
8474 		ICMPCONST(FLAG_JUMP)
8475 		ICMPCONST(FLAG_SPECIAL)
8476 		ICMPCONST(FLAG_SCREENSHOT)
8477 		ICMPCONST(FLAG_ANYBUTTON)
8478 		ICMPCONST(FLAG_FORWARD)
8479 		ICMPCONST(FLAG_BACKWARD)
8480 		ICMPCONST(SDID_MOVEUP)
8481 		ICMPCONST(SDID_MOVEDOWN)
8482 		ICMPCONST(SDID_MOVELEFT)
8483 		ICMPCONST(SDID_MOVERIGHT)
8484 		ICMPCONST(SDID_SPECIAL)
8485 		ICMPCONST(SDID_ATTACK)
8486 		ICMPCONST(SDID_ATTACK2)
8487 		ICMPCONST(SDID_ATTACK3)
8488 		ICMPCONST(SDID_ATTACK4)
8489 		ICMPCONST(SDID_JUMP)
8490 		ICMPCONST(SDID_START)
8491 		ICMPCONST(SDID_SCREENSHOT)
8492 		ICMPCONST(TYPE_NONE)
8493 		ICMPCONST(TYPE_PLAYER)
8494 		ICMPCONST(TYPE_ENEMY)
8495 		ICMPCONST(TYPE_ITEM)
8496 		ICMPCONST(TYPE_OBSTACLE)
8497 		ICMPCONST(TYPE_STEAMER)
8498 		ICMPCONST(TYPE_SHOT)
8499 		ICMPCONST(TYPE_TRAP)
8500 		ICMPCONST(TYPE_TEXTBOX)
8501 		ICMPCONST(TYPE_ENDLEVEL)
8502 		ICMPCONST(TYPE_NPC)
8503 		ICMPCONST(TYPE_PANEL)
8504 		ICMPCONST(TYPE_RESERVED)
8505 		ICMPCONST(SUBTYPE_NONE)
8506 		ICMPCONST(SUBTYPE_BIKER)
8507 		ICMPCONST(SUBTYPE_NOTGRAB)
8508 		ICMPCONST(SUBTYPE_ARROW)
8509 		ICMPCONST(SUBTYPE_TOUCH)
8510 		ICMPCONST(SUBTYPE_WEAPON)
8511 		ICMPCONST(SUBTYPE_NOSKIP)
8512 		ICMPCONST(SUBTYPE_FLYDIE)
8513 		ICMPCONST(SUBTYPE_BOTH)
8514 		ICMPCONST(SUBTYPE_PROJECTILE)
8515 		ICMPCONST(SUBTYPE_FOLLOW)
8516 		ICMPCONST(SUBTYPE_CHASE)
8517 		ICMPCONST(AIMOVE1_NORMAL)
8518 		ICMPCONST(AIMOVE1_CHASE)
8519 		ICMPCONST(AIMOVE1_CHASEZ)
8520 		ICMPCONST(AIMOVE1_CHASEX)
8521 		ICMPCONST(AIMOVE1_AVOID)
8522 		ICMPCONST(AIMOVE1_AVOIDZ)
8523 		ICMPCONST(AIMOVE1_AVOIDX)
8524 		ICMPCONST(AIMOVE1_WANDER)
8525 		ICMPCONST(AIMOVE1_NOMOVE)
8526 		ICMPCONST(AIMOVE1_BIKER)
8527 		ICMPCONST(AIMOVE1_STAR)
8528 		ICMPCONST(AIMOVE1_ARROW)
8529 		ICMPCONST(AIMOVE1_BOMB)
8530 		ICMPCONST(AIMOVE2_NORMAL)
8531 		ICMPCONST(AIMOVE2_IGNOREHOLES)
8532 		ICMPCONST(AIATTACK1_NORMAL)
8533 		ICMPCONST(AIATTACK1_LONG)
8534 		ICMPCONST(AIATTACK1_MELEE)
8535 		ICMPCONST(AIATTACK1_NOATTACK)
8536 		ICMPCONST(AIATTACK1_ALWAYS)
8537 		ICMPCONST(AIATTACK2_NORMAL)
8538 		ICMPCONST(AIATTACK2_DODGE)
8539 		ICMPCONST(AIATTACK2_DODGEMOVE)
8540 		ICMPCONST(FRONTPANEL_Z)
8541 		ICMPCONST(HOLE_Z)
8542 		ICMPCONST(NEONPANEL_Z)
8543 		ICMPCONST(SHADOW_Z)
8544 		ICMPCONST(SCREENPANEL_Z)
8545 		ICMPCONST(PANEL_Z)
8546 		ICMPCONST(MIRROR_Z)
8547 		ICMPCONST(PIT_DEPTH)
8548 		ICMPCONST(P2_STATS_DIST)
8549 		ICMPCONST(CONTACT_DIST_H)
8550 		ICMPCONST(CONTACT_DIST_V)
8551 		ICMPCONST(GRAB_DIST)
8552 		ICMPCONST(GRAB_STALL)
8553 		ICMPCONST(ATK_NORMAL)
8554 		ICMPCONST(ATK_NORMAL2)
8555 		ICMPCONST(ATK_NORMAL3)
8556 		ICMPCONST(ATK_NORMAL4)
8557 		ICMPCONST(ATK_BLAST)
8558 		ICMPCONST(ATK_BURN)
8559 		ICMPCONST(ATK_FREEZE)
8560 		ICMPCONST(ATK_SHOCK)
8561 		ICMPCONST(ATK_STEAL)
8562 		ICMPCONST(ATK_NORMAL5)
8563 		ICMPCONST(ATK_NORMAL6)
8564 		ICMPCONST(ATK_NORMAL7)
8565 		ICMPCONST(ATK_NORMAL8)
8566 		ICMPCONST(ATK_NORMAL9)
8567 		ICMPCONST(ATK_NORMAL10)
8568 		ICMPCONST(ATK_ITEM)
8569 		ICMPCONST(SCROLL_RIGHT)
8570 		ICMPCONST(SCROLL_DOWN)
8571 		ICMPCONST(SCROLL_LEFT)
8572 		ICMPCONST(SCROLL_UP)
8573 		ICMPCONST(SCROLL_BOTH)
8574 		ICMPCONST(SCROLL_LEFTRIGHT)
8575 		ICMPCONST(SCROLL_RIGHTLEFT)
8576 		ICMPCONST(SCROLL_INWARD)
8577 		ICMPCONST(SCROLL_OUTWARD)
8578 		ICMPCONST(SCROLL_INOUT)
8579 		ICMPCONST(SCROLL_OUTIN)
8580 		ICMPCONST(SCROLL_UPWARD)
8581 		ICMPCONST(SCROLL_DOWNWARD)
8582 		ICMPCONST(ANI_IDLE)
8583 		ICMPCONST(ANI_WALK)
8584 		ICMPCONST(ANI_JUMP)
8585 		ICMPCONST(ANI_LAND)
8586 		ICMPCONST(ANI_PAIN)
8587 		ICMPCONST(ANI_FALL)
8588 		ICMPCONST(ANI_RISE)
8589 		//ICMPCONST(ANI_ATTACK1)// move these below because we have some dynamic animation ids
8590 		//ICMPCONST(ANI_ATTACK2)
8591 		//ICMPCONST(ANI_ATTACK3)
8592 		//ICMPCONST(ANI_ATTACK4)
8593 		ICMPCONST(ANI_UPPER)
8594 		ICMPCONST(ANI_BLOCK)
8595 		ICMPCONST(ANI_JUMPATTACK)
8596 		ICMPCONST(ANI_JUMPATTACK2)
8597 		ICMPCONST(ANI_GET)
8598 		ICMPCONST(ANI_GRAB)
8599 		ICMPCONST(ANI_GRABATTACK)
8600 		ICMPCONST(ANI_GRABATTACK2)
8601 		ICMPCONST(ANI_THROW)
8602 		ICMPCONST(ANI_SPECIAL)
8603 		//ICMPCONST(ANI_FREESPECIAL)// move these below because we have some dynamic animation ids
8604 		ICMPCONST(ANI_SPAWN)
8605 		ICMPCONST(ANI_DIE)
8606 		ICMPCONST(ANI_PICK)
8607 		//ICMPCONST(ANI_FREESPECIAL2)
8608 		ICMPCONST(ANI_JUMPATTACK3)
8609 		//ICMPCONST(ANI_FREESPECIAL3)
8610 		ICMPCONST(ANI_UP)
8611 		ICMPCONST(ANI_DOWN)
8612 		ICMPCONST(ANI_SHOCK)
8613 		ICMPCONST(ANI_BURN)
8614 
8615 		ICMPCONST(ANI_SHOCKPAIN)
8616 		ICMPCONST(ANI_BURNPAIN)
8617 		ICMPCONST(ANI_GRABBED)
8618 		ICMPCONST(ANI_SPECIAL2)
8619 		ICMPCONST(ANI_RUN)
8620 		ICMPCONST(ANI_RUNATTACK)
8621 		ICMPCONST(ANI_RUNJUMPATTACK)
8622 		ICMPCONST(ANI_ATTACKUP)
8623 		ICMPCONST(ANI_ATTACKDOWN)
8624 		ICMPCONST(ANI_ATTACKFORWARD)
8625 		ICMPCONST(ANI_ATTACKBACKWARD)
8626 		//ICMPCONST(ANI_FREESPECIAL4)
8627 		//ICMPCONST(ANI_FREESPECIAL5)
8628 		//ICMPCONST(ANI_FREESPECIAL6)
8629 		//ICMPCONST(ANI_FREESPECIAL7)
8630 		//ICMPCONST(ANI_FREESPECIAL8)
8631 		ICMPCONST(ANI_RISEATTACK)
8632 		ICMPCONST(ANI_DODGE)
8633 		ICMPCONST(ANI_ATTACKBOTH)
8634 		ICMPCONST(ANI_GRABFORWARD)
8635 		ICMPCONST(ANI_GRABFORWARD2)
8636 		ICMPCONST(ANI_JUMPFORWARD)
8637 		ICMPCONST(ANI_GRABDOWN)
8638 		ICMPCONST(ANI_GRABDOWN2)
8639 		ICMPCONST(ANI_GRABUP)
8640 		ICMPCONST(ANI_GRABUP2)
8641 		ICMPCONST(ANI_SELECT)
8642 		ICMPCONST(ANI_DUCK)
8643 		ICMPCONST(ANI_FAINT)
8644 		ICMPCONST(ANI_CANT)
8645 		ICMPCONST(ANI_THROWATTACK)
8646 		ICMPCONST(ANI_CHARGEATTACK)
8647 		ICMPCONST(ANI_VAULT)
8648 		ICMPCONST(ANI_JUMPCANT)
8649 		ICMPCONST(ANI_JUMPSPECIAL)
8650 		ICMPCONST(ANI_BURNDIE)
8651 		ICMPCONST(ANI_SHOCKDIE)
8652 		ICMPCONST(ANI_PAIN2)
8653 		ICMPCONST(ANI_PAIN3)
8654 		ICMPCONST(ANI_PAIN4)
8655 		ICMPCONST(ANI_FALL2)
8656 		ICMPCONST(ANI_FALL3)
8657 		ICMPCONST(ANI_FALL4)
8658 		ICMPCONST(ANI_DIE2)
8659 		ICMPCONST(ANI_DIE3)
8660 		ICMPCONST(ANI_DIE4)
8661 		ICMPCONST(ANI_CHARGE)
8662 		ICMPCONST(ANI_BACKWALK)
8663 		ICMPCONST(ANI_SLEEP)
8664 		//ICMPCONST(ANI_FOLLOW1) // move these below because we have some dynamic animation ids
8665 		//ICMPCONST(ANI_FOLLOW2)
8666 		//ICMPCONST(ANI_FOLLOW3)
8667 		//ICMPCONST(ANI_FOLLOW4)
8668 		ICMPCONST(ANI_PAIN5)
8669 		ICMPCONST(ANI_PAIN6)
8670 		ICMPCONST(ANI_PAIN7)
8671 		ICMPCONST(ANI_PAIN8)
8672 		ICMPCONST(ANI_PAIN9)
8673 		ICMPCONST(ANI_PAIN10)
8674 		ICMPCONST(ANI_FALL5)
8675 		ICMPCONST(ANI_FALL6)
8676 		ICMPCONST(ANI_FALL7)
8677 		ICMPCONST(ANI_FALL8)
8678 		ICMPCONST(ANI_FALL9)
8679 		ICMPCONST(ANI_FALL10)
8680 		ICMPCONST(ANI_DIE5)
8681 		ICMPCONST(ANI_DIE6)
8682 		ICMPCONST(ANI_DIE7)
8683 		ICMPCONST(ANI_DIE8)
8684 		ICMPCONST(ANI_DIE9)
8685 		ICMPCONST(ANI_DIE10)
8686 		ICMPCONST(ANI_TURN)
8687 		ICMPCONST(ANI_RESPAWN)
8688 		ICMPCONST(ANI_FORWARDJUMP)
8689 		ICMPCONST(ANI_RUNJUMP)
8690 		ICMPCONST(ANI_JUMPLAND)
8691 		ICMPCONST(ANI_JUMPDELAY)
8692 		ICMPCONST(ANI_HITWALL)
8693 		ICMPCONST(ANI_GRABBACKWARD)
8694 		ICMPCONST(ANI_GRABBACKWARD2)
8695 		ICMPCONST(ANI_GRABWALK)
8696 		ICMPCONST(ANI_GRABBEDWALK)
8697 		ICMPCONST(ANI_GRABWALKUP)
8698 		ICMPCONST(ANI_GRABBEDWALKUP)
8699 		ICMPCONST(ANI_GRABWALKDOWN)
8700 		ICMPCONST(ANI_GRABBEDWALKDOWN)
8701 		ICMPCONST(ANI_GRABTURN)
8702 		ICMPCONST(ANI_GRABBEDTURN)
8703 		ICMPCONST(ANI_GRABBACKWALK)
8704 		ICMPCONST(ANI_GRABBEDBACKWALK)
8705 
8706 		ICMPCONST(ANI_SLIDE)
8707 		ICMPCONST(ANI_RUNSLIDE)
8708 		ICMPCONST(ANI_BLOCKPAIN)
8709 		ICMPCONST(ANI_DUCKATTACK)
8710 		ICMPCONST(MAX_ANIS)
8711 		ICMPCONST(PLAYER_MIN_Z)
8712 		ICMPCONST(PLAYER_MAX_Z)
8713 		ICMPCONST(BGHEIGHT)
8714 		ICMPCONST(MAX_WALL_HEIGHT)
8715 		ICMPCONST(SAMPLE_GO);
8716 		ICMPCONST(SAMPLE_BEAT);
8717 		ICMPCONST(SAMPLE_BLOCK);
8718 		ICMPCONST(SAMPLE_INDIRECT);
8719 		ICMPCONST(SAMPLE_GET);
8720 		ICMPCONST(SAMPLE_GET2);
8721 		ICMPCONST(SAMPLE_FALL);
8722 		ICMPCONST(SAMPLE_JUMP);
8723 		ICMPCONST(SAMPLE_PUNCH);
8724 		ICMPCONST(SAMPLE_1UP);
8725 		ICMPCONST(SAMPLE_TIMEOVER);
8726 		ICMPCONST(SAMPLE_BEEP);
8727 		ICMPCONST(SAMPLE_BEEP2);
8728 		ICMPCONST(SAMPLE_BIKE);
8729 		ICMPCONST(ANI_RISE2);
8730 		ICMPCONST(ANI_RISE3);
8731 		ICMPCONST(ANI_RISE4);
8732 		ICMPCONST(ANI_RISE5);
8733 		ICMPCONST(ANI_RISE6);
8734 		ICMPCONST(ANI_RISE7);
8735 		ICMPCONST(ANI_RISE8);
8736 		ICMPCONST(ANI_RISE9);
8737 		ICMPCONST(ANI_RISE10);
8738 		ICMPCONST(ANI_RISEB);
8739 		ICMPCONST(ANI_RISES);
8740 		ICMPCONST(ANI_BLOCKPAIN2);
8741 		ICMPCONST(ANI_BLOCKPAIN3);
8742 		ICMPCONST(ANI_BLOCKPAIN4);
8743 		ICMPCONST(ANI_BLOCKPAIN5);
8744 		ICMPCONST(ANI_BLOCKPAIN6);
8745 		ICMPCONST(ANI_BLOCKPAIN7);
8746 		ICMPCONST(ANI_BLOCKPAIN8);
8747 		ICMPCONST(ANI_BLOCKPAIN9);
8748 		ICMPCONST(ANI_BLOCKPAIN10);
8749 		ICMPCONST(ANI_BLOCKPAINB);
8750 		ICMPCONST(ANI_BLOCKPAINS);
8751 		ICMPCONST(ANI_CHIPDEATH);
8752 		ICMPCONST(ANI_GUARDBREAK);
8753 		ICMPCONST(ANI_RISEATTACK2);
8754 		ICMPCONST(ANI_RISEATTACK3);
8755 		ICMPCONST(ANI_RISEATTACK4);
8756 		ICMPCONST(ANI_RISEATTACK5);
8757 		ICMPCONST(ANI_RISEATTACK6);
8758 		ICMPCONST(ANI_RISEATTACK7);
8759 		ICMPCONST(ANI_RISEATTACK8);
8760 		ICMPCONST(ANI_RISEATTACK9);
8761 		ICMPCONST(ANI_RISEATTACK10);
8762 		ICMPCONST(ANI_RISEATTACKB);
8763 		ICMPCONST(ANI_RISEATTACKS);
8764 		ICMPCONST(ANI_SLIDE);
8765 		ICMPCONST(ANI_RUNSLIDE);
8766 		ICMPCONST(ANI_DUCKATTACK);
8767 		ICMPCONST(ANI_WALKOFF);
8768 	}
8769 }
openbor_transconst(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8770 //openborconstant(constname);
8771 //translate a constant by string, used to retrieve a constant or macro of openbor
8772 HRESULT openbor_transconst(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
8773 {
8774 	char* constname = NULL;
8775 	int temp;
8776 
8777 	if(paramCount < 1)
8778 	{
8779 		*pretvar = NULL;
8780 		return E_FAIL;
8781 	}
8782 
8783 	mapstrings_transconst(varlist, paramCount);
8784 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8785 
8786 	if(varlist[0]->vt == VT_INTEGER) // return value already determined by mapstrings
8787 	{
8788 		(*pretvar)->lVal = varlist[0]->lVal;
8789 		return S_OK;
8790 	}
8791 	else if(varlist[0]->vt != VT_STR)
8792 	{
8793 		*pretvar = NULL;
8794 		return E_FAIL;
8795 	}
8796 
8797 	// if we get to this point, it's a dynamic animation id
8798 	constname = StrCache_Get(varlist[0]->strVal);
8799 
8800 	// for the extra animation ids
8801 	// for the extra animation ids
8802 	if(strnicmp(constname, "ANI_DOWN", 8)==0 && constname[8] >= '1') // new down walk?
8803 	{
8804 		temp = atoi(constname+8);
8805 		(*pretvar)->lVal = (LONG)(animdowns[temp-1]);
8806 		return S_OK;
8807 	}
8808 	if(strnicmp(constname, "ANI_UP", 8)==0 && constname[8] >= '1') // new up walk?
8809 	{
8810 		temp = atoi(constname+8);
8811 		(*pretvar)->lVal = (LONG)(animups[temp-1]);
8812 		return S_OK;
8813 	}
8814 	if(strnicmp(constname, "ANI_BACKWALK", 8)==0 && constname[8] >= '1') // new backwalk?
8815 	{
8816 		temp = atoi(constname+8);
8817 		(*pretvar)->lVal = (LONG)(animbackwalks[temp-1]);
8818 		return S_OK;
8819 	}
8820 	if(strnicmp(constname, "ANI_WALK", 8)==0 && constname[8] >= '1') // new Walk?
8821 	{
8822 		temp = atoi(constname+8);
8823 		(*pretvar)->lVal = (LONG)(animwalks[temp-1]);
8824 		return S_OK;
8825 	}
8826 	if(strnicmp(constname, "ANI_IDLE", 8)==0 && constname[8] >= '1') // new idle?
8827 	{
8828 		temp = atoi(constname+8);
8829 		(*pretvar)->lVal = (LONG)(animidles[temp-1]);
8830 		return S_OK;
8831 	}
8832 	if(strnicmp(constname, "ANI_FALL", 8)==0 && constname[8] >= '1' && constname[8]<='9') // new fall?
8833 	{
8834 		temp = atoi(constname+8); // so must be greater than 10
8835 		if(temp<MAX_ATKS-STA_ATKS+1) temp = MAX_ATKS-STA_ATKS+1; // just in case
8836 		(*pretvar)->lVal = (LONG)(animfalls[temp+STA_ATKS-1]);
8837 		return S_OK;
8838 	}
8839 	if(strnicmp(constname, "ANI_RISE", 8)==0 && constname[8] >= '1' && constname[8]<='9') // new fall?
8840 	{
8841 		temp = atoi(constname+8);
8842 		if(temp<MAX_ATKS-STA_ATKS+1) temp = MAX_ATKS-STA_ATKS+1; // just in case
8843 		(*pretvar)->lVal = (LONG)(animrises[temp+STA_ATKS-1]);
8844 		return S_OK;
8845 	}
8846 	if(strnicmp(constname, "ANI_RISEATTACK", 14)==0 && constname[14] >= '1' && constname[14]<='9') // new fall?
8847 	{
8848 		temp = atoi(constname+14);
8849 		if(temp<MAX_ATKS-STA_ATKS+1) temp = MAX_ATKS-STA_ATKS+1; // just in case
8850 		(*pretvar)->lVal = (LONG)(animriseattacks[temp+STA_ATKS-1]);
8851 		return S_OK;
8852 	}
8853 	if(strnicmp(constname, "ANI_PAIN", 8)==0 && constname[8] >= '1' && constname[8]<='9') // new fall?
8854 	{
8855 		temp = atoi(constname+8); // so must be greater than 10
8856 		if(temp<MAX_ATKS-STA_ATKS+1) temp = MAX_ATKS-STA_ATKS+1; // just in case
8857 		(*pretvar)->lVal = (LONG)(animpains[temp+STA_ATKS-1]);
8858 		return S_OK;
8859 	}
8860 	if(strnicmp(constname, "ANI_DIE", 7)==0 && constname[7] >= '1' && constname[7]<='9') // new fall?
8861 	{
8862 		temp = atoi(constname+7); // so must be greater than 10
8863 		if(temp<MAX_ATKS-STA_ATKS+1) temp = MAX_ATKS-STA_ATKS+1; // just in case
8864 		(*pretvar)->lVal = (LONG)(animdies[temp+STA_ATKS-1]);
8865 		return S_OK;
8866 	}
8867 	if(strnicmp(constname, "ANI_ATTACK", 10)==0 && constname[10] >= '1' && constname[10]<='9')
8868 	{
8869 		temp = atoi(constname+10);
8870 		(*pretvar)->lVal = (LONG)(animattacks[temp-1]);
8871 		return S_OK;
8872 	}
8873 	if(strnicmp(constname, "ANI_FOLLOW", 10)==0 && constname[10] >= '1' && constname[10]<='9')
8874 	{
8875 		temp = atoi(constname+10);
8876 		(*pretvar)->lVal = (LONG)(animfollows[temp-1]);
8877 		return S_OK;
8878 	}
8879 	if(strnicmp(constname, "ANI_FREESPECIAL", 15)==0 && (!constname[15] ||(constname[15] >= '1' && constname[15]<='9')))
8880 	{
8881 		temp = atoi(constname+15);
8882 		if(temp<1) temp = 1;
8883 		(*pretvar)->lVal = (LONG)(animspecials[temp-1]);
8884 		return S_OK;
8885 	}
8886 	ScriptVariant_Clear(*pretvar);
8887 	return S_OK;
8888 }
openbor_rgbcolor(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8889 
8890 //int rgbcolor(int r, int g, int b);
8891 HRESULT openbor_rgbcolor(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
8892 {
8893 	LONG r, g, b;
8894 
8895 	if(paramCount != 3) goto rgbcolor_error;
8896 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &r))) goto rgbcolor_error; // decimal/integer value for red?
8897 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &g))) goto rgbcolor_error; // decimal/integer value for green?
8898 	if(FAILED(ScriptVariant_IntegerValue(varlist[2], &b))) goto rgbcolor_error; // decimal/integer value for blue?
8899 
8900 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8901 	(*pretvar)->lVal = _makecolour(r, g, b);
8902 	return S_OK;
8903 
8904 rgbcolor_error:
8905 	*pretvar = NULL;
8906 	return E_FAIL;
8907 }
8908 
8909 // ===== playerkeys =====
8910 enum playerkeys_enum
8911 {
8912 	_pk_anybutton,
8913 	_pk_attack,
8914 	_pk_attack2,
8915 	_pk_attack3,
8916 	_pk_attack4,
8917 	_pk_esc,
8918 	_pk_jump,
8919 	_pk_movedown,
8920 	_pk_moveleft,
8921 	_pk_moveright,
8922 	_pk_moveup,
8923 	_pk_screenshot,
8924 	_pk_special,
8925 	_pk_start,
8926 	_pk_the_end,
mapstrings_playerkeys(ScriptVariant ** varlist,int paramCount)8927 };
8928 
8929 void mapstrings_playerkeys(ScriptVariant** varlist, int paramCount)
8930 {
8931 	char* propname = NULL;
8932 	int i, prop;
8933 
8934 	static const char* proplist[] = // for args 2+
8935 	{
8936 		"anybutton",
8937 		"attack",
8938 		"attack2",
8939 		"attack3",
8940 		"attack4",
8941 		"esc",
8942 		"jump",
8943 		"movedown",
8944 		"moveleft",
8945 		"moveright",
8946 		"moveup",
8947 		"screenshot",
8948 		"special",
8949 		"start",
8950 	};
8951 
8952 	for(i=2; i<paramCount; i++)
8953 	{
8954 		MAPSTRINGS(varlist[i], proplist, _pk_the_end,
8955 			"Button name '%s' is not supported by playerkeys.");
8956 	}
8957 }
openbor_playerkeys(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8958 
8959 //playerkeys(playerindex, newkey?, key1, key2, ...);
8960 HRESULT openbor_playerkeys(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
8961 {
8962 	LONG ltemp;
8963 	int index, newkey;
8964 	int i;
8965 	u32 keys;
8966 	ScriptVariant* arg = NULL;
8967 
8968 	if(paramCount < 3)
8969 	{
8970 		*pretvar = NULL;
8971 		return E_FAIL;
8972 	}
8973 
8974 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8975 	(*pretvar)->lVal = (LONG)1;
8976 
8977 	mapstrings_playerkeys(varlist, paramCount);
8978 
8979 	if(FAILED(ScriptVariant_IntegerValue((varlist[0]), &ltemp)))
8980 	{
8981 		index = 0;
8982 	} else index = (int)ltemp;
8983 
8984 	if(SUCCEEDED(ScriptVariant_IntegerValue((varlist[1]), &ltemp)))
8985 		newkey = (int)ltemp;
8986 	else newkey = 0;
8987 
8988 	if(newkey == 1) keys = player[index].newkeys;
8989 	else if(newkey == 2) keys = player[index].releasekeys;
8990 	else keys = player[index].keys;
8991 
8992 	for(i=2; i<paramCount; i++)
8993 	{
8994 		arg = varlist[i];
8995 		if(arg->vt == VT_INTEGER)
8996 		{
8997 			switch(arg->lVal)
8998 			{
8999 		    case _pk_jump:
9000 				(*pretvar)->lVal = (LONG)(keys & FLAG_JUMP);
9001 				break;
9002 			case _pk_attack:
9003 				(*pretvar)->lVal = (LONG)(keys & FLAG_ATTACK);
9004 				break;
9005 			case _pk_attack2:
9006 				(*pretvar)->lVal = (LONG)(keys & FLAG_ATTACK2);
9007 				break;
9008 			case _pk_attack3:
9009 				(*pretvar)->lVal = (LONG)(keys & FLAG_ATTACK3);
9010 				break;
9011 			case _pk_attack4:
9012 				(*pretvar)->lVal = (LONG)(keys & FLAG_ATTACK4);
9013 				break;
9014 			case _pk_special:
9015 				(*pretvar)->lVal = (LONG)(keys & FLAG_SPECIAL);
9016 				break;
9017 			case _pk_esc:
9018 				(*pretvar)->lVal = (LONG)(keys & FLAG_ESC);
9019 				break;
9020 			case _pk_start:
9021 				(*pretvar)->lVal = (LONG)(keys & FLAG_START);
9022 				break;
9023 			case _pk_moveleft:
9024 				(*pretvar)->lVal = (LONG)(keys & FLAG_MOVELEFT);
9025 				break;
9026 			case _pk_moveright:
9027 				(*pretvar)->lVal = (LONG)(keys & FLAG_MOVERIGHT);
9028 				break;
9029 			case _pk_moveup:
9030 				(*pretvar)->lVal = (LONG)(keys & FLAG_MOVEUP);
9031 				break;
9032 			case _pk_movedown:
9033 				(*pretvar)->lVal = (LONG)(keys & FLAG_MOVEDOWN);
9034 				break;
9035 			case _pk_screenshot:
9036 				(*pretvar)->lVal = (LONG)(keys & FLAG_SCREENSHOT);
9037 				break;
9038 			case _pk_anybutton:
9039 				(*pretvar)->lVal = (LONG)(keys & FLAG_ANYBUTTON);
9040 				break;
9041 			default:
9042 				(*pretvar)->lVal = (LONG)0;
9043 			}
9044 		}
9045 		else (*pretvar)->lVal = (LONG)0;
9046 		if(!((*pretvar)->lVal)) break;
9047 	}
9048 
9049 	return S_OK;
9050 }
openbor_playmusic(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9051 
9052 //playmusic(name, loop)
9053 HRESULT openbor_playmusic(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9054 {
9055 	int loop = 0;
9056 	LONG offset = 0;
9057 	char* thename = NULL;
9058 
9059 	*pretvar = NULL;
9060 	if(paramCount < 1)
9061 	{
9062 		sound_close_music();
9063 		return S_OK;
9064 	}
9065 	if(varlist[0]->vt != VT_STR)
9066 	{
9067 		//printf("");
9068 		return E_FAIL;
9069 	}
9070 	thename = StrCache_Get(varlist[0]->strVal);
9071 
9072 	if(paramCount > 1)
9073 	{
9074 		loop = (int)ScriptVariant_IsTrue(varlist[1]);
9075 	}
9076 
9077 	if(paramCount > 2)
9078 	{
9079 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &offset)))
9080 			return E_FAIL;
9081 	}
9082 
9083 
9084 	music(thename, loop, offset);
9085 	return S_OK;
9086 }
openbor_fademusic(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9087 
9088 //fademusic(fade, name, loop, offset)
9089 HRESULT openbor_fademusic(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9090 {
9091 	DOUBLE value = 0;
9092 	LONG values[2] = {0,0};
9093 	*pretvar = NULL;
9094 	if(paramCount < 1) goto fademusic_error;
9095 	if(FAILED(ScriptVariant_DecimalValue(varlist[0], &value))) goto fademusic_error;
9096 	musicfade[0] = value;
9097 	musicfade[1] = (float)savedata.musicvol;
9098 
9099 	if(paramCount == 4)
9100 	{
9101 		strncpy(musicname, StrCache_Get(varlist[1]->strVal), 128);
9102 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &values[0]))) goto fademusic_error;
9103 		if(FAILED(ScriptVariant_IntegerValue(varlist[3], &values[1]))) goto fademusic_error;
9104 		musicloop = values[0];
9105 		musicoffset = values[1];
9106 	}
9107 	return S_OK;
9108 
9109 fademusic_error:
9110 	printf("Function requires 1 value, with an optional 3 for music triggering: fademusic_error(float fade, char name, int loop, unsigned long offset)\n");
9111 	return E_FAIL;
9112 }
openbor_setmusicvolume(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9113 
9114 //setmusicvolume(left, right)
9115 HRESULT openbor_setmusicvolume(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9116 {
9117 	LONG channels[2];
9118 
9119 	if(paramCount < 1)
9120 	{
9121 		return S_OK;
9122 	}
9123 
9124 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], channels)))
9125 			goto setmusicvolume_error;
9126 
9127 	if(paramCount > 1)
9128 	{
9129 		if(FAILED(ScriptVariant_IntegerValue(varlist[1], channels+1)))
9130 			goto setmusicvolume_error;
9131 	}
9132 	else
9133 		channels[1] = channels[0];
9134 
9135 	sound_volume_music((int)channels[0], (int)channels[1]);
9136 	return S_OK;
9137 
9138 setmusicvolume_error:
9139 	printf("values must be integers: setmusicvolume(int left, (optional)int right)\n");
9140 	return E_FAIL;
9141 }
openbor_setmusictempo(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9142 
9143 //setmusicvolume(left, right)
9144 HRESULT openbor_setmusictempo(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9145 {
9146 	LONG new_tempo;
9147 
9148 	if(paramCount < 1)
9149 	{
9150 		return S_OK;
9151 	}
9152 
9153 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &new_tempo)))
9154 		return E_FAIL;
9155 
9156 	sound_music_tempo(new_tempo);
9157 	return S_OK;
9158 }
openbor_pausemusic(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9159 
9160 //pausemusic(value)
9161 HRESULT openbor_pausemusic(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9162 {
9163 	int pause = 0;
9164 	if(paramCount < 1)
9165 	{
9166 		return S_OK;
9167 	}
9168 
9169 	pause = (int)ScriptVariant_IsTrue(varlist[0]);
9170 
9171 	sound_pause_music(pause);
9172 	return S_OK;
9173 }
openbor_playsample(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9174 
9175 //playsample(id, priority, lvolume, rvolume, speed, loop)
9176 HRESULT openbor_playsample(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9177 {
9178 	int i;
9179 	LONG value[6] = {-1, 0, savedata.effectvol, savedata.effectvol, 100, 0};
9180 
9181 	*pretvar = NULL;
9182 	for(i=0; i<6 && i<paramCount; i++)
9183 	{
9184 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i)))
9185 			goto playsample_error;
9186 	}
9187 	if((int)value[0] < 0)
9188 	{
9189 		printf("Invalid Id for playsample(id=%d, priority=%d, lvolume=%d, rvolume=%d, speed=%d, loop=%d)\n", (int)value[0], (unsigned int)value[1], (int)value[2], (int)value[3], (unsigned int)value[4], (int)value[5]);
9190 		return E_FAIL;
9191 	}
9192 	if((int)value[5]) sound_loop_sample((int)value[0], (unsigned int)value[1], (int)value[2], (int)value[3], (unsigned int)value[4]);
9193 	else sound_play_sample((int)value[0], (unsigned int)value[1], (int)value[2], (int)value[3], (unsigned int)value[4]);
9194 	return S_OK;
9195 
9196 playsample_error:
9197 
9198 	printf("Function requires 6 integer values: playsample(int id, unsigned int priority, int lvolume, int rvolume, unsigned int speed, int loop)\n");
9199 	return E_FAIL;
9200 }
openbor_loadsample(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9201 
9202 // int loadsample(filename, log)
9203 HRESULT openbor_loadsample(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9204 {
9205 	int arg = 0;
9206 
9207 	if(paramCount < 1)
9208 	{
9209 		goto loadsample_error;
9210 	}
9211 	if(varlist[0]->vt != VT_STR) goto loadsample_error;
9212 
9213 	if(paramCount > 1)
9214 	{
9215 		if(varlist[1]->vt == VT_INTEGER)
9216 		{
9217 			arg = varlist[1]->lVal;
9218 		}
9219 		else
9220 		{
9221 			goto loadsample_error;
9222 		}
9223 	}
9224 
9225 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9226 	(*pretvar)->lVal = (LONG)sound_load_sample(StrCache_Get(varlist[0]->strVal), packfile, arg);
9227 	return S_OK;
9228 
9229 loadsample_error:
9230 	printf("Function requires 1 string value and optional log value: loadsample(string {filename} integer {log})\n");
9231 	*pretvar = NULL;
9232 	return E_FAIL;
9233 }
openbor_unloadsample(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9234 
9235 // void unloadsample(id)
9236 HRESULT openbor_unloadsample(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9237 {
9238 	LONG id;
9239 	*pretvar = NULL;
9240 	if(paramCount != 1 ) goto unloadsample_error;
9241 
9242 	if(FAILED(ScriptVariant_IntegerValue((varlist[0]), &id)))
9243 		goto unloadsample_error;
9244 
9245 	sound_unload_sample((int)id);
9246 	return S_OK;
9247 
9248 unloadsample_error:
9249 	printf("Function requires 1 integer value: unloadsample(int id)\n");
9250 	return E_FAIL;
9251 }
openbor_fadeout(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9252 
9253 //fadeout(type, speed);
9254 HRESULT openbor_fadeout(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9255 {
9256 	LONG type;
9257 	LONG speed;
9258 	*pretvar = NULL;
9259 	if(paramCount < 1 ) goto fade_out_error;
9260 
9261 	if(FAILED(ScriptVariant_IntegerValue((varlist[0]), &type)))
9262 		goto fade_out_error;
9263 	if(FAILED(ScriptVariant_IntegerValue((varlist[1]), &speed)))
9264 
9265 	fade_out((int)type, (int)speed);
9266 	return S_OK;
9267 
9268 fade_out_error:
9269 	printf("Function requires 2 integer values: fade_out(int type, int speed)\n");
9270 	return E_FAIL;
9271 }
openbor_changepalette(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9272 
9273 //changepalette(index);
9274 HRESULT openbor_changepalette(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9275 {
9276 	LONG index;
9277 
9278 	*pretvar = NULL;
9279 
9280 	if(paramCount < 1) goto changepalette_error;
9281 
9282 	if(FAILED(ScriptVariant_IntegerValue((varlist[0]), &index)))
9283 		goto changepalette_error;
9284 
9285 	change_system_palette((int)index);
9286 
9287 	return S_OK;
9288 
9289 changepalette_error:
9290 	printf("Function requires 1 integer value: changepalette(int index)\n");
9291 	return E_FAIL;
9292 }
openbor_changelight(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9293 
9294 //changelight(x, z);
9295 HRESULT openbor_changelight(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9296 {
9297 	LONG x, z;
9298 	extern int            light[2];
9299 	ScriptVariant* arg = NULL;
9300 
9301 	*pretvar = NULL;
9302 	if(paramCount < 2) goto changelight_error;
9303 
9304 	arg = varlist[0];
9305 	if(arg->vt!=VT_EMPTY)
9306 	{
9307 		if(FAILED(ScriptVariant_IntegerValue(arg, &x)))
9308 			goto changelight_error;
9309 		light[0] = (int)x;
9310 	}
9311 
9312 	arg = varlist[1];
9313 	if(arg->vt!=VT_EMPTY)
9314 	{
9315 		if(FAILED(ScriptVariant_IntegerValue(arg, &z)))
9316 			goto changelight_error;
9317 		light[1] = (int)z;
9318 	}
9319 
9320 	return S_OK;
9321 changelight_error:
9322 	printf("Function requires 2 integer values: changepalette(int x, int z)\n");
9323 	return E_FAIL;
9324 }
9325 
9326 //changeshadowcolor(color, alpha);
openbor_changeshadowcolor(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9327 // color = 0 means no gfxshadow, -1 means don't fill the shadow with colour
9328 // alpha default to 2, <=0 means no alpha effect
9329 HRESULT openbor_changeshadowcolor(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9330 {
9331 	LONG c, a;
9332 	extern int            shadowcolor;
9333 	extern int            shadowalpha;
9334 
9335 	*pretvar = NULL;
9336 	if(paramCount < 1) goto changeshadowcolor_error;
9337 
9338 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &c)))
9339 		goto changeshadowcolor_error;
9340 
9341 	shadowcolor = (int)c;
9342 
9343 	if(paramCount>1)
9344 	{
9345 		if(FAILED(ScriptVariant_IntegerValue(varlist[1], &a)))
9346 			goto changeshadowcolor_error;
9347 		shadowalpha = (int)a;
9348 	}
9349 
9350 	return S_OK;
9351 changeshadowcolor_error:
9352 	printf("Function requires at least 1 integer value, the 2nd integer parameter is optional: changepalette(int colorindex, int alpha)\n");
9353 	return E_FAIL;
9354 }
9355 
9356 // ===== gettextobjproperty(name, value) =====
9357 enum gtop_enum
9358 {
9359 	_gtop_font,
9360 	_gtop_text,
9361 	_gtop_time,
9362 	_gtop_x,
9363 	_gtop_y,
9364 	_gtop_z,
9365 	_gtop_the_end,
mapstrings_gettextobjproperty(ScriptVariant ** varlist,int paramCount)9366 };
9367 
9368 void mapstrings_gettextobjproperty(ScriptVariant** varlist, int paramCount)
9369 {
9370 	char* propname = NULL;
9371 	int prop;
9372 
9373 	static const char* proplist[] = {
9374 		"font",
9375 		"text",
9376 		"time"
9377 		"x",
9378 		"y",
9379 		"z",
9380 	};
9381 
9382 	if(paramCount < 2) return;
9383 
9384 	MAPSTRINGS(varlist[1], proplist, _gtop_the_end,
9385 		"Property name '%s' is not supported by function gettextobjproperty.\n");
openbor_gettextobjproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9386 }
9387 
9388 HRESULT openbor_gettextobjproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9389 {
9390 	LONG ind;
9391 	int propind;
9392 
9393 	if(paramCount < 2)
9394 		goto gettextobjproperty_error;
9395 
9396 
9397 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
9398 	{
9399 		printf("Function's 1st argument must be a numeric value: gettextproperty(int index, \"property\")\n");
9400 		goto gettextobjproperty_error;
9401 	}
9402 
9403 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9404 	mapstrings_gettextobjproperty(varlist, paramCount);
9405 
9406 	if(ind<0 || ind >= LEVEL_MAX_TEXTOBJS)
9407 	{
9408 		(*pretvar)->lVal = 0;
9409 		return S_OK;
9410 	}
9411 
9412 	if(varlist[1]->vt != VT_INTEGER)
9413 	{
9414 		if(varlist[1]->vt != VT_STR)
9415 			printf("Function gettextobjproperty must have a string property name.\n");
9416 		goto gettextobjproperty_error;
9417 	}
9418 
9419 	propind = varlist[1]->lVal;
9420 
9421 	switch(propind)
9422 	{
9423 	case _gtop_font:
9424 	{
9425 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9426 		(*pretvar)->lVal = (LONG)level->textobjs[ind].font;
9427 		break;
9428 	}
9429 	case _gtop_text:
9430 	{
9431 		ScriptVariant_ChangeType(*pretvar, VT_STR);
9432 		strcpy(StrCache_Get((*pretvar)->strVal), level->textobjs[ind].text);
9433 		break;
9434 	}
9435 	case _gtop_time:
9436 	{
9437 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9438 		(*pretvar)->lVal = (LONG)level->textobjs[ind].t;
9439 		break;
9440 	}
9441 	case _gtop_x:
9442 	{
9443 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9444 		(*pretvar)->lVal = (LONG)level->textobjs[ind].x;
9445 		break;
9446 	}
9447 	case _gtop_y:
9448 	{
9449 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9450 		(*pretvar)->lVal = (LONG)level->textobjs[ind].y;
9451 		break;
9452 	}
9453 	case _gtop_z:
9454 	{
9455 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9456 		(*pretvar)->lVal = (LONG)level->textobjs[ind].z;
9457 		break;
9458 	}
9459 	default:
9460 		//printf("Property name '%s' is not supported by function gettextobjproperty.\n", propname);
9461 		goto gettextobjproperty_error;
9462 		break;
9463 	}
9464 
9465 	return S_OK;
9466 
9467 gettextobjproperty_error:
9468 	*pretvar = NULL;
9469 	return E_FAIL;
9470 }
9471 
9472 // ===== changetextobjproperty(name, value) =====
9473 enum ctop_enum
9474 {
9475 	_ctop_font,
9476 	_ctop_text,
9477 	_ctop_time,
9478 	_ctop_x,
9479 	_ctop_y,
9480 	_ctop_z,
9481 	_ctop_the_end,
mapstrings_changetextobjproperty(ScriptVariant ** varlist,int paramCount)9482 };
9483 
9484 void mapstrings_changetextobjproperty(ScriptVariant** varlist, int paramCount)
9485 {
9486 	char* propname = NULL;
9487 	int prop;
9488 
9489 	static const char* proplist[] = {
9490 		"font",
9491 		"text",
9492 		"time",
9493 		"x",
9494 		"y",
9495 		"z",
9496 	};
9497 
9498 	if(paramCount < 2) return;
9499 	MAPSTRINGS(varlist[1], proplist, _ctop_the_end,
9500 		"Property name '%s' is not supported by function changetextobjproperty.\n");
openbor_changetextobjproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9501 }
9502 
9503 HRESULT openbor_changetextobjproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9504 {
9505 	LONG ind;
9506 	int propind;
9507 	LONG ltemp;
9508 
9509 	if(paramCount < 3)
9510 		goto changetextobjproperty_error;
9511 
9512 
9513 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
9514 	{
9515 		printf("Function's 1st argument must be a numeric value: changetextobjproperty(int index, \"property\", value)\n");
9516 		goto changetextobjproperty_error;
9517 	}
9518 
9519 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9520 	mapstrings_changetextobjproperty(varlist, paramCount);
9521 
9522 	if(ind<0 || ind >= LEVEL_MAX_TEXTOBJS)
9523 	{
9524 		(*pretvar)->lVal = 0;
9525 		return S_OK;
9526 	}
9527 
9528 	if(varlist[1]->vt != VT_INTEGER)
9529 	{
9530 		if(varlist[1]->vt != VT_STR)
9531 			printf("Function changetextobjproperty must have a string property name.\n");
9532 		goto changetextobjproperty_error;
9533 	}
9534 
9535 	propind = varlist[1]->lVal;
9536 
9537 	switch(propind)
9538 	{
9539 	case _ctop_font:
9540 	{
9541 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
9542 		{
9543 			(*pretvar)->lVal = (LONG)1;
9544 			level->textobjs[ind].font = (int)ltemp;
9545 		}
9546 		break;
9547 	}
9548 	case _ctop_text:
9549 	{
9550 		if(varlist[2]->vt != VT_STR)
9551 		{
9552 			printf("You must give a string value for textobj text.\n");
9553 			goto changetextobjproperty_error;
9554 		}
9555 		if(!level->textobjs[ind].text)
9556 		{
9557 			level->textobjs[ind].text = (char*)malloc(MAX_STR_VAR_LEN);
9558 		}
9559 		strncpy(level->textobjs[ind].text, (char*)StrCache_Get(varlist[2]->strVal), MAX_STR_VAR_LEN);
9560 		//level->textobjs[ind].text = (char*)StrCache_Get(varlist[2]->strVal);
9561 		(*pretvar)->lVal = (LONG)1;
9562 		break;
9563 	}
9564 	case _ctop_time:
9565 	{
9566 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
9567 		{
9568 			(*pretvar)->lVal = (LONG)1;
9569 			level->textobjs[ind].t = (int)ltemp;
9570 		}
9571 		break;
9572 	}
9573 	case _ctop_x:
9574 	{
9575 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
9576 		{
9577 			(*pretvar)->lVal = (LONG)1;
9578 			level->textobjs[ind].x = (int)ltemp;
9579 		}
9580 		break;
9581 	}
9582 	case _ctop_y:
9583 	{
9584 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
9585 		{
9586 			(*pretvar)->lVal = (LONG)1;
9587 			level->textobjs[ind].y = (int)ltemp;
9588 		}
9589 		break;
9590 	}
9591 	case _ctop_z:
9592 	{
9593 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
9594 		{
9595 			(*pretvar)->lVal = (LONG)1;
9596 			level->textobjs[ind].z = (int)ltemp;
9597 		}
9598 		break;
9599 	}
9600 	default:
9601 		//printf("Property name '%s' is not supported by function changetextobjproperty.\n", propname);
9602 		goto changetextobjproperty_error;
9603 		break;
9604 	}
9605 
9606 	return S_OK;
9607 
9608 changetextobjproperty_error:
9609 	*pretvar = NULL;
9610 	return E_FAIL;
9611 }
openbor_settextobj(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9612 
9613 // settextobj(int index, int x, int y, int font, int z, char text, int time {optional})
9614 HRESULT openbor_settextobj(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9615 {
9616 	LONG ind;
9617 	LONG ltemp;
9618 
9619 	if(paramCount < 6)
9620 		goto settextobj_error;
9621 
9622 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
9623 	{
9624 		printf("Function's 1st argument must be a numeric value: settextobj(int index, int x, int y, int font, int z, char text, int time {optional})\n");
9625 		goto settextobj_error;
9626 	}
9627 
9628 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9629 
9630 	if(ind<0 || ind >= LEVEL_MAX_TEXTOBJS)
9631 	{
9632 		(*pretvar)->lVal = 0;
9633 		return S_OK;
9634 	}
9635 
9636 	if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)))
9637 	{
9638 		(*pretvar)->lVal = (LONG)1;
9639 		level->textobjs[ind].x = (int)ltemp;
9640 	}
9641 
9642 	if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
9643 	{
9644 		(*pretvar)->lVal = (LONG)1;
9645 		level->textobjs[ind].y = (int)ltemp;
9646 	}
9647 
9648 	if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
9649 	{
9650 		(*pretvar)->lVal = (LONG)1;
9651 		level->textobjs[ind].font = (int)ltemp;
9652 	}
9653 
9654 	if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
9655 	{
9656 		(*pretvar)->lVal = (LONG)1;
9657 		level->textobjs[ind].z = (int)ltemp;
9658 	}
9659 
9660 	if(varlist[5]->vt != VT_STR)
9661 	{
9662 		printf("You must give a string value for textobj text.\n");
9663 		goto settextobj_error;
9664 	}
9665 
9666 	if(paramCount >= 7)
9667 	{
9668 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[6], &ltemp)))
9669 		{
9670 			(*pretvar)->lVal = (LONG)1;
9671 			level->textobjs[ind].t = (int)ltemp;
9672 		}
9673 	}
9674 
9675 	if(!level->textobjs[ind].text)
9676 	{
9677 		level->textobjs[ind].text = (char*)malloc(MAX_STR_VAR_LEN);
9678 	}
9679 	strncpy(level->textobjs[ind].text, (char*)StrCache_Get(varlist[5]->strVal), MAX_STR_VAR_LEN);
9680 	(*pretvar)->lVal = (LONG)1;
9681 
9682 	return S_OK;
9683 
9684 settextobj_error:
9685 	*pretvar = NULL;
9686 	return E_FAIL;
9687 }
9688 
9689 HRESULT openbor_cleartextobj(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
9690 {
9691 	LONG ind;
9692 
9693 	if(paramCount < 1)
9694 		goto cleartextobj_error;
9695 
9696 
9697 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
9698 	{
9699 		printf("Function's 1st argument must be a numeric value: cleartextobj(int index)\n");
9700 		goto cleartextobj_error;
9701 	}
9702 
9703 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9704 
9705 	if(ind<0 || ind >= LEVEL_MAX_TEXTOBJS)
9706 	{
9707 		(*pretvar)->lVal = 0;
9708 		return S_OK;
9709 	}
9710 
9711 	level->textobjs[ind].t = 0;
9712 	level->textobjs[ind].x = 0;
9713 	level->textobjs[ind].y = 0;
9714 	level->textobjs[ind].font = 0;
9715 	level->textobjs[ind].z = 0;
9716 	if(level->textobjs[ind].text)
9717 		 free(level->textobjs[ind].text);
9718 	level->textobjs[ind].text = NULL;
9719 	return S_OK;
9720 
9721 cleartextobj_error:
9722 	*pretvar = NULL;
9723 	return E_FAIL;
9724 }
9725 
9726 // ===== get layer type ======
9727 enum getlt_enum
9728 {
9729 	_glt_background,
9730 	_glt_bglayer,
9731 	_glt_fglayer,
9732 	_glt_frontpanel,
9733 	_glt_generic,
9734 	_glt_neon,
9735 	_glt_panel,
9736 	_glt_screen,
9737 	_glt_water,
9738 	_glt_the_end,
9739 };
9740 
9741 
9742 // ===== getbglayerproperty ======
9743 enum getbglp_enum
9744 {
9745 	_glp_alpha,
9746 	_glp_amplitude,
9747 	_glp_bgspeedratio,
9748 	_glp_enabled,
9749 	_glp_neon,
9750 	_glp_quake,
9751 	_glp_transparency,
9752 	_glp_watermode,
9753 	_glp_wavelength,
9754 	_glp_wavespeed,
9755 	_glp_xoffset,
9756 	_glp_xratio,
9757 	_glp_xrepeat,
9758 	_glp_xspacing,
9759 	_glp_z,
9760 	_glp_zoffset,
9761 	_glp_zratio,
9762 	_glp_zrepeat,
9763 	_glp_zspacing,
9764 	_glp_the_end,
mapstrings_layerproperty(ScriptVariant ** varlist,int paramCount)9765 };
9766 
9767 void mapstrings_layerproperty(ScriptVariant** varlist, int paramCount)
9768 {
9769 	char *propname = NULL;
9770 	int prop;
9771 
9772 	static const char* proplist[] = {
9773 		"alpha",
9774 		"amplitude",
9775 		"bgspeedratio",
9776 		"enabled",
9777 		"neon",
9778 		"quake",
9779 		"transparency",
9780 		"watermode",
9781 		"wavelength",
9782 		"wavespeed",
9783 		"xoffset",
9784 		"xratio",
9785 		"xrepeat",
9786 		"xspacing",
9787 		"z",
9788 		"zoffset",
9789 		"zratio",
9790 		"zrepeat",
9791 		"zspacing",
9792 	};
9793 
9794 	static const char* typelist[] = {
9795 		"background",
9796 		"bglayer",
9797 		"fglayer",
9798 		"frontpanel",
9799 		"generic",
9800 		"neon",
9801 		"panel",
9802 		"water",
9803 	};
9804 
9805 	if(paramCount < 3) return;
9806 	MAPSTRINGS(varlist[0], typelist, _glt_the_end,
9807 		"Type name '%s' is not supported by function getlayerproperty.\n");
9808 	MAPSTRINGS(varlist[2], proplist, _glp_the_end,
9809 		"Property name '%s' is not supported by function getlayerproperty.\n");
_getlayerproperty(s_layer * layer,int propind,ScriptVariant ** pretvar)9810 }
9811 
9812 HRESULT _getlayerproperty(s_layer* layer, int propind, ScriptVariant** pretvar)
9813 {
9814 
9815 	switch(propind)
9816 	{
9817 	case _glp_alpha:
9818 	{
9819 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9820 		(*pretvar)->lVal = (LONG)layer->drawmethod.alpha;
9821 		break;
9822 	}
9823 	case _glp_amplitude:
9824 	{
9825 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9826 		(*pretvar)->lVal = (LONG)layer->drawmethod.water.amplitude;
9827 		break;
9828 	}
9829 	case _glp_bgspeedratio:
9830 	{
9831 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
9832 		(*pretvar)->dblVal = (DOUBLE)layer->bgspeedratio;
9833 		break;
9834 	}
9835 	case _glp_enabled:
9836 	{
9837 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9838 		(*pretvar)->lVal = (LONG)layer->enabled;
9839 		break;
9840 	}
9841 	case _glp_neon:
9842 	{
9843 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9844 		(*pretvar)->lVal = (LONG)layer->neon;
9845 		break;
9846 	}
9847 	case _glp_quake:
9848 	{
9849 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9850 		(*pretvar)->lVal = (LONG)layer->quake;
9851 		break;
9852 	}
9853 	case _glp_transparency:
9854 	{
9855 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9856 		(*pretvar)->lVal = (LONG)layer->drawmethod.transbg;
9857 		break;
9858 	}
9859 	case _glp_watermode:
9860 	{
9861 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9862 		(*pretvar)->lVal = (LONG)layer->drawmethod.water.watermode;
9863 		break;
9864 	}
9865 
9866 	case _glp_wavelength:
9867 	{
9868 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9869 		(*pretvar)->lVal = (LONG)layer->drawmethod.water.wavelength;
9870 		break;
9871 	}
9872 	case _glp_wavespeed:
9873 	{
9874 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
9875 		(*pretvar)->dblVal = (DOUBLE)layer->drawmethod.water.wavespeed;
9876 		break;
9877 	}
9878 	case _glp_xoffset:
9879 	{
9880 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9881 		(*pretvar)->lVal = (LONG)layer->xoffset;
9882 		break;
9883 	}
9884 	case _glp_xratio:
9885 	{
9886 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
9887 		(*pretvar)->dblVal = (DOUBLE)layer->xratio;
9888 		break;
9889 	}
9890 	case _glp_xrepeat:
9891 	{
9892 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9893 		(*pretvar)->lVal = (LONG)layer->drawmethod.xrepeat;
9894 		break;
9895 	}
9896 	case _glp_xspacing:
9897 	{
9898 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9899 		(*pretvar)->lVal = (LONG)layer->xspacing;
9900 		break;
9901 	}
9902 	case _glp_z:
9903 	{
9904 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9905 		(*pretvar)->lVal = (LONG)layer->z;
9906 		break;
9907 	}
9908 	case _glp_zoffset:
9909 	{
9910 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9911 		(*pretvar)->lVal = (LONG)layer->zoffset;
9912 		break;
9913 	}
9914 	case _glp_zratio:
9915 	{
9916 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
9917 		(*pretvar)->dblVal = (DOUBLE)layer->zratio;
9918 		break;
9919 	}
9920 	case _glp_zrepeat:
9921 	{
9922 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9923 		(*pretvar)->lVal = (LONG)layer->drawmethod.yrepeat;
9924 		break;
9925 	}
9926 	case _glp_zspacing:
9927 	{
9928 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9929 		(*pretvar)->lVal = (LONG)layer->zspacing;
9930 		break;
9931 	}
9932 	default:
9933 		*pretvar = NULL;
9934 		return E_FAIL;
9935 	}
9936 	return S_OK;
9937 }
9938 
9939 HRESULT _changelayerproperty(s_layer* layer, int propind, ScriptVariant* var)
9940 {
9941 	LONG temp;
9942 	DOUBLE temp2;
9943 	switch(propind)
9944 	{
9945 	case _glp_alpha:
9946 	{
9947 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
9948 		layer->drawmethod.alpha = temp;
9949 		break;
9950 	}
9951 	case _glp_amplitude:
9952 	{
9953 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
9954 		layer->drawmethod.water.amplitude = temp;
9955 		break;
9956 	}
9957 	case _glp_bgspeedratio:
9958 	{
9959 		if(FAILED(ScriptVariant_DecimalValue(var, &temp2))) return E_FAIL;
9960 		layer->bgspeedratio = temp2;
9961 		break;
9962 	}
9963 	case _glp_enabled:
9964 	{
9965 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
9966 		layer->enabled = temp;
9967 		break;
9968 	}
9969 	case _glp_neon:
9970 	{
9971 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
9972 		layer->neon = temp;
9973 		break;
9974 	}
9975 	case _glp_quake:
9976 	{
9977 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
9978 		layer->quake = temp;
9979 		break;
9980 	}
9981 	case _glp_transparency:
9982 	{
9983 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
9984 		layer->drawmethod.transbg = temp;
9985 		break;
9986 	}
9987 	case _glp_watermode:
9988 	{
9989 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
9990 		layer->drawmethod.water.watermode = temp;
9991 		break;
9992 	}
9993 
9994 	case _glp_wavelength:
9995 	{
9996 		if(FAILED(ScriptVariant_DecimalValue(var, &temp2))) return E_FAIL;
9997 		layer->drawmethod.water.wavelength = temp2;
9998 		break;
9999 	}
10000 	case _glp_wavespeed:
10001 	{
10002 		if(FAILED(ScriptVariant_DecimalValue(var, &temp2))) return E_FAIL;
10003 		layer->drawmethod.water.wavespeed = temp2;
10004 		break;
10005 	}
10006 	case _glp_xoffset:
10007 	{
10008 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
10009 		layer->xoffset = temp;
10010 		break;
10011 	}
10012 	case _glp_xratio:
10013 	{
10014 		if(FAILED(ScriptVariant_DecimalValue(var, &temp2))) return E_FAIL;
10015 		layer->xratio = temp2;
10016 		break;
10017 	}
10018 	case _glp_xrepeat:
10019 	{
10020 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
10021 		layer->drawmethod.xrepeat = temp;
10022 		break;
10023 	}
10024 	case _glp_xspacing:
10025 	{
10026 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
10027 		layer->xspacing = temp;
10028 		break;
10029 	}
10030 	case _glp_z:
10031 	{
10032 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
10033 		layer->z = temp;
10034 		break;
10035 	}
10036 	case _glp_zoffset:
10037 	{
10038 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
10039 		layer->zoffset = temp;
10040 		break;
10041 	}
10042 	case _glp_zratio:
10043 	{
10044 		if(FAILED(ScriptVariant_DecimalValue(var, &temp2))) return E_FAIL;
10045 		layer->zratio = temp2;
10046 		break;
10047 	}
10048 	case _glp_zrepeat:
10049 	{
10050 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
10051 		layer->drawmethod.yrepeat = temp;
10052 		break;
10053 	}
10054 	case _glp_zspacing:
10055 	{
10056 		if(FAILED(ScriptVariant_IntegerValue(var, &temp))) return E_FAIL;
10057 		layer->zspacing = temp;
10058 		break;
10059 	}
10060 	default:
10061 		return E_FAIL;
10062 	}
10063 	return S_OK;
_getlayer(int type,int ind)10064 }
10065 
10066 s_layer* _getlayer(int type, int ind){
10067 	switch(type){
10068 	case _glt_background:
10069 		return level->background;
10070 	case _glt_bglayer:
10071 		if(ind<0 || ind>=level->numbglayers) return NULL;
10072 		return level->bglayers[ind];
10073 	case _glt_fglayer:
10074 		if(ind<0 || ind>=level->numfglayers) return NULL;
10075 		return level->fglayers[ind];
10076 	case _glt_frontpanel:
10077 		if(ind<0 || ind>=level->numfrontpanels) return NULL;
10078 		return level->frontpanels[ind];
10079 	case _glt_generic:
10080 		if(ind<0 || ind>=level->numgenericlayers) return NULL;
10081 		return level->genericlayers[ind];
10082 	case _glt_neon:
10083 		if(ind<0 || ind>=level->numpanels) return NULL;
10084 		return level->panels[ind][1];
10085 	case _glt_panel:
10086 		if(ind<0 || ind>=level->numpanels) return NULL;
10087 		return level->panels[ind][0];
10088 	case _glt_screen:
10089 		if(ind<0 || ind>=level->numpanels) return NULL;
10090 		return level->panels[ind][2];
10091 	case _glt_water:
10092 		if(ind<0 || ind>=level->numwaters) return NULL;
10093 		return level->waters[ind];
10094 	default:
10095 		return NULL;
10096 	}
10097 }
openbor_getlayerproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10098 
10099 // getlayerproperty(type, index, propertyname);
10100 HRESULT openbor_getlayerproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10101 {
10102 	LONG ind;
10103 	int propind, type;
10104 	s_layer* layer = NULL;
10105 
10106 	if(paramCount < 3)
10107 		goto getlayerproperty_error;
10108 
10109 	mapstrings_layerproperty(varlist, paramCount);
10110 
10111 	type = varlist[0]->lVal;
10112 	propind = varlist[2]->lVal;
10113 
10114 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &ind)))
10115 		goto getlayerproperty_error2;
10116 
10117 	layer = _getlayer(type, (int)ind);
10118 
10119 	if(layer==NULL) goto getlayerproperty_error2;
10120 
10121 	if(FAILED(_getlayerproperty(layer, propind, pretvar)))
10122 		goto getlayerproperty_error3;
10123 
10124 	return S_OK;
10125 
10126 getlayerproperty_error:
10127 	*pretvar = NULL;
10128 	printf("Function getlayerproperty must have 3 parameters: layertype, index and propertyname\n");
10129 	return E_FAIL;
10130 getlayerproperty_error2:
10131 	*pretvar = NULL;
10132 	printf("Layer not found!\n");
10133 	return E_FAIL;
10134 getlayerproperty_error3:
10135 	*pretvar = NULL;
10136 	printf("Bad property name or value.\n");
10137 	return E_FAIL;
10138 }
openbor_changelayerproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10139 
10140 // changelayerproperty(type, index, propertyname);
10141 HRESULT openbor_changelayerproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10142 {
10143 	LONG ind;
10144 	int propind, type;
10145 	s_layer* layer = NULL;
10146 	*pretvar = NULL;
10147 
10148 	if(paramCount < 4)
10149 		goto chglayerproperty_error;
10150 
10151 	mapstrings_layerproperty(varlist, paramCount);
10152 
10153 	type = varlist[0]->lVal;
10154 	propind = varlist[2]->lVal;
10155 
10156 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &ind)))
10157 		goto chglayerproperty_error2;
10158 
10159 	layer = _getlayer(type, (int)ind);
10160 
10161 	if(layer==NULL) goto chglayerproperty_error2;
10162 
10163 	if(FAILED(_changelayerproperty(layer, propind, varlist[3])))
10164 		goto chglayerproperty_error3;
10165 
10166 	return S_OK;
10167 
10168 chglayerproperty_error:
10169 	printf("Function changelayerproperty must have 4 parameters: layertype, index, propertyname and value\n");
10170 	return E_FAIL;
10171 chglayerproperty_error2:
10172 	printf("Layer not found!\n");
10173 	return E_FAIL;
10174 chglayerproperty_error3:
10175 	printf("Layer property not understood or bad value.\n");
10176 	return E_FAIL;
10177 }
10178 
10179 
10180 // ===== level properties ======
10181 enum levelproperty_enum
10182 {
10183 	_lp_bgspeed,
10184 	_lp_cameraxoffset,
10185 	_lp_camerazoffset,
10186 	_lp_gravity,
10187 	_lp_maxfallspeed,
10188 	_lp_maxtossspeed,
10189 	_lp_rocking,
10190 	_lp_scrollspeed,
10191 	_lp_the_end,
10192 };
mapstrings_levelproperty(ScriptVariant ** varlist,int paramCount)10193 
10194 
10195 void mapstrings_levelproperty(ScriptVariant** varlist, int paramCount)
10196 {
10197 	char *propname = NULL;
10198 	int prop;
10199 
10200 	static const char* proplist[] = {
10201 		"bgspeed",
10202 		"cameraxoffset",
10203 		"camerazoffset",
10204 		"gravity",
10205 		"maxfallspeed",
10206 		"maxtossspeed",
10207 		"rocking",
10208 		"scrollspeed",
10209 	};
10210 
10211 
10212 	if(paramCount < 1) return;
10213 	MAPSTRINGS(varlist[0], proplist, _lp_the_end,
10214 		"Level property '%s' is not supported.\n");
10215 }
10216 
10217 HRESULT openbor_getlevelproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10218 {
10219 	mapstrings_drawmethodproperty(varlist, paramCount);
10220 
10221 	switch(varlist[0]->lVal)
10222 	{
10223 	case _lp_bgspeed:
10224 	{
10225 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
10226 		(*pretvar)->lVal = (LONG)level->bgspeed;
10227 		break;
10228 	}
10229 	case _lp_cameraxoffset:
10230 	{
10231 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
10232 		(*pretvar)->lVal = (LONG)level->cameraxoffset;
10233 		break;
10234 	}
10235 	case _lp_camerazoffset:
10236 	{
10237 		ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
10238 		(*pretvar)->lVal = (LONG)level->camerazoffset;
10239 		break;
10240 	}
10241 	case _lp_gravity:
10242 	{
10243 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
10244 		(*pretvar)->dblVal = (DOUBLE)level->gravity;
10245 		break;
10246 	}
10247 	case _lp_maxfallspeed:
10248 	{
10249 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
10250 		(*pretvar)->dblVal = (DOUBLE)level->maxfallspeed;
10251 		break;
10252 	}
10253 	case _lp_maxtossspeed:
10254 	{
10255 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
10256 		(*pretvar)->dblVal = (DOUBLE)level->maxtossspeed;
10257 		break;
10258 	}
10259 	case _lp_scrollspeed:
10260 	{
10261 		ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
10262 		(*pretvar)->dblVal = (DOUBLE)level->scrollspeed;
10263 		break;
10264 	}
10265 	default:
10266 		printf("Property is not supported by function getlevelproperty yet.\n");
10267 		goto getlevelproperty_error;
10268 		break;
10269 	}
10270 
10271 	return S_OK;
10272 
10273 getlevelproperty_error:
10274 	*pretvar = NULL;
10275 	return E_FAIL;
10276 }
openbor_changelevelproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10277 
10278 //changelevelproperty(name, value)
10279 HRESULT openbor_changelevelproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10280 {
10281 	LONG ltemp;
10282 	DOUBLE dbltemp;
10283 	ScriptVariant* arg = NULL;
10284 
10285 	if(paramCount < 2)
10286 	{
10287 		*pretvar = NULL;
10288 		return E_FAIL;
10289 	}
10290 
10291 	mapstrings_drawmethodproperty(varlist, paramCount);
10292 
10293 	arg = varlist[1];
10294 
10295 	switch(varlist[0]->lVal)
10296 	{
10297 	case _lp_rocking:
10298 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
10299 			level->rocking = (int)ltemp;
10300 		else (*pretvar)->lVal = (LONG)0;
10301 		break;
10302 	case _lp_bgspeed:
10303 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
10304 			level->bgspeed = (float)ltemp;
10305 		else (*pretvar)->lVal = (LONG)0;
10306 		break;
10307 	case _lp_scrollspeed:
10308 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
10309 			level->scrollspeed = (float)ltemp;
10310 		else (*pretvar)->lVal = (LONG)0;
10311 		break;
10312 	case _lp_cameraxoffset:
10313 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
10314 			level->cameraxoffset = (int)ltemp;
10315 		else (*pretvar)->lVal = (LONG)0;
10316 		break;
10317 	case _lp_camerazoffset:
10318 		if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
10319 			level->camerazoffset = (int)ltemp;
10320 		else (*pretvar)->lVal = (LONG)0;
10321 		break;
10322 	case _lp_gravity:
10323 		if(SUCCEEDED(ScriptVariant_DecimalValue(arg, &dbltemp)))
10324 			level->gravity = (float)dbltemp;
10325 		else (*pretvar)->lVal = (LONG)0;
10326 		break;
10327 	case _lp_maxfallspeed:
10328 		if(SUCCEEDED(ScriptVariant_DecimalValue(arg, &dbltemp)))
10329 			level->maxfallspeed = (float)dbltemp;
10330 		else (*pretvar)->lVal = (LONG)0;
10331 		break;
10332 	case _lp_maxtossspeed:
10333 		if(SUCCEEDED(ScriptVariant_DecimalValue(arg, &dbltemp)))
10334 			level->maxtossspeed = (float)dbltemp;
10335 		else (*pretvar)->lVal = (LONG)0;
10336 		break;
10337 	default:
10338 		printf("The level property is read-only.\n");
10339 		*pretvar = NULL;
10340 		return E_FAIL;
10341 		break;
10342 	}
10343 
10344 	return S_OK;
10345 }
10346 
openbor_shutdown(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10347 
10348 //shutdown(status, message)
10349 HRESULT openbor_shutdown(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10350 {
10351 	LONG ltemp = 0;
10352 
10353 	*pretvar = NULL;
10354 
10355 	if(paramCount > 0 && FAILED(ScriptVariant_IntegerValue(varlist[0], &ltemp))) goto shutdown_error;
10356 	if(paramCount > 1 && varlist[1]->vt != VT_STR) goto shutdown_error;
10357 
10358 	shutdown((int)ltemp,  paramCount > 1?StrCache_Get(varlist[0]->strVal):(DEFAULT_SHUTDOWN_MESSAGE));
10359 
10360 	return S_OK;
10361 shutdown_error:
10362 	printf("shutdown(status, message): both parameters are optional but must be valid.\n");
10363 	return E_FAIL;
10364 }
openbor_jumptobranch(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10365 
10366 //jumptobranch(name, immediate)
10367 HRESULT openbor_jumptobranch(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10368 {
10369 	LONG ltemp;
10370 	extern char branch_name[MAX_NAME_LEN+1];
10371 	extern int  endgame;
10372 
10373 	*pretvar = NULL;
10374 	if(paramCount < 1) goto jumptobranch_error;
10375 	if(varlist[0]->vt != VT_STR) goto jumptobranch_error;
10376 
10377 	strncpy(branch_name, StrCache_Get(varlist[0]->strVal), MIN(MAX_NAME_LEN, MAX_STR_VAR_LEN)); // copy the string value to branch name
10378 
10379 	if(paramCount >= 2)
10380 	{
10381 		if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)))
10382 		{
10383 			endgame = (int)ltemp;
10384 			// 1 means goto that level immediately, or, wait until the level is complete
10385 		}
10386 		else goto jumptobranch_error;
10387 	}
10388 
10389 	return S_OK;
10390 jumptobranch_error:
10391 	printf("Function requires 1 string value, the second argument is optional(int): jumptobranch(name, immediate)\n");
10392 	return E_FAIL;
10393 }
10394 
openbor_bindentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10395 //bindentity(entity, target, x, z, a, direction, bindanim);
10396 //bindentity(entity, NULL()); // unbind
10397 HRESULT openbor_bindentity(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10398 {
10399 	entity* ent = NULL;
10400 	entity* other = NULL;
10401 	ScriptVariant* arg = NULL;
10402 	void adjust_bind(entity* e);
10403 	LONG x=0, z=0, a=0, dir=0, anim=0;
10404 
10405    *pretvar = NULL;
10406 	if(paramCount < 2)
10407 	{
10408 		return E_FAIL;
10409 	}
10410 
10411 	ent = (entity*)(varlist[0])->ptrVal; //retrieve the entity
10412 	if(!ent)  return S_OK;
10413 
10414 	other = (entity*)(varlist[1])->ptrVal;
10415 	if(!other)  {ent->bound = NULL; return S_OK;}
10416 
10417 	ent->bound = other;
10418 
10419 	if(paramCount < 3) goto BIND;
10420 	// x
10421 	arg = varlist[2];
10422 	if(arg->vt != VT_EMPTY)
10423 	{
10424 		if(FAILED(ScriptVariant_IntegerValue(arg, &x)))  return E_FAIL;
10425 
10426 		ent->bindoffset[0] = (int)x;
10427 	}
10428 	if(paramCount < 4) goto BIND;
10429 	// z
10430 	arg = varlist[3];
10431 	if(arg->vt != VT_EMPTY)
10432 	{
10433 		if(FAILED(ScriptVariant_IntegerValue(arg, &z)))  return E_FAIL;
10434 		ent->bindoffset[1] = (int)z;
10435 	}
10436 	if(paramCount < 5) goto BIND;
10437 	// a
10438 	arg = varlist[4];
10439 	if(arg->vt != VT_EMPTY)
10440 	{
10441 		if(FAILED(ScriptVariant_IntegerValue(arg, &a)))  return E_FAIL;
10442 		ent->bindoffset[2] = (int)a;
10443 	}
10444 	if(paramCount < 6) goto BIND;
10445 	// direction
10446 	arg = varlist[5];
10447 	if(arg->vt != VT_EMPTY)
10448 	{
10449 		if(FAILED(ScriptVariant_IntegerValue(arg, &dir)))  return E_FAIL;
10450 		ent->bindoffset[3] = (int)dir;
10451 	}
10452 	if(paramCount < 7) goto BIND;
10453 	// animation
10454 	arg = varlist[6];
10455 	if(arg->vt != VT_EMPTY)
10456 	{
10457 		if(FAILED(ScriptVariant_IntegerValue(arg, &anim)))  return E_FAIL;
10458 		ent->bindanim = (int)anim;
10459 	}
10460 
10461 BIND:
10462 	adjust_bind(ent);
10463 
10464 	return S_OK;
10465 }
openbor_array(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10466 
10467 //array(size);
10468 HRESULT openbor_array(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10469 {
10470 	LONG size;
10471 	void* array;
10472 
10473 	if(paramCount < 1) goto array_error;
10474 
10475 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &size)))
10476 		goto array_error;
10477 
10478 	if(size<=0) goto array_error;
10479 
10480 	ScriptVariant_ChangeType(*pretvar, VT_PTR);
10481 	array = malloc(sizeof(ScriptVariant)*(size+1));
10482 	if(array) memset(array, 0, sizeof(ScriptVariant)*(size+1));
10483 	(*pretvar)->ptrVal = (VOID*)array;
10484 
10485 	if((*pretvar)->ptrVal==NULL)
10486 	{
10487 		printf("Not enough memory: array(%d)\n", (int)size);
10488 		(*pretvar) = NULL;
10489 		return E_FAIL;
10490 	}
10491 
10492 	ScriptVariant_ChangeType((ScriptVariant*)array, VT_INTEGER);
10493 	((ScriptVariant*)array)->lVal = (LONG)size;
10494 
10495 	List_InsertAfter(&scriptheap, (void*)((*pretvar)->ptrVal), "openbor_array");
10496 	return S_OK;
10497 
10498 array_error:
10499 	printf("Function requires 1 positive int value: array(int size)\n");
10500 	(*pretvar) = NULL;
10501 	return E_FAIL;
10502 }
10503 
openbor_size(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10504 
10505 //size(array)
10506 HRESULT openbor_size(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10507 {
10508 	if(paramCount < 1 ) goto size_error;
10509 	if(varlist[0]->vt!=VT_PTR)  goto size_error;
10510 
10511 	ScriptVariant_Copy(*pretvar, ((ScriptVariant*)varlist[0]->ptrVal));
10512 
10513 	return S_OK;
10514 
10515 size_error:
10516 	printf("Function requires 1 array handle: size(array)\n");
10517 	(*pretvar) = NULL;
10518 	return E_FAIL;
10519 }
openbor_get(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10520 
10521 //get(array, index);
10522 HRESULT openbor_get(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10523 {
10524 	LONG ind, size;
10525 
10526 	if(paramCount < 2 ) goto get_error;
10527 
10528 	if(varlist[0]->vt!=VT_PTR)  goto get_error;
10529 
10530 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &ind)))
10531 		goto get_error;
10532 
10533 	ScriptVariant_IntegerValue(((ScriptVariant*)varlist[0]->ptrVal), &size);
10534 	if(ind<0 || ind>=size) goto get_error2;
10535 
10536 	ScriptVariant_Copy(*pretvar, ((ScriptVariant*)varlist[0]->ptrVal)+ind+1);
10537 
10538 	return S_OK;
10539 
10540 get_error:
10541 	printf("Function requires 1 array handle and 1 int value: get(array, int index)\n");
10542 	(*pretvar) = NULL;
10543 	return E_FAIL;
10544 get_error2:
10545 	printf("Array bound out of range: %d, max %d\n", ind, size-1);
10546 	(*pretvar) = NULL;
10547 	return E_FAIL;
10548 }
openbor_set(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10549 
10550 //set(array, index, value);
10551 HRESULT openbor_set(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10552 {
10553 	LONG ind, size;
10554 	(*pretvar) = NULL;
10555 
10556 	if(paramCount < 3 ) goto set_error;
10557 
10558 	if(varlist[0]->vt!=VT_PTR)  goto set_error;
10559 
10560 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &ind)))
10561 		goto set_error;
10562 
10563 	ScriptVariant_IntegerValue(((ScriptVariant*)varlist[0]->ptrVal), &size);
10564 	if(ind<0 || ind>=size) goto set_error2;
10565 
10566 	ScriptVariant_Copy(((ScriptVariant*)varlist[0]->ptrVal)+ind+1, varlist[2]);
10567 
10568 	return S_OK;
10569 
10570 set_error:
10571 	printf("Function requires 1 array handle, 1 int value and 1 value: set(array, int index, value)\n");
10572 	return E_FAIL;
10573 set_error2:
10574 	printf("Array bound out of range: %d, max %d\n", ind, size-1);
10575 	return E_FAIL;
10576 }
openbor_allocscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10577 
10578 //allocscreen(int w, int h);
10579 HRESULT openbor_allocscreen(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10580 {
10581 	LONG w, h;
10582 	s_screen* screen;
10583 
10584 	if(paramCount < 2) goto allocscreen_error;
10585 
10586 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &w)))
10587 		goto allocscreen_error;
10588 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &h)))
10589 		goto allocscreen_error;
10590 
10591 
10592 	ScriptVariant_ChangeType(*pretvar, VT_PTR);
10593 	screen = allocscreen((int)w, (int)h, screenformat);
10594 	if(screen) clearscreen(screen);
10595 	(*pretvar)->ptrVal = (VOID*)screen;
10596 
10597 	if((*pretvar)->ptrVal==NULL)
10598 	{
10599 		printf("Not enough memory: allocscreen(%d, %d)\n", (int)w, (int)h);
10600 		(*pretvar) = NULL;
10601 		return E_FAIL;
10602 	}
10603 	List_InsertAfter(&scriptheap, (void*)((*pretvar)->ptrVal), "openbor_allocscreen");
10604 	return S_OK;
10605 
10606 allocscreen_error:
10607 	printf("Function requires 2 int values: allocscreen(int width, int height)\n");
10608 	(*pretvar) = NULL;
10609 	return E_FAIL;
10610 }
openbor_clearscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10611 
10612 //clearscreen(s_screen* screen)
10613 HRESULT openbor_clearscreen(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10614 {
10615 	s_screen* screen;
10616 
10617 	*pretvar = NULL;
10618 	if(paramCount != 1) goto clearscreen_error;
10619 	if(varlist[0]->vt != VT_PTR) goto clearscreen_error;
10620 
10621 	screen = (s_screen*)varlist[0]->ptrVal;
10622 
10623 	if(screen == NULL)
10624 	{
10625 		printf("Error: NULL pointer passed to clearscreen(void screen)\n");
10626 		*pretvar = NULL;
10627 		return E_FAIL;
10628 	}
10629 	clearscreen(screen);
10630 	return S_OK;
10631 
10632 clearscreen_error:
10633 	printf("Function requires a screen pointer: clearscreen(void screen)\n");
10634 	return E_FAIL;
10635 }
10636 
10637 // ===== changedrawmethod ======
10638 enum drawmethod_enum
10639 {
10640 	_dm_alpha,
10641 	_dm_amplitude,
10642 	_dm_beginsize,
10643 	_dm_centerx,
10644 	_dm_centery,
10645 	_dm_enabled,
10646 	_dm_endsize,
10647 	_dm_fillcolor,
10648 	_dm_flag,
10649 	_dm_fliprotate,
10650 	_dm_flipx,
10651 	_dm_perspective,
10652 	_dm_remap,
10653 	_dm_reset,
10654 	_dm_rotate,
10655 	_dm_scalex,
10656 	_dm_scaley,
10657 	_dm_shiftx,
10658 	_dm_table,
10659 	_dm_transbg,
10660 	_dm_watermode,
10661 	_dm_wavelength,
10662 	_dm_wavespeed,
10663 	_dm_wavetime,
10664 	_dm_xrepeat,
10665 	_dm_xspan,
10666 	_dm_yrepeat,
10667 	_dm_yspan,
10668 	_dm_the_end,
10669 };
mapstrings_drawmethodproperty(ScriptVariant ** varlist,int paramCount)10670 
10671 
10672 void mapstrings_drawmethodproperty(ScriptVariant** varlist, int paramCount)
10673 {
10674 	char *propname = NULL;
10675 	int prop;
10676 
10677 	static const char* proplist[] = {
10678 		"alpha",
10679 		"amplitude",
10680 		"beginsize",
10681 		"centerx",
10682 		"centery",
10683 		"enabled",
10684 		"endsize",
10685 		"fillcolor",
10686 		"flag",
10687 		"fliprotate",
10688 		"flipx",
10689 		"perspective",
10690 		"remap",
10691 		"reset",
10692 		"rotate",
10693 		"scalex",
10694 		"scaley",
10695 		"shiftx",
10696 		"table",
10697 		"transbg",
10698 		"watermode",
10699 		"wavelength",
10700 		"wavespeed",
10701 		"wavetime",
10702 		"xrepeat",
10703 		"xspan",
10704 		"yrepeat",
10705 		"yspan",
10706 	};
10707 
10708 
10709 	if(paramCount < 2) return;
10710 	MAPSTRINGS(varlist[1], proplist, _dm_the_end,
10711 		"Property name '%s' is not supported by drawmethod.\n");
10712 }
openbor_changedrawmethod(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10713 
10714 // changedrawmethod(entity, propertyname, value);
10715 HRESULT openbor_changedrawmethod(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10716 {
10717 	entity* e;
10718 	LONG temp = 0;
10719 	DOUBLE ftemp = 0;
10720 	s_drawmethod *pmethod;
10721 	*pretvar = NULL;
10722 
10723 	if(paramCount < 3)
10724 		goto changedm_error;
10725 
10726 	mapstrings_drawmethodproperty(varlist, paramCount);
10727 
10728 	if(varlist[0]->vt==VT_EMPTY) e = NULL;
10729 	else if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
10730 	else goto changedm_error;
10731 
10732 	if(e) pmethod = &(e->drawmethod);
10733 	else  pmethod = &(drawmethod);
10734 
10735 	switch(varlist[1]->lVal){
10736 
10737 	case _dm_alpha:
10738 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10739 		pmethod->alpha = (int)temp;
10740 	break;
10741 	case _dm_amplitude:
10742 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10743 		pmethod->water.amplitude = (int)temp;
10744 	break;
10745 	case _dm_beginsize:
10746 		if(FAILED(ScriptVariant_DecimalValue(varlist[2], &ftemp))) return E_FAIL;
10747 		pmethod->water.beginsize = (float)ftemp;
10748 	break;
10749 	case _dm_centerx:
10750 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10751 		pmethod->centerx = (int)temp;
10752 	break;
10753 	case _dm_centery:
10754 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10755 		pmethod->centery = (int)temp;
10756 	break;
10757 	case _dm_enabled:
10758 	case _dm_flag:
10759 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10760 		pmethod->flag = (int)temp;
10761 	break;
10762 	case _dm_endsize:
10763 		if(FAILED(ScriptVariant_DecimalValue(varlist[2], &ftemp))) return E_FAIL;
10764 		pmethod->water.endsize = (float)ftemp;
10765 	break;
10766 	case _dm_fillcolor:
10767 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10768 		pmethod->fillcolor = (int)temp;
10769 	break;
10770 	case _dm_fliprotate:
10771 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10772 		pmethod->fliprotate = (int)temp;
10773 	break;
10774 	case _dm_flipx:
10775 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10776 		pmethod->flipx = (int)temp;
10777 	break;
10778 	case _dm_perspective:
10779 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10780 		pmethod->water.perspective = (int)temp;
10781 	break;
10782 	case _dm_remap:
10783 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10784 		pmethod->remap = (int)temp;
10785 	break;
10786 	case _dm_reset:
10787 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10788 		if(temp) *pmethod = plainmethod;
10789 	break;
10790 	case _dm_rotate:
10791 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10792 		pmethod->rotate = (int)temp;
10793 	break;
10794 	case _dm_scalex:
10795 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10796 		pmethod->scalex = (int)temp;
10797 	break;
10798 	case _dm_scaley:
10799 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10800 		pmethod->scaley = (int)temp;
10801 	break;
10802 	case _dm_shiftx:
10803 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10804 		pmethod->shiftx = (int)temp;
10805 	break;
10806 	case _dm_table:
10807 		if(varlist[2]->vt != VT_PTR && varlist[2]->vt != VT_EMPTY ) return E_FAIL;
10808 		pmethod->table = (void*)varlist[2]->ptrVal;
10809 	break;
10810 	case _dm_transbg:
10811 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10812 		pmethod->transbg = (int)temp;
10813 	break;
10814 	case _dm_watermode:
10815 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10816 		pmethod->water.watermode = (int)temp;
10817 	break;
10818 	case _dm_wavelength:
10819 		if(FAILED(ScriptVariant_DecimalValue(varlist[2], &ftemp))) return E_FAIL;
10820 		pmethod->water.wavelength = (float)ftemp;
10821 	break;
10822 	case _dm_wavespeed:
10823 		if(FAILED(ScriptVariant_DecimalValue(varlist[2], &ftemp))) return E_FAIL;
10824 		pmethod->water.wavespeed = (float)ftemp;
10825 	break;
10826 	case _dm_wavetime:
10827 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10828 		pmethod->water.wavetime = (int)(temp*pmethod->water.wavespeed);
10829 	break;
10830 	case _dm_xrepeat:
10831 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10832 		pmethod->xrepeat = (int)temp;
10833 	break;
10834 	case _dm_yrepeat:
10835 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10836 		pmethod->yrepeat = (int)temp;
10837 	break;
10838 	case _dm_xspan:
10839 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10840 		pmethod->xspan = (int)temp;
10841 	break;
10842 	case _dm_yspan:
10843 		if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp))) return E_FAIL;
10844 		pmethod->yspan = (int)temp;
10845 	break;
10846 	default:
10847 	break;
10848 
10849 	}
10850 
10851 	return S_OK;
10852 
10853 changedm_error:
10854 	printf("Function changedrawmethod must have at least 3 parameters: entity, propertyname, value\n");
10855 	return E_FAIL;
10856 }
10857 
10858 
openbor_setdrawmethod(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10859 //deprecated
10860 //setdrawmethod(entity, int flag, int scalex, int scaley, int flipx, int flipy, int shiftx, int alpha, int remap, int fillcolor, int rotate, int fliprotate, int transparencybg, void* colourmap, int centerx, int centery);
10861 HRESULT openbor_setdrawmethod(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10862 {
10863 	LONG value[14];
10864 	entity* e;
10865 	s_drawmethod *pmethod;
10866 	int i;
10867 
10868 	*pretvar = NULL;
10869 	if(paramCount<2) goto setdrawmethod_error;
10870 
10871 	if(varlist[0]->vt==VT_EMPTY) e = NULL;
10872 	else if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
10873 	else goto setdrawmethod_error;
10874 
10875 	if(e) pmethod = &(e->drawmethod);
10876 	else  pmethod = &(drawmethod);
10877 
10878 	memset(value, 0, sizeof(LONG)*14);
10879 	for(i=1; i<paramCount && i<13; i++)
10880 	{
10881 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-1))) goto setdrawmethod_error;
10882 	}
10883 
10884 	if(paramCount>=14 && varlist[13]->vt!=VT_PTR && varlist[13]->vt!=VT_EMPTY) goto setdrawmethod_error;
10885 
10886 	for(i=14; i<paramCount && i<16; i++)
10887 	{
10888 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-2))) goto setdrawmethod_error;
10889 	}
10890 
10891 	pmethod->flag = (int)value[0];
10892 	pmethod->scalex = (int)value[1];
10893 	pmethod->scaley = (int)value[2];
10894 	pmethod->flipx = (int)value[3];
10895 	pmethod->flipy = (int)value[4];
10896 	pmethod->shiftx = (int)value[5];
10897 	pmethod->alpha = (int)value[6];
10898 	pmethod->remap = (int)value[7];
10899 	pmethod->fillcolor = (int)value[8];
10900 	pmethod->rotate = ((int)value[9])%360;
10901 	pmethod->fliprotate = (int)value[10];
10902 	pmethod->transbg = (int)value[11];
10903 	if(paramCount>=14) pmethod->table=(unsigned char*)varlist[13]->ptrVal;
10904 	pmethod->centerx = (int)value[12];
10905 	pmethod->centery = (int)value[13];
10906 
10907 	if(pmethod->rotate<0) pmethod->rotate += 360;
10908 	return S_OK;
10909 
10910 setdrawmethod_error:
10911 	printf("Function need a valid entity handle and at least 1 interger parameter, setdrawmethod(entity, int flag, int scalex, int scaley, int flipx, int flipy, int shiftx, int alpha, int remap, int fillcolor, int rotate, int fliprotate, int transparencybg, void* colourmap, centerx, centery)\n");
10912 	return E_FAIL;
10913 }
openbor_updateframe(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10914 
10915 //updateframe(entity, int frame);
10916 HRESULT openbor_updateframe(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10917 {
10918 	LONG f;
10919 	entity* e;
10920 	void update_frame(entity* ent, int f);
10921 
10922 	*pretvar = NULL;
10923 	if(paramCount<2) goto updateframe_error;
10924 
10925 	if(varlist[0]->vt==VT_EMPTY) e = NULL;
10926 	else if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
10927 	else goto updateframe_error;
10928 
10929 	if(!e) goto updateframe_error;
10930 
10931 	if(FAILED(ScriptVariant_IntegerValue(varlist[1], &f))) goto updateframe_error;
10932 
10933 	update_frame(e, (int)f);
10934 
10935 	return S_OK;
10936 
10937 updateframe_error:
10938 	printf("Function need a valid entity handle and at an interger parameter: updateframe(entity, int frame)\n");
10939 	return E_FAIL;
10940 }
openbor_performattack(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10941 
10942 //performattack(entity, int anim, int resetable);
10943 HRESULT openbor_performattack(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10944 {
10945 	LONG anim, resetable=0;
10946 	entity* e;
10947 
10948 	*pretvar = NULL;
10949 	if(paramCount<1) goto performattack_error;
10950 
10951 	if(varlist[0]->vt==VT_EMPTY) e = NULL;
10952 	else if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
10953 	else goto performattack_error;
10954 
10955 	if(!e) goto performattack_error;
10956 
10957 	e->takeaction = common_attack_proc;
10958 	e->attacking = 1;
10959 	e->idling = 0;
10960 	e->drop = 0;
10961 	e->falling = 0;
10962 	e->inpain = 0;
10963 	e->blocking = 0;
10964 
10965 	if(paramCount==1) return S_OK;
10966 
10967 	if(paramCount>1 && FAILED(ScriptVariant_IntegerValue(varlist[1], &anim))) goto performattack_error;
10968 	if(paramCount>2 && FAILED(ScriptVariant_IntegerValue(varlist[2], &resetable)))  goto performattack_error;
10969 	ent_set_anim(e, (int)anim, (int)resetable);
10970 
10971 	return S_OK;
10972 
10973 performattack_error:
10974 	printf("Function need a valid entity handle, the other 2 integer parameters are optional: performattack(entity, int anim, int resetable)\n");
10975 	return E_FAIL;
10976 }
openbor_setidle(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10977 
10978 //setidle(entity, int anim, int resetable, int stalladd);
10979 HRESULT openbor_setidle(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
10980 {
10981 	LONG anim=0, resetable=0, stalladd=0;
10982 	entity* e;
10983 	extern unsigned int time;
10984 
10985 	*pretvar = NULL;
10986 	if(paramCount<1) goto setidle_error;
10987 
10988 	if(varlist[0]->vt==VT_EMPTY) e = NULL;
10989 	else if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
10990 	else goto setidle_error;
10991 
10992 	if(!e) goto setidle_error;
10993 
10994 	e->takeaction = NULL;
10995 	e->attacking = 0;
10996 	e->idling = 1;
10997 	e->drop = 0;
10998 	e->falling = 0;
10999 	e->inpain = 0;
11000 	e->blocking = 0;
11001 	e->nograb = 0;
11002 	e->destx = e->x;
11003 	e->destz = e->z;
11004 
11005 	if(paramCount==1) return S_OK;
11006 
11007 	if(paramCount>1 && FAILED(ScriptVariant_IntegerValue(varlist[1], &anim))) goto setidle_error;
11008 	if(paramCount>2 && FAILED(ScriptVariant_IntegerValue(varlist[2], &resetable)))  goto setidle_error;
11009 	if(paramCount>3 && FAILED(ScriptVariant_IntegerValue(varlist[3], &stalladd)))  goto setidle_error;
11010 	ent_set_anim(e, (int)anim, (int)resetable);
11011 
11012 	if(stalladd>0) e->stalltime = time+stalladd;
11013 
11014 	return S_OK;
11015 
11016 setidle_error:
11017 	printf("Function need a valid entity handle, the other 3 integer parameters are optional: setidle(entity, int anim, int resetable, int stalladd)\n");
11018 	return E_FAIL;
11019 }
openbor_getentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11020 
11021 //getentity(int index_from_list)
11022 HRESULT openbor_getentity(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11023 {
11024 	LONG ind;
11025 	extern entity** ent_list;
11026 	extern int ent_list_size;
11027 
11028 	if(paramCount!=1) goto getentity_error;
11029 
11030 	if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind))) goto getentity_error;
11031 
11032 	ScriptVariant_Clear(*pretvar);
11033 
11034 	if((int)ind<ent_list_size && (int)ind>=0)
11035 	{
11036 		ScriptVariant_ChangeType(*pretvar, VT_PTR);
11037 		(*pretvar)->ptrVal = (VOID*)ent_list[(int)ind];
11038 	}
11039 	//else, it should return an empty value
11040 	return S_OK;
11041 
11042 getentity_error:
11043 	printf("Function need an integer parameter: getentity(int index_in_list)\n");
11044 	*pretvar = NULL;
11045 	return E_FAIL;
11046 }
11047 
openbor_loadmodel(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11048 
11049 //loadmodel(name)
11050 HRESULT openbor_loadmodel(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11051 {
11052 	LONG unload = 0;
11053 	s_model* model;
11054 	if(paramCount<1) goto loadmodel_error;
11055 	if(varlist[0]->vt!=VT_STR) goto loadmodel_error;
11056 
11057 	 ScriptVariant_ChangeType(*pretvar, VT_PTR);
11058 	 if(paramCount >= 2)
11059 		 if(FAILED(ScriptVariant_IntegerValue(varlist[1], &unload))) goto loadmodel_error;
11060 
11061 	model = load_cached_model(StrCache_Get(varlist[0]->strVal), "openbor_loadmodel", (char)unload);
11062 
11063 	if(paramCount>=3 && model) model_cache[model->index].selectable = (char)ScriptVariant_IsTrue(varlist[2]);
11064 
11065 	(*pretvar)->ptrVal = (VOID*)model;
11066 
11067 	//else, it should return an empty value
11068 	return S_OK;
11069 
11070 loadmodel_error:
11071 	printf("Function needs a string and integer parameters: loadmodel(name, unload, selectable)\n");
11072 	ScriptVariant_Clear(*pretvar);
11073 	*pretvar = NULL;
11074 	return E_FAIL;
11075 }
11076 
openbor_loadsprite(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11077 // load a sprite which doesn't belong to the sprite_cache
11078 // loadsprite(path)
11079 HRESULT openbor_loadsprite(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11080 {
11081 	extern s_sprite * loadsprite2(char *filename, int* width, int* height);
11082 	if(paramCount!=1) goto loadsprite_error;
11083 
11084 	if(varlist[0]->vt!=VT_STR) goto loadsprite_error;
11085 
11086 	ScriptVariant_ChangeType(*pretvar, VT_PTR);
11087 	if(((*pretvar)->ptrVal = (VOID*)loadsprite2(StrCache_Get(varlist[0]->strVal), NULL, NULL)))
11088 	{
11089 		List_InsertAfter(&scriptheap, (void*)((*pretvar)->ptrVal), "openbor_loadsprite");
11090 	}
11091 	//else, it should return an empty value
11092 	return S_OK;
11093 
11094 loadsprite_error:
11095 	printf("Function need a string parameter: loadsprite(path)\n");
11096 	ScriptVariant_Clear(*pretvar);
11097 	*pretvar = NULL;
11098 	return E_FAIL;
11099 }
openbor_options(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11100 
11101 // debug only for now
11102 HRESULT openbor_options(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11103 {
11104 	void options();
11105 	options();
11106 	*pretvar = NULL;
11107 	return S_OK;
11108 }
openbor_playgif(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11109 
11110 //playgif(path, int x, int y, int noskip)
11111 HRESULT openbor_playgif(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11112 {
11113 	LONG temp[3] = {0,0,0}; //x,y,noskip
11114 	int i;
11115 	extern unsigned char pal[1024];
11116 	extern int playgif(char *filename, int x, int y, int noskip);
11117 	if(paramCount<1) goto playgif_error;
11118 
11119 	if(varlist[0]->vt!=VT_STR) goto playgif_error;
11120 
11121 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11122 	for(i=0; i<3 && i<paramCount-1; i++)
11123 	{
11124 		if(FAILED(ScriptVariant_IntegerValue(varlist[i+1], temp+i))) goto playgif_error;
11125 	}
11126 	(*pretvar)->lVal = (LONG)playgif(StrCache_Get(varlist[0]->strVal), (int)(temp[0]), (int)(temp[1]), (int)(temp[2]));
11127 	palette_set_corrected(pal, savedata.gamma,savedata.gamma,savedata.gamma, savedata.brightness,savedata.brightness,savedata.brightness);
11128 	return S_OK;
11129 
11130 playgif_error:
11131 	printf("Function need a string parameter, other parameters are optional: playgif(path, int x, int y, int noskip)\n");
11132 	*pretvar = NULL;
11133 	return E_FAIL;
11134 }
11135 
openbor_aicheckwarp(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11136 
11137 // basic ai checkings, make it easier for modder to create their own think script
11138 HRESULT openbor_aicheckwarp(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11139 
11140 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11141 	(*pretvar)->lVal = (LONG) ai_check_warp();
11142 	return S_OK;
11143 }
11144 HRESULT openbor_aichecklie(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11145 
11146 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11147 	(*pretvar)->lVal = (LONG) ai_check_lie();
openbor_aicheckgrabbed(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11148 	return S_OK;
11149 }
11150 HRESULT openbor_aicheckgrabbed(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11151 
11152 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11153 	(*pretvar)->lVal = (LONG) ai_check_grabbed();
openbor_aicheckgrab(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11154 	return S_OK;
11155 }
11156 HRESULT openbor_aicheckgrab(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11157 
11158 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11159 	(*pretvar)->lVal = (LONG) ai_check_grab();
openbor_aicheckescape(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11160 	return S_OK;
11161 }
11162 HRESULT openbor_aicheckescape(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11163 
11164 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11165 	(*pretvar)->lVal = (LONG) ai_check_escape();
openbor_aicheckbusy(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11166 	return S_OK;
11167 }
11168 HRESULT openbor_aicheckbusy(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11169 
11170 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11171 	(*pretvar)->lVal = (LONG) ai_check_busy();
openbor_aicheckattack(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11172 	return S_OK;
11173 }
11174 HRESULT openbor_aicheckattack(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11175 
11176 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11177 	(*pretvar)->lVal = (LONG) common_attack();
openbor_aicheckmove(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11178 	return S_OK;
11179 }
11180 HRESULT openbor_aicheckmove(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11181 
11182 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11183 	(*pretvar)->lVal = (LONG) common_move();
openbor_aicheckjump(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11184 	return S_OK;
11185 }
11186 HRESULT openbor_aicheckjump(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11187 
11188 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11189 	(*pretvar)->lVal = (LONG) common_try_jump();
openbor_aicheckpathblocked(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11190 	return S_OK;
11191 }
11192 HRESULT openbor_aicheckpathblocked(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11193 
11194 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11195 	(*pretvar)->lVal = (LONG) checkpathblocked();
11196 	return S_OK;
11197 }
11198 
openbor_adjustwalkanimation(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11199 // complex, so make a function for ai
11200 // adjustwalkanimation(ent, target);
11201 HRESULT openbor_adjustwalkanimation(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11202 
11203 	entity* e, *t, *temp;
11204 
11205 	*pretvar = NULL;
11206 
11207 	if(paramCount<1) e = self;
11208 	else if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
11209 	else goto adjustwalkanimation_error;
11210 
11211 	if(paramCount<2) t = NULL;
11212 	else if(varlist[1]->vt==VT_PTR) t = (entity*)varlist[1]->ptrVal;
11213 	else if(varlist[1]->vt==VT_EMPTY) t = NULL;
11214 	else goto adjustwalkanimation_error;
11215 
11216 	temp = self;
11217 
11218 	self = e;
11219 	adjust_walk_animation(t);
11220 	self = temp;
11221 
11222 	return S_OK;
11223 adjustwalkanimation_error:
11224 	printf("Function adjustwalkanimation(entity, target), both parameters are optional, but must be valid.");
11225 	return E_FAIL;
11226 }
openbor_finditem(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11227 
11228 //finditem(entity)
11229 HRESULT openbor_finditem(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11230 
11231 	entity* e, *t, *temp;
11232 
11233 	if(paramCount<1) e = self;
11234 	else if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
11235 	else goto finditem_error;
11236 
11237 	temp = self;
11238 
11239 	self = e;
11240 	t = normal_find_item();
11241 	self = temp;
11242 
11243 	ScriptVariant_ChangeType(*pretvar, VT_PTR);
11244 	(*pretvar)->ptrVal = (VOID*)t;
11245 
11246 	return S_OK;
11247 finditem_error:
11248 
11249 	*pretvar = NULL;
11250 	printf("Function finditem(entity), entity is optional, but must be valid.");
11251 	return E_FAIL;
11252 }
openbor_pickup(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11253 
11254 //pickup(entity, item)
11255 HRESULT openbor_pickup(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11256 
11257 	entity* e, *t, *temp;
11258 
11259 	*pretvar = NULL;
11260 
11261 	if(paramCount<2) goto pickup_error;
11262 
11263 	if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
11264 	else goto pickup_error;
11265 
11266 	if(varlist[1]->vt==VT_PTR) t = (entity*)varlist[1]->ptrVal;
11267 	else goto pickup_error;
11268 
11269 	if(!e || !t) goto pickup_error;
11270 
11271 	temp = self;
11272 
11273 	self = e;
11274 	common_pickupitem(t);
11275 	self = temp;
11276 
11277 	return S_OK;
11278 pickup_error:
11279 	printf("Function pickup(entity, item), handles must be valid.");
11280 	return E_FAIL;
11281 }
11282 
openbor_waypoints(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11283 //waypoints(ent, x1, z1, x2, z2, x3, z3, ...)
11284 //zero length list means clear waypoints
11285 HRESULT openbor_waypoints(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11286 	int num, i;
11287 	point2d* wp = NULL;
11288 	DOUBLE x, z;
11289 
11290 	entity* e;
11291 	*pretvar = NULL;
11292 
11293 	if(paramCount<1) goto wp_error;
11294 
11295 	if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
11296 	else goto wp_error;
11297 
11298 	num = (paramCount-1)/2;
11299 	if(num>0) {
11300 		//append
11301 		wp = (point2d*)malloc(sizeof(point2d)*(num+e->numwaypoints));
11302 
11303 		for(i=0; i<num ; i++){
11304 			if(FAILED(ScriptVariant_DecimalValue(varlist[1], &x)))
11305 				goto wp_error;
11306 
11307 			if(FAILED(ScriptVariant_DecimalValue(varlist[2], &z)))
11308 				goto wp_error;
11309 
11310 			wp[num-i-1].x = (float)x;
11311 			wp[num-i-1].z = (float)z;
11312 		}
11313 		if(e->numwaypoints){
11314 			for(i=0; i<e->numwaypoints; i++){
11315 				wp[i+num] = e->waypoints[i];
11316 			}
11317 		}
11318 
11319 		if(e->waypoints) free(e->waypoints);
11320 		e->waypoints = wp;
11321 		e->numwaypoints = num;
11322 	} else {
11323 		e->numwaypoints = 0;
11324 		if(e->waypoints) free(e->waypoints);
11325 		e->waypoints = NULL;
11326 	}
11327 	return S_OK;
11328 
11329 wp_error:
11330 	if(wp) free(wp);
11331 	wp = NULL;
11332 	printf("Function waypoints requires a valid entity handle and a list of x, z value pairs.");
11333 	return E_FAIL;
11334 }
openbor_testmove(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11335 
11336 //testmove(entity, x, z)
11337 HRESULT openbor_testmove(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11338 
11339 	entity* e;
11340 	DOUBLE x, z;
11341 
11342 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11343 
11344 	if(paramCount<3) goto testmove_error;
11345 
11346 	if(varlist[0]->vt==VT_PTR) e = (entity*)varlist[0]->ptrVal;
11347 	else goto testmove_error;
11348 
11349 	if(FAILED(ScriptVariant_DecimalValue(varlist[1], &x)))
11350 		goto testmove_error;
11351 
11352 	if(FAILED(ScriptVariant_DecimalValue(varlist[2], &z)))
11353 		goto testmove_error;
11354 
11355 	if(!e) goto testmove_error;
11356 
11357 	(*pretvar)->lVal = (LONG) testmove(e, e->x, e->z, x, z);
11358 
11359 	return S_OK;
11360 testmove_error:
11361 	*pretvar = NULL;
11362 	printf("Function testmove(entity, x, z)");
11363 	return E_FAIL;
11364 }
openbor_drawspriteq(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11365 
11366 //spriteq_draw(vscreen, 0, MIN_INT, MAX_INT, dx, dy)
11367 HRESULT openbor_drawspriteq(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11368 
11369 	LONG value[5] = {0, MIN_INT, MAX_INT, 0, 0};
11370 	int i;
11371 	s_screen* screen;
11372 	extern s_screen* vscreen;
11373 
11374 	*pretvar = NULL;
11375 
11376 	if(paramCount<1) goto drawsq_error;
11377 
11378 	if(varlist[0]->vt!=VT_PTR && varlist[0]->vt!=VT_EMPTY) goto drawsq_error;
11379 
11380 	if(varlist[0]->ptrVal) screen = (s_screen*)varlist[0]->ptrVal;
11381 	else screen = vscreen;
11382 
11383 	for(i=1; i<paramCount && i<=5; i++){
11384 		if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-1)))
11385 			goto drawsq_error;
11386 	}
11387 
11388 	spriteq_draw(screen, (int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4]);
11389 
11390 	return S_OK;
11391 
11392 drawsq_error:
11393 	printf("Function drawspriteq needs a valid screen handle and all other paramaters must be integers.");
11394 	return E_FAIL;
11395 
11396 }
11397 
11398 HRESULT openbor_clearspriteq(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount){
11399 	*pretvar = NULL;
11400 	spriteq_clear();
11401 	return S_OK;
11402 
11403 }
11404 
11405 // ===== gfxproperty ======
11406 enum gfxproperty_enum
11407 {
11408 	_gfx_centerx,
11409 	_gfx_centery,
11410 	_gfx_height,
11411 	_gfx_palette,
11412 	_gfx_pixel,
11413 	_gfx_pixelformat,
11414 	_gfx_srcheight,
11415 	_gfx_srcwidth,
11416 	_gfx_width,
11417 	_gfx_the_end,
mapstrings_gfxproperty(ScriptVariant ** varlist,int paramCount)11418 };
11419 
11420 void mapstrings_gfxproperty(ScriptVariant** varlist, int paramCount)
11421 {
11422 	char *propname = NULL;
11423 	int prop;
11424 
11425 	static const char* proplist[] = {
11426 		"centerx",
11427 		"centery",
11428 		"height",
11429 		"palette",
11430 		"pixel",
11431 		"pixelformat",
11432 		"srcheight",
11433 		"srcwidth",
11434 		"width",
11435 	};
11436 
11437 
11438 	if(paramCount < 2) return;
11439 	MAPSTRINGS(varlist[1], proplist, _gfx_the_end,
11440 		"Property name '%s' is not supported by gfxproperty.\n");
11441 }
11442 
openbor_getgfxproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11443 
11444 // getgfxproperty(handle, propertyname, ...);
11445 HRESULT openbor_getgfxproperty(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11446 {
11447 	s_screen* screen;
11448 	s_sprite* sprite;
11449 	s_bitmap* bitmap;
11450 	LONG value[2] = {0,0}, v;
11451 	void* handle;
11452 	int i, x, y;
11453 
11454 	if(paramCount < 2)
11455 		goto ggp_error;
11456 
11457 	mapstrings_gfxproperty(varlist, paramCount);
11458 
11459 	if(varlist[0]->vt!=VT_PTR) goto ggp_error;
11460 
11461 	handle = varlist[0]->ptrVal;
11462 
11463 	if(!handle)  goto ggp_error;
11464 
11465 	screen = (s_screen*)handle;
11466 	sprite = (s_sprite*)handle;
11467 	bitmap = (s_bitmap*)handle;
11468 
11469 	ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11470 
11471 
11472 	switch(varlist[1]->lVal){
11473 	case _gfx_width:
11474 		switch(screen->magic){
11475 		case screen_magic:
11476 			(*pretvar)->lVal = screen->width;
11477 			break;
11478 		case sprite_magic:
11479 			(*pretvar)->lVal = sprite->width;
11480 			break;
11481 		case bitmap_magic:
11482 			(*pretvar)->lVal = bitmap->width;
11483 			break;
11484 		default:
11485 			goto ggp_error2;
11486 		}
11487 	break;
11488 	case _gfx_height:
11489 		switch(screen->magic){
11490 		case screen_magic:
11491 			(*pretvar)->lVal = screen->height;
11492 			break;
11493 		case sprite_magic:
11494 			(*pretvar)->lVal = sprite->height;
11495 			break;
11496 		case bitmap_magic:
11497 			(*pretvar)->lVal = bitmap->height;
11498 			break;
11499 		default:
11500 			goto ggp_error2;
11501 		}
11502 	break;
11503 	case _gfx_srcwidth:
11504 		switch(screen->magic){
11505 		case screen_magic:
11506 			(*pretvar)->lVal = screen->width;
11507 			break;
11508 		case sprite_magic:
11509 			(*pretvar)->lVal = sprite->srcwidth;
11510 			break;
11511 		case bitmap_magic:
11512 			(*pretvar)->lVal = bitmap->width;
11513 			break;
11514 		default:
11515 			goto ggp_error2;
11516 		}
11517 	break;
11518 	case _gfx_srcheight:
11519 		switch(screen->magic){
11520 		case screen_magic:
11521 			(*pretvar)->lVal = screen->height;
11522 			break;
11523 		case sprite_magic:
11524 			(*pretvar)->lVal = sprite->srcheight;
11525 			break;
11526 		case bitmap_magic:
11527 			(*pretvar)->lVal = bitmap->height;
11528 			break;
11529 		default:
11530 			goto ggp_error2;
11531 		}
11532 	break;
11533 	case _gfx_centerx:
11534 		switch(screen->magic){
11535 		case screen_magic:
11536 		case bitmap_magic:
11537 			(*pretvar)->lVal = 0;
11538 			break;
11539 		case sprite_magic:
11540 			(*pretvar)->lVal = sprite->centerx;
11541 			break;
11542 		default:
11543 			goto ggp_error2;
11544 		}
11545 	break;
11546 	case _gfx_centery:
11547 		switch(screen->magic){
11548 		case screen_magic:
11549 		case bitmap_magic:
11550 			(*pretvar)->lVal = 0;
11551 			break;
11552 		case sprite_magic:
11553 			(*pretvar)->lVal = sprite->centery;
11554 			break;
11555 		default:
11556 			goto ggp_error2;
11557 		}
11558 	break;
11559 	case _gfx_palette:
11560 		ScriptVariant_ChangeType(*pretvar, VT_PTR);
11561 		switch(screen->magic){
11562 		case screen_magic:
11563 			(*pretvar)->ptrVal = (VOID*)screen->palette;
11564 			break;
11565 		case sprite_magic:
11566 			(*pretvar)->ptrVal = (VOID*)sprite->palette;
11567 			break;
11568 		case bitmap_magic:
11569 			(*pretvar)->ptrVal = (VOID*)bitmap->palette;
11570 			break;
11571 		default:
11572 			goto ggp_error2;
11573 		}
11574 	break;
11575 	case _gfx_pixelformat:
11576 		switch(screen->magic){
11577 		case screen_magic:
11578 			(*pretvar)->lVal = screen->pixelformat;
11579 			break;
11580 		case sprite_magic:
11581 			(*pretvar)->lVal = sprite->pixelformat;
11582 			break;
11583 		case bitmap_magic:
11584 			(*pretvar)->lVal = bitmap->pixelformat;
11585 			break;
11586 		default:
11587 			goto ggp_error2;
11588 		}
11589 	break;
11590 	case _gfx_pixel:
11591 		if(paramCount<4) goto ggp_error3;
11592 		for(i=2; i<4; i++){
11593 			if(FAILED(ScriptVariant_IntegerValue(varlist[i], value+i-2)))
11594 				goto ggp_error4;
11595 		}
11596 		x = value[0]; y = value[1];
11597 		switch(screen->magic){
11598 		case bitmap_magic: //As long as the two structures are identical...
11599 		case screen_magic:
11600 			if(x<0 || x>=screen->width || y<0 || y>=screen->height)
11601 				v = 0;
11602 			else
11603 			{
11604 				switch(screen->pixelformat){
11605 				case PIXEL_8:
11606 				case PIXEL_x8:
11607 					v = (LONG)(((unsigned char*)screen->data)[y*screen->width+x]);
11608 					break;
11609 				case PIXEL_16:
11610 					v = (LONG)(((unsigned short*)screen->data)[y*screen->width+x]);
11611 					break;
11612 				case PIXEL_32:
11613 					v = (LONG)(((unsigned*)screen->data)[y*screen->width+x]);
11614 					break;
11615 				default:
11616 					v = 0;
11617 				}
11618 			}
11619 			break;
11620 		case sprite_magic:
11621 			if(x<0 || x>=sprite->width || y<0 || y>=sprite->height)
11622 				v = 0;
11623 			else
11624 				v = (LONG)sprite_get_pixel(sprite,x,y);
11625 			break;
11626 		default: goto ggp_error2;
11627 		}
11628 		(*pretvar)->lVal = v;
11629 	break;
11630 	default:
11631 	break;
11632 
11633 	}
11634 
11635 	return S_OK;
11636 
11637 ggp_error:
11638 	printf("Function getgfxproperty must have a valid handle and a property name.\n");
11639 	*pretvar = NULL;
11640 	return E_FAIL;
11641 ggp_error2:
11642 	printf("Function getgfxproperty encountered an invalid handle.\n");
11643 	*pretvar = NULL;
11644 	return E_FAIL;
11645 ggp_error3:
11646 	printf("You need to specify x, y value for getgfxproperty.\n");
11647 	*pretvar = NULL;
11648 	return E_FAIL;
11649 ggp_error4:
11650 	printf("Invalid x or y value for getgfxproperty.\n");
11651 	*pretvar = NULL;
11652 	return E_FAIL;
11653 }
openbor_allocscript(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11654 
11655 //allocscript(name, comment);
11656 HRESULT openbor_allocscript(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11657 {
11658 	Script* ns;
11659 	char* name = NULL, *comment = NULL;
11660 
11661 	ns = malloc(sizeof(Script));
11662 
11663 	if(ns==NULL) goto as_error;
11664 
11665 	if(paramCount>=1 && varlist[0]->vt==VT_STR) name = (char*)StrCache_Get(varlist[0]->strVal);
11666 	if(paramCount>=2 && varlist[1]->vt==VT_STR) comment = (char*)StrCache_Get(varlist[1]->strVal);
11667 
11668 	Script_Init(ns, name, comment, 1);
11669 
11670 	List_InsertAfter(&scriptheap, (void*)ns, "openbor_allocscript");
11671 
11672 	ScriptVariant_ChangeType(*pretvar, VT_PTR);
11673 	(*pretvar)->ptrVal = (VOID*)ns;
11674 	return S_OK;
11675 
11676 as_error:
11677 	printf("Function allocscript failed to alloc enough memory.\n");
11678 	(*pretvar) = NULL;
11679 	return E_FAIL;
11680 }
openbor_loadscript(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11681 
11682 //loadscript(handle, path);
11683 HRESULT openbor_loadscript(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11684 {
11685 	Script* ns = NULL;
11686 	char* path = NULL;
11687 	int load_script(Script* script, char* file);
11688 
11689 	(*pretvar) = NULL;
11690 
11691 	if(paramCount>=1 && varlist[0]->vt==VT_PTR) ns = (Script*)varlist[0]->ptrVal;
11692 	if(ns==NULL || ns->magic!=script_magic) goto ls_error;
11693 	if(paramCount>=2 && varlist[1]->vt==VT_STR) path = (char*)StrCache_Get(varlist[1]->strVal);
11694 	if(path==NULL) goto ls_error;
11695 
11696 	load_script(ns, path);
11697 	//Script_Init(ns, name, comment, 1);
11698 	//if(!load_script(ns, path)) goto ls_error2;
11699 
11700 	return S_OK;
11701 
11702 ls_error:
11703 	printf("Function loadscript requires a valid script handle and a path.\n");
11704 	return E_FAIL;
11705 }
openbor_compilescript(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11706 
11707 //compilescript(handle);
11708 HRESULT openbor_compilescript(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11709 {
11710 	Script* ns = NULL;
11711 
11712 	(*pretvar) = NULL;
11713 
11714 	if(paramCount>=1 && varlist[0]->vt==VT_PTR) ns = (Script*)varlist[0]->ptrVal;
11715 	if(ns==NULL || ns->magic!=script_magic) goto cs_error;
11716 
11717 	Script_Compile(ns);
11718 
11719 	return S_OK;
11720 
11721 cs_error:
11722 	printf("Function compilescript requires a valid script handle.\n");
11723 	return E_FAIL;
11724 }
openbor_executescript(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11725 
11726 //executescript(handle);
11727 HRESULT openbor_executescript(ScriptVariant** varlist , ScriptVariant** pretvar, int paramCount)
11728 {
11729 	Script* ns = NULL;
11730 
11731 	(*pretvar) = NULL;
11732 
11733 	if(paramCount>=1 && varlist[0]->vt==VT_PTR) ns = (Script*)varlist[0]->ptrVal;
11734 	if(ns==NULL || ns->magic!=script_magic) goto cs_error;
11735 
11736 	Script_Execute(ns);
11737 
11738 	return S_OK;
11739 
11740 cs_error:
11741 	printf("Function executescript requires a valid script handle.\n");
11742 	return E_FAIL;
11743 }
11744