#include #include #include #include #include "inifile.h" #include "Daodan_BSL.h" #include "Daodan_Utility.h" #include "Daodan_Patch.h" #include "Daodan_Console.h" #include "BFW_ScriptLang.h" #include "Oni.h" #include "Oni_Character.h" #include "oni_gl.h" #include "dSFMT\dSFMT.h" #include "Daodan_Character.h" uint16_t ONICALL bsl_int32mul(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { ret->value_int32 = args[0].value_int32 * args[1].value_int32; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_mul(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { double val1; double val2; if (args[0].type == sl_int32) val1 = args[0].value_int32; else val1 = args[0].value_float; if (args[1].type == sl_int32) val2 = args[1].value_int32; else val2 = args[1].value_float; ret->value_float = (float)(val1 * val2); ret->type = sl_float; return 0; } uint16_t ONICALL bsl_int32div(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { ret->value_int32 = args[0].value_int32 / args[1].value_int32; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_div(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { double val1; double val2; if (args[0].type == sl_int32) val1 = args[0].value_int32; else val1 = args[0].value_float; if (args[1].type == sl_int32) val2 = args[1].value_int32; else val2 = args[1].value_float; ret->value_float = (float)(val1 / val2); ret->type = sl_float; return 0; } uint16_t ONICALL bsl_int32rand(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int32_t start = 0; int32_t end = 0; if (args[0].value_int32 == args[1].value_int32) return 1; else if (args[0].value_int32 > args[1].value_int32) { start = args[1].value_int32; end = args[0].value_int32; } else { start = args[0].value_int32; end = args[1].value_int32; } ret->value_int32 = start + (dsfmt_gv_genrand_uint32() % (uint32_t)(end - start + 1)); ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_getkills(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int index; if (numargs == 0) index = 0; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; int* killcount = ONgGameState + index * 0x16A0 + 0x1260 + 0x1670; ret->value_int32 = *killcount; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_getdamage(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int index; if (numargs == 0) index = 0; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; int* killcount = ONgGameState + index * 0x16A0 + 0x1260 + 0x1674; ret->value_int32 = *killcount; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_returnoffset(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { //int offset = 140; //if (== 1) offset = 148; //else index = args[0].value_int32; int* killcount = ONgGameState + args[0].value_int32; ret->value_int32 = *killcount; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_powerup(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int index; if (numargs < 2 || args[1].type != sl_str32) return 1; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; void* returnval; bool is_lsi = 0; Character* Chr = ONgGameState + 0x1260; if(!strcmp(args[1].value_str32,"ammo")) { returnval = &(Chr[index].Inventory_.AmmoUsed); } else if(!strcmp(args[1].value_str32,"hypo")) { returnval = &(Chr[index].Inventory_.HypoUsed); } else if(!strcmp(args[1].value_str32,"cells")) { returnval = &(Chr[index].Inventory_.CellsUsed); } else if(!strcmp(args[1].value_str32,"invis")) { returnval = &(Chr[index].Inventory_.CloakUsed); } else if(!strcmp(args[1].value_str32,"shield")) { returnval = &(Chr[index].Inventory_.ShieldUsed); } else if(!strcmp(args[1].value_str32,"lsi")) { returnval = &(Chr[index].Inventory_.hasLSI); is_lsi = 1; } // else if(!strcmp(args[1].value_str32,"bossshield")) // { // ret->value_int32 = Chr[index].Flags & char_bossshield; // ret->type = sl_int32; // if (numargs >=3) { // if (Chr[index].Flags & char_bossshield) Chr[index].Flags = Chr[index].Flags & ~char_bossshield; // else Chr[index].Flags = Chr[index].Flags | char_bossshield; // } // return 0; // } else return 1; //todo, add setting if(is_lsi) ret->value_int32 = (int)*(bool*)returnval; else ret->value_int32 = *(int*)returnval; ret->type = sl_int32; if (numargs >= 3) { if(is_lsi) *(bool*)returnval = args[2].value_int32; else *(int*)returnval = args[2].value_int32; } return 0; } uint16_t ONICALL bsl_health(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int index; if (numargs == 0) index = 0; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; Character* Chr = ONgGameState + 0x1260 ; int* health = &Chr[index].Health; ret->value_int32 = *health; ret->type = sl_int32; if (numargs >= 2) { *health = args[1].value_int32; } ret->value_int32 = *health; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_regen(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int index; if (numargs == 0) index = 0; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; Character* Chr = ONgGameState + 0x1260 ; int* health = (int*)&Chr[index] + 0x144; ret->value_int32 = *health; ret->type = sl_int32; if (numargs >= 2) { *health = args[1].value_int32; } ret->value_int32 = *health; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_maxhealth(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int index; if (numargs == 0) index = 0; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; Character* Chr = ONgGameState + 0x1260 ; int* maxhealth = &Chr[index].MaxHealth; int oldmaxhealth = Chr[index].MaxHealth; int oldhealth = Chr->Health; if (numargs >= 2) { *maxhealth = args[1].value_int32; } if (numargs >= 3 && args[2].value_bool) { Chr->Health = (int)(((float)args[1].value_int32 / (float)oldmaxhealth) * (float)oldhealth); } ret->value_int32 = oldmaxhealth; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_getattacker(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { //broken int index; if (numargs == 0) index = 0; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; Character* Chr = ONgGameState + 0x1260; ActiveCharacter* Active = (ActiveCharacter*)ONrGetActiveCharacter(&Chr[index]); if ((int)Active == 0) return 1; // ret->value_int32 = Active->LastDamageSourceCharacter; ret->type = sl_int32; return 0; } uint16_t ONICALL bsl_chrname(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int index; if (numargs == 0) index = 0; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; if (index == -1) { ret->type = sl_str32; ret->value_str32 = "NULL"; return 0; } char* name = ONgGameState + 0x1260 + index * 0x16A0 + 0x14; if (numargs == 2) { strncpy(name, (char*)args[1].value_str32, 31); } ret->type = sl_str32; ret->value_str32 = name; return 0; } uint16_t ONICALL bsl_count(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { //testing numargs... ret->type = sl_int32; ret->value_int32 = numargs; return 0; } uint16_t ONICALL bsl_dprintcolored(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { //TODO: figure out why our implementation of dprint shows after dev mode is turned off RGBA color; RGBA shade; if(numargs == 0) return 0; if(numargs > 1 ) color.R = (char)args[1].value_int32; else color.R = 255; if(numargs > 2 ) color.G = (char)args[2].value_int32; else color.G = 255; if(numargs > 3 ) color.B = (char)args[3].value_int32; else color.B = 255; color.A = 0; if(numargs > 5 ) shade.R = (char)args[5].value_int32; else shade.R = 0x3F; if(numargs > 6 ) shade.G = (char)args[6].value_int32; else shade.G = 0x3F; if(numargs > 7 ) shade.B = (char)args[7].value_int32; else shade.B = 0x3F; shade.A = 0; DDrConsole_PrintColored(args[0].value_str32, 1, color, shade); return 0; } uint16_t ONICALL bsl_nametoindex(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { ret->type = sl_int32; ret->value_int32 = DDrGetCharacterIndexFromName(args[0].value_str32); return 0; } uint16_t ONICALL bsl_getactiveoffset(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { DDrConsole_PrintF("Character: 0x%x",(int)ONgGameState + 0x1260); DDrConsole_PrintF("ActiveChar: 0x%x",(int)ONrGetActiveCharacter((void*)((int)ONgGameState + 0x1260))); return 0; } typedef struct { char Name[16]; int Bit; } KeyBit; KeyBit Actions1[32] = { {"Escape", Action_Escape}, {"Console", Action_Console}, {"PauseScreen", Action_PauseScreen}, {"Cutscene1", Action_Cutscene_1 }, {"Cutscene2", Action_Cutscene_2 }, {"F4", Action_F4 }, {"F5", Action_F5 }, {"F6", Action_F6 }, {"F7", Action_F7 }, {"F8", Action_F8 }, {"StartRecorn", Action_StartRecord }, {"StopRecord", Action_StopRecord }, {"PlayRecord", Action_PlayRecord }, {"F12", Action_F12 }, {"Unknown1", Action_Unknown1 }, {"LookMode", Action_LookMode }, {"Screenshot", Action_Screenshot }, {"Unknown2", Action_Unknown2 }, {"Unknown3", Action_Unknown3 }, {"Unknown4", Action_Unknown4 }, {"Unknown5", Action_Unknown5 }, {"Forward", Action_Forward }, {"Backward", Action_Backward }, {"TurnLeft", Action_TurnLeft }, {"TurnRight", Action_TurnRight }, {"StepLeft", Action_StepLeft }, {"StepRight", Action_StepRight }, {"Jump", Action_Jump }, {"Crouch", Action_Crouch }, {"Punch",Action_Punch }, {"Kick", Action_Kick }, {"Block", Action_Block } }; KeyBit Actions2[9] = { {"Walk", Action2_Walk}, {"Action", Action2_Action}, {"Hypo", Action2_Hypo}, {"Reload", Action2_Reload }, {"Swap", Action2_Swap }, {"Drop", Action2_Drop }, {"Fire1", Action2_Fire1 }, {"Fire2", Action2_Fire2 }, {"Fire3", Action2_Fire3 } }; uint16_t ONICALL bsl_holdkey(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { int index; if (numargs < 4) index = 0; else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); else index = args[0].value_int32; Character* Chr = ONgGameState + 0x1260; ActiveCharacter* Active = (ActiveCharacter*)ONrGetActiveCharacter(&Chr[index]); if ((int)Active == 0) return 1; int i = 2; int j = 0; int Input1 = 0; int Input2 = 0; for(i = 1; i < numargs; i++) { for(j = 0; j < 32; j++) { if(strcmp(args[i].value_str32, Actions1[j].Name)) Input1 = Input1 | Actions1[j].Bit; DDrConsole_PrintF("Testing %s against %s 0x%x", args[i].value_str32, Actions1[j].Name, Actions1[j].Bit); } for(j = 0; j < 9; j++) { if(!strcmp(args[i].value_str32, Actions2[j].Name)) Input2 = Input2 | Actions2[j].Bit; } } for(i = 0; i < numargs; i++) { DDrConsole_PrintF("%s", args[i].value_str32); } // if return 0; } uint16_t ONICALL bsl_isheld(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { // int index; // if (numargs < 4) index = 0; // else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); // else index = args[0].value_int32; // Character* Chr = ONgGameState + 0x1260; // ActiveCharacter* Active = (ActiveCharacter*)ONrGetActiveCharacter(&Chr[index]); // if ((int)Active == 0) return 1; int i = 2; int j = 0; int Input1 = 0; int Input2 = 0; for(i = 0; i < numargs; i++) { for(j = 0; j < 32; j++) { //DDrConsole_PrintF("Testing %s against %s 0x%x", args[i].value_str32, Actions1[j].Name, Actions1[j].Bit); if(!strcmp(args[i].value_str32, Actions1[j].Name)) { Input1 = Input1 | Actions1[j].Bit; //DDrConsole_PrintF("Success!"); } } for(j = 0; j < 9; j++) { if(!strcmp(args[i].value_str32, Actions2[j].Name)) Input2 = Input2 | Actions2[j].Bit; } } //DDrConsole_PrintF("Testing: 0x%x Input: 0x%x",Input1, *(int*)(ONgGameState + 0xB8 + 0x10)); ret->value_int32 = 0; ret->type = sl_int32; if ( ((*(int*)(ONgGameState + 0xB8 + 0x10) & Input1) == Input1) && ((*(int*)(ONgGameState + 0xB8 + 0x14) & Input2) == Input2)) ret->value_int32 = 1; return 0; } uint16_t ONICALL bsl_waitforkey(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], int* dontuse1, int* dontuse2, sl_arg* ret) { // int index; // if (numargs < 4) index = 0; // else if (args[0].type == sl_str32) index = DDrGetCharacterIndexFromName(args[0].value_str32); // else index = args[0].value_int32; // Character* Chr = ONgGameState + 0x1260; // ActiveCharacter* Active = (ActiveCharacter*)ONrGetActiveCharacter(&Chr[index]); // if ((int)Active == 0) return 1; int i = 2; int j = 0; int Input1 = 0; int Input2 = 0; for(i = 0; i < numargs; i++) { for(j = 0; j < 32; j++) { //DDrConsole_PrintF("Testing %s against %s 0x%x", args[i].value_str32, Actions1[j].Name, Actions1[j].Bit); if(!strcmp(args[i].value_str32, Actions1[j].Name)) { Input1 = Input1 | Actions1[j].Bit; //DDrConsole_PrintF("Success!"); } } for(j = 0; j < 9; j++) { if(!strcmp(args[i].value_str32, Actions2[j].Name)) Input2 = Input2 | Actions2[j].Bit; } } //DDrConsole_PrintF("Waiting..."); if ( ((*(int*)(ONgGameState + 0xB8 + 0x10) & Input1) == Input1) && ((*(int*)(ONgGameState + 0xB8 + 0x14) & Input2) == Input2)) { } else { //else (int)*ret = 1; *dontuse2 = 1; *dontuse1 = 1; } /* __asm__( "movl 0x10(%esp), %edx\n\t" "movl $1,(%eax)\n\t" ); //ret->type = sl_void */ return 0; } /* uint16_t ONICALL bsl_sprintf(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { if (numargs < 2) return 1; char output[255]; int i; for(i = 1; i < numargs; i++) { sprintf(output, args[0].value_str32, args[i].value_str32); } ret->value_str32 = output; ret->type = sl_str32; return 0; } */ uint16_t ONICALL bsl_sprintf(sl_callinfo* callinfo, uint32_t numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { if (numargs < 1 || args[0].type != sl_str32) { 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); return 0; } if (!args[0].value_str32) args[0].value_str32 = ""; int ffi_ret; char* str = NULL; int size = 0; ffi_cif cif; ffi_type* ffi_args[256]; void* values[256]; ffi_args[0] = &ffi_type_pointer; values[0] = &str; ffi_args[1] = &ffi_type_uint32; values[1] = &size; int i; for(i = 2; i < numargs + 2; i ++) { if (args[i - 2].type == sl_float) { float value_float = args[i - 2].value_float; double* value_double = (double*)&(args[i - 2]); *value_double = value_float; ffi_args[i] = &ffi_type_double; values[i] = value_double; } else { ffi_args[i] = &ffi_type_pointer; values[i] = &(args[i - 2].value); } } if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, i, &ffi_type_sint32, ffi_args) != FFI_OK) return 1; ffi_call(&cif, (void*)snprintf, (void*)&ffi_ret, values); str = malloc(ffi_ret + 1); size = ffi_ret + 1; ffi_call(&cif, (void*)snprintf, (void*)&ffi_ret, values); ret->value_str32 = str; ret->type = sl_str32; return 0; } // Widescreen patch for talking heads. uint16_t ONICALL cinematic_start_patch(sl_callinfo* callinfo, unsigned int numargs, sl_arg args[], void* dontuse1, void* dontuse2, sl_arg* ret) { args[1].value_int32 = (double)args[1].value_int32 / (double)(gl->DisplayMode.Width) * (4.0 / 3.0 * (double)(gl->DisplayMode.Height)); return ((sl_func)(OniExe + 0x000f3830))(callinfo, numargs, args, dontuse1, dontuse2, ret); } bool ini_inbsl = false; bool SLrIniCallback(char* section, bool newsection, char* name, char* value) { if (newsection && !stricmp(section, "bsl")) ini_inbsl = true; if (ini_inbsl) { bool isptr = false; sl_type bsl_type; if (value[0] == 'p' && value[1] == 't' && value[2] == 'r' && value[3] == ':') { isptr = true; value += 4; } char* type = value; for (; *type; type++) if (*type == ':') { *type = '\0'; type++; break; } if (!*type) DDrStartupMessage("badly formed bsl definition for \"%s\"", name); if (!strcmp(type, "int")) bsl_type = sl_int32; else if (!strcmp(type, "string")) bsl_type = sl_str32; else if (!strcmp(type, "float")) bsl_type = sl_float; else if (!strcmp(type, "bool")) bsl_type = sl_bool; else { DDrStartupMessage("unknown type in bsl definition for \"%s\"", name); return true; } if (isptr) { char* bsl_var = malloc(strlen(name) + 1); memcpy(bsl_var, name, strlen(name) + 1); switch (bsl_type) { case sl_int32: SLrGlobalVariable_Register_Int32(bsl_var, "see daodan.ini", (int32_t*)(uint32_t)inifile_parseint(value, false)); break; case sl_float: SLrGlobalVariable_Register_Float(bsl_var, "see daodan.ini", (float*)(uint32_t)inifile_parseint(value, false)); break; default: break; } } else { char* bsl_var = malloc(strlen(name) + 1 + sizeof(int32_t)); int32_t* bsl_val = (int32_t*)bsl_var; bsl_var += sizeof(int32_t); memcpy(bsl_var, name, strlen(name) + 1); switch (bsl_type) { case sl_int32: *bsl_val = inifile_parseint(value, false); SLrGlobalVariable_Register_Int32(bsl_var, "see daodan.ini", bsl_val); break; case sl_float: break; default: break; } } } return true; } void SLrConfig() { DDrStartupMessage("re-parsing daodan.ini for bsl..."); inifile_read("daodan.ini", SLrIniCallback); DDrStartupMessage("finished parsing"); } void SLrDaodan_Initalize() { //const char regen_patch[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}; //DDrPatch_Const(OniExe + 0x0011BB6D, regen_patch); //This one should work but doesn't. //const char regen_patch[] ={0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8B, 0x86, 0x44}; //DDrPatch_Const(OniExe + 0x0011BB64, regen_patch); SLrConfig(); SLrScript_Command_Register_ReturnType("int32mul", "Multiplies two numbers", "n1:int n2:int", sl_int32, bsl_int32mul); SLrScript_Command_Register_ReturnType("mul", "Multiplies two numbers", "[int1:int|float1:float] [int2:int|float2:float]", sl_float, bsl_mul); SLrScript_Command_Register_ReturnType("int32div", "Divides two numbers", "n1:int n2:int", sl_int32, bsl_int32div); SLrScript_Command_Register_ReturnType("div", "Divides two numbers", "[int1:int|float1:float] [int2:int|float2:float]", sl_float, bsl_div); dsfmt_gv_init_gen_rand((uint32_t)time(NULL)); SLrScript_Command_Register_ReturnType("int32rand", "Returns a pseudo-random number between two numbers (inclusive).", "start:int end:int", sl_int32, bsl_int32rand); SLrScript_Command_Register_ReturnType("d_getkills","Gets the number of kills a character has", "[ai_name:str | script_id:int]", sl_int32, bsl_getkills); 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); 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); SLrScript_Command_Register_ReturnType("d_getindex","Converts a character's name to its index", "script_id:int", sl_int32, bsl_nametoindex); 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); SLrScript_Command_Register_ReturnType("d_regen","Gets or sets a character's health", "[ai_name:str | script_id:int] [newhealth:int]", sl_str32, bsl_regen); 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); 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); SLrScript_Command_Register_ReturnType("d_holdkey","Makes an AI hold a key", "[ai_name:string | script_id:int] keys", sl_int32, bsl_holdkey); SLrScript_Command_Register_ReturnType("d_isheld","Checks for a held key", "keys", sl_int32, bsl_isheld); SLrScript_Command_Register_Void("d_waitforkey","Waits for a keypress.", "keys", bsl_waitforkey); //broken. sometimes crashes, and sometimes returns a string... : / SLrScript_Command_Register_ReturnType("d_getattacker","Gets the last person to hurt a character", "[ai_name:string | script_id:int]", sl_int32, bsl_getattacker); SLrScript_Command_Register_ReturnType("d_active","Gets the last person to hurt a character", "[ai_name:string | script_id:int]", sl_int32, bsl_getactiveoffset); SLrScript_Command_Register_ReturnType("sprintf", "C-style sprintf.", "format:string arg1 arg2 ...", sl_str32, bsl_sprintf); 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); //SLrScript_Command_Register_ReturnType("d_offset", "a test", "thing:int", sl_int32, bsl_returnoffset); } void SLrDaodan_Patch() { DDrPatch_Int32(OniExe + 0x000f3755, (int)cinematic_start_patch); }