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 _is_not_a_known_subproperty_of_  "'%s' is not a known subproperty of '%s'.\n"
38 #define _is_not_supported_by_ "'%s' is not supported by '%s'.\n"
39 
40 // Define macro for string mapping
41 #define MAPSTRINGS(VAR, LIST, MAXINDEX, FAILMSG, args...) \
42 if(VAR->vt == VT_STR) { \
43 	propname = (char*)StrCache_Get(VAR->strVal); \
44 	prop = searchList(LIST, propname, MAXINDEX); \
45 	if(prop >= 0) { \
46 		ScriptVariant_ChangeType(VAR, VT_INTEGER); \
47 		VAR->lVal = prop; \
48 	} else { printf(FAILMSG, propname, ##args); return 0;} \
49 }
50 
51 extern int			  PLAYER_MIN_Z;
52 extern int			  PLAYER_MAX_Z;
53 extern int			  BGHEIGHT;
54 extern int            MAX_WALL_HEIGHT;
55 extern int			  SAMPLE_GO;
56 extern int			  SAMPLE_BEAT;
57 extern int			  SAMPLE_BLOCK;
58 extern int			  SAMPLE_INDIRECT;
59 extern int			  SAMPLE_GET;
60 extern int			  SAMPLE_GET2;
61 extern int			  SAMPLE_FALL;
62 extern int			  SAMPLE_JUMP;
63 extern int			  SAMPLE_PUNCH;
64 extern int			  SAMPLE_1UP;
65 extern int			  SAMPLE_TIMEOVER;
66 extern int			  SAMPLE_BEEP;
67 extern int			  SAMPLE_BEEP2;
68 extern int			  SAMPLE_BIKE;
69 extern int            current_palette;
70 extern s_player       player[4];
71 extern s_level        *level;
72 extern s_filestream  *filestreams;
73 extern int			  numfilestreams;
74 extern entity         *self;
75 extern int            *animspecials;
76 extern int            *animattacks;
77 extern int            *animfollows;
78 extern int            *animpains;
79 extern int            *animfalls;
80 extern int            *animrises;
81 extern int            *animriseattacks;
82 extern int            *animdies;
83 extern int            *animidles;
84 extern int            *animwalks;
85 extern int            *animbackwalks;
86 extern int            *animups;
87 extern int            *animdowns;
88 extern int            noshare;
89 extern int            credits;
90 extern char           musicname[128];
91 extern float          musicfade[2];
92 extern int            musicloop;
93 extern u32            musicoffset;
94 extern int            models_cached;
95 extern int endgame;
96 extern int useSave;
97 extern int useSet;
98 
99 
100 extern s_sprite_list *sprite_list;
101 extern s_sprite_map *sprite_map;
102 
103 extern unsigned char *blendings[MAX_BLENDINGS];
104 extern int            current_palette;
105 extern s_attack emptyattack;
106 Varlist global_var_list;
107 Script *pcurrentscript = NULL;//used by local script functions
108 List theFunctionList;
109 static List   scriptheap;
110 static s_spawn_entry spawnentry;
111 static s_drawmethod drawmethod;
112 static s_attack attack ;
113 
114 int            max_indexed_vars = 0;
115 int            max_entity_vars = 0;
116 int            max_script_vars = 0;
117 int			   no_nested_script = 0;
118 
clear_named_var_list(List * list,int level)119 static void clear_named_var_list(List *list, int level)
120 {
121     ScriptVariant *var;
122     int i, size;
123     size = List_GetSize(list);
124     for(i = 0, List_Reset(list); i < size; i++)
125     {
126         var = (ScriptVariant *)List_Retrieve(list);
127         ScriptVariant_Clear(var);
128         free(var);
129         List_Remove(list);
130     }
131     if(level)
132     {
133         List_Clear(list);
134     }
135 }
136 
Varlist_Init(Varlist * varlist,int size)137 void Varlist_Init(Varlist *varlist, int size)
138 {
139     int i;
140     varlist->magic = varlist_magic;
141     varlist->list = calloc(1, sizeof(*varlist->list));
142     List_Init(varlist->list);
143     varlist->vars = calloc(size + 1, sizeof(*varlist->vars));
144     for(i = 0; i <= size; i++)
145     {
146         ScriptVariant_Init(varlist->vars + i);
147         ScriptVariant_ChangeType(varlist->vars, VT_INTEGER);
148         varlist->vars->lVal = (LONG)size;
149     }
150 }
151 
Varlist_Clear(Varlist * varlist)152 void Varlist_Clear(Varlist *varlist)
153 {
154     int i;
155     clear_named_var_list(varlist->list, 1);
156     free(varlist->list);
157     varlist->list = NULL;
158     // the first one must be an integer variable, so it's safe to leave it alone
159     for(i = 1; i <= varlist->vars->lVal; i++)
160     {
161         ScriptVariant_Clear(varlist->vars + i);
162     }
163     free(varlist->vars);
164     varlist->vars = NULL;
165     varlist->magic = 0;
166 }
167 
Varlist_Cleanup(Varlist * varlist)168 void Varlist_Cleanup(Varlist *varlist)
169 {
170     int i;
171     clear_named_var_list(varlist->list, 0);
172     for(i = 1; i <= varlist->vars->lVal; i++)
173     {
174         ScriptVariant_Clear(varlist->vars + i);
175     }
176 }
177 
Varlist_GetByName(Varlist * varlist,char * theName)178 ScriptVariant *Varlist_GetByName(Varlist *varlist, char *theName)
179 {
180     if(!theName || !theName[0])
181     {
182         return NULL;
183     }
184 
185     if(List_FindByName(varlist->list, theName))
186     {
187         return (ScriptVariant *)List_Retrieve(varlist->list);
188     }
189 
190     return NULL;
191 }
192 
Varlist_SetByName(Varlist * varlist,char * theName,ScriptVariant * var)193 int Varlist_SetByName(Varlist *varlist, char *theName, ScriptVariant *var)
194 {
195     ScriptVariant *v;
196     if(!theName || !theName[0])
197     {
198         return 0;
199     }
200     if(List_FindByName(varlist->list, theName))
201     {
202         ScriptVariant_Copy((ScriptVariant *)List_Retrieve(varlist->list), var);
203     }
204     else
205     {
206         v = calloc(1, sizeof(*v));
207         ScriptVariant_Copy(v, var);
208         List_InsertAfter(varlist->list, v, theName);
209     }
210     return 1;
211 }
212 
Varlist_GetByIndex(Varlist * varlist,int index)213 ScriptVariant *Varlist_GetByIndex(Varlist *varlist, int index)
214 {
215     if(index < 0 || index >= varlist->vars->lVal)
216     {
217         return NULL;
218     }
219     return varlist->vars + index + 1;
220 }
221 
Varlist_SetByIndex(Varlist * varlist,int index,ScriptVariant * var)222 int Varlist_SetByIndex(Varlist *varlist, int index, ScriptVariant *var)
223 {
224     if(index < 0)
225     {
226         return 0;
227     }
228     else if(index >= varlist->vars->lVal)
229     {
230         __reallocto(varlist->vars, varlist->vars->lVal + 1, index + 2);
231         varlist->vars->lVal = index + 1;
232     }
233     ScriptVariant_Copy(varlist->vars + index + 1, var);
234     return 1;
235 }
236 
237 //this function should be called before all script methods, for once
Script_Global_Init()238 void Script_Global_Init()
239 {
240     memset(&spawnentry, 0, sizeof(spawnentry));//clear up the spawn entry
241     drawmethod = plainmethod;
242 
243     Varlist_Init(&global_var_list, max_indexed_vars);
244 
245     List_Init(&theFunctionList);
246     Script_LoadSystemFunctions();
247     List_Init(&scriptheap);
248     ImportCache_Init();
249 }
250 
_freeheapnode(void * ptr)251 void _freeheapnode(void *ptr)
252 {
253     if(((Script *)ptr)->magic == script_magic)
254     {
255         Script_Clear((Script *)ptr, 2);
256     }
257     else if(((anigif_info *)ptr)->magic == anigif_magic)
258     {
259         anigif_close((anigif_info *)ptr);
260     }
261     else if(((Varlist *)ptr)->magic == varlist_magic)
262     {
263         Varlist_Clear((Varlist *)ptr);
264     }
265     else if(((s_sprite *)ptr)->magic == sprite_magic)
266     {
267         if(((s_sprite *)ptr)->mask)
268         {
269             free(((s_sprite *)ptr)->mask);
270         }
271     }
272     free(ptr);
273 }
274 
275 //this function should only be called when the engine is shutting down
Script_Global_Clear()276 void Script_Global_Clear()
277 {
278     int i, size;
279     List_Clear(&theFunctionList);
280     // dump all un-freed variants
281     size = List_GetSize(&scriptheap);
282     if(size > 0)
283     {
284         printf("\nWarning: %d script variants are not freed, dumping...\n", size);
285     }
286     for(i = 0, List_Reset(&scriptheap); i < size; List_GotoNext(&scriptheap), i++)
287     {
288         printf("%s\n", List_GetName(&scriptheap));
289         _freeheapnode(List_Retrieve(&scriptheap));
290     }
291     List_Clear(&scriptheap);
292     // clear the global list
293     Varlist_Clear(&global_var_list);
294 
295     memset(&spawnentry, 0, sizeof(spawnentry));//clear up the spawn entry
296     for(i = 0; i < numfilestreams; i++)
297     {
298         if(filestreams[i].buf)
299         {
300             free(filestreams[i].buf);
301             filestreams[i].buf = NULL;
302         }
303     }
304     if(filestreams)
305     {
306         free(filestreams);
307     }
308     filestreams = NULL;
309     numfilestreams = 0;
310     ImportCache_Clear();
311     StrCache_Clear();
312 }
313 
Script_Save_Local_Variant(Script * cs,char * namelist[])314 int Script_Save_Local_Variant(Script *cs, char *namelist[])
315 {
316     return 0;
317 }
318 
Script_Load_Local_Variant(Script * cs,int handle)319 void Script_Load_Local_Variant(Script *cs, int handle)
320 {
321 
322 }
323 
alloc_script()324 Script *alloc_script()
325 {
326     Script *pscript = calloc(1, sizeof(*pscript));
327     pscript->magic = script_magic;
328     pscript->varlist = calloc(1, sizeof(*pscript->varlist));
329     Varlist_Init(pscript->varlist, max_script_vars);
330     return pscript;
331 }
332 
Script_Init(Script * pscript,char * theName,char * comment,int first)333 void Script_Init(Script *pscript, char *theName, char *comment, int first)
334 {
335     if(first)
336     {
337         memset(pscript, 0, sizeof(*pscript));
338         pscript->magic = script_magic;
339         pscript->varlist = calloc(1, sizeof(*pscript->varlist));
340         Varlist_Init(pscript->varlist, max_script_vars);
341     }
342     if(!theName || !theName[0])
343     {
344         return;    // if no name specified, only alloc the variants
345     }
346 
347     pscript->pinterpreter = malloc(sizeof(*pscript->pinterpreter));
348     Interpreter_Init(pscript->pinterpreter, theName, &theFunctionList);
349     pscript->interpreterowner = 1; // this is the owner, important
350     pscript->initialized = 1;
351     if(comment)
352     {
353         pscript->comment = malloc(sizeof(*pscript->comment) * (strlen(comment) + 1));
354         strcpy(pscript->comment, comment);
355     }
356 }
357 
execute_init_method(Script * pdest,int iscopy,int localclear)358 static void execute_init_method(Script *pdest, int iscopy, int localclear)
359 {
360     Script *temp;
361     ScriptVariant tempvar;
362     //Execute init method
363     if(pdest->initialized && pdest->pinterpreter->pInitEntry)
364     {
365         temp = pcurrentscript;
366         pcurrentscript = pdest;
367 
368         ScriptVariant_Init(&tempvar);
369         ScriptVariant_ChangeType(&tempvar, VT_INTEGER);
370         tempvar.lVal = (LONG)iscopy;
371         Script_Set_Local_Variant(pdest, "iscopy", &tempvar);
372         tempvar.lVal = (LONG)localclear;
373         Script_Set_Local_Variant(pdest, "localclear", &tempvar);
374         Interpreter_Reset(pdest->pinterpreter);
375         pdest->pinterpreter->pCurrentInstruction = pdest->pinterpreter->pInitEntry;
376         if(FAILED( Interpreter_EvaluateCall(pdest->pinterpreter)))
377         {
378             shutdown(1, "Fatal: failed to execute 'init' in script %s %s", pdest->pinterpreter->theSymbolTable.name, pdest->comment ? pdest->comment : "");
379         }
380         pdest->pinterpreter->bReset = FALSE; // not needed, perhaps
381         ScriptVariant_Clear(&tempvar);
382         Script_Set_Local_Variant(pdest, "iscopy", &tempvar);
383         Script_Set_Local_Variant(pdest, "localclear", &tempvar);
384         pcurrentscript = temp;
385     }
386 }
387 
388 //safe copy method
Script_Copy(Script * pdest,Script * psrc,int localclear)389 void Script_Copy(Script *pdest, Script *psrc, int localclear)
390 {
391     if(!psrc->initialized)
392     {
393         return;
394     }
395     if(pdest->initialized)
396     {
397         Script_Clear(pdest, localclear);
398     }
399     pdest->pinterpreter = psrc->pinterpreter;
400     pdest->comment = psrc->comment;
401     pdest->interpreterowner = 0; // dont own it
402     pdest->initialized = psrc->initialized; //just copy, it should be 1
403     execute_init_method(pdest, 1, localclear);
404 }
405 
Script_Clear(Script * pscript,int localclear)406 void Script_Clear(Script *pscript, int localclear)
407 {
408     Script *temp;
409     Varlist *pvars;
410 
411     ScriptVariant tempvar;
412     //Execute clear method
413     if(pscript->initialized && pscript->pinterpreter->pClearEntry)
414     {
415         temp = pcurrentscript;
416         pcurrentscript = pscript;
417 
418         ScriptVariant_Init(&tempvar);
419         ScriptVariant_ChangeType(&tempvar, VT_INTEGER);
420         tempvar.lVal = (LONG)localclear;
421         Script_Set_Local_Variant(pscript, "localclear", &tempvar);
422         Interpreter_Reset(pscript->pinterpreter);
423         pscript->pinterpreter->pCurrentInstruction = pscript->pinterpreter->pClearEntry;
424         if(FAILED( Interpreter_EvaluateCall(pscript->pinterpreter)))
425         {
426             shutdown(1, "Fatal: failed to execute 'clear' in script %s %s", pscript->pinterpreter->theSymbolTable.name, pscript->comment ? pscript->comment : "");
427         }
428         pscript->pinterpreter->bReset = FALSE; // not needed, perhaps
429         ScriptVariant_Clear(&tempvar);
430         Script_Set_Local_Variant(pscript, "localclear", &tempvar);
431         pcurrentscript = temp;
432     }
433 
434     if(localclear && pscript->varlist)
435     {
436         if(localclear == 2)
437         {
438             Varlist_Clear(pscript->varlist);
439             free(pscript->varlist);
440             pscript->varlist = NULL;
441         }
442         else
443         {
444             Varlist_Cleanup(pscript->varlist);
445         }
446     }
447     if(!pscript->initialized)
448     {
449         return;
450     }
451 
452     //if it is the owner, free the interpreter
453     if(pscript->pinterpreter && pscript->interpreterowner)
454     {
455         Interpreter_Clear(pscript->pinterpreter);
456         free(pscript->pinterpreter);
457         pscript->pinterpreter = NULL;
458         if(pscript->comment)
459         {
460             free(pscript->comment);
461         }
462         pscript->comment = NULL;
463     }
464     pvars = pscript->varlist; // in game clear(localclear!=2) just keep this value
465     memset(pscript, 0, sizeof(*pscript));
466     pscript->varlist = pvars; // copy it back
467 }
468 
469 //append part of the script
470 //Because the script might not be initialized in 1 time.
Script_AppendText(Script * pscript,char * text,char * path)471 int Script_AppendText(Script *pscript, char *text, char *path)
472 {
473     int success;
474 
475     //printf(text);
476     Interpreter_Reset(pscript->pinterpreter);
477 
478     success = SUCCEEDED(Interpreter_ParseText(pscript->pinterpreter, text, 1, path));
479 
480     return success;
481 }
482 
483 //return name of function from pointer to function
Script_GetFunctionName(void * functionRef)484 const char *Script_GetFunctionName(void *functionRef)
485 {
486     if (functionRef == ((void *)system_isempty))
487     {
488         return "isempty";
489     }
490     else if (functionRef == ((void *)system_exit))
491     {
492         return "exit";
493     }
494     else if (functionRef == ((void *)system_NULL))
495     {
496         return "NULL";
497     }
498     else if (functionRef == ((void *)system_rand))
499     {
500         return "rand";
501     }
502     else if (functionRef == ((void *)system_getglobalvar))
503     {
504         return "getglobalvar";
505     }
506     else if (functionRef == ((void *)system_setglobalvar))
507     {
508         return "setglobalvar";
509     }
510     else if (functionRef == ((void *)system_getlocalvar))
511     {
512         return "getlocalvar";
513     }
514     else if (functionRef == ((void *)system_setlocalvar))
515     {
516         return "setlocalvar";
517     }
518     else if (functionRef == ((void *)system_clearglobalvar))
519     {
520         return "clearglobalvar";
521     }
522     else if (functionRef == ((void *)system_clearlocalvar))
523     {
524         return "clearlocalvar";
525     }
526     else if (functionRef == ((void *)system_free))
527     {
528         return "free";
529     }
530     else if (functionRef == ((void *)system_typeof))
531     {
532         return "typeof";
533     }
534     else if (functionRef == ((void *)math_sin))
535     {
536         return "sin";
537     }
538     else if (functionRef == ((void *)math_cos))
539     {
540         return "cos";
541     }
542     else if (functionRef == ((void *)math_sqrt))
543     {
544         return "sqrt";
545     }
546     else if (functionRef == ((void *)openbor_systemvariant))
547     {
548         return "openborvariant";
549     }
550     else if (functionRef == ((void *)openbor_changesystemvariant))
551     {
552         return "changeopenborvariant";
553     }
554     else if (functionRef == ((void *)openbor_drawstring))
555     {
556         return "drawstring";
557     }
558     else if (functionRef == ((void *)openbor_drawstringtoscreen))
559     {
560         return "drawstringtoscreen";
561     }
562     else if (functionRef == ((void *)openbor_log))
563     {
564         return "log";
565     }
566     else if (functionRef == ((void *)openbor_drawbox))
567     {
568         return "drawbox";
569     }
570     else if (functionRef == ((void *)openbor_drawboxtoscreen))
571     {
572         return "drawboxtoscreen";
573     }
574     else if (functionRef == ((void *)openbor_drawline))
575     {
576         return "drawline";
577     }
578     else if (functionRef == ((void *)openbor_drawlinetoscreen))
579     {
580         return "drawlinetoscreen";
581     }
582     else if (functionRef == ((void *)openbor_drawsprite))
583     {
584         return "drawsprite";
585     }
586     else if (functionRef == ((void *)openbor_drawspritetoscreen))
587     {
588         return "drawspritetoscreen";
589     }
590     else if (functionRef == ((void *)openbor_drawdot))
591     {
592         return "drawdot";
593     }
594     else if (functionRef == ((void *)openbor_drawdottoscreen))
595     {
596         return "drawdottoscreen";
597     }
598     else if (functionRef == ((void *)openbor_drawscreen))
599     {
600         return "drawscreen";
601     }
602     else if (functionRef == ((void *)openbor_changeplayerproperty))
603     {
604         return "changeplayerproperty";
605     }
606     else if (functionRef == ((void *)openbor_changeentityproperty))
607     {
608         return "changeentityproperty";
609     }
610     else if (functionRef == ((void *)openbor_getplayerproperty))
611     {
612         return "getplayerproperty";
613     }
614     else if (functionRef == ((void *)openbor_getentityproperty))
615     {
616         return "getentityproperty";
617     }
618     else if (functionRef == ((void *)openbor_tossentity))
619     {
620         return "tossentity";
621     }
622     else if (functionRef == ((void *)openbor_clearspawnentry))
623     {
624         return "clearspawnentry";
625     }
626     else if (functionRef == ((void *)openbor_setspawnentry))
627     {
628         return "setspawnentry";
629     }
630     else if (functionRef == ((void *)openbor_spawn))
631     {
632         return "spawn";
633     }
634     else if (functionRef == ((void *)openbor_projectile))
635     {
636         return "projectile";
637     }
638     else if (functionRef == ((void *)openbor_transconst))
639     {
640         return "openborconstant";
641     }
642     else if (functionRef == ((void *)openbor_playmusic))
643     {
644         return "playmusic";
645     }
646     else if (functionRef == ((void *)openbor_fademusic))
647     {
648         return "fademusic";
649     }
650     else if (functionRef == ((void *)openbor_setmusicvolume))
651     {
652         return "setmusicvolume";
653     }
654     else if (functionRef == ((void *)openbor_setmusictempo))
655     {
656         return "setmusictempo";
657     }
658     else if (functionRef == ((void *)openbor_pausemusic))
659     {
660         return "pausemusic";
661     }
662     else if (functionRef == ((void *)openbor_querychannel))
663     {
664         return "querychannel";
665     }
666     else if (functionRef == ((void *)openbor_stopchannel))
667     {
668         return "stopchannel";
669     }
670     else if (functionRef == ((void *)openbor_playsample))
671     {
672         return "playsample";
673     }
674     else if (functionRef == ((void *)openbor_loadsample))
675     {
676         return "loadsample";
677     }
678     else if (functionRef == ((void *)openbor_unloadsample))
679     {
680         return "unloadsample";
681     }
682     else if (functionRef == ((void *)openbor_fadeout))
683     {
684         return "fadeout";
685     }
686     else if (functionRef == ((void *)openbor_playerkeys))
687     {
688         return "playerkeys";
689     }
690     else if (functionRef == ((void *)openbor_changepalette))
691     {
692         return "changepalette";
693     }
694     else if (functionRef == ((void *)openbor_changeattackproperty))
695     {
696         return "changeattackproperty";
697     }
698     else if (functionRef == ((void *)openbor_damageentity))
699     {
700         return "damageentity";
701     }
702     else if (functionRef == ((void *)openbor_killentity))
703     {
704         return "killentity";
705     }
706     else if (functionRef == ((void *)openbor_findtarget))
707     {
708         return "findtarget";
709     }
710     else if (functionRef == ((void *)openbor_checkrange))
711     {
712         return "checkrange";
713     }
714     else if (functionRef == ((void *)openbor_gettextobjproperty))
715     {
716         return "gettextobjproperty";
717     }
718     else if (functionRef == ((void *)openbor_changetextobjproperty))
719     {
720         return "changetextobjproperty";
721     }
722     else if (functionRef == ((void *)openbor_settextobj))
723     {
724         return "settextobj";
725     }
726     else if (functionRef == ((void *)openbor_cleartextobj))
727     {
728         return "cleartextobj";
729     }
730     else if (functionRef == ((void *)openbor_getlayerproperty))
731     {
732         return "getlayerproperty";
733     }
734     else if (functionRef == ((void *)openbor_changelayerproperty))
735     {
736         return "changelayerproperty";
737     }
738     else if (functionRef == ((void *)openbor_getlevelproperty))
739     {
740         return "getlevelproperty";
741     }
742     else if (functionRef == ((void *)openbor_changelevelproperty))
743     {
744         return "changelevelproperty";
745     }
746     else if (functionRef == ((void *)openbor_checkhole))
747     {
748         return "checkhole";
749     }
750     else if (functionRef == ((void *)openbor_checkwall))
751     {
752         return "checkwall";
753     }
754     else if (functionRef == ((void *)openbor_checkplatformbelow))
755     {
756         return "checkplatformbelow";
757     }
758     else if (functionRef == ((void *)openbor_openfilestream))
759     {
760         return "openfilestream";
761     }
762     else if (functionRef == ((void *)openbor_getfilestreamline))
763     {
764         return "getfilestreamline";
765     }
766     else if (functionRef == ((void *)openbor_getfilestreamargument))
767     {
768         return "getfilestreamargument";
769     }
770     else if (functionRef == ((void *)openbor_filestreamnextline))
771     {
772         return "filestreamnextline";
773     }
774     else if (functionRef == ((void *)openbor_getfilestreamposition))
775     {
776         return "getfilestreamposition";
777     }
778     else if (functionRef == ((void *)openbor_setfilestreamposition))
779     {
780         return "setfilestreamposition";
781     }
782     else if (functionRef == ((void *)openbor_filestreamappend))
783     {
784         return "filestreamappend";
785     }
786     else if (functionRef == ((void *)openbor_createfilestream))
787     {
788         return "createfilestream";
789     }
790     else if (functionRef == ((void *)openbor_closefilestream))
791     {
792         return "closefilestream";
793     }
794     else if (functionRef == ((void *)openbor_savefilestream))
795     {
796         return "savefilestream";
797     }
798     else if (functionRef == ((void *)openbor_getindexedvar))
799     {
800         return "getindexedvar";
801     }
802     else if (functionRef == ((void *)openbor_setindexedvar))
803     {
804         return "setindexedvar";
805     }
806     else if (functionRef == ((void *)openbor_getscriptvar))
807     {
808         return "getscriptvar";
809     }
810     else if (functionRef == ((void *)openbor_setscriptvar))
811     {
812         return "setscriptvar";
813     }
814     else if (functionRef == ((void *)openbor_getentityvar))
815     {
816         return "getentityvar";
817     }
818     else if (functionRef == ((void *)openbor_setentityvar))
819     {
820         return "setentityvar";
821     }
822     else if (functionRef == ((void *)openbor_shutdown))
823     {
824         return "shutdown";
825     }
826     else if (functionRef == ((void *)openbor_jumptobranch))
827     {
828         return "jumptobranch";
829     }
830     else if (functionRef == ((void *)openbor_changelight))
831     {
832         return "changelight";
833     }
834     else if (functionRef == ((void *)openbor_changeshadowcolor))
835     {
836         return "changeshadowcolor";
837     }
838     else if (functionRef == ((void *)openbor_bindentity))
839     {
840         return "bindentity";
841     }
842     else if (functionRef == ((void *)openbor_array))
843     {
844         return "array";
845     }
846     else if (functionRef == ((void *)openbor_size))
847     {
848         return "size";
849     }
850     else if (functionRef == ((void *)openbor_get))
851     {
852         return "get";
853     }
854     else if (functionRef == ((void *)openbor_set))
855     {
856         return "set";
857     }
858     else if (functionRef == ((void *)openbor_reset))
859     {
860         return "reset";
861     }
862     else if (functionRef == ((void *)openbor_next))
863     {
864         return "next";
865     }
866     else if (functionRef == ((void *)openbor_key))
867     {
868         return "key";
869     }
870     else if (functionRef == ((void *)openbor_value))
871     {
872         return "value";
873     }
874     else if (functionRef == ((void *)openbor_allocscreen))
875     {
876         return "allocscreen";
877     }
878     else if (functionRef == ((void *)openbor_clearscreen))
879     {
880         return "clearscreen";
881     }
882     else if (functionRef == ((void *)openbor_setdrawmethod))
883     {
884         return "setdrawmethod";
885     }
886     else if (functionRef == ((void *)openbor_changedrawmethod))
887     {
888         return "changedrawmethod";
889     }
890     else if (functionRef == ((void *)openbor_updateframe))
891     {
892         return "updateframe";
893     }
894     else if (functionRef == ((void *)openbor_performattack))
895     {
896         return "performattack";
897     }
898     else if (functionRef == ((void *)openbor_setidle))
899     {
900         return "setidle";
901     }
902     else if (functionRef == ((void *)openbor_getentity))
903     {
904         return "getentity";
905     }
906     else if (functionRef == ((void *)openbor_loadmodel))
907     {
908         return "loadmodel";
909     }
910     else if (functionRef == ((void *)openbor_loadsprite))
911     {
912         return "loadsprite";
913     }
914     else if (functionRef == ((void *)openbor_options))
915     {
916         return "options";
917     }
918     else if (functionRef == ((void *)openbor_playgif))
919     {
920         return "playgif";
921     }
922     else if (functionRef == ((void *)openbor_openanigif))
923     {
924         return "openanigif";
925     }
926     else if (functionRef == ((void *)openbor_decodeanigif))
927     {
928         return "decodeanigif";
929     }
930     else if (functionRef == ((void *)openbor_getanigifinfo))
931     {
932         return "getanigifinfo";
933     }
934     else if (functionRef == ((void *)openbor_strinfirst))
935     {
936         return "strinfirst";
937     }
938     else if (functionRef == ((void *)openbor_strinlast))
939     {
940         return "strinlast";
941     }
942     else if (functionRef == ((void *)openbor_strleft))
943     {
944         return "strleft";
945     }
946     else if (functionRef == ((void *)openbor_strlength))
947     {
948         return "strlength";
949     }
950     else if (functionRef == ((void *)openbor_strwidth))
951     {
952         return "strwidth";
953     }
954     else if (functionRef == ((void *)openbor_strright))
955     {
956         return "strright";
957     }
958     else if (functionRef == ((void *)openbor_getmodelproperty))
959     {
960         return "getmodelproperty";
961     }
962     else if (functionRef == ((void *)openbor_changemodelproperty))
963     {
964         return "changemodelproperty";
965     }
966     else if (functionRef == ((void *)openbor_rgbcolor))
967     {
968         return "rgbcolor";
969     }
970     else if (functionRef == ((void *)openbor_adjustwalkanimation))
971     {
972         return "adjustwalkanimation";
973     }
974     else if (functionRef == ((void *)openbor_finditem))
975     {
976         return "finditem";
977     }
978     else if (functionRef == ((void *)openbor_pickup))
979     {
980         return "pickup";
981     }
982     else if (functionRef == ((void *)openbor_waypoints))
983     {
984         return "waypoints";
985     }
986     else if (functionRef == ((void *)openbor_drawspriteq))
987     {
988         return "drawspriteq";
989     }
990     else if (functionRef == ((void *)openbor_clearspriteq))
991     {
992         return "clearspriteq";
993     }
994     else if (functionRef == ((void *)openbor_getgfxproperty))
995     {
996         return "getgfxproperty";
997     }
998     else if (functionRef == ((void *)openbor_allocscript))
999     {
1000         return "allocscript";
1001     }
1002     else if (functionRef == ((void *)openbor_loadscript))
1003     {
1004         return "loadscript";
1005     }
1006     else if (functionRef == ((void *)openbor_compilescript))
1007     {
1008         return "compilescript";
1009     }
1010     else if (functionRef == ((void *)openbor_executescript))
1011     {
1012         return "executescript";
1013     }
1014     else if (functionRef == ((void *)openbor_loadgamefile))
1015     {
1016         return "loadgamefile";
1017     }
1018     else if (functionRef == ((void *)openbor_playgame))
1019     {
1020         return "playgame";
1021     }
1022     else if (functionRef == ((void *)openbor_getsaveinfo))
1023     {
1024         return "getsaveinfo";
1025     }
1026     else
1027     {
1028         return "<unknown function>";
1029     }
1030 }
1031 
1032 //return string mapping function corresponding to a given function
Script_GetStringMapFunction(void * functionRef)1033 void *Script_GetStringMapFunction(void *functionRef)
1034 {
1035     if (functionRef == ((void *)openbor_systemvariant))
1036     {
1037         return (void *)mapstrings_systemvariant;
1038     }
1039     else if (functionRef == ((void *)openbor_changesystemvariant))
1040     {
1041         return (void *)mapstrings_systemvariant;
1042     }
1043     else if (functionRef == ((void *)openbor_getentityproperty))
1044     {
1045         return (void *)mapstrings_entityproperty;
1046     }
1047     else if (functionRef == ((void *)openbor_changeentityproperty))
1048     {
1049         return (void *)mapstrings_entityproperty;
1050     }
1051     else if (functionRef == ((void *)openbor_getplayerproperty))
1052     {
1053         return (void *)mapstrings_playerproperty;
1054     }
1055     else if (functionRef == ((void *)openbor_changeplayerproperty))
1056     {
1057         return (void *)mapstrings_playerproperty;
1058     }
1059     else if (functionRef == ((void *)openbor_changeattackproperty))
1060     {
1061         return (void *)mapstrings_attackproperty;
1062     }
1063     else if (functionRef == ((void *)openbor_setspawnentry))
1064     {
1065         return (void *)mapstrings_setspawnentry;
1066     }
1067     else if (functionRef == ((void *)openbor_transconst))
1068     {
1069         return (void *)mapstrings_transconst;
1070     }
1071     else if (functionRef == ((void *)openbor_playerkeys))
1072     {
1073         return (void *)mapstrings_playerkeys;
1074     }
1075     else if (functionRef == ((void *)openbor_gettextobjproperty))
1076     {
1077         return (void *)mapstrings_textobjproperty;
1078     }
1079     else if (functionRef == ((void *)openbor_changetextobjproperty))
1080     {
1081         return (void *)mapstrings_textobjproperty;
1082     }
1083     else if (functionRef == ((void *)openbor_getlayerproperty))
1084     {
1085         return (void *)mapstrings_layerproperty;
1086     }
1087     else if (functionRef == ((void *)openbor_changelayerproperty))
1088     {
1089         return (void *)mapstrings_layerproperty;
1090     }
1091     else if (functionRef == ((void *)openbor_changedrawmethod))
1092     {
1093         return (void *)mapstrings_drawmethodproperty;
1094     }
1095     else if (functionRef == ((void *)openbor_getgfxproperty))
1096     {
1097         return (void *)mapstrings_gfxproperty;
1098     }
1099     else if (functionRef == ((void *)openbor_getlevelproperty))
1100     {
1101         return (void *)mapstrings_levelproperty;
1102     }
1103     else if (functionRef == ((void *)openbor_changelevelproperty))
1104     {
1105         return (void *)mapstrings_levelproperty;
1106     }
1107     else
1108     {
1109         return NULL;
1110     }
1111 }
1112 
1113 #if 0
1114 const ScriptVariant *Script_Find_Constant(Script *pscript, const ScriptVariant *value)
1115 {
1116     int i, size;
1117     Interpreter *pinterpreter = pscript->pinterpreter;
1118     Instruction *pInstruction;
1119 
1120     size = List_GetSize(&(pinterpreter->theInstructionList));
1121     for(i = 0; i < size; i++)
1122     {
1123         pInstruction = (Instruction *)(pinterpreter->theInstructionList.solidlist[i]);
1124         if(pInstruction->theVal2 == value)
1125         {
1126             return pInstruction->theVal;
1127         }
1128     }
1129     return NULL;
1130 }
1131 #endif
1132 
1133 /* Replace string constants with enum constants at compile time to speed up
1134    script execution. */
Script_MapStringConstants(Instruction * pInstruction)1135 int Script_MapStringConstants(Instruction *pInstruction)
1136 {
1137     ScriptVariant **params;
1138     int paramCount;
1139     int (*pMapstrings)(ScriptVariant **, int);
1140 
1141     if(pInstruction->functionRef)
1142     {
1143         params = (ScriptVariant **)pInstruction->theRefList->solidlist;
1144         paramCount = (int)pInstruction->theRef->lVal;
1145         assert(paramCount <= 32);
1146         // Get the pointer to the correct mapstrings function, if one exists.
1147         pMapstrings = Script_GetStringMapFunction(pInstruction->functionRef);
1148         if(pMapstrings)
1149         {
1150             // Call the mapstrings function.
1151             if(!pMapstrings(params, paramCount))
1152             {
1153                 return 0;
1154             }
1155         }
1156     }
1157 
1158     return 1;
1159 }
1160 
1161 // replaces the entire instruction list with a new instruction list after optimization
Script_ReplaceInstructionList(Interpreter * pInterpreter,List * newList)1162 int Script_ReplaceInstructionList(Interpreter *pInterpreter, List *newList)
1163 {
1164     int i, j, newSize = List_GetSize(newList);
1165     Instruction *pInstruction, *pTarget;
1166     Instruction **oldList = (Instruction **)pInterpreter->theInstructionList.solidlist;
1167     List_Solidify(newList);
1168 
1169     char buf[256];
1170 
1171     for(i = 0; i < newSize; i++)
1172     {
1173         pInstruction = (Instruction *)newList->solidlist[i];
1174         if(pInstruction->theJumpTargetIndex >= 0)
1175         {
1176             pTarget = (Instruction *)oldList[pInstruction->theJumpTargetIndex];
1177             for(j = 0; j < newSize; j++)
1178             {
1179                 if(newList->solidlist[j] == pTarget)
1180                 {
1181                     pInstruction->theJumpTargetIndex = j;
1182                     break;
1183                 }
1184             }
1185             // if the jump target isn't found, it must have been removed in an optimization - whoops!
1186             if(j == newSize)
1187             {
1188                 Instruction_ToString(pTarget, buf);
1189                 printf("Error: jump target %i (%s) not found - overzealous optimization!\n", pInstruction->theJumpTargetIndex, buf);
1190                 return 0;
1191             }
1192         }
1193     }
1194 
1195     // replace new list with old list
1196     List_Clear(&(pInterpreter->theInstructionList));
1197     memcpy(&(pInterpreter->theInstructionList), newList, sizeof(*newList));
1198 
1199     return 1;
1200 }
1201 
1202 // prints lots of debugging stuff about optimizations that can be made
Script_LowerConstants(Script * pscript)1203 void Script_LowerConstants(Script *pscript)
1204 {
1205     Interpreter *pinterpreter = pscript->pinterpreter;
1206     Instruction *pInstruction, *pInstruction2;
1207     List *newInstructionList = malloc(sizeof(*newInstructionList));
1208     int i, j, size;
1209 
1210     List_Init(newInstructionList);
1211 
1212     size = List_GetSize(&(pinterpreter->theInstructionList));
1213 
1214     for(i = 0; i < size; i++)
1215     {
1216         pInstruction = (Instruction *)(pinterpreter->theInstructionList.solidlist[i]);
1217         if(pInstruction->OpCode == DATA)
1218         {
1219             int numRefs = 0;
1220             for(j = 0; j < size; j++)
1221             {
1222                 pInstruction2 = (Instruction *)(pinterpreter->theInstructionList.solidlist[j]);
1223                 if(pInstruction2->OpCode == LOAD && pInstruction2->theRef == pInstruction->theVal)
1224                 {
1225                     numRefs++;
1226                 }
1227             }
1228             //printf("Variable declared, %i references\n", numRefs, pInstruction->theToken->theSource);
1229             //printf("DATA (theVal=0x%08X, theRef=0x%08X)\n", pInstruction->theVal, pInstruction->theRef);
1230             if(numRefs > 0)
1231             {
1232                 List_InsertAfter(newInstructionList, pInstruction, NULL);
1233             }
1234             else
1235             {
1236                 printf("Unused variable\n");
1237                 free(pInstruction);
1238             }
1239         }
1240         else
1241         {
1242             List_InsertAfter(newInstructionList, pInstruction, NULL);
1243         }
1244 #define ISCONST(x) ((x) && ((x->OpCode==CONSTINT)||(x->OpCode==CONSTSTR)||(x->OpCode==CONSTDBL)))
1245         // Look for constant binary ops
1246         if(pInstruction->OpCode == ADD)
1247         {
1248             Instruction *pSrc1 = NULL, *pSrc2 = NULL;
1249             char buf[1024], buf2[1024], buf3[1024];
1250             for(j = 0; j < size; j++)
1251             {
1252                 Instruction *tmp = (Instruction *)(pinterpreter->theInstructionList.solidlist[j]);
1253                 if(tmp->theVal == pInstruction->theRef || tmp->theVal2 == pInstruction->theRef)
1254                 {
1255                     pSrc1 = tmp;
1256                 }
1257                 if(tmp->theVal == pInstruction->theRef2 || tmp->theVal2 == pInstruction->theRef2)
1258                 {
1259                     pSrc2 = tmp;
1260                 }
1261             }
1262 
1263             if(ISCONST(pSrc1) && ISCONST(pSrc2))
1264             {
1265                 ScriptVariant *sum = ScriptVariant_Add(pSrc1->theVal2, pSrc2->theVal2);
1266                 ScriptVariant_ToString(pSrc1->theVal2, buf);
1267                 ScriptVariant_ToString(pSrc2->theVal2, buf2);
1268                 ScriptVariant_ToString(sum, buf3);
1269                 //printf("ADD 0x%08X: %s + %s = %s\n", pInstruction, buf, buf2, buf3);
1270             }
1271 #if 0
1272             else if(pSrc1 && pSrc2)
1273             {
1274                 Instruction_ToString(pSrc1, buf);
1275                 Instruction_ToString(pSrc2, buf2);
1276                 printf("ADD 0x%08X: %s + %s\n", pInstruction, buf, buf2);
1277             }
1278             else
1279             {
1280                 printf("ADD 0x%08X: Non-constant addition?\n");
1281             }
1282 #endif
1283         }
1284 #undef ISCONST
1285     }
1286 
1287     // replace old instruction list with optimized one (TODO: enable when this function actually does optimizations)
1288     //Script_ReplaceInstructionList(pinterpreter, &newInstructionList);
1289 }
1290 
1291 // detect unused functions in scripts (to save memory)
Script_DetectUnusedFunctions(Script * pScript)1292 int Script_DetectUnusedFunctions(Script *pScript)
1293 {
1294     Interpreter *pInterpreter = pScript->pinterpreter;
1295     Instruction *pInstruction, *pInstruction2, **instructionList = (Instruction **)pInterpreter->theInstructionList.solidlist;
1296     List newInstructionList;
1297     int i, size = List_GetSize(&(pInterpreter->theInstructionList));
1298 
1299     List_Init(&newInstructionList);
1300 
1301     for(i = 0; i < size; i++)
1302     {
1303         pInstruction = instructionList[i];
1304         // detect function declarations (FIXME: should have an opcode for function declarations other than NOOP)
1305         if(pInstruction->OpCode == NOOP && pInstruction->theToken && strlen(pInstruction->theToken->theSource) > 0)
1306         {
1307             int j, numCalls = 0;
1308 
1309             // find all calls to this function
1310             for(j = 0; j < size; j++)
1311             {
1312                 pInstruction2 = instructionList[j];
1313                 if(pInstruction2->OpCode == CALL && pInstruction2->theJumpTargetIndex == i)
1314                 {
1315                     numCalls++;
1316                 }
1317             }
1318 
1319             if(numCalls == 0 && strcmp(pInstruction->theToken->theSource, "main") != 0)
1320             {
1321                 printf("Unused function %s()\n", pInstruction->theToken->theSource);
1322                 while(instructionList[i]->OpCode != RET) // skip function without adding to new instruction list
1323                 {
1324                     free(instructionList[i++]);
1325                     if(i >= size)
1326                     {
1327                         List_Clear(&newInstructionList);    // this shouldn't happen!
1328                         return 0;
1329                     }
1330                 }
1331                 free(instructionList[i]); // free the final RET instruction too
1332             }
1333             else
1334             {
1335                 List_InsertAfter(&newInstructionList, pInstruction, NULL);
1336             }
1337         }
1338         else
1339         {
1340             List_InsertAfter(&newInstructionList, pInstruction, NULL);
1341         }
1342 
1343         List_InsertAfter(&newInstructionList, pInstruction, NULL);
1344 
1345         //if(pInstruction->theToken) {free(pInstruction->theToken); pInstruction->theToken=NULL;} // TODO: move somewhere else
1346     }
1347 
1348     return Script_ReplaceInstructionList(pInterpreter, &newInstructionList);
1349 }
1350 
1351 //should be called only once after parsing text
Script_Compile(Script * pscript)1352 int Script_Compile(Script *pscript)
1353 {
1354     int result;
1355     if(!pscript || !pscript->pinterpreter)
1356     {
1357         return 1;
1358     }
1359     //Interpreter_OutputPCode(pscript->pinterpreter, "code");
1360     result = SUCCEEDED(Interpreter_CompileInstructions(pscript->pinterpreter));
1361     if(!result)
1362     {
1363         shutdown(1, "Can't compile script '%s' %s\n", pscript->pinterpreter->theSymbolTable.name, pscript->comment ? pscript->comment : "");
1364     }
1365 
1366     pscript->pinterpreter->bReset = FALSE;
1367     //result = Script_DetectUnusedFunctions(pscript);
1368     //if(!result) {Script_Clear(pscript, 1);shutdown(1, "Script optimization failed!\n");}
1369     //Script_LowerConstants(pscript);
1370     execute_init_method(pscript, 0, 1);
1371     return result;
1372 }
1373 
Script_IsInitialized(Script * pscript)1374 int Script_IsInitialized(Script *pscript)
1375 {
1376     //if(pscript && pscript->initialized) pcurrentscript = pscript; //used by local script functions
1377     return pscript->initialized;
1378 }
1379 
1380 //execute the script
Script_Execute(Script * pscript)1381 int Script_Execute(Script *pscript)
1382 {
1383     int result, nested;
1384     extern int no_cmd_compatible;
1385     Script *temp = pcurrentscript;
1386     Interpreter tinter, *pinter;
1387     pcurrentscript = pscript; //used by local script functions
1388     nested = pscript->pinterpreter->bReset;
1389     if(no_nested_script && nested)
1390     {
1391         result = 1;
1392     }
1393     else
1394     {
1395         pinter = pscript->pinterpreter;
1396         if(nested && no_cmd_compatible)
1397         {
1398             tinter = *pinter;
1399         }
1400         Interpreter_Reset(pinter);
1401         result = (int)SUCCEEDED(Interpreter_EvaluateImmediate(pinter));
1402         if(nested && no_cmd_compatible)
1403         {
1404             *pinter = tinter;
1405         }
1406         else if(nested)
1407         {
1408             pinter->bReset = FALSE;
1409         }
1410     }
1411     pcurrentscript = temp;
1412     if(!result)
1413     {
1414         shutdown(1, "There's an exception while executing script '%s' %s", pscript->pinterpreter->theSymbolTable.name, pscript->comment ? pscript->comment : "");
1415     }
1416     return result;
1417 }
1418 
1419 #ifndef COMPILED_SCRIPT
1420 //this method is for debug purpose
Script_Call(Script * pscript,char * method,ScriptVariant * pretvar)1421 int Script_Call(Script *pscript, char *method, ScriptVariant *pretvar)
1422 {
1423     int result;
1424     Script *temp = pcurrentscript;
1425     pcurrentscript = pscript; //used by local script functions
1426     Interpreter_Reset(pscript->pinterpreter);
1427     result = (int)SUCCEEDED(Interpreter_Call(pscript->pinterpreter, method, pretvar));
1428     pcurrentscript = temp;
1429     return result;
1430 }
1431 #endif
1432 
1433 //used by Script_Global_Init
Script_LoadSystemFunctions()1434 void Script_LoadSystemFunctions()
1435 {
1436     //printf("Loading system script functions....");
1437     //load system functions if we need
1438     List_Reset(&theFunctionList);
1439 
1440     List_InsertAfter(&theFunctionList,
1441                      (void *)system_isempty, "isempty");
1442     List_InsertAfter(&theFunctionList,
1443                      (void *)system_exit, "exit");
1444     List_InsertAfter(&theFunctionList,
1445                      (void *)system_NULL, "NULL");
1446     List_InsertAfter(&theFunctionList,
1447                      (void *)system_rand, "rand");
1448     List_InsertAfter(&theFunctionList,
1449                      (void *)system_getglobalvar, "getglobalvar");
1450     List_InsertAfter(&theFunctionList,
1451                      (void *)system_setglobalvar, "setglobalvar");
1452     List_InsertAfter(&theFunctionList,
1453                      (void *)system_getlocalvar, "getlocalvar");
1454     List_InsertAfter(&theFunctionList,
1455                      (void *)system_setlocalvar, "setlocalvar");
1456     List_InsertAfter(&theFunctionList,
1457                      (void *)system_clearglobalvar, "clearglobalvar");
1458     List_InsertAfter(&theFunctionList,
1459                      (void *)system_clearlocalvar, "clearlocalvar");
1460     List_InsertAfter(&theFunctionList,
1461                      (void *)system_free, "free");
1462     List_InsertAfter(&theFunctionList,
1463                      (void *)system_typeof, "typeof");
1464     List_InsertAfter(&theFunctionList,
1465                      (void *)math_sin, "sin");
1466     List_InsertAfter(&theFunctionList,
1467                      (void *)math_cos, "cos");
1468     List_InsertAfter(&theFunctionList,
1469                      (void *)math_sqrt, "sqrt");
1470     List_InsertAfter(&theFunctionList,
1471                      (void *)openbor_systemvariant, "openborvariant");
1472     List_InsertAfter(&theFunctionList,
1473                      (void *)openbor_changesystemvariant, "changeopenborvariant");
1474     List_InsertAfter(&theFunctionList,
1475                      (void *)openbor_drawstring, "drawstring");
1476     List_InsertAfter(&theFunctionList,
1477                      (void *)openbor_drawstringtoscreen, "drawstringtoscreen");
1478     List_InsertAfter(&theFunctionList,
1479                      (void *)openbor_log, "log");
1480     List_InsertAfter(&theFunctionList,
1481                      (void *)openbor_drawbox, "drawbox");
1482     List_InsertAfter(&theFunctionList,
1483                      (void *)openbor_drawboxtoscreen, "drawboxtoscreen");
1484     List_InsertAfter(&theFunctionList,
1485                      (void *)openbor_drawline, "drawline");
1486     List_InsertAfter(&theFunctionList,
1487                      (void *)openbor_drawlinetoscreen, "drawlinetoscreen");
1488     List_InsertAfter(&theFunctionList,
1489                      (void *)openbor_drawsprite, "drawsprite");
1490     List_InsertAfter(&theFunctionList,
1491                      (void *)openbor_drawspritetoscreen, "drawspritetoscreen");
1492     List_InsertAfter(&theFunctionList,
1493                      (void *)openbor_drawdot, "drawdot");
1494     List_InsertAfter(&theFunctionList,
1495                      (void *)openbor_drawdottoscreen, "drawdottoscreen");
1496     List_InsertAfter(&theFunctionList,
1497                      (void *)openbor_drawscreen, "drawscreen");
1498     List_InsertAfter(&theFunctionList,
1499                      (void *)openbor_changeplayerproperty, "changeplayerproperty");
1500     List_InsertAfter(&theFunctionList,
1501                      (void *)openbor_changeentityproperty, "changeentityproperty");
1502     List_InsertAfter(&theFunctionList,
1503                      (void *)openbor_getplayerproperty, "getplayerproperty");
1504     List_InsertAfter(&theFunctionList,
1505                      (void *)openbor_getentityproperty, "getentityproperty");
1506     List_InsertAfter(&theFunctionList,
1507                      (void *)openbor_tossentity, "tossentity");
1508     List_InsertAfter(&theFunctionList,
1509                      (void *)openbor_clearspawnentry, "clearspawnentry");
1510     List_InsertAfter(&theFunctionList,
1511                      (void *)openbor_setspawnentry, "setspawnentry");
1512     List_InsertAfter(&theFunctionList,
1513                      (void *)openbor_spawn, "spawn");
1514     List_InsertAfter(&theFunctionList,
1515                      (void *)openbor_projectile, "projectile");
1516     List_InsertAfter(&theFunctionList,
1517                      (void *)openbor_transconst, "openborconstant");
1518     List_InsertAfter(&theFunctionList,
1519                      (void *)openbor_playmusic, "playmusic");
1520     List_InsertAfter(&theFunctionList,
1521                      (void *)openbor_fademusic, "fademusic");
1522     List_InsertAfter(&theFunctionList,
1523                      (void *)openbor_setmusicvolume, "setmusicvolume");
1524     List_InsertAfter(&theFunctionList,
1525                      (void *)openbor_setmusictempo, "setmusictempo");
1526     List_InsertAfter(&theFunctionList,
1527                      (void *)openbor_pausemusic, "pausemusic");
1528     List_InsertAfter(&theFunctionList,
1529                      (void *)openbor_querychannel, "querychannel");
1530     List_InsertAfter(&theFunctionList,
1531                      (void *)openbor_stopchannel, "stopchannel");
1532     List_InsertAfter(&theFunctionList,
1533                      (void *)openbor_playsample, "playsample");
1534     List_InsertAfter(&theFunctionList,
1535                      (void *)openbor_loadsample, "loadsample");
1536     List_InsertAfter(&theFunctionList,
1537                      (void *)openbor_unloadsample, "unloadsample");
1538     List_InsertAfter(&theFunctionList,
1539                      (void *)openbor_fadeout, "fadeout");
1540     List_InsertAfter(&theFunctionList,
1541                      (void *)openbor_playerkeys, "playerkeys");
1542     List_InsertAfter(&theFunctionList,
1543                      (void *)openbor_changepalette, "changepalette");
1544     List_InsertAfter(&theFunctionList,
1545                      (void *)openbor_changeattackproperty, "changeattackproperty");
1546     List_InsertAfter(&theFunctionList,
1547                      (void *)openbor_damageentity, "damageentity");
1548     List_InsertAfter(&theFunctionList,
1549                      (void *)openbor_killentity, "killentity");
1550     List_InsertAfter(&theFunctionList,
1551                      (void *)openbor_findtarget, "findtarget");
1552     List_InsertAfter(&theFunctionList,
1553                      (void *)openbor_checkrange, "checkrange");
1554     List_InsertAfter(&theFunctionList,
1555                      (void *)openbor_gettextobjproperty, "gettextobjproperty");
1556     List_InsertAfter(&theFunctionList,
1557                      (void *)openbor_changetextobjproperty, "changetextobjproperty");
1558     List_InsertAfter(&theFunctionList,
1559                      (void *)openbor_settextobj, "settextobj");
1560     List_InsertAfter(&theFunctionList,
1561                      (void *)openbor_cleartextobj, "cleartextobj");
1562     List_InsertAfter(&theFunctionList,
1563                      (void *)openbor_getlayerproperty, "getlayerproperty");
1564     List_InsertAfter(&theFunctionList,
1565                      (void *)openbor_changelayerproperty, "changelayerproperty");
1566     List_InsertAfter(&theFunctionList,
1567                      (void *)openbor_getlevelproperty, "getlevelproperty");
1568     List_InsertAfter(&theFunctionList,
1569                      (void *)openbor_changelevelproperty, "changelevelproperty");
1570     List_InsertAfter(&theFunctionList,
1571                      (void *)openbor_checkhole, "checkhole");
1572     List_InsertAfter(&theFunctionList,
1573                      (void *)openbor_checkwall, "checkwall");
1574     List_InsertAfter(&theFunctionList,
1575                      (void *)openbor_checkplatformbelow, "checkplatformbelow");
1576     List_InsertAfter(&theFunctionList,
1577                      (void *)openbor_openfilestream, "openfilestream");
1578     List_InsertAfter(&theFunctionList,
1579                      (void *)openbor_getfilestreamline, "getfilestreamline");
1580     List_InsertAfter(&theFunctionList,
1581                      (void *)openbor_getfilestreamargument, "getfilestreamargument");
1582     List_InsertAfter(&theFunctionList,
1583                      (void *)openbor_filestreamnextline, "filestreamnextline");
1584     List_InsertAfter(&theFunctionList,
1585                      (void *)openbor_getfilestreamposition, "getfilestreamposition");
1586     List_InsertAfter(&theFunctionList,
1587                      (void *)openbor_setfilestreamposition, "setfilestreamposition");
1588     List_InsertAfter(&theFunctionList,
1589                      (void *)openbor_filestreamappend, "filestreamappend");
1590     List_InsertAfter(&theFunctionList,
1591                      (void *)openbor_createfilestream, "createfilestream");
1592     List_InsertAfter(&theFunctionList,
1593                      (void *)openbor_closefilestream, "closefilestream");
1594     List_InsertAfter(&theFunctionList,
1595                      (void *)openbor_savefilestream, "savefilestream");
1596     List_InsertAfter(&theFunctionList,
1597                      (void *)openbor_getindexedvar, "getindexedvar");
1598     List_InsertAfter(&theFunctionList,
1599                      (void *)openbor_setindexedvar, "setindexedvar");
1600     List_InsertAfter(&theFunctionList,
1601                      (void *)openbor_getscriptvar, "getscriptvar");
1602     List_InsertAfter(&theFunctionList,
1603                      (void *)openbor_setscriptvar, "setscriptvar");
1604     List_InsertAfter(&theFunctionList,
1605                      (void *)openbor_getentityvar, "getentityvar");
1606     List_InsertAfter(&theFunctionList,
1607                      (void *)openbor_setentityvar, "setentityvar");
1608     List_InsertAfter(&theFunctionList,
1609                      (void *)openbor_shutdown, "shutdown");
1610     List_InsertAfter(&theFunctionList,
1611                      (void *)openbor_jumptobranch, "jumptobranch");
1612     List_InsertAfter(&theFunctionList,
1613                      (void *)openbor_changelight, "changelight");
1614     List_InsertAfter(&theFunctionList,
1615                      (void *)openbor_changeshadowcolor, "changeshadowcolor");
1616     List_InsertAfter(&theFunctionList,
1617                      (void *)openbor_bindentity, "bindentity");
1618     List_InsertAfter(&theFunctionList,
1619                      (void *)openbor_array, "array");
1620     List_InsertAfter(&theFunctionList,
1621                      (void *)openbor_size, "size");
1622     List_InsertAfter(&theFunctionList,
1623                      (void *)openbor_get, "get");
1624     List_InsertAfter(&theFunctionList,
1625                      (void *)openbor_set, "set");
1626     List_InsertAfter(&theFunctionList,
1627                      (void *)openbor_reset, "reset");
1628     List_InsertAfter(&theFunctionList,
1629                      (void *)openbor_next, "next");
1630     List_InsertAfter(&theFunctionList,
1631                      (void *)openbor_key, "key");
1632     List_InsertAfter(&theFunctionList,
1633                      (void *)openbor_value, "value");
1634     List_InsertAfter(&theFunctionList,
1635                      (void *)openbor_allocscreen, "allocscreen");
1636     List_InsertAfter(&theFunctionList,
1637                      (void *)openbor_clearscreen, "clearscreen");
1638     List_InsertAfter(&theFunctionList,
1639                      (void *)openbor_setdrawmethod, "setdrawmethod");
1640     List_InsertAfter(&theFunctionList,
1641                      (void *)openbor_changedrawmethod, "changedrawmethod");
1642     List_InsertAfter(&theFunctionList,
1643                      (void *)openbor_updateframe, "updateframe");
1644     List_InsertAfter(&theFunctionList,
1645                      (void *)openbor_performattack, "performattack");
1646     List_InsertAfter(&theFunctionList,
1647                      (void *)openbor_setidle, "setidle");
1648     List_InsertAfter(&theFunctionList,
1649                      (void *)openbor_getentity, "getentity");
1650     List_InsertAfter(&theFunctionList,
1651                      (void *)openbor_loadmodel, "loadmodel");
1652     List_InsertAfter(&theFunctionList,
1653                      (void *)openbor_loadsprite, "loadsprite");
1654     List_InsertAfter(&theFunctionList,
1655                      (void *)openbor_options, "options");
1656     List_InsertAfter(&theFunctionList,
1657                      (void *)openbor_playgif, "playgif");
1658     List_InsertAfter(&theFunctionList,
1659                      (void *)openbor_openanigif, "openanigif");
1660     List_InsertAfter(&theFunctionList,
1661                      (void *)openbor_decodeanigif, "decodeanigif");
1662     List_InsertAfter(&theFunctionList,
1663                      (void *)openbor_getanigifinfo, "getanigifinfo");
1664     List_InsertAfter(&theFunctionList,
1665                      (void *)openbor_strinfirst, "strinfirst");
1666     List_InsertAfter(&theFunctionList,
1667                      (void *)openbor_strinlast, "strinlast");
1668     List_InsertAfter(&theFunctionList,
1669                      (void *)openbor_strleft, "strleft");
1670     List_InsertAfter(&theFunctionList,
1671                      (void *)openbor_strlength, "strlength");
1672     List_InsertAfter(&theFunctionList,
1673                      (void *)openbor_strwidth, "strwidth");
1674     List_InsertAfter(&theFunctionList,
1675                      (void *)openbor_strright, "strright");
1676     List_InsertAfter(&theFunctionList,
1677                      (void *)openbor_getmodelproperty, "getmodelproperty");
1678     List_InsertAfter(&theFunctionList,
1679                      (void *)openbor_changemodelproperty, "changemodelproperty");
1680     List_InsertAfter(&theFunctionList,
1681                      (void *)openbor_rgbcolor, "rgbcolor");
1682 
1683     List_InsertAfter(&theFunctionList,
1684                      (void *)openbor_adjustwalkanimation, "adjustwalkanimation");
1685     List_InsertAfter(&theFunctionList,
1686                      (void *)openbor_finditem, "finditem");
1687     List_InsertAfter(&theFunctionList,
1688                      (void *)openbor_pickup, "pickup");
1689     List_InsertAfter(&theFunctionList,
1690                      (void *)openbor_waypoints, "waypoints");
1691     List_InsertAfter(&theFunctionList,
1692                      (void *)openbor_drawspriteq, "drawspriteq");
1693     List_InsertAfter(&theFunctionList,
1694                      (void *)openbor_clearspriteq, "clearspriteq");
1695     List_InsertAfter(&theFunctionList,
1696                      (void *)openbor_getgfxproperty, "getgfxproperty");
1697     List_InsertAfter(&theFunctionList,
1698                      (void *)openbor_allocscript, "allocscript");
1699     List_InsertAfter(&theFunctionList,
1700                      (void *)openbor_loadscript, "loadscript");
1701     List_InsertAfter(&theFunctionList,
1702                      (void *)openbor_compilescript, "compilescript");
1703     List_InsertAfter(&theFunctionList,
1704                      (void *)openbor_executescript, "executescript");
1705     List_InsertAfter(&theFunctionList,
1706                      (void *)openbor_loadgamefile, "loadgamefile");
1707     List_InsertAfter(&theFunctionList,
1708                      (void *)openbor_playgame, "playgame");
1709     List_InsertAfter(&theFunctionList,
1710                      (void *)openbor_getsaveinfo, "getsaveinfo");
1711 
1712     //printf("Done!\n");
1713 
1714 }
1715 
1716 //////////////////////////////////////////////////////////
1717 ////////////   system functions
1718 //////////////////////////////////////////////////////////
1719 //isempty(var);
system_isempty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1720 HRESULT system_isempty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1721 {
1722     *pretvar = NULL;
1723     if(paramCount != 1)
1724     {
1725         return E_FAIL;
1726     }
1727 
1728     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1729     (*pretvar)->lVal = (LONG)((varlist[0])->vt == VT_EMPTY );
1730 
1731     return S_OK;
1732 }
1733 //NULL();
system_NULL(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1734 HRESULT system_NULL(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1735 {
1736     ScriptVariant_Clear(*pretvar);
1737 
1738     return S_OK;
1739 }
system_exit(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1740 HRESULT system_exit(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1741 {
1742     *pretvar = NULL;
1743     pcurrentscript->pinterpreter->bReset = FALSE;
1744     return S_OK;
1745 }
system_rand(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1746 HRESULT system_rand(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1747 {
1748     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1749     (*pretvar)->lVal = (LONG)rand32();
1750     return S_OK;
1751 }
1752 //getglobalvar(varname);
system_getglobalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1753 HRESULT system_getglobalvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1754 {
1755     LONG ltemp;
1756     ScriptVariant *ptmpvar;
1757 
1758     if(paramCount != 1)
1759     {
1760         goto ggv_error;
1761     }
1762 
1763     if(varlist[0]->vt == VT_STR)
1764     {
1765         ptmpvar = Varlist_GetByName(&global_var_list, StrCache_Get(varlist[0]->strVal));
1766     }
1767     else if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
1768     {
1769         ptmpvar = Varlist_GetByIndex(&global_var_list, (int)ltemp);
1770     }
1771     else
1772     {
1773         goto ggv_error;
1774     }
1775 
1776     if(ptmpvar)
1777     {
1778         ScriptVariant_Copy(*pretvar,  ptmpvar);
1779     }
1780     else
1781     {
1782         ScriptVariant_Clear(*pretvar);
1783     }
1784     return S_OK;
1785 
1786 ggv_error:
1787     *pretvar = NULL;
1788     return E_FAIL;
1789 }
1790 //setglobalvar(varname, value);
system_setglobalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1791 HRESULT system_setglobalvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1792 {
1793     LONG ltemp;
1794     if(paramCount < 2)
1795     {
1796         goto sgv_error;
1797     }
1798 
1799     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1800 
1801     if(varlist[0]->vt == VT_STR)
1802     {
1803         (*pretvar)->lVal = (LONG)Varlist_SetByName(&global_var_list, StrCache_Get(varlist[0]->strVal), varlist[1]);
1804     }
1805     else if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
1806     {
1807         (*pretvar)->lVal = (LONG)Varlist_SetByIndex(&global_var_list, (int)ltemp, varlist[1]);
1808     }
1809     else
1810     {
1811         goto sgv_error;
1812     }
1813 
1814     return S_OK;
1815 sgv_error:
1816     *pretvar = NULL;
1817     return E_FAIL;
1818 }
1819 //getlocalvar(varname);
system_getlocalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1820 HRESULT system_getlocalvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1821 {
1822     LONG ltemp;
1823     ScriptVariant *ptmpvar;
1824 
1825     if(paramCount != 1)
1826     {
1827         goto glv_error;
1828     }
1829 
1830     if(varlist[0]->vt == VT_STR)
1831     {
1832         ptmpvar = Varlist_GetByName(pcurrentscript->varlist, StrCache_Get(varlist[0]->strVal));
1833     }
1834     else if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
1835     {
1836         ptmpvar = Varlist_GetByIndex(pcurrentscript->varlist, (int)ltemp);
1837     }
1838     else
1839     {
1840         goto glv_error;
1841     }
1842 
1843     if(ptmpvar)
1844     {
1845         ScriptVariant_Copy(*pretvar,  ptmpvar);
1846     }
1847     else
1848     {
1849         ScriptVariant_Clear(*pretvar);
1850     }
1851     return S_OK;
1852 
1853 glv_error:
1854     *pretvar = NULL;
1855     return E_FAIL;
1856 }
1857 //setlocalvar(varname, value);
system_setlocalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1858 HRESULT system_setlocalvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1859 {
1860     LONG ltemp;
1861     if(paramCount < 2)
1862     {
1863         goto slv_error;
1864     }
1865 
1866     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1867 
1868     if(varlist[0]->vt == VT_STR)
1869     {
1870         (*pretvar)->lVal = (LONG)Varlist_SetByName(pcurrentscript->varlist, StrCache_Get(varlist[0]->strVal), varlist[1]);
1871     }
1872     else if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
1873     {
1874         (*pretvar)->lVal = (LONG)Varlist_SetByIndex(pcurrentscript->varlist, (int)ltemp, varlist[1]);
1875     }
1876     else
1877     {
1878         goto slv_error;
1879     }
1880 
1881     return S_OK;
1882 slv_error:
1883     *pretvar = NULL;
1884     return E_FAIL;
1885 }
1886 //clearlocalvar();
system_clearlocalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1887 HRESULT system_clearlocalvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1888 {
1889     *pretvar = NULL;
1890     Varlist_Cleanup(pcurrentscript->varlist);
1891     return S_OK;
1892 }
1893 //clearglobalvar();
system_clearglobalvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1894 HRESULT system_clearglobalvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1895 {
1896     *pretvar = NULL;
1897     Varlist_Cleanup(&global_var_list);
1898     return S_OK;
1899 }
1900 
1901 //free();
system_free(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1902 HRESULT system_free(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1903 {
1904     *pretvar = NULL;
1905     if(paramCount < 1)
1906     {
1907         return E_FAIL;
1908     }
1909     if(List_Includes(&scriptheap, varlist[0]->ptrVal))
1910     {
1911         _freeheapnode(List_Retrieve(&scriptheap));
1912         List_Remove(&scriptheap);
1913         return S_OK;
1914     }
1915     return E_FAIL;
1916 }
1917 
1918 //typeof(v);
system_typeof(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1919 HRESULT system_typeof(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1920 {
1921     if(paramCount < 1)
1922     {
1923         *pretvar = NULL;
1924         return E_FAIL;
1925     }
1926     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
1927     (*pretvar)->lVal = (LONG)varlist[0]->vt;
1928     return S_OK;
1929 }
1930 
math_sin(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1931 HRESULT math_sin(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1932 {
1933     LONG ltemp;
1934     if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
1935     {
1936         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
1937         (*pretvar)->dblVal = sin_table[(ltemp % 360 + 360) % 360];
1938         return S_OK;
1939     }
1940     *pretvar = NULL;
1941     return E_FAIL;
1942 }
1943 
math_cos(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1944 HRESULT math_cos(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1945 {
1946     LONG ltemp;
1947     if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
1948     {
1949         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
1950         (*pretvar)->dblVal = cos_table[(ltemp % 360 + 360) % 360];
1951         return S_OK;
1952     }
1953     *pretvar = NULL;
1954     return E_FAIL;
1955 }
1956 
math_sqrt(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)1957 HRESULT math_sqrt(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
1958 {
1959     DOUBLE dbltemp;
1960     float inv;
1961     if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[0], &dbltemp)))
1962     {
1963         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
1964         inv = invsqrt((float)dbltemp);
1965         assert(inv != 0.0f);
1966         (*pretvar)->dblVal = (DOUBLE)1.0 / inv;
1967         return S_OK;
1968     }
1969     *pretvar = NULL;
1970     return E_FAIL;
1971 }
1972 //////////////////////////////////////////////////////////
1973 ////////////   openbor functions
1974 //////////////////////////////////////////////////////////
1975 
1976 //check openborscript.h for systemvariant_enum
1977 
1978 // arranged list, for searching
1979 static const char *svlist[] =
1980 {
1981     "background",
1982     "blockade",
1983     "branchname",
1984     "count_enemies",
1985     "count_entities",
1986     "count_npcs",
1987     "count_players",
1988     "current_branch",
1989     "current_level",
1990     "current_palette",
1991     "current_scene",
1992     "current_set",
1993     "current_stage",
1994     "effectvol",
1995     "elapsed_time",
1996     "ent_max",
1997     "freeram",
1998     "game_paused",
1999     "game_speed",
2000     "gfx_x_offset",
2001     "gfx_y_offset",
2002     "gfx_y_offset_adj",
2003     "hResolution",
2004     "in_cheat_options",
2005     "in_control_options",
2006     "in_gameoverscreen",
2007     "in_halloffamescreen",
2008     "in_level",
2009     "in_load_game",
2010     "in_menuscreen",
2011     "in_new_game",
2012     "in_options",
2013     "in_selectscreen",
2014     "in_showcomplete",
2015     "in_sound_options",
2016     "in_start_game",
2017     "in_system_options",
2018     "in_titlescreen",
2019     "in_video_options",
2020     "lasthita",
2021     "lasthitc",
2022     "lasthitt",
2023     "lasthitx",
2024     "lasthitz",
2025     "levelheight",
2026     "levelpos",
2027     "levelwidth",
2028     "lightx",
2029     "lightz",
2030     "maxanimations",
2031     "maxattacktypes",
2032     "maxentityvars",
2033     "maxglobalvars",
2034     "maxindexedvars",
2035     "maxplayers",
2036     "maxscriptvars",
2037     "models_cached",
2038     "models_loaded",
2039     "musicvol",
2040     "nofadeout",
2041     "nojoin",
2042     "nopause",
2043     "nosave",
2044     "noscreenshot",
2045     "numpalettes",
2046     "pakname",
2047     "pause",
2048     "pixelformat",
2049     "player",
2050     "player1",
2051     "player2",
2052     "player3",
2053     "player4",
2054     "player_max_z",
2055     "player_min_z",
2056     "sample_play_id",
2057     "scrollmaxx",
2058     "scrollmaxz",
2059     "scrollminx",
2060     "scrollminz",
2061     "self",
2062     "shadowalpha",
2063     "shadowcolor",
2064     "skiptoset",
2065     "slowmotion",
2066     "slowmotion_duration",
2067     "smartbomber",
2068     "soundvol",
2069     "textbox",
2070     "ticks",
2071     "totalram",
2072     "usedram",
2073     "vResolution",
2074     "viewporth",
2075     "viewportw",
2076     "viewportx",
2077     "viewporty",
2078     "vscreen",
2079     "waiting",
2080     "xpos",
2081     "ypos",
2082 };
2083 
2084 
2085 // ===== openborvariant =====
mapstrings_systemvariant(ScriptVariant ** varlist,int paramCount)2086 int mapstrings_systemvariant(ScriptVariant **varlist, int paramCount)
2087 {
2088     char *propname;
2089     int prop;
2090 
2091 
2092     MAPSTRINGS(varlist[0], svlist, _sv_the_end,
2093                "openborvariant: System variable name not found: '%s'\n");
2094 
2095     return 1;
2096 }
2097 
2098 //sample function, used for getting a system variant
2099 //openborvariant(varname);
openbor_systemvariant(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2100 HRESULT openbor_systemvariant(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2101 {
2102     //used for getting the index from the enum of properties
2103     int variantindex = -1;
2104     //the paramCount used for checking.
2105     //check it first so the engine wont crash if the list is empty
2106     if(paramCount != 1)
2107     {
2108         goto systemvariant_error;
2109     }
2110     //call this function's mapstrings function to map string constants to enum values
2111     mapstrings_systemvariant(varlist, paramCount);
2112     //the variant name should be here
2113     //you can check the argument type if you like
2114     if(varlist[0]->vt == VT_INTEGER)
2115     {
2116         variantindex = varlist[0]->lVal;
2117     }
2118     else
2119     {
2120         goto systemvariant_error;
2121     }
2122     ///////these should be your get method, ///////
2123     ScriptVariant_Clear(*pretvar);
2124     if(getsyspropertybyindex(*pretvar, variantindex))
2125     {
2126         return S_OK;
2127     }
2128     //else if
2129     //////////////////////////////////////////////
2130 systemvariant_error:
2131     *pretvar = NULL;
2132     // we have finshed, so return
2133     return E_FAIL;
2134 }
2135 
2136 
2137 //used for changing a system variant
2138 //changeopenborvariant(varname, value);
openbor_changesystemvariant(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2139 HRESULT openbor_changesystemvariant(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2140 {
2141     //used for getting the enum constant corresponding to the desired variable
2142     int variantindex = 0;
2143     //reference to the arguments
2144     ScriptVariant *arg = NULL;
2145     //the paramCount used for checking.
2146     //check it first so the engine wont crash if the list is empty
2147     if(paramCount != 2)
2148     {
2149         goto changesystemvariant_error;
2150     }
2151     // map string constants to enum constants for speed
2152     mapstrings_systemvariant(varlist, paramCount);
2153     //get the 1st argument
2154     arg = varlist[0];
2155     //the variant name should be here
2156     //you can check the argument type if you like
2157     if(arg->vt == VT_INTEGER)
2158     {
2159         variantindex = arg->lVal;
2160     }
2161     else
2162     {
2163         goto changesystemvariant_error;
2164     }
2165 
2166     if(changesyspropertybyindex(variantindex, varlist[1]))
2167     {
2168         return S_OK;
2169     }
2170 changesystemvariant_error:
2171     *pretvar = NULL;
2172     // we have finshed, so return
2173     return E_FAIL;
2174 
2175 }
2176 
2177 // use font_printf to draw string
2178 //drawstring(x, y, font, string, z);
openbor_drawstring(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2179 HRESULT openbor_drawstring(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2180 {
2181     int i;
2182     char buf[256];
2183     LONG value[4];
2184     *pretvar = NULL;
2185 
2186     if(paramCount < 4)
2187     {
2188         goto drawstring_error;
2189     }
2190 
2191     for(i = 0; i < 3; i++)
2192     {
2193         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i)))
2194         {
2195             goto drawstring_error;
2196         }
2197     }
2198     if(paramCount > 4)
2199     {
2200         if(FAILED(ScriptVariant_IntegerValue(varlist[4], value + 3)))
2201         {
2202             goto drawstring_error;
2203         }
2204     }
2205     else
2206     {
2207         value[3] = 0;
2208     }
2209     ScriptVariant_ToString(varlist[3], buf);
2210     font_printf((int)value[0], (int)value[1], (int)value[2], (int)value[3], "%s", buf);
2211     return S_OK;
2212 
2213 drawstring_error:
2214     printf("First 3 values must be integer values and 4th value a string: drawstring(int x, int y, int font, value)\n");
2215     return E_FAIL;
2216 }
2217 
2218 //use screen_printf
2219 //drawstringtoscreen(screen, x, y, font, string);
openbor_drawstringtoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2220 HRESULT openbor_drawstringtoscreen(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2221 {
2222     int i;
2223     s_screen *scr;
2224     char buf[256];
2225     LONG value[3];
2226     *pretvar = NULL;
2227 
2228     if(paramCount != 5)
2229     {
2230         goto drawstring_error;
2231     }
2232 
2233     if(varlist[0]->vt != VT_PTR)
2234     {
2235         goto drawstring_error;
2236     }
2237     scr = (s_screen *)varlist[0]->ptrVal;
2238     if(!scr)
2239     {
2240         goto drawstring_error;
2241     }
2242 
2243     for(i = 0; i < 3; i++)
2244     {
2245         if(FAILED(ScriptVariant_IntegerValue(varlist[i + 1], value + i)))
2246         {
2247             goto drawstring_error;
2248         }
2249     }
2250 
2251     ScriptVariant_ToString(varlist[4], buf);
2252     screen_printf(scr, (int)value[0], (int)value[1], (int)value[2], "%s", buf);
2253     return S_OK;
2254 
2255 drawstring_error:
2256     printf("Function needs a valid screen handle, 3 integers and a string value: drawstringtoscreen(screen, int font, value)\n");
2257     return E_FAIL;
2258 }
2259 
2260 // debug purpose
2261 //log(string);
openbor_log(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2262 HRESULT openbor_log(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2263 {
2264     char buf[256];
2265     *pretvar = NULL;
2266 
2267     if(paramCount != 1)
2268     {
2269         goto drawstring_error;
2270     }
2271 
2272     ScriptVariant_ToString(varlist[0], buf);
2273     printf("%s", buf);
2274     return S_OK;
2275 
2276 drawstring_error:
2277     printf("Function needs 1 parameter: log(value)\n");
2278     return E_FAIL;
2279 }
2280 
2281 //drawbox(x, y, width, height, z, color, lut);
openbor_drawbox(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2282 HRESULT openbor_drawbox(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2283 {
2284     int i;
2285     LONG value[6], l;
2286     *pretvar = NULL;
2287     s_drawmethod dm;
2288 
2289     if(paramCount < 6)
2290     {
2291         goto drawbox_error;
2292     }
2293 
2294     for(i = 0; i < 6; i++)
2295     {
2296         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i)))
2297         {
2298             goto drawbox_error;
2299         }
2300     }
2301 
2302     if(paramCount > 6)
2303     {
2304         if(FAILED(ScriptVariant_IntegerValue(varlist[6], &l)))
2305         {
2306             goto drawbox_error;
2307         }
2308     }
2309     else
2310     {
2311         l = -1;
2312     }
2313 
2314     if(l >= 0)
2315     {
2316         l %= MAX_BLENDINGS + 1;
2317     }
2318     if(drawmethod.flag)
2319     {
2320         dm = drawmethod;
2321     }
2322     else
2323     {
2324         dm = plainmethod;
2325     }
2326     dm.alpha = l;
2327     spriteq_add_box((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], (int)value[5], &dm);
2328 
2329     return S_OK;
2330 
2331 drawbox_error:
2332     printf("Function requires 6 integer values: drawbox(int x, int y, int width, int height, int z, int color, int lut)\n");
2333     return E_FAIL;
2334 }
2335 
2336 //drawboxtoscreen(screen, x, y, width, height, color, lut);
openbor_drawboxtoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2337 HRESULT openbor_drawboxtoscreen(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2338 {
2339     int i;
2340     s_screen *s;
2341     LONG value[5], l;
2342     *pretvar = NULL;
2343     s_drawmethod dm;
2344 
2345     if(paramCount < 6)
2346     {
2347         goto drawbox_error;
2348     }
2349 
2350     s = (s_screen *)varlist[0]->ptrVal;
2351 
2352     if(!s)
2353     {
2354         goto drawbox_error;
2355     }
2356 
2357     for(i = 1; i < 6; i++)
2358     {
2359         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 1)))
2360         {
2361             goto drawbox_error;
2362         }
2363     }
2364 
2365     if(paramCount > 6)
2366     {
2367         if(FAILED(ScriptVariant_IntegerValue(varlist[6], &l)))
2368         {
2369             goto drawbox_error;
2370         }
2371     }
2372     else
2373     {
2374         l = -1;
2375     }
2376 
2377     if(l >= 0)
2378     {
2379         l %= MAX_BLENDINGS + 1;
2380     }
2381     if(drawmethod.flag)
2382     {
2383         dm = drawmethod;
2384     }
2385     else
2386     {
2387         dm = plainmethod;
2388     }
2389     dm.alpha = l;
2390 
2391     putbox((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], s, &dm);
2392 
2393     return S_OK;
2394 
2395 drawbox_error:
2396     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");
2397     return E_FAIL;
2398 }
2399 
2400 //drawline(x1, y1, x2, y2, z, color, lut);
openbor_drawline(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2401 HRESULT openbor_drawline(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2402 {
2403     int i;
2404     LONG value[6], l;
2405     *pretvar = NULL;
2406     s_drawmethod dm;
2407 
2408     if(paramCount < 6)
2409     {
2410         goto drawline_error;
2411     }
2412 
2413     for(i = 0; i < 6; i++)
2414     {
2415         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i)))
2416         {
2417             goto drawline_error;
2418         }
2419     }
2420 
2421     if(paramCount > 6)
2422     {
2423         if(FAILED(ScriptVariant_IntegerValue(varlist[6], &l)))
2424         {
2425             goto drawline_error;
2426         }
2427     }
2428     else
2429     {
2430         l = -1;
2431     }
2432 
2433     if(l >= 0 )
2434     {
2435         l %= MAX_BLENDINGS + 1;
2436     }
2437     if(drawmethod.flag)
2438     {
2439         dm = drawmethod;
2440     }
2441     else
2442     {
2443         dm = plainmethod;
2444     }
2445     dm.alpha = l;
2446     spriteq_add_line((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], (int)value[5], &dm);
2447 
2448     return S_OK;
2449 
2450 drawline_error:
2451     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");
2452     return E_FAIL;
2453 }
2454 
2455 //drawlinetoscreen(screen, x1, y1, x2, y2, color, lut);
openbor_drawlinetoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2456 HRESULT openbor_drawlinetoscreen(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2457 {
2458     int i;
2459     LONG value[5], l;
2460     s_screen *s;
2461     *pretvar = NULL;
2462     s_drawmethod dm;
2463 
2464     if(paramCount < 6)
2465     {
2466         goto drawline_error;
2467     }
2468 
2469     s = (s_screen *)varlist[0]->ptrVal;
2470 
2471     if(!s)
2472     {
2473         goto drawline_error;
2474     }
2475 
2476     for(i = 1; i < 6; i++)
2477     {
2478         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 1)))
2479         {
2480             goto drawline_error;
2481         }
2482     }
2483 
2484     if(paramCount > 6)
2485     {
2486         if(FAILED(ScriptVariant_IntegerValue(varlist[6], &l)))
2487         {
2488             goto drawline_error;
2489         }
2490     }
2491     else
2492     {
2493         l = -1;
2494     }
2495 
2496     if(l >= 0 )
2497     {
2498         l %= MAX_BLENDINGS + 1;
2499     }
2500     if(drawmethod.flag)
2501     {
2502         dm = drawmethod;
2503     }
2504     else
2505     {
2506         dm = plainmethod;
2507     }
2508     dm.alpha = l;
2509     putline((int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4], s, &dm);
2510 
2511     return S_OK;
2512 drawline_error:
2513     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");
2514     return E_FAIL;
2515 }
2516 
2517 //drawsprite(sprite, x, y, z, sortid);
openbor_drawsprite(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2518 HRESULT openbor_drawsprite(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2519 {
2520     int i;
2521     LONG value[4];
2522     s_sprite *spr;
2523     *pretvar = NULL;
2524 
2525     if(paramCount < 4)
2526     {
2527         goto drawsprite_error;
2528     }
2529     if(varlist[0]->vt != VT_PTR)
2530     {
2531         goto drawsprite_error;
2532     }
2533 
2534     spr = varlist[0]->ptrVal;
2535     if(!spr)
2536     {
2537         goto drawsprite_error;
2538     }
2539 
2540     value[3] = (LONG)0;
2541     for(i = 1; i < paramCount && i < 5; i++)
2542     {
2543         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 1)))
2544         {
2545             goto drawsprite_error;
2546         }
2547     }
2548 
2549     spriteq_add_frame((int)value[0], (int)value[1], (int)value[2], spr, &drawmethod, (int)value[3]);
2550 
2551     return S_OK;
2552 
2553 drawsprite_error:
2554     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");
2555     return E_FAIL;
2556 }
2557 
2558 //drawspritetoscreen(sprite, screen, x, y);
openbor_drawspritetoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2559 HRESULT openbor_drawspritetoscreen(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2560 {
2561     int i;
2562     LONG value[2];
2563     s_sprite *spr;
2564     s_screen *scr;
2565     *pretvar = NULL;
2566 
2567     if(paramCount < 4)
2568     {
2569         goto drawsprite_error;
2570     }
2571     if(varlist[0]->vt != VT_PTR)
2572     {
2573         goto drawsprite_error;
2574     }
2575     spr = varlist[0]->ptrVal;
2576     if(!spr)
2577     {
2578         goto drawsprite_error;
2579     }
2580 
2581     if(varlist[1]->vt != VT_PTR)
2582     {
2583         goto drawsprite_error;
2584     }
2585     scr = varlist[1]->ptrVal;
2586     if(!scr)
2587     {
2588         goto drawsprite_error;
2589     }
2590 
2591     for(i = 2; i < paramCount && i < 4; i++)
2592     {
2593         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 2)))
2594         {
2595             goto drawsprite_error;
2596         }
2597     }
2598 
2599     putsprite((int)value[0], (int)value[1], spr, scr, &drawmethod);
2600 
2601     return S_OK;
2602 
2603 drawsprite_error:
2604     printf("Function requires a valid sprite handle, a valid screen handle and 2 integer values: drawspritetoscreen(sprite, screen, int x, int y)\n");
2605     return E_FAIL;
2606 }
2607 
2608 //drawdot(x, y, z, color, lut);
openbor_drawdot(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2609 HRESULT openbor_drawdot(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2610 {
2611     int i;
2612     LONG value[4], l;
2613     *pretvar = NULL;
2614     s_drawmethod dm;
2615 
2616     if(paramCount < 4)
2617     {
2618         goto drawdot_error;
2619     }
2620 
2621     for(i = 0; i < 4; i++)
2622     {
2623         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i)))
2624         {
2625             goto drawdot_error;
2626         }
2627     }
2628 
2629     if(paramCount > 4)
2630     {
2631         if(FAILED(ScriptVariant_IntegerValue(varlist[4], &l)))
2632         {
2633             goto drawdot_error;
2634         }
2635     }
2636     else
2637     {
2638         l = -1;
2639     }
2640 
2641     if(l >= 0 )
2642     {
2643         l %= MAX_BLENDINGS + 1;
2644     }
2645     if(drawmethod.flag)
2646     {
2647         dm = drawmethod;
2648     }
2649     else
2650     {
2651         dm = plainmethod;
2652     }
2653     dm.alpha = l;
2654     spriteq_add_dot((int)value[0], (int)value[1], (int)value[2], (int)value[3], &dm);
2655 
2656     return S_OK;
2657 
2658 drawdot_error:
2659     printf("Function requires 4 integer values, 5th integer value is optional: drawdot(int x, int y, int z, int color, int lut)\n");
2660     return E_FAIL;
2661 }
2662 
2663 //drawdottoscreen(screen, x, y, color, lut);
openbor_drawdottoscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2664 HRESULT openbor_drawdottoscreen(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2665 {
2666     int i;
2667     LONG value[3], l;
2668     s_screen *s;
2669     *pretvar = NULL;
2670     s_drawmethod dm;
2671 
2672     if(paramCount < 4)
2673     {
2674         goto drawdot_error;
2675     }
2676 
2677     s = (s_screen *)varlist[0]->ptrVal;
2678 
2679     if(!s)
2680     {
2681         goto drawdot_error;
2682     }
2683 
2684     for(i = 1; i < 4; i++)
2685     {
2686         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 1)))
2687         {
2688             goto drawdot_error;
2689         }
2690     }
2691 
2692     if(paramCount > 4)
2693     {
2694         if(FAILED(ScriptVariant_IntegerValue(varlist[4], &l)))
2695         {
2696             goto drawdot_error;
2697         }
2698     }
2699     else
2700     {
2701         l = -1;
2702     }
2703 
2704     if(l >= 0 )
2705     {
2706         l %= MAX_BLENDINGS + 1;
2707     }
2708     if(drawmethod.flag)
2709     {
2710         dm = drawmethod;
2711     }
2712     else
2713     {
2714         dm = plainmethod;
2715     }
2716     dm.alpha = l;
2717 
2718     putpixel((int)value[0], (int)value[1], (int)value[2], s, &dm);
2719 
2720     return S_OK;
2721 
2722 drawdot_error:
2723     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");
2724     return E_FAIL;
2725 }
2726 
2727 
2728 //drawscreen(screen, x, y, z, lut);
openbor_drawscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2729 HRESULT openbor_drawscreen(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2730 {
2731     int i;
2732     LONG value[3], l;
2733     s_screen *s;
2734     s_drawmethod screenmethod;
2735     *pretvar = NULL;
2736 
2737     if(paramCount < 4)
2738     {
2739         goto drawscreen_error;
2740     }
2741 
2742     s = (s_screen *)varlist[0]->ptrVal;
2743 
2744     if(!s)
2745     {
2746         goto drawscreen_error;
2747     }
2748 
2749     for(i = 1; i < 4; i++)
2750     {
2751         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 1)))
2752         {
2753             goto drawscreen_error;
2754         }
2755     }
2756 
2757     if(paramCount > 4)
2758     {
2759         if(FAILED(ScriptVariant_IntegerValue(varlist[4], &l)))
2760         {
2761             goto drawscreen_error;
2762         }
2763     }
2764     else
2765     {
2766         l = -1;
2767     }
2768 
2769     if(l >= 0 )
2770     {
2771         l %= MAX_BLENDINGS + 1;
2772     }
2773     if(paramCount <= 4)
2774     {
2775         screenmethod = drawmethod;
2776     }
2777     else
2778     {
2779         screenmethod = plainmethod;
2780         screenmethod.alpha = l;
2781         screenmethod.transbg = 1;
2782     }
2783 
2784     spriteq_add_screen((int)value[0], (int)value[1], (int)value[2], s, &screenmethod, 0);
2785 
2786     return S_OK;
2787 
2788 drawscreen_error:
2789     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");
2790     return E_FAIL;
2791 }
2792 
2793 //getindexedvar(int index);
openbor_getindexedvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2794 HRESULT openbor_getindexedvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2795 {
2796     return system_getglobalvar(varlist, pretvar, paramCount);
2797 }
2798 
2799 //setindexedvar(int index, var);
openbor_setindexedvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2800 HRESULT openbor_setindexedvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2801 {
2802     return system_setglobalvar(varlist, pretvar, paramCount);
2803 }
2804 
2805 //getscriptvar(int index);
openbor_getscriptvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2806 HRESULT openbor_getscriptvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2807 {
2808     return system_getlocalvar(varlist, pretvar, paramCount);
2809 }
2810 
2811 //setscriptvar(int index, var);
openbor_setscriptvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2812 HRESULT openbor_setscriptvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2813 {
2814     return system_setlocalvar(varlist, pretvar, paramCount);
2815 }
2816 
2817 //getentityvar(entity, int index);
openbor_getentityvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2818 HRESULT openbor_getentityvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2819 {
2820     LONG ltemp;
2821     ScriptVariant *ptmpvar;
2822     entity *ent;
2823 
2824     if(paramCount < 2 || varlist[0]->vt != VT_PTR || !varlist[0]->ptrVal)
2825     {
2826         goto gev_error;
2827     }
2828 
2829     ent = (entity *)varlist[0]->ptrVal;
2830 
2831     if(varlist[1]->vt == VT_STR)
2832     {
2833         ptmpvar = Varlist_GetByName(ent->varlist, StrCache_Get(varlist[1]->strVal));
2834     }
2835     else if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)))
2836     {
2837         ptmpvar = Varlist_GetByIndex(ent->varlist, (int)ltemp);
2838     }
2839     else
2840     {
2841         goto gev_error;
2842     }
2843 
2844     if(ptmpvar)
2845     {
2846         ScriptVariant_Copy(*pretvar,  ptmpvar);
2847     }
2848     else
2849     {
2850         ScriptVariant_Clear(*pretvar);
2851     }
2852     return S_OK;
2853 
2854 gev_error:
2855     *pretvar = NULL;
2856     return E_FAIL;
2857 }
2858 
2859 //setentityvar(int index, var);
openbor_setentityvar(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2860 HRESULT openbor_setentityvar(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2861 {
2862     LONG ltemp;
2863     entity *ent;
2864 
2865     if(paramCount < 3 || varlist[0]->vt != VT_PTR || !varlist[0]->ptrVal)
2866     {
2867         goto sev_error;
2868     }
2869 
2870     ent = (entity *)varlist[0]->ptrVal;
2871 
2872     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2873 
2874     if(varlist[1]->vt == VT_STR)
2875     {
2876         (*pretvar)->lVal = (LONG)Varlist_SetByName(ent->varlist, StrCache_Get(varlist[1]->strVal), varlist[2]);
2877     }
2878     else if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)))
2879     {
2880         (*pretvar)->lVal = (LONG)Varlist_SetByIndex(ent->varlist, (int)ltemp, varlist[2]);
2881     }
2882     else
2883     {
2884         goto sev_error;
2885     }
2886 
2887     return S_OK;
2888 sev_error:
2889     *pretvar = NULL;
2890     return E_FAIL;
2891 }
2892 
2893 //strinfirst(char string, char search_string);
openbor_strinfirst(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2894 HRESULT openbor_strinfirst(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2895 {
2896     char *tempstr = NULL;
2897 
2898     if(paramCount < 2)
2899     {
2900         goto sif_error;
2901     }
2902 
2903     if(varlist[0]->vt != VT_STR || varlist[1]->vt != VT_STR)
2904     {
2905         printf("\n Error, strinfirst({string}, {search string}): Strinfirst must be passed valid {string} and {search string}. \n");
2906         goto sif_error;
2907     }
2908 
2909     tempstr = strstr((char *)StrCache_Get(varlist[0]->strVal), (char *)StrCache_Get(varlist[1]->strVal));
2910 
2911     if (tempstr != NULL)
2912     {
2913         ScriptVariant_ChangeType(*pretvar, VT_STR);
2914         StrCache_Copy((*pretvar)->strVal, tempstr);
2915     }
2916     else
2917     {
2918         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2919         (*pretvar)->lVal = -1;
2920     }
2921     return S_OK;
2922 
2923 sif_error:
2924     *pretvar = NULL;
2925     return E_FAIL;
2926 }
2927 
2928 //strinlast(char string, char search_string);
openbor_strinlast(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2929 HRESULT openbor_strinlast(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2930 {
2931     char *tempstr = NULL;
2932 
2933     if(paramCount < 2)
2934     {
2935         goto sil_error;
2936     }
2937 
2938     if(varlist[0]->vt != VT_STR || varlist[1]->vt != VT_STR)
2939     {
2940         printf("\n Error, strinlast({string}, {search string}): Strinlast must be passed valid {string} and {search string}. \n");
2941         goto sil_error;
2942     }
2943 
2944     tempstr = strrchr((char *)StrCache_Get(varlist[0]->strVal), varlist[1]->strVal);
2945 
2946     if (tempstr != NULL)
2947     {
2948         ScriptVariant_ChangeType(*pretvar, VT_STR);
2949         StrCache_Copy((*pretvar)->strVal, tempstr);
2950     }
2951     else
2952     {
2953         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2954         (*pretvar)->lVal = -1;
2955     }
2956     return S_OK;
2957 sil_error:
2958     *pretvar = NULL;
2959     return E_FAIL;
2960 }
2961 
2962 //strleft(char string, int i);
openbor_strleft(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2963 HRESULT openbor_strleft(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2964 {
2965     if(paramCount < 2)
2966     {
2967         goto sl_error;
2968     }
2969 
2970     if(varlist[0]->vt != VT_STR || varlist[1]->vt != VT_INTEGER)
2971     {
2972         printf("\n Error, strleft({string}, {characters}): Invalid or missing parameter. Strleft must be passed valid {string} and number of {characters}.\n");
2973         goto sl_error;
2974     }
2975     ScriptVariant_ChangeType(*pretvar, VT_STR);
2976     StrCache_NCopy((*pretvar)->strVal, (char *)StrCache_Get(varlist[0]->strVal), varlist[1]->lVal);
2977 
2978     return S_OK;
2979 sl_error:
2980     *pretvar = NULL;
2981     return E_FAIL;
2982 }
2983 
2984 //strlength(char string);
openbor_strlength(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)2985 HRESULT openbor_strlength(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
2986 {
2987     if(paramCount < 1 || varlist[0]->vt != VT_STR)
2988     {
2989         goto strlength_error;
2990     }
2991 
2992     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
2993     (*pretvar)->lVal = strlen((char *)StrCache_Get(varlist[0]->strVal));
2994     return S_OK;
2995 
2996 strlength_error:
2997     printf("Error, strlength({string}): Invalid or missing parameter. Strlength must be passed a valid {string}.\n");
2998     *pretvar = NULL;
2999     return E_FAIL;
3000 }
3001 
3002 //strwidth(char string, int font);
openbor_strwidth(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)3003 HRESULT openbor_strwidth(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
3004 {
3005     LONG ltemp;
3006     if(paramCount < 2 || varlist[0]->vt != VT_STR ||
3007             FAILED(ScriptVariant_IntegerValue(varlist[1], &ltemp)))
3008     {
3009         goto strwidth_error;
3010     }
3011 
3012     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3013     (*pretvar)->lVal = font_string_width((int)ltemp, (char *)StrCache_Get(varlist[0]->strVal));
3014     return S_OK;
3015 
3016 strwidth_error:
3017     printf("Error, strwidth({string}, {font}): Invalid or missing parameter.\n");
3018     *pretvar = NULL;
3019     return E_FAIL;
3020 }
3021 
3022 //strright(char string, int i);
openbor_strright(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)3023 HRESULT openbor_strright(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
3024 {
3025     char *tempstr = NULL;
3026 
3027     if(paramCount < 2)
3028     {
3029         goto sr_error;
3030     }
3031 
3032     if(varlist[0]->vt != VT_STR || varlist[1]->vt != VT_INTEGER)
3033     {
3034         printf("\n Error, strright({string}, {characters}): Invalid or missing parameter. Strright must be passed valid {string} and number of {characters}.\n");
3035         goto sr_error;
3036     }
3037 
3038     tempstr = (char *)StrCache_Get(varlist[0]->strVal);
3039 
3040     if (tempstr && tempstr[0])
3041     {
3042         ScriptVariant_ChangeType(*pretvar, VT_STR);
3043         StrCache_Copy((*pretvar)->strVal, &tempstr[varlist[1]->lVal]);
3044     }
3045     else
3046     {
3047         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3048         (*pretvar)->lVal = -1;
3049     }
3050 
3051     return S_OK;
3052 sr_error:
3053     *pretvar = NULL;
3054     return E_FAIL;
3055 }
3056 
openbor_getmodelproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)3057 HRESULT openbor_getmodelproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
3058 {
3059     int iArg;
3060 
3061     if(paramCount < 2)
3062     {
3063         *pretvar = NULL;
3064         return E_FAIL;
3065     }
3066 
3067     if((varlist[0]->vt != VT_INTEGER && varlist[0]->vt != VT_STR) || varlist[1]->vt != VT_INTEGER)
3068     {
3069         printf("\n Error, getmodelproperty({model}, {property}): Invalid or missing parameter. Getmodelproperty must be passed valid {model} and {property} indexes.\n");
3070     }
3071 
3072     iArg = varlist[0]->vt == VT_INTEGER ? varlist[0]->lVal : get_cached_model_index(StrCache_Get(varlist[0]->strVal));
3073 
3074     if(iArg < 0 || iArg >= models_cached)
3075     {
3076         return E_FAIL;
3077     }
3078 
3079     switch (varlist[1]->lVal)
3080     {
3081     case 0:                                                    //Loaded?
3082     {
3083         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3084         (*pretvar)->lVal = (LONG)model_cache[iArg].loadflag;
3085         break;
3086     }
3087     case 1:
3088     {
3089         ScriptVariant_ChangeType(*pretvar, VT_PTR);
3090         (*pretvar)->ptrVal = (VOID *)model_cache[iArg].model;
3091     }
3092     case 2:
3093     {
3094         ScriptVariant_ChangeType(*pretvar, VT_STR);
3095         StrCache_Copy((*pretvar)->strVal, model_cache[iArg].name);
3096         break;
3097     }
3098     case 3:
3099     {
3100         ScriptVariant_ChangeType(*pretvar, VT_STR);
3101         StrCache_Copy((*pretvar)->strVal, model_cache[iArg].path);
3102         break;
3103     }
3104     case 4:                                                    //Loaded?
3105     {
3106         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
3107         (*pretvar)->lVal = (LONG)model_cache[iArg].selectable;
3108         break;
3109     }
3110     }
3111 
3112     return S_OK;
3113 }
3114 
openbor_changemodelproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)3115 HRESULT openbor_changemodelproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
3116 {
3117     int iArg;
3118     LONG ltemp;
3119 
3120     if(paramCount < 2)
3121     {
3122         *pretvar = NULL;
3123         return E_FAIL;
3124     }
3125 
3126     if((varlist[0]->vt != VT_INTEGER && varlist[0]->vt != VT_STR) || varlist[1]->vt != VT_INTEGER)
3127     {
3128         printf("\n Error, changemodelproperty({model}, {property}, {value}): Invalid or missing parameter. Changemodelproperty must be passed valid {model}, {property} and {value}.\n");
3129     }
3130 
3131     iArg = varlist[0]->vt == VT_INTEGER ? varlist[0]->lVal : get_cached_model_index(StrCache_Get(varlist[0]->strVal));
3132 
3133     if(iArg < 0 || iArg >= models_cached)
3134     {
3135         return E_FAIL;
3136     }
3137 
3138     switch (varlist[1]->lVal)
3139     {
3140     case 0:                                                    //Loaded?
3141     {
3142         /*
3143         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
3144         	model_cache[iArg].loadflag = (int)ltemp;
3145         else (*pretvar)->lVal = (LONG)0;
3146         break;
3147         */
3148     }
3149     case 1:
3150     {
3151         /*
3152         if(varlist[2]->vt != VT_STR)
3153         {
3154         	printf("You must give a string value for {value}.\n");
3155         	goto changeentityproperty_error;
3156         }
3157         strcpy(model_cache[iArg].model, (char*)StrCache_Get(varlist[2]->strVal));
3158         (*pretvar)->lVal = (LONG)1;
3159         break;
3160         */
3161     }
3162     case 2:
3163     {
3164         /*
3165         if(varlist[2]->vt != VT_STR)
3166         {
3167         	printf("You must give a string value for {value}.\n");
3168         	goto changeentityproperty_error;
3169         }
3170         strcpy(model_cache[iArg].name, (char*)StrCache_Get(varlist[2]->strVal));
3171         (*pretvar)->lVal = (LONG)1;
3172         break;
3173         */
3174     }
3175     case 3:
3176     {
3177         /*
3178         if(varlist[2]->vt != VT_STR)
3179         {
3180         	printf("You must give a string value for {value}.\n");
3181         	goto changeentityproperty_error;
3182         }
3183         strcpy(model_cache[iArg].path, (char*)StrCache_Get(varlist[2]->strVal));
3184         (*pretvar)->lVal = (LONG)1;
3185         break;
3186         */
3187     }
3188     case 4:
3189     {
3190         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
3191         {
3192             model_cache[iArg].selectable = (int)ltemp;
3193         }
3194         else
3195         {
3196             (*pretvar)->lVal = (LONG)0;
3197         }
3198         break;
3199     }
3200     }
3201 
3202     return S_OK;
3203 }
3204 
3205 // ===== getentityproperty =====
3206 enum entityproperty_enum
3207 {
3208     _ep_a,
3209     _ep_aggression,
3210     _ep_aiattack,
3211     _ep_aiflag,
3212     _ep_aimove,
3213     _ep_alpha,
3214     _ep_animal,
3215     _ep_animating,
3216     _ep_animation,
3217     _ep_animationid,
3218     _ep_animheight,
3219     _ep_animhits,
3220     _ep_animnum,
3221     _ep_animpos,
3222     _ep_animvalid,
3223     _ep_antigrab,
3224     _ep_antigravity,
3225     _ep_attack,
3226     _ep_attackid,
3227     _ep_attacking,
3228     _ep_attackthrottle,
3229     _ep_attackthrottletime,
3230     _ep_autokill,
3231     _ep_base,
3232     _ep_bbox,
3233     _ep_blink,
3234     _ep_blockback,
3235     _ep_blockodds,
3236     _ep_blockpain,
3237     _ep_boss,
3238     _ep_bounce,
3239     _ep_bound,
3240     _ep_candamage,
3241     _ep_chargerate,
3242     _ep_colourmap,
3243     _ep_colourtable,
3244     _ep_combostep,
3245     _ep_combotime,
3246     _ep_damage_on_landing,
3247     _ep_dead,
3248     _ep_defaultmodel,
3249     _ep_defaultname,
3250     _ep_defense,
3251     _ep_detect,
3252     _ep_direction,
3253     _ep_dot,
3254     _ep_dropframe,
3255     _ep_edelay,
3256     _ep_energycost,
3257     _ep_escapecount,
3258     _ep_escapehits,
3259     _ep_exists,
3260     _ep_falldie,
3261     _ep_flash,
3262     _ep_freezetime,
3263     _ep_frozen,
3264     _ep_gfxshadow,
3265     _ep_grabbing,
3266     _ep_grabforce,
3267     _ep_guardpoints,
3268     _ep_health,
3269     _ep_height,
3270     _ep_hitbyid,
3271     _ep_hmapl,
3272     _ep_hmapu,
3273     _ep_hostile,
3274     _ep_icon,
3275     _ep_iconposition,
3276     _ep_invincible,
3277     _ep_invinctime,
3278     _ep_jugglepoints,
3279     _ep_jumpheight,
3280     _ep_knockdowncount,
3281     _ep_komap,
3282     _ep_landframe,
3283     _ep_lifeposition,
3284     _ep_lifespancountdown,
3285     _ep_link,
3286     _ep_map,
3287     _ep_mapcount,
3288     _ep_mapdefault,
3289     _ep_maps,
3290     _ep_maptime,
3291     _ep_maxguardpoints,
3292     _ep_maxhealth,
3293     _ep_maxjugglepoints,
3294     _ep_maxmp,
3295     _ep_model,
3296     _ep_mp,
3297     _ep_mpdroprate,
3298     _ep_mprate,
3299     _ep_mpset,
3300     _ep_mpstable,
3301     _ep_mpstableval,
3302     _ep_name,
3303     _ep_nameposition,
3304     _ep_nextanim,
3305     _ep_nextmove,
3306     _ep_nextthink,
3307     _ep_no_adjust_base,
3308     _ep_noaicontrol,
3309     _ep_nodieblink,
3310     _ep_nodrop,
3311     _ep_nograb,
3312     _ep_nolife,
3313     _ep_nopain,
3314     _ep_offense,
3315     _ep_opponent,
3316     _ep_owner,
3317     _ep_pain_time,
3318     _ep_parent,
3319     _ep_path,
3320     _ep_pathfindstep,
3321     _ep_playerindex,
3322     _ep_position,
3323     _ep_projectile,
3324     _ep_projectilehit,
3325     _ep_range,
3326     _ep_releasetime,
3327     _ep_running,
3328     _ep_rush_count,
3329     _ep_rush_tally,
3330     _ep_rush_time,
3331     _ep_score,
3332     _ep_scroll,
3333     _ep_seal,
3334     _ep_sealtime,
3335     _ep_setlayer,
3336     _ep_sortid,
3337     _ep_spawntype,
3338     _ep_speed,
3339     _ep_sprite,
3340     _ep_spritea,
3341     _ep_stalltime,
3342     _ep_stats,
3343     _ep_staydown,
3344     _ep_staydownatk,
3345     _ep_stealth,
3346     _ep_subentity,
3347     _ep_subject_to_gravity,
3348     _ep_subject_to_hole,
3349     _ep_subject_to_maxz,
3350     _ep_subject_to_minz,
3351     _ep_subject_to_obstacle,
3352     _ep_subject_to_platform,
3353     _ep_subject_to_screen,
3354     _ep_subject_to_wall,
3355     _ep_subtype,
3356     _ep_takeaction,
3357     _ep_think,
3358     _ep_thold,
3359     _ep_throwdamage,
3360     _ep_throwdist,
3361     _ep_throwframewait,
3362     _ep_throwheight,
3363     _ep_tosstime,
3364     _ep_tossv,
3365     _ep_trymove,
3366     _ep_type,
3367     _ep_velocity,
3368     _ep_vulnerable,
3369     _ep_weapent,
3370     _ep_weapon,
3371     _ep_x,
3372     _ep_xdir,
3373     _ep_z,
3374     _ep_zdir,
3375     _ep_the_end,
3376 };
3377 
3378 // arranged list, for searching
3379 static const char *eplist[] =
3380 {
3381     "a",
3382     "aggression",
3383     "aiattack",
3384     "aiflag",
3385     "aimove",
3386     "alpha",
3387     "animal",
3388     "animating",
3389     "animation",
3390     "animationid",
3391     "animheight",
3392     "animhits",
3393     "animnum",
3394     "animpos",
3395     "animvalid",
3396     "antigrab",
3397     "antigravity",
3398     "attack",
3399     "attackid",
3400     "attacking",
3401     "attackthrottle",
3402     "attackthrottletime",
3403     "autokill",
3404     "base",
3405     "bbox",
3406     "blink",
3407     "blockback",
3408     "blockodds",
3409     "blockpain",
3410     "boss",
3411     "bounce",
3412     "bound",
3413     "candamage",
3414     "chargerate",
3415     "colourmap",
3416     "colourtable",
3417     "combostep",
3418     "combotime",
3419     "damage_on_landing",
3420     "dead",
3421     "defaultmodel",
3422     "defaultname",
3423     "defense",
3424     "detect",
3425     "direction",
3426     "dot",
3427     "dropframe",
3428     "edelay",
3429     "energycost",
3430     "escapecount",
3431     "escapehits",
3432     "exists",
3433     "falldie",
3434     "flash",
3435     "freezetime",
3436     "frozen",
3437     "gfxshadow",
3438     "grabbing",
3439     "grabforce",
3440     "guardpoints",
3441     "health",
3442     "height",
3443     "hitbyid",
3444     "hmapl",
3445     "hmapu",
3446     "hostile",
3447     "icon",
3448     "iconposition",
3449     "invincible",
3450     "invinctime",
3451     "jugglepoints",
3452     "jumpheight",
3453     "knockdowncount",
3454     "komap",
3455     "landframe",
3456     "lifeposition",
3457     "lifespancountdown",
3458     "link",
3459     "map",
3460     "mapcount",
3461     "mapdefault",
3462     "maps",
3463     "maptime",
3464     "maxguardpoints",
3465     "maxhealth",
3466     "maxjugglepoints",
3467     "maxmp",
3468     "model",
3469     "mp",
3470     "mpdroprate",
3471     "mprate",
3472     "mpset",
3473     "mpstable",
3474     "mpstableval",
3475     "name",
3476     "nameposition",
3477     "nextanim",
3478     "nextmove",
3479     "nextthink",
3480     "no_adjust_base",
3481     "noaicontrol",
3482     "nodieblink",
3483     "nodrop",
3484     "nograb",
3485     "nolife",
3486     "nopain",
3487     "offense",
3488     "opponent",
3489     "owner",
3490     "pain_time",
3491     "parent",
3492     "path",
3493     "pathfindstep",
3494     "playerindex",
3495     "position",
3496     "projectile",
3497     "projectilehit",
3498     "range",
3499     "releasetime",
3500     "running",
3501     "rush_count",
3502     "rush_tally",
3503     "rush_time",
3504     "score",
3505     "scroll",
3506     "seal",
3507     "sealtime",
3508     "setlayer",
3509     "sortid",
3510     "spawntype",
3511     "speed",
3512     "sprite",
3513     "spritea",
3514     "stalltime",
3515     "stats",
3516     "staydown",
3517     "staydownatk",
3518     "stealth",
3519     "subentity",
3520     "subject_to_gravity",
3521     "subject_to_hole",
3522     "subject_to_maxz",
3523     "subject_to_minz",
3524     "subject_to_obstacle",
3525     "subject_to_platform",
3526     "subject_to_screen",
3527     "subject_to_wall",
3528     "subtype",
3529     "takeaction",
3530     "think",
3531     "thold",
3532     "throwdamage",
3533     "throwdist",
3534     "throwframewait",
3535     "throwheight",
3536     "tosstime",
3537     "tossv",
3538     "trymove",
3539     "type",
3540     "velocity",
3541     "vulnerable",
3542     "weapent",
3543     "weapon",
3544     "x",
3545     "xdir",
3546     "z",
3547     "zdir",
3548 };
3549 
3550 enum aiflag_enum
3551 {
3552     _ep_aiflag_animating,
3553     _ep_aiflag_attacking,
3554     _ep_aiflag_autokill,
3555     _ep_aiflag_blink,
3556     _ep_aiflag_blocking,
3557     _ep_aiflag_charging,
3558     _ep_aiflag_dead,
3559     _ep_aiflag_drop,
3560     _ep_aiflag_falling,
3561     _ep_aiflag_frozen,
3562     _ep_aiflag_getting,
3563     _ep_aiflag_idlemode,
3564     _ep_aiflag_idling,
3565     _ep_aiflag_inpain,
3566     _ep_aiflag_invincible,
3567     _ep_aiflag_jumpid,
3568     _ep_aiflag_jumping,
3569     _ep_aiflag_projectile,
3570     _ep_aiflag_running,
3571     _ep_aiflag_toexplode,
3572     _ep_aiflag_turning,
3573     _ep_aiflag_walking,
3574     _ep_aiflag_walkmode,
3575     _ep_aiflag_the_end,
3576 };
3577 
3578 
3579 static const char *eplist_aiflag[] =
3580 {
3581     "animating",
3582     "attacking",
3583     "autokill",
3584     "blink",
3585     "blocking",
3586     "charging",
3587     "dead",
3588     "drop",
3589     "falling",
3590     "frozen",
3591     "getting",
3592     "idlemode",
3593     "idling",
3594     "inpain",
3595     "invincible",
3596     "jumpid",
3597     "jumping",
3598     "projectile",
3599     "running",
3600     "toexplode",
3601     "turning",
3602     "walking",
3603     "walkmode",
3604 };
3605 
3606 static const char *eplist_attack[] =
3607 {
3608     "blast",
3609     "blockflash",
3610     "blocksound",
3611     "coords",
3612     "counterattack",
3613     "direction",
3614     "dol",
3615     "dot",
3616     "dotforce",
3617     "dotindex",
3618     "dotrate",
3619     "dottime",
3620     "drop",
3621     "dropv",
3622     "force",
3623     "forcemap",
3624     "freeze",
3625     "freezetime",
3626     "grab",
3627     "grabdistance",
3628     "guardcost",
3629     "hitflash",
3630     "hitsound",
3631     "jugglecost",
3632     "maptime",
3633     "noblock",
3634     "noflash",
3635     "nokill",
3636     "nopain",
3637     "otg",
3638     "pause",
3639     "reset",
3640     "seal",
3641     "sealtime",
3642     "staydown",
3643     "steal",
3644     "type",
3645 };
3646 
3647 enum gep_attack_enum
3648 {
3649     _ep_attack_blast,
3650     _ep_attack_blockflash,
3651     _ep_attack_blocksound,
3652     _ep_attack_coords,
3653     _ep_attack_counterattack,
3654     _ep_attack_direction,
3655     _ep_attack_dol,
3656     _ep_attack_dot,
3657     _ep_attack_dotforce,
3658     _ep_attack_dotindex,
3659     _ep_attack_dotrate,
3660     _ep_attack_dottime,
3661     _ep_attack_drop,
3662     _ep_attack_dropv,
3663     _ep_attack_force,
3664     _ep_attack_forcemap,
3665     _ep_attack_freeze,
3666     _ep_attack_freezetime,
3667     _ep_attack_grab,
3668     _ep_attack_grabdistance,
3669     _ep_attack_guardcost,
3670     _ep_attack_hitflash,
3671     _ep_attack_hitsound,
3672     _ep_attack_jugglecost,
3673     _ep_attack_maptime,
3674     _ep_attack_noblock,
3675     _ep_attack_noflash,
3676     _ep_attack_nokill,
3677     _ep_attack_nopain,
3678     _ep_attack_otg,
3679     _ep_attack_pause,
3680     _ep_attack_reset,
3681     _ep_attack_seal,
3682     _ep_attack_sealtime,
3683     _ep_attack_staydown,
3684     _ep_attack_steal,
3685     _ep_attack_type,
3686     _ep_attack_the_end,
3687 };
3688 
3689 enum _ep_defense_enum
3690 {
3691     _ep_defense_blockpower,
3692     _ep_defense_blockratio,
3693     _ep_defense_blockthreshold,
3694     _ep_defense_blocktype,
3695     _ep_defense_factor,
3696     _ep_defense_knockdown,
3697     _ep_defense_pain,
3698     _ep_defense_the_end,
3699 };
3700 
3701 enum gep_dot_enum
3702 {
3703     _ep_dot_force,
3704     _ep_dot_mode,
3705     _ep_dot_owner,
3706     _ep_dot_rate,
3707     _ep_dot_time,
3708     _ep_dot_type,
3709     _ep_dot_the_end,
3710 };
3711 
3712 enum gep_edelay_enum
3713 {
3714     _ep_edelay_cap_max,
3715     _ep_edelay_cap_min,
3716     _ep_edelay_factor,
3717     _ep_edelay_mode,
3718     _ep_edelay_range_max,
3719     _ep_edelay_range_min,
3720     _ep_edelay_the_end,
3721 };
3722 
3723 enum gep_energycost_enum
3724 {
3725     _ep_energycost_cost,
3726     _ep_energycost_disable,
3727     _ep_energycost_mponly,
3728     _ep_energycost_the_end,
3729 };
3730 
3731 enum gep_flash_enum
3732 {
3733     _ep_flash_block,
3734     _ep_flash_def,
3735     _ep_flash_noattack,
3736     _ep_flash_the_end,
3737 };
3738 
3739 enum gep_icon_enum
3740 {
3741     _ep_icon_def,
3742     _ep_icon_die,
3743     _ep_icon_get,
3744     _ep_icon_mphigh,
3745     _ep_icon_mplow,
3746     _ep_icon_mpmed,
3747     _ep_icon_pain,
3748     _ep_icon_weapon,
3749     _ep_icon_x,
3750     _ep_icon_y,
3751     _ep_icon_the_end,
3752 };
3753 
3754 enum _ep_knockdowncount_enum
3755 {
3756     _ep_knockdowncount_current,
3757     _ep_knockdowncount_max,
3758     _ep_knockdowncount_time,
3759     _ep_knockdowncount_the_end,
3760 };
3761 
3762 enum gep_landframe_enum
3763 {
3764     _ep_landframe_ent,
3765     _ep_landframe_frame,
3766     _ep_landframe_the_end,
3767 };
3768 
3769 enum gep_maps_enum
3770 {
3771     _ep_maps_count,
3772     _ep_maps_current,
3773     _ep_maps_default,
3774     _ep_maps_dying,
3775     _ep_maps_dying_critical,
3776     _ep_maps_dying_low,
3777     _ep_maps_frozen,
3778     _ep_maps_hide_end,
3779     _ep_maps_hide_start,
3780     _ep_maps_ko,
3781     _ep_maps_kotype,
3782     _ep_maps_table,
3783     _ep_maps_time,
3784     _ep_maps_the_end,
3785 };
3786 
3787 enum gep_range_enum
3788 {
3789     _ep_range_amax,
3790     _ep_range_amin,
3791     _ep_range_bmax,
3792     _ep_range_bmin,
3793     _ep_range_xmax,
3794     _ep_range_xmin,
3795     _ep_range_zmax,
3796     _ep_range_zmin,
3797     _ep_range_the_end,
3798 };
3799 
3800 enum gep_running_enum
3801 {
3802     _ep_running_jumpx,
3803     _ep_running_jumpy,
3804     _ep_running_land,
3805     _ep_running_movez,
3806     _ep_running_speed,
3807     _ep_running_the_end,
3808 };
3809 
3810 enum gep_spritea_enum
3811 {
3812     _ep_spritea_centerx,
3813     _ep_spritea_centery,
3814     _ep_spritea_file,
3815     _ep_spritea_offsetx,
3816     _ep_spritea_offsety,
3817     _ep_spritea_sprite,
3818     _ep_spritea_the_end,
3819 };
3820 
3821 enum gep_staydown_enum
3822 {
3823     _ep_staydown_rise,
3824     _ep_staydown_riseattack,
3825     _ep_staydown_riseattack_stall,
3826     _ep_staydown_the_end,
3827 };
3828 
3829 enum cep_hostile_candamage_enum
3830 {
3831     _ep_hcd_ground,
3832     _ep_hcd_type_enemy,
3833     _ep_hcd_type_npc,
3834     _ep_hcd_type_obstacle,
3835     _ep_hcd_type_player,
3836     _ep_hcd_type_shot,
3837     _ep_hcd_the_end,
3838 };
3839 
3840 enum cep_takeaction_enum
3841 {
3842     _ep_ta_bomb_explode,
3843     _ep_ta_common_attack_proc,
3844     _ep_ta_common_block,
3845     _ep_ta_common_drop,
3846     _ep_ta_common_fall,
3847     _ep_ta_common_get,
3848     _ep_ta_common_grab,
3849     _ep_ta_common_grabattack,
3850     _ep_ta_common_grabbed,
3851     _ep_ta_common_jump,
3852     _ep_ta_common_land,
3853     _ep_ta_common_lie,
3854     _ep_ta_common_pain,
3855     _ep_ta_common_prejump,
3856     _ep_ta_common_rise,
3857     _ep_ta_common_spawn,
3858     _ep_ta_common_turn,
3859     _ep_ta_common_vault,
3860     _ep_ta_normal_prepare,
3861     _ep_ta_npc_warp,
3862     _ep_ta_player_blink,
3863     _ep_ta_suicide,
3864     _ep_ta_the_end,
3865 };
3866 
3867 enum cep_think_enum   // 2011_03_03, DC: Think types.
3868 {
3869     _ep_th_common_think,
3870     _ep_th_player_think,
3871     _ep_th_steam_think,
3872     _ep_th_steamer_think,
3873     _ep_th_text_think,
3874     _ep_th_trap_think,
3875     _ep_th_the_end,
3876 };
3877 
mapstrings_entityproperty(ScriptVariant ** varlist,int paramCount)3878 int mapstrings_entityproperty(ScriptVariant **varlist, int paramCount)
3879 {
3880     char *propname;
3881     const char *eps;
3882     int prop, i, ep, t;
3883 
3884     static const char *proplist_defense[] =
3885     {
3886         "blockpower",
3887         "blockratio",
3888         "blockthreshold",
3889         "blocktype",
3890         "factor",
3891         "knockdown",
3892         "pain",
3893     };
3894 
3895     static const char *proplist_dot[] =
3896     {
3897         "force",
3898         "mode",
3899         "owner",
3900         "rate",
3901         "time",
3902         "type",
3903     };
3904 
3905     static const char *proplist_edelay[] =
3906     {
3907         "cap_max",
3908         "cap_min",
3909         "factor",
3910         "mode",
3911         "range_max",
3912         "range_min",
3913     };
3914 
3915     static const char *proplist_energycost[] =
3916     {
3917         "cost",
3918         "disable",
3919         "mponly",
3920     };
3921 
3922     static const char *proplist_flash[] =
3923     {
3924         "block",
3925         "default",
3926         "noattack",
3927     };
3928 
3929     static const char *proplist_icon[] =
3930     {
3931         "default",
3932         "die",
3933         "get",
3934         "mphigh",
3935         "mplow",
3936         "mpmed",
3937         "pain",
3938         "weapon",
3939         "x",
3940         "y",
3941     };
3942 
3943     static const char *proplist_knockdowncount[] =
3944     {
3945         "current",
3946         "max",
3947         "time",
3948     };
3949 
3950     static const char *proplist_landframe[] =
3951     {
3952         "ent",
3953         "frame",
3954     };
3955 
3956     static const char *proplist_maps[] =
3957     {
3958         "count",
3959         "current",
3960         "default",
3961         "dying",
3962         "dying_critical",
3963         "dying_low",
3964         "frozen",
3965         "hide_end",
3966         "hide_start",
3967         "ko",
3968         "kotype",
3969         "table",
3970         "time",
3971     };
3972 
3973     static const char *proplist_range[] =
3974     {
3975         "amax",
3976         "amin",
3977         "bmax",
3978         "bmin",
3979         "xmax",
3980         "xmin",
3981         "zmax",
3982         "zmin",
3983     };
3984 
3985     static const char *proplist_running[] =
3986     {
3987         "jumpx",
3988         "jumpy",
3989         "land",
3990         "movez",
3991         "speed",
3992     };
3993 
3994     static const char *proplist_spritea[] =
3995     {
3996         "centerx",
3997         "centery",
3998         "file",
3999         "offsetx",
4000         "offsety",
4001         "sprite",
4002     };
4003 
4004     static const char *proplist_staydown[] =
4005     {
4006         "rise",
4007         "riseattack",
4008         "riseattack_stall",
4009     };
4010 
4011     static const char *proplist_hostile_candamage[] =
4012     {
4013         "ground",
4014         "type_enemy",
4015         "type_npc",
4016         "type_obstacle",
4017         "type_player",
4018         "type_shot",
4019     };
4020 
4021     static const char *proplist_takeaction[] =
4022     {
4023         "bomb_explode",
4024         "common_attack_proc",
4025         "common_block",
4026         "common_drop",
4027         "common_fall",
4028         "common_get",
4029         "common_grab",
4030         "common_grabattack",
4031         "common_grabbed",
4032         "common_jump",
4033         "common_land",
4034         "common_lie",
4035         "common_pain",
4036         "common_prejump",
4037         "common_rise",
4038         "common_spawn",
4039         "common_turn",
4040         "common_vault",
4041         "normal_prepare",
4042         "npc_warp",
4043         "player_blink",
4044         "suicide",
4045     };
4046 
4047     static const char *proplist_think[] =   // 2011_03_03, DC: Think types.
4048     {
4049         "common_think",
4050         "player_think",
4051         "steam_think",
4052         "steamer_think",
4053         "text_think",
4054         "trap_think",
4055     };
4056 
4057     if(paramCount < 2)
4058     {
4059         return 1;
4060     }
4061 
4062     // map entity properties
4063     MAPSTRINGS(varlist[1], eplist, _ep_the_end,
4064                "Property name '%s' is not supported by function getentityproperty.\n");
4065 
4066     if(paramCount < 3 || varlist[1]->vt != VT_INTEGER)
4067     {
4068         return 1;
4069     }
4070 
4071     ep = varlist[1]->lVal;
4072     eps = (ep < _ep_the_end && ep >= 0) ? eplist[ep] : "";
4073 
4074     switch (ep)
4075     {
4076         // map subproperties of aiflag property
4077     case _ep_aiflag:
4078     {
4079         MAPSTRINGS(varlist[2], eplist_aiflag, _ep_aiflag_the_end,
4080                    _is_not_a_known_subproperty_of_, eps);
4081         break;
4082     }
4083     // map subproperties of Attack
4084     case _ep_attack:
4085     {
4086         MAPSTRINGS(varlist[2], eplist_attack, _ep_attack_the_end,
4087                    _is_not_a_known_subproperty_of_, eps);
4088         break;
4089     }
4090     // map subproperties of defense property
4091     case _ep_defense:
4092     {
4093         if(paramCount >= 4)
4094         {
4095             MAPSTRINGS(varlist[3], proplist_defense, _ep_defense_the_end,
4096                        _is_not_a_known_subproperty_of_, eps);
4097         }
4098         break;
4099     }
4100     // map subproperties of DOT
4101     case _ep_dot:
4102     {
4103         MAPSTRINGS(varlist[2], proplist_dot, _ep_dot_the_end,
4104                    _is_not_a_known_subproperty_of_, eps);
4105         break;
4106     }
4107     // map subproperties of Edelay property
4108     case _ep_edelay:
4109     {
4110         MAPSTRINGS(varlist[2], proplist_edelay, _ep_edelay_the_end,
4111                    _is_not_a_known_subproperty_of_, eps);
4112         break;
4113     }
4114     // map subproperties of Energycost
4115     case _ep_energycost:
4116     {
4117         MAPSTRINGS(varlist[2], proplist_energycost, _ep_energycost_the_end,
4118                    _is_not_a_known_subproperty_of_, eps);
4119         break;
4120     }
4121     // map subproperties of Flash
4122     case _ep_flash:
4123     {
4124         MAPSTRINGS(varlist[2], proplist_flash, _ep_flash_the_end,
4125                    _is_not_a_known_subproperty_of_, eps);
4126         break;
4127     }
4128     // map subproperties of Icon
4129     case _ep_icon:
4130     {
4131         MAPSTRINGS(varlist[2], proplist_icon, _ep_icon_the_end,
4132                    _is_not_a_known_subproperty_of_, eps);
4133         break;
4134     }
4135 
4136     // map subproperties of Knockdowncount
4137     case _ep_knockdowncount:
4138     {
4139         MAPSTRINGS(varlist[2], proplist_knockdowncount, _ep_knockdowncount_the_end,
4140                    _is_not_a_known_subproperty_of_, eps);
4141         break;
4142     }
4143     // map subproperties of Landframe
4144     case _ep_landframe:
4145     {
4146         MAPSTRINGS(varlist[2], proplist_landframe, _ep_landframe_the_end,
4147                    _is_not_a_known_subproperty_of_, eps);
4148         break;
4149     }
4150     // map subproperties of Maps
4151     case  _ep_maps:
4152     {
4153         MAPSTRINGS(varlist[2], proplist_maps, _ep_maps_the_end,
4154                    _is_not_a_known_subproperty_of_, eps);
4155         break;
4156     }
4157     // map subproperties of Range
4158     case _ep_range:
4159     {
4160         MAPSTRINGS(varlist[2], proplist_range, _ep_range_the_end,
4161                    _is_not_a_known_subproperty_of_, eps);
4162         break;
4163     }
4164     // map subproperties of Running
4165     case _ep_running:
4166     {
4167         MAPSTRINGS(varlist[2], proplist_running, _ep_running_the_end,
4168                    _is_not_a_known_subproperty_of_, eps);
4169         break;
4170     }
4171 
4172     // map subproperties of Spritea
4173     case _ep_spritea:
4174     {
4175         MAPSTRINGS(varlist[2], proplist_spritea, _ep_spritea_the_end,
4176                    _is_not_a_known_subproperty_of_, eps);
4177         break;
4178     }
4179     // map subproperties of Staydown
4180     case _ep_staydown:
4181     {
4182         MAPSTRINGS(varlist[2], proplist_staydown, _ep_running_the_end,
4183                    _is_not_a_known_subproperty_of_, eps);
4184         break;
4185     }
4186     //hostile, candamage, projectilehit
4187     case _ep_hostile:
4188     case _ep_candamage:
4189     case _ep_projectilehit:
4190     {
4191         for(i = 2; i < paramCount; i++)
4192         {
4193             t = varlist[i]->vt;
4194             MAPSTRINGS(varlist[i], proplist_hostile_candamage, _ep_hcd_the_end,
4195                        _is_not_supported_by_, eps);
4196 
4197             if(varlist[i]->vt == VT_INTEGER && t == VT_STR)
4198             {
4199                 varlist[i]->lVal |= 0x80000000;    //flag it
4200             }
4201         }
4202         break;
4203     }
4204     // action for takeaction
4205     case _ep_takeaction:
4206     {
4207         MAPSTRINGS(varlist[2], proplist_takeaction, _ep_ta_the_end,
4208                    _is_not_supported_by_, eps);
4209         break;
4210     }
4211     // 2011_03_13, DC: Think sets for think.
4212     case _ep_think:
4213     {
4214         MAPSTRINGS(varlist[2], proplist_think, _ep_th_the_end,
4215                    _is_not_supported_by_, eps);
4216         break;
4217     }
4218     }
4219 
4220     return 1;
4221 }
4222 
4223 //getentityproperty(pentity, propname);
openbor_getentityproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)4224 HRESULT openbor_getentityproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
4225 {
4226     entity *ent			= NULL;
4227     char *tempstr		= NULL;
4228     ScriptVariant *arg	= NULL;
4229     ScriptVariant *arg1	= NULL;
4230     s_sprite *spr;
4231     s_attack *attack;
4232     LONG ltemp, ltemp2;
4233     int i				= 0;
4234     int propind ;
4235     int tempint			= 0;
4236     int *coords;
4237 
4238     if(paramCount < 2)
4239     {
4240         *pretvar = NULL;
4241         return E_FAIL;
4242     }
4243 
4244     ScriptVariant_Clear(*pretvar);
4245     mapstrings_entityproperty(varlist, paramCount);
4246 
4247     arg = varlist[0];
4248     if(arg->vt != VT_PTR && arg->vt != VT_EMPTY)
4249     {
4250         printf("Function getentityproperty must have a valid entity handle.\n");
4251         *pretvar = NULL;
4252         return E_FAIL;
4253     }
4254     ent = (entity *)arg->ptrVal; //retrieve the entity
4255     if(!ent)
4256     {
4257         return S_OK;
4258     }
4259 
4260     arg = varlist[1];
4261     if(arg->vt != VT_INTEGER)
4262     {
4263         printf("Function getentityproperty must have a string property name.\n");
4264     }
4265 
4266     propind = arg->lVal;
4267 
4268     switch(propind)
4269     {
4270     case _ep_a:
4271     {
4272         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4273         (*pretvar)->dblVal = (DOUBLE)ent->a;
4274         break;
4275     }
4276     case _ep_aggression:
4277     {
4278         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4279         (*pretvar)->lVal = (LONG)ent->modeldata.aggression;
4280         break;
4281     }
4282     case _ep_aiattack:
4283     {
4284         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4285         (*pretvar)->lVal = (LONG)ent->modeldata.aiattack;
4286         break;
4287     }
4288     case _ep_aiflag:
4289     {
4290         if(paramCount < 3)
4291         {
4292             break;
4293         }
4294         arg = varlist[2];
4295         if(arg->vt != VT_INTEGER)
4296         {
4297             printf("You must give a string name for aiflag.\n");
4298             return E_FAIL;
4299         }
4300         ltemp = arg->lVal;
4301 
4302         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4303         switch(ltemp)
4304         {
4305         case _ep_aiflag_dead:
4306             (*pretvar)->lVal = (LONG)ent->dead;
4307             break;
4308         case _ep_aiflag_jumpid:
4309             (*pretvar)->lVal = (LONG)ent->jumpid;
4310             break;
4311         case _ep_aiflag_jumping:
4312             (*pretvar)->lVal = (LONG)ent->jumping;
4313             break;
4314         case _ep_aiflag_idling:
4315             (*pretvar)->lVal = (LONG)ent->idling;
4316             break;
4317         case _ep_aiflag_drop:
4318             (*pretvar)->lVal = (LONG)ent->drop;
4319             break;
4320         case _ep_aiflag_attacking:
4321             (*pretvar)->lVal = (LONG)ent->attacking;
4322             break;
4323         case _ep_aiflag_getting:
4324             (*pretvar)->lVal = (LONG)ent->getting;
4325             break;
4326         case _ep_aiflag_turning:
4327             (*pretvar)->lVal = (LONG)ent->turning;
4328             break;
4329         case _ep_aiflag_charging:
4330             (*pretvar)->lVal = (LONG)ent->charging;
4331             break;
4332         case _ep_aiflag_blocking:
4333             (*pretvar)->lVal = (LONG)ent->blocking;
4334             break;
4335         case _ep_aiflag_falling:
4336             (*pretvar)->lVal = (LONG)ent->falling;
4337             break;
4338         case _ep_aiflag_running:
4339             (*pretvar)->lVal = (LONG)ent->running;
4340             break;
4341         case _ep_aiflag_inpain:
4342             (*pretvar)->lVal = (LONG)ent->inpain;
4343             break;
4344         case _ep_aiflag_projectile:
4345             (*pretvar)->lVal = (LONG)ent->projectile;
4346             break;
4347         case _ep_aiflag_frozen:
4348             (*pretvar)->lVal = (LONG)ent->frozen;
4349             break;
4350         case _ep_aiflag_toexplode:
4351             (*pretvar)->lVal = (LONG)ent->toexplode;
4352             break;
4353         case _ep_aiflag_animating:
4354             (*pretvar)->lVal = (LONG)ent->animating;
4355             break;
4356         case _ep_aiflag_blink:
4357             (*pretvar)->lVal = (LONG)ent->blink;
4358             break;
4359         case _ep_aiflag_invincible:
4360             (*pretvar)->lVal = (LONG)ent->invincible;
4361             break;
4362         case _ep_aiflag_autokill:
4363             (*pretvar)->lVal = (LONG)ent->autokill;
4364             break;
4365         case _ep_aiflag_idlemode:
4366             (*pretvar)->lVal = (LONG)ent->idlemode;
4367             break;
4368         case _ep_aiflag_walkmode:
4369             (*pretvar)->lVal = (LONG)ent->walkmode;
4370             break;
4371         case _ep_aiflag_walking:
4372             break;
4373         default:
4374             ScriptVariant_Clear(*pretvar);
4375             return E_FAIL;
4376         }
4377         break;
4378     }
4379     case _ep_aimove:
4380     {
4381         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4382         (*pretvar)->lVal = (LONG)ent->modeldata.aimove;
4383         break;
4384     }
4385     case _ep_alpha:
4386     {
4387         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4388         (*pretvar)->lVal = (LONG)ent->modeldata.alpha;
4389         break;
4390     }
4391     case _ep_animal:
4392     {
4393         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4394         (*pretvar)->lVal = (LONG)ent->modeldata.animal;
4395         break;
4396     }
4397     case _ep_animating:
4398     {
4399         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4400         (*pretvar)->lVal = (LONG)ent->animating;
4401         break;
4402     }
4403     case _ep_animation:
4404     {
4405         ScriptVariant_ChangeType(*pretvar, VT_PTR);
4406         (*pretvar)->ptrVal = (VOID *)ent->animation;
4407         break;
4408     }
4409 
4410     /*
4411     case _ep_animationid: See animnum.
4412     */
4413 
4414     case _ep_animheight:
4415     {
4416         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4417         (*pretvar)->lVal = (LONG)ent->animation->height;
4418         break;
4419     }
4420     case _ep_animhits:
4421     {
4422         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4423         (*pretvar)->lVal = (LONG)ent->animation->animhits;
4424         break;
4425     }
4426     case _ep_animnum:
4427     case _ep_animationid:
4428     {
4429         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4430         (*pretvar)->lVal = (LONG)ent->animnum;
4431         break;
4432     }
4433     case _ep_animpos:
4434     {
4435         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4436         (*pretvar)->lVal = (LONG)ent->animpos;
4437         break;
4438     }
4439     case _ep_animvalid:
4440     {
4441         ltemp = 0;
4442         if(paramCount == 3)
4443         {
4444             arg = varlist[2];
4445             if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
4446             {
4447                 ltemp = (LONG)0;
4448             }
4449         }
4450         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4451         (*pretvar)->lVal = (LONG)validanim(ent, ltemp);
4452         break;
4453     }
4454     case _ep_antigrab:
4455     {
4456         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4457         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.antigrab;
4458         break;
4459     }
4460     case _ep_antigravity:
4461     {
4462         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4463         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.antigravity;
4464         break;
4465     }
4466     case _ep_attack:
4467     {
4468         if(paramCount < 6)
4469         {
4470             break;
4471         }
4472         arg = varlist[2];
4473         if(arg->vt != VT_INTEGER)
4474         {
4475             printf("Error, getentityproperty({ent}, 'attack', {sub property}, {index}, {animation}, {frame}): You must give a string name for {sub property}.\n");
4476             return E_FAIL;
4477         }
4478         ltemp = arg->lVal;
4479 
4480         if(varlist[3]->vt != VT_INTEGER
4481                 || varlist[4]->vt != VT_INTEGER
4482                 || varlist[5]->vt != VT_INTEGER)
4483         {
4484             printf("\n Error, getentityproperty({ent}, 'attack', {sub property}, {index}, {animation}, {frame}): {Animation} or {frame} parameter is missing or invalid. \n");
4485             return E_FAIL;
4486         }
4487 
4488         //varlist[3]->lval														//Attack box index (multiple attack boxes).
4489         i		= varlist[4]->lVal;												//Animation parameter.
4490         tempint	= varlist[5]->lVal;												//Frame parameter.
4491 
4492         if(!validanim(ent, i) || !ent->modeldata.animation[i]->attacks || !ent->modeldata.animation[i]->attacks[tempint])	//Verify animation and active attack on frame.
4493         {
4494             break;
4495         }
4496 
4497         attack = ent->modeldata.animation[i]->attacks[tempint];					//Get attack struct.
4498 
4499         switch(ltemp)
4500         {
4501         case _ep_attack_blockflash:
4502             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4503             (*pretvar)->lVal = (LONG)attack->blockflash;
4504             break;
4505         case _ep_attack_blocksound:
4506             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4507             (*pretvar)->lVal = (LONG)attack->blocksound;
4508             break;
4509         case _ep_attack_coords:
4510             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4511             (*pretvar)->lVal = (LONG)attack->attack_coords[varlist[6]->lVal];
4512             break;
4513         case _ep_attack_counterattack:
4514             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4515             (*pretvar)->lVal = (LONG)attack->counterattack;
4516             break;
4517         case _ep_attack_direction:
4518             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4519             (*pretvar)->lVal = (LONG)attack->force_direction;
4520             break;
4521         case _ep_attack_dol:
4522             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4523             (*pretvar)->lVal = (LONG)attack->damage_on_landing;
4524             break;
4525         case _ep_attack_dot:
4526             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4527             (*pretvar)->lVal = (LONG)attack->dot;
4528             break;
4529         case _ep_attack_dotforce:
4530             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4531             (*pretvar)->lVal = (LONG)attack->dot_force;
4532             break;
4533         case _ep_attack_dotindex:
4534             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4535             (*pretvar)->lVal = (LONG)attack->dot_index;
4536             break;
4537         case _ep_attack_dotrate:
4538             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4539             (*pretvar)->lVal = (LONG)attack->dot_rate;
4540             break;
4541         case _ep_attack_dottime:
4542             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4543             (*pretvar)->lVal = (LONG)attack->dot_time;
4544             break;
4545         case _ep_attack_drop:
4546             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4547             (*pretvar)->lVal = (LONG)attack->attack_drop;
4548             break;
4549         case _ep_attack_dropv:
4550             ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4551             (*pretvar)->dblVal = (DOUBLE)attack->dropv[varlist[6]->lVal];
4552             break;
4553         case _ep_attack_force:
4554             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4555             (*pretvar)->lVal = (LONG)attack->attack_force;
4556             break;
4557         case _ep_attack_forcemap:
4558             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4559             (*pretvar)->lVal = (LONG)attack->forcemap;
4560             break;
4561         case _ep_attack_freeze:
4562             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4563             (*pretvar)->lVal = (LONG)attack->freeze;
4564             break;
4565         case _ep_attack_freezetime:
4566             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4567             (*pretvar)->lVal = (LONG)attack->freezetime;
4568             break;
4569         case _ep_attack_grab:
4570             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4571             (*pretvar)->lVal = (LONG)attack->grab;
4572             break;
4573         case _ep_attack_grabdistance:
4574             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4575             (*pretvar)->lVal = (LONG)attack->grab_distance;
4576             break;
4577         case _ep_attack_guardcost:
4578             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4579             (*pretvar)->lVal = (LONG)attack->guardcost;
4580             break;
4581         case _ep_attack_hitflash:
4582             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4583             (*pretvar)->lVal = (LONG)attack->hitflash;
4584             break;
4585         case _ep_attack_hitsound:
4586             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4587             (*pretvar)->lVal = (LONG)attack->hitsound;
4588             break;
4589         case _ep_attack_jugglecost:
4590             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4591             (*pretvar)->lVal = (LONG)attack->jugglecost;
4592             break;
4593         case _ep_attack_maptime:
4594             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4595             (*pretvar)->lVal = (LONG)attack->maptime;
4596             break;
4597         case _ep_attack_noblock:
4598             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4599             (*pretvar)->lVal = (LONG)attack->no_block;
4600             break;
4601         case _ep_attack_noflash:
4602             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4603             (*pretvar)->lVal = (LONG)attack->no_flash;
4604             break;
4605         case _ep_attack_nokill:
4606             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4607             (*pretvar)->lVal = (LONG)attack->no_kill;
4608             break;
4609         case _ep_attack_nopain:
4610             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4611             (*pretvar)->lVal = (LONG)attack->no_pain;
4612             break;
4613         case _ep_attack_otg:
4614             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4615             (*pretvar)->lVal = (LONG)attack->otg;
4616             break;
4617         case _ep_attack_pause:
4618             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4619             (*pretvar)->lVal = (LONG)attack->pause_add;
4620             break;
4621         case _ep_attack_seal:
4622             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4623             (*pretvar)->lVal = (LONG)attack->seal;
4624             break;
4625         case _ep_attack_sealtime:
4626             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4627             (*pretvar)->lVal = (LONG)attack->sealtime;
4628             break;
4629         case _ep_attack_staydown:
4630             ScriptVariant_ChangeType(*pretvar, VT_PTR);
4631             (*pretvar)->ptrVal = (VOID *)attack->staydown;
4632             break;
4633         case _ep_attack_steal:
4634             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4635             (*pretvar)->lVal = (LONG)attack->steal;
4636             break;
4637         case _ep_attack_type:
4638             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4639             (*pretvar)->lVal = (LONG)attack->attack_type;
4640             break;
4641         default:
4642             *pretvar = NULL;
4643             return E_FAIL;
4644         }
4645         break;
4646     }
4647     case _ep_attacking:
4648     {
4649         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4650         (*pretvar)->lVal = (LONG)ent->attacking;
4651         break;
4652     }
4653     case _ep_attackid:
4654     {
4655         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4656         (*pretvar)->lVal = (LONG)ent->attack_id;
4657         break;
4658     }
4659     case _ep_autokill:
4660     {
4661         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4662         (*pretvar)->lVal = (LONG)ent->autokill;
4663         break;
4664     }
4665     case _ep_base:
4666     {
4667         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4668         (*pretvar)->dblVal = (DOUBLE)ent->base;
4669         break;
4670     }
4671     case _ep_vulnerable:
4672     {
4673         if(paramCount == 2)
4674         {
4675             i		= ent->animnum;
4676             tempint	= ent->animpos;
4677         }
4678         else if(paramCount < 4
4679                 || varlist[2]->vt != VT_INTEGER
4680                 || varlist[3]->vt != VT_INTEGER)
4681         {
4682             printf("\n Error, getentityproperty({ent}, \"vulnerable\", {animation}, {frame}): parameters missing or invalid. \n");
4683             *pretvar = NULL;
4684             return E_FAIL;
4685         }
4686         else
4687         {
4688             i		= varlist[2]->lVal;												//Animation parameter.
4689             tempint	= varlist[3]->lVal;												//Frame parameter.
4690         }
4691         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4692         (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->vulnerable[tempint];
4693         break;
4694     }
4695     case _ep_bbox:
4696     {
4697         if(paramCount < 6
4698                 || varlist[2]->vt != VT_INTEGER
4699                 || varlist[3]->vt != VT_INTEGER
4700                 || varlist[4]->vt != VT_INTEGER
4701                 || varlist[5]->vt != VT_INTEGER)
4702         {
4703             printf("\n Error, getentityproperty({ent}, \"bbox\", {index}, {animation}, {frame}, {arg}): parameters  missing or invalid. \n");
4704             *pretvar = NULL;
4705             return E_FAIL;
4706         }
4707 
4708         //varlist[2]->lval;														//bbox index (multiple bbox support).
4709         i		= varlist[3]->lVal;												//Animation parameter.
4710         tempint	= varlist[4]->lVal;												//Frame parameter.
4711 
4712         if(!ent->modeldata.animation[i]->vulnerable[tempint])
4713         {
4714 
4715             ScriptVariant_Clear(*pretvar);
4716             break;
4717         }
4718 
4719         coords = ent->modeldata.animation[i]->bbox_coords[tempint];
4720 
4721         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4722         (*pretvar)->lVal = (LONG)coords[varlist[5]->lVal];
4723         break;
4724     }
4725     case _ep_blink:
4726     {
4727         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4728         (*pretvar)->lVal = (LONG)ent->blink;
4729         break;
4730     }
4731     case _ep_blockback:
4732     {
4733         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
4734         {
4735             ent->modeldata.blockback = (int)ltemp;
4736         }
4737         break;
4738     }
4739     case _ep_blockodds:
4740     {
4741         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4742         (*pretvar)->lVal = (LONG)ent->modeldata.blockodds;
4743         break;
4744     }
4745     case _ep_blockpain:
4746     {
4747         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
4748         {
4749             ent->modeldata.blockpain = (int)ltemp;
4750         }
4751         break;
4752     }
4753     case _ep_boss:
4754     {
4755         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4756         (*pretvar)->lVal = (LONG)ent->boss;
4757         break;
4758     }
4759     case _ep_bounce:
4760     {
4761         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4762         (*pretvar)->lVal = (LONG)ent->modeldata.bounce;
4763         break;
4764     }
4765     case _ep_bound:
4766     {
4767         ScriptVariant_ChangeType(*pretvar, VT_PTR);
4768         (*pretvar)->ptrVal = (VOID *)ent->bound;
4769         break;
4770     }
4771     case _ep_candamage:
4772     {
4773         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4774         (*pretvar)->lVal = (LONG)ent->modeldata.candamage;
4775         break;
4776     }
4777     case _ep_combostep:
4778     {
4779         if(paramCount >= 3)
4780         {
4781             if(FAILED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
4782             {
4783                 *pretvar = NULL;
4784                 return E_FAIL;
4785             }
4786         }
4787         else
4788         {
4789             ltemp2 = 0;
4790         }
4791         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4792         (*pretvar)->lVal = (LONG)ent->combostep[(int)ltemp2];
4793         break;
4794     }
4795     case _ep_combotime:
4796     {
4797         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4798         (*pretvar)->lVal = (LONG)ent->combotime;
4799         break;
4800     }
4801     case _ep_hostile:
4802     {
4803         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4804         (*pretvar)->lVal = (LONG)ent->modeldata.hostile;
4805         break;
4806     }
4807     case _ep_projectilehit:
4808     {
4809         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4810         (*pretvar)->lVal = (LONG)ent->modeldata.projectilehit;
4811         break;
4812     }
4813     case _ep_chargerate:
4814     {
4815         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4816         (*pretvar)->lVal = (LONG)ent->modeldata.chargerate;
4817         break;
4818     }
4819     case _ep_colourmap:
4820     {
4821         ScriptVariant_ChangeType(*pretvar, VT_PTR);
4822         (*pretvar)->ptrVal = (VOID *)(ent->colourmap);
4823         break;
4824     }
4825     case _ep_colourtable:
4826     {
4827         ScriptVariant_ChangeType(*pretvar, VT_PTR);
4828         (*pretvar)->ptrVal = (VOID *)model_get_colourmap(&(ent->modeldata), varlist[2]->lVal + 1);
4829         break;
4830     }
4831     case _ep_damage_on_landing:
4832     {
4833         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4834         (*pretvar)->lVal = (LONG)ent->damage_on_landing;
4835         break;
4836     }
4837     case _ep_dead:
4838     {
4839         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4840         (*pretvar)->lVal = (LONG)ent->dead;
4841         break;
4842     }
4843     case _ep_defaultmodel:
4844     case _ep_defaultname:
4845     {
4846         ScriptVariant_ChangeType(*pretvar, VT_STR);
4847         StrCache_Copy((*pretvar)->strVal, ent->defaultmodel->name);
4848         break;
4849     }
4850     case _ep_defense:
4851     {
4852         ltemp = 0;
4853         if(paramCount >= 3)
4854         {
4855             if(FAILED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
4856             {
4857                 printf("You must specify an attack type for your defense property.\n");
4858                 *pretvar = NULL;
4859                 return E_FAIL;
4860             }
4861             ltemp2 = _ep_defense_factor;
4862         }
4863 
4864         if(paramCount >= 4)
4865         {
4866             if(FAILED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
4867             {
4868                 *pretvar = NULL;
4869                 return E_FAIL;
4870             }
4871         }
4872         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
4873 
4874         switch(ltemp2)
4875         {
4876         case _ep_defense_factor:
4877         {
4878             (*pretvar)->dblVal = (DOUBLE)ent->defense[(int)ltemp].factor;
4879             break;
4880         }
4881         case _ep_defense_blockpower:
4882         {
4883             (*pretvar)->dblVal = (DOUBLE)ent->defense[(int)ltemp].blockpower;
4884             break;
4885         }
4886         case _ep_defense_blockratio:
4887         {
4888             (*pretvar)->dblVal = (DOUBLE)ent->defense[(int)ltemp].blockratio;
4889             break;
4890         }
4891         case _ep_defense_blockthreshold:
4892         {
4893             (*pretvar)->dblVal = (DOUBLE)ent->defense[(int)ltemp].blockthreshold;
4894             break;
4895         }
4896         case _ep_defense_blocktype:
4897         {
4898             (*pretvar)->dblVal = (DOUBLE)ent->defense[(int)ltemp].blocktype;
4899             break;
4900         }
4901         case _ep_defense_knockdown:
4902         {
4903             (*pretvar)->dblVal = (DOUBLE)ent->defense[(int)ltemp].knockdown;
4904             break;
4905         }
4906         case _ep_defense_pain:
4907         {
4908             (*pretvar)->dblVal = (DOUBLE)ent->defense[(int)ltemp].pain;
4909             break;
4910         }
4911         default:
4912             *pretvar = NULL;
4913             return E_FAIL;
4914         }
4915         break;
4916     }
4917     case _ep_detect:
4918     {
4919         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4920         (*pretvar)->lVal = (LONG)ent->modeldata.stealth.detect;
4921         break;
4922     }
4923     case _ep_direction:
4924     {
4925         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4926         (*pretvar)->lVal = (LONG)ent->direction;
4927         break;
4928     }
4929     case _ep_dot:
4930     {
4931         if(paramCount < 4)
4932         {
4933             break;
4934         }
4935 
4936         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
4937         {
4938             i = (int)ltemp;
4939         }
4940 
4941         arg = varlist[3];
4942         if(arg->vt != VT_INTEGER)
4943         {
4944             printf("You must provide a string name for dot subproperty.\n\
4945 	~'time'\n\
4946 	~'mode'\n\
4947 	~'force'\n\
4948 	~'rate'\n\
4949 	~'type'\n\
4950 	~'owner'\n");
4951             *pretvar = NULL;
4952             return E_FAIL;
4953         }
4954         switch(arg->lVal)
4955         {
4956         case _ep_dot_time:
4957         {
4958             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4959             (*pretvar)->lVal = (LONG)ent->dot_time[i];
4960             break;
4961         }
4962         case _ep_dot_mode:
4963         {
4964             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4965             (*pretvar)->lVal = (LONG)ent->dot[i];
4966             break;
4967         }
4968         case _ep_dot_force:
4969 
4970         {
4971             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4972             (*pretvar)->lVal = (LONG)ent->dot_force[i];
4973             break;
4974         }
4975         case _ep_dot_rate:
4976         {
4977             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4978             (*pretvar)->lVal = (LONG)ent->dot_rate[i];
4979             break;
4980         }
4981         case _ep_dot_type:
4982         {
4983             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
4984             (*pretvar)->lVal = (LONG)ent->dot_atk[i];
4985             break;
4986         }
4987         case _ep_dot_owner:
4988         {
4989             ScriptVariant_ChangeType(*pretvar, VT_PTR);
4990             (*pretvar)->ptrVal = (VOID *)ent->dot_owner[i];
4991             break;
4992         }
4993         break;
4994         }
4995     }
4996     case _ep_dropframe:
4997     {
4998         ltemp = 0;
4999         if(paramCount == 3)
5000         {
5001             arg = varlist[2];
5002             if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
5003             {
5004                 ltemp = (LONG)0;
5005             }
5006         }
5007         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5008         (*pretvar)->lVal = (LONG)ent->modeldata.animation[ltemp]->dropframe;
5009         break;
5010     }
5011     case _ep_edelay:
5012     {
5013         arg = varlist[2];
5014         if(arg->vt != VT_INTEGER)
5015         {
5016             printf("You must provide a string name for edelay subproperty.\n\
5017 	~'cap_max'\n\
5018 	~'cap_min'\n\
5019 	~'factor'\n\
5020 	~'mode'\n\
5021 	~'range_max'\n\
5022 	~'range_min'\n");
5023             *pretvar = NULL;
5024             return E_FAIL;
5025         }
5026         ltemp = arg->lVal;
5027         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5028 
5029         switch(ltemp)
5030         {
5031         case _ep_edelay_mode:
5032         {
5033             (*pretvar)->lVal = (LONG)ent->modeldata.edelay.mode;
5034             break;
5035         }
5036         case _ep_edelay_factor:
5037         {
5038             (*pretvar)->dblVal = (float)ent->modeldata.edelay.factor;
5039             break;
5040         }
5041         case _ep_edelay_cap_min:
5042         {
5043             (*pretvar)->lVal = (LONG)ent->modeldata.edelay.cap_min;
5044             break;
5045         }
5046         case _ep_edelay_cap_max:
5047         {
5048             (*pretvar)->lVal = (LONG)ent->modeldata.edelay.cap_max;
5049             break;
5050         }
5051         case _ep_edelay_range_min:
5052         {
5053             (*pretvar)->lVal = (LONG)ent->modeldata.edelay.range_min;
5054             break;
5055         }
5056         case _ep_edelay_range_max:
5057         {
5058             (*pretvar)->lVal = (LONG)ent->modeldata.edelay.range_max;
5059             break;
5060         }
5061         default:
5062             *pretvar = NULL;
5063             return E_FAIL;
5064         }
5065         break;
5066     }
5067     case _ep_energycost:
5068     {
5069         if(paramCount < 4)
5070         {
5071             break;
5072         }
5073 
5074         if(varlist[2]->vt != VT_INTEGER)
5075         {
5076             printf("You must provide a string name for energycost.\n\
5077 	~'cost'\n\
5078 	~'disable'\n\
5079 	~'mponly'\n");
5080             *pretvar = NULL;
5081             return E_FAIL;
5082         }
5083         ltemp	= varlist[2]->lVal;												//Subproperty.
5084         i		= varlist[3]->lVal;												//Animation.
5085 
5086         if(!validanim(ent, i))													//Verify animation.
5087         {
5088             break;
5089         }
5090 
5091         switch(ltemp)
5092         {
5093         case _ep_energycost_cost:
5094             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5095             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->energycost.cost;
5096             break;
5097         case _ep_energycost_disable:
5098             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5099             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->energycost.disable;
5100             break;
5101         case _ep_energycost_mponly:
5102             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5103             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->energycost.mponly;
5104             break;
5105         default:
5106             *pretvar = NULL;
5107             return E_FAIL;
5108         }
5109         break;
5110     }
5111     case _ep_escapecount:
5112     {
5113         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5114         (*pretvar)->lVal = (LONG)ent->escapecount;
5115         break;
5116     }
5117     case _ep_escapehits:
5118     {
5119         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5120         (*pretvar)->lVal = (LONG)ent->modeldata.escapehits;
5121         break;
5122     }
5123     case _ep_exists:
5124     {
5125         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5126         (*pretvar)->lVal = (LONG)ent->exists;
5127         break;
5128     }
5129     case _ep_falldie:
5130     {
5131         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5132         (*pretvar)->lVal = (LONG)ent->modeldata.falldie;
5133         break;
5134     }
5135     case _ep_flash:
5136     {
5137         arg = varlist[2];
5138         if(arg->vt != VT_INTEGER)
5139         {
5140             printf("You must give a string name for flash property.\n");
5141             *pretvar = NULL;
5142             return E_FAIL;
5143         }
5144         ltemp = arg->lVal;
5145         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5146 
5147         switch(ltemp)
5148         {
5149         case _ep_flash_block:
5150         {
5151             i = ent->modeldata.bflash;
5152             break;
5153         }
5154         case _ep_flash_def:
5155         {
5156             i = ent->modeldata.flash;
5157             break;
5158         }
5159         case _ep_flash_noattack:
5160         {
5161             i = ent->modeldata.noatflash;
5162             break;
5163         }
5164         default:
5165         {
5166             *pretvar = NULL;
5167             return E_FAIL;
5168         }
5169         }
5170         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5171         (*pretvar)->lVal = (LONG)i;
5172         break;
5173     }
5174     case _ep_pain_time:
5175     {
5176         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5177         (*pretvar)->lVal = (LONG)ent->pain_time;
5178         break;
5179     }
5180     case _ep_freezetime:
5181     {
5182         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5183         (*pretvar)->lVal = (LONG)ent->freezetime;
5184         break;
5185     }
5186     case _ep_frozen:
5187     {
5188         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5189         (*pretvar)->lVal = (LONG)ent->frozen;
5190         break;
5191     }
5192     case _ep_gfxshadow:
5193     {
5194         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5195         (*pretvar)->lVal = (LONG)ent->modeldata.gfxshadow;
5196         break;
5197     }
5198     case _ep_grabbing:
5199     {
5200         if(ent->grabbing) // always return an empty var if it is NULL
5201         {
5202             ScriptVariant_ChangeType(*pretvar, VT_PTR);
5203             (*pretvar)->ptrVal = (VOID *)ent->grabbing;
5204         }
5205         break;
5206     }
5207     case _ep_grabforce:
5208     {
5209         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5210         (*pretvar)->lVal = (LONG)ent->modeldata.grabforce;
5211         break;
5212     }
5213     case _ep_guardpoints:
5214     {
5215         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5216         (*pretvar)->lVal = (LONG)ent->modeldata.guardpoints.current;
5217         break;
5218     }
5219     case _ep_health:
5220     {
5221         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5222         (*pretvar)->lVal = (LONG)ent->health;
5223         break;
5224     }
5225     case _ep_height:
5226     {
5227         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5228         (*pretvar)->lVal = (LONG)ent->modeldata.height;
5229         break;
5230     }
5231     case _ep_hitbyid:
5232     {
5233         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5234         (*pretvar)->lVal = (LONG)ent->hit_by_attack_id;
5235         break;
5236     }
5237     case _ep_hmapl:
5238     {
5239         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5240         (*pretvar)->lVal = (LONG)ent->modeldata.maps.hide_start;
5241         break;
5242     }
5243     case _ep_hmapu:
5244     {
5245         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5246         (*pretvar)->lVal = (LONG)ent->modeldata.maps.hide_end;
5247         break;
5248     }
5249     case _ep_icon:
5250     {
5251         arg = varlist[2];
5252         if(arg->vt != VT_INTEGER)
5253         {
5254             printf("You must provide a string name for icon subproperty:\n\
5255 	getentityproperty({ent}, 'icon', {subproperty});\n\
5256 	~'default'\n\
5257 	~'die'\n\
5258 	~'get'\n\
5259 	~'mphigh'\n\
5260 	~'mplow'\n\
5261 	~'mpmed'\n\
5262 	~'pain'\n\
5263 	~'weapon'\n\
5264 	~'x'\n\
5265 	~'y'\n");
5266             *pretvar = NULL;
5267             return E_FAIL;
5268         }
5269         ltemp = arg->lVal;
5270         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5271 
5272         switch(ltemp)
5273         {
5274         case _ep_icon_def:
5275         {
5276             i = ent->modeldata.icon.def;
5277             break;
5278         }
5279         case _ep_icon_die:
5280         {
5281             i = ent->modeldata.icon.die;
5282             break;
5283         }
5284         case _ep_icon_get:
5285         {
5286             i = ent->modeldata.icon.get;
5287             break;
5288         }
5289         case _ep_icon_mphigh:
5290         {
5291             i = ent->modeldata.icon.mphigh;
5292             break;
5293         }
5294         case _ep_icon_mplow:
5295         {
5296             i = ent->modeldata.icon.mplow;
5297             break;
5298         }
5299         case _ep_icon_mpmed:
5300         {
5301             i = ent->modeldata.icon.mpmed;
5302             break;
5303         }
5304         case _ep_icon_pain:
5305         {
5306             i = ent->modeldata.icon.pain;
5307             break;
5308         }
5309         case _ep_icon_weapon:
5310         {
5311             i = ent->modeldata.icon.weapon;
5312             break;
5313         }
5314         case _ep_icon_x:
5315         {
5316             i = ent->modeldata.icon.x;
5317             break;
5318         }
5319         case _ep_icon_y:
5320         {
5321             i = ent->modeldata.icon.y;
5322             break;
5323         }
5324         default:
5325         {
5326             *pretvar = NULL;
5327             return E_FAIL;
5328         }
5329         }
5330 
5331         if (i >= 0)
5332         {
5333             ScriptVariant_ChangeType(*pretvar, VT_PTR);
5334             spr = sprite_map[i].node->sprite;
5335             spr->centerx = sprite_map[i].centerx;
5336             spr->centery = sprite_map[i].centery;
5337             (*pretvar)->ptrVal = (VOID *)(spr);
5338         }
5339         else
5340         {
5341             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5342             (*pretvar)->lVal = -1;
5343         }
5344         break;
5345     }
5346     case _ep_invincible:
5347     {
5348         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5349         (*pretvar)->lVal = (LONG)ent->invincible;
5350         break;
5351     }
5352     case _ep_invinctime:
5353     {
5354         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5355         (*pretvar)->lVal = (LONG)ent->invinctime;
5356         break;
5357     }
5358     case _ep_jugglepoints:
5359     {
5360         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5361         (*pretvar)->lVal = (LONG)ent->modeldata.jugglepoints.current;
5362         break;
5363     }
5364     case _ep_jumpheight:
5365     {
5366         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5367         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.jumpheight;
5368         break;
5369     }
5370     case _ep_knockdowncount:
5371     {
5372         /*
5373         2011_04_14, DC: Backward compatability; default to current if subproperty not provided.
5374         */
5375         if(paramCount < 3)
5376         {
5377             ltemp = _ep_knockdowncount_current;
5378         }
5379         else
5380         {
5381             arg = varlist[2];
5382 
5383             if(arg->vt != VT_INTEGER)
5384             {
5385                 printf("You must provide a string name for knockdowncount subproperty:\n\
5386 		getentityproperty({ent}, 'knockdowncount', {subproperty})\n\
5387 		~'current'\n\
5388 		~'max'\n\
5389 		~'time'\n");
5390                 *pretvar = NULL;
5391                 return E_FAIL;
5392             }
5393 
5394             ltemp = arg->lVal;
5395         }
5396 
5397         switch(ltemp)
5398         {
5399         case _ep_knockdowncount_current:
5400             ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5401             (*pretvar)->dblVal = (DOUBLE)ent->knockdowncount;
5402             break;
5403         case _ep_knockdowncount_max:
5404             ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5405             (*pretvar)->dblVal = (DOUBLE)ent->modeldata.knockdowncount;
5406             break;
5407         case _ep_knockdowncount_time:
5408             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5409             (*pretvar)->lVal = (LONG)ent->knockdowncount;
5410             break;
5411         default:
5412             *pretvar = NULL;
5413             return E_FAIL;
5414         }
5415         break;
5416     }
5417     case _ep_komap:
5418     {
5419         if(paramCount < 2)
5420         {
5421             break;
5422         }
5423 
5424         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5425         (*pretvar)->lVal = (LONG)ent->modeldata.maps.ko;
5426         break;
5427     }
5428     case _ep_landframe:
5429     {
5430         if(paramCount < 4)
5431         {
5432             break;
5433         }
5434 
5435         if(varlist[2]->vt != VT_INTEGER
5436                 || varlist[3]->vt != VT_INTEGER)
5437         {
5438             printf("\n Error, getentityproperty({ent}, 'landframe', {sub property}, {animation}): {Sub property} or {Animation} parameter is missing or invalid. \n");
5439             *pretvar = NULL;
5440             return E_FAIL;
5441         }
5442         ltemp	= varlist[2]->lVal;												//Subproperty.
5443         i		= varlist[3]->lVal;												//Animation.
5444 
5445         if(!validanim(ent, i))													//Verify animation.
5446         {
5447             break;
5448         }
5449 
5450         switch(ltemp)
5451         {
5452         case _ep_landframe_ent:
5453             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5454             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->landframe.ent;
5455             break;
5456         case _ep_landframe_frame:
5457             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5458             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->landframe.frame;
5459             break;
5460         default:
5461             *pretvar = NULL;
5462             return E_FAIL;
5463         }
5464         break;
5465     }
5466     case _ep_lifespancountdown:
5467     {
5468         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5469         (*pretvar)->lVal = (LONG)ent->lifespancountdown;
5470         break;
5471     }
5472     case _ep_attackthrottle:
5473     {
5474         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5475         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.attackthrottle;
5476         break;
5477     }
5478     case _ep_attackthrottletime:
5479     {
5480         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5481         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.attackthrottletime;
5482         break;
5483     }
5484     case _ep_link:
5485     {
5486         if(ent->link) // always return an empty var if it is NULL
5487         {
5488             ScriptVariant_ChangeType(*pretvar, VT_PTR);
5489             (*pretvar)->ptrVal = (VOID *)ent->link;
5490         }
5491         break;
5492     }
5493     case _ep_map:
5494     {
5495         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5496         (*pretvar)->lVal = (LONG)0;
5497         for(i = 0; i < ent->modeldata.maps_loaded; i++)
5498         {
5499             if(ent->colourmap == ent->modeldata.colourmap[i])
5500             {
5501                 (*pretvar)->lVal = (LONG)(i + 1);
5502                 break;
5503             }
5504         }
5505         break;
5506     }
5507     case _ep_mapcount:
5508     {
5509         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5510         (*pretvar)->lVal = (LONG)(ent->modeldata.maps_loaded + 1);
5511         break;
5512     }
5513     case _ep_mapdefault:
5514     {
5515         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5516         (*pretvar)->lVal = (LONG)(ent->map);
5517         break;
5518     }
5519     case _ep_maps:
5520     {
5521         arg = varlist[2];
5522         if(arg->vt != VT_INTEGER)
5523         {
5524             printf("You must give a string name for maps property.\n");
5525             *pretvar = NULL;
5526             return E_FAIL;
5527         }
5528         ltemp = arg->lVal;
5529         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5530 
5531         switch(ltemp)
5532         {
5533         case _ep_maps_count:
5534         {
5535             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5536             (*pretvar)->lVal = (LONG)(ent->modeldata.maps_loaded + 1);
5537             break;
5538         }
5539 
5540         case _ep_maps_current:
5541         {
5542             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5543             (*pretvar)->lVal = (LONG)0;
5544             for(i = 0; i < ent->modeldata.maps_loaded; i++)
5545             {
5546                 if(ent->colourmap == ent->modeldata.colourmap[i])
5547                 {
5548                     (*pretvar)->lVal = (LONG)(i + 1);
5549                     break;
5550                 }
5551             }
5552             break;
5553         }
5554         case _ep_maps_dying:
5555         {
5556             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5557             (*pretvar)->lVal = (LONG)(ent->dying);
5558             break;
5559         }
5560         case _ep_maps_dying_critical:
5561         {
5562             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5563             (*pretvar)->lVal = (LONG)(ent->per2);
5564             break;
5565         }
5566         case _ep_maps_dying_low:
5567         {
5568             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5569             (*pretvar)->lVal = (LONG)(ent->per1);
5570             break;
5571         }
5572         case _ep_maps_frozen:
5573         {
5574             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5575             (*pretvar)->lVal = (LONG)(ent->modeldata.maps.frozen);
5576             break;
5577         }
5578         case _ep_maps_hide_end:
5579         {
5580             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5581             (*pretvar)->lVal = (LONG)(ent->modeldata.maps.hide_end);
5582             break;
5583         }
5584         case _ep_maps_hide_start:
5585         {
5586             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5587             (*pretvar)->lVal = (LONG)(ent->modeldata.maps.hide_start);
5588             break;
5589         }
5590         case _ep_maps_ko:
5591         {
5592             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5593             (*pretvar)->lVal = (LONG)(ent->modeldata.maps.ko);
5594             break;
5595         }
5596         case _ep_maps_kotype:
5597         {
5598             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5599             (*pretvar)->lVal = (LONG)(ent->modeldata.maps.kotype);
5600             break;
5601         }
5602         case _ep_maps_table:
5603         {
5604             ScriptVariant_ChangeType(*pretvar, VT_PTR);
5605             (*pretvar)->ptrVal = (VOID *)(ent->colourmap);
5606             break;
5607         }
5608         case _ep_maps_time:
5609         {
5610             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5611             (*pretvar)->lVal = (LONG)(ent->maptime);
5612             break;
5613         }
5614         default:
5615         {
5616             *pretvar = NULL;
5617             return E_FAIL;
5618         }
5619         }
5620         break;
5621     }
5622     case _ep_maxguardpoints:
5623     {
5624         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5625         (*pretvar)->lVal = (LONG)ent->modeldata.guardpoints.maximum;
5626         break;
5627     }
5628     case _ep_maxhealth:
5629     {
5630         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5631         (*pretvar)->lVal = (LONG)ent->modeldata.health;
5632         break;
5633     }
5634     case _ep_maxjugglepoints:
5635     {
5636         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5637         (*pretvar)->lVal = (LONG)ent->modeldata.jugglepoints.maximum;
5638         break;
5639     }
5640     case _ep_maxmp:
5641     {
5642         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5643         (*pretvar)->lVal = (LONG)ent->modeldata.mp;
5644         break;
5645     }
5646     case _ep_model:
5647     {
5648         ScriptVariant_ChangeType(*pretvar, VT_STR);
5649         StrCache_Copy((*pretvar)->strVal, ent->model->name);
5650         break;
5651     }
5652     case _ep_mp:
5653     {
5654         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5655         (*pretvar)->lVal = (LONG)ent->mp;
5656         break;
5657     }
5658     case _ep_mpdroprate:
5659     {
5660         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5661         (*pretvar)->lVal = (LONG)ent->modeldata.mpdroprate;
5662         break;
5663     }
5664     case _ep_mprate:
5665     {
5666         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5667         (*pretvar)->lVal = (LONG)ent->modeldata.mprate;
5668         break;
5669     }
5670     case _ep_mpstable:
5671     {
5672         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5673         (*pretvar)->lVal = (LONG)ent->modeldata.mpstable;
5674         break;
5675     }
5676     case _ep_mpstableval:
5677     {
5678         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5679         (*pretvar)->lVal = (LONG)ent->modeldata.mpstableval;
5680         break;
5681     }
5682     case _ep_name:
5683     {
5684         ScriptVariant_ChangeType(*pretvar, VT_STR);
5685         StrCache_Copy((*pretvar)->strVal, ent->name);
5686         break;
5687     }
5688     case _ep_nextanim:
5689     {
5690         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5691         (*pretvar)->lVal = (LONG)ent->nextanim;
5692         break;
5693     }
5694     case _ep_nextmove:
5695     {
5696         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5697         (*pretvar)->lVal = (LONG)ent->nextmove;
5698         break;
5699     }
5700     case _ep_nextthink:
5701     {
5702         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5703         (*pretvar)->lVal = (LONG)ent->nextthink;
5704         break;
5705     }
5706     case _ep_no_adjust_base:
5707     {
5708         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5709         (*pretvar)->lVal = (LONG)ent->modeldata.no_adjust_base;
5710         break;
5711     }
5712     case _ep_noaicontrol:
5713     {
5714         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5715         (*pretvar)->lVal = (LONG)ent->noaicontrol;
5716         break;
5717     }
5718     case _ep_nodieblink:
5719     {
5720         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5721         (*pretvar)->lVal = (LONG)ent->modeldata.nodieblink;
5722         break;
5723     }
5724     case _ep_nodrop:
5725     {
5726         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5727         (*pretvar)->lVal = (LONG)ent->modeldata.nodrop;
5728         break;
5729     }
5730     case _ep_nograb:
5731     {
5732         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5733         (*pretvar)->lVal = (LONG)ent->nograb;
5734         break;
5735     }
5736     case _ep_nolife:
5737     {
5738         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5739         (*pretvar)->lVal = (LONG)ent->modeldata.nolife;
5740         break;
5741     }
5742     case _ep_nopain:
5743     {
5744         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5745         (*pretvar)->lVal = (LONG)ent->modeldata.nopain;
5746         break;
5747     }
5748     case _ep_offense:
5749     {
5750         ltemp = 0;
5751         if(paramCount >= 3)
5752         {
5753             arg = varlist[2];
5754             if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
5755             {
5756                 ltemp = (LONG)0;
5757             }
5758         }
5759         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5760         (*pretvar)->dblVal = (DOUBLE)ent->offense_factors[(int)ltemp];
5761         break;
5762     }
5763     case _ep_opponent:
5764     {
5765         if(ent->opponent) // always return an empty var if it is NULL
5766         {
5767             ScriptVariant_ChangeType(*pretvar, VT_PTR);
5768             (*pretvar)->ptrVal = (VOID *)ent->opponent;
5769         }
5770         break;
5771     }
5772     case _ep_owner:
5773     {
5774         if(ent->owner) // always return an empty var if it is NULL
5775         {
5776             ScriptVariant_ChangeType(*pretvar, VT_PTR);
5777             (*pretvar)->ptrVal = (VOID *)ent->owner;
5778         }
5779         break;
5780     }
5781     case _ep_parent:
5782     {
5783         if(ent->parent) // always return an empty var if it is NULL
5784         {
5785             ScriptVariant_ChangeType(*pretvar, VT_PTR);
5786             (*pretvar)->ptrVal = (VOID *)ent->parent;
5787         }
5788         break;
5789     }
5790     case _ep_path:
5791     {
5792         ScriptVariant_ChangeType(*pretvar, VT_STR);
5793         tempstr = ent->modeldata.path;
5794 
5795         StrCache_Copy((*pretvar)->strVal, tempstr);
5796         break;
5797     }
5798     case _ep_pathfindstep:
5799     {
5800         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5801         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.pathfindstep;
5802         //printf("%d %s %d\n", ent->sortid, ent->name, ent->playerindex);
5803         break;
5804     }
5805     case _ep_playerindex:
5806     {
5807         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5808         (*pretvar)->lVal = (LONG)ent->playerindex;
5809         //printf("%d %s %d\n", ent->sortid, ent->name, ent->playerindex);
5810         break;
5811     }
5812     case _ep_projectile:
5813     {
5814         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5815         (*pretvar)->lVal = (LONG)ent->projectile;
5816         break;
5817     }
5818     case _ep_range:
5819     {
5820         if(paramCount < 4)
5821         {
5822             break;
5823         }
5824 
5825         if(varlist[2]->vt != VT_INTEGER
5826                 || varlist[3]->vt != VT_INTEGER)
5827         {
5828             printf("\n Error, getentityproperty({ent}, 'range', {sub property}, {animation}): {Sub property} or {Animation} parameter is missing or invalid. \n");
5829             *pretvar = NULL;
5830             return E_FAIL;
5831         }
5832         ltemp	= varlist[2]->lVal;												//Subproperty.
5833         i		= varlist[3]->lVal;												//Animation.
5834 
5835         if(!validanim(ent, i))													//Verify animation.
5836         {
5837             break;
5838         }
5839 
5840         switch(ltemp)
5841         {
5842         case _ep_range_amax:
5843             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5844             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.amax;
5845             break;
5846         case _ep_range_amin:
5847             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5848             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.amin;
5849             break;
5850         case _ep_range_bmax:
5851             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5852             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.bmax;
5853             break;
5854         case _ep_range_bmin:
5855             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5856             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.bmin;
5857             break;
5858         case _ep_range_xmax:
5859             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5860             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.xmax;
5861             break;
5862         case _ep_range_xmin:
5863             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5864             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.xmin;
5865             break;
5866         case _ep_range_zmax:
5867             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5868             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.zmax;
5869             break;
5870         case _ep_range_zmin:
5871             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5872             (*pretvar)->lVal = (LONG)ent->modeldata.animation[i]->range.zmin;
5873             break;
5874         default:
5875             *pretvar = NULL;
5876             return E_FAIL;
5877         }
5878         break;
5879 
5880         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5881         (*pretvar)->lVal = (LONG)coords[varlist[4]->lVal];
5882         break;
5883     }
5884     case _ep_running:
5885     {
5886         if(paramCount < 3)
5887         {
5888             break;
5889         }
5890         arg = varlist[2];
5891         if(arg->vt != VT_INTEGER)
5892         {
5893             printf("You must give a string name for running property.\n");
5894             *pretvar = NULL;
5895             return E_FAIL;
5896         }
5897         ltemp = arg->lVal;
5898         switch(ltemp)
5899         {
5900         case _ep_running_speed:
5901         {
5902             ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5903             (*pretvar)->dblVal = (DOUBLE)ent->modeldata.runspeed;
5904             break;
5905         }
5906         case _ep_running_jumpy:
5907         {
5908             ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5909             (*pretvar)->dblVal = (DOUBLE)ent->modeldata.runjumpheight;
5910             break;
5911         }
5912         case _ep_running_jumpx:
5913         {
5914             ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5915             (*pretvar)->dblVal = (DOUBLE)ent->modeldata.runjumpdist;
5916             break;
5917         }
5918         case _ep_running_land:
5919         {
5920             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5921             (*pretvar)->lVal = (LONG)ent->modeldata.runhold;
5922             break;
5923         }
5924         case _ep_running_movez:
5925         {
5926             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5927             (*pretvar)->lVal = (LONG)ent->modeldata.runupdown;
5928             break;
5929         }
5930         }
5931         break;
5932     }
5933     case _ep_rush_count:
5934     {
5935         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5936         (*pretvar)->lVal = (LONG)ent->rush[0];
5937         break;
5938     }
5939     case _ep_rush_tally:
5940     {
5941         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5942         (*pretvar)->lVal = (LONG)ent->rush[1];
5943         break;
5944     }
5945     case _ep_rush_time:
5946     {
5947         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5948         (*pretvar)->lVal = (LONG)ent->rushtime;
5949         break;
5950     }
5951     case _ep_score:
5952     {
5953         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5954         (*pretvar)->lVal = (LONG)ent->modeldata.score;
5955         break;
5956     }
5957     case _ep_scroll:
5958     {
5959         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5960         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.scroll;
5961         break;
5962     }
5963     case _ep_seal:
5964     {
5965         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5966         (*pretvar)->lVal = (LONG)ent->seal;
5967         break;
5968     }
5969     case _ep_sealtime:
5970     {
5971         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5972         (*pretvar)->lVal = (LONG)ent->sealtime;
5973         break;
5974     }
5975     case _ep_setlayer:
5976     {
5977         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5978         (*pretvar)->lVal = (LONG)ent->modeldata.setlayer;
5979         break;
5980     }
5981     case _ep_sortid:
5982     {
5983         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5984         (*pretvar)->lVal = (LONG)ent->sortid;
5985         break;
5986     }
5987     case _ep_spawntype:
5988     {
5989         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
5990         (*pretvar)->lVal = (LONG)ent->spawntype;
5991         break;
5992     }
5993     case _ep_speed:
5994     {
5995         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
5996         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.speed;
5997         break;
5998     }
5999     case _ep_sprite:
6000     {
6001         ScriptVariant_ChangeType(*pretvar, VT_PTR);
6002         i = ent->animation->sprite[ent->animpos];
6003         spr = sprite_map[i].node->sprite;
6004         spr->centerx = sprite_map[i].centerx;
6005         spr->centery = sprite_map[i].centery;
6006         (*pretvar)->ptrVal = (VOID *)(spr);
6007         break;
6008     }
6009     case _ep_spritea:
6010     {
6011         /*
6012         2011_04_17, DC: Modder can now specify animation and frame to return sprite from.
6013         To retain backward compatibility, sprite from current animation/frame is returned
6014         when animation and/or frame parameters are not provided.
6015         */
6016 
6017         ltemp   = varlist[2]->lVal;
6018         arg     = varlist[3];
6019         arg1    = varlist[4];
6020 
6021         /*
6022         Request from animation or frame that doesn't exist = shutdown.
6023         Let's be more user friendly then that; return empty so modder can evaluate
6024         and take action accordingly.*/
6025         if(!validanim(ent, arg->lVal) || !(ent->modeldata.animation[arg->lVal]->numframes >= arg1->lVal))
6026         {
6027             break;
6028         }
6029 
6030         i = ent->modeldata.animation[arg->lVal]->sprite[arg1->lVal];
6031 
6032         switch(ltemp)
6033         {
6034         case _ep_spritea_centerx:
6035         {
6036             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6037             (*pretvar)->lVal = (LONG)sprite_map[i].centerx;
6038             break;
6039         }
6040         case _ep_spritea_centery:
6041         {
6042             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6043             (*pretvar)->lVal = (LONG)sprite_map[i].centery;
6044             break;
6045         }
6046         case _ep_spritea_file:
6047         {
6048             ScriptVariant_ChangeType(*pretvar, VT_STR);
6049             StrCache_Copy((*pretvar)->strVal, sprite_map[i].node->filename);
6050             break;
6051         }
6052         case _ep_spritea_sprite:
6053         {
6054             ScriptVariant_ChangeType(*pretvar, VT_PTR);
6055             spr = sprite_map[i].node->sprite;
6056             spr->centerx = sprite_map[i].centery;
6057             spr->centery = sprite_map[i].centery;
6058             (*pretvar)->ptrVal = (VOID *)(spr);
6059             break;
6060         }
6061         default:
6062         {
6063             *pretvar = NULL;
6064             return E_FAIL;
6065         }
6066         }
6067 
6068         break;
6069 
6070     }
6071     case _ep_stalltime:
6072     {
6073         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6074         (*pretvar)->lVal = (LONG)ent->stalltime;
6075         break;
6076     }
6077     case _ep_releasetime:
6078     {
6079         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6080         (*pretvar)->lVal = (LONG)ent->releasetime;
6081         break;
6082     }
6083     case _ep_stats:
6084     {
6085         if(paramCount < 4)
6086         {
6087             break;
6088         }
6089         arg = varlist[2];
6090         arg1 = varlist[3];
6091 
6092         if(arg->vt != VT_INTEGER || arg1->vt != VT_INTEGER)
6093         {
6094             printf("Incorrect parameters: getentityproperty({ent}, 'stats', {type}, {index}) \n {type}: \n 0 = Model. \n 1 = Entity. \n");
6095             *pretvar = NULL;
6096             return E_FAIL;
6097         }
6098 
6099         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
6100 
6101         switch(arg->lVal)
6102         {
6103         default:
6104             if (ent->modeldata.stats[arg1->lVal])
6105             {
6106                 (*pretvar)->dblVal = (DOUBLE)ent->modeldata.stats[arg1->lVal];
6107             }
6108             break;
6109         case 1:
6110             if (ent->stats[arg1->lVal])
6111             {
6112                 (*pretvar)->dblVal = (DOUBLE)ent->stats[arg1->lVal];
6113             }
6114             break;
6115         }
6116         break;
6117     }
6118     case _ep_staydown:
6119     {
6120         arg = varlist[2];
6121         if(arg->vt != VT_INTEGER)
6122         {
6123 
6124             printf("You must provide a string name for staydown property:\n\
6125 	getentityproperty({ent}, 'staydown', {subproperty})\n\
6126 	~'rise'\n\
6127 	~'riseattack'\n\
6128 	~'riseattack_stall' \n");
6129             *pretvar = NULL;
6130             return E_FAIL;
6131         }
6132         ltemp = arg->lVal;
6133         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6134 
6135         switch(ltemp)
6136         {
6137         case _ep_staydown_rise:
6138         {
6139             i = ent->staydown.rise;
6140             break;
6141         }
6142         case _ep_staydown_riseattack:
6143         {
6144             i = ent->staydown.riseattack;
6145             break;
6146         }
6147         case _ep_staydown_riseattack_stall:
6148         {
6149             i = ent->staydown.riseattack_stall;
6150             break;
6151         }
6152         default:
6153         {
6154             *pretvar = NULL;
6155             return E_FAIL;
6156         }
6157         }
6158         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6159         (*pretvar)->lVal = (LONG)i;
6160         break;
6161     }
6162     case _ep_stealth:
6163     {
6164         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6165         (*pretvar)->lVal = (LONG)ent->modeldata.stealth.hide;
6166         break;
6167     }
6168     case _ep_subentity:
6169     {
6170         if(ent->subentity) // always return an empty var if it is NULL
6171         {
6172             ScriptVariant_ChangeType(*pretvar, VT_PTR);
6173             (*pretvar)->ptrVal = (VOID *)ent->subentity;
6174         }
6175         break;
6176     }
6177     case _ep_subject_to_gravity:
6178     {
6179         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6180         (*pretvar)->lVal = (LONG)ent->modeldata.subject_to_gravity;
6181         break;
6182     }
6183     case _ep_subject_to_hole:
6184     {
6185         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6186         (*pretvar)->lVal = (LONG)ent->modeldata.subject_to_hole;
6187         break;
6188     }
6189     case _ep_subject_to_maxz:
6190     {
6191         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6192         (*pretvar)->lVal = (LONG)ent->modeldata.subject_to_maxz;
6193         break;
6194     }
6195     case _ep_subject_to_minz:
6196     {
6197         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6198         (*pretvar)->lVal = (LONG)ent->modeldata.subject_to_minz;
6199         break;
6200     }
6201     case _ep_subject_to_obstacle:
6202     {
6203         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6204         (*pretvar)->lVal = (LONG)ent->modeldata.subject_to_obstacle;
6205         break;
6206     }
6207     case _ep_subject_to_platform:
6208     {
6209         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6210         (*pretvar)->lVal = (LONG)ent->modeldata.subject_to_platform;
6211         break;
6212     }
6213     case _ep_subject_to_screen:
6214     {
6215         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6216         (*pretvar)->lVal = (LONG)ent->modeldata.subject_to_screen;
6217         break;
6218     }
6219     case _ep_subject_to_wall:
6220     {
6221         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6222         (*pretvar)->lVal = (LONG)ent->modeldata.subject_to_wall;
6223         break;
6224     }
6225     case _ep_subtype:
6226     {
6227         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6228         (*pretvar)->lVal = (LONG)ent->modeldata.subtype;
6229         break;
6230     }
6231     case _ep_thold:
6232     {
6233         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6234         (*pretvar)->lVal = (LONG)ent->modeldata.thold;
6235         break;
6236     }
6237     case _ep_throwdamage:
6238     {
6239         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6240         (*pretvar)->lVal = (LONG)ent->modeldata.throwdamage;
6241         break;
6242     }
6243     case _ep_throwdist:
6244     {
6245         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
6246         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.throwdist;
6247         break;
6248     }
6249     case _ep_throwframewait:
6250     {
6251         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6252         (*pretvar)->lVal = (LONG)ent->modeldata.throwframewait;
6253         break;
6254     }
6255     case _ep_throwheight:
6256     {
6257         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
6258         (*pretvar)->dblVal = (DOUBLE)ent->modeldata.throwheight;
6259         break;
6260     }
6261     case _ep_tosstime:
6262     {
6263         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6264         (*pretvar)->lVal = (LONG)ent->toss_time;
6265         break;
6266     }
6267     case _ep_tossv:
6268     {
6269         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
6270         (*pretvar)->dblVal = (DOUBLE)ent->tossv;
6271         break;
6272     }
6273     case _ep_type:
6274     {
6275         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
6276         (*pretvar)->lVal = (LONG)ent->modeldata.type;
6277         break;
6278     }
6279     case _ep_weapent:
6280     {
6281         ScriptVariant_ChangeType(*pretvar, VT_PTR);
6282         (*pretvar)->ptrVal = (VOID *)ent->weapent;
6283         break;
6284     }
6285     case _ep_x:
6286     {
6287         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
6288         (*pretvar)->dblVal = (DOUBLE)ent->x;
6289         break;
6290     }
6291     case _ep_xdir:
6292     {
6293         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
6294         (*pretvar)->dblVal = (DOUBLE)ent->xdir;
6295         break;
6296     }
6297     case _ep_z:
6298     {
6299         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
6300         (*pretvar)->dblVal = (DOUBLE)ent->z;
6301         break;
6302     }
6303     case _ep_zdir:
6304     {
6305         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
6306         (*pretvar)->dblVal = (DOUBLE)ent->zdir;
6307         break;
6308     }
6309     default:
6310         //printf("Property name '%s' is not supported by function getentityproperty.\n", propname);
6311         *pretvar = NULL;
6312         return E_FAIL;
6313         break;
6314     }
6315 
6316     return S_OK;
6317 }
6318 
6319 
6320 //changeentityproperty(pentity, propname, value1[ ,value2, value3, ...]);
openbor_changeentityproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)6321 HRESULT openbor_changeentityproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
6322 {
6323     entity *ent = NULL;
6324     s_model *tempmodel ;
6325     char *tempstr = NULL;
6326     LONG ltemp, ltemp2;
6327     DOUBLE dbltemp;
6328     int propind;
6329     int i = 0;
6330 
6331     static const void *actions[] =   // for takeaction
6332     {
6333         bomb_explode,
6334         common_attack_proc,
6335         common_block,
6336         common_drop,
6337         common_fall,
6338         common_get,
6339         common_grab,
6340         common_grabattack,
6341         common_grabbed,
6342         common_jump,
6343         common_land,
6344         common_lie,
6345         common_pain,
6346         common_prejump,
6347         common_rise,
6348         common_spawn,
6349         common_turn,
6350         common_vault,
6351         normal_prepare,
6352         npc_warp,
6353         player_blink,
6354         suicide,
6355     };
6356 
6357     static const int entitytypes[] =
6358     {
6359         0, // "ground"; not a real entity type
6360         TYPE_ENEMY,
6361         TYPE_NPC,
6362         TYPE_OBSTACLE,
6363         TYPE_PLAYER,
6364         TYPE_SHOT,
6365 
6366     };
6367 
6368     static const void *think[] =   // 2011_03_03, DC: Think types.
6369     {
6370         common_think,
6371         player_think,
6372         steam_think,
6373         steamer_think,
6374         text_think,
6375         trap_think,
6376     };
6377 
6378     *pretvar = NULL;
6379 
6380     if(paramCount < 3)
6381     {
6382         printf("Function changeentityproperty must have have at least 3 parameters.");
6383         goto changeentityproperty_error;
6384     }
6385 
6386     mapstrings_entityproperty(varlist, paramCount);
6387 
6388     if(varlist[0]->vt != VT_PTR && varlist[0]->vt != VT_EMPTY)
6389     {
6390         printf("Function changeentityproperty must have a valid entity handle.");
6391         goto changeentityproperty_error;
6392     }
6393     ent = (entity *)varlist[0]->ptrVal; //retrieve the entity
6394     if(!ent)
6395     {
6396         return S_OK;
6397     }
6398 
6399     if(varlist[1]->vt != VT_INTEGER)
6400     {
6401         if(varlist[1]->vt != VT_STR)
6402         {
6403             printf("Function changeentityproperty must have a string property name.\n");
6404         }
6405         goto changeentityproperty_error;
6406     }
6407 
6408     propind = varlist[1]->lVal;
6409 
6410     switch(propind)
6411     {
6412     case _ep_aggression:
6413     {
6414         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6415         {
6416             ent->modeldata.aggression = (int)ltemp;
6417         }
6418         break;
6419     }
6420     case _ep_aiattack:
6421     {
6422         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6423         {
6424             ent->modeldata.aiattack = (int)ltemp;
6425         }
6426         break;
6427     }
6428     case _ep_aiflag:
6429     {
6430         if(varlist[2]->vt != VT_INTEGER)
6431         {
6432             if(varlist[2]->vt != VT_STR)
6433             {
6434                 printf("You must give a string value for AI flag name.\n");
6435             }
6436             goto changeentityproperty_error;
6437         }
6438         if(paramCount < 4)
6439         {
6440             break;
6441         }
6442 
6443         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6444         {
6445             switch(varlist[2]->lVal)
6446             {
6447             case _ep_aiflag_dead:
6448                 ent->dead = (int)ltemp;
6449                 break;
6450             case _ep_aiflag_jumpid:
6451                 ent->jumpid = (int)ltemp;
6452                 break;
6453             case _ep_aiflag_jumping:
6454                 ent->jumping = (int)ltemp;
6455                 break;
6456             case _ep_aiflag_idling:
6457                 ent->idling = (int)ltemp;
6458                 break;
6459             case _ep_aiflag_drop:
6460                 ent->drop = (int)ltemp;
6461                 break;
6462             case _ep_aiflag_attacking:
6463                 ent->attacking = (int)ltemp;
6464                 break;
6465             case _ep_aiflag_getting:
6466                 ent->getting = (int)ltemp;
6467                 break;
6468             case _ep_aiflag_turning:
6469                 ent->turning = (int)ltemp;
6470                 break;
6471             case _ep_aiflag_charging:
6472                 ent->charging = (int)ltemp;
6473                 break;
6474             case _ep_aiflag_blocking:
6475                 ent->blocking = (int)ltemp;
6476                 break;
6477             case _ep_aiflag_falling:
6478                 ent->falling = (int)ltemp;
6479                 break;
6480             case _ep_aiflag_running:
6481                 ent->running = (int)ltemp;
6482                 break;
6483             case _ep_aiflag_inpain:
6484                 ent->inpain = (int)ltemp;
6485                 break;
6486             case _ep_aiflag_projectile:
6487                 ent->projectile = (int)ltemp;
6488                 break;
6489             case _ep_aiflag_frozen:
6490                 ent->frozen = (int)ltemp;
6491                 break;
6492             case _ep_aiflag_toexplode:
6493                 ent->toexplode = (int)ltemp;
6494                 break;
6495             case _ep_aiflag_animating:
6496                 ent->animating = (int)ltemp;
6497                 break;
6498             case _ep_aiflag_blink:
6499                 ent->blink = (int)ltemp;
6500                 break;
6501             case _ep_aiflag_invincible:
6502                 ent->invincible = (int)ltemp;
6503                 break;
6504             case _ep_aiflag_autokill:
6505                 ent->autokill = (int)ltemp;
6506                 break;
6507             case _ep_aiflag_idlemode:
6508                 ent->idlemode = (int)ltemp;
6509                 break;
6510             case _ep_aiflag_walkmode:
6511                 ent->walkmode = (int)ltemp;
6512                 break;
6513             case _ep_aiflag_walking:
6514                 break;
6515             default:
6516                 printf("Unknown AI flag.\n");
6517                 goto changeentityproperty_error;
6518             }
6519         }
6520         break;
6521     }
6522     case _ep_aimove:
6523     {
6524         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6525         {
6526             ent->modeldata.aimove = (int)ltemp;
6527         }
6528         break;
6529     }
6530     case _ep_alpha:
6531     {
6532         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6533         {
6534             ent->modeldata.alpha = (int)ltemp;
6535         }
6536         break;
6537     }
6538     case _ep_animation:
6539     {
6540         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6541         {
6542             ltemp2 = (LONG)1;
6543             if(paramCount < 4 || SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
6544             {
6545                 ent_set_anim(ent, (int)ltemp, (int)ltemp2);
6546             }
6547         }
6548         break;
6549     }
6550     case _ep_animhits:
6551     {
6552         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6553         {
6554             ent->animation->animhits = (int)ltemp;
6555         }
6556         break;
6557     }
6558     case _ep_animpos:
6559     {
6560         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6561         {
6562             ent->animpos = (int)ltemp;
6563         }
6564         break;
6565     }
6566     case _ep_antigrab:
6567     {
6568         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6569         {
6570             ent->modeldata.antigrab = (int)ltemp;
6571         }
6572         break;
6573     }
6574     case _ep_antigravity:
6575     {
6576         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6577         {
6578             ent->modeldata.antigravity = (float)dbltemp;
6579         }
6580         break;
6581     }
6582     case _ep_attacking:
6583     {
6584         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6585         {
6586             ent->attacking = (int)ltemp;
6587         }
6588         break;
6589     }
6590     case _ep_attackid:
6591     {
6592         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6593         {
6594             ent->attack_id = (int)ltemp;
6595         }
6596         break;
6597     }
6598     case _ep_autokill:
6599     {
6600         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6601         {
6602             ent->autokill = (int)ltemp;
6603         }
6604         break;
6605     }
6606     case _ep_base:
6607     {
6608         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6609         {
6610             ent->base = (float)dbltemp;
6611         }
6612         break;
6613     }
6614     case _ep_blink:
6615     {
6616         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6617         {
6618             ent->blink = (int)ltemp;
6619         }
6620         break;
6621     }
6622     case _ep_blockback:
6623     {
6624         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6625         {
6626             ent->modeldata.blockback = (int)ltemp;
6627         }
6628         break;
6629     }
6630     case _ep_blockodds:
6631     {
6632         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6633         {
6634             ent->modeldata.blockodds = (int)ltemp;
6635         }
6636         break;
6637     }
6638     case _ep_blockpain:
6639     {
6640         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6641         {
6642             ent->modeldata.blockpain = (int)ltemp;
6643         }
6644         break;
6645     }
6646     case _ep_boss:
6647     {
6648         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6649         {
6650             ent->boss = (int)ltemp;
6651         }
6652         break;
6653     }
6654     case _ep_bounce:
6655     {
6656         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6657         {
6658             ent->modeldata.bounce = (int)ltemp;
6659         }
6660         break;
6661     }
6662     case _ep_candamage:
6663     {
6664         ent->modeldata.candamage = 0;
6665 
6666         for(i = 2; i < paramCount; i++)
6667         {
6668             if(varlist[i]->vt == VT_INTEGER) // known entity type
6669             {
6670                 ltemp = varlist[i]->lVal;
6671                 if(ltemp == (_ep_hcd_ground | 0x80000000)) // "ground" - not needed?
6672                 {
6673                     ent->modeldata.ground = 1;
6674                 }
6675                 else if(ltemp & 0x80000000)
6676                 {
6677                     ent->modeldata.candamage |= entitytypes[ltemp & 0x7fffffff];
6678                 }
6679                 else
6680                 {
6681                     ent->modeldata.candamage |= ltemp;
6682                 }
6683             }
6684             else
6685             {
6686                 printf("You must pass one or more string constants for candamage entity type.\n");
6687                 goto changeentityproperty_error;
6688             }
6689         }
6690         break;
6691     }
6692     case _ep_combostep:
6693     {
6694         if(paramCount >= 4 &&
6695                 SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) &&
6696                 SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
6697         {
6698             ent->combostep[(int)ltemp] = (int)ltemp2;
6699         }
6700         break;
6701     }
6702     case _ep_combotime:
6703     {
6704         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6705         {
6706             ent->combotime = (int)ltemp;
6707         }
6708         break;
6709     }
6710     case _ep_colourmap:
6711     {
6712         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6713         {
6714             ent->colourmap = (VOID *)model_get_colourmap(&(ent->modeldata), ltemp);
6715         }
6716         break;
6717     }
6718     case _ep_damage_on_landing:
6719     {
6720         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6721         {
6722             ent->damage_on_landing = (int)ltemp;
6723         }
6724         break;
6725     }
6726     case _ep_dead:
6727     {
6728         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6729         {
6730             ent->dead = (int)ltemp;
6731         }
6732         break;
6733     }
6734     case _ep_defaultname:
6735     {
6736         if(varlist[2]->vt != VT_STR)
6737         {
6738             printf("You must give a string value for entity name.\n");
6739             goto changeentityproperty_error;
6740         }
6741         tempmodel = findmodel((char *)StrCache_Get(varlist[2]->strVal));
6742         if(!tempmodel)
6743         {
6744             printf("Use must give an existing model's name for entity's default model name.\n");
6745             goto changeentityproperty_error;
6746         }
6747         ent->defaultmodel = tempmodel;
6748         break;
6749     }
6750     case _ep_defense:
6751     {
6752         if((ltemp2 =
6753                     (paramCount >= 4 &&
6754                      SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) &&
6755                      ltemp < (LONG)MAX_ATKS && ltemp >= (LONG)0 &&
6756                      SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6757            ))
6758         {
6759             ent->defense[(int)ltemp].factor = (float)dbltemp;
6760         }
6761 
6762         if(paramCount >= 5 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp))))
6763         {
6764             ent->defense[(int)ltemp].pain = (float)dbltemp;
6765         }
6766         if(paramCount >= 6 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp))))
6767         {
6768             ent->defense[(int)ltemp].knockdown = (float)dbltemp;
6769         }
6770         if(paramCount >= 7 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[6], &dbltemp))))
6771         {
6772             ent->defense[(int)ltemp].blockpower = (float)dbltemp;
6773         }
6774         if(paramCount >= 8 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[7], &dbltemp))))
6775         {
6776             ent->defense[(int)ltemp].blockthreshold = (float)dbltemp;
6777         }
6778         if(paramCount >= 9 && ltemp2 && (ltemp2 = SUCCEEDED(ScriptVariant_DecimalValue(varlist[8], &dbltemp))))
6779         {
6780             ent->defense[(int)ltemp].blockratio = (float)dbltemp;
6781         }
6782         if(paramCount >= 10 && ltemp2 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[9], &dbltemp)))
6783         {
6784             ent->defense[(int)ltemp].blocktype = (float)dbltemp;
6785         }
6786 
6787         break;
6788     }
6789     case _ep_detect:
6790     {
6791         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6792         {
6793             ent->modeldata.stealth.detect = (int)ltemp;
6794         }
6795         break;
6796     }
6797     case _ep_direction:
6798     {
6799         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
6800         {
6801             ent->direction = (int)dbltemp;
6802         }
6803         break;
6804     }
6805     case _ep_dot:
6806     {
6807         if((SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp))))
6808         {
6809             i = (int)ltemp;
6810             if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6811             {
6812                 ent->dot_time[i] = (int)dbltemp;
6813             }
6814             if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
6815             {
6816                 ent->dot[i] = (int)dbltemp;
6817             }
6818             if(paramCount >= 6 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp)))
6819             {
6820                 ent->dot_force[i] = (int)dbltemp;
6821             }
6822             if(paramCount >= 7 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[6], &dbltemp)))
6823             {
6824                 ent->dot_rate[i] = (int)dbltemp;
6825             }
6826             if(paramCount >= 8 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[7], &dbltemp)))
6827             {
6828                 ent->dot_atk[i] = (int)dbltemp;
6829             }
6830             if(paramCount >= 9)
6831             {
6832                 ent->dot_owner[i] = (entity *)varlist[8]->ptrVal;
6833             }
6834         }
6835         break;
6836     }
6837     case _ep_edelay:
6838     {
6839         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6840         {
6841             ent->modeldata.edelay.mode = (int)ltemp;
6842         }
6843         if(paramCount >= 3 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
6844         {
6845             ent->modeldata.edelay.factor = (float)dbltemp;
6846         }
6847         if(paramCount >= 4 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
6848         {
6849             ent->modeldata.edelay.cap_min = (int)ltemp;
6850         }
6851         if(paramCount >= 5 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
6852         {
6853             ent->modeldata.edelay.cap_max = (int)ltemp;
6854         }
6855         if(paramCount >= 6 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[6], &ltemp)))
6856         {
6857             ent->modeldata.edelay.range_min = (int)ltemp;
6858         }
6859         if(paramCount >= 7 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[7], &ltemp)))
6860         {
6861             ent->modeldata.edelay.range_max = (int)ltemp;
6862         }
6863 
6864         break;
6865     }
6866     case _ep_energycost:
6867     {
6868         if(paramCount != 5)
6869         {
6870             printf("\n Error, changeentityproperty({ent}, 'energycost', {subproperty}, {animation}, {value}): Invalid or missing parameter. \n");
6871             goto changeentityproperty_error;
6872         }
6873 
6874         if(FAILED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
6875         {
6876             printf("\n Error, changeentityproperty has invalid animation id.\n");
6877             goto changeentityproperty_error;
6878         }
6879 
6880         i = (int)ltemp;
6881 
6882         if(!validanim(ent, i))
6883         {
6884             printf("\n Error, changeentityproperty({ent}, 'energycost', {subproperty}, {animation}, {value}): {animation} parameter invalid. Make sure the animation exists. \n");
6885             goto changeentityproperty_error;
6886         }
6887 
6888         if(varlist[2]->vt != VT_INTEGER)
6889         {
6890             printf("You must give a string value for energycost flag name.\n");
6891             goto changeentityproperty_error;
6892         }
6893 
6894         switch(varlist[2]->lVal)
6895         {
6896         case _ep_energycost_cost:
6897         {
6898             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
6899             {
6900                 ent->modeldata.animation[i]->energycost.cost = (int)ltemp;
6901             }
6902             break;
6903         }
6904         case _ep_energycost_disable:
6905         {
6906             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
6907             {
6908                 ent->modeldata.animation[i]->energycost.disable = (int)ltemp;
6909             }
6910             break;
6911         }
6912         case _ep_energycost_mponly:
6913         {
6914             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
6915             {
6916                 ent->modeldata.animation[i]->energycost.mponly = (int)ltemp;
6917             }
6918             break;
6919         }
6920         default:
6921             printf("Unknown Energycost flag.\n");
6922             goto changeentityproperty_error;
6923         }
6924         break;
6925     }
6926     case _ep_escapecount:
6927     {
6928         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6929         {
6930             ent->escapecount = (int)ltemp;
6931         }
6932         break;
6933     }
6934     case _ep_escapehits:
6935     {
6936         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6937         {
6938             ent->modeldata.escapehits = (int)ltemp;
6939         }
6940         break;
6941     }
6942     case _ep_falldie:
6943     {
6944         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6945         {
6946             ent->modeldata.falldie = (int)ltemp;
6947         }
6948         break;
6949     }
6950     case _ep_playerindex:
6951     {
6952         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6953         {
6954             ent->playerindex = (int)ltemp;
6955         }
6956         break;
6957     }
6958     case _ep_pain_time:
6959     {
6960         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6961         {
6962             ent->pain_time = (int)ltemp;
6963         }
6964         break;
6965     }
6966     case _ep_freezetime:
6967     {
6968         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6969         {
6970             ent->freezetime = (int)ltemp;
6971         }
6972         break;
6973     }
6974     case _ep_frozen:
6975     {
6976         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6977         {
6978             ent->frozen = (int)ltemp;
6979         }
6980         break;
6981     }
6982     case _ep_gfxshadow:
6983     {
6984         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6985         {
6986             ent->modeldata.gfxshadow = (int)ltemp;
6987         }
6988         break;
6989     }
6990     case _ep_grabforce:
6991     {
6992         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
6993         {
6994             ent->modeldata.grabforce = (int)ltemp;
6995         }
6996         break;
6997     }
6998     case _ep_guardpoints:
6999     {
7000         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7001         {
7002             ent->modeldata.guardpoints.current = (int)ltemp;
7003         }
7004         break;
7005     }
7006     case _ep_health:
7007     {
7008         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7009         {
7010             ent->health = (int)ltemp;
7011             if(ent->health > ent->modeldata.health)
7012             {
7013                 ent->health = ent->modeldata.health;
7014             }
7015             else if(ent->health < 0)
7016             {
7017                 ent->health = 0;
7018             }
7019         }
7020         break;
7021     }
7022     case _ep_hitbyid:
7023     {
7024         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7025         {
7026             ent->hit_by_attack_id = (int)ltemp;
7027         }
7028         break;
7029     }
7030     case _ep_hmapl:
7031     {
7032         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7033         {
7034             ent->modeldata.maps.hide_start = ltemp;
7035         }
7036         break;
7037     }
7038     case _ep_hmapu:
7039     {
7040         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7041         {
7042             ent->modeldata.maps.hide_end = ltemp;
7043         }
7044         break;
7045     }
7046     case _ep_hostile:
7047     {
7048         ent->modeldata.hostile = 0;
7049         for(i = 2; i < paramCount; i++)
7050         {
7051             if(varlist[i]->vt == VT_INTEGER) // known entity type
7052             {
7053                 ltemp = varlist[i]->lVal;
7054                 if(ltemp & 0x80000000)
7055                 {
7056                     ent->modeldata.hostile |= entitytypes[ltemp & 0x7fffffff];
7057                 }
7058                 else
7059                 {
7060                     ent->modeldata.hostile |= ltemp;
7061                 }
7062             }
7063             else
7064             {
7065                 printf("You must pass one or more string constants for hostile entity type.\n");
7066                 goto changeentityproperty_error;
7067             }
7068         }
7069 
7070         break;
7071     }
7072     case _ep_iconposition:
7073     {
7074         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7075         {
7076             ent->modeldata.icon.x = (int)ltemp;
7077         }
7078         if(paramCount > 3 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7079         {
7080             ent->modeldata.icon.y = (int)ltemp;
7081         }
7082         break;
7083     }
7084     case _ep_invincible:
7085     {
7086         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7087         {
7088             ent->invincible = (int)ltemp;
7089         }
7090         break;
7091     }
7092     case _ep_invinctime:
7093     {
7094         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7095         {
7096             ent->invinctime = (int)ltemp;
7097         }
7098         break;
7099     }
7100     case _ep_jugglepoints:
7101     {
7102         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7103         {
7104             ent->modeldata.jugglepoints.current = (int)ltemp;
7105         }
7106         break;
7107     }
7108     case _ep_jumpheight:
7109     {
7110         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7111         {
7112             ent->modeldata.jumpheight = (float)dbltemp;
7113         }
7114         break;
7115     }
7116     case _ep_knockdowncount:
7117     {
7118         if(varlist[2]->vt != VT_INTEGER)
7119         {
7120             if(varlist[2]->vt != VT_STR)
7121                 printf("You must provide a string value for Knockdowncount subproperty:\n\
7122                     changeentityproperty({ent}, 'knockdowncount', {subproperty}, {value})\n\
7123                     ~'current'\n\
7124                     ~'max'\n\
7125                     ~'time'\n");
7126             goto changeentityproperty_error;
7127         }
7128 
7129         switch(varlist[2]->lVal)
7130         {
7131         case _ep_knockdowncount_current:
7132         {
7133             if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
7134             {
7135                 ent->knockdowncount = (float)dbltemp;
7136             }
7137             break;
7138         }
7139         case _ep_knockdowncount_max:
7140         {
7141             if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
7142             {
7143                 ent->modeldata.knockdowncount = (float)dbltemp;
7144             }
7145             break;
7146             case _ep_knockdowncount_time:
7147                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7148                 {
7149                     ent->knockdowntime = (int)ltemp;
7150                 }
7151                 break;
7152             }
7153         default:
7154             printf("Unknown knockdowncount subproperty.\n");
7155             goto changeentityproperty_error;
7156         }
7157         break;
7158     }
7159     case _ep_komap:
7160     {
7161         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7162         {
7163             ent->modeldata.maps.ko = (int)ltemp;
7164         }
7165         if(paramCount >= 4 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7166         {
7167             ent->modeldata.maps.kotype = (int)ltemp;
7168         }
7169         break;
7170     }
7171     case _ep_lifeposition:
7172     {
7173         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7174         {
7175             ent->modeldata.hpx = (int)ltemp;
7176         }
7177         if(paramCount > 3 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7178         {
7179             ent->modeldata.hpy = (int)ltemp;
7180         }
7181         break;
7182     }
7183     case _ep_lifespancountdown:
7184     {
7185         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7186         {
7187             ent->lifespancountdown = (int)ltemp;
7188         }
7189         break;
7190     }
7191     case _ep_attackthrottle:
7192     {
7193         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7194         {
7195             ent->modeldata.attackthrottle = (float)dbltemp;
7196         }
7197         break;
7198     }
7199     case _ep_attackthrottletime:
7200     {
7201         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7202         {
7203             ent->modeldata.attackthrottletime = (float)dbltemp;
7204         }
7205         break;
7206     }
7207     case _ep_map:
7208     {
7209         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7210         {
7211             ent_set_colourmap(ent, (int)ltemp);
7212         }
7213         break;
7214     }
7215     case _ep_maptime:
7216     {
7217         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7218         {
7219             ent->maptime = (int)ltemp;
7220         }
7221         break;
7222     }
7223     case _ep_maxguardpoints:
7224     {
7225         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7226         {
7227             ent->modeldata.guardpoints.maximum = (int)ltemp;
7228         }
7229         break;
7230     }
7231     case _ep_maxhealth:
7232     {
7233         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7234         {
7235             ent->modeldata.health = (int)ltemp;
7236             if(ent->modeldata.health < 0)
7237             {
7238                 ent->modeldata.health = 0;    //OK, no need to have ot below 0
7239             }
7240         }
7241         break;
7242     }
7243     case _ep_maxjugglepoints:
7244     {
7245         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7246         {
7247             ent->modeldata.jugglepoints.maximum = (int)ltemp;
7248         }
7249         break;
7250     }
7251     case _ep_maxmp:
7252     {
7253         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7254         {
7255             ent->modeldata.mp = (int)ltemp;
7256             if(ent->modeldata.mp < 0)
7257             {
7258                 ent->modeldata.mp = 0;    //OK, no need to have ot below 0
7259             }
7260         }
7261         break;
7262     }
7263     case _ep_model:
7264     {
7265         if(varlist[2]->vt != VT_STR)
7266         {
7267             printf("You must give a string value for model name.\n");
7268             goto changeentityproperty_error;
7269         }
7270         tempstr = (char *)StrCache_Get(varlist[2]->strVal);
7271         if(paramCount > 3 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7272         {
7273             set_model_ex(ent, tempstr, -1, NULL, (int)ltemp);
7274             if(!ent->weapent)
7275             {
7276                 ent->weapent = ent;
7277             }
7278         }
7279         break;
7280     }
7281     case _ep_mp:
7282     {
7283         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7284         {
7285             ent->mp = (int)ltemp;
7286             if(ent->mp > ent->modeldata.mp)
7287             {
7288                 ent->mp = ent->modeldata.mp;
7289             }
7290             else if(ent->mp < 0)
7291             {
7292                 ent->mp = 0;
7293             }
7294         }
7295         break;
7296     }
7297     case _ep_mpset:
7298     {
7299         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7300         {
7301             ent->modeldata.mp = (int)dbltemp;
7302         }
7303         if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
7304         {
7305             ent->modeldata.mpstable = (int)dbltemp;
7306         }
7307         if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
7308         {
7309             ent->modeldata.mpstableval = (int)dbltemp;
7310         }
7311         if(paramCount >= 6 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp)))
7312         {
7313             ent->modeldata.mprate = (int)dbltemp;
7314         }
7315         if(paramCount >= 7 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[6], &dbltemp)))
7316         {
7317             ent->modeldata.mpdroprate = (int)dbltemp;
7318         }
7319         if(paramCount >= 8 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[7], &dbltemp)))
7320         {
7321             ent->modeldata.chargerate = (int)dbltemp;
7322         }
7323         break;
7324     }
7325     case _ep_name:
7326     {
7327         if(varlist[2]->vt != VT_STR)
7328         {
7329             printf("You must give a string value for entity name.\n");
7330             goto changeentityproperty_error;
7331         }
7332         strcpy(ent->name, (char *)StrCache_Get(varlist[2]->strVal));
7333         break;
7334     }
7335     case _ep_nameposition:
7336     {
7337         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7338         {
7339             ent->modeldata.namex = (int)ltemp;
7340         }
7341         if(paramCount > 3 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7342         {
7343             ent->modeldata.namey = (int)ltemp;
7344         }
7345         break;
7346     }
7347     case _ep_nextanim:
7348     {
7349         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7350         {
7351             ent->nextanim = (int)ltemp;
7352         }
7353         break;
7354     }
7355     case _ep_nextmove:
7356     {
7357         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7358         {
7359             ent->nextmove = (int)ltemp;
7360         }
7361         break;
7362     }
7363     case _ep_nextthink:
7364     {
7365         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7366         {
7367             ent->nextthink = (int)ltemp;
7368         }
7369         break;
7370     }
7371     case _ep_no_adjust_base:
7372     {
7373         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7374         {
7375             ent->modeldata.no_adjust_base = (int)ltemp;
7376         }
7377         break;
7378     }
7379     case _ep_noaicontrol:
7380     {
7381         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7382         {
7383             ent->noaicontrol = (int)ltemp;
7384         }
7385         break;
7386     }
7387     case _ep_nodieblink:
7388     {
7389         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7390         {
7391             ent->modeldata.nodieblink = (int)ltemp;
7392         }
7393         break;
7394     }
7395     case _ep_nodrop:
7396     {
7397         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7398         {
7399             ent->modeldata.nodrop = (int)ltemp;
7400         }
7401         break;
7402     }
7403     case _ep_nograb:
7404     {
7405         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7406         {
7407             ent->nograb = (int)ltemp;
7408         }
7409         break;
7410     }
7411     case _ep_nolife:
7412     {
7413         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7414         {
7415             ent->modeldata.nolife = (int)ltemp;
7416         }
7417         break;
7418     }
7419     case _ep_nopain:
7420     {
7421         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7422         {
7423             ent->modeldata.nopain = (int)ltemp;
7424         }
7425         break;
7426     }
7427     case _ep_offense:
7428     {
7429         if(paramCount >= 4 &&
7430                 SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) &&
7431                 ltemp < (LONG)MAX_ATKS && ltemp >= (LONG)0 &&
7432                 SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
7433         {
7434             ent->offense_factors[(int)ltemp] = (float)dbltemp;
7435         }
7436         break;
7437     }
7438     case _ep_opponent:
7439     {
7440         ent->opponent = (entity *)varlist[2]->ptrVal;
7441         break;
7442     }
7443     case _ep_owner:
7444     {
7445         ent->owner = (entity *)varlist[2]->ptrVal;
7446         break;
7447     }
7448     case _ep_parent:
7449     {
7450         ent->parent = (entity *)varlist[2]->ptrVal;
7451         break;
7452     }
7453     case _ep_pathfindstep:
7454     {
7455         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7456         {
7457             ent->modeldata.pathfindstep = (float)dbltemp;
7458         }
7459         break;
7460     }
7461     case _ep_position:
7462     {
7463         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7464         {
7465             ent->x = (float)dbltemp;
7466         }
7467         if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
7468         {
7469             ent->z = (float)dbltemp;
7470         }
7471         if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
7472         {
7473             ent->a = (float)dbltemp;
7474         }
7475         break;
7476     }
7477     case _ep_x:
7478     {
7479         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7480         {
7481             ent->x = (float)dbltemp;
7482         }
7483         break;
7484     }
7485     case _ep_z:
7486     {
7487         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7488         {
7489             ent->z = (float)dbltemp;
7490         }
7491         break;
7492     }
7493     case _ep_a:
7494     {
7495         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7496         {
7497             ent->a = (float)dbltemp;
7498         }
7499         break;
7500     }
7501     case _ep_projectile:
7502     {
7503         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7504         {
7505             ent->projectile = (int)ltemp;
7506         }
7507         break;
7508     }
7509     case _ep_projectilehit:
7510     {
7511         ent->modeldata.projectilehit = 0;
7512 
7513         for(i = 2; i < paramCount; i++)
7514         {
7515             if(varlist[i]->vt == VT_INTEGER) // known entity type
7516             {
7517                 ltemp = varlist[i]->lVal;
7518                 if(ltemp & 0x80000000)
7519                 {
7520                     ent->modeldata.projectilehit |= entitytypes[ltemp & 0x7fffffff];
7521                 }
7522                 else
7523                 {
7524                     ent->modeldata.projectilehit |= ltemp;
7525                 }
7526             }
7527             else
7528             {
7529                 printf("You must pass one or more string constants for projectilehit entity type.\n");
7530                 goto changeentityproperty_error;
7531             }
7532         }
7533 
7534         break;
7535     }
7536     case _ep_running:
7537     {
7538         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7539         {
7540             ent->modeldata.runspeed = (float)dbltemp;
7541         }
7542         if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
7543         {
7544             ent->modeldata.runjumpheight = (float)dbltemp;
7545         }
7546         if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
7547         {
7548             ent->modeldata.runjumpdist = (float)dbltemp;
7549         }
7550         if(paramCount >= 6 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp)))
7551         {
7552             ent->modeldata.runhold = (int)dbltemp;
7553         }
7554         if(paramCount >= 7 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[6], &dbltemp)))
7555         {
7556             ent->modeldata.runupdown = (int)dbltemp;
7557         }
7558 
7559         break;
7560     }
7561     case _ep_rush_count:
7562     {
7563         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7564         {
7565             ent->rush[0] = (int)ltemp;
7566         }
7567         break;
7568     }
7569     case _ep_rush_tally:
7570     {
7571         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7572         {
7573             ent->rush[1] = (int)ltemp;
7574         }
7575         break;
7576     }
7577     case _ep_rush_time:
7578     {
7579         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7580         {
7581             ent->rushtime = (int)ltemp;
7582         }
7583         break;
7584     }
7585     case _ep_score:
7586     {
7587         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7588         {
7589             ent->modeldata.score = (int)ltemp;
7590         }
7591         break;
7592     }
7593     case _ep_scroll:
7594     {
7595         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7596         {
7597             ent->modeldata.scroll = (float)dbltemp;
7598         }
7599         break;
7600     }
7601     case _ep_seal:
7602     {
7603         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7604         {
7605             ent->seal = (int)ltemp;
7606         }
7607         break;
7608     }
7609     case _ep_sealtime:
7610     {
7611         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7612         {
7613             ent->sealtime = (int)ltemp;
7614         }
7615         break;
7616     }
7617     case _ep_setlayer:
7618     {
7619         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7620         {
7621             ent->modeldata.setlayer = (int)ltemp;
7622         }
7623         break;
7624     }
7625     case _ep_sortid:
7626     {
7627         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7628         {
7629             ent->sortid = (int)ltemp;
7630         }
7631         break;
7632     }
7633     case _ep_speed:
7634     {
7635         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7636         {
7637             ent->modeldata.speed = (float)dbltemp;
7638         }
7639         break;
7640     }
7641     case _ep_spritea:
7642     {
7643         if(varlist[2]->vt != VT_INTEGER)
7644         {
7645             if(varlist[2]->vt != VT_STR)
7646                 printf("You must provide a string value for Sprite Array subproperty:\n\
7647                     changeentityproperty({ent}, 'spritea', {subproperty}, {animation ID}, {frame}, {value})\n\
7648                     ~'centerx'\n\
7649                     ~'centery'\n\
7650                     ~'file'\n\
7651                     ~'offsetx'\n\
7652                     ~'sprite'\n");
7653             goto changeentityproperty_error;
7654         }
7655 
7656         ltemp   = varlist[2]->lVal;
7657 
7658         /*
7659         Failsafe checks. Any attempt to access a sprite property on invalid frame would cause instant shutdown.
7660         */
7661         if(!validanim(ent, varlist[3]->lVal) || !(ent->modeldata.animation[varlist[3]->lVal]->numframes >= varlist[4]->lVal) || paramCount < 5)
7662         {
7663             break;
7664         }
7665 
7666         i = ent->modeldata.animation[varlist[3]->lVal]->sprite[varlist[4]->lVal];   //Get sprite index.
7667 
7668         switch(ltemp)
7669         {
7670         case _ep_spritea_centerx:
7671         {
7672             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
7673             {
7674                 sprite_map[i].centerx = (int)ltemp;
7675             }
7676 
7677             break;
7678         }
7679         case _ep_spritea_centery:
7680         {
7681             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
7682             {
7683                 sprite_map[i].centery = (int)ltemp;
7684             }
7685             break;
7686         }
7687         case _ep_spritea_file:
7688         {
7689             if(varlist[5]->vt != VT_STR)
7690             {
7691                 printf("You must provide a string value for file name.\n");
7692                 goto changeentityproperty_error;
7693             }
7694             strcpy(sprite_map[i].node->filename, (char *)StrCache_Get(varlist[5]->strVal));
7695             break;
7696         }
7697         /*
7698         case _ep_spritea_offsetx:
7699         {
7700             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
7701             {
7702                 sprite_map[i].ofsx = (int)ltemp;
7703                 (*pretvar)->lVal = (LONG)1;
7704             }
7705             break;
7706         }
7707         case _ep_spritea_offsety:
7708         {
7709             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7710             {
7711                 sprite_map[i].ofsy = (int)ltemp;
7712                 (*pretvar)->lVal = (LONG)1;
7713             }
7714             break;
7715         }*/
7716         case _ep_spritea_sprite:
7717         {
7718             sprite_map[i].node->sprite = (VOID *)varlist[5]->ptrVal;
7719 
7720             break;
7721         }
7722         default:
7723             printf("Unknown Sprite Array subproperty.\n");
7724             goto changeentityproperty_error;
7725         }
7726         break;
7727     }
7728     case _ep_stalltime:
7729     {
7730         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7731         {
7732             ent->stalltime = (int)ltemp;
7733         }
7734         break;
7735     }
7736     case _ep_releasetime:
7737     {
7738         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7739         {
7740             ent->releasetime = (int)ltemp;
7741         }
7742         break;
7743     }
7744     case _ep_stats:
7745     {
7746         if(paramCount < 4)
7747         {
7748             break;
7749         }
7750 
7751         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7752         {
7753             if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
7754             {
7755                 switch(varlist[2]->lVal)
7756                 {
7757                 default:
7758                     ent->modeldata.stats[(int)ltemp] = (float)dbltemp;
7759                     break;
7760                 case 1:
7761                     ent->stats[(int)ltemp] = (float)dbltemp;
7762                     break;
7763                 }
7764             }
7765         }
7766         break;
7767     }
7768     case _ep_staydown:
7769     {
7770         if(varlist[2]->vt != VT_INTEGER)
7771         {
7772             if(varlist[2]->vt != VT_STR)
7773                 printf("You must provide a string value for Staydown subproperty:\n\
7774                     changeentityproperty({ent}, 'staydown', {subproperty}, {value})\n\
7775                     ~'rise'\n\
7776                     ~'riseattack'\n\
7777                     ~'riseattack_stall'\n");
7778             goto changeentityproperty_error;
7779         }
7780         if(paramCount < 4)
7781         {
7782             break;
7783         }
7784 
7785         switch(varlist[2]->lVal)
7786         {
7787         case _ep_staydown_rise:
7788         {
7789             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7790             {
7791                 ent->staydown.rise = (int)ltemp;
7792             }
7793             break;
7794         }
7795         case _ep_staydown_riseattack:
7796         {
7797             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7798             {
7799                 ent->staydown.riseattack = (int)ltemp;
7800             }
7801             break;
7802         }
7803         case _ep_staydown_riseattack_stall:
7804         {
7805             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
7806             {
7807                 ent->staydown.riseattack_stall = (int)ltemp;
7808             }
7809             break;
7810         }
7811         default:
7812             printf("Unknown Staydown subproperty.\n");
7813             goto changeentityproperty_error;
7814         }
7815         break;
7816     }
7817     case _ep_stealth:
7818     {
7819         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7820         {
7821             ent->modeldata.stealth.hide = (int)ltemp;
7822         }
7823         break;
7824     }
7825     case _ep_subentity:
7826     {
7827         if(ent->subentity)
7828         {
7829             ent->subentity->parent = NULL;
7830         }
7831         ent->subentity = (entity *)varlist[2]->ptrVal;
7832         if(ent->subentity)
7833         {
7834             ent->subentity->parent = ent;
7835         }
7836         break;
7837     }
7838     case _ep_subject_to_gravity:
7839     {
7840         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7841         {
7842             ent->modeldata.subject_to_gravity = (int)ltemp;
7843         }
7844         break;
7845     }
7846     case _ep_subject_to_hole:
7847     {
7848         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7849         {
7850             ent->modeldata.subject_to_hole = (int)ltemp;
7851         }
7852         break;
7853     }
7854     case _ep_subject_to_maxz:
7855     {
7856         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7857         {
7858             ent->modeldata.subject_to_maxz = (int)ltemp;
7859         }
7860         break;
7861     }
7862     case _ep_subject_to_minz:
7863     {
7864         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7865         {
7866             ent->modeldata.subject_to_minz = (int)ltemp;
7867         }
7868         break;
7869     }
7870     case _ep_subject_to_obstacle:
7871     {
7872         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7873         {
7874             ent->modeldata.subject_to_obstacle = (int)ltemp;
7875         }
7876         break;
7877     }
7878     case _ep_subject_to_platform:
7879     {
7880         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7881         {
7882             ent->modeldata.subject_to_platform = (int)ltemp;
7883         }
7884         break;
7885     }
7886     case _ep_subject_to_screen:
7887     {
7888         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7889         {
7890             ent->modeldata.subject_to_screen = (int)ltemp;
7891         }
7892         break;
7893     }
7894     case _ep_subject_to_wall:
7895     {
7896         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7897         {
7898             ent->modeldata.subject_to_wall = (int)ltemp;
7899         }
7900         break;
7901     }
7902     case _ep_takeaction:
7903     {
7904         //if(varlist[2]->vt == VT_STRING)
7905         if(varlist[2]->vt == VT_EMPTY)
7906         {
7907             // UT: changed this to only accept NULL(), otherwise the log file is filled with warnings
7908             ent->takeaction = NULL;
7909             break;
7910         }
7911         else if(varlist[2]->vt != VT_INTEGER)
7912         {
7913             printf("You must give a string value for action type.\n");
7914             goto changeentityproperty_error;
7915         }
7916 
7917         // otherwise, the parameter is a known action
7918         ltemp = varlist[2]->lVal;
7919         if((ltemp >= 0) && (ltemp < _ep_ta_the_end))
7920         {
7921             ent->takeaction = actions[(int)ltemp];
7922         }
7923 
7924         break;
7925     }
7926     case _ep_think:
7927     {
7928         //if(varlist[2]->vt == VT_STRING)
7929         if(varlist[2]->vt == VT_EMPTY)
7930         {
7931             // UT: changed this to only accept NULL(), otherwise the log file is filled with warnings
7932             break;
7933         }
7934         else if(varlist[2]->vt != VT_INTEGER)
7935         {
7936             printf("You must give a string value for think type.\n");
7937             goto changeentityproperty_error;
7938         }
7939 
7940         // otherwise, the parameter is a known action
7941         ltemp = varlist[2]->lVal;
7942         if((ltemp >= 0) && (ltemp < _ep_th_the_end))
7943         {
7944             ent->think = think[(int)ltemp];
7945         }
7946 
7947         break;
7948     }
7949     case _ep_thold:
7950     {
7951         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7952         {
7953             ent->modeldata.thold = (int)ltemp;
7954         }
7955         break;
7956     }
7957     case _ep_throwdamage:
7958     {
7959         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7960         {
7961             ent->modeldata.throwdamage = (int)ltemp;
7962         }
7963         break;
7964     }
7965     case _ep_throwdist:
7966     {
7967         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7968         {
7969             ent->modeldata.throwdist = (float)dbltemp;
7970         }
7971         break;
7972     }
7973     case _ep_throwframewait:
7974     {
7975         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7976         {
7977             ent->modeldata.throwframewait = (int)ltemp;
7978         }
7979         break;
7980     }
7981     case _ep_throwheight:
7982     {
7983         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
7984         {
7985             ent->modeldata.throwheight = (float)dbltemp;
7986         }
7987         break;
7988     }
7989     case _ep_tosstime:
7990     {
7991         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
7992         {
7993             ent->toss_time = (int)ltemp;
7994         }
7995         break;
7996     }
7997     case _ep_trymove:
7998     {
7999         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
8000         {
8001             if(ltemp == 1)
8002             {
8003                 ent->trymove = common_trymove;
8004             }
8005             else if(ltemp == 2)
8006             {
8007                 ent->trymove = player_trymove;
8008             }
8009             else
8010             {
8011                 ent->trymove = NULL;
8012             }
8013         }
8014         break;
8015     }
8016     case _ep_type:
8017     {
8018         if(varlist[2]->vt != VT_INTEGER)
8019         {
8020             printf("You must provide a type constant for type.\n");
8021             goto changeentityproperty_error;
8022         }
8023 
8024         ltemp = varlist[2]->lVal;
8025         ent->modeldata.type = (int)ltemp;
8026 
8027         break;
8028     }
8029     case _ep_velocity:
8030     {
8031         if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
8032         {
8033             ent->xdir = (float)dbltemp;
8034         }
8035         if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
8036         {
8037             ent->zdir = (float)dbltemp;
8038         }
8039         if(paramCount >= 5 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[4], &dbltemp)))
8040         {
8041             ent->tossv = (float)dbltemp;
8042         }
8043         break;
8044     }
8045     case _ep_weapon:
8046     {
8047         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
8048         {
8049             ltemp2 = (LONG)0;
8050             if(paramCount < 4 ||  SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
8051             {
8052                 set_weapon(ent, (int)ltemp, (int)ltemp2);
8053             }
8054         }
8055         break;
8056     }
8057     default:
8058         //printf("Property name '%s' is not supported by function changeentityproperty.\n", propname);
8059         goto changeentityproperty_error;
8060         break;
8061     }
8062 
8063     return S_OK;
8064 changeentityproperty_error:
8065     return E_FAIL;
8066 }
8067 
8068 //tossentity(entity, height, speedx, speedz)
openbor_tossentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8069 HRESULT openbor_tossentity(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8070 {
8071     entity *ent = NULL;
8072     DOUBLE height = 0, speedx = 0, speedz = 0;
8073 
8074     if(paramCount < 1)
8075     {
8076         goto toss_error;
8077     }
8078 
8079     ent = (entity *)varlist[0]->ptrVal; //retrieve the entity
8080     if(!ent)
8081     {
8082         goto toss_error;
8083     }
8084 
8085     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8086     (*pretvar)->lVal = (LONG)1;
8087 
8088     if(paramCount >= 2)
8089     {
8090         ScriptVariant_DecimalValue(varlist[1], &height);
8091     }
8092     if(paramCount >= 3)
8093     {
8094         ScriptVariant_DecimalValue(varlist[2], &speedx);
8095     }
8096     if(paramCount >= 4)
8097     {
8098         ScriptVariant_DecimalValue(varlist[3], &speedz);
8099     }
8100 
8101     ent->xdir = (float)speedx;
8102     ent->zdir = (float)speedz;
8103     toss(ent, (float)height);
8104     return S_OK;
8105 
8106 toss_error:
8107     printf("Function tossentity(entity,height, speedx, speedz) requires at least a valid entity handle.\n");
8108     *pretvar = NULL;
8109     return E_FAIL;
8110 }
8111 
8112 // ===== getplayerproperty =====
8113 enum playerproperty_enum
8114 {
8115     _pp_colourmap,
8116     _pp_credits,
8117     _pp_ent,
8118     _pp_entity,
8119     _pp_hasplayed,
8120     _pp_keys,
8121     _pp_lives,
8122     _pp_name,
8123     _pp_playkeys,
8124     _pp_score,
8125     _pp_spawnhealth,
8126     _pp_spawnmp,
8127     _pp_weapon,
8128     _pp_weapnum,
8129     _pp_the_end,
8130 };
8131 
mapstrings_playerproperty(ScriptVariant ** varlist,int paramCount)8132 int mapstrings_playerproperty(ScriptVariant **varlist, int paramCount)
8133 {
8134     char *propname;
8135     int prop;
8136 
8137     static const char *proplist[] =
8138     {
8139         "colourmap",
8140         "credits",
8141         "ent",
8142         "entity",
8143         "hasplayed",
8144         "keys",
8145         "lives",
8146         "name",
8147         "playkeys",
8148         "score",
8149         "spawnhealth",
8150         "spawnmp",
8151         "weapon",
8152         "weapnum",
8153     };
8154 
8155     if(paramCount < 2)
8156     {
8157         return 1;
8158     }
8159 
8160     // property name
8161     MAPSTRINGS(varlist[1], proplist, _pp_the_end,
8162                "Player property name '%s' is not supported yet.\n");
8163 
8164     return 1;
8165 }
8166 
8167 //getplayerproperty(index, propname);
openbor_getplayerproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8168 HRESULT openbor_getplayerproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8169 {
8170     LONG ltemp;
8171     int index;
8172     entity *ent = NULL;
8173     int prop = -1;
8174     ScriptVariant *arg = NULL;
8175 
8176     if(paramCount < 2)
8177     {
8178         *pretvar = NULL;
8179         return E_FAIL;
8180     }
8181 
8182     mapstrings_playerproperty(varlist, paramCount);
8183     ScriptVariant_Clear(*pretvar);
8184 
8185     arg = varlist[0];
8186     if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
8187     {
8188         index = 0;
8189     }
8190     else
8191     {
8192         index = (int)ltemp;
8193     }
8194 
8195 
8196     ent = player[index].ent;
8197 
8198     arg = varlist[1];
8199     if(arg->vt != VT_INTEGER)
8200     {
8201         if(arg->vt != VT_STR)
8202         {
8203             printf("Function call getplayerproperty has invalid propery name parameter, it must be a string value.\n");
8204         }
8205         *pretvar = NULL;
8206         return E_FAIL;
8207     }
8208     prop = arg->lVal;
8209 
8210     switch(prop)
8211     {
8212     case _pp_ent:
8213     case _pp_entity:
8214     {
8215         if(!ent)
8216         {
8217             ScriptVariant_Clear(*pretvar);    // player not spawned
8218         }
8219         else
8220         {
8221             ScriptVariant_ChangeType(*pretvar, VT_PTR);
8222             (*pretvar)->ptrVal = (VOID *)ent;
8223         }
8224         break;
8225     }
8226     case _pp_name:
8227     {
8228         ScriptVariant_ChangeType(*pretvar, VT_STR);
8229         StrCache_Copy((*pretvar)->strVal, (char *)player[index].name);
8230         break;
8231     }
8232     case _pp_colourmap:
8233     {
8234         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8235         (*pretvar)->lVal = (LONG)player[index].colourmap;
8236         break;
8237     }
8238     case _pp_score:
8239     {
8240         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8241         (*pretvar)->lVal = (LONG)player[index].score;
8242         break;
8243     }
8244     case _pp_hasplayed:
8245     {
8246         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8247         (*pretvar)->lVal = (LONG)player[index].hasplayed;
8248         break;
8249     }
8250     case _pp_spawnhealth:
8251     {
8252         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8253         (*pretvar)->lVal = (LONG)player[index].spawnhealth;
8254         break;
8255     }
8256     case _pp_spawnmp:
8257     {
8258         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8259         (*pretvar)->lVal = (LONG)player[index].spawnmp;
8260         break;
8261     }
8262     case _pp_lives:
8263     {
8264         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8265         (*pretvar)->lVal = (LONG)player[index].lives;
8266         break;
8267     }
8268     case _pp_playkeys:
8269     {
8270         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8271         (*pretvar)->lVal = (LONG)player[index].playkeys;
8272         break;
8273     }
8274     case _pp_keys:
8275     {
8276         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8277         (*pretvar)->lVal = (LONG)player[index].keys;
8278         break;
8279     }
8280     case _pp_credits:
8281     {
8282         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8283         if(noshare)
8284         {
8285             (*pretvar)->lVal = (LONG)player[index].credits;
8286         }
8287         else
8288         {
8289             (*pretvar)->lVal = credits;
8290         }
8291         break;
8292     }
8293     case _pp_weapnum:
8294     {
8295         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8296         (*pretvar)->lVal = (LONG)player[index].weapnum;
8297         break;
8298     }
8299     //this property is not known
8300     //default:{
8301     //  .....
8302     //}
8303     }
8304     return S_OK;
8305 }
8306 
8307 
8308 //changeplayerproperty(index, propname, value[, value2, value3,...]);
openbor_changeplayerproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8309 HRESULT openbor_changeplayerproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8310 {
8311     LONG ltemp, ltemp2;
8312     int index;
8313     entity *ent = NULL;
8314     int prop = -1;
8315     char *tempstr = NULL;
8316     static char buffer[64];
8317     ScriptVariant *arg = NULL;
8318 
8319     *pretvar = NULL;
8320     if(paramCount < 3)
8321     {
8322         printf("Function changeplayerproperty must have at least 3 arguments.\n");
8323         return E_FAIL;
8324     }
8325 
8326     mapstrings_playerproperty(varlist, paramCount);
8327     arg = varlist[0];
8328 
8329     if(FAILED(ScriptVariant_IntegerValue(arg, &ltemp)))
8330     {
8331         index = 0;
8332     }
8333     else
8334     {
8335         index = (int)ltemp;
8336     }
8337 
8338     ent = player[index].ent;
8339 
8340     if(varlist[1]->vt != VT_INTEGER)
8341     {
8342         if(varlist[1]->vt != VT_STR)
8343         {
8344             printf("You must give a string value for player property name.\n");
8345         }
8346         return E_FAIL;
8347     }
8348     prop = varlist[1]->lVal;
8349 
8350     arg = varlist[2];
8351 
8352     //change the model
8353     switch(prop)
8354     {
8355     case _pp_ent:
8356     case _pp_entity:
8357     {
8358         if(arg->vt == VT_PTR || arg->vt == VT_EMPTY)
8359         {
8360             player[index].ent = (entity *)arg->ptrVal;
8361         }
8362         else
8363         {
8364             goto cpperror;
8365         }
8366         break;
8367     }
8368     case _pp_weapon:
8369     {
8370         if(ent)
8371         {
8372             if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8373             {
8374                 if(paramCount > 3)
8375                 {
8376                     if(FAILED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)))
8377                     {
8378                         goto cpperror;
8379                     }
8380                 }
8381                 else
8382                 {
8383                     ltemp2 = (LONG)0;
8384                 }
8385                 set_weapon(player[index].ent, (int)ltemp, (int)ltemp2);
8386             }
8387             else
8388             {
8389                 goto cpperror;
8390             }
8391         }
8392         break;
8393     }
8394     case _pp_weapnum:
8395     {
8396         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8397         {
8398             player[index].weapnum = (int)ltemp;
8399         }
8400         else
8401         {
8402             goto cpperror;
8403         }
8404         break;
8405     }
8406     case _pp_name:
8407     {
8408         if(arg->vt != VT_STR)
8409         {
8410             goto cpperror;
8411         }
8412         tempstr = (char *)StrCache_Get(arg->strVal);
8413         strcpy(player[index].name, tempstr);
8414         break;
8415     }
8416     case _pp_colourmap:
8417     {
8418         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8419         {
8420             player[index].colourmap = (int)ltemp;
8421         }
8422         else
8423         {
8424             goto cpperror;
8425         }
8426         break;
8427     }
8428     case _pp_score:
8429     {
8430         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8431         {
8432             if(ltemp < 0)
8433             {
8434                 ltemp = 0;
8435             }
8436             else if(ltemp > 999999999)
8437             {
8438                 ltemp = 999999999;
8439             }
8440             player[index].score = (unsigned int)ltemp;
8441         }
8442         else
8443         {
8444             goto cpperror;
8445         }
8446         break;
8447     }
8448     case _pp_hasplayed:
8449     {
8450         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8451         {
8452             player[index].hasplayed = (int)ltemp;
8453         }
8454         else
8455         {
8456             goto cpperror;
8457         }
8458         break;
8459     }
8460     case _pp_spawnhealth:
8461     {
8462         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8463         {
8464             player[index].spawnhealth = (int)ltemp;
8465         }
8466         else
8467         {
8468             goto cpperror;
8469         }
8470         break;
8471     }
8472     case _pp_spawnmp:
8473     {
8474         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8475         {
8476             player[index].spawnmp = (int)ltemp;
8477         }
8478         else
8479         {
8480             goto cpperror;
8481         }
8482         break;
8483     }
8484     case _pp_lives:
8485     {
8486         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8487         {
8488             player[index].lives = (int)ltemp;
8489         }
8490         else
8491         {
8492             goto cpperror;
8493         }
8494         break;
8495     }
8496     case _pp_playkeys:
8497     {
8498         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8499         {
8500             player[index].playkeys = (int)ltemp;
8501         }
8502         else
8503         {
8504             goto cpperror;
8505         }
8506         break;
8507     }
8508     case _pp_keys:
8509     {
8510         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8511         {
8512             player[index].keys = (int)ltemp;
8513         }
8514         else
8515         {
8516             goto cpperror;
8517         }
8518         break;
8519     }
8520     case _pp_credits:
8521     {
8522         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
8523         {
8524             if(noshare)
8525             {
8526                 player[index].credits = (int)ltemp;
8527             }
8528             else
8529             {
8530                 credits = (int)ltemp;
8531             }
8532         }
8533         else
8534         {
8535             goto cpperror;
8536         }
8537         break;
8538     }
8539     default:
8540         printf("Invalid property name for function changeplayerproperty.\n");
8541         return E_FAIL;
8542     }
8543 
8544     return S_OK;
8545 cpperror:
8546     ScriptVariant_ToString(arg, buffer);
8547     printf("Function changeplayerproperty receives an invalid value: %s.\n", buffer);
8548     return E_FAIL;
8549 }
8550 
8551 //checkhole(x,z), return 1 if there's hole here
openbor_checkhole(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8552 HRESULT openbor_checkhole(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8553 {
8554     ScriptVariant *arg = NULL;
8555     DOUBLE x, z;
8556 
8557     if(paramCount < 2)
8558     {
8559         *pretvar = NULL;
8560         return E_FAIL;
8561     }
8562 
8563     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8564     (*pretvar)->lVal = (LONG)0;
8565 
8566     arg = varlist[0];
8567     if(FAILED(ScriptVariant_DecimalValue(arg, &x)))
8568     {
8569         return S_OK;
8570     }
8571 
8572     arg = varlist[1];
8573     if(FAILED(ScriptVariant_DecimalValue(arg, &z)))
8574     {
8575         return S_OK;
8576     }
8577 
8578     (*pretvar)->lVal = (LONG)(checkhole((float)x, (float)z) && checkwall((float)x, (float)z) < 0);
8579     return S_OK;
8580 }
8581 
8582 //checkwall(x,z), return wall height, or 0
openbor_checkwall(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8583 HRESULT openbor_checkwall(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8584 {
8585     ScriptVariant *arg = NULL;
8586     DOUBLE x, z;
8587     int wall;
8588 
8589     if(paramCount < 2)
8590     {
8591         *pretvar = NULL;
8592         return E_FAIL;
8593     }
8594 
8595     ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
8596     (*pretvar)->dblVal = (DOUBLE)0;
8597 
8598     arg = varlist[0];
8599     if(FAILED(ScriptVariant_DecimalValue(arg, &x)))
8600     {
8601         return S_OK;
8602     }
8603 
8604     arg = varlist[1];
8605     if(FAILED(ScriptVariant_DecimalValue(arg, &z)))
8606     {
8607         return S_OK;
8608     }
8609 
8610     if((wall = checkwall_below((float)x, (float)z, 100000)) >= 0)
8611     {
8612         (*pretvar)->dblVal = (DOUBLE)level->walls[wall][7];
8613     }
8614     return S_OK;
8615 }
8616 
8617 //checkplatformbelow(x,z,a), return the highest platfrom entity below
openbor_checkplatformbelow(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8618 HRESULT openbor_checkplatformbelow(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8619 {
8620     ScriptVariant *arg = NULL;
8621     DOUBLE x, z, a;
8622 
8623     if(paramCount < 3)
8624     {
8625         *pretvar = NULL;
8626         return E_FAIL;
8627     }
8628 
8629     ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
8630     (*pretvar)->dblVal = (DOUBLE)0;
8631 
8632     arg = varlist[0];
8633     if(FAILED(ScriptVariant_DecimalValue(arg, &x)))
8634     {
8635         return S_OK;
8636     }
8637 
8638     arg = varlist[1];
8639     if(FAILED(ScriptVariant_DecimalValue(arg, &z)))
8640     {
8641         return S_OK;
8642     }
8643 
8644     arg = varlist[2];
8645     if(FAILED(ScriptVariant_DecimalValue(arg, &a)))
8646     {
8647         return S_OK;
8648     }
8649 
8650     ScriptVariant_ChangeType(*pretvar, VT_PTR);
8651     (*pretvar)->ptrVal = (VOID *)check_platform_below((float)x, (float)z, (float)a, NULL);
8652     return S_OK;
8653 }
8654 
openbor_openfilestream(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8655 HRESULT openbor_openfilestream(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8656 {
8657     char *filename = NULL;
8658     ScriptVariant *arg = NULL;
8659     LONG location = 0;
8660     int fsindex;
8661 
8662     FILE *handle = NULL;
8663     char path[256] = {""};
8664     char tmpname[256] = {""};
8665     long size;
8666 
8667     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8668 
8669     if(paramCount < 1)
8670     {
8671         *pretvar = NULL;
8672         return E_FAIL;
8673     }
8674 
8675     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8676 
8677     arg = varlist[0];
8678     if(arg->vt != VT_STR)
8679     {
8680         printf("Filename for openfilestream must be a string.\n");
8681         *pretvar = NULL;
8682         return E_FAIL;
8683     }
8684 
8685     filename = (char *)StrCache_Get(arg->strVal);
8686 
8687     if(paramCount > 1)
8688     {
8689         arg = varlist[1];
8690         if(FAILED(ScriptVariant_IntegerValue(arg, &location)))
8691         {
8692             *pretvar = NULL;
8693             return E_FAIL;
8694         }
8695     }
8696 
8697     for(fsindex = 0; fsindex < numfilestreams; fsindex++)
8698     {
8699         if(filestreams[fsindex].buf == NULL)
8700         {
8701             break;
8702         }
8703     }
8704 
8705     if(fsindex == numfilestreams)
8706     {
8707         __realloc(filestreams, numfilestreams); //warning, don't ++ here, its a macro
8708         numfilestreams++;
8709     }
8710 
8711     // Load file from saves directory if specified
8712     if(location)
8713     {
8714         getBasePath(path, "Saves", 0);
8715         getPakName(tmpname, -1);
8716         strcat(path, tmpname);
8717         strcat(path, "/");
8718         strcat(path, filename);
8719         //printf("open path: %s", path);
8720 #ifndef DC
8721         if(!(fileExists(path)))
8722         {
8723             /*
8724             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.
8725 
8726             printf("Openfilestream - file specified does not exist.\n"); //Keep this for possible debug mode in the future.
8727             */
8728             (*pretvar)->lVal = -1;
8729 
8730             return S_OK;
8731         }
8732 #endif
8733         handle = fopen(path, "rb");
8734         if(handle == NULL)
8735         {
8736             (*pretvar)->lVal = -1;
8737             return S_OK;
8738         }
8739         //printf("\nfile opened\n");
8740         fseek(handle, 0, SEEK_END);
8741         size = ftell(handle);
8742         //printf("\n file size %d fsindex %d\n", size, fsindex);
8743         rewind(handle);
8744         filestreams[fsindex].buf = malloc(sizeof(*filestreams[fsindex].buf) * (size + 1));
8745         if(filestreams[fsindex].buf == NULL)
8746         {
8747             (*pretvar)->lVal = -1;
8748             return S_OK;
8749         }
8750         fread(filestreams[fsindex].buf, 1, size, handle);
8751         filestreams[fsindex].buf[size] = 0;
8752         filestreams[fsindex].size = size;
8753     }
8754     else if(buffer_pakfile(filename, &filestreams[fsindex].buf, &filestreams[fsindex].size) != 1)
8755     {
8756         printf("Invalid filename used in openfilestream.\n");
8757         (*pretvar)->lVal = -1;
8758         return S_OK;
8759     }
8760 
8761     (*pretvar)->lVal = (LONG)fsindex;
8762 
8763     filestreams[fsindex].pos = 0;
8764     return S_OK;
8765 }
8766 
openbor_getfilestreamline(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8767 HRESULT openbor_getfilestreamline(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8768 {
8769     int length;
8770     char *buf;
8771     ScriptVariant *arg = NULL;
8772     LONG filestreamindex;
8773 
8774     if(paramCount < 1)
8775     {
8776         *pretvar = NULL;
8777         return E_FAIL;
8778     }
8779 
8780     arg = varlist[0];
8781     if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
8782     {
8783         return S_OK;
8784     }
8785 
8786     ScriptVariant_ChangeType(*pretvar, VT_STR);
8787 
8788     length = 0;
8789     buf = filestreams[filestreamindex].buf + filestreams[filestreamindex].pos;
8790     while(buf[length] && buf[length] != '\n' && buf[length] != '\r')
8791     {
8792         ++length;
8793     }
8794 
8795     StrCache_NCopy((*pretvar)->strVal, buf, length);
8796 
8797     return S_OK;
8798 }
8799 
openbor_getfilestreamargument(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8800 HRESULT openbor_getfilestreamargument(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8801 {
8802     ScriptVariant *arg = NULL;
8803     LONG filestreamindex, argument;
8804     char *argtype = NULL;
8805 
8806     if(paramCount < 3)
8807     {
8808         *pretvar = NULL;
8809         return E_FAIL;
8810     }
8811 
8812     arg = varlist[0];
8813     if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
8814     {
8815         return S_OK;
8816     }
8817 
8818     arg = varlist[1];
8819     if(FAILED(ScriptVariant_IntegerValue(arg, &argument)))
8820     {
8821         return S_OK;
8822     }
8823     ScriptVariant_Clear(*pretvar);
8824 
8825     if(varlist[2]->vt != VT_STR)
8826     {
8827         printf("You must give a string value specifying what kind of value you want the argument converted to.\n");
8828         return E_FAIL;
8829     }
8830     argtype = (char *)StrCache_Get(varlist[2]->strVal);
8831 
8832     if(stricmp(argtype, "string") == 0)
8833     {
8834         ScriptVariant_ChangeType(*pretvar, VT_STR);
8835         StrCache_Copy((*pretvar)->strVal, (char *)findarg(filestreams[filestreamindex].buf + filestreams[filestreamindex].pos, argument));
8836     }
8837     else if(stricmp(argtype, "int") == 0)
8838     {
8839         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8840         (*pretvar)->lVal = (LONG)atoi(findarg(filestreams[filestreamindex].buf + filestreams[filestreamindex].pos, argument));
8841     }
8842     else if(stricmp(argtype, "float") == 0)
8843     {
8844         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
8845         (*pretvar)->dblVal = (DOUBLE)atof(findarg(filestreams[filestreamindex].buf + filestreams[filestreamindex].pos, argument));
8846     }
8847     else
8848     {
8849         printf("Invalid type for argument converted to (getfilestreamargument).\n");
8850         return E_FAIL;
8851     }
8852 
8853     return S_OK;
8854 }
8855 
openbor_filestreamnextline(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8856 HRESULT openbor_filestreamnextline(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8857 {
8858     ScriptVariant *arg = NULL;
8859     char *buf;
8860     size_t pos;
8861     LONG filestreamindex;
8862 
8863     if(paramCount < 1)
8864     {
8865         *pretvar = NULL;
8866         return E_FAIL;
8867     }
8868 
8869     arg = varlist[0];
8870     if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
8871     {
8872         return S_OK;
8873     }
8874     pos = filestreams[filestreamindex].pos;
8875     buf = filestreams[filestreamindex].buf;
8876     while(buf[pos] && buf[pos] != '\n' && buf[pos] != '\r')
8877     {
8878         ++pos;
8879     }
8880     while(buf[pos] == '\n' || buf[pos] == '\r')
8881     {
8882         ++pos;
8883     }
8884     filestreams[filestreamindex].pos = pos;
8885 
8886     return S_OK;
8887 }
8888 
openbor_getfilestreamposition(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8889 HRESULT openbor_getfilestreamposition(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8890 {
8891     ScriptVariant *arg = NULL;
8892     LONG filestreamindex;
8893 
8894     if(paramCount < 1)
8895     {
8896         *pretvar = NULL;
8897         return E_FAIL;
8898     }
8899 
8900     arg = varlist[0];
8901     if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
8902     {
8903         return S_OK;
8904     }
8905 
8906     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
8907     (*pretvar)->lVal = (LONG)filestreams[filestreamindex].pos;
8908     return S_OK;
8909 }
8910 
openbor_setfilestreamposition(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8911 HRESULT openbor_setfilestreamposition(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8912 {
8913     ScriptVariant *arg = NULL;
8914     LONG filestreamindex, position;
8915 
8916 
8917     if(paramCount < 2)
8918     {
8919         *pretvar = NULL;
8920         return E_FAIL;
8921     }
8922 
8923     arg = varlist[0];
8924     if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
8925     {
8926         return S_OK;
8927     }
8928 
8929     arg = varlist[1];
8930     if(FAILED(ScriptVariant_IntegerValue(arg, &position)))
8931     {
8932         return S_OK;
8933     }
8934 
8935     filestreams[filestreamindex].pos = position;
8936     return S_OK;
8937 }
8938 
openbor_filestreamappend(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)8939 HRESULT openbor_filestreamappend(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
8940 {
8941     LONG filestreamindex;
8942     ScriptVariant *arg = NULL;
8943     LONG appendtype = -1;
8944     size_t len1, len2;
8945     char *temp;
8946     static char append[2048];
8947 
8948     *pretvar = NULL;
8949     if(paramCount < 2)
8950     {
8951         goto append_error;
8952     }
8953 
8954     arg = varlist[0];
8955     if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
8956     {
8957         goto append_error;
8958     }
8959 
8960     if(paramCount >= 3)
8961     {
8962         arg = varlist[2];
8963         if(FAILED(ScriptVariant_IntegerValue(arg, &appendtype)))
8964         {
8965             goto append_error;
8966         }
8967     }
8968 
8969     arg = varlist[1];
8970     ScriptVariant_ToString(arg, append);
8971 
8972     len1 = strlen(append);
8973     len2 = filestreams[filestreamindex].size;
8974 
8975     filestreams[filestreamindex].buf = realloc(filestreams[filestreamindex].buf, sizeof(*temp) * (len1 + len2 + 4));
8976 
8977     if(appendtype == 0)
8978     {
8979         append[len1] = ' ';
8980         append[++len1] = '\0';
8981         strcpy(filestreams[filestreamindex].buf + len2, "\r\n");
8982         len2 += 2;
8983         strcpy(filestreams[filestreamindex].buf + len2, append);
8984     }
8985     else if(appendtype == 1)
8986     {
8987         append[len1] = ' ';
8988         append[++len1] = '\0';
8989         strcpy(filestreams[filestreamindex].buf + len2, append);
8990     }
8991     else
8992     {
8993         strcpy(filestreams[filestreamindex].buf + len2, append);
8994     }
8995     filestreams[filestreamindex].size = len1 + len2;
8996 
8997     return S_OK;
8998 
8999 append_error:
9000     return E_FAIL;
9001 
9002 }
9003 
openbor_createfilestream(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9004 HRESULT openbor_createfilestream(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9005 {
9006     int fsindex;
9007     ScriptVariant_Clear(*pretvar);
9008 
9009     for(fsindex = 0; fsindex < numfilestreams; fsindex++)
9010     {
9011         if(filestreams[fsindex].buf == NULL)
9012         {
9013             break;
9014         }
9015     }
9016 
9017     if(fsindex == numfilestreams)
9018     {
9019         __realloc(filestreams, numfilestreams); //warning, don't ++ here, its a macro
9020         numfilestreams++;
9021     }
9022 
9023     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9024     (*pretvar)->lVal = (LONG)fsindex;
9025 
9026     // Initialize the new filestream
9027     filestreams[fsindex].pos = 0;
9028     filestreams[fsindex].size = 0;
9029     filestreams[fsindex].buf = malloc(sizeof(*filestreams[fsindex].buf) * 128);
9030     filestreams[fsindex].buf[0] = '\0';
9031     return S_OK;
9032 }
9033 
openbor_savefilestream(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9034 HRESULT openbor_savefilestream(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9035 {
9036     int i;
9037     LONG filestreamindex;
9038     ScriptVariant *arg = NULL;
9039     FILE *handle = NULL;
9040     char path[256] = {""};
9041     char tmpname[256] = {""};
9042 
9043     *pretvar = NULL;
9044 
9045     if(paramCount < 1)
9046     {
9047         return E_FAIL;
9048     }
9049 
9050     arg = varlist[0];
9051     if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
9052     {
9053         printf("You must give a valid filestrema handle for savefilestream!\n");
9054         return E_FAIL;
9055     }
9056 
9057     arg = varlist[1];
9058     if(arg->vt != VT_STR)
9059     {
9060         printf("Filename for savefilestream must be a string.\n");
9061         return E_FAIL;
9062     }
9063 
9064     // Get the saves directory
9065     getBasePath(path, "Saves", 0);
9066     getPakName(tmpname, -1);
9067     strcat(path, tmpname);
9068 
9069     // Add user's filename to path and write the filestream to it
9070     strcat(path, "/");
9071     strcat(path, (char *)StrCache_Get(arg->strVal));
9072 
9073     for(i = strlen(path) - 1; i >= 0; i--)
9074     {
9075 
9076         if(path[i] == '/' || path[i] == '\\')
9077         {
9078             path[i] = 0;
9079             // Make folder if it doesn't exist
9080 #ifndef DC
9081             dirExists(path, 1);
9082 #endif
9083             path[i] = '/';
9084             break;
9085         }
9086     }
9087 
9088     //printf("save path: %s", path);
9089     handle = fopen(path, "wb");
9090     if(handle == NULL)
9091     {
9092         return E_FAIL;
9093     }
9094     fwrite(filestreams[filestreamindex].buf, 1, strlen(filestreams[filestreamindex].buf), handle);
9095 
9096     // add blank line so it can be read successfully
9097     fwrite("\r\n", 1, 2, handle);
9098     fclose(handle);
9099 
9100     return S_OK;
9101 }
9102 
openbor_closefilestream(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9103 HRESULT openbor_closefilestream(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9104 {
9105     LONG filestreamindex;
9106     ScriptVariant *arg = NULL;
9107 
9108     *pretvar = NULL;
9109 
9110     if(paramCount < 1)
9111     {
9112         return E_FAIL;
9113     }
9114 
9115     arg = varlist[0];
9116     if(FAILED(ScriptVariant_IntegerValue(arg, &filestreamindex)))
9117     {
9118         return E_FAIL;
9119     }
9120 
9121 
9122     if(filestreams[filestreamindex].buf)
9123     {
9124         free(filestreams[filestreamindex].buf);
9125         filestreams[filestreamindex].buf = NULL;
9126     }
9127     return S_OK;
9128 }
9129 
mapstrings_attackproperty(ScriptVariant ** varlist,int paramCount)9130 int mapstrings_attackproperty(ScriptVariant **varlist, int paramCount)
9131 {
9132     char *propname;
9133     int prop;
9134     if(paramCount < 2)
9135     {
9136         return 1;
9137     }
9138     MAPSTRINGS(varlist[0], eplist_attack, _ep_attack_the_end,
9139                "'%s' is not a valid attack property.\n");
9140 
9141     return 1;
9142 }
9143 
9144 //changeattackproperty(propname, value1[, value2, value3, ...]);
openbor_changeattackproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9145 HRESULT openbor_changeattackproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9146 {
9147     //LONG ltemp;
9148     DOUBLE dbltemp;
9149     int prop;
9150     ScriptVariant *arg = NULL;
9151 
9152     *pretvar = NULL;
9153 
9154     if(paramCount < 2)
9155     {
9156         return E_FAIL;
9157     }
9158 
9159     mapstrings_attackproperty(varlist, paramCount);
9160     if(varlist[0]->vt != VT_INTEGER)
9161     {
9162         printf("You must give a string value for spawn entry property name.\n");
9163         return E_FAIL;
9164     }
9165 
9166     prop = varlist[0]->lVal;
9167 
9168     arg = varlist[1];
9169 
9170     if(FAILED(ScriptVariant_DecimalValue(arg, &dbltemp)))
9171     {
9172         goto cap_error;
9173     }
9174 
9175     switch(prop)
9176     {
9177     case _ep_attack_blast:
9178         attack.blast = (int)dbltemp;
9179         break;
9180     case _ep_attack_direction:
9181         attack.force_direction = (int)dbltemp;
9182         break;
9183     case _ep_attack_dol:
9184         attack.damage_on_landing = (int)dbltemp;
9185         break;
9186     case _ep_attack_dot:
9187         attack.dot = (int)dbltemp;
9188         break;
9189     case _ep_attack_dotforce:
9190         attack.dot_force = (int)dbltemp;
9191         break;
9192     case _ep_attack_dotindex:
9193         attack.dot_index = (int)dbltemp;
9194         break;
9195     case _ep_attack_dotrate:
9196         attack.dot_rate = (int)dbltemp;
9197         break;
9198     case _ep_attack_dottime:
9199         attack.dot_time = (int)dbltemp;
9200         break;
9201     case _ep_attack_drop:
9202         attack.attack_drop = (int)dbltemp;
9203         break;
9204     case _ep_attack_dropv:
9205         attack.dropv[0] = (float)dbltemp;
9206         if(paramCount > 2)
9207         {
9208             if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
9209             {
9210                 attack.dropv[1] = (float)dbltemp;
9211             }
9212             else
9213             {
9214                 goto cap_error;
9215             }
9216         }
9217         if(paramCount > 3)
9218         {
9219             if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
9220             {
9221                 attack.dropv[2] = (float)dbltemp;
9222             }
9223             else
9224             {
9225                 goto cap_error;
9226             }
9227         }
9228         break;
9229     case _ep_attack_force:
9230         attack.attack_force = (int)dbltemp;
9231         break;
9232     case _ep_attack_forcemap:
9233         attack.forcemap = (int)dbltemp;
9234         break;
9235     case _ep_attack_freeze:
9236         attack.freeze = (int)dbltemp;
9237         break;
9238     case _ep_attack_freezetime:
9239         attack.freezetime = (int)dbltemp;
9240         break;
9241     case _ep_attack_grab:
9242         attack.grab = (int)dbltemp;
9243         break;
9244     case _ep_attack_grabdistance:
9245         attack.grab_distance = (int)dbltemp;
9246         break;
9247     case _ep_attack_guardcost:
9248         attack.guardcost = (int)dbltemp;
9249         break;
9250     case _ep_attack_jugglecost:
9251         attack.jugglecost = (int)dbltemp;
9252         break;
9253     case _ep_attack_maptime:
9254         attack.maptime = (int)dbltemp;
9255         break;
9256     case _ep_attack_nokill:
9257         attack.no_kill = (int)dbltemp;
9258         break;
9259     case _ep_attack_nopain:
9260         attack.no_pain = (int)dbltemp;
9261         break;
9262     case _ep_attack_otg:
9263         attack.otg = (int)dbltemp;
9264         break;
9265     case _ep_attack_seal:
9266         attack.seal = (int)dbltemp;
9267         break;
9268     case _ep_attack_sealtime:
9269         attack.sealtime = (int)dbltemp;
9270         break;
9271     case _ep_attack_type:
9272         attack.attack_type = (int)dbltemp;
9273         break;
9274     case _ep_attack_reset:
9275         attack = emptyattack;
9276         break;
9277     default:
9278         //printf("Property name '%s' is not supported by setspawnentry.\n", propname);
9279         goto cap_error;
9280     }
9281 
9282     return S_OK;
9283 cap_error:
9284 
9285     return E_FAIL;
9286 }
9287 
9288 //damageentity(entity, other, force, drop, type)
openbor_damageentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9289 HRESULT openbor_damageentity(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9290 {
9291     entity *ent = NULL;
9292     entity *other = NULL;
9293     entity *temp = NULL;
9294     LONG force, drop, type;
9295     s_attack atk;
9296 
9297     if(paramCount < 1)
9298     {
9299         printf("Function requires at least 1 parameter.\n");
9300         goto de_error;
9301     }
9302 
9303     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9304     (*pretvar)->lVal = (LONG)0;
9305 
9306     ent = (entity *)(varlist[0])->ptrVal; //retrieve the entity
9307     if(!ent)
9308     {
9309         printf("Invalid entity parameter.\n");
9310         goto de_error;
9311     }
9312 
9313     other = ent;
9314 
9315     if(paramCount >= 2 && varlist[1]->ptrVal)
9316     {
9317         other = (entity *)(varlist[1])->ptrVal;
9318     }
9319 
9320     if(paramCount >= 3 )
9321     {
9322         force = (LONG)1;
9323         drop = (LONG)0;
9324         type = (LONG)ATK_NORMAL;
9325 
9326         if(FAILED(ScriptVariant_IntegerValue((varlist[2]), &force)))
9327         {
9328             printf("Wrong force value.\n");
9329             goto de_error;
9330         }
9331 
9332         if(paramCount >= 4)
9333         {
9334             if(FAILED(ScriptVariant_IntegerValue((varlist[3]), &drop)))
9335             {
9336                 printf("Wrong drop value.\n");
9337                 goto de_error;
9338             }
9339         }
9340         if(paramCount >= 5)
9341         {
9342             if(FAILED(ScriptVariant_IntegerValue((varlist[4]), &type)))
9343             {
9344                 printf("Wrong type value.\n");
9345                 goto de_error;
9346             }
9347         }
9348 
9349         atk = emptyattack;
9350         atk.attack_force = force;
9351         atk.attack_drop = drop;
9352         if(drop)
9353         {
9354             atk.dropv[0] = (float)3;
9355             atk.dropv[1] = (float)1.2;
9356             atk.dropv[2] = (float)0;
9357         }
9358         atk.attack_type = type;
9359     }
9360     else
9361     {
9362         atk = attack;
9363     }
9364 
9365     if(!ent->takedamage)
9366     {
9367         ent->health -= atk.attack_force;
9368         if(ent->health <= 0)
9369         {
9370             kill(ent);
9371         }
9372         (*pretvar)->lVal = (LONG)1;
9373     }
9374     else
9375     {
9376         temp = self;
9377         self = ent;
9378         (*pretvar)->lVal = (LONG)self->takedamage(other, &atk);
9379         self = temp;
9380     }
9381     return S_OK;
9382 
9383 de_error:
9384     *pretvar = NULL;
9385     return E_FAIL;
9386 }
9387 
9388 //killentity(entity)
openbor_killentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9389 HRESULT openbor_killentity(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9390 {
9391     entity *ent = NULL;
9392 
9393     if(paramCount < 1)
9394     {
9395         *pretvar = NULL;
9396         return E_FAIL;
9397     }
9398 
9399     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9400 
9401     ent = (entity *)(varlist[0])->ptrVal; //retrieve the entity
9402     if(!ent)
9403     {
9404         (*pretvar)->lVal = (LONG)0;
9405         return S_OK;
9406     }
9407     kill(ent);
9408     (*pretvar)->lVal = (LONG)1;
9409     return S_OK;
9410 }
9411 
9412 //findtarget(entity, int animation);
openbor_findtarget(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9413 HRESULT openbor_findtarget(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9414 {
9415     int i = 0;
9416     entity *ent = NULL;
9417     entity *tempself, *target;
9418     LONG anim = -1;
9419 
9420     if(paramCount > 2)
9421     {
9422         ScriptVariant_IntegerValue(varlist[2], &i);
9423     }
9424 
9425     if(paramCount < 1)
9426     {
9427         *pretvar = NULL;
9428         return E_FAIL;
9429     }
9430 
9431     ScriptVariant_ChangeType(*pretvar, VT_PTR);
9432 
9433     ent = (entity *)(varlist[0])->ptrVal; //retrieve the entity
9434     if(!ent)
9435     {
9436         ScriptVariant_Clear(*pretvar);
9437         return S_OK;
9438     }
9439     if(paramCount > 1 && FAILED(ScriptVariant_IntegerValue(varlist[1], &anim)))
9440     {
9441         return E_FAIL;
9442     }
9443     tempself = self;
9444     self = ent;
9445     target = normal_find_target((int)anim, i);
9446     if(!target)
9447     {
9448         ScriptVariant_Clear(*pretvar);
9449     }
9450     else
9451     {
9452         (*pretvar)->ptrVal = (VOID *)target;
9453     }
9454     self = tempself;
9455     return S_OK;
9456 }
9457 
9458 //checkrange(entity, target, int ani);
openbor_checkrange(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9459 HRESULT openbor_checkrange(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9460 {
9461     entity *ent = NULL, *target = NULL;
9462     LONG ani = 0;
9463     extern int max_animations;
9464 
9465     if(paramCount < 2)
9466     {
9467         goto checkrange_error;
9468     }
9469 
9470     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9471 
9472     if(varlist[0]->vt != VT_PTR || varlist[1]->vt != VT_PTR)
9473     {
9474         goto checkrange_error;
9475     }
9476 
9477     ent = (entity *)(varlist[0])->ptrVal; //retrieve the entity
9478     target = (entity *)(varlist[1])->ptrVal; //retrieve the target
9479 
9480     if(!ent || !target)
9481     {
9482         goto checkrange_error;
9483     }
9484 
9485     if(paramCount > 2 && FAILED(ScriptVariant_IntegerValue(varlist[2], &ani)))
9486     {
9487         goto checkrange_error;
9488     }
9489     else if(paramCount <= 2)
9490     {
9491         ani = ent->animnum;
9492     }
9493 
9494     if(ani < 0 || ani >= max_animations)
9495     {
9496         printf("Animation id out of range: %d / %d.\n", (int)ani, max_animations);
9497         goto checkrange_error;
9498     }
9499 
9500     (*pretvar)->lVal = check_range(ent, target, ani);
9501 
9502     return S_OK;
9503 
9504 checkrange_error:
9505     printf("Function needs at least 2 valid entity handles, the third parameter is optional: checkrange(entity, target, int animnum)\n");
9506     *pretvar = NULL;
9507     return E_FAIL;
9508 }
9509 
9510 //clearspawnentry();
openbor_clearspawnentry(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9511 HRESULT openbor_clearspawnentry(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9512 {
9513     *pretvar = NULL;
9514     memset(&spawnentry, 0, sizeof(spawnentry));
9515     spawnentry.index = spawnentry.itemindex = spawnentry.weaponindex = -1;
9516     return S_OK;
9517 }
9518 
9519 // ===== setspawnentry =====
9520 enum setspawnentry_enum
9521 {
9522     _sse_2phealth,
9523     _sse_2pitem,
9524     _sse_3phealth,
9525     _sse_3pitem,
9526     _sse_4phealth,
9527     _sse_4pitem,
9528     _sse_aggression,
9529     _sse_alias,
9530     _sse_alpha,
9531     _sse_boss,
9532     _sse_coords,
9533     _sse_credit,
9534     _sse_dying,
9535     _sse_flip,
9536     _sse_health,
9537     _sse_item,
9538     _sse_itemalias,
9539     _sse_itemhealth,
9540     _sse_itemmap,
9541     _sse_map,
9542     _sse_mp,
9543     _sse_multiple,
9544     _sse_name,
9545     _sse_nolife,
9546     _sse_weapon,
9547     _sse_the_end,
9548 };
9549 
mapstrings_setspawnentry(ScriptVariant ** varlist,int paramCount)9550 int mapstrings_setspawnentry(ScriptVariant **varlist, int paramCount)
9551 {
9552     char *propname;
9553     int prop;
9554     static const char *proplist[] =
9555     {
9556         "2phealth",
9557         "2pitem",
9558         "3phealth",
9559         "3pitem",
9560         "4phealth",
9561         "4pitem",
9562         "aggression",
9563         "alias",
9564         "alpha",
9565         "boss",
9566         "coords",
9567         "credit",
9568         "dying",
9569         "flip",
9570         "health",
9571         "item",
9572         "itemalias",
9573         "itemhealth",
9574         "itemmap",
9575         "map",
9576         "mp",
9577         "multiple",
9578         "name",
9579         "nolife",
9580         "weapon",
9581     };
9582 
9583     MAPSTRINGS(varlist[0], proplist, _sse_the_end,
9584                "Property name '%s' is not supported by setspawnentry.\n");
9585 
9586     return 1;
9587 }
9588 
9589 //setspawnentry(propname, value1[, value2, value3, ...]);
openbor_setspawnentry(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9590 HRESULT openbor_setspawnentry(ScriptVariant **varlist, ScriptVariant **pretvar, int paramCount)
9591 {
9592     LONG ltemp;
9593     s_model *tempmodel;
9594     DOUBLE dbltemp;
9595     int temp, prop;
9596     ScriptVariant *arg = NULL;
9597 
9598     if(paramCount < 2)
9599     {
9600         *pretvar = NULL;
9601         return E_FAIL;
9602     }
9603 
9604     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
9605     (*pretvar)->lVal = (LONG)1;
9606 
9607     mapstrings_setspawnentry(varlist, paramCount);
9608     if(varlist[0]->vt != VT_INTEGER)
9609     {
9610         if(varlist[0]->vt != VT_STR)
9611         {
9612             printf("You must give a string value for spawn entry property name.\n");
9613         }
9614         *pretvar = NULL;
9615         return E_FAIL;
9616     }
9617 
9618     prop = varlist[0]->lVal;
9619 
9620     arg = varlist[1];
9621 
9622     switch(prop)
9623     {
9624     case _sse_name:
9625         if(arg->vt != VT_STR)
9626         {
9627             printf("You must use a string value for spawn entry's name property: function setspawnentry.\n");
9628             goto setspawnentry_error;
9629         }
9630         spawnentry.model = findmodel((char *)StrCache_Get(arg->strVal));
9631         break;
9632     case _sse_alias:
9633         if(arg->vt != VT_STR)
9634         {
9635             goto setspawnentry_error;
9636         }
9637         strcpy(spawnentry.alias, (char *)StrCache_Get(arg->strVal));
9638         break;
9639     case _sse_item:
9640         if(arg->vt != VT_STR)
9641         {
9642             goto setspawnentry_error;
9643         }
9644         spawnentry.itemmodel = findmodel((char *)StrCache_Get(arg->strVal));
9645         spawnentry.item = spawnentry.itemmodel->name;
9646         spawnentry.itemindex = get_cached_model_index(spawnentry.item);
9647         spawnentry.itemplayer_count = 0;
9648         break;
9649     case _sse_2pitem:
9650         if(arg->vt != VT_STR)
9651         {
9652             goto setspawnentry_error;
9653         }
9654         tempmodel = findmodel((char *)StrCache_Get(arg->strVal));
9655         if(!tempmodel)
9656         {
9657             spawnentry.item = NULL;
9658         }
9659         else
9660         {
9661             spawnentry.item = tempmodel->name;
9662         }
9663         spawnentry.itemplayer_count = 1;
9664         break;
9665     case _sse_3pitem:
9666         if(arg->vt != VT_STR)
9667         {
9668             goto setspawnentry_error;
9669         }
9670         spawnentry.itemmodel = findmodel((char *)StrCache_Get(arg->strVal));
9671         spawnentry.itemplayer_count = 2;
9672         break;
9673     case _sse_4pitem:
9674         if(arg->vt != VT_STR)
9675         {
9676             goto setspawnentry_error;
9677         }
9678         spawnentry.itemmodel = findmodel((char *)StrCache_Get(arg->strVal));
9679         spawnentry.itemplayer_count = 3;
9680         break;
9681     case _sse_health:
9682         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9683         {
9684             spawnentry.health[0] = (int)ltemp;
9685         }
9686         else
9687         {
9688             (*pretvar)->lVal = (LONG)0;
9689         }
9690         break;
9691     case _sse_itemhealth:
9692         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9693         {
9694             spawnentry.itemhealth = (int)ltemp;
9695         }
9696         else
9697         {
9698             (*pretvar)->lVal = (LONG)0;
9699         }
9700         break;
9701     case _sse_itemalias:
9702         if(arg->vt != VT_STR)
9703         {
9704             return E_FAIL;
9705         }
9706         strcpy(spawnentry.itemalias, (char *)StrCache_Get(arg->strVal));
9707         break;
9708     case _sse_2phealth:
9709         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9710         {
9711             spawnentry.health[1] = (int)ltemp;
9712         }
9713         else
9714         {
9715             (*pretvar)->lVal = (LONG)0;
9716         }
9717         break;
9718     case _sse_3phealth:
9719         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9720         {
9721             spawnentry.health[2] = (int)ltemp;
9722         }
9723         else
9724         {
9725             (*pretvar)->lVal = (LONG)0;
9726         }
9727         break;
9728     case _sse_4phealth:
9729         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9730         {
9731             spawnentry.health[3] = (int)ltemp;
9732         }
9733         else
9734         {
9735             (*pretvar)->lVal = (LONG)0;
9736         }
9737         break;
9738     case _sse_coords:
9739         temp = 1;
9740         if(SUCCEEDED(ScriptVariant_DecimalValue(arg, &dbltemp)))
9741         {
9742             spawnentry.x = (float)dbltemp;
9743         }
9744         else
9745         {
9746             temp = 0;
9747         }
9748         if(paramCount >= 3 && temp)
9749         {
9750             if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &dbltemp)))
9751             {
9752                 spawnentry.z = (float)dbltemp;
9753             }
9754             else
9755             {
9756                 temp = 0;
9757             }
9758         }
9759         if(paramCount >= 4 && temp)
9760         {
9761             if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
9762             {
9763                 spawnentry.a = (float)dbltemp;
9764             }
9765             else
9766             {
9767                 temp = 0;
9768             }
9769         }
9770         (*pretvar)->lVal = (LONG)temp;
9771         break;
9772     case _sse_mp:
9773         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9774         {
9775             spawnentry.mp = (int)ltemp;
9776         }
9777         else
9778         {
9779             (*pretvar)->lVal = (LONG)0;
9780         }
9781         break;
9782     case _sse_map:
9783         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9784         {
9785             spawnentry.colourmap = (int)ltemp;
9786         }
9787         else
9788         {
9789             (*pretvar)->lVal = (LONG)0;
9790         }
9791         break;
9792     case _sse_itemmap:
9793         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9794         {
9795             spawnentry.itemmap = (int)ltemp;
9796         }
9797         else
9798         {
9799             (*pretvar)->lVal = (LONG)0;
9800         }
9801         break;
9802     case _sse_alpha:
9803         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9804         {
9805             spawnentry.alpha = (int)ltemp;
9806         }
9807         else
9808         {
9809             (*pretvar)->lVal = (LONG)0;
9810         }
9811         break;
9812     case _sse_multiple:
9813         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9814         {
9815             spawnentry.multiple = (int)ltemp;
9816         }
9817         else
9818         {
9819             (*pretvar)->lVal = (LONG)0;
9820         }
9821         break;
9822     case _sse_dying:
9823         temp = 1;
9824         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9825         {
9826             spawnentry.dying = (int)ltemp;
9827         }
9828         else
9829         {
9830             temp = 0;
9831         }
9832         if(paramCount >= 3 && temp)
9833         {
9834             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
9835             {
9836                 spawnentry.per1 = (int)ltemp;
9837             }
9838             else
9839             {
9840                 temp = 0;
9841             }
9842         }
9843         if(paramCount >= 4 && temp)
9844         {
9845             if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp)))
9846             {
9847                 spawnentry.per2 = (int)ltemp;
9848             }
9849             else
9850             {
9851                 temp = 0;
9852             }
9853         }
9854         (*pretvar)->lVal = (LONG)temp;
9855         break;
9856     case _sse_nolife:
9857         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9858         {
9859             spawnentry.nolife = (int)ltemp;
9860         }
9861         else
9862         {
9863             (*pretvar)->lVal = (LONG)0;
9864         }
9865         break;
9866     case _sse_boss:
9867         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9868         {
9869             spawnentry.boss = (int)ltemp;
9870         }
9871         else
9872         {
9873             (*pretvar)->lVal = (LONG)0;
9874         }
9875         break;
9876     case _sse_flip:
9877         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9878         {
9879             spawnentry.flip = (int)ltemp;
9880         }
9881         else
9882         {
9883             (*pretvar)->lVal = (LONG)0;
9884         }
9885         break;
9886     case _sse_credit:
9887         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9888         {
9889             spawnentry.credit = (int)ltemp;
9890         }
9891         else
9892         {
9893             (*pretvar)->lVal = (LONG)0;
9894         }
9895         break;
9896     case _sse_aggression:
9897         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
9898         {
9899             spawnentry.aggression = (int)ltemp;
9900         }
9901         else
9902         {
9903             (*pretvar)->lVal = (LONG)0;
9904         }
9905         break;
9906     case _sse_weapon:
9907         if(arg->vt != VT_STR)
9908         {
9909             goto setspawnentry_error;
9910         }
9911         spawnentry.weaponmodel = findmodel((char *)StrCache_Get(arg->strVal));
9912         break;
9913     default:
9914         //printf("Property name '%s' is not supported by setspawnentry.\n", propname);
9915         goto setspawnentry_error;
9916     }
9917 
9918     return S_OK;
9919 setspawnentry_error:
9920     *pretvar = NULL;
9921     return E_FAIL;
9922 }
9923 
9924 //spawn();
openbor_spawn(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9925 HRESULT openbor_spawn(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9926 {
9927     entity *ent;
9928 
9929     if(spawnentry.boss && level)
9930     {
9931         level->bosses++;
9932     }
9933 
9934     ent = smartspawn(&spawnentry);
9935 
9936     if(ent)
9937     {
9938         ScriptVariant_ChangeType(*pretvar, VT_PTR);
9939         (*pretvar)->ptrVal = (VOID *) ent;
9940     }
9941     else
9942     {
9943         ScriptVariant_Clear(*pretvar);
9944     }
9945 
9946     return S_OK;
9947 }
9948 
9949 //entity * projectile([0/1], char *name, float x, float z, float a, int direction, int pytype, int type, int map);
openbor_projectile(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)9950 HRESULT openbor_projectile(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
9951 {
9952     DOUBLE temp = 0;
9953     LONG ltemp = 0;
9954     entity *ent;
9955     char *name = NULL;
9956     float x = 0, z = 0, a = 0;
9957     int direction = 0;
9958     int type = 0;
9959     int ptype = 0;
9960     int map = 0;
9961 
9962     int relative;
9963 
9964     if(paramCount >= 1 && varlist[0]->vt == VT_INTEGER && varlist[0]->lVal)
9965     {
9966         relative = 1;
9967         paramCount--;
9968         varlist++;
9969     }
9970     else
9971     {
9972         relative = 0;
9973     }
9974 
9975     if(paramCount >= 1 && varlist[0]->vt == VT_STR)
9976     {
9977         name = StrCache_Get(varlist[0]->strVal);
9978     }
9979 
9980     if(paramCount >= 2 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[1], &temp)))
9981     {
9982         x = (float)temp;
9983     }
9984     else if(relative)
9985     {
9986         x = 0;
9987     }
9988     else
9989     {
9990         x = self->x;
9991     }
9992     if(paramCount >= 3 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[2], &temp)))
9993     {
9994         z = (float)temp;
9995     }
9996     else if(relative)
9997     {
9998         z = 0;
9999     }
10000     else
10001     {
10002         z = self->z;
10003     }
10004     if(paramCount >= 4 && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &temp)))
10005     {
10006         a = (float)temp;
10007     }
10008     else if(relative)
10009     {
10010         a  = self->animation->throwa;
10011     }
10012     else
10013     {
10014         a = self->a + self->animation->throwa;
10015     }
10016     if(paramCount >= 5 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp)))
10017     {
10018         direction = (int)ltemp;
10019     }
10020     else if(relative)
10021     {
10022         direction  = 1;
10023     }
10024     else
10025     {
10026         direction = self->direction;
10027     }
10028     if(paramCount >= 6 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[5], &ltemp)))
10029     {
10030         ptype = (int)ltemp;
10031     }
10032     if(paramCount >= 7 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[6], &ltemp)))
10033     {
10034         type = (int)ltemp;
10035     }
10036     if(paramCount >= 8 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[7], &ltemp)))
10037     {
10038         map = (int)ltemp;
10039     }
10040 
10041     if(relative)
10042     {
10043         if(self->direction)
10044         {
10045             x += self->x;
10046         }
10047         else
10048         {
10049             x = self->x - x;
10050             direction = !direction;
10051         }
10052         z += self->z;
10053         a += self->a;
10054     }
10055 
10056     switch(type)
10057     {
10058     default:
10059     case 0:
10060         ent = knife_spawn(name, -1, x, z, a, direction, ptype, map);
10061         break;
10062     case 1:
10063         ent = bomb_spawn(name, -1, x, z, a, direction, map);
10064         break;
10065     }
10066 
10067     ScriptVariant_ChangeType(*pretvar, VT_PTR);
10068     (*pretvar)->ptrVal = (VOID *) ent;
10069 
10070     return S_OK;
10071 }
10072 
10073 
10074 // ===== openborconstant =====
10075 #define IICMPCONST(x) \
10076 if(stricmp(#x, constname)==0) {\
10077 	v.lVal = (LONG)x;\
10078 }
10079 
10080 
10081 #define ICMPCONST(x) \
10082 else if(stricmp(#x, constname)==0) {\
10083 	v.lVal = (LONG)x;\
10084 }
10085 
10086 #define ICMPSCONSTA(x, y) \
10087 else if(strnicmp(constname, #x, sizeof(#x)-1)==0 && constname[sizeof(#x)-1] >= '1' && constname[sizeof(#x)-1]<='9') \
10088 { \
10089 	v.lVal = (LONG)(y[atoi(constname+(sizeof(#x)-1))-1]);\
10090 }
10091 
10092 #define ICMPSCONSTB(x, y) \
10093 else if(strnicmp(constname, #x, sizeof(#x)-1)==0 && constname[sizeof(#x)-1] >= '1' && constname[sizeof(#x)-1]<='9') \
10094 { \
10095 	v.lVal = (LONG)(y[atoi(constname+(sizeof(#x)-1))+STA_ATKS-1]);\
10096 }
10097 
10098 #define ICMPSCONSTC(x) \
10099 else if(strnicmp(constname, #x, sizeof(#x)-1)==0 && constname[sizeof(#x)-1] >= '1' && constname[sizeof(#x)-1]<='9') \
10100 { \
10101 	v.lVal = (LONG)(atoi(constname+(sizeof(#x)-1))+STA_ATKS-1);\
10102 }
10103 
mapstrings_transconst(ScriptVariant ** varlist,int paramCount)10104 int mapstrings_transconst(ScriptVariant **varlist, int paramCount)
10105 {
10106     char *constname = NULL;
10107     int found = TRUE;
10108     ScriptVariant v;
10109 
10110     if(paramCount < 1)
10111     {
10112         return 1;
10113     }
10114 
10115     if(varlist[0]->vt == VT_STR)
10116     {
10117         ScriptVariant_Init(&v);
10118         ScriptVariant_ChangeType(&v, VT_INTEGER);
10119         constname = (char *)StrCache_Get(varlist[0]->strVal);
10120 
10121         IICMPCONST(COMPATIBLEVERSION)
10122         ICMPCONST(VT_EMPTY)
10123         ICMPCONST(VT_STR)
10124         ICMPCONST(VT_INTEGER)
10125         ICMPCONST(VT_DECIMAL)
10126         ICMPCONST(VT_PTR)
10127         ICMPCONST(MIN_INT)
10128         ICMPCONST(MAX_INT)
10129         ICMPCONST(PIXEL_8)
10130         ICMPCONST(PIXEL_x8)
10131         ICMPCONST(PIXEL_16)
10132         ICMPCONST(PIXEL_32)
10133         ICMPCONST(CV_SAVED_GAME)
10134         ICMPCONST(CV_HIGH_SCORE)
10135         ICMPCONST(THINK_SPEED)
10136         ICMPCONST(COUNTER_SPEED)
10137         ICMPCONST(MAX_ENTS)
10138         ICMPCONST(MAX_PANELS)
10139         ICMPCONST(MAX_WEAPONS)
10140         ICMPCONST(MAX_COLOUR_MAPS)
10141         ICMPCONST(MAX_NAME_LEN)
10142         ICMPCONST(LEVEL_MAX_SPAWNS)
10143         ICMPCONST(LEVEL_MAX_PANELS)
10144         ICMPCONST(LEVEL_MAX_HOLES)
10145         ICMPCONST(LEVEL_MAX_WALLS)
10146         ICMPCONST(MAX_LEVELS)
10147         ICMPCONST(MAX_DIFFICULTIES)
10148         ICMPCONST(MAX_SPECIALS)
10149         ICMPCONST(MAX_ATCHAIN)
10150         ICMPCONST(MAX_ATTACKS)
10151         ICMPCONST(MAX_FOLLOWS)
10152         ICMPCONST(MAX_PLAYERS)
10153         ICMPCONST(MAX_ARG_LEN)
10154         ICMPCONST(FLAG_ESC)
10155         ICMPCONST(FLAG_START)
10156         ICMPCONST(FLAG_MOVELEFT)
10157         ICMPCONST(FLAG_MOVERIGHT)
10158         ICMPCONST(FLAG_MOVEUP)
10159         ICMPCONST(FLAG_MOVEDOWN)
10160         ICMPCONST(FLAG_ATTACK)
10161         ICMPCONST(FLAG_ATTACK2)
10162         ICMPCONST(FLAG_ATTACK3)
10163         ICMPCONST(FLAG_ATTACK4)
10164         ICMPCONST(FLAG_JUMP)
10165         ICMPCONST(FLAG_SPECIAL)
10166         ICMPCONST(FLAG_SCREENSHOT)
10167         ICMPCONST(FLAG_ANYBUTTON)
10168         ICMPCONST(FLAG_FORWARD)
10169         ICMPCONST(FLAG_BACKWARD)
10170         ICMPCONST(SDID_MOVEUP)
10171         ICMPCONST(SDID_MOVEDOWN)
10172         ICMPCONST(SDID_MOVELEFT)
10173         ICMPCONST(SDID_MOVERIGHT)
10174         ICMPCONST(SDID_SPECIAL)
10175         ICMPCONST(SDID_ATTACK)
10176         ICMPCONST(SDID_ATTACK2)
10177         ICMPCONST(SDID_ATTACK3)
10178         ICMPCONST(SDID_ATTACK4)
10179         ICMPCONST(SDID_JUMP)
10180         ICMPCONST(SDID_START)
10181         ICMPCONST(SDID_SCREENSHOT)
10182         ICMPCONST(TYPE_NONE)
10183         ICMPCONST(TYPE_PLAYER)
10184         ICMPCONST(TYPE_ENEMY)
10185         ICMPCONST(TYPE_ITEM)
10186         ICMPCONST(TYPE_OBSTACLE)
10187         ICMPCONST(TYPE_STEAMER)
10188         ICMPCONST(TYPE_SHOT)
10189         ICMPCONST(TYPE_TRAP)
10190         ICMPCONST(TYPE_TEXTBOX)
10191         ICMPCONST(TYPE_ENDLEVEL)
10192         ICMPCONST(TYPE_NPC)
10193         ICMPCONST(TYPE_PANEL)
10194         ICMPCONST(TYPE_MAX)
10195         ICMPCONST(TYPE_RESERVED)
10196         ICMPCONST(SUBTYPE_NONE)
10197         ICMPCONST(SUBTYPE_BIKER)
10198         ICMPCONST(SUBTYPE_NOTGRAB)
10199         ICMPCONST(SUBTYPE_ARROW)
10200         ICMPCONST(SUBTYPE_TOUCH)
10201         ICMPCONST(SUBTYPE_WEAPON)
10202         ICMPCONST(SUBTYPE_NOSKIP)
10203         ICMPCONST(SUBTYPE_FLYDIE)
10204         ICMPCONST(SUBTYPE_BOTH)
10205         ICMPCONST(SUBTYPE_PROJECTILE)
10206         ICMPCONST(SUBTYPE_FOLLOW)
10207         ICMPCONST(SUBTYPE_CHASE)
10208         ICMPCONST(AIMOVE1_NORMAL)
10209         ICMPCONST(AIMOVE1_CHASE)
10210         ICMPCONST(AIMOVE1_CHASEZ)
10211         ICMPCONST(AIMOVE1_CHASEX)
10212         ICMPCONST(AIMOVE1_AVOID)
10213         ICMPCONST(AIMOVE1_AVOIDZ)
10214         ICMPCONST(AIMOVE1_AVOIDX)
10215         ICMPCONST(AIMOVE1_WANDER)
10216         ICMPCONST(AIMOVE1_NOMOVE)
10217         ICMPCONST(AIMOVE1_BIKER)
10218         ICMPCONST(AIMOVE1_STAR)
10219         ICMPCONST(AIMOVE1_ARROW)
10220         ICMPCONST(AIMOVE1_BOMB)
10221         ICMPCONST(AIMOVE2_NORMAL)
10222         ICMPCONST(AIMOVE2_IGNOREHOLES)
10223         ICMPCONST(AIATTACK1_NORMAL)
10224         ICMPCONST(AIATTACK1_LONG)
10225         ICMPCONST(AIATTACK1_MELEE)
10226         ICMPCONST(AIATTACK1_NOATTACK)
10227         ICMPCONST(AIATTACK1_ALWAYS)
10228         ICMPCONST(AIATTACK2_NORMAL)
10229         ICMPCONST(AIATTACK2_DODGE)
10230         ICMPCONST(AIATTACK2_DODGEMOVE)
10231         ICMPCONST(FRONTPANEL_Z)
10232         ICMPCONST(HOLE_Z)
10233         ICMPCONST(NEONPANEL_Z)
10234         ICMPCONST(SHADOW_Z)
10235         ICMPCONST(SCREENPANEL_Z)
10236         ICMPCONST(PANEL_Z)
10237         ICMPCONST(MIRROR_Z)
10238         ICMPCONST(PIT_DEPTH)
10239         ICMPCONST(P2_STATS_DIST)
10240         ICMPCONST(CONTACT_DIST_H)
10241         ICMPCONST(CONTACT_DIST_V)
10242         ICMPCONST(GRAB_DIST)
10243         ICMPCONST(GRAB_STALL)
10244         ICMPCONST(ATK_NORMAL)
10245         ICMPCONST(ATK_NORMAL2)
10246         ICMPCONST(ATK_NORMAL3)
10247         ICMPCONST(ATK_NORMAL4)
10248         ICMPCONST(ATK_BLAST)
10249         ICMPCONST(ATK_BURN)
10250         ICMPCONST(ATK_FREEZE)
10251         ICMPCONST(ATK_SHOCK)
10252         ICMPCONST(ATK_STEAL)
10253         ICMPCONST(ATK_NORMAL5)
10254         ICMPCONST(ATK_NORMAL6)
10255         ICMPCONST(ATK_NORMAL7)
10256         ICMPCONST(ATK_NORMAL8)
10257         ICMPCONST(ATK_NORMAL9)
10258         ICMPCONST(ATK_NORMAL10)
10259         ICMPCONST(ATK_ITEM)
10260         ICMPCONST(ATK_LAND)
10261         ICMPCONST(ATK_PIT)
10262         ICMPCONST(ATK_LIFESPAN)
10263         ICMPCONST(ATK_TIMEOVER)
10264         ICMPCONST(SCROLL_RIGHT)
10265         ICMPCONST(SCROLL_DOWN)
10266         ICMPCONST(SCROLL_LEFT)
10267         ICMPCONST(SCROLL_UP)
10268         ICMPCONST(SCROLL_BOTH)
10269         ICMPCONST(SCROLL_LEFTRIGHT)
10270         ICMPCONST(SCROLL_RIGHTLEFT)
10271         ICMPCONST(SCROLL_INWARD)
10272         ICMPCONST(SCROLL_OUTWARD)
10273         ICMPCONST(SCROLL_INOUT)
10274         ICMPCONST(SCROLL_OUTIN)
10275         ICMPCONST(SCROLL_UPWARD)
10276         ICMPCONST(SCROLL_DOWNWARD)
10277         ICMPCONST(ANI_IDLE)
10278         ICMPCONST(ANI_WALK)
10279         ICMPCONST(ANI_JUMP)
10280         ICMPCONST(ANI_LAND)
10281         ICMPCONST(ANI_PAIN)
10282         ICMPCONST(ANI_FALL)
10283         ICMPCONST(ANI_RISE)
10284         ICMPCONST(ANI_UPPER)
10285         ICMPCONST(ANI_BLOCK)
10286         ICMPCONST(ANI_JUMPATTACK)
10287         ICMPCONST(ANI_JUMPATTACK2)
10288         ICMPCONST(ANI_GET)
10289         ICMPCONST(ANI_GRAB)
10290         ICMPCONST(ANI_GRABATTACK)
10291         ICMPCONST(ANI_GRABATTACK2)
10292         ICMPCONST(ANI_THROW)
10293         ICMPCONST(ANI_SPECIAL)
10294         ICMPCONST(ANI_SPAWN)
10295         ICMPCONST(ANI_DIE)
10296         ICMPCONST(ANI_PICK)
10297         ICMPCONST(ANI_JUMPATTACK3)
10298         ICMPCONST(ANI_UP)
10299         ICMPCONST(ANI_DOWN)
10300         ICMPCONST(ANI_SHOCK)
10301         ICMPCONST(ANI_BURN)
10302         ICMPCONST(ANI_SHOCKPAIN)
10303         ICMPCONST(ANI_BURNPAIN)
10304         ICMPCONST(ANI_GRABBED)
10305         ICMPCONST(ANI_SPECIAL2)
10306         ICMPCONST(ANI_RUN)
10307         ICMPCONST(ANI_RUNATTACK)
10308         ICMPCONST(ANI_RUNJUMPATTACK)
10309         ICMPCONST(ANI_ATTACKUP)
10310         ICMPCONST(ANI_ATTACKDOWN)
10311         ICMPCONST(ANI_ATTACKFORWARD)
10312         ICMPCONST(ANI_ATTACKBACKWARD)
10313         ICMPCONST(ANI_RISEATTACK)
10314         ICMPCONST(ANI_DODGE)
10315         ICMPCONST(ANI_ATTACKBOTH)
10316         ICMPCONST(ANI_GRABFORWARD)
10317         ICMPCONST(ANI_GRABFORWARD2)
10318         ICMPCONST(ANI_JUMPFORWARD)
10319         ICMPCONST(ANI_GRABDOWN)
10320         ICMPCONST(ANI_GRABDOWN2)
10321         ICMPCONST(ANI_GRABUP)
10322         ICMPCONST(ANI_GRABUP2)
10323         ICMPCONST(ANI_SELECT)
10324         ICMPCONST(ANI_DUCK)
10325         ICMPCONST(ANI_FAINT)
10326         ICMPCONST(ANI_CANT)
10327         ICMPCONST(ANI_THROWATTACK)
10328         ICMPCONST(ANI_CHARGEATTACK)
10329         ICMPCONST(ANI_VAULT)
10330         ICMPCONST(ANI_JUMPCANT)
10331         ICMPCONST(ANI_JUMPSPECIAL)
10332         ICMPCONST(ANI_BURNDIE)
10333         ICMPCONST(ANI_SHOCKDIE)
10334         ICMPCONST(ANI_PAIN2)
10335         ICMPCONST(ANI_PAIN3)
10336         ICMPCONST(ANI_PAIN4)
10337         ICMPCONST(ANI_FALL2)
10338         ICMPCONST(ANI_FALL3)
10339         ICMPCONST(ANI_FALL4)
10340         ICMPCONST(ANI_DIE2)
10341         ICMPCONST(ANI_DIE3)
10342         ICMPCONST(ANI_DIE4)
10343         ICMPCONST(ANI_CHARGE)
10344         ICMPCONST(ANI_BACKWALK)
10345         ICMPCONST(ANI_SLEEP)
10346         ICMPCONST(ANI_PAIN5)
10347         ICMPCONST(ANI_PAIN6)
10348         ICMPCONST(ANI_PAIN7)
10349         ICMPCONST(ANI_PAIN8)
10350         ICMPCONST(ANI_PAIN9)
10351         ICMPCONST(ANI_PAIN10)
10352         ICMPCONST(ANI_FALL5)
10353         ICMPCONST(ANI_FALL6)
10354         ICMPCONST(ANI_FALL7)
10355         ICMPCONST(ANI_FALL8)
10356         ICMPCONST(ANI_FALL9)
10357         ICMPCONST(ANI_FALL10)
10358         ICMPCONST(ANI_DIE5)
10359         ICMPCONST(ANI_DIE6)
10360         ICMPCONST(ANI_DIE7)
10361         ICMPCONST(ANI_DIE8)
10362         ICMPCONST(ANI_DIE9)
10363         ICMPCONST(ANI_DIE10)
10364         ICMPCONST(ANI_TURN)
10365         ICMPCONST(ANI_RESPAWN)
10366         ICMPCONST(ANI_FORWARDJUMP)
10367         ICMPCONST(ANI_RUNJUMP)
10368         ICMPCONST(ANI_JUMPLAND)
10369         ICMPCONST(ANI_JUMPDELAY)
10370         ICMPCONST(ANI_HITWALL)
10371         ICMPCONST(ANI_GRABBACKWARD)
10372         ICMPCONST(ANI_GRABBACKWARD2)
10373         ICMPCONST(ANI_GRABWALK)
10374         ICMPCONST(ANI_GRABBEDWALK)
10375         ICMPCONST(ANI_GRABWALKUP)
10376         ICMPCONST(ANI_GRABBEDWALKUP)
10377         ICMPCONST(ANI_GRABWALKDOWN)
10378         ICMPCONST(ANI_GRABBEDWALKDOWN)
10379         ICMPCONST(ANI_GRABTURN)
10380         ICMPCONST(ANI_GRABBEDTURN)
10381         ICMPCONST(ANI_GRABBACKWALK)
10382         ICMPCONST(ANI_GRABBEDBACKWALK)
10383         ICMPCONST(ANI_SLIDE)
10384         ICMPCONST(ANI_RUNSLIDE)
10385         ICMPCONST(ANI_BLOCKPAIN)
10386         ICMPCONST(ANI_DUCKATTACK)
10387         ICMPCONST(MAX_ANIS)
10388         ICMPCONST(PLAYER_MIN_Z)
10389         ICMPCONST(PLAYER_MAX_Z)
10390         ICMPCONST(BGHEIGHT)
10391         ICMPCONST(MAX_WALL_HEIGHT)
10392         ICMPCONST(SAMPLE_GO)
10393         ICMPCONST(SAMPLE_BEAT)
10394         ICMPCONST(SAMPLE_BLOCK)
10395         ICMPCONST(SAMPLE_INDIRECT)
10396         ICMPCONST(SAMPLE_GET)
10397         ICMPCONST(SAMPLE_GET2)
10398         ICMPCONST(SAMPLE_FALL)
10399         ICMPCONST(SAMPLE_JUMP)
10400         ICMPCONST(SAMPLE_PUNCH)
10401         ICMPCONST(SAMPLE_1UP)
10402         ICMPCONST(SAMPLE_TIMEOVER)
10403         ICMPCONST(SAMPLE_BEEP)
10404         ICMPCONST(SAMPLE_BEEP2)
10405         ICMPCONST(SAMPLE_BIKE)
10406         ICMPCONST(ANI_RISE2)
10407         ICMPCONST(ANI_RISE3)
10408         ICMPCONST(ANI_RISE4)
10409         ICMPCONST(ANI_RISE5)
10410         ICMPCONST(ANI_RISE6)
10411         ICMPCONST(ANI_RISE7)
10412         ICMPCONST(ANI_RISE8)
10413         ICMPCONST(ANI_RISE9)
10414         ICMPCONST(ANI_RISE10)
10415         ICMPCONST(ANI_RISEB)
10416         ICMPCONST(ANI_RISES)
10417         ICMPCONST(ANI_BLOCKPAIN2)
10418         ICMPCONST(ANI_BLOCKPAIN3)
10419         ICMPCONST(ANI_BLOCKPAIN4)
10420         ICMPCONST(ANI_BLOCKPAIN5)
10421         ICMPCONST(ANI_BLOCKPAIN6)
10422         ICMPCONST(ANI_BLOCKPAIN7)
10423         ICMPCONST(ANI_BLOCKPAIN8)
10424         ICMPCONST(ANI_BLOCKPAIN9)
10425         ICMPCONST(ANI_BLOCKPAIN10)
10426         ICMPCONST(ANI_BLOCKPAINB)
10427         ICMPCONST(ANI_BLOCKPAINS)
10428         ICMPCONST(ANI_CHIPDEATH)
10429         ICMPCONST(ANI_GUARDBREAK)
10430         ICMPCONST(ANI_RISEATTACK2)
10431         ICMPCONST(ANI_RISEATTACK3)
10432         ICMPCONST(ANI_RISEATTACK4)
10433         ICMPCONST(ANI_RISEATTACK5)
10434         ICMPCONST(ANI_RISEATTACK6)
10435         ICMPCONST(ANI_RISEATTACK7)
10436         ICMPCONST(ANI_RISEATTACK8)
10437         ICMPCONST(ANI_RISEATTACK9)
10438         ICMPCONST(ANI_RISEATTACK10)
10439         ICMPCONST(ANI_RISEATTACKB)
10440         ICMPCONST(ANI_RISEATTACKS)
10441         ICMPCONST(ANI_SLIDE)
10442         ICMPCONST(ANI_RUNSLIDE)
10443         ICMPCONST(ANI_DUCKATTACK)
10444         ICMPCONST(ANI_WALKOFF)
10445         ICMPCONST(ANI_FREESPECIAL)
10446         ICMPCONST(ANI_ATTACK)
10447 
10448         // for the extra animation ids
10449         ICMPSCONSTC(ATK_NORMAL)
10450         ICMPSCONSTA(ANI_DOWN, animdowns)
10451         ICMPSCONSTA(ANI_UP, animups)
10452         ICMPSCONSTA(ANI_BACKWALK, animbackwalks)
10453         ICMPSCONSTA(ANI_WALK, animwalks)
10454         ICMPSCONSTA(ANI_IDLE, animidles)
10455         ICMPSCONSTB(ANI_FALL, animfalls)
10456         ICMPSCONSTB(ANI_RISE, animrises)
10457         ICMPSCONSTB(ANI_RISEATTACK, animriseattacks)
10458         ICMPSCONSTB(ANI_PAIN, animpains)
10459         ICMPSCONSTB(ANI_DIE, animdies)
10460         ICMPSCONSTA(ANI_ATTACK, animattacks)
10461         ICMPSCONSTA(ANI_FOLLOW, animfollows)
10462         ICMPSCONSTA(ANI_FREESPECIAL, animspecials)
10463         else
10464         {
10465             found = FALSE;
10466         }
10467 
10468         if(found)
10469         {
10470             ScriptVariant_Copy(varlist[0], &v);
10471         }
10472         else
10473         {
10474             ScriptVariant_Clear(&v);
10475             printf("Can't find openbor constant '%s' \n", constname);
10476         }
10477 
10478         return found;
10479     }
10480 
10481     return 1;
10482 }
10483 //openborconstant(constname);
10484 //translate a constant by string, used to retrieve a constant or macro of openbor
openbor_transconst(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10485 HRESULT openbor_transconst(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10486 {
10487     static char buf[128];
10488     if(paramCount < 1)
10489     {
10490         goto transconst_error;
10491     }
10492 
10493     //if(varlist[0]->vt == VT_INTEGER) printf("debug: mapstring for openborconstant works!\n");
10494 
10495     mapstrings_transconst(varlist, paramCount);
10496 
10497     if(varlist[0]->vt == VT_INTEGER) // return value already determined by mapstrings
10498     {
10499         ScriptVariant_Copy((*pretvar), varlist[0]);
10500         return S_OK;
10501     }
10502 
10503 transconst_error:
10504     ScriptVariant_ToString(varlist[0], buf);
10505     printf("Can't translate constant %s\n", buf);
10506     *pretvar = NULL;
10507     return E_FAIL;
10508 }
10509 
10510 //int rgbcolor(int r, int g, int b);
openbor_rgbcolor(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10511 HRESULT openbor_rgbcolor(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10512 {
10513     LONG r, g, b;
10514 
10515     if(paramCount != 3)
10516     {
10517         goto rgbcolor_error;
10518     }
10519     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &r)))
10520     {
10521         goto rgbcolor_error;    // decimal/integer value for red?
10522     }
10523     if(FAILED(ScriptVariant_IntegerValue(varlist[1], &g)))
10524     {
10525         goto rgbcolor_error;    // decimal/integer value for green?
10526     }
10527     if(FAILED(ScriptVariant_IntegerValue(varlist[2], &b)))
10528     {
10529         goto rgbcolor_error;    // decimal/integer value for blue?
10530     }
10531 
10532     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
10533     (*pretvar)->lVal = _makecolour(r, g, b);
10534     return S_OK;
10535 
10536 rgbcolor_error:
10537     *pretvar = NULL;
10538     return E_FAIL;
10539 }
10540 
10541 // ===== playerkeys =====
10542 enum playerkeys_enum
10543 {
10544     _pk_anybutton,
10545     _pk_attack,
10546     _pk_attack2,
10547     _pk_attack3,
10548     _pk_attack4,
10549     _pk_esc,
10550     _pk_jump,
10551     _pk_movedown,
10552     _pk_moveleft,
10553     _pk_moveright,
10554     _pk_moveup,
10555     _pk_screenshot,
10556     _pk_special,
10557     _pk_start,
10558     _pk_the_end,
10559 };
10560 
mapstrings_playerkeys(ScriptVariant ** varlist,int paramCount)10561 int mapstrings_playerkeys(ScriptVariant **varlist, int paramCount)
10562 {
10563     char *propname = NULL;
10564     int i, prop;
10565 
10566     static const char *proplist[] = // for args 2+
10567     {
10568         "anybutton",
10569         "attack",
10570         "attack2",
10571         "attack3",
10572         "attack4",
10573         "esc",
10574         "jump",
10575         "movedown",
10576         "moveleft",
10577         "moveright",
10578         "moveup",
10579         "screenshot",
10580         "special",
10581         "start",
10582     };
10583 
10584     for(i = 2; i < paramCount; i++)
10585     {
10586         MAPSTRINGS(varlist[i], proplist, _pk_the_end,
10587                    "Button name '%s' is not supported by playerkeys.");
10588     }
10589 
10590     return 1;
10591 }
10592 
10593 //playerkeys(playerindex, newkey?, key1, key2, ...);
openbor_playerkeys(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10594 HRESULT openbor_playerkeys(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10595 {
10596     LONG ltemp;
10597     int index, newkey;
10598     int i;
10599     u32 keys;
10600     ScriptVariant *arg = NULL;
10601 
10602     if(paramCount < 3)
10603     {
10604         *pretvar = NULL;
10605         return E_FAIL;
10606     }
10607 
10608     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
10609     (*pretvar)->lVal = (LONG)1;
10610 
10611     mapstrings_playerkeys(varlist, paramCount);
10612 
10613     if(FAILED(ScriptVariant_IntegerValue((varlist[0]), &ltemp)))
10614     {
10615         index = 0;
10616     }
10617     else
10618     {
10619         index = (int)ltemp;
10620     }
10621 
10622     if(SUCCEEDED(ScriptVariant_IntegerValue((varlist[1]), &ltemp)))
10623     {
10624         newkey = (int)ltemp;
10625     }
10626     else
10627     {
10628         newkey = 0;
10629     }
10630 
10631     if(newkey == 1)
10632     {
10633         keys = player[index].newkeys;
10634     }
10635     else if(newkey == 2)
10636     {
10637         keys = player[index].releasekeys;
10638     }
10639     else
10640     {
10641         keys = player[index].keys;
10642     }
10643 
10644     for(i = 2; i < paramCount; i++)
10645     {
10646         arg = varlist[i];
10647         if(arg->vt == VT_INTEGER)
10648         {
10649             switch(arg->lVal)
10650             {
10651             case _pk_jump:
10652                 (*pretvar)->lVal = (LONG)(keys & FLAG_JUMP);
10653                 break;
10654             case _pk_attack:
10655                 (*pretvar)->lVal = (LONG)(keys & FLAG_ATTACK);
10656                 break;
10657             case _pk_attack2:
10658                 (*pretvar)->lVal = (LONG)(keys & FLAG_ATTACK2);
10659                 break;
10660             case _pk_attack3:
10661                 (*pretvar)->lVal = (LONG)(keys & FLAG_ATTACK3);
10662                 break;
10663             case _pk_attack4:
10664                 (*pretvar)->lVal = (LONG)(keys & FLAG_ATTACK4);
10665                 break;
10666             case _pk_special:
10667                 (*pretvar)->lVal = (LONG)(keys & FLAG_SPECIAL);
10668                 break;
10669             case _pk_esc:
10670                 (*pretvar)->lVal = (LONG)(keys & FLAG_ESC);
10671                 break;
10672             case _pk_start:
10673                 (*pretvar)->lVal = (LONG)(keys & FLAG_START);
10674                 break;
10675             case _pk_moveleft:
10676                 (*pretvar)->lVal = (LONG)(keys & FLAG_MOVELEFT);
10677                 break;
10678             case _pk_moveright:
10679                 (*pretvar)->lVal = (LONG)(keys & FLAG_MOVERIGHT);
10680                 break;
10681             case _pk_moveup:
10682                 (*pretvar)->lVal = (LONG)(keys & FLAG_MOVEUP);
10683                 break;
10684             case _pk_movedown:
10685                 (*pretvar)->lVal = (LONG)(keys & FLAG_MOVEDOWN);
10686                 break;
10687             case _pk_screenshot:
10688                 (*pretvar)->lVal = (LONG)(keys & FLAG_SCREENSHOT);
10689                 break;
10690             case _pk_anybutton:
10691                 (*pretvar)->lVal = (LONG)(keys & FLAG_ANYBUTTON);
10692                 break;
10693             default:
10694                 (*pretvar)->lVal = (LONG)0;
10695             }
10696         }
10697         else
10698         {
10699             (*pretvar)->lVal = (LONG)0;
10700         }
10701         if(!((*pretvar)->lVal))
10702         {
10703             break;
10704         }
10705     }
10706 
10707     return S_OK;
10708 }
10709 
10710 //playmusic(name, loop)
openbor_playmusic(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10711 HRESULT openbor_playmusic(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10712 {
10713     int loop = 0;
10714     LONG offset = 0;
10715     char *thename = NULL;
10716 
10717     *pretvar = NULL;
10718     if(paramCount < 1)
10719     {
10720         sound_close_music();
10721         return S_OK;
10722     }
10723     if(varlist[0]->vt != VT_STR)
10724     {
10725         //printf("");
10726         return E_FAIL;
10727     }
10728     thename = StrCache_Get(varlist[0]->strVal);
10729 
10730     if(paramCount > 1)
10731     {
10732         loop = (int)ScriptVariant_IsTrue(varlist[1]);
10733     }
10734 
10735     if(paramCount > 2)
10736     {
10737         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &offset)))
10738         {
10739             return E_FAIL;
10740         }
10741     }
10742 
10743 
10744     music(thename, loop, offset);
10745     return S_OK;
10746 }
10747 
10748 //fademusic(fade, name, loop, offset)
openbor_fademusic(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10749 HRESULT openbor_fademusic(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10750 {
10751     DOUBLE value = 0;
10752     LONG values[2] = {0, 0};
10753     *pretvar = NULL;
10754     if(paramCount < 1)
10755     {
10756         goto fademusic_error;
10757     }
10758     if(FAILED(ScriptVariant_DecimalValue(varlist[0], &value)))
10759     {
10760         goto fademusic_error;
10761     }
10762     musicfade[0] = value;
10763     musicfade[1] = (float)savedata.musicvol;
10764 
10765     if(paramCount == 4)
10766     {
10767         strncpy(musicname, StrCache_Get(varlist[1]->strVal), 128);
10768         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &values[0])))
10769         {
10770             goto fademusic_error;
10771         }
10772         if(FAILED(ScriptVariant_IntegerValue(varlist[3], &values[1])))
10773         {
10774             goto fademusic_error;
10775         }
10776         musicloop = values[0];
10777         musicoffset = values[1];
10778     }
10779     return S_OK;
10780 
10781 fademusic_error:
10782     printf("Function requires 1 value, with an optional 3 for music triggering: fademusic_error(float fade, char name, int loop, unsigned long offset)\n");
10783     return E_FAIL;
10784 }
10785 
10786 //setmusicvolume(left, right)
openbor_setmusicvolume(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10787 HRESULT openbor_setmusicvolume(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10788 {
10789     LONG channels[2];
10790 
10791     if(paramCount < 1)
10792     {
10793         return S_OK;
10794     }
10795 
10796     if(FAILED(ScriptVariant_IntegerValue(varlist[0], channels)))
10797     {
10798         goto setmusicvolume_error;
10799     }
10800 
10801     if(paramCount > 1)
10802     {
10803         if(FAILED(ScriptVariant_IntegerValue(varlist[1], channels + 1)))
10804         {
10805             goto setmusicvolume_error;
10806         }
10807     }
10808     else
10809     {
10810         channels[1] = channels[0];
10811     }
10812 
10813     sound_volume_music((int)channels[0], (int)channels[1]);
10814     return S_OK;
10815 
10816 setmusicvolume_error:
10817     printf("values must be integers: setmusicvolume(int left, (optional)int right)\n");
10818     return E_FAIL;
10819 }
10820 
10821 //setmusicvolume(left, right)
openbor_setmusictempo(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10822 HRESULT openbor_setmusictempo(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10823 {
10824     LONG new_tempo;
10825 
10826     if(paramCount < 1)
10827     {
10828         return S_OK;
10829     }
10830 
10831     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &new_tempo)))
10832     {
10833         return E_FAIL;
10834     }
10835 
10836     sound_music_tempo(new_tempo);
10837     return S_OK;
10838 }
10839 
10840 //pausemusic(value)
openbor_pausemusic(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10841 HRESULT openbor_pausemusic(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10842 {
10843     int pause = 0;
10844     if(paramCount < 1)
10845     {
10846         return S_OK;
10847     }
10848 
10849     pause = (int)ScriptVariant_IsTrue(varlist[0]);
10850 
10851     sound_pause_music(pause);
10852     return S_OK;
10853 }
10854 
openbor_querychannel(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10855 HRESULT openbor_querychannel(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10856 {
10857     LONG ltemp;
10858     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
10859     {
10860         goto query_error;
10861     }
10862     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
10863     (*pretvar)->lVal = sound_query_channel((int)ltemp);
10864 
10865 query_error:
10866     *pretvar = NULL;
10867     return E_FAIL;
10868 }
10869 
10870 
openbor_stopchannel(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10871 HRESULT openbor_stopchannel(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10872 {
10873     LONG ltemp;
10874     *pretvar = NULL;
10875     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
10876     {
10877         goto sc_error;
10878     }
10879     sound_stop_sample((int)ltemp);
10880 
10881 sc_error:
10882     return E_FAIL;
10883 }
10884 
10885 //playsample(id, priority, lvolume, rvolume, speed, loop)
openbor_playsample(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10886 HRESULT openbor_playsample(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10887 {
10888     int i, result;
10889     LONG value[6] = { -1, 0, savedata.effectvol, savedata.effectvol, 100, 0};
10890 
10891     for(i = 0; i < 6 && i < paramCount; i++)
10892     {
10893         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i)))
10894         {
10895             goto playsample_error;
10896         }
10897     }
10898     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
10899     if((int)value[5])
10900     {
10901         result = sound_loop_sample((int)value[0], (unsigned int)value[1], (int)value[2], (int)value[3], (unsigned int)value[4]);
10902     }
10903     else
10904     {
10905         result = sound_play_sample((int)value[0], (unsigned int)value[1], (int)value[2], (int)value[3], (unsigned int)value[4]);
10906     }
10907     (*pretvar)->lVal = (LONG)result;
10908     return S_OK;
10909 
10910 playsample_error:
10911     *pretvar = NULL;
10912     printf("Function requires 6 integer values: playsample(int id, unsigned int priority, int lvolume, int rvolume, unsigned int speed, int loop)\n");
10913     return E_FAIL;
10914 }
10915 
10916 // int loadsample(filename, log)
openbor_loadsample(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10917 HRESULT openbor_loadsample(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10918 {
10919     int arg = 0;
10920 
10921     if(paramCount < 1)
10922     {
10923         goto loadsample_error;
10924     }
10925     if(varlist[0]->vt != VT_STR)
10926     {
10927         goto loadsample_error;
10928     }
10929 
10930     if(paramCount > 1)
10931     {
10932         if(varlist[1]->vt == VT_INTEGER)
10933         {
10934             arg = varlist[1]->lVal;
10935         }
10936         else
10937         {
10938             goto loadsample_error;
10939         }
10940     }
10941 
10942     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
10943     (*pretvar)->lVal = (LONG)sound_load_sample(StrCache_Get(varlist[0]->strVal), packfile, arg);
10944     return S_OK;
10945 
10946 loadsample_error:
10947     printf("Function requires 1 string value and optional log value: loadsample(string {filename} integer {log})\n");
10948     *pretvar = NULL;
10949     return E_FAIL;
10950 }
10951 
10952 // void unloadsample(id)
openbor_unloadsample(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10953 HRESULT openbor_unloadsample(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10954 {
10955     LONG id;
10956     *pretvar = NULL;
10957     if(paramCount != 1 )
10958     {
10959         goto unloadsample_error;
10960     }
10961 
10962     if(FAILED(ScriptVariant_IntegerValue((varlist[0]), &id)))
10963     {
10964         goto unloadsample_error;
10965     }
10966 
10967     sound_unload_sample((int)id);
10968     return S_OK;
10969 
10970 unloadsample_error:
10971     printf("Function requires 1 integer value: unloadsample(int id)\n");
10972     return E_FAIL;
10973 }
10974 
10975 //fadeout(type, speed);
openbor_fadeout(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)10976 HRESULT openbor_fadeout(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
10977 {
10978     LONG type;
10979     LONG speed;
10980     *pretvar = NULL;
10981     if(paramCount < 1 )
10982     {
10983         goto fade_out_error;
10984     }
10985 
10986     if(FAILED(ScriptVariant_IntegerValue((varlist[0]), &type)))
10987     {
10988         goto fade_out_error;
10989     }
10990     if(FAILED(ScriptVariant_IntegerValue((varlist[1]), &speed)))
10991 
10992     {
10993         fade_out((int)type, (int)speed);
10994     }
10995     return S_OK;
10996 
10997 fade_out_error:
10998     printf("Function requires 2 integer values: fade_out(int type, int speed)\n");
10999     return E_FAIL;
11000 }
11001 
11002 //changepalette(index);
openbor_changepalette(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11003 HRESULT openbor_changepalette(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11004 {
11005     LONG index;
11006 
11007     *pretvar = NULL;
11008 
11009     if(paramCount < 1)
11010     {
11011         goto changepalette_error;
11012     }
11013 
11014     if(FAILED(ScriptVariant_IntegerValue((varlist[0]), &index)))
11015     {
11016         goto changepalette_error;
11017     }
11018 
11019     change_system_palette((int)index);
11020 
11021     return S_OK;
11022 
11023 changepalette_error:
11024     printf("Function requires 1 integer value: changepalette(int index)\n");
11025     return E_FAIL;
11026 }
11027 
11028 //changelight(x, z);
openbor_changelight(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11029 HRESULT openbor_changelight(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11030 {
11031     LONG x, z;
11032     extern int            light[2];
11033     ScriptVariant *arg = NULL;
11034 
11035     *pretvar = NULL;
11036     if(paramCount < 2)
11037     {
11038         goto changelight_error;
11039     }
11040 
11041     arg = varlist[0];
11042     if(arg->vt != VT_EMPTY)
11043     {
11044         if(FAILED(ScriptVariant_IntegerValue(arg, &x)))
11045         {
11046             goto changelight_error;
11047         }
11048         light[0] = (int)x;
11049     }
11050 
11051     arg = varlist[1];
11052     if(arg->vt != VT_EMPTY)
11053     {
11054         if(FAILED(ScriptVariant_IntegerValue(arg, &z)))
11055         {
11056             goto changelight_error;
11057         }
11058         light[1] = (int)z;
11059     }
11060 
11061     return S_OK;
11062 changelight_error:
11063     printf("Function requires 2 integer values: changepalette(int x, int z)\n");
11064     return E_FAIL;
11065 }
11066 
11067 //changeshadowcolor(color, alpha);
11068 // color = 0 means no gfxshadow, -1 means don't fill the shadow with colour
11069 // alpha default to 2, <=0 means no alpha effect
openbor_changeshadowcolor(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11070 HRESULT openbor_changeshadowcolor(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11071 {
11072     LONG c, a;
11073     extern int            shadowcolor;
11074     extern int            shadowalpha;
11075 
11076     *pretvar = NULL;
11077     if(paramCount < 1)
11078     {
11079         goto changeshadowcolor_error;
11080     }
11081 
11082     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &c)))
11083     {
11084         goto changeshadowcolor_error;
11085     }
11086 
11087     shadowcolor = (int)c;
11088 
11089     if(paramCount > 1)
11090     {
11091         if(FAILED(ScriptVariant_IntegerValue(varlist[1], &a)))
11092         {
11093             goto changeshadowcolor_error;
11094         }
11095         shadowalpha = (int)a;
11096     }
11097 
11098     return S_OK;
11099 changeshadowcolor_error:
11100     printf("Function requires at least 1 integer value, the 2nd integer parameter is optional: changepalette(int colorindex, int alpha)\n");
11101     return E_FAIL;
11102 }
11103 
11104 // ===== gettextobjproperty(name, value) =====
11105 enum gtop_enum
11106 {
11107     _top_font,
11108     _top_text,
11109     _top_time,
11110     _top_x,
11111     _top_y,
11112     _top_z,
11113     _top_the_end,
11114 };
11115 
mapstrings_textobjproperty(ScriptVariant ** varlist,int paramCount)11116 int mapstrings_textobjproperty(ScriptVariant **varlist, int paramCount)
11117 {
11118     char *propname = NULL;
11119     int prop;
11120 
11121     static const char *proplist[] =
11122     {
11123         "font",
11124         "text",
11125         "time"
11126         "x",
11127         "y",
11128         "z",
11129     };
11130 
11131     if(paramCount < 2)
11132     {
11133         return 1;
11134     }
11135 
11136     MAPSTRINGS(varlist[1], proplist, _top_the_end,
11137                "'%s' is not a valid textobj property.\n");
11138 
11139     return 1;
11140 }
11141 
openbor_gettextobjproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11142 HRESULT openbor_gettextobjproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11143 {
11144     LONG ind;
11145     int propind;
11146 
11147     if(paramCount < 2)
11148     {
11149         goto gettextobjproperty_error;
11150     }
11151 
11152 
11153     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
11154     {
11155         printf("Function's 1st argument must be a numeric value: gettextproperty(int index, \"property\")\n");
11156         goto gettextobjproperty_error;
11157     }
11158 
11159     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11160     mapstrings_textobjproperty(varlist, paramCount);
11161 
11162     if(ind < 0 || ind >= level->numtextobjs)
11163     {
11164         (*pretvar)->lVal = 0;
11165         return S_OK;
11166     }
11167 
11168     if(varlist[1]->vt != VT_INTEGER)
11169     {
11170         if(varlist[1]->vt != VT_STR)
11171         {
11172             printf("Function gettextobjproperty must have a string property name.\n");
11173         }
11174         goto gettextobjproperty_error;
11175     }
11176 
11177     propind = varlist[1]->lVal;
11178 
11179     switch(propind)
11180     {
11181     case _top_font:
11182     {
11183         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11184         (*pretvar)->lVal = (LONG)level->textobjs[ind].font;
11185         break;
11186     }
11187     case _top_text:
11188     {
11189         ScriptVariant_ChangeType(*pretvar, VT_STR);
11190         StrCache_Copy((*pretvar)->strVal, level->textobjs[ind].text);
11191         break;
11192     }
11193     case _top_time:
11194     {
11195         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11196         (*pretvar)->lVal = (LONG)level->textobjs[ind].t;
11197         break;
11198     }
11199     case _top_x:
11200     {
11201         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11202         (*pretvar)->lVal = (LONG)level->textobjs[ind].x;
11203         break;
11204     }
11205     case _top_y:
11206     {
11207         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11208         (*pretvar)->lVal = (LONG)level->textobjs[ind].y;
11209         break;
11210     }
11211     case _top_z:
11212     {
11213         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11214         (*pretvar)->lVal = (LONG)level->textobjs[ind].z;
11215         break;
11216     }
11217     default:
11218         //printf("Property name '%s' is not supported by function gettextobjproperty.\n", propname);
11219         goto gettextobjproperty_error;
11220         break;
11221     }
11222 
11223     return S_OK;
11224 
11225 gettextobjproperty_error:
11226     *pretvar = NULL;
11227     return E_FAIL;
11228 }
11229 
openbor_changetextobjproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11230 HRESULT openbor_changetextobjproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11231 {
11232     LONG ind;
11233     int propind;
11234     static char buf[MAX_STR_VAR_LEN];
11235     LONG ltemp;
11236     const char *ctotext = "changetextobjproperty(int index, \"property\", value)";
11237 
11238     *pretvar = NULL;
11239 
11240     if(paramCount < 3)
11241     {
11242         printf("Function needs at last 3 parameters: %s\n", ctotext);
11243         return E_FAIL;
11244     }
11245 
11246     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
11247     {
11248         printf("Function's 1st argument must be a numeric value: %s\n", ctotext);
11249         return E_FAIL;
11250     }
11251 
11252     mapstrings_textobjproperty(varlist, paramCount);
11253 
11254     if(ind < 0)
11255     {
11256         printf("Invalid textobj index, must be >= 0\n");
11257         return E_FAIL;
11258     }
11259     else if (ind >= level->numtextobjs)
11260     {
11261         __reallocto(level->textobjs, level->numtextobjs, ind + 1);
11262         level->numtextobjs = ind + 1;
11263     }
11264 
11265     if(varlist[1]->vt != VT_INTEGER)
11266     {
11267         printf("Invalid property type for changetextobjproperty.\n");
11268         return E_FAIL;
11269     }
11270 
11271     propind = varlist[1]->lVal;
11272 
11273     switch(propind)
11274     {
11275     case _top_font:
11276     {
11277         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
11278         {
11279             level->textobjs[ind].font = (int)ltemp;
11280         }
11281         else
11282         {
11283             goto changetextobjproperty_error;
11284         }
11285         break;
11286     }
11287     case _top_text:
11288     {
11289         ScriptVariant_ToString(varlist[2], buf);
11290         level->textobjs[ind].text = malloc(MAX_STR_VAR_LEN);
11291         strncpy(level->textobjs[ind].text, buf, MAX_STR_VAR_LEN);
11292         break;
11293     }
11294     case _top_time:
11295     {
11296         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
11297         {
11298             level->textobjs[ind].t = (int)ltemp;
11299         }
11300         else
11301         {
11302             goto changetextobjproperty_error;
11303         }
11304         break;
11305     }
11306     case _top_x:
11307     {
11308         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
11309         {
11310             level->textobjs[ind].x = (int)ltemp;
11311         }
11312         else
11313         {
11314             goto changetextobjproperty_error;
11315         }
11316         break;
11317     }
11318     case _top_y:
11319     {
11320         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
11321         {
11322             level->textobjs[ind].y = (int)ltemp;
11323         }
11324         else
11325         {
11326             goto changetextobjproperty_error;
11327         }
11328         break;
11329     }
11330     case _top_z:
11331     {
11332         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp)))
11333         {
11334             level->textobjs[ind].z = (int)ltemp;
11335         }
11336         else
11337         {
11338             goto changetextobjproperty_error;
11339         }
11340         break;
11341     }
11342     default:
11343         //printf("Property name '%s' is not supported by function changetextobjproperty.\n", propname);
11344         return E_FAIL;
11345         break;
11346     }
11347 
11348     return S_OK;
11349 
11350 changetextobjproperty_error:
11351     ScriptVariant_ToString(varlist[2], buf);
11352     printf("Invalid textobj value: %s\n", buf);
11353     return E_FAIL;
11354 }
11355 
11356 // settextobj(int index, int x, int y, int font, int z, char text, int time {optional})
openbor_settextobj(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11357 HRESULT openbor_settextobj(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11358 {
11359     LONG ind;
11360     LONG X, Y, Z, F, T = 0;
11361     static char buf[MAX_STR_VAR_LEN];
11362     const char *stotext = "settextobj(int index, int x, int y, int font, int z, char text, int time {optional})";
11363 
11364     *pretvar = NULL;
11365 
11366 
11367     if(paramCount < 6)
11368     {
11369         printf("Function needs at least 6 parameters: %s\n", stotext);
11370         return E_FAIL;
11371     }
11372 
11373     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
11374     {
11375         printf("Function's 1st argument must be a numeric value: %s\n", stotext);
11376         return E_FAIL;
11377     }
11378 
11379     if(ind < 0)
11380     {
11381         printf("Invalid textobj index, must be >= 0\n");
11382         return E_FAIL;
11383     }
11384     else if(ind >= level->numtextobjs)
11385     {
11386         __reallocto(level->textobjs, level->numtextobjs, ind + 1);
11387         level->numtextobjs = ind + 1;
11388     }
11389 
11390     if(FAILED(ScriptVariant_IntegerValue(varlist[1], &X)))
11391     {
11392         goto settextobj_error;
11393     }
11394     if(FAILED(ScriptVariant_IntegerValue(varlist[2], &Y)))
11395     {
11396         goto settextobj_error;
11397     }
11398     if(FAILED(ScriptVariant_IntegerValue(varlist[3], &F)))
11399     {
11400         goto settextobj_error;
11401     }
11402     if(FAILED(ScriptVariant_IntegerValue(varlist[4], &Z)))
11403     {
11404         goto settextobj_error;
11405     }
11406     ScriptVariant_ToString(varlist[5], buf);
11407     if(paramCount >= 7 && FAILED(ScriptVariant_IntegerValue(varlist[6], &T)))
11408     {
11409         goto settextobj_error;
11410     }
11411 
11412     level->textobjs[ind].t = (int)T;
11413     level->textobjs[ind].x = (int)X;
11414     level->textobjs[ind].y = (int)Y;
11415     level->textobjs[ind].z = (int)Z;
11416     level->textobjs[ind].font = (int)F;
11417 
11418     if(!level->textobjs[ind].text)
11419     {
11420         level->textobjs[ind].text = (char *)malloc(MAX_STR_VAR_LEN);
11421     }
11422     strncpy(level->textobjs[ind].text, buf, MAX_STR_VAR_LEN);
11423 
11424     return S_OK;
11425 
11426 settextobj_error:
11427     printf("Invalid value(s) for settextobj: %s\n", stotext);
11428     return E_FAIL;
11429 }
11430 
openbor_cleartextobj(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11431 HRESULT openbor_cleartextobj(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11432 {
11433     LONG ind;
11434     const char *cltotext = "cleartextobj(int index)";
11435 
11436     *pretvar = NULL;
11437 
11438     if(paramCount < 1)
11439     {
11440         printf("Function needs at least 1 parameter: %s\n", cltotext);
11441         return E_FAIL;
11442     }
11443 
11444     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
11445     {
11446         printf("Function's 1st argument must be a numeric value: %s\n", cltotext);
11447         return E_FAIL;
11448     }
11449 
11450     if(ind < 0 || ind >= level->numtextobjs)
11451     {
11452         return S_OK;
11453     }
11454 
11455     level->textobjs[ind].t = 0;
11456     level->textobjs[ind].x = 0;
11457     level->textobjs[ind].y = 0;
11458     level->textobjs[ind].font = 0;
11459     level->textobjs[ind].z = 0;
11460     if(level->textobjs[ind].text)
11461     {
11462         free(level->textobjs[ind].text);
11463     }
11464     level->textobjs[ind].text = NULL;
11465     return S_OK;
11466 }
11467 
11468 // ===== get layer type ======
11469 enum getlt_enum
11470 {
11471     _glt_background,
11472     _glt_bglayer,
11473     _glt_fglayer,
11474     _glt_frontpanel,
11475     _glt_generic,
11476     _glt_neon,
11477     _glt_panel,
11478     _glt_screen,
11479     _glt_water,
11480     _glt_the_end,
11481 };
11482 
11483 
11484 // ===== getbglayerproperty ======
11485 enum getbglp_enum
11486 {
11487     _glp_alpha,
11488     _glp_amplitude,
11489     _glp_bgspeedratio,
11490     _glp_enabled,
11491     _glp_neon,
11492     _glp_quake,
11493     _glp_transparency,
11494     _glp_watermode,
11495     _glp_wavelength,
11496     _glp_wavespeed,
11497     _glp_xoffset,
11498     _glp_xratio,
11499     _glp_xrepeat,
11500     _glp_xspacing,
11501     _glp_z,
11502     _glp_zoffset,
11503     _glp_zratio,
11504     _glp_zrepeat,
11505     _glp_zspacing,
11506     _glp_the_end,
11507 };
11508 
mapstrings_layerproperty(ScriptVariant ** varlist,int paramCount)11509 int mapstrings_layerproperty(ScriptVariant **varlist, int paramCount)
11510 {
11511     char *propname = NULL;
11512     int prop;
11513 
11514     static const char *proplist[] =
11515     {
11516         "alpha",
11517         "amplitude",
11518         "bgspeedratio",
11519         "enabled",
11520         "neon",
11521         "quake",
11522         "transparency",
11523         "watermode",
11524         "wavelength",
11525         "wavespeed",
11526         "xoffset",
11527         "xratio",
11528         "xrepeat",
11529         "xspacing",
11530         "z",
11531         "zoffset",
11532         "zratio",
11533         "zrepeat",
11534         "zspacing",
11535     };
11536 
11537     static const char *typelist[] =
11538     {
11539         "background",
11540         "bglayer",
11541         "fglayer",
11542         "frontpanel",
11543         "generic",
11544         "neon",
11545         "panel",
11546         "water",
11547     };
11548 
11549     if(paramCount < 3)
11550     {
11551         return 1;
11552     }
11553     MAPSTRINGS(varlist[0], typelist, _glt_the_end,
11554                "Type name '%s' is not supported by function getlayerproperty.\n");
11555     MAPSTRINGS(varlist[2], proplist, _glp_the_end,
11556                "Property name '%s' is not supported by function getlayerproperty.\n");
11557 
11558     return 1;
11559 }
11560 
_getlayerproperty(s_layer * layer,int propind,ScriptVariant ** pretvar)11561 HRESULT _getlayerproperty(s_layer *layer, int propind, ScriptVariant **pretvar)
11562 {
11563 
11564     switch(propind)
11565     {
11566     case _glp_alpha:
11567     {
11568         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11569         (*pretvar)->lVal = (LONG)layer->drawmethod.alpha;
11570         break;
11571     }
11572     case _glp_amplitude:
11573     {
11574         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11575         (*pretvar)->lVal = (LONG)layer->drawmethod.water.amplitude;
11576         break;
11577     }
11578     case _glp_bgspeedratio:
11579     {
11580         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
11581         (*pretvar)->dblVal = (DOUBLE)layer->bgspeedratio;
11582         break;
11583     }
11584     case _glp_enabled:
11585     {
11586         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11587         (*pretvar)->lVal = (LONG)layer->enabled;
11588         break;
11589     }
11590     case _glp_neon:
11591     {
11592         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11593         (*pretvar)->lVal = (LONG)layer->neon;
11594         break;
11595     }
11596     case _glp_quake:
11597     {
11598         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11599         (*pretvar)->lVal = (LONG)layer->quake;
11600         break;
11601     }
11602     case _glp_transparency:
11603     {
11604         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11605         (*pretvar)->lVal = (LONG)layer->drawmethod.transbg;
11606         break;
11607     }
11608     case _glp_watermode:
11609     {
11610         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11611         (*pretvar)->lVal = (LONG)layer->drawmethod.water.watermode;
11612         break;
11613     }
11614 
11615     case _glp_wavelength:
11616     {
11617         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11618         (*pretvar)->lVal = (LONG)layer->drawmethod.water.wavelength;
11619         break;
11620     }
11621     case _glp_wavespeed:
11622     {
11623         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
11624         (*pretvar)->dblVal = (DOUBLE)layer->drawmethod.water.wavespeed;
11625         break;
11626     }
11627     case _glp_xoffset:
11628     {
11629         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11630         (*pretvar)->lVal = (LONG)layer->xoffset;
11631         break;
11632     }
11633     case _glp_xratio:
11634     {
11635         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
11636         (*pretvar)->dblVal = (DOUBLE)layer->xratio;
11637         break;
11638     }
11639     case _glp_xrepeat:
11640     {
11641         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11642         (*pretvar)->lVal = (LONG)layer->drawmethod.xrepeat;
11643         break;
11644     }
11645     case _glp_xspacing:
11646     {
11647         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11648         (*pretvar)->lVal = (LONG)layer->xspacing;
11649         break;
11650     }
11651     case _glp_z:
11652     {
11653         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11654         (*pretvar)->lVal = (LONG)layer->z;
11655         break;
11656     }
11657     case _glp_zoffset:
11658     {
11659         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11660         (*pretvar)->lVal = (LONG)layer->zoffset;
11661         break;
11662     }
11663     case _glp_zratio:
11664     {
11665         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
11666         (*pretvar)->dblVal = (DOUBLE)layer->zratio;
11667         break;
11668     }
11669     case _glp_zrepeat:
11670     {
11671         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11672         (*pretvar)->lVal = (LONG)layer->drawmethod.yrepeat;
11673         break;
11674     }
11675     case _glp_zspacing:
11676     {
11677         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
11678         (*pretvar)->lVal = (LONG)layer->zspacing;
11679         break;
11680     }
11681     default:
11682         *pretvar = NULL;
11683         return E_FAIL;
11684     }
11685     return S_OK;
11686 }
11687 
_changelayerproperty(s_layer * layer,int propind,ScriptVariant * var)11688 HRESULT _changelayerproperty(s_layer *layer, int propind, ScriptVariant *var)
11689 {
11690     LONG temp;
11691     DOUBLE temp2;
11692     switch(propind)
11693     {
11694     case _glp_alpha:
11695     {
11696         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11697         {
11698             return E_FAIL;
11699         }
11700         layer->drawmethod.alpha = temp;
11701         break;
11702     }
11703     case _glp_amplitude:
11704     {
11705         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11706         {
11707             return E_FAIL;
11708         }
11709         layer->drawmethod.water.amplitude = temp;
11710         break;
11711     }
11712     case _glp_bgspeedratio:
11713     {
11714         if(FAILED(ScriptVariant_DecimalValue(var, &temp2)))
11715         {
11716             return E_FAIL;
11717         }
11718         layer->bgspeedratio = temp2;
11719         break;
11720     }
11721     case _glp_enabled:
11722     {
11723         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11724         {
11725             return E_FAIL;
11726         }
11727         layer->enabled = temp;
11728         break;
11729     }
11730     case _glp_neon:
11731     {
11732         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11733         {
11734             return E_FAIL;
11735         }
11736         layer->neon = temp;
11737         break;
11738     }
11739     case _glp_quake:
11740     {
11741         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11742         {
11743             return E_FAIL;
11744         }
11745         layer->quake = temp;
11746         break;
11747     }
11748     case _glp_transparency:
11749     {
11750         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11751         {
11752             return E_FAIL;
11753         }
11754         layer->drawmethod.transbg = temp;
11755         break;
11756     }
11757     case _glp_watermode:
11758     {
11759         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11760         {
11761             return E_FAIL;
11762         }
11763         layer->drawmethod.water.watermode = temp;
11764         break;
11765     }
11766 
11767     case _glp_wavelength:
11768     {
11769         if(FAILED(ScriptVariant_DecimalValue(var, &temp2)))
11770         {
11771             return E_FAIL;
11772         }
11773         layer->drawmethod.water.wavelength = temp2;
11774         break;
11775     }
11776     case _glp_wavespeed:
11777     {
11778         if(FAILED(ScriptVariant_DecimalValue(var, &temp2)))
11779         {
11780             return E_FAIL;
11781         }
11782         layer->drawmethod.water.wavespeed = temp2;
11783         break;
11784     }
11785     case _glp_xoffset:
11786     {
11787         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11788         {
11789             return E_FAIL;
11790         }
11791         layer->xoffset = temp;
11792         break;
11793     }
11794     case _glp_xratio:
11795     {
11796         if(FAILED(ScriptVariant_DecimalValue(var, &temp2)))
11797         {
11798             return E_FAIL;
11799         }
11800         layer->xratio = temp2;
11801         break;
11802     }
11803     case _glp_xrepeat:
11804     {
11805         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11806         {
11807             return E_FAIL;
11808         }
11809         layer->drawmethod.xrepeat = temp;
11810         break;
11811     }
11812     case _glp_xspacing:
11813     {
11814         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11815         {
11816             return E_FAIL;
11817         }
11818         layer->xspacing = temp;
11819         break;
11820     }
11821     case _glp_z:
11822     {
11823         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11824         {
11825             return E_FAIL;
11826         }
11827         layer->z = temp;
11828         break;
11829     }
11830     case _glp_zoffset:
11831     {
11832         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11833         {
11834             return E_FAIL;
11835         }
11836         layer->zoffset = temp;
11837         break;
11838     }
11839     case _glp_zratio:
11840     {
11841         if(FAILED(ScriptVariant_DecimalValue(var, &temp2)))
11842         {
11843             return E_FAIL;
11844         }
11845         layer->zratio = temp2;
11846         break;
11847     }
11848     case _glp_zrepeat:
11849     {
11850         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11851         {
11852             return E_FAIL;
11853         }
11854         layer->drawmethod.yrepeat = temp;
11855         break;
11856     }
11857     case _glp_zspacing:
11858     {
11859         if(FAILED(ScriptVariant_IntegerValue(var, &temp)))
11860         {
11861             return E_FAIL;
11862         }
11863         layer->zspacing = temp;
11864         break;
11865     }
11866     default:
11867         return E_FAIL;
11868     }
11869     return S_OK;
11870 }
11871 
_getlayer(int type,int ind)11872 s_layer *_getlayer(int type, int ind)
11873 {
11874     switch(type)
11875     {
11876     case _glt_background:
11877         return level->background;
11878     case _glt_bglayer:
11879         if(ind < 0 || ind >= level->numbglayers)
11880         {
11881             return NULL;
11882         }
11883         return level->bglayers[ind];
11884     case _glt_fglayer:
11885         if(ind < 0 || ind >= level->numfglayers)
11886         {
11887             return NULL;
11888         }
11889         return level->fglayers[ind];
11890     case _glt_frontpanel:
11891         if(ind < 0 || ind >= level->numfrontpanels)
11892         {
11893             return NULL;
11894         }
11895         return level->frontpanels[ind];
11896     case _glt_generic:
11897         if(ind < 0 || ind >= level->numgenericlayers)
11898         {
11899             return NULL;
11900         }
11901         return level->genericlayers[ind];
11902     case _glt_neon:
11903         if(ind < 0 || ind >= level->numpanels)
11904         {
11905             return NULL;
11906         }
11907         return level->panels[ind][1];
11908     case _glt_panel:
11909         if(ind < 0 || ind >= level->numpanels)
11910         {
11911             return NULL;
11912         }
11913         return level->panels[ind][0];
11914     case _glt_screen:
11915         if(ind < 0 || ind >= level->numpanels)
11916         {
11917             return NULL;
11918         }
11919         return level->panels[ind][2];
11920     case _glt_water:
11921         if(ind < 0 || ind >= level->numwaters)
11922         {
11923             return NULL;
11924         }
11925         return level->waters[ind];
11926     default:
11927         return NULL;
11928     }
11929 }
11930 
11931 // getlayerproperty(type, index, propertyname);
openbor_getlayerproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11932 HRESULT openbor_getlayerproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11933 {
11934     LONG ind;
11935     int propind, type;
11936     s_layer *layer = NULL;
11937 
11938     if(paramCount < 3)
11939     {
11940         goto getlayerproperty_error;
11941     }
11942 
11943     mapstrings_layerproperty(varlist, paramCount);
11944 
11945     type = varlist[0]->lVal;
11946     propind = varlist[2]->lVal;
11947 
11948     if(FAILED(ScriptVariant_IntegerValue(varlist[1], &ind)))
11949     {
11950         goto getlayerproperty_error2;
11951     }
11952 
11953     layer = _getlayer(type, (int)ind);
11954 
11955     if(layer == NULL)
11956     {
11957         goto getlayerproperty_error2;
11958     }
11959 
11960     if(FAILED(_getlayerproperty(layer, propind, pretvar)))
11961     {
11962         goto getlayerproperty_error3;
11963     }
11964 
11965     return S_OK;
11966 
11967 getlayerproperty_error:
11968     *pretvar = NULL;
11969     printf("Function getlayerproperty must have 3 parameters: layertype, index and propertyname\n");
11970     return E_FAIL;
11971 getlayerproperty_error2:
11972     *pretvar = NULL;
11973     printf("Layer not found!\n");
11974     return E_FAIL;
11975 getlayerproperty_error3:
11976     *pretvar = NULL;
11977     printf("Bad property name or value.\n");
11978     return E_FAIL;
11979 }
11980 
11981 // changelayerproperty(type, index, propertyname);
openbor_changelayerproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)11982 HRESULT openbor_changelayerproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
11983 {
11984     LONG ind;
11985     int propind, type;
11986     s_layer *layer = NULL;
11987     *pretvar = NULL;
11988 
11989     if(paramCount < 4)
11990     {
11991         goto chglayerproperty_error;
11992     }
11993 
11994     mapstrings_layerproperty(varlist, paramCount);
11995 
11996     type = varlist[0]->lVal;
11997     propind = varlist[2]->lVal;
11998 
11999     if(FAILED(ScriptVariant_IntegerValue(varlist[1], &ind)))
12000     {
12001         goto chglayerproperty_error2;
12002     }
12003 
12004     layer = _getlayer(type, (int)ind);
12005 
12006     if(layer == NULL)
12007     {
12008         goto chglayerproperty_error2;
12009     }
12010 
12011     if(FAILED(_changelayerproperty(layer, propind, varlist[3])))
12012     {
12013         goto chglayerproperty_error3;
12014     }
12015 
12016     return S_OK;
12017 
12018 chglayerproperty_error:
12019     printf("Function changelayerproperty must have 4 parameters: layertype, index, propertyname and value\n");
12020     return E_FAIL;
12021 chglayerproperty_error2:
12022     printf("Layer not found!\n");
12023     return E_FAIL;
12024 chglayerproperty_error3:
12025     printf("Layer property not understood or bad value.\n");
12026     return E_FAIL;
12027 }
12028 
12029 
12030 // ===== level properties ======
12031 enum levelproperty_enum
12032 {
12033     _lp_basemap,
12034     _lp_bgspeed,
12035     _lp_cameraxoffset,
12036     _lp_camerazoffset,
12037     _lp_gravity,
12038     _lp_hole,
12039     _lp_maxfallspeed,
12040     _lp_maxtossspeed,
12041     _lp_quake,
12042     _lp_rocking,
12043     _lp_scrollspeed,
12044     _lp_type,
12045     _lp_wall,
12046     _lp_the_end,
12047 };
12048 
12049 
12050 enum basemap_enum
12051 {
12052     _lp_bm_map,
12053     _lp_bm_x,
12054     _lp_bm_xsize,
12055     _lp_bm_z,
12056     _lp_bm_zsize,
12057     _lp_bm_the_end,
12058 };
12059 
mapstrings_levelproperty(ScriptVariant ** varlist,int paramCount)12060 int mapstrings_levelproperty(ScriptVariant **varlist, int paramCount)
12061 {
12062     char *propname = NULL;
12063     int prop;
12064 
12065     static const char *proplist[] =
12066     {
12067         "basemap",
12068         "bgspeed",
12069         "cameraxoffset",
12070         "camerazoffset",
12071         "gravity",
12072         "hole",
12073         "maxfallspeed",
12074         "maxtossspeed",
12075         "quake",
12076         "rocking",
12077         "scrollspeed",
12078         "type",
12079         "wall",
12080     };
12081 
12082     static const char *basemaplist[] =
12083     {
12084         "map",
12085         "x",
12086         "xsize",
12087         "z",
12088         "zsize",
12089     };
12090 
12091 
12092     if(paramCount < 1)
12093     {
12094         return 1;
12095     }
12096     MAPSTRINGS(varlist[0], proplist, _lp_the_end,
12097                "Level property '%s' is not supported.\n");
12098 
12099     if(paramCount >= 3 && varlist[0]->vt == VT_INTEGER && varlist[0]->lVal == _lp_basemap)
12100     {
12101         MAPSTRINGS(varlist[2], basemaplist, _lp_bm_the_end,
12102                    _is_not_supported_by_, "basemap");
12103     }
12104 
12105     return 1;
12106 }
12107 
openbor_getlevelproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12108 HRESULT openbor_getlevelproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12109 {
12110     LONG ltemp, ltemp2;
12111     mapstrings_levelproperty(varlist, paramCount);
12112 
12113     switch(varlist[0]->lVal)
12114     {
12115     case _lp_bgspeed:
12116     {
12117         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
12118         (*pretvar)->lVal = (LONG)level->bgspeed;
12119         break;
12120     }
12121     case _lp_cameraxoffset:
12122     {
12123         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
12124         (*pretvar)->lVal = (LONG)level->cameraxoffset;
12125         break;
12126     }
12127     case _lp_camerazoffset:
12128     {
12129         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
12130         (*pretvar)->lVal = (LONG)level->camerazoffset;
12131         break;
12132     }
12133     case _lp_gravity:
12134     {
12135         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
12136         (*pretvar)->dblVal = (DOUBLE)level->gravity;
12137         break;
12138     }
12139     case _lp_maxfallspeed:
12140     {
12141         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
12142         (*pretvar)->dblVal = (DOUBLE)level->maxfallspeed;
12143         break;
12144     }
12145     case _lp_maxtossspeed:
12146     {
12147         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
12148         (*pretvar)->dblVal = (DOUBLE)level->maxtossspeed;
12149         break;
12150     }
12151     case _lp_quake:
12152     {
12153         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
12154         (*pretvar)->lVal = (LONG)level->quake;
12155         break;
12156     }
12157     case _lp_scrollspeed:
12158     {
12159         ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
12160         (*pretvar)->dblVal = (DOUBLE)level->scrollspeed;
12161         break;
12162     }
12163     case _lp_type:
12164     {
12165         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
12166         (*pretvar)->lVal = (LONG)level->type;
12167         break;
12168     }
12169     case _lp_hole:
12170     {
12171         if(paramCount > 2 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp))
12172                 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp2))
12173                 && ltemp >= 0 && ltemp < level->numholes && ltemp2 >= 0 && ltemp2 < 7)
12174         {
12175             ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
12176             (*pretvar)->dblVal = level->holes[ltemp][ltemp2];
12177         }
12178         else
12179         {
12180             goto getlevelproperty_error;
12181         }
12182         break;
12183     }
12184     case _lp_wall:
12185     {
12186         if(paramCount > 2 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp))
12187                 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp2))
12188                 && ltemp >= 0 && ltemp < level->numwalls && ltemp2 >= 0 && ltemp2 < 8)
12189         {
12190             ScriptVariant_ChangeType(*pretvar, VT_DECIMAL);
12191             (*pretvar)->dblVal = level->walls[ltemp][ltemp2];
12192         }
12193         else
12194         {
12195             goto getlevelproperty_error;
12196         }
12197         break;
12198     }
12199     default:
12200         printf("Property is not supported by function getlevelproperty yet. %d\n", varlist[0]->lVal);
12201         goto getlevelproperty_error;
12202         break;
12203     }
12204 
12205     return S_OK;
12206 
12207 getlevelproperty_error:
12208     *pretvar = NULL;
12209     return E_FAIL;
12210 }
12211 
12212 //changelevelproperty(name, value)
openbor_changelevelproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12213 HRESULT openbor_changelevelproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12214 {
12215     LONG ltemp, ltemp2, ltemp3;
12216     DOUBLE dbltemp;
12217     static char buf[64];
12218     int i;
12219     ScriptVariant *arg = NULL;
12220 
12221     *pretvar = NULL;
12222 
12223     if(paramCount < 2)
12224     {
12225         printf("Function changelevelproperty(prop, value) need at least 2 parameters.\n");
12226         return E_FAIL;
12227     }
12228 
12229     mapstrings_levelproperty(varlist, paramCount);
12230 
12231     arg = varlist[1];
12232 
12233     switch(varlist[0]->lVal)
12234     {
12235     case _lp_rocking:
12236         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
12237         {
12238             level->rocking = (int)ltemp;
12239         }
12240         else
12241         {
12242             goto clperror;
12243         }
12244         break;
12245     case _lp_bgspeed:
12246         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
12247         {
12248             level->bgspeed = (float)ltemp;
12249         }
12250         else
12251         {
12252             goto clperror;
12253         }
12254         break;
12255     case _lp_scrollspeed:
12256         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
12257         {
12258             level->scrollspeed = (float)ltemp;
12259         }
12260         else
12261         {
12262             goto clperror;
12263         }
12264         break;
12265     case _lp_type:
12266         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
12267         {
12268             level->type = (int)ltemp;
12269         }
12270         else
12271         {
12272             goto clperror;
12273         }
12274         break;
12275     case _lp_cameraxoffset:
12276         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
12277         {
12278             level->cameraxoffset = (int)ltemp;
12279         }
12280         else
12281         {
12282             goto clperror;
12283         }
12284         break;
12285     case _lp_camerazoffset:
12286         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
12287         {
12288             level->camerazoffset = (int)ltemp;
12289         }
12290         else
12291         {
12292             goto clperror;
12293         }
12294         break;
12295     case _lp_gravity:
12296         if(SUCCEEDED(ScriptVariant_DecimalValue(arg, &dbltemp)))
12297         {
12298             level->gravity = (float)dbltemp;
12299         }
12300         else
12301         {
12302             goto clperror;
12303         }
12304         break;
12305     case _lp_maxfallspeed:
12306         if(SUCCEEDED(ScriptVariant_DecimalValue(arg, &dbltemp)))
12307         {
12308             level->maxfallspeed = (float)dbltemp;
12309         }
12310         else
12311         {
12312             goto clperror;
12313         }
12314         break;
12315     case _lp_maxtossspeed:
12316         if(SUCCEEDED(ScriptVariant_DecimalValue(arg, &dbltemp)))
12317         {
12318             level->maxtossspeed = (float)dbltemp;
12319         }
12320         else
12321         {
12322             goto clperror;
12323         }
12324         break;
12325     case _lp_quake:
12326         if(SUCCEEDED(ScriptVariant_IntegerValue(arg, &ltemp)))
12327         {
12328             level->quake = (int)ltemp;
12329         }
12330         else
12331         {
12332             goto clperror;
12333         }
12334         break;
12335     case _lp_basemap:
12336         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)) && ltemp >= 0)
12337         {
12338             if(ltemp >= level->numbasemaps)
12339             {
12340                 __reallocto(level->basemaps, level->numbasemaps, ltemp + 1);
12341                 level->numbasemaps = ltemp + 1;
12342             }
12343             if(paramCount >= 4)
12344             {
12345                 switch(varlist[2]->lVal)
12346                 {
12347                 case _lp_bm_x:
12348                     if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)) )
12349                     {
12350                         level->basemaps[ltemp].x = ltemp2;
12351                     }
12352                     else
12353                     {
12354                         goto clperror;
12355                     }
12356                     break;
12357                 case _lp_bm_xsize:
12358                     if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)) )
12359                     {
12360                         level->basemaps[ltemp].xsize = ltemp2;
12361                     }
12362                     else
12363                     {
12364                         goto clperror;
12365                     }
12366                     break;
12367                 case _lp_bm_z:
12368                     if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)) )
12369                     {
12370                         level->basemaps[ltemp].z = ltemp2;
12371                     }
12372                     else
12373                     {
12374                         goto clperror;
12375                     }
12376                     break;
12377                 case _lp_bm_zsize:
12378                     if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)) )
12379                     {
12380                         level->basemaps[ltemp].zsize = ltemp2;
12381                     }
12382                     else
12383                     {
12384                         goto clperror;
12385                     }
12386                     break;
12387                 case _lp_bm_map:
12388                     if(paramCount >= 6 && SUCCEEDED(ScriptVariant_IntegerValue(varlist[3], &ltemp2)) &&
12389                             SUCCEEDED(ScriptVariant_IntegerValue(varlist[4], &ltemp3)) &&
12390                             SUCCEEDED(ScriptVariant_DecimalValue(varlist[5], &dbltemp)) &&
12391                             ltemp2 >= 0 && ltemp2 < level->basemaps[ltemp].xsize && ltemp3 >= 0 && ltemp3 < level->basemaps[ltemp].zsize
12392                       )
12393                     {
12394                         if(!level->basemaps[ltemp].map)
12395                         {
12396                             level->basemaps[ltemp].map = calloc(1, sizeof(*(level->basemaps[ltemp].map)) * level->basemaps[ltemp].xsize * level->basemaps[ltemp].zsize);
12397                         }
12398                         level->basemaps[ltemp].map[ltemp2 + ltemp3 * level->basemaps[ltemp].xsize] = (float)dbltemp;
12399                     }
12400                     else
12401                     {
12402                         goto clperror;
12403                     }
12404                     break;
12405                 default:
12406                     goto clperror;
12407                 }
12408             }
12409             else
12410             {
12411                 goto clperror;
12412             }
12413         }
12414         else
12415         {
12416             goto clperror;
12417         }
12418         break;
12419     case _lp_hole:
12420     {
12421         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)) && ltemp >= 0)
12422         {
12423             if(ltemp >= level->numholes)
12424             {
12425                 __reallocto(level->holes, level->numholes, ltemp + 1);
12426                 level->numholes = ltemp + 1;
12427             }
12428             if (paramCount == 4 )
12429             {
12430                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp2))	&& ltemp2 >= 0 && ltemp2 < 7
12431                         && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)) )
12432                 {
12433                     level->holes[ltemp][ltemp2] = (float)dbltemp;
12434                 }
12435                 else
12436                 {
12437                     goto clperror;
12438                 }
12439             }
12440             else if (paramCount == 9)
12441             {
12442                 for (i = 0; i < 7; i++)
12443                 {
12444                     if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
12445                     {
12446                         level->holes[ltemp][i] = (float)dbltemp;
12447                     }
12448                     else
12449                     {
12450                         goto clperror;
12451                     }
12452                 }
12453             }
12454             else
12455             {
12456                 goto clperror;
12457             }
12458 
12459         }
12460         else
12461         {
12462             goto clperror;
12463         }
12464         break;
12465     }
12466     case _lp_wall:
12467     {
12468         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)) && ltemp >= 0)
12469         {
12470             if(ltemp >= level->numwalls)
12471             {
12472                 __reallocto(level->walls, level->numwalls, ltemp + 1);
12473                 level->numwalls = ltemp + 1;
12474             }
12475             if (paramCount == 4 )
12476             {
12477                 if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[2], &ltemp2))	&& ltemp2 >= 0 && ltemp2 < 8
12478                         && SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)) )
12479                 {
12480                     level->walls[ltemp][ltemp2] = (float)dbltemp;
12481                 }
12482                 else
12483                 {
12484                     goto clperror;
12485                 }
12486             }
12487             else if (paramCount == 10)
12488             {
12489                 for (i = 0; i < 8; i++)
12490                 {
12491                     if(SUCCEEDED(ScriptVariant_DecimalValue(varlist[3], &dbltemp)))
12492                     {
12493                         level->walls[ltemp][i] = (float)dbltemp;
12494                     }
12495                     else
12496                     {
12497                         goto clperror;
12498                     }
12499                 }
12500             }
12501             else
12502             {
12503                 goto clperror;
12504             }
12505 
12506         }
12507         else
12508         {
12509             goto clperror;
12510         }
12511         break;
12512     }
12513     default:
12514         printf("Invalid or read-only level property.\n");
12515         return E_FAIL;
12516         break;
12517     }
12518 
12519     return S_OK;
12520 clperror:
12521     printf("Function changelevelproperty(prop, value) received invalid value(s). \n");
12522     printf("Dumping values: ");
12523     for(i = 1; i < paramCount; i++)
12524     {
12525         ScriptVariant_ToString(varlist[i], buf);
12526         printf("%s, ", buf);
12527     }
12528     printf("\n");
12529     return E_FAIL;
12530 }
12531 
12532 
12533 //shutdown(status, message)
openbor_shutdown(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12534 HRESULT openbor_shutdown(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12535 {
12536     LONG ltemp = 0;
12537 
12538     *pretvar = NULL;
12539 
12540     if(paramCount > 0 && FAILED(ScriptVariant_IntegerValue(varlist[0], &ltemp)))
12541     {
12542         goto shutdown_error;
12543     }
12544     if(paramCount > 1 && varlist[1]->vt != VT_STR)
12545     {
12546         goto shutdown_error;
12547     }
12548 
12549     shutdown((int)ltemp,  paramCount > 1 ? StrCache_Get(varlist[0]->strVal) : (DEFAULT_SHUTDOWN_MESSAGE));
12550 
12551     return S_OK;
12552 shutdown_error:
12553     printf("shutdown(status, message): both parameters are optional but must be valid.\n");
12554     return E_FAIL;
12555 }
12556 
12557 //jumptobranch(name, immediate)
openbor_jumptobranch(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12558 HRESULT openbor_jumptobranch(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12559 {
12560     LONG ltemp;
12561     extern char branch_name[MAX_NAME_LEN + 1];
12562     *pretvar = NULL;
12563     if(paramCount < 1)
12564     {
12565         goto jumptobranch_error;
12566     }
12567     if(varlist[0]->vt != VT_STR)
12568     {
12569         goto jumptobranch_error;
12570     }
12571 
12572     strncpy(branch_name, StrCache_Get(varlist[0]->strVal), MIN(MAX_NAME_LEN, MAX_STR_VAR_LEN)); // copy the string value to branch name
12573 
12574     if(paramCount >= 2)
12575     {
12576         if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)))
12577         {
12578             endgame = (int)ltemp;
12579             // 1 means goto that level immediately, or, wait until the level is complete
12580         }
12581         else
12582         {
12583             goto jumptobranch_error;
12584         }
12585     }
12586 
12587     return S_OK;
12588 jumptobranch_error:
12589     printf("Function requires 1 string value, the second argument is optional(int): jumptobranch(name, immediate)\n");
12590     return E_FAIL;
12591 }
12592 
12593 //bindentity(entity, target, x, z, a, direction, bindanim);
12594 //bindentity(entity, NULL()); // unbind
openbor_bindentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12595 HRESULT openbor_bindentity(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12596 {
12597     entity *ent = NULL;
12598     entity *other = NULL;
12599     ScriptVariant *arg = NULL;
12600     void adjust_bind(entity * e);
12601     LONG x = 0, z = 0, a = 0, dir = 0, anim = 0;
12602 
12603     *pretvar = NULL;
12604     if(paramCount < 2)
12605     {
12606         return E_FAIL;
12607     }
12608 
12609     ent = (entity *)(varlist[0])->ptrVal; //retrieve the entity
12610     if(!ent)
12611     {
12612         return S_OK;
12613     }
12614 
12615     other = (entity *)(varlist[1])->ptrVal;
12616     if(!other)
12617     {
12618         ent->bound = NULL;
12619         return S_OK;
12620     }
12621 
12622     ent->bound = other;
12623 
12624     if(paramCount < 3)
12625     {
12626         goto BIND;
12627     }
12628     // x
12629     arg = varlist[2];
12630     if(arg->vt != VT_EMPTY)
12631     {
12632         if(FAILED(ScriptVariant_IntegerValue(arg, &x)))
12633         {
12634             return E_FAIL;
12635         }
12636 
12637         ent->bindoffset[0] = (int)x;
12638     }
12639     if(paramCount < 4)
12640     {
12641         goto BIND;
12642     }
12643     // z
12644     arg = varlist[3];
12645     if(arg->vt != VT_EMPTY)
12646     {
12647         if(FAILED(ScriptVariant_IntegerValue(arg, &z)))
12648         {
12649             return E_FAIL;
12650         }
12651         ent->bindoffset[1] = (int)z;
12652     }
12653     if(paramCount < 5)
12654     {
12655         goto BIND;
12656     }
12657     // a
12658     arg = varlist[4];
12659     if(arg->vt != VT_EMPTY)
12660     {
12661         if(FAILED(ScriptVariant_IntegerValue(arg, &a)))
12662         {
12663             return E_FAIL;
12664         }
12665         ent->bindoffset[2] = (int)a;
12666     }
12667     if(paramCount < 6)
12668     {
12669         goto BIND;
12670     }
12671     // direction
12672     arg = varlist[5];
12673     if(arg->vt != VT_EMPTY)
12674     {
12675         if(FAILED(ScriptVariant_IntegerValue(arg, &dir)))
12676         {
12677             return E_FAIL;
12678         }
12679         ent->bindoffset[3] = (int)dir;
12680     }
12681     if(paramCount < 7)
12682     {
12683         goto BIND;
12684     }
12685     // animation
12686     arg = varlist[6];
12687     if(arg->vt != VT_EMPTY)
12688     {
12689         if(FAILED(ScriptVariant_IntegerValue(arg, &anim)))
12690         {
12691             return E_FAIL;
12692         }
12693         ent->bindanim = (int)anim;
12694     }
12695 
12696 BIND:
12697     adjust_bind(ent);
12698 
12699     return S_OK;
12700 }
12701 
12702 //array(size);
openbor_array(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12703 HRESULT openbor_array(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12704 {
12705     LONG size;
12706     Varlist *array;
12707 
12708     if(paramCount < 1 || FAILED(ScriptVariant_IntegerValue(varlist[0], &size)) || size < 0)
12709     {
12710         printf("Function requires 1 positive int value: array(int size)\n");
12711         goto array_error;
12712     }
12713 
12714     ScriptVariant_ChangeType(*pretvar, VT_PTR);
12715     array = malloc(sizeof(*array));
12716     (*pretvar)->ptrVal = (VOID *)array;
12717 
12718     if((*pretvar)->ptrVal == NULL)
12719     {
12720         printf("Not enough memory: array(%d)\n", (int)size);
12721         goto array_error;
12722     }
12723 
12724     Varlist_Init(array, size);
12725 
12726     List_InsertAfter(&scriptheap, (void *)(array), "openbor_array");
12727     return S_OK;
12728 
12729 array_error:
12730     (*pretvar) = NULL;
12731     return E_FAIL;
12732 }
12733 
12734 //size(array)
openbor_size(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12735 HRESULT openbor_size(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12736 {
12737     Varlist *array;
12738     if(paramCount < 1 || varlist[0]->vt != VT_PTR || !(array = (Varlist *)varlist[0]->ptrVal) || array->magic != varlist_magic)
12739     {
12740         goto size_error;
12741     }
12742     ScriptVariant_Copy(*pretvar, array->vars);
12743 
12744     return S_OK;
12745 size_error:
12746     printf("Function requires 1 array handle: %s(array)\n", "size");
12747     (*pretvar) = NULL;
12748     return E_FAIL;
12749 }
12750 
12751 //get(array, index);
openbor_get(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12752 HRESULT openbor_get(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12753 {
12754     ScriptVariant *ptmpvar;
12755     Varlist *array;
12756     LONG ltemp;
12757 
12758     if(paramCount < 2 || varlist[0]->vt != VT_PTR || !(array = (Varlist *)varlist[0]->ptrVal) || array->magic != varlist_magic)
12759     {
12760         goto get_error;
12761     }
12762 
12763     if(varlist[1]->vt == VT_STR)
12764     {
12765         ptmpvar = Varlist_GetByName(array, StrCache_Get(varlist[1]->strVal));
12766     }
12767     else if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)))
12768     {
12769         ptmpvar = Varlist_GetByIndex(array, (int)ltemp);
12770     }
12771     else
12772     {
12773         goto get_error;
12774     }
12775 
12776     if(ptmpvar)
12777     {
12778         ScriptVariant_Copy(*pretvar,  ptmpvar);
12779     }
12780     else
12781     {
12782         ScriptVariant_Clear(*pretvar);
12783     }
12784     return S_OK;
12785 
12786 get_error:
12787     printf("Function requires 1 array handle and 1 int value: get(array, int index)\n");
12788     (*pretvar) = NULL;
12789     return E_FAIL;
12790 }
12791 
12792 //set(array, index, value);
openbor_set(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12793 HRESULT openbor_set(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12794 {
12795     Varlist *array;
12796     LONG ltemp;
12797 
12798     *pretvar = NULL;
12799     if(paramCount < 3 || varlist[0]->vt != VT_PTR || !(array = (Varlist *)varlist[0]->ptrVal) || array->magic != varlist_magic)
12800     {
12801         goto set_error;
12802     }
12803 
12804     if(varlist[1]->vt == VT_STR)
12805     {
12806         Varlist_SetByName(array, StrCache_Get(varlist[1]->strVal), varlist[2]);
12807     }
12808     else if(SUCCEEDED(ScriptVariant_IntegerValue(varlist[1], &ltemp)))
12809     {
12810         Varlist_SetByIndex(array, (int)ltemp, varlist[2]);
12811     }
12812     else
12813     {
12814         goto set_error;
12815     }
12816 
12817     return S_OK;
12818 
12819 set_error:
12820     printf("Function requires 1 array handle, 1 int value and 1 value: set(array, int index, value)\n");
12821     return E_FAIL;
12822 }
12823 
12824 //reset(array)
openbor_reset(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12825 HRESULT openbor_reset(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12826 {
12827     Varlist *array;
12828     if(paramCount < 1 || varlist[0]->vt != VT_PTR || !(array = (Varlist *)varlist[0]->ptrVal) || array->magic != varlist_magic)
12829     {
12830         goto reset_error;
12831     }
12832     List_Reset(array->list);
12833 
12834     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
12835     (*pretvar)->lVal = (LONG)(array->list->current != NULL);
12836 
12837     return S_OK;
12838 reset_error:
12839     printf("Function requires 1 array handle: %s(array)\n", "reset");
12840     (*pretvar) = NULL;
12841     return E_FAIL;
12842 }
12843 
12844 //next(array)
openbor_next(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12845 HRESULT openbor_next(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12846 {
12847     Varlist *array;
12848     if(paramCount < 1 || varlist[0]->vt != VT_PTR || !(array = (Varlist *)varlist[0]->ptrVal) || array->magic != varlist_magic)
12849     {
12850         goto next_error;
12851     }
12852 
12853     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
12854     (*pretvar)->lVal = (LONG)(List_GotoNext(array->list));
12855 
12856     return S_OK;
12857 next_error:
12858     printf("Function requires 1 array handle: %s(array)\n", "next");
12859     (*pretvar) = NULL;
12860     return E_FAIL;
12861 }
12862 
12863 //key(array)
openbor_key(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12864 HRESULT openbor_key(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12865 {
12866     char *name;
12867     Varlist *array;
12868     if(paramCount < 1 || varlist[0]->vt != VT_PTR || !(array = (Varlist *)varlist[0]->ptrVal) || array->magic != varlist_magic)
12869     {
12870         goto key_error;
12871     }
12872 
12873     name = List_GetName(array->list);
12874     if(name)
12875     {
12876         ScriptVariant_ChangeType(*pretvar, VT_STR);
12877         StrCache_Copy((*pretvar)->strVal, name);
12878     }
12879     else
12880     {
12881         ScriptVariant_Clear(*pretvar);
12882     }
12883 
12884     return S_OK;
12885 key_error:
12886     printf("Function requires 1 array handle: %s(array)\n", "key");
12887     (*pretvar) = NULL;
12888     return E_FAIL;
12889 }
12890 
12891 //value(array)
openbor_value(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12892 HRESULT openbor_value(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12893 {
12894     ScriptVariant *var;
12895     Varlist *array;
12896     if(paramCount < 1 || varlist[0]->vt != VT_PTR || !(array = (Varlist *)varlist[0]->ptrVal) || array->magic != varlist_magic)
12897     {
12898         goto value_error;
12899     }
12900 
12901     var = List_Retrieve(array->list);
12902     if(var)
12903     {
12904         ScriptVariant_Copy(*pretvar, var);
12905     }
12906     else
12907     {
12908         ScriptVariant_Clear(*pretvar);
12909     }
12910 
12911     return S_OK;
12912 value_error:
12913     printf("Function requires 1 array handle: %s(array)\n", "value");
12914     (*pretvar) = NULL;
12915     return E_FAIL;
12916 }
12917 
12918 //allocscreen(int w, int h);
openbor_allocscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12919 HRESULT openbor_allocscreen(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12920 {
12921     LONG w, h;
12922     s_screen *screen;
12923 
12924     if(paramCount < 2)
12925     {
12926         goto allocscreen_error;
12927     }
12928 
12929     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &w)))
12930     {
12931         goto allocscreen_error;
12932     }
12933     if(FAILED(ScriptVariant_IntegerValue(varlist[1], &h)))
12934     {
12935         goto allocscreen_error;
12936     }
12937 
12938 
12939     ScriptVariant_ChangeType(*pretvar, VT_PTR);
12940     screen = allocscreen((int)w, (int)h, screenformat);
12941     if(screen)
12942     {
12943         clearscreen(screen);
12944     }
12945     (*pretvar)->ptrVal = (VOID *)screen;
12946 
12947     if((*pretvar)->ptrVal == NULL)
12948     {
12949         printf("Not enough memory: allocscreen(%d, %d)\n", (int)w, (int)h);
12950         (*pretvar) = NULL;
12951         return E_FAIL;
12952     }
12953     List_InsertAfter(&scriptheap, (void *)((*pretvar)->ptrVal), "openbor_allocscreen");
12954     return S_OK;
12955 
12956 allocscreen_error:
12957     printf("Function requires 2 int values: allocscreen(int width, int height)\n");
12958     (*pretvar) = NULL;
12959     return E_FAIL;
12960 }
12961 
12962 //clearscreen(s_screen* screen)
openbor_clearscreen(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)12963 HRESULT openbor_clearscreen(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
12964 {
12965     s_screen *screen;
12966 
12967     *pretvar = NULL;
12968     if(paramCount != 1)
12969     {
12970         goto clearscreen_error;
12971     }
12972     if(varlist[0]->vt != VT_PTR)
12973     {
12974         goto clearscreen_error;
12975     }
12976 
12977     screen = (s_screen *)varlist[0]->ptrVal;
12978 
12979     if(screen == NULL)
12980     {
12981         printf("Error: NULL pointer passed to clearscreen(void screen)\n");
12982         *pretvar = NULL;
12983         return E_FAIL;
12984     }
12985     clearscreen(screen);
12986     return S_OK;
12987 
12988 clearscreen_error:
12989     printf("Function requires a screen pointer: clearscreen(void screen)\n");
12990     return E_FAIL;
12991 }
12992 
12993 // ===== changedrawmethod ======
12994 enum drawmethod_enum
12995 {
12996     _dm_alpha,
12997     _dm_amplitude,
12998     _dm_beginsize,
12999     _dm_centerx,
13000     _dm_centery,
13001     _dm_channelb,
13002     _dm_channelg,
13003     _dm_channelr,
13004     _dm_clip,
13005     _dm_cliph,
13006     _dm_clipw,
13007     _dm_clipx,
13008     _dm_clipy,
13009     _dm_enabled,
13010     _dm_endsize,
13011     _dm_fillcolor,
13012     _dm_flag,
13013     _dm_fliprotate,
13014     _dm_flipx,
13015     _dm_perspective,
13016     _dm_remap,
13017     _dm_reset,
13018     _dm_rotate,
13019     _dm_scalex,
13020     _dm_scaley,
13021     _dm_shiftx,
13022     _dm_table,
13023     _dm_tintcolor,
13024     _dm_tintmode,
13025     _dm_transbg,
13026     _dm_watermode,
13027     _dm_wavelength,
13028     _dm_wavespeed,
13029     _dm_wavetime,
13030     _dm_xrepeat,
13031     _dm_xspan,
13032     _dm_yrepeat,
13033     _dm_yspan,
13034     _dm_the_end,
13035 };
13036 
13037 
mapstrings_drawmethodproperty(ScriptVariant ** varlist,int paramCount)13038 int mapstrings_drawmethodproperty(ScriptVariant **varlist, int paramCount)
13039 {
13040     char *propname = NULL;
13041     int prop;
13042 
13043     static const char *proplist[] =
13044     {
13045         "alpha",
13046         "amplitude",
13047         "beginsize",
13048         "centerx",
13049         "centery",
13050         "channelb",
13051         "channelg",
13052         "channelr",
13053         "clip",
13054         "cliph",
13055         "clipw",
13056         "clipx",
13057         "clipy",
13058         "enabled",
13059         "endsize",
13060         "fillcolor",
13061         "flag",
13062         "fliprotate",
13063         "flipx",
13064         "perspective",
13065         "remap",
13066         "reset",
13067         "rotate",
13068         "scalex",
13069         "scaley",
13070         "shiftx",
13071         "table",
13072         "tintcolor",
13073         "tintmode",
13074         "transbg",
13075         "watermode",
13076         "wavelength",
13077         "wavespeed",
13078         "wavetime",
13079         "xrepeat",
13080         "xspan",
13081         "yrepeat",
13082         "yspan",
13083     };
13084 
13085 
13086     if(paramCount < 2)
13087     {
13088         return 1;
13089     }
13090     MAPSTRINGS(varlist[1], proplist, _dm_the_end,
13091                "Property name '%s' is not supported by drawmethod.\n");
13092 
13093     return 1;
13094 }
13095 
13096 // changedrawmethod(entity, propertyname, value);
openbor_changedrawmethod(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13097 HRESULT openbor_changedrawmethod(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13098 {
13099     entity *e;
13100     LONG temp = 0;
13101     DOUBLE ftemp = 0;
13102     s_drawmethod *pmethod;
13103     *pretvar = NULL;
13104 
13105     if(paramCount < 3)
13106     {
13107         goto changedm_error;
13108     }
13109 
13110     mapstrings_drawmethodproperty(varlist, paramCount);
13111 
13112     if(varlist[0]->vt == VT_EMPTY)
13113     {
13114         e = NULL;
13115     }
13116     else if(varlist[0]->vt == VT_PTR)
13117     {
13118         e = (entity *)varlist[0]->ptrVal;
13119     }
13120     else
13121     {
13122         goto changedm_error;
13123     }
13124 
13125     if(e)
13126     {
13127         pmethod = &(e->drawmethod);
13128     }
13129     else
13130     {
13131         pmethod = &(drawmethod);
13132     }
13133 
13134     switch(varlist[1]->lVal)
13135     {
13136 
13137     case _dm_alpha:
13138         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13139         {
13140             return E_FAIL;
13141         }
13142         pmethod->alpha = (int)temp;
13143         break;
13144     case _dm_amplitude:
13145         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13146         {
13147             return E_FAIL;
13148         }
13149         pmethod->water.amplitude = (int)temp;
13150         break;
13151     case _dm_beginsize:
13152         if(FAILED(ScriptVariant_DecimalValue(varlist[2], &ftemp)))
13153         {
13154             return E_FAIL;
13155         }
13156         pmethod->water.beginsize = (float)ftemp;
13157         break;
13158     case _dm_centerx:
13159         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13160         {
13161             return E_FAIL;
13162         }
13163         pmethod->centerx = (int)temp;
13164         break;
13165     case _dm_centery:
13166         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13167         {
13168             return E_FAIL;
13169         }
13170         pmethod->centery = (int)temp;
13171         break;
13172     case _dm_channelb:
13173         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13174         {
13175             return E_FAIL;
13176         }
13177         pmethod->channelb = (int)temp;
13178         break;
13179     case _dm_channelg:
13180         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13181         {
13182             return E_FAIL;
13183         }
13184         pmethod->channelg = (int)temp;
13185         break;
13186     case _dm_channelr:
13187         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13188         {
13189             return E_FAIL;
13190         }
13191         pmethod->channelr = (int)temp;
13192         break;
13193     case _dm_clip:
13194         if(paramCount < 6)
13195         {
13196             return E_FAIL;
13197         }
13198         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13199         {
13200             return E_FAIL;
13201         }
13202         pmethod->clipx = (int)temp;
13203         if(FAILED(ScriptVariant_IntegerValue(varlist[3], &temp)))
13204         {
13205             return E_FAIL;
13206         }
13207         pmethod->clipy = (int)temp;
13208         if(FAILED(ScriptVariant_IntegerValue(varlist[4], &temp)))
13209         {
13210             return E_FAIL;
13211         }
13212         pmethod->clipw = (int)temp;
13213         if(FAILED(ScriptVariant_IntegerValue(varlist[5], &temp)))
13214         {
13215             return E_FAIL;
13216         }
13217         pmethod->cliph = (int)temp;
13218         break;
13219     case _dm_clipx:
13220         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13221         {
13222             return E_FAIL;
13223         }
13224         pmethod->clipx = (int)temp;
13225         break;
13226     case _dm_clipy:
13227         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13228         {
13229             return E_FAIL;
13230         }
13231         pmethod->clipy = (int)temp;
13232         break;
13233     case _dm_clipw:
13234         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13235         {
13236             return E_FAIL;
13237         }
13238         pmethod->clipw = (int)temp;
13239         break;
13240     case _dm_cliph:
13241         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13242         {
13243             return E_FAIL;
13244         }
13245         pmethod->cliph = (int)temp;
13246         break;
13247     case _dm_enabled:
13248     case _dm_flag:
13249         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13250         {
13251             return E_FAIL;
13252         }
13253         pmethod->flag = (int)temp;
13254         break;
13255     case _dm_endsize:
13256         if(FAILED(ScriptVariant_DecimalValue(varlist[2], &ftemp)))
13257         {
13258             return E_FAIL;
13259         }
13260         pmethod->water.endsize = (float)ftemp;
13261         break;
13262     case _dm_fillcolor:
13263         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13264         {
13265             return E_FAIL;
13266         }
13267         pmethod->fillcolor = (int)temp;
13268         break;
13269     case _dm_fliprotate:
13270         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13271         {
13272             return E_FAIL;
13273         }
13274         pmethod->fliprotate = (int)temp;
13275         break;
13276     case _dm_flipx:
13277         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13278         {
13279             return E_FAIL;
13280         }
13281         pmethod->flipx = (int)temp;
13282         break;
13283     case _dm_perspective:
13284         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13285         {
13286             return E_FAIL;
13287         }
13288         pmethod->water.perspective = (int)temp;
13289         break;
13290     case _dm_remap:
13291         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13292         {
13293             return E_FAIL;
13294         }
13295         pmethod->remap = (int)temp;
13296         break;
13297     case _dm_reset:
13298         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13299         {
13300             return E_FAIL;
13301         }
13302         if(temp)
13303         {
13304             *pmethod = plainmethod;
13305         }
13306         break;
13307     case _dm_rotate:
13308         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13309         {
13310             return E_FAIL;
13311         }
13312         pmethod->rotate = (int)temp;
13313         break;
13314     case _dm_scalex:
13315         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13316         {
13317             return E_FAIL;
13318         }
13319         pmethod->scalex = (int)temp;
13320         break;
13321     case _dm_scaley:
13322         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13323         {
13324             return E_FAIL;
13325         }
13326         pmethod->scaley = (int)temp;
13327         break;
13328     case _dm_shiftx:
13329         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13330         {
13331             return E_FAIL;
13332         }
13333         pmethod->shiftx = (int)temp;
13334         break;
13335     case _dm_table:
13336         if(varlist[2]->vt != VT_PTR && varlist[2]->vt != VT_EMPTY )
13337         {
13338             return E_FAIL;
13339         }
13340         pmethod->table = (void *)varlist[2]->ptrVal;
13341         break;
13342     case _dm_tintmode:
13343         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13344         {
13345             return E_FAIL;
13346         }
13347         pmethod->tintmode = (int)temp;
13348         break;
13349     case _dm_tintcolor:
13350         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13351         {
13352             return E_FAIL;
13353         }
13354         pmethod->tintcolor = (int)temp;
13355         break;
13356     case _dm_transbg:
13357         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13358         {
13359             return E_FAIL;
13360         }
13361         pmethod->transbg = (int)temp;
13362         break;
13363     case _dm_watermode:
13364         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13365         {
13366             return E_FAIL;
13367         }
13368         pmethod->water.watermode = (int)temp;
13369         break;
13370     case _dm_wavelength:
13371         if(FAILED(ScriptVariant_DecimalValue(varlist[2], &ftemp)))
13372         {
13373             return E_FAIL;
13374         }
13375         pmethod->water.wavelength = (float)ftemp;
13376         break;
13377     case _dm_wavespeed:
13378         if(FAILED(ScriptVariant_DecimalValue(varlist[2], &ftemp)))
13379         {
13380             return E_FAIL;
13381         }
13382         pmethod->water.wavespeed = (float)ftemp;
13383         break;
13384     case _dm_wavetime:
13385         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13386         {
13387             return E_FAIL;
13388         }
13389         pmethod->water.wavetime = (int)(temp * pmethod->water.wavespeed);
13390         break;
13391     case _dm_xrepeat:
13392         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13393         {
13394             return E_FAIL;
13395         }
13396         pmethod->xrepeat = (int)temp;
13397         break;
13398     case _dm_yrepeat:
13399         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13400         {
13401             return E_FAIL;
13402         }
13403         pmethod->yrepeat = (int)temp;
13404         break;
13405     case _dm_xspan:
13406         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13407         {
13408             return E_FAIL;
13409         }
13410         pmethod->xspan = (int)temp;
13411         break;
13412     case _dm_yspan:
13413         if(FAILED(ScriptVariant_IntegerValue(varlist[2], &temp)))
13414         {
13415             return E_FAIL;
13416         }
13417         pmethod->yspan = (int)temp;
13418         break;
13419     default:
13420         break;
13421 
13422     }
13423 
13424     return S_OK;
13425 
13426 changedm_error:
13427     printf("Function changedrawmethod must have at least 3 parameters: entity, propertyname, value\n");
13428     return E_FAIL;
13429 }
13430 
13431 
13432 //deprecated
13433 //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);
openbor_setdrawmethod(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13434 HRESULT openbor_setdrawmethod(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13435 {
13436     LONG value[14];
13437     entity *e;
13438     s_drawmethod *pmethod;
13439     int i;
13440 
13441     *pretvar = NULL;
13442     if(paramCount < 2)
13443     {
13444         goto setdrawmethod_error;
13445     }
13446 
13447     if(varlist[0]->vt == VT_EMPTY)
13448     {
13449         e = NULL;
13450     }
13451     else if(varlist[0]->vt == VT_PTR)
13452     {
13453         e = (entity *)varlist[0]->ptrVal;
13454     }
13455     else
13456     {
13457         goto setdrawmethod_error;
13458     }
13459 
13460     if(e)
13461     {
13462         pmethod = &(e->drawmethod);
13463     }
13464     else
13465     {
13466         pmethod = &(drawmethod);
13467     }
13468 
13469     memset(value, 0, sizeof(value));
13470     for(i = 1; i < paramCount && i < 13; i++)
13471     {
13472         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 1)))
13473         {
13474             goto setdrawmethod_error;
13475         }
13476     }
13477 
13478     if(paramCount >= 14 && varlist[13]->vt != VT_PTR && varlist[13]->vt != VT_EMPTY)
13479     {
13480         goto setdrawmethod_error;
13481     }
13482 
13483     for(i = 14; i < paramCount && i < 16; i++)
13484     {
13485         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 2)))
13486         {
13487             goto setdrawmethod_error;
13488         }
13489     }
13490 
13491     pmethod->flag = (int)value[0];
13492     pmethod->scalex = (int)value[1];
13493     pmethod->scaley = (int)value[2];
13494     pmethod->flipx = (int)value[3];
13495     pmethod->flipy = (int)value[4];
13496     pmethod->shiftx = (int)value[5];
13497     pmethod->alpha = (int)value[6];
13498     pmethod->remap = (int)value[7];
13499     pmethod->fillcolor = (int)value[8];
13500     pmethod->rotate = ((int)value[9]) % 360;
13501     pmethod->fliprotate = (int)value[10];
13502     pmethod->transbg = (int)value[11];
13503     if(paramCount >= 14)
13504     {
13505         pmethod->table = (unsigned char *)varlist[13]->ptrVal;
13506     }
13507     pmethod->centerx = (int)value[12];
13508     pmethod->centery = (int)value[13];
13509 
13510     if(pmethod->rotate < 0)
13511     {
13512         pmethod->rotate += 360;
13513     }
13514     return S_OK;
13515 
13516 setdrawmethod_error:
13517     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");
13518     return E_FAIL;
13519 }
13520 
13521 //updateframe(entity, int frame);
openbor_updateframe(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13522 HRESULT openbor_updateframe(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13523 {
13524     LONG f;
13525     entity *e;
13526     void update_frame(entity * ent, int f);
13527 
13528     *pretvar = NULL;
13529     if(paramCount < 2)
13530     {
13531         goto updateframe_error;
13532     }
13533 
13534     if(varlist[0]->vt == VT_EMPTY)
13535     {
13536         e = NULL;
13537     }
13538     else if(varlist[0]->vt == VT_PTR)
13539     {
13540         e = (entity *)varlist[0]->ptrVal;
13541     }
13542     else
13543     {
13544         goto updateframe_error;
13545     }
13546 
13547     if(!e)
13548     {
13549         goto updateframe_error;
13550     }
13551 
13552     if(FAILED(ScriptVariant_IntegerValue(varlist[1], &f)))
13553     {
13554         goto updateframe_error;
13555     }
13556 
13557     update_frame(e, (int)f);
13558 
13559     return S_OK;
13560 
13561 updateframe_error:
13562     printf("Function need a valid entity handle and at an interger parameter: updateframe(entity, int frame)\n");
13563     return E_FAIL;
13564 }
13565 
13566 //performattack(entity, int anim, int resetable);
openbor_performattack(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13567 HRESULT openbor_performattack(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13568 {
13569     LONG anim, resetable = 0;
13570     entity *e;
13571 
13572     *pretvar = NULL;
13573     if(paramCount < 1)
13574     {
13575         goto performattack_error;
13576     }
13577 
13578     if(varlist[0]->vt == VT_EMPTY)
13579     {
13580         e = NULL;
13581     }
13582     else if(varlist[0]->vt == VT_PTR)
13583     {
13584         e = (entity *)varlist[0]->ptrVal;
13585     }
13586     else
13587     {
13588         goto performattack_error;
13589     }
13590 
13591     if(!e)
13592     {
13593         goto performattack_error;
13594     }
13595 
13596     e->takeaction = common_attack_proc;
13597     e->attacking = 1;
13598     e->idling = 0;
13599     e->drop = 0;
13600     e->falling = 0;
13601     e->inpain = 0;
13602     e->blocking = 0;
13603 
13604     if(paramCount == 1)
13605     {
13606         return S_OK;
13607     }
13608 
13609     if(paramCount > 1 && FAILED(ScriptVariant_IntegerValue(varlist[1], &anim)))
13610     {
13611         goto performattack_error;
13612     }
13613     if(paramCount > 2 && FAILED(ScriptVariant_IntegerValue(varlist[2], &resetable)))
13614     {
13615         goto performattack_error;
13616     }
13617     ent_set_anim(e, (int)anim, (int)resetable);
13618 
13619     return S_OK;
13620 
13621 performattack_error:
13622     printf("Function need a valid entity handle, the other 2 integer parameters are optional: performattack(entity, int anim, int resetable)\n");
13623     return E_FAIL;
13624 }
13625 
13626 //setidle(entity, int anim, int resetable, int stalladd);
openbor_setidle(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13627 HRESULT openbor_setidle(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13628 {
13629     LONG anim = 0, resetable = 0, stalladd = 0;
13630     entity *e;
13631     extern unsigned int time;
13632 
13633     *pretvar = NULL;
13634     if(paramCount < 1)
13635     {
13636         goto setidle_error;
13637     }
13638 
13639     if(varlist[0]->vt == VT_EMPTY)
13640     {
13641         e = NULL;
13642     }
13643     else if(varlist[0]->vt == VT_PTR)
13644     {
13645         e = (entity *)varlist[0]->ptrVal;
13646     }
13647     else
13648     {
13649         goto setidle_error;
13650     }
13651 
13652     if(!e)
13653     {
13654         goto setidle_error;
13655     }
13656 
13657     e->takeaction = NULL;
13658     e->attacking = 0;
13659     e->idling = 1;
13660     e->drop = 0;
13661     e->falling = 0;
13662     e->inpain = 0;
13663     e->blocking = 0;
13664     e->nograb = 0;
13665     e->destx = e->x;
13666     e->destz = e->z;
13667 
13668     if(paramCount == 1)
13669     {
13670         return S_OK;
13671     }
13672 
13673     if(paramCount > 1 && FAILED(ScriptVariant_IntegerValue(varlist[1], &anim)))
13674     {
13675         goto setidle_error;
13676     }
13677     if(paramCount > 2 && FAILED(ScriptVariant_IntegerValue(varlist[2], &resetable)))
13678     {
13679         goto setidle_error;
13680     }
13681     if(paramCount > 3 && FAILED(ScriptVariant_IntegerValue(varlist[3], &stalladd)))
13682     {
13683         goto setidle_error;
13684     }
13685     ent_set_anim(e, (int)anim, (int)resetable);
13686 
13687     if(stalladd > 0)
13688     {
13689         e->stalltime = time + stalladd;
13690     }
13691 
13692     return S_OK;
13693 
13694 setidle_error:
13695     printf("Function need a valid entity handle, the other 3 integer parameters are optional: setidle(entity, int anim, int resetable, int stalladd)\n");
13696     return E_FAIL;
13697 }
13698 
13699 //getentity(int index_from_list)
openbor_getentity(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13700 HRESULT openbor_getentity(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13701 {
13702     LONG ind;
13703     extern entity **ent_list;
13704     extern int ent_list_size;
13705 
13706     if(paramCount != 1)
13707     {
13708         goto getentity_error;
13709     }
13710 
13711     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ind)))
13712     {
13713         goto getentity_error;
13714     }
13715 
13716     ScriptVariant_Clear(*pretvar);
13717 
13718     if((int)ind < ent_list_size && (int)ind >= 0)
13719     {
13720         ScriptVariant_ChangeType(*pretvar, VT_PTR);
13721         (*pretvar)->ptrVal = (VOID *)ent_list[(int)ind];
13722     }
13723     //else, it should return an empty value
13724     return S_OK;
13725 
13726 getentity_error:
13727     printf("Function need an integer parameter: getentity(int index_in_list)\n");
13728     *pretvar = NULL;
13729     return E_FAIL;
13730 }
13731 
13732 
13733 //loadmodel(name)
openbor_loadmodel(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13734 HRESULT openbor_loadmodel(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13735 {
13736     LONG unload = 0;
13737     s_model *model;
13738     if(paramCount < 1)
13739     {
13740         goto loadmodel_error;
13741     }
13742     if(varlist[0]->vt != VT_STR)
13743     {
13744         goto loadmodel_error;
13745     }
13746 
13747     ScriptVariant_ChangeType(*pretvar, VT_PTR);
13748     if(paramCount >= 2)
13749         if(FAILED(ScriptVariant_IntegerValue(varlist[1], &unload)))
13750         {
13751             goto loadmodel_error;
13752         }
13753 
13754     model = load_cached_model(StrCache_Get(varlist[0]->strVal), "openbor_loadmodel", (char)unload);
13755 
13756     if(paramCount >= 3 && model)
13757     {
13758         model_cache[model->index].selectable = (char)ScriptVariant_IsTrue(varlist[2]);
13759     }
13760 
13761     (*pretvar)->ptrVal = (VOID *)model;
13762 
13763     //else, it should return an empty value
13764     return S_OK;
13765 
13766 loadmodel_error:
13767     printf("Function needs a string and integer parameters: loadmodel(name, unload, selectable)\n");
13768     ScriptVariant_Clear(*pretvar);
13769     *pretvar = NULL;
13770     return E_FAIL;
13771 }
13772 
13773 // load a sprite which doesn't belong to the sprite_cache
13774 // loadsprite(path, maskpath)
openbor_loadsprite(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13775 HRESULT openbor_loadsprite(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13776 {
13777     extern s_sprite *loadsprite2(char * filename, int * width, int * height);
13778     s_sprite *spr, *mask;
13779     if(paramCount < 1)
13780     {
13781         goto loadsprite_error;
13782     }
13783 
13784     if(varlist[0]->vt != VT_STR)
13785     {
13786         goto loadsprite_error;
13787     }
13788 
13789     ScriptVariant_ChangeType(*pretvar, VT_PTR);
13790     if((spr = loadsprite2(StrCache_Get(varlist[0]->strVal), NULL, NULL)))
13791     {
13792         (*pretvar)->ptrVal = (VOID *)spr;
13793         if(paramCount > 1 && (mask = loadsprite2(StrCache_Get(varlist[1]->strVal), NULL, NULL)))
13794         {
13795             spr->mask = mask;
13796         }
13797         List_InsertAfter(&scriptheap, (void *)spr, "openbor_loadsprite");
13798     }
13799     //else, it should return an empty value
13800     return S_OK;
13801 
13802 loadsprite_error:
13803     printf("Function need a string parameter: loadsprite(path)\n");
13804     ScriptVariant_Clear(*pretvar);
13805     *pretvar = NULL;
13806     return E_FAIL;
13807 }
13808 
13809 // Call options menu, blocked
openbor_options(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13810 HRESULT openbor_options(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13811 {
13812     void options();
13813     options();
13814     *pretvar = NULL;
13815     return S_OK;
13816 }
13817 
13818 //playgif(path, int x, int y, int noskip)
openbor_playgif(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13819 HRESULT openbor_playgif(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13820 {
13821     LONG temp[3] = {0, 0, 0}; //x,y,noskip
13822     int i;
13823     extern unsigned char pal[1024];
13824     extern int playgif(char * filename, int x, int y, int noskip);
13825     if(paramCount < 1)
13826     {
13827         goto playgif_error;
13828     }
13829 
13830     if(varlist[0]->vt != VT_STR)
13831     {
13832         goto playgif_error;
13833     }
13834 
13835     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13836     for(i = 0; i < 3 && i < paramCount - 1; i++)
13837     {
13838         if(FAILED(ScriptVariant_IntegerValue(varlist[i + 1], temp + i)))
13839         {
13840             goto playgif_error;
13841         }
13842     }
13843     (*pretvar)->lVal = (LONG)playgif(StrCache_Get(varlist[0]->strVal), (int)(temp[0]), (int)(temp[1]), (int)(temp[2]));
13844     palette_set_corrected(pal, savedata.gamma, savedata.gamma, savedata.gamma, savedata.brightness, savedata.brightness, savedata.brightness);
13845     return S_OK;
13846 
13847 playgif_error:
13848     printf("Function need a string parameter, other parameters are optional: playgif(path, int x, int y, int noskip)\n");
13849     *pretvar = NULL;
13850     return E_FAIL;
13851 }
13852 
13853 //open and return a handle
13854 //TODO: error messages
openbor_openanigif(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13855 HRESULT openbor_openanigif(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13856 {
13857     anigif_info *info = NULL;
13858 
13859     if(varlist[0]->vt != VT_STR)
13860     {
13861         goto openanigif_error;
13862     }
13863 
13864     info = calloc(1, sizeof(*info));
13865     if(anigif_open(StrCache_Get(varlist[0]->strVal), packfile, info))
13866     {
13867         info->magic = anigif_magic;
13868         List_InsertAfter(&scriptheap, (void *)info, "openbor_openanigif");
13869         ScriptVariant_ChangeType(*pretvar, VT_PTR);
13870         (*pretvar)->ptrVal = (VOID *)info;
13871         return S_OK;
13872     }
13873 
13874 openanigif_error:
13875     if(info)
13876     {
13877         free(info);
13878     }
13879     *pretvar = NULL;
13880     return E_FAIL;
13881 }
13882 
13883 //decode a frame if any
openbor_decodeanigif(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13884 HRESULT openbor_decodeanigif(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13885 {
13886     anigif_info *info = NULL;
13887 
13888     if(varlist[0]->vt != VT_PTR || !varlist[0]->ptrVal)
13889     {
13890         goto decodeanigif_error;
13891     }
13892     info = (anigif_info *) varlist[0]->ptrVal;
13893 
13894     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13895     (*pretvar)->lVal = (LONG)anigif_decode_frame(info);
13896     return S_OK;
13897 
13898 decodeanigif_error:
13899     *pretvar = NULL;
13900     return E_FAIL;
13901 }
13902 
13903 //TODO mapstrings
openbor_getanigifinfo(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13904 HRESULT openbor_getanigifinfo(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13905 {
13906     anigif_info *info = NULL;
13907     char *name;
13908 
13909     if(varlist[0]->vt != VT_PTR || !varlist[0]->ptrVal)
13910     {
13911         goto getanigifinfo_error;
13912     }
13913     info = (anigif_info *) varlist[0]->ptrVal;
13914 
13915     if(varlist[1]->vt != VT_STR)
13916     {
13917         goto getanigifinfo_error;
13918     }
13919     name = StrCache_Get(varlist[1]->strVal);
13920     if(0 == stricmp(name, "buffer"))
13921     {
13922         ScriptVariant_ChangeType(*pretvar, VT_PTR);
13923         (*pretvar)->ptrVal = (VOID *)anigif_getbuffer(info);
13924     }
13925     else if(0 == stricmp(name, "done"))
13926     {
13927         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13928         (*pretvar)->lVal = (LONG)info->done;
13929     }
13930     else if(0 == stricmp(name, "frame"))
13931     {
13932         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13933         (*pretvar)->lVal = (LONG)info->frame;
13934     }
13935     else if(0 == stricmp(name, "isRGB"))
13936     {
13937         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13938         (*pretvar)->lVal = (LONG)info->isRGB;
13939     }
13940     else if(0 == stricmp(name, "width"))
13941     {
13942         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13943         (*pretvar)->lVal = (LONG)(info->gifbuffer[0] ? info->gifbuffer[0]->width : 0);
13944     }
13945     else if(0 == stricmp(name, "height"))
13946     {
13947         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13948         (*pretvar)->lVal = (LONG)(info->gifbuffer[0] ? info->gifbuffer[0]->height : 0);
13949     }
13950     else if(0 == stricmp(name, "nextframe"))
13951     {
13952         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13953         (*pretvar)->lVal = (LONG)info->info[0].nextframe;
13954     }
13955     else if(0 == stricmp(name, "lastdelay"))
13956     {
13957         ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
13958         (*pretvar)->lVal = (LONG)info->info[0].lastdelay;
13959     }
13960     else
13961     {
13962         goto getanigifinfo_error;
13963     }
13964 
13965     return S_OK;
13966 
13967 getanigifinfo_error:
13968     *pretvar = NULL;
13969     return E_FAIL;
13970 }
13971 
13972 // complex, so make a function for ai
13973 // adjustwalkanimation(ent, target);
openbor_adjustwalkanimation(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)13974 HRESULT openbor_adjustwalkanimation(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
13975 {
13976 
13977     entity *e, *t, *temp;
13978 
13979     *pretvar = NULL;
13980 
13981     if(paramCount < 1)
13982     {
13983         e = self;
13984     }
13985     else if(varlist[0]->vt == VT_PTR)
13986     {
13987         e = (entity *)varlist[0]->ptrVal;
13988     }
13989     else
13990     {
13991         goto adjustwalkanimation_error;
13992     }
13993 
13994     if(paramCount < 2)
13995     {
13996         t = NULL;
13997     }
13998     else if(varlist[1]->vt == VT_PTR)
13999     {
14000         t = (entity *)varlist[1]->ptrVal;
14001     }
14002     else if(varlist[1]->vt == VT_EMPTY)
14003     {
14004         t = NULL;
14005     }
14006     else
14007     {
14008         goto adjustwalkanimation_error;
14009     }
14010 
14011     temp = self;
14012 
14013     self = e;
14014     adjust_walk_animation(t);
14015     self = temp;
14016 
14017     return S_OK;
14018 adjustwalkanimation_error:
14019     printf("Function adjustwalkanimation(entity, target), both parameters are optional, but must be valid.");
14020     return E_FAIL;
14021 }
14022 
14023 //finditem(entity)
openbor_finditem(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14024 HRESULT openbor_finditem(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14025 {
14026 
14027     entity *e, *t, *temp;
14028 
14029     if(paramCount < 1)
14030     {
14031         e = self;
14032     }
14033     else if(varlist[0]->vt == VT_PTR)
14034     {
14035         e = (entity *)varlist[0]->ptrVal;
14036     }
14037     else
14038     {
14039         goto finditem_error;
14040     }
14041 
14042     temp = self;
14043 
14044     self = e;
14045     t = normal_find_item();
14046     self = temp;
14047 
14048     ScriptVariant_ChangeType(*pretvar, VT_PTR);
14049     (*pretvar)->ptrVal = (VOID *)t;
14050 
14051     return S_OK;
14052 finditem_error:
14053 
14054     *pretvar = NULL;
14055     printf("Function finditem(entity), entity is optional, but must be valid.");
14056     return E_FAIL;
14057 }
14058 
14059 //pickup(entity, item)
openbor_pickup(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14060 HRESULT openbor_pickup(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14061 {
14062 
14063     entity *e, *t, *temp;
14064 
14065     *pretvar = NULL;
14066 
14067     if(paramCount < 2)
14068     {
14069         goto pickup_error;
14070     }
14071 
14072     if(varlist[0]->vt == VT_PTR)
14073     {
14074         e = (entity *)varlist[0]->ptrVal;
14075     }
14076     else
14077     {
14078         goto pickup_error;
14079     }
14080 
14081     if(varlist[1]->vt == VT_PTR)
14082     {
14083         t = (entity *)varlist[1]->ptrVal;
14084     }
14085     else
14086     {
14087         goto pickup_error;
14088     }
14089 
14090     if(!e || !t)
14091     {
14092         goto pickup_error;
14093     }
14094 
14095     temp = self;
14096 
14097     self = e;
14098     common_pickupitem(t);
14099     self = temp;
14100 
14101     return S_OK;
14102 pickup_error:
14103     printf("Function pickup(entity, item), handles must be valid.");
14104     return E_FAIL;
14105 }
14106 
14107 //waypoints(ent, x1, z1, x2, z2, x3, z3, ...)
14108 //zero length list means clear waypoints
openbor_waypoints(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14109 HRESULT openbor_waypoints(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14110 {
14111     int num, i;
14112     point2d *wp = NULL;
14113     DOUBLE x, z;
14114 
14115     entity *e;
14116     *pretvar = NULL;
14117 
14118     if(paramCount < 1)
14119     {
14120         goto wp_error;
14121     }
14122 
14123     if(varlist[0]->vt == VT_PTR)
14124     {
14125         e = (entity *)varlist[0]->ptrVal;
14126     }
14127     else
14128     {
14129         goto wp_error;
14130     }
14131 
14132     num = (paramCount - 1) / 2;
14133     if(num > 0)
14134     {
14135         //append
14136         wp = malloc(sizeof(*wp) * (num + e->numwaypoints));
14137 
14138         for(i = 0; i < num ; i++)
14139         {
14140             if(FAILED(ScriptVariant_DecimalValue(varlist[1], &x)))
14141             {
14142                 goto wp_error;
14143             }
14144 
14145             if(FAILED(ScriptVariant_DecimalValue(varlist[2], &z)))
14146             {
14147                 goto wp_error;
14148             }
14149 
14150             wp[num - i - 1].x = (float)x;
14151             wp[num - i - 1].z = (float)z;
14152         }
14153         if(e->numwaypoints)
14154         {
14155             for(i = 0; i < e->numwaypoints; i++)
14156             {
14157                 wp[i + num] = e->waypoints[i];
14158             }
14159         }
14160 
14161         if(e->waypoints)
14162         {
14163             free(e->waypoints);
14164         }
14165         e->waypoints = wp;
14166         e->numwaypoints = num;
14167     }
14168     else
14169     {
14170         e->numwaypoints = 0;
14171         if(e->waypoints)
14172         {
14173             free(e->waypoints);
14174         }
14175         e->waypoints = NULL;
14176     }
14177     return S_OK;
14178 
14179 wp_error:
14180     if(wp)
14181     {
14182         free(wp);
14183     }
14184     wp = NULL;
14185     printf("Function waypoints requires a valid entity handle and a list of x, z value pairs.");
14186     return E_FAIL;
14187 }
14188 
14189 //testmove(entity, x, z)
openbor_testmove(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14190 HRESULT openbor_testmove(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14191 {
14192 
14193     entity *e;
14194     DOUBLE x, z;
14195 
14196     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
14197 
14198     if(paramCount < 3)
14199     {
14200         goto testmove_error;
14201     }
14202 
14203     if(varlist[0]->vt == VT_PTR)
14204     {
14205         e = (entity *)varlist[0]->ptrVal;
14206     }
14207     else
14208     {
14209         goto testmove_error;
14210     }
14211 
14212     if(FAILED(ScriptVariant_DecimalValue(varlist[1], &x)))
14213     {
14214         goto testmove_error;
14215     }
14216 
14217     if(FAILED(ScriptVariant_DecimalValue(varlist[2], &z)))
14218     {
14219         goto testmove_error;
14220     }
14221 
14222     if(!e)
14223     {
14224         goto testmove_error;
14225     }
14226 
14227     (*pretvar)->lVal = (LONG) testmove(e, e->x, e->z, x, z);
14228 
14229     return S_OK;
14230 testmove_error:
14231     *pretvar = NULL;
14232     printf("Function testmove(entity, x, z)");
14233     return E_FAIL;
14234 }
14235 
14236 //spriteq_draw(vscreen, 0, MIN_INT, MAX_INT, dx, dy)
openbor_drawspriteq(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14237 HRESULT openbor_drawspriteq(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14238 {
14239 
14240     LONG value[5] = {0, MIN_INT, MAX_INT, 0, 0};
14241     int i;
14242     s_screen *screen;
14243     extern s_screen *vscreen;
14244 
14245     *pretvar = NULL;
14246 
14247     if(paramCount < 1)
14248     {
14249         goto drawsq_error;
14250     }
14251 
14252     if(varlist[0]->vt != VT_PTR && varlist[0]->vt != VT_EMPTY)
14253     {
14254         goto drawsq_error;
14255     }
14256 
14257     if(varlist[0]->ptrVal)
14258     {
14259         screen = (s_screen *)varlist[0]->ptrVal;
14260     }
14261     else
14262     {
14263         screen = vscreen;
14264     }
14265 
14266     for(i = 1; i < paramCount && i <= 5; i++)
14267     {
14268         if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 1)))
14269         {
14270             goto drawsq_error;
14271         }
14272     }
14273 
14274     spriteq_draw(screen, (int)value[0], (int)value[1], (int)value[2], (int)value[3], (int)value[4]);
14275 
14276     return S_OK;
14277 
14278 drawsq_error:
14279     printf("Function drawspriteq needs a valid screen handle and all other paramaters must be integers.");
14280     return E_FAIL;
14281 
14282 }
14283 
openbor_clearspriteq(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14284 HRESULT openbor_clearspriteq(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14285 {
14286     *pretvar = NULL;
14287     spriteq_clear();
14288     return S_OK;
14289 
14290 }
14291 
14292 // ===== gfxproperty ======
14293 enum gfxproperty_enum
14294 {
14295     _gfx_centerx,
14296     _gfx_centery,
14297     _gfx_height,
14298     _gfx_palette,
14299     _gfx_pixel,
14300     _gfx_pixelformat,
14301     _gfx_srcheight,
14302     _gfx_srcwidth,
14303     _gfx_width,
14304     _gfx_the_end,
14305 };
14306 
mapstrings_gfxproperty(ScriptVariant ** varlist,int paramCount)14307 int mapstrings_gfxproperty(ScriptVariant **varlist, int paramCount)
14308 {
14309     char *propname = NULL;
14310     int prop;
14311 
14312     static const char *proplist[] =
14313     {
14314         "centerx",
14315         "centery",
14316         "height",
14317         "palette",
14318         "pixel",
14319         "pixelformat",
14320         "srcheight",
14321         "srcwidth",
14322         "width",
14323     };
14324 
14325 
14326     if(paramCount < 2)
14327     {
14328         return 1;
14329     }
14330     MAPSTRINGS(varlist[1], proplist, _gfx_the_end,
14331                "Property name '%s' is not supported by gfxproperty.\n");
14332 
14333     return 1;
14334 }
14335 
14336 
14337 // getgfxproperty(handle, propertyname, ...);
openbor_getgfxproperty(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14338 HRESULT openbor_getgfxproperty(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14339 {
14340     s_screen *screen;
14341     s_sprite *sprite;
14342     s_bitmap *bitmap;
14343     LONG value[2] = {0, 0}, v;
14344     void *handle;
14345     int i, x, y;
14346 
14347     if(paramCount < 2)
14348     {
14349         goto ggp_error;
14350     }
14351 
14352     mapstrings_gfxproperty(varlist, paramCount);
14353 
14354     if(varlist[0]->vt != VT_PTR)
14355     {
14356         goto ggp_error;
14357     }
14358 
14359     handle = varlist[0]->ptrVal;
14360 
14361     if(!handle)
14362     {
14363         goto ggp_error;
14364     }
14365 
14366     screen = (s_screen *)handle;
14367     sprite = (s_sprite *)handle;
14368     bitmap = (s_bitmap *)handle;
14369 
14370     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
14371 
14372 
14373     switch(varlist[1]->lVal)
14374     {
14375     case _gfx_width:
14376         switch(screen->magic)
14377         {
14378         case screen_magic:
14379             (*pretvar)->lVal = screen->width;
14380             break;
14381         case sprite_magic:
14382             (*pretvar)->lVal = sprite->width;
14383             break;
14384         case bitmap_magic:
14385             (*pretvar)->lVal = bitmap->width;
14386             break;
14387         default:
14388             goto ggp_error2;
14389         }
14390         break;
14391     case _gfx_height:
14392         switch(screen->magic)
14393         {
14394         case screen_magic:
14395             (*pretvar)->lVal = screen->height;
14396             break;
14397         case sprite_magic:
14398             (*pretvar)->lVal = sprite->height;
14399             break;
14400         case bitmap_magic:
14401             (*pretvar)->lVal = bitmap->height;
14402             break;
14403         default:
14404             goto ggp_error2;
14405         }
14406         break;
14407     case _gfx_srcwidth:
14408         switch(screen->magic)
14409         {
14410         case screen_magic:
14411             (*pretvar)->lVal = screen->width;
14412             break;
14413         case sprite_magic:
14414             (*pretvar)->lVal = sprite->srcwidth;
14415             break;
14416         case bitmap_magic:
14417             (*pretvar)->lVal = bitmap->width;
14418             break;
14419         default:
14420             goto ggp_error2;
14421         }
14422         break;
14423     case _gfx_srcheight:
14424         switch(screen->magic)
14425         {
14426         case screen_magic:
14427             (*pretvar)->lVal = screen->height;
14428             break;
14429         case sprite_magic:
14430             (*pretvar)->lVal = sprite->srcheight;
14431             break;
14432         case bitmap_magic:
14433             (*pretvar)->lVal = bitmap->height;
14434             break;
14435         default:
14436             goto ggp_error2;
14437         }
14438         break;
14439     case _gfx_centerx:
14440         switch(screen->magic)
14441         {
14442         case screen_magic:
14443         case bitmap_magic:
14444             (*pretvar)->lVal = 0;
14445             break;
14446         case sprite_magic:
14447             (*pretvar)->lVal = sprite->centerx;
14448             break;
14449         default:
14450             goto ggp_error2;
14451         }
14452         break;
14453     case _gfx_centery:
14454         switch(screen->magic)
14455         {
14456         case screen_magic:
14457         case bitmap_magic:
14458             (*pretvar)->lVal = 0;
14459             break;
14460         case sprite_magic:
14461             (*pretvar)->lVal = sprite->centery;
14462             break;
14463         default:
14464             goto ggp_error2;
14465         }
14466         break;
14467     case _gfx_palette:
14468         ScriptVariant_ChangeType(*pretvar, VT_PTR);
14469         switch(screen->magic)
14470         {
14471         case screen_magic:
14472             (*pretvar)->ptrVal = (VOID *)screen->palette;
14473             break;
14474         case sprite_magic:
14475             (*pretvar)->ptrVal = (VOID *)sprite->palette;
14476             break;
14477         case bitmap_magic:
14478             (*pretvar)->ptrVal = (VOID *)bitmap->palette;
14479             break;
14480         default:
14481             goto ggp_error2;
14482         }
14483         break;
14484     case _gfx_pixelformat:
14485         switch(screen->magic)
14486         {
14487         case screen_magic:
14488             (*pretvar)->lVal = screen->pixelformat;
14489             break;
14490         case sprite_magic:
14491             (*pretvar)->lVal = sprite->pixelformat;
14492             break;
14493         case bitmap_magic:
14494             (*pretvar)->lVal = bitmap->pixelformat;
14495             break;
14496         default:
14497             goto ggp_error2;
14498         }
14499         break;
14500     case _gfx_pixel:
14501         if(paramCount < 4)
14502         {
14503             goto ggp_error3;
14504         }
14505         for(i = 2; i < 4; i++)
14506         {
14507             if(FAILED(ScriptVariant_IntegerValue(varlist[i], value + i - 2)))
14508             {
14509                 goto ggp_error4;
14510             }
14511         }
14512         x = value[0];
14513         y = value[1];
14514         switch(screen->magic)
14515         {
14516         case bitmap_magic: //As long as the two structures are identical...
14517         case screen_magic:
14518             if(x < 0 || x >= screen->width || y < 0 || y >= screen->height)
14519             {
14520                 v = 0;
14521             }
14522             else
14523             {
14524                 switch(screen->pixelformat)
14525                 {
14526                 case PIXEL_8:
14527                 case PIXEL_x8:
14528                     v = (LONG)(((unsigned char *)screen->data)[y * screen->width + x]);
14529                     break;
14530                 case PIXEL_16:
14531                     v = (LONG)(((unsigned short *)screen->data)[y * screen->width + x]);
14532                     break;
14533                 case PIXEL_32:
14534                     v = (LONG)(((unsigned *)screen->data)[y * screen->width + x]);
14535                     break;
14536                 default:
14537                     v = 0;
14538                 }
14539             }
14540             break;
14541         case sprite_magic:
14542             if(x < 0 || x >= sprite->width || y < 0 || y >= sprite->height)
14543             {
14544                 v = 0;
14545             }
14546             else
14547             {
14548                 v = (LONG)sprite_get_pixel(sprite, x, y);
14549             }
14550             break;
14551         default:
14552             goto ggp_error2;
14553         }
14554         (*pretvar)->lVal = v;
14555         break;
14556     default:
14557         break;
14558 
14559     }
14560 
14561     return S_OK;
14562 
14563 ggp_error:
14564     printf("Function getgfxproperty must have a valid handle and a property name.\n");
14565     *pretvar = NULL;
14566     return E_FAIL;
14567 ggp_error2:
14568     printf("Function getgfxproperty encountered an invalid handle.\n");
14569     *pretvar = NULL;
14570     return E_FAIL;
14571 ggp_error3:
14572     printf("You need to specify x, y value for getgfxproperty.\n");
14573     *pretvar = NULL;
14574     return E_FAIL;
14575 ggp_error4:
14576     printf("Invalid x or y value for getgfxproperty.\n");
14577     *pretvar = NULL;
14578     return E_FAIL;
14579 }
14580 
14581 //allocscript(name, comment);
openbor_allocscript(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14582 HRESULT openbor_allocscript(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14583 {
14584     Script *ns;
14585     char *name = NULL, *comment = NULL;
14586 
14587     ns = malloc(sizeof(Script));
14588 
14589     if(ns == NULL)
14590     {
14591         goto as_error;
14592     }
14593 
14594     if(paramCount >= 1 && varlist[0]->vt == VT_STR)
14595     {
14596         name = (char *)StrCache_Get(varlist[0]->strVal);
14597     }
14598     if(paramCount >= 2 && varlist[1]->vt == VT_STR)
14599     {
14600         comment = (char *)StrCache_Get(varlist[1]->strVal);
14601     }
14602 
14603     Script_Init(ns, name, comment, 1);
14604 
14605     List_InsertAfter(&scriptheap, (void *)ns, "openbor_allocscript");
14606 
14607     ScriptVariant_ChangeType(*pretvar, VT_PTR);
14608     (*pretvar)->ptrVal = (VOID *)ns;
14609     return S_OK;
14610 
14611 as_error:
14612     printf("Function allocscript failed to alloc enough memory.\n");
14613     (*pretvar) = NULL;
14614     return E_FAIL;
14615 }
14616 
14617 //loadscript(handle, path);
openbor_loadscript(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14618 HRESULT openbor_loadscript(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14619 {
14620     Script *ns = NULL;
14621     char *path = NULL;
14622     int load_script(Script * script, char * file);
14623 
14624     (*pretvar) = NULL;
14625 
14626     if(paramCount >= 1 && varlist[0]->vt == VT_PTR)
14627     {
14628         ns = (Script *)varlist[0]->ptrVal;
14629     }
14630     if(ns == NULL || ns->magic != script_magic)
14631     {
14632         goto ls_error;
14633     }
14634     if(paramCount >= 2 && varlist[1]->vt == VT_STR)
14635     {
14636         path = (char *)StrCache_Get(varlist[1]->strVal);
14637     }
14638     if(path == NULL)
14639     {
14640         goto ls_error;
14641     }
14642 
14643     load_script(ns, path);
14644     //Script_Init(ns, name, comment, 1);
14645     //if(!load_script(ns, path)) goto ls_error2;
14646 
14647     return S_OK;
14648 
14649 ls_error:
14650     printf("Function loadscript requires a valid script handle and a path.\n");
14651     return E_FAIL;
14652 }
14653 
14654 //compilescript(handle);
openbor_compilescript(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14655 HRESULT openbor_compilescript(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14656 {
14657     Script *ns = NULL;
14658 
14659     (*pretvar) = NULL;
14660 
14661     if(paramCount >= 1 && varlist[0]->vt == VT_PTR)
14662     {
14663         ns = (Script *)varlist[0]->ptrVal;
14664     }
14665     if(ns == NULL || ns->magic != script_magic)
14666     {
14667         goto cs_error;
14668     }
14669 
14670     Script_Compile(ns);
14671 
14672     return S_OK;
14673 
14674 cs_error:
14675     printf("Function compilescript requires a valid script handle.\n");
14676     return E_FAIL;
14677 }
14678 
14679 //executescript(handle);
openbor_executescript(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14680 HRESULT openbor_executescript(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14681 {
14682     Script *ns = NULL;
14683 
14684     (*pretvar) = NULL;
14685 
14686     if(paramCount >= 1 && varlist[0]->vt == VT_PTR)
14687     {
14688         ns = (Script *)varlist[0]->ptrVal;
14689     }
14690     if(ns == NULL || ns->magic != script_magic)
14691     {
14692         goto cs_error;
14693     }
14694 
14695     Script_Execute(ns);
14696 
14697     return S_OK;
14698 
14699 cs_error:
14700     printf("Function executescript requires a valid script handle.\n");
14701     return E_FAIL;
14702 }
14703 
14704 
14705 //loadgamefile() //only reload saved level file from saves
openbor_loadgamefile(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14706 HRESULT openbor_loadgamefile(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14707 {
14708     loadGameFile();
14709     *pretvar = NULL;
14710     return S_OK;
14711 }
14712 
14713 //playgame(set, usesave?)
openbor_playgame(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14714 HRESULT openbor_playgame(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14715 {
14716     LONG lset = 0, lsave = -1;
14717     *pretvar = NULL;
14718 
14719     if(paramCount >= 1 && FAILED(ScriptVariant_IntegerValue(varlist[0], &lset)) )
14720     {
14721         goto pg_error;
14722     }
14723     if(paramCount >= 2 && FAILED(ScriptVariant_IntegerValue(varlist[1], &lsave)) )
14724     {
14725         goto pg_error;
14726     }
14727 
14728 
14729     useSave = lsave;
14730     useSet = lset;
14731     endgame = 1;
14732 
14733     return S_OK;
14734 
14735 pg_error:
14736     *pretvar = NULL;
14737     return E_FAIL;
14738 }
14739 
14740 //getsaveinfo(set, prop);
openbor_getsaveinfo(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)14741 HRESULT openbor_getsaveinfo(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
14742 {
14743     LONG ltemp;
14744     s_savelevel *slot;
14745     char *prop;
14746     if(paramCount < 2)
14747     {
14748         goto gsi_error;
14749     }
14750 
14751     if(FAILED(ScriptVariant_IntegerValue(varlist[0], &ltemp)) || varlist[1]->vt != VT_STR)
14752     {
14753         goto gsi_error;
14754     }
14755 
14756     if(!savelevel)
14757     {
14758         ScriptVariant_Clear(*pretvar);
14759         return S_OK;
14760     }
14761 
14762     slot = savelevel + ltemp;
14763     prop = (char *)StrCache_Get(varlist[1]->strVal);
14764 
14765     ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
14766     if(0 == stricmp(prop, "flag"))
14767     {
14768         (*pretvar)->lVal = (LONG)slot->flag;
14769     }
14770     else if(0 == stricmp(prop, "level"))
14771     {
14772         (*pretvar)->lVal = (LONG)slot->level;
14773     }
14774     else if(0 == stricmp(prop, "stage"))
14775     {
14776         (*pretvar)->lVal = (LONG)slot->stage;
14777     }
14778     else if(0 == stricmp(prop, "times_completed"))
14779     {
14780         (*pretvar)->lVal = (LONG)slot->times_completed;
14781     }
14782     else if(0 == stricmp(prop, "score"))
14783     {
14784         if(paramCount < 3 || FAILED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) )
14785         {
14786             goto gsi_error;
14787         }
14788         (*pretvar)->lVal = (LONG)slot->pScores[ltemp];
14789     }
14790     else if(0 == stricmp(prop, "lives"))
14791     {
14792         if(paramCount < 3 || FAILED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) )
14793         {
14794             goto gsi_error;
14795         }
14796         (*pretvar)->lVal = (LONG)slot->pLives[ltemp];
14797     }
14798     else if(0 == stricmp(prop, "credits"))
14799     {
14800         if(paramCount < 3 || FAILED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) )
14801         {
14802             goto gsi_error;
14803         }
14804         (*pretvar)->lVal = (LONG)(noshare ? slot->credits : slot->pCredits[ltemp]);
14805     }
14806     else if(0 == stricmp(prop, "name"))
14807     {
14808         ScriptVariant_ChangeType(*pretvar, VT_STR);
14809         StrCache_Copy((*pretvar)->strVal, slot->dName);
14810     }
14811     else if(0 == stricmp(prop, "playername"))
14812     {
14813         if(paramCount < 3 || FAILED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) )
14814         {
14815             goto gsi_error;
14816         }
14817         ScriptVariant_ChangeType(*pretvar, VT_STR);
14818         StrCache_Copy((*pretvar)->strVal, slot->pName[ltemp]);
14819     }
14820     else if(0 == stricmp(prop, "health"))
14821     {
14822         if(paramCount < 3 || FAILED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) )
14823         {
14824             goto gsi_error;
14825         }
14826         (*pretvar)->lVal = (LONG)slot->pSpawnhealth[ltemp];
14827     }
14828     else if(0 == stricmp(prop, "mp"))
14829     {
14830         if(paramCount < 3 || FAILED(ScriptVariant_IntegerValue(varlist[2], &ltemp)) )
14831         {
14832             goto gsi_error;
14833         }
14834         (*pretvar)->lVal = (LONG)slot->pSpawnmp[ltemp];
14835     }
14836     else
14837     {
14838         goto gsi_error;
14839     }
14840     return S_OK;
14841 
14842 gsi_error:
14843     *pretvar = NULL;
14844     return E_FAIL;
14845 }
14846