source: Daodan/src/Daodan_BSL.c @ 455

Last change on this file since 455 was 451, checked in by rossy, 14 years ago

bsl thingy

File size: 16.2 KB
Line 
1#include <stdio.h>
2#include <stdbool.h>
3#include <time.h>
4#include <ffi.h>
5
6#include "inifile.h"
7
8#include "Daodan_BSL.h"
9#include "Daodan_Utility.h"
10#include "Daodan_Patch.h"
11#include "Daodan_Console.h"
12#include "BFW_ScriptLang.h"
13#include "Oni.h"
14#include "Oni_Character.h"
15#include "oni_gl.h"
16#include "dSFMT\dSFMT.h"
17#include "Daodan_Character.h"
18
19uint16_t ONICALL bsl_int32mul(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
20{
21        ret->value_int32 = args[0].value_int32 * args[1].value_int32;
22        ret->type = sl_int32;
23        return 0;
24}
25
26uint16_t ONICALL bsl_mul(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
27{
28        double val1;
29        double val2;
30       
31        if (args[0].type == sl_int32)
32                val1 = args[0].value_int32;
33        else
34                val1 = args[0].value_float;
35       
36        if (args[1].type == sl_int32)
37                val2 = args[1].value_int32;
38        else
39                val2 = args[1].value_float;
40       
41        ret->value_float = (float)(val1 * val2);
42        ret->type = sl_float;
43        return 0;
44}
45
46uint16_t ONICALL bsl_int32div(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
47{
48        ret->value_int32 = args[0].value_int32 / args[1].value_int32;
49        ret->type = sl_int32;
50        return 0;
51}
52
53uint16_t ONICALL bsl_div(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
54{
55        double val1;
56        double val2;
57       
58        if (args[0].type == sl_int32)
59                val1 = args[0].value_int32;
60        else
61                val1 = args[0].value_float;
62       
63        if (args[1].type == sl_int32)
64                val2 = args[1].value_int32;
65        else
66                val2 = args[1].value_float;
67       
68        ret->value_float = (float)(val1 / val2);
69        ret->type = sl_float;
70        return 0;
71}
72
73uint16_t ONICALL bsl_int32rand(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
74{
75        int32_t start = 0;
76        int32_t end = 0;
77       
78        if (args[0].value_int32 == args[1].value_int32)
79                return 1;
80        else if (args[0].value_int32 > args[1].value_int32)
81        {
82                start = args[1].value_int32;
83                end = args[0].value_int32;
84        }
85        else
86        {
87                start = args[0].value_int32;
88                end = args[1].value_int32;
89        }
90       
91        ret->value_int32 = start + (dsfmt_gv_genrand_uint32() % (uint32_t)(end - start + 1));
92        ret->type = sl_int32;
93        return 0;
94}
95
96uint16_t ONICALL bsl_getkills(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
97{
98        int index;
99        if (numargs == 0) index = 0;
100        else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32);
101        else index = args[0].value_int32;
102        int* killcount = ONgGameState + index * 0x16A0 + 0x1260 + 0x1670;
103        ret->value_int32 = *killcount;
104        ret->type = sl_int32;
105        return 0;
106}
107
108uint16_t ONICALL bsl_getdamage(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
109{
110        int index;
111        if (numargs == 0) index = 0;
112        else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32);
113        else index = args[0].value_int32;
114        int* killcount = ONgGameState + index * 0x16A0 + 0x1260 + 0x1674;
115        ret->value_int32 = *killcount;
116        ret->type = sl_int32;
117        return 0;
118}
119
120uint16_t ONICALL bsl_powerup(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
121{
122        int index;
123        if (numargs < 2 || args[1].type != sl_str32) return 1;
124        else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32);
125        else index = args[0].value_int32;
126        void* returnval;
127        bool is_lsi = 0;
128        Character* Chr = ONgGameState + 0x1260;
129        if(!strcmp(args[1].value_str32,"ammo")) 
130        {
131                returnval = &(Chr[index].Inventory_.AmmoUsed);
132        }
133        else if(!strcmp(args[1].value_str32,"hypo")) 
134        {
135                returnval = &(Chr[index].Inventory_.HypoUsed);
136        }
137        else if(!strcmp(args[1].value_str32,"cells")) 
138        {
139                returnval = &(Chr[index].Inventory_.CellsUsed);
140        }
141        else if(!strcmp(args[1].value_str32,"invis")) 
142        {
143                returnval = &(Chr[index].Inventory_.CloakUsed);
144        }
145        else if(!strcmp(args[1].value_str32,"shield")) 
146        {
147                returnval = &(Chr[index].Inventory_.ShieldUsed);
148        }
149        else if(!strcmp(args[1].value_str32,"lsi")) 
150        {
151                returnval = &(Chr[index].Inventory_.hasLSI);
152                is_lsi = 1;
153        }
154//      else if(!strcmp(args[1].value_str32,"bossshield"))
155//      {
156//              ret->value_int32 = Chr[index].Flags & char_bossshield;
157//              ret->type = sl_int32;
158//              if (numargs >=3) {
159//                      if (Chr[index].Flags & char_bossshield) Chr[index].Flags = Chr[index].Flags & ~char_bossshield;
160//                      else Chr[index].Flags = Chr[index].Flags | char_bossshield;
161//              }
162//              return 0;
163//      }
164        else return 1;
165        //todo, add setting
166       
167        if(is_lsi) ret->value_int32 = (int)*(bool*)returnval;
168        else    ret->value_int32 = *(int*)returnval;
169        ret->type = sl_int32;
170
171        if (numargs >= 3) 
172        {
173                if(is_lsi) *(bool*)returnval = args[2].value_int32;
174                else *(int*)returnval = args[2].value_int32;
175        }
176       
177       
178        return 0;
179}
180
181uint16_t ONICALL bsl_health(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
182{
183        int index;
184        if (numargs == 0) index = 0;
185        else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32);
186        else index = args[0].value_int32;
187        Character* Chr = ONgGameState + 0x1260 ;
188        int* health = &Chr[index].Health;
189
190        ret->value_int32 = *health;
191        ret->type = sl_int32;
192
193        if (numargs >= 2) {
194                *health = args[1].value_int32;
195        }
196        ret->value_int32 = *health;
197        ret->type = sl_int32;
198        return 0;
199}
200
201uint16_t ONICALL bsl_maxhealth(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
202{
203        int index;
204        if (numargs == 0) index = 0;
205        else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32);
206        else index = args[0].value_int32;
207        Character* Chr = ONgGameState + 0x1260 ;
208        int* maxhealth = &Chr[index].MaxHealth;
209        int oldmaxhealth = Chr[index].MaxHealth;
210        int oldhealth = Chr->Health;
211        if (numargs >= 2) {
212                *maxhealth = args[1].value_int32;
213        }
214        if (numargs >= 3 && args[2].value_bool) {
215                Chr->Health = (int)(((float)args[1].value_int32 / (float)oldmaxhealth) * (float)oldhealth);
216        }
217        ret->value_int32 = oldmaxhealth;
218        ret->type = sl_int32;
219        return 0;
220}
221
222uint16_t ONICALL bsl_getattacker(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
223{
224        //broken...not only does it sometimes blam, but it returns a string when i want an int so i can study it :<
225        int index;
226        if (numargs == 0) index = 0;
227        else    if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32);
228        else index = args[0].value_int32;
229       
230        Character* Chr = ONgGameState + 0x1260;
231        ActiveCharacter* Active = (ActiveCharacter*)ONrGetActiveCharacter(&Chr[index]);
232        if ((int)Active == 0) return 1;
233//      ret->value_int32 = Active->LastDamageSourceCharacter;
234        ret->type = sl_int32;
235        return 0;
236}
237
238
239
240uint16_t ONICALL bsl_chrname(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
241{
242        int index;
243        if (numargs == 0) index = 0;
244        else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32);
245        else index = args[0].value_int32;
246        if (index == -1) {
247                ret->type = sl_str32;
248                ret->value_str32 = "NULL";
249                return 0;
250        }
251        char* name = ONgGameState + 0x1260  + index * 0x16A0 + 0x14;
252        if (numargs == 2) {
253                strncpy(name, (char*)args[1].value_str32, 31);
254        }
255       
256        ret->type = sl_str32;
257        ret->value_str32 = name;
258       
259        return 0;
260}
261
262
263uint16_t ONICALL bsl_count(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
264{
265        //testing numargs...
266        ret->type = sl_int32;
267        ret->value_int32 = numargs;
268        return 0;
269}
270
271uint16_t ONICALL bsl_dprintcolored(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
272{
273        //TODO: figure out why our implementation of dprint shows after dev mode is turned off
274        RGBA color;
275        RGBA shade;
276       
277        if(numargs == 0) return 0;
278        if(numargs > 1 ) color.R = (char)args[1].value_int32;
279        else color.R = 255;
280        if(numargs > 2 ) color.G = (char)args[2].value_int32;
281        else color.G = 255;
282        if(numargs > 3 ) color.B = (char)args[3].value_int32;
283        else color.B = 255;
284        color.A = 0;
285        if(numargs > 5 ) shade.R = (char)args[5].value_int32;
286        else shade.R = 0x3F;
287        if(numargs > 6 ) shade.G = (char)args[6].value_int32;
288        else shade.G = 0x3F;
289        if(numargs > 7 ) shade.B = (char)args[7].value_int32;
290        else shade.B = 0x3F;
291        shade.A = 0; 
292
293        DDrConsole_PrintColored(args[0].value_str32, 1, color, shade);
294        return 0;
295}
296
297
298uint16_t ONICALL bsl_nametoindex(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
299{
300        ret->type = sl_int32;
301        ret->value_int32 = DDrGetCharacterIndexFromName(args[0].value_str32);
302        return 0;
303}
304
305uint16_t ONICALL bsl_getactiveoffset(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
306{
307        DDrConsole_PrintF("Character: 0x%x",(int)ONgGameState + 0x1260);
308        DDrConsole_PrintF("ActiveChar: 0x%x",(int)ONrGetActiveCharacter((void*)((int)ONgGameState + 0x1260)));
309        return 0;
310}
311/*
312uint16_t ONICALL bsl_sprintf(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
313{
314        if (numargs < 2)
315                return 1;
316       
317        char output[255];
318        int i;
319        for(i = 1; i < numargs; i++)    {
320                sprintf(output, args[0].value_str32, args[i].value_str32);
321        }
322       
323        ret->value_str32 = output;
324        ret->type = sl_str32;
325        return 0;
326}
327*/
328uint16_t ONICALL bsl_sprintf(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
329{
330        DDrConsole_PrintF("%d", numargs);
331       
332        if (numargs < 1 || args[0].type != sl_str32)
333        {
334                DDrConsole_PrintF("Func \"%s\", File \"%s\", Line %d: semantic error, \"%s\": parameter list does not match: format:string arg1 arg2 ...", callinfo->name, callinfo->calllocation, callinfo->linenumber, callinfo->name);
335                return 0;
336        }
337       
338        if (!args[0].value_str32)
339                args[0].value_str32 = "";
340       
341        int ffi_ret;
342        char* str = NULL;
343        int size = 0;
344       
345        ffi_cif cif;
346        ffi_type* ffi_args[256];
347        void* values[256];
348       
349        ffi_args[0] = &ffi_type_pointer;
350        values[0] = &str;
351        ffi_args[1] = &ffi_type_uint32;
352        values[1] = &size;
353       
354        int i;
355        for(i = 2; i < numargs + 2; i ++)
356        {
357                if (args[i - 2].type == sl_float)
358                {
359                        float value_float = args[i - 2].value_float;
360                        double* value_double = (double*)&(args[i - 2]);
361                        *value_double = value_float;
362                       
363                        ffi_args[i] = &ffi_type_double;
364                        values[i] = value_double;
365                }
366                else
367                {
368                        ffi_args[i] = &ffi_type_pointer;
369                        values[i] = &(args[i - 2].value);
370                }
371        }
372       
373        if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, i, &ffi_type_sint32, ffi_args) != FFI_OK)
374                return 1;
375        ffi_call(&cif, (void*)snprintf, (void*)&ffi_ret, values);
376        str = malloc(ffi_ret + 1);
377        size = ffi_ret + 1;
378        ffi_call(&cif, (void*)snprintf, (void*)&ffi_ret, values);
379        ret->value_str32 = str;
380        ret->type = sl_str32;
381        return 0;
382}
383
384// Widescreen patch for talking heads.
385uint16_t ONICALL cinematic_start_patch(sl_callinfo* callinfo, unsigned int numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret)
386{
387        args[1].value_int32 = (double)args[1].value_int32 / (double)(gl->DisplayMode.Width) * (4.0 / 3.0 * (double)(gl->DisplayMode.Height));
388        return ((sl_func)(OniExe + 0x000f3830))(callinfo, numargs, args, dontuse1, dontuse2, ret);
389}
390
391bool ini_inbsl = false;
392bool SLrIniCallback(char* section, bool newsection, char* name, char* value)
393{
394        if (newsection && !stricmp(section, "bsl"))
395                ini_inbsl = true;
396       
397        if (ini_inbsl)
398        {
399                bool isptr = false;
400                sl_type bsl_type;
401               
402                if (value[0] == 'p' && value[1] == 't' && value[2] == 'r' && value[3] == ':')
403                {
404                        isptr = true;
405                        value += 4;
406                }
407               
408                char* type = value;
409               
410                for (; *type; type++)
411                        if (*type == ':')
412                        {
413                                *type = '\0';
414                                type++;
415                                break;
416                        }
417               
418                if (!*type)
419                        DDrStartupMessage("badly formed bsl definition for \"%s\"", name);
420               
421                if (!strcmp(type, "int"))
422                        bsl_type = sl_int32;
423                else if (!strcmp(type, "string"))
424                        bsl_type = sl_str32;
425                else if (!strcmp(type, "float"))
426                        bsl_type = sl_float;
427                else if (!strcmp(type, "bool"))
428                        bsl_type = sl_bool;
429                else
430                {
431                        DDrStartupMessage("unknown type in bsl definition for \"%s\"", name);
432                        return true;
433                }
434               
435                if (isptr)
436                {
437                        char* bsl_var = malloc(strlen(name) + 1);
438                        memcpy(bsl_var, name, strlen(name) + 1);
439                        switch (bsl_type)
440                        {
441                                case sl_int32:
442                                        SLrGlobalVariable_Register_Int32(bsl_var, "see daodan.ini", (int32_t*)(uint32_t)inifile_parseint(value, false));
443                                        break;
444                                case sl_float:
445                                        SLrGlobalVariable_Register_Float(bsl_var, "see daodan.ini", (float*)(uint32_t)inifile_parseint(value, false));
446                                        break;
447                                default:
448                                        break;
449                        }
450                }
451                else
452                {
453                        char* bsl_var = malloc(strlen(name) + 1 + sizeof(int32_t));
454                        int32_t* bsl_val = (int32_t*)bsl_var;
455                        bsl_var += sizeof(int32_t);
456                        memcpy(bsl_var, name, strlen(name) + 1);
457                       
458                        switch (bsl_type)
459                        {
460                                case sl_int32:
461                                        *bsl_val = inifile_parseint(value, false);
462                                        SLrGlobalVariable_Register_Int32(bsl_var, "see daodan.ini", bsl_val);
463                                        break;
464                                case sl_float:
465                                        break;
466                                default:
467                                        break;
468                        }
469                }
470        }
471        return true;
472}
473
474void SLrConfig()
475{
476        DDrStartupMessage("re-parsing daodan.ini for bsl...");
477        inifile_read("daodan.ini", SLrIniCallback);
478        DDrStartupMessage("finished parsing");
479}
480
481void SLrDaodan_Initalize()
482{
483        SLrConfig();
484       
485        SLrScript_Command_Register_ReturnType("int32mul", "Multiplies two numbers", "n1:int n2:int", sl_int32, bsl_int32mul);
486        SLrScript_Command_Register_ReturnType("mul", "Multiplies two numbers", "[int1:int|float1:float] [int2:int|float2:float]", sl_float, bsl_mul);
487       
488        SLrScript_Command_Register_ReturnType("int32div", "Divides two numbers", "n1:int n2:int", sl_int32, bsl_int32div);
489        SLrScript_Command_Register_ReturnType("div", "Divides two numbers", "[int1:int|float1:float] [int2:int|float2:float]", sl_float, bsl_div);
490       
491        dsfmt_gv_init_gen_rand((uint32_t)time(NULL));
492        SLrScript_Command_Register_ReturnType("int32rand", "Returns a pseudo-random number between two numbers (inclusive).", "start:int end:int", sl_int32, bsl_int32rand);
493       
494        SLrScript_Command_Register_ReturnType("d_getkills","Gets the number of kills a character has", "[ai_name:str | script_id:int]", sl_int32, bsl_getkills);
495        SLrScript_Command_Register_ReturnType("d_getdamage","Gets the amount of damage a character has caused", "[ai_name:string | script_id:int]", sl_int32, bsl_getdamage);
496        SLrScript_Command_Register_ReturnType("d_name","Gets or sets a character's name", "[ai_name:str | script_id:int] [newname:string]", sl_str32, bsl_chrname);
497        SLrScript_Command_Register_ReturnType("d_getindex","Converts a character's name to its index", "script_id:int", sl_int32, bsl_nametoindex);
498        SLrScript_Command_Register_ReturnType("d_health","Gets or sets a character's health", "[ai_name:str | script_id:int] [newhealth:int]", sl_str32, bsl_health);
499        SLrScript_Command_Register_ReturnType("d_maxhealth","Gets or sets a character's maximum health", "[ai_name:str | script_id:int] [newmaxhealth:int] [scalehealth:bool]", sl_str32, bsl_maxhealth);
500        SLrScript_Command_Register_ReturnType("d_powerup","Gets or sets a character's powerups", "ai_name:str|script_id:int powerup:str", sl_int32, bsl_powerup);
501        //broken. sometimes crashes, and sometimes returns a string... : /
502        SLrScript_Command_Register_ReturnType("d_getattacker","Gets the last person to hurt a character", "[ai_name:string | script_id:int]", sl_int32, bsl_getattacker);
503       
504        SLrScript_Command_Register_ReturnType("d_active","Gets the last person to hurt a character", "[ai_name:string | script_id:int]", sl_int32, bsl_getactiveoffset);
505
506        SLrScript_Command_Register_ReturnType("sprintf", "C-style sprintf.", "format:string arg1 arg2 ...", sl_str32, bsl_sprintf);
507        SLrScript_Command_Register_ReturnType("dprintcolor", "prints to console in color", "text:string [color: r b g] [color: r b g]", sl_void, bsl_dprintcolored);
508       
509        SLrScript_Command_Register_ReturnType("d_dprint", "prints to console in color", "text:string [color: r b g] [color: r b g]", sl_void, bsl_dprintcolored);
510}
511
512void SLrDaodan_Patch()
513{
514        DDrPatch_Int32(OniExe + 0x000f3755, (int)cinematic_start_patch);
515}
Note: See TracBrowser for help on using the repository browser.