diff --git a/rwengine/src/script/modules/GameModule.cpp b/rwengine/src/script/modules/GameModule.cpp index 469035cf..73432404 100644 --- a/rwengine/src/script/modules/GameModule.cpp +++ b/rwengine/src/script/modules/GameModule.cpp @@ -614,6 +614,41 @@ void game_add_sprite_blip(const ScriptArguments& args) *args[4].globalInteger = args.getWorld()->state->addRadarBlip(bd); } +template +void game_add_object_sprite_blip(const ScriptArguments& args) +{ + BlipData data; + auto target = args.getObject(0); + data.target = target->getGameObjectID(); + unsigned int sprite = args[1].integerValue(); + + // Look up the sprite ID. + std::string spriteName = ""; + if ( sprite < sizeof( sprite_names ) ) + { + spriteName = sprite_names[sprite]; + } + + switch(target->type()) { + case GameObject::Vehicle: + data.type = BlipData::Vehicle; + break; + case GameObject::Character: + data.type = BlipData::Character; + break; + case GameObject::Pickup: + data.type = BlipData::Pickup; + break; + default: + data.type = BlipData::Location; + RW_ERROR("Unhandled blip type"); + break; + } + + data.texture = spriteName; + *args[2].globalInteger = args.getWorld()->state->addRadarBlip(data); +} + void game_load_cutscene(const ScriptArguments& args) { args.getWorld()->loadCutscene(args[0].string); @@ -1352,6 +1387,7 @@ GameModule::GameModule() bindUnimplemented( 0x03DA, game_set_garage_follow_player, 1, "Set Garage Camera Follows Player" ); bindFunction(0x03DC, game_add_object_blip, 2, "Add blip for pickup"); + bindUnimplemented(0x03DD, game_add_object_sprite_blip, 3, "Add Sprite Blip for Pickup"); /// @todo crashes LUIGI4 because of missing 032B bindUnimplemented( 0x03DE, game_set_pedestrian_density, 1, "Set Pedestrian density" ); diff --git a/rwengine/src/script/modules/ObjectModule.cpp b/rwengine/src/script/modules/ObjectModule.cpp index dfd60461..ef6ec8e0 100644 --- a/rwengine/src/script/modules/ObjectModule.cpp +++ b/rwengine/src/script/modules/ObjectModule.cpp @@ -578,7 +578,7 @@ void game_give_weapon_to_character(const ScriptArguments& args) int bulletsTotal = args[2].integerValue(); RW_CHECK(weaponId >= 0, "Weapon-ID too low"); - RW_CHECK(weaponId < cs.weapons.size(), "Weapon-ID too high"); + RW_CHECK(weaponId < static_cast(cs.weapons.size()), "Weapon-ID too high"); // Give character the weapon auto& weapon = cs.weapons[weaponId]; @@ -708,6 +708,27 @@ bool game_character_stoped_in_volume(const ScriptArguments& args) return false; } +bool game_locate_vehicle_near_point_2D(const ScriptArguments& args) +{ + auto vehicle = static_cast(args.getObject(0)); + glm::vec2 position(args[1].real, args[2].real); + glm::vec2 radius(args[3].real, args[4].real); + bool drawCylinder = !!args[5].integerValue(); + + auto vp = vehicle->getPosition(); + glm::vec2 distance = glm::abs(position - glm::vec2(vp)); + + if(distance.x <= radius.x && distance.y <= radius.y) { + return true; + } + + if(drawCylinder) { + auto ground = args.getWorld()->getGroundAtPosition(glm::vec3(position, 100.f)); + args.getWorld()->drawAreaIndicator(AreaIndicatorInfo::Cylinder, ground + glm::vec3(0.f, 0.f, 4.5f), glm::vec3(radius, 5.f)); + } + + return false; +} template bool game_is_character_stopped(const ScriptArguments& args) @@ -775,6 +796,14 @@ bool game_objects_in_volume(const ScriptArguments& args) return false; } +bool game_is_vehicle_in_water(const ScriptArguments& args) +{ + RW_UNIMPLEMENTED("game_is_vehicle_in_water"); + RW_UNUSED(args); + /// @todo + return false; +} + bool game_player_in_taxi(const ScriptArguments& args) { auto character = static_cast(args.getPlayerCharacter(0)); @@ -792,6 +821,39 @@ void game_get_speed(const ScriptArguments& args) } } +void game_create_character_as_passenger(const ScriptArguments& args) +{ + auto vehicle = static_cast(args.getObject(0)); + auto type = args[1].integerValue(); + RW_UNUSED(type); + RW_UNIMPLEMENTED("game_create_character_as_passenger(): character type"); + auto id = args[2].integerValue(); + auto seat = args[3].integerValue(); + + auto character = args.getWorld()->createPedestrian(id, vehicle->getPosition() + spawnMagic); + new DefaultAIController(character); + + if (seat <= -1) { + for (seat = 0; seat < static_cast(vehicle->info->seats.size()); seat++) { + if (vehicle->getOccupant(seat) == nullptr && !vehicle->isOccupantDriver(seat)) { + break; + } + } + } else { + /// @todo 0 - passenger seat (or back seat of bike); 1 - left rear seat; 2 - right rear seat + seat++; + } + + RW_CHECK(seat < static_cast(vehicle->info->seats.size()), "Seat index too high"); + RW_CHECK(vehicle->getOccupant(seat) == nullptr, "Seat is not free"); + RW_CHECK(vehicle->isOccupantDriver(seat) == false, "Seat is not a passenger seat"); + + character->setCurrentVehicle(vehicle, seat); + vehicle->setOccupant(seat, character); + + *args[4].globalInteger = character->getGameObjectID(); +} + void game_enter_as_driver(const ScriptArguments& args) { auto character = static_cast(args.getObject(0)); @@ -990,6 +1052,16 @@ bool game_character_near_car_2d(const ScriptArguments& args) return false; } +void game_get_vehicle_health(const ScriptArguments& args) +{ + RW_UNIMPLEMENTED("game_get_vehicle_health"); + auto vehicle = static_cast(args.getObject(0)); + if (vehicle) { + /// @todo + *args[1].globalReal = 1000.f; + } +} + void game_set_vehicle_colours(const ScriptArguments& args) { auto vehicle = static_cast(args.getObject(0)); @@ -1222,6 +1294,8 @@ ObjectModule::ObjectModule() bindFunction(0x00A6, game_destroy_object, 1, "Destroy Vehicle" ); bindFunction(0x00AA, game_get_vehicle_position, 4, "Get Vehicle Position" ); + + bindUnimplemented( 0x00AF, game_set_vehicle_objective, 2, "Set Vehicle Objective" ); bindFunction(0x00D9, game_get_character_vehicle, 2, "Get Character Vehicle" ); bindFunction(0x00DA, game_get_character_vehicle, 2, "Get Player Vehicle" ); @@ -1293,6 +1367,8 @@ ObjectModule::ObjectModule() bindFunction(0x01A8, game_character_stoped_in_volume, 8, "Is Char Stopped in volume" ); bindFunction(0x01AA, game_character_stoped_in_volume_in_vehicle, 8, "Is Char Stopped in cube in vehicle" ); + bindFunction(0x01AD, game_locate_vehicle_near_point_2D, 6, "Locate Vehicle Near Point 2D" ); + bindFunction(0x01B2, game_give_weapon_to_character, 3, "Give Weapon to Character" ); bindUnimplemented( 0x01BB, game_object_coordinates, 4, "Get Object Coordinates" ); @@ -1304,6 +1380,9 @@ ObjectModule::ObjectModule() bindUnimplemented( 0x01C3, game_mark_object_as_unneeded, 1, "Mark Vehicle Unneeded" ); bindFunction(0x01C7, game_dont_remove_object, 1, "Don't remove object" ); + bindFunction(0x01C8, game_create_character_as_passenger, 5, "Create Character as Passenger" ); + + bindUnimplemented( 0x01CC, game_set_character_objective_kill_player_any_means, 2, "Set Character Objective to Kill Player by Any Means" ); bindFunction(0x01D5, game_enter_as_driver, 2, "Character Enter Vehicle as Driver" ); bindFunction(0x01D4, game_enter_as_passenger, 2, "Character Enter Vehicle as Passenger" ); @@ -1323,17 +1402,24 @@ ObjectModule::ObjectModule() bindFunction(0x0213, game_create_pickup, 6, "Create pickup"); bindFunction(0x0214, game_is_pickup_collected, 1, "Has Pickup been collected"); bindFunction(0x0215, game_destroy_pickup, 1, "Destroy Pickup"); - + + bindFunction(0x0227, game_get_vehicle_health, 2, "Get Vehicle Health" ); bindFunction(0x0229, game_set_vehicle_colours, 3, "Set Vehicle Colours" ); bindFunction(0x0239, game_character_run_to, 3, "Character Run to" ); + + bindUnimplemented( 0x0243, game_set_character_personality, 2, "Set Character Personality" ); bindFunction(0x029B, game_create_object_world, 5, "Create Object no offset" ); bindFunction(0x029C, game_is_boat, 1, "Is Vehicle Boat" ); bindFunction(0x029F, game_is_character_stopped, 1, "Is Player Stopped" ); + + bindUnimplemented( 0x02AA, game_set_car_only_damageable_by_player, 2, "Set Car Only Damageable by Player" ); bindFunction(0x02B3, game_character_in_area_9, 9, "Is Player In Area" ); + + bindFunction(0x02BF, game_is_vehicle_in_water, 1, "Is Vehicle in Water" ); bindFunction(0x02DE, game_player_in_taxi, 1, "Is Player In Taxi" ); @@ -1353,6 +1439,8 @@ ObjectModule::ObjectModule() bindUnimplemented( 0x0368, game_create_ev_crane, 10, "Create ev Crane" ); + bindUnimplemented( 0x039C, game_set_car_watertight, 2, "Set Car Watertight" ); + bindFunction(0x03B6, game_change_nearest_model, 6, "Change Nearest Instance Model" ); bindUnimplemented( 0x03BA, game_clear_area_vehicles, 6, "Clear Cars From Area" );