diff --git a/rwengine/include/script/ScriptTypes.hpp b/rwengine/include/script/ScriptTypes.hpp index 091e608a..59ce4976 100644 --- a/rwengine/include/script/ScriptTypes.hpp +++ b/rwengine/include/script/ScriptTypes.hpp @@ -82,6 +82,22 @@ struct SCMOpcodeParameter { return 0; } } + + float realValue() const + { + switch (type) + { + case TGlobal: + case TLocal: + return *globalReal; + case TFloat16: + return real; + default: + RW_ERROR("Unhandled type"); + return 0; + } + } + }; typedef std::vector SCMParams; diff --git a/rwengine/src/script/modules/GameModule.cpp b/rwengine/src/script/modules/GameModule.cpp index 35139694..ac997cc6 100644 --- a/rwengine/src/script/modules/GameModule.cpp +++ b/rwengine/src/script/modules/GameModule.cpp @@ -66,6 +66,20 @@ void game_print_now(const ScriptArguments& args) )); } +void game_print_soon(const ScriptArguments& args) +{ + const auto& world = args.getWorld(); + + std::string id(args[0].string); + int time = args[1].integerValue(); + unsigned short style = args[2].integerValue(); + + auto str = world->data->texts.text(id); + + auto textEntry = ScreenTextEntry::makeBig(id, str, style, time); + world->state->text.addText(textEntry); +} + void game_clear_prints(const ScriptArguments& args) { args.getWorld()->state->text.clear(); @@ -85,9 +99,18 @@ void game_set_time(const ScriptArguments& args) bool game_is_button_pressed(const ScriptArguments& args) { - /// @todo implement - RW_UNUSED(args); + int player = args[0].integerValue(); + int index = args[1].integerValue(); RW_UNIMPLEMENTED("game_is_button_pressed()"); + // NOTE: This is a hack. Hence we'll keep the unimplemented message for now. + if (player == 0) { + if (index == 19) { // look behind / sub-mission + /// @todo Return the keystate instead + auto object = args.getWorld()->pedestrianPool.find(args.getState()->playerObject); + auto player = static_cast(object); + return player->isRunning(); + } + } return false; } @@ -311,7 +334,8 @@ void game_add_location_blip(const ScriptArguments& args) { BlipData data; data.target = 0; - data.coord = glm::vec3(args[0].real, args[1].real, args[2].real); + /// @todo this might use ground coords if z is -100.0 + data.coord = glm::vec3(args[0].realValue(), args[1].realValue(), args[2].realValue()); data.texture = ""; *args[3].globalInteger = args.getWorld()->state->addRadarBlip(data); } @@ -903,6 +927,22 @@ void game_start_chase_scene(const ScriptArguments& args) args.getWorld()->chase.start(); } +void game_print_big_with_2_numbers(const ScriptArguments& args) +{ + const auto& world = args.getWorld(); + + auto id(args[0].string); + int time = args[3].integerValue(); + unsigned short style = args[4].integerValue(); + + std::string str = ScreenText::format(world->data->texts.text(id), + formatValue(args[1]), + formatValue(args[2])); + + auto textEntry = ScreenTextEntry::makeBig(id, str, style, time); + world->state->text.addText(textEntry); +} + void game_stop_chase_scene(const ScriptArguments& args) { // Clean up remaining vehicles @@ -1152,6 +1192,7 @@ GameModule::GameModule() bindFunction(0x00BA, game_print_big, 3, "Print big" ); bindFunction(0x00BC, game_print_now, 3, "Print Message Now" ); + bindFunction(0x00BD, game_print_soon, 3, "Print Message Soon" ); bindFunction(0x00BE, game_clear_prints, 0, "Clear Message Prints" ); bindFunction(0x00BF, game_get_time, 2, "Get Time of Day" ); @@ -1337,6 +1378,8 @@ GameModule::GameModule() bindFunction( 0x0354, game_start_chase_scene, 1, "Start Chase Scene" ); bindFunction( 0x0355, game_stop_chase_scene, 0, "Stop Chase Scene" ); + bindFunction(0x036D, game_print_big_with_2_numbers, 5, "Print Big With 2 Numbers"); + bindUnimplemented( 0x0373, game_camera_behind_player, 0, "Set Camera Behind Player" ); bindUnimplemented( 0x0374, game_set_motion_blur, 1, "Set Motion Blur" ); diff --git a/rwengine/src/script/modules/VMModule.cpp b/rwengine/src/script/modules/VMModule.cpp index 80b45da7..3c756f68 100644 --- a/rwengine/src/script/modules/VMModule.cpp +++ b/rwengine/src/script/modules/VMModule.cpp @@ -52,6 +52,15 @@ void vm_dec_global_float(const ScriptArguments& args) *args[0].globalReal -= args[1].real; } +void vm_mul_global_int(const ScriptArguments& args) +{ + *args[0].globalInteger *= args[1].integer; +} + +void vm_div_global_int(const ScriptArguments& args) +{ + *args[0].globalInteger /= args[1].integer; +} void vm_div_global_float(const ScriptArguments& args) { *args[0].globalReal /= args[1].real; @@ -67,6 +76,11 @@ void vm_int_gt_global_int(const ScriptArguments& args) args.getThread()->conditionResult = args[0].integer > *args[1].globalInteger; } +bool vm_global_int_gt_global_int(const ScriptArguments& args) +{ + return *args[0].globalInteger > *args[1].globalInteger; +} + void vm_global_float_gt_float(const ScriptArguments& args) { args.getThread()->conditionResult = *args[0].globalReal > args[1].real; @@ -79,12 +93,12 @@ void vm_global_int_ge_int(const ScriptArguments& args) void vm_int_ge_global_int(const ScriptArguments& args) { - args.getThread()->conditionResult = args[0].integer >= *args[1].globalInteger; + args.getThread()->conditionResult = args[0].integerValue() >= *args[1].globalInteger; } void vm_global_int_eq_int(const ScriptArguments& args) { - args.getThread()->conditionResult = *args[0].globalInteger == args[1].integer; + args.getThread()->conditionResult = *args[0].globalInteger == args[1].integerValue(); } void vm_global_float_eq_float(const ScriptArguments& args) @@ -92,6 +106,11 @@ void vm_global_float_eq_float(const ScriptArguments& args) args.getThread()->conditionResult = *args[0].globalReal == args[1].real; } +bool vm_global_int_eq_global_int(const ScriptArguments& args) +{ + return *args[0].globalInteger == *args[1].globalInteger; +} + void vm_new_thread(const ScriptArguments& args) { args.getVM()->startThread(args[0].integer); @@ -122,6 +141,15 @@ void vm_return(const ScriptArguments& args) args.getThread()->programCounter = args.getThread()->calls[--args.getThread()->stackDepth]; } +void vm_inc_global_int_by_global(const ScriptArguments& args) +{ + *args[0].globalInteger += *args[1].globalInteger; +} +void vm_inc_global_float_by_global(const ScriptArguments& args) +{ + *args[0].globalReal += *args[1].globalReal; +} + void vm_dec_global_int_by_global(const ScriptArguments& args) { *args[0].globalInteger -= *args[1].globalInteger; @@ -132,6 +160,11 @@ void vm_dec_global_float_by_global(const ScriptArguments& args) *args[0].globalReal -= *args[1].globalReal; } +void vm_mul_global_float_by_global(const ScriptArguments& args) +{ + *args[0].globalReal *= *args[1].globalReal; +} + void vm_global_int_to_global(const ScriptArguments& args) { *args[0].globalInteger = *args[1].globalInteger; @@ -142,6 +175,12 @@ void vm_global_float_to_global(const ScriptArguments& args) *args[0].globalReal = *args[1].globalReal; } +void vm_floor_float_to_int(const ScriptArguments& args) +{ + /// @todo Not sure if this might round to zero + *args[0].globalInteger = floorf(*args[1].globalReal); +} + void vm_if(const ScriptArguments& args) { auto n = args[0].integer; @@ -205,7 +244,10 @@ VMModule::VMModule() bindFunction(0x009, vm_inc_global_float, 2, "Increment Global Float"); bindFunction(0x00C, vm_dec_global_int, 2, "Decrement Global Int"); bindFunction(0x00D, vm_dec_global_float, 2, "Decrement Global Float"); - + + bindFunction(0x010, vm_mul_global_int, 2, "Multiply Global Int by Int"); + + bindFunction(0x014, vm_div_global_int, 2, "Divide Global by Integer"); bindFunction(0x015, vm_div_global_float, 2, "Divide Global by Float"); bindFunction(0x018, vm_global_int_gt_int, 2, "Global Int Greater than Int"); @@ -214,6 +256,7 @@ VMModule::VMModule() bindFunction(0x01A, vm_int_gt_global_int, 2, "Int Greater Than Global Int"); bindFunction(0x01B, vm_int_gt_global_int, 2, "Int Greater Than Var Int"); + bindFunction(0x01F, vm_global_int_gt_global_int, 2, "Local Int Greater than Global Int"); bindFunction(0x020, vm_global_float_gt_float, 2, "Global Float Greather than Float"); bindFunction(0x028, vm_global_int_ge_int, 2, "Global Int >= Int"); @@ -223,6 +266,7 @@ VMModule::VMModule() bindFunction(0x038, vm_global_int_eq_int, 2, "Global Int Equal to Int"); bindFunction(0x039, vm_global_int_eq_int, 2, "Local Int Equal to Int"); + bindFunction(0x03A, vm_global_int_eq_global_int, 2, "Global Int Equal to Global Int"); bindFunction(0x042, vm_global_float_eq_float, 2, "Global Float Equal to Float"); @@ -236,13 +280,20 @@ VMModule::VMModule() bindFunction(0x051, vm_return, 0, "Return"); + bindFunction(0x058, vm_inc_global_int_by_global, 2, "Increment Global Integer by Global Integer"); + bindFunction(0x059, vm_inc_global_float_by_global, 2, "Increment Global Float by Global Float"); + bindFunction(0x060, vm_dec_global_int_by_global, 2, "Decrement Global Integer by Global Integer"); bindFunction(0x061, vm_dec_global_float_by_global, 2, "Decrement Global Float by Global Float"); + bindFunction(0x069, vm_mul_global_float_by_global, 2, "Multiply Global Float by Global Float"); + bindFunction(0x084, vm_global_int_to_global, 2, "Set Global Int To Global"); bindFunction(0x086, vm_global_float_to_global, 2, "Set Global Float To Global"); + bindFunction(0x08C, vm_floor_float_to_int, 2, "Floor Float To Int"); + bindFunction(0x0D6, vm_if, 1, "If"); bindFunction(0x0D7, vm_new_mission_thread, 1, "Start Mission Thread");