diff --git a/src/openloco/objects/objectmgr.cpp b/src/openloco/objects/objectmgr.cpp index da6e53b2..ce790c01 100644 --- a/src/openloco/objects/objectmgr.cpp +++ b/src/openloco/objects/objectmgr.cpp @@ -5,7 +5,42 @@ using namespace openloco::interop; namespace openloco::objectmgr { + loco_global_array object_repository; + + loco_global_array _interfaceObjects; + loco_global_array _soundObjects; + loco_global_array _currencyObjects; + loco_global_array _steamObjects; + loco_global_array _rockObjects; + loco_global_array _waterObjects; + loco_global_array _landObjects; + loco_global_array _townNamesObjects; loco_global_array _cargoObjects; + loco_global_array _wallObjects; + loco_global_array _trainSignalObjects; + loco_global_array _levelCrossingObjects; + loco_global_array _streetLightObjects; + loco_global_array _tunnelObjects; + loco_global_array _bridgeObjects; + loco_global_array _trainStationObjects; + loco_global_array _trackExtraObjects; + loco_global_array _trackObjects; + loco_global_array _roadStationObjects; + loco_global_array _roadExtraObjects; + loco_global_array _roadObjects; + loco_global_array _airportObjects; + loco_global_array _dockObjects; + loco_global_array _vehicleObjects; + loco_global_array _treeObjects; + loco_global_array _snowObjects; + loco_global_array _climateObjects; + loco_global_array _hillShapeObjects; + loco_global_array _buildingObjects; + loco_global_array _scaffoldingObjects; + loco_global_array _industryObjects; + loco_global_array _regionObjects; + loco_global_array _competitorsObjects; + loco_global_array _scenarioTextObjects; // 0x00470F3C void load_index() @@ -18,6 +53,11 @@ namespace openloco::objectmgr return _cargoObjects[id]; } + vehicle_object* get_vehicle_object(size_t id) + { + return _vehicleObjects[id]; + } + size_t get_max_objects(object_type type) { static size_t counts[] = { @@ -28,7 +68,7 @@ namespace openloco::objectmgr 8, // rock, 1, // water, 32, // surface, - 1, // town_name, + 1, // town_names, 32, // cargo, 32, // wall, 16, // train_signal, diff --git a/src/openloco/objects/objectmgr.h b/src/openloco/objects/objectmgr.h index 40b0c216..c75564a3 100644 --- a/src/openloco/objects/objectmgr.h +++ b/src/openloco/objects/objectmgr.h @@ -1,5 +1,6 @@ #pragma once +#include #include namespace openloco @@ -42,7 +43,48 @@ namespace openloco scenario_text, }; + struct object; + struct object_entry_extended; struct cargo_object; + struct interface_skin_object; + struct sound_object; + struct currency_object; + struct steam_object; + struct rock_object; + struct water_object; + struct land_object; + struct town_names_object; + struct wall_object; + struct train_signal_object; + struct level_crossing_object; + struct street_light_object; + struct tunnel_object; + struct bridge_object; + struct train_station_object; + struct track_extra_object; + struct track_object; + struct road_station_object; + struct road_extra_object; + struct road_object; + struct airport_object; + struct dock_object; + struct vehicle_object; + struct tree_object; + struct snow_object; + struct climate_object; + struct hill_shapes_object; + struct building_object; + struct scaffolding_object; + struct industry_object; + struct region_object; + struct competitors_object; + struct scenario_text_object; + + struct object_repository_item + { + object* objects; + uint32_t* object_entry_extendeds; + }; } namespace openloco::objectmgr @@ -50,4 +92,5 @@ namespace openloco::objectmgr void load_index(); cargo_object* get_cargo_object(size_t id); size_t get_max_objects(object_type type); + vehicle_object* get_vehicle_object(size_t id); } diff --git a/src/openloco/objects/vehicle_object.h b/src/openloco/objects/vehicle_object.h new file mode 100644 index 00000000..2139d494 --- /dev/null +++ b/src/openloco/objects/vehicle_object.h @@ -0,0 +1,66 @@ +#pragma once + +#include "../localisation/stringmgr.h" + +namespace openloco +{ + struct vehicle_object_unk + { + uint8_t length; // 0x00 + uint8_t pad_01[0x04 - 0x01]; + uint8_t sprite_ind; // 0x04 + uint8_t var_05; + }; + + struct vehicle_object_sprite + { + uint8_t num_dir; // 0x00 + uint8_t pad_01[0x03 - 0x01]; + uint8_t vehicle_type; // 0x03 + uint8_t num_units; // 0x04 + uint8_t pad_05; + uint8_t bogey_position; // 0x06 + uint8_t flags; // 0x07 + uint8_t pad_08[0x0E - 0x08]; + uint8_t sprite_num; // 0x0E + uint8_t pad_0F[0x1E - 0xF]; + }; + + struct vehicle_object + { + string_id name; // 0x00 probably not confirmed + uint8_t vehicle_class; // 0x02 + uint8_t type; // 0x03 + uint8_t pad_04[0x6 - 0x4]; + uint8_t num_mods; // 0x06 + uint8_t cost_ind; // 0x07 + int16_t cost_fact; // 0x08 + uint8_t reliability; // 0x0A + uint8_t run_cost_ind; // 0x0B + int16_t run_cost_fact; // 0x0C + uint8_t colour_type; // 0x0E + uint8_t num_compat; // 0x0F + uint8_t pad_10[0x24 - 0x10]; + vehicle_object_unk var_24[4]; + vehicle_object_sprite sprites[4]; // 0x3C + uint8_t pad_B4[0xD8 - 0xB4]; + uint16_t power; // 0xD8 + uint16_t speed; // 0xDA + uint16_t rack_speed; // 0xDC + uint16_t weight; // 0xDE + uint16_t flags; // 0xE0 + uint8_t pad_E1[0x10E - 0xE1]; + uint8_t vis_fx_height; // 0x10E + uint8_t vis_fx_type; // 0x10F + uint8_t pad_110[0x112 - 0x110]; + uint8_t wake_fx_type; // 0x112 + uint8_t pad_113; + uint16_t designed; // 0x114 + uint16_t obsolete; // 0x116 + uint8_t pad_118; + uint8_t startsnd_type; // 0x119 + uint8_t pad_11A[0x15A - 0x11A]; + uint8_t numsnd; // 0x15A + uint8_t pad_15B[0x15E - 0x15B]; + }; +} diff --git a/src/openloco/openloco.vcxproj b/src/openloco/openloco.vcxproj index 74863d44..1a120ea1 100644 --- a/src/openloco/openloco.vcxproj +++ b/src/openloco/openloco.vcxproj @@ -30,6 +30,7 @@ + @@ -63,6 +64,7 @@ + @@ -73,6 +75,7 @@ + @@ -106,4 +109,4 @@ - + \ No newline at end of file diff --git a/src/openloco/things/thing.cpp b/src/openloco/things/thing.cpp index 9114f7c6..baa8cecf 100644 --- a/src/openloco/things/thing.cpp +++ b/src/openloco/things/thing.cpp @@ -1,9 +1,14 @@ #include "thing.h" +#include "../graphics/gfx.h" #include "../interop/interop.hpp" +#include "../viewportmgr.h" +#include using namespace openloco; using namespace openloco::interop; +loco_global thing_zoom_max; + // 0x0046FC83 void thing::move_to(loc16 loc) { @@ -14,3 +19,57 @@ void thing::move_to(loc16 loc) regs.esi = (int32_t)this; call(0x0046FC83, regs); } + +// 0x004CBB01 +void openloco::thing::invalidate_sprite() +{ + if (sprite_left == (int16_t)0x8000u) + { + return; + } + + int16_t left = sprite_left; + int16_t top = sprite_top; + int16_t right = sprite_right; + int16_t bottom = sprite_bottom; + for (auto& viewport : openloco::ui::viewportmgr::viewports()) + { + if (viewport->zoom > thing_zoom_max) + continue; + + if (sprite_right <= viewport->view_x) + continue; + + if (sprite_bottom <= viewport->view_y) + continue; + + if (sprite_left >= viewport->view_x + viewport->view_width) + continue; + + left = std::max(sprite_left, viewport->view_x); + right = std::min(sprite_right, viewport->view_x + viewport->view_width); + + if (sprite_top >= viewport->view_y + viewport->view_height) + continue; + + bottom = std::max(sprite_bottom, viewport->view_y); + top = std::min(sprite_top, viewport->view_y + viewport->view_height); + + left -= viewport->view_x; + bottom -= viewport->view_y; + right -= viewport->view_x; + top -= viewport->view_y; + + left >>= viewport->zoom; + bottom >>= viewport->zoom; + right >>= viewport->zoom; + top >>= viewport->zoom; + + left += viewport->x; + bottom += viewport->y; + right += viewport->x; + top += viewport->y; + + openloco::gfx::set_dirty_blocks(left, top, right, bottom); + } +} diff --git a/src/openloco/things/thing.h b/src/openloco/things/thing.h index 06f3da3f..42cbed9b 100644 --- a/src/openloco/things/thing.h +++ b/src/openloco/things/thing.h @@ -34,19 +34,30 @@ namespace openloco int16_t z; // 0x12 uint8_t var_14; uint8_t var_15; - uint8_t pad_16[0x28 - 0x16]; + int16_t sprite_left; // 0x16 + int16_t sprite_top; // 0x18 + int16_t sprite_right; // 0x1A + int16_t sprite_bottom; // 0x1C + uint8_t pad_1E[0x28 - 0x1E]; uint16_t var_28; - uint8_t pad_2A[0x3A - 0x2A]; + uint8_t pad_2A[0x38 - 0x2A]; + uint8_t var_38; + uint8_t pad_39; thing_id_t next_car_id; // 0x3A - uint8_t pad_3C[0x4C - 0x3C]; + uint8_t pad_3C[0x40 - 0x3C]; + uint16_t object_type; + uint8_t var_42; + uint8_t pad_43[0x4C - 0x43]; uint8_t cargo_type; // 0x4C uint8_t pad_4D; uint16_t cargo_origin; // 0x4E uint8_t pad_50; uint8_t cargo_quantity; // 0x51 - uint8_t pad_52[0x5D - 0x52]; + uint8_t pad_52[0x54 - 0x52]; + uint8_t var_54; + uint8_t pad_55[0x5D - 0x55]; uint8_t var_5D; - uint8_t pad_5E; + uint8_t var_5E; uint8_t var_5F; // 0x5F (bit 1 = can break down) uint8_t pad_60[0x6A - 0x60]; uint8_t var_6A; @@ -56,6 +67,7 @@ namespace openloco }; void move_to(loc16 loc); + void invalidate_sprite(); }; #pragma pack(pop) } diff --git a/src/openloco/things/vehicle.cpp b/src/openloco/things/vehicle.cpp index 8b1b2c9c..570e94d5 100644 --- a/src/openloco/things/vehicle.cpp +++ b/src/openloco/things/vehicle.cpp @@ -1,13 +1,26 @@ #include "vehicle.h" #include "../audio/audio.h" #include "../config.h" +#include "../graphics/gfx.h" #include "../interop/interop.hpp" +#include "../objects/objectmgr.h" +#include "../objects/vehicle_object.h" #include "../openloco.h" #include "../utility/numeric.hpp" +#include "../viewportmgr.h" #include "thingmgr.h" +#include using namespace openloco; using namespace openloco::interop; +using namespace openloco::objectmgr; + +loco_global vehicle_1136118; +loco_global vehicle_1136124; +loco_global vehicle_1136128; +loco_global vehicle_var_1136130; +loco_global vehicle_var_1136237; // var_28 related? +loco_global vehicle_var_1136238; // var_28 related? vehicle* vehicle::next_vehicle() { @@ -53,7 +66,7 @@ bool vehicle::update() break; case 4: case 5: - result = call(0x004AA1D0, regs); + result = sub_4AA1D0(); break; case 6: result = call(0x004AA24A, regs); @@ -146,3 +159,90 @@ void vehicle::sub_4BAA76() regs.esi = (int32_t)this; call(0x004BAA76, regs); } + +// 0x004AA1D0 +int32_t openloco::vehicle::sub_4AA1D0() +{ + registers regs; + regs.esi = (int32_t)this; + + if (var_42 == 2 || var_42 == 3) + { + sub_4AAC4E(); + return 0; + } + + if (vehicle_var_1136237 | vehicle_var_1136238) + { + invalidate_sprite(); + vehicle* veh = vehicle_1136124; + regs.ebx = (int32_t)veh; + veh = vehicle_1136128; + regs.edi = (int32_t)veh; + call(0x004AC255, regs); + invalidate_sprite(); + } + uint32_t backup1136130 = vehicle_var_1136130; + if (var_5E != 0) + { + uint32_t var_1136130 = var_5E; + if (var_5E > 32) + { + var_1136130 = 64 - var_1136130; + } + + vehicle_var_1136130 += var_1136130 * 320 + 500; + } + sub_4AAC4E(); + call(0x004AAB0B, regs); + vehicle_var_1136130 = backup1136130; + return 0; +} + +void openloco::vehicle::sub_4AAC4E() +{ + if (var_38 & (1 << 4)) + return; + + vehicle* veh = vehicle_1136118; + if ((veh->var_5D == 8) || (veh->var_5D == 9)) + return; + + vehicle_object* vehicleObject = get_vehicle_object(object_type); + registers regs; + regs.esi = (int32_t)this; + regs.bl = vehicleObject->var_24[var_54].var_05; + if (vehicleObject->var_24[var_54].var_05 == 0) + { + call(0x004AB655, regs); + return; + } + + regs.ebx -= 0x80; + switch (vehicleObject->vis_fx_type) + { + case 0: + call(0x004AB655, regs); + break; + case 1: + case 2: + case 3: + call(0x004AACA5, regs); + break; + case 4: + call(0x004AAFFA, regs); + break; + case 5: + call(0x004AB3CA, regs); + break; + case 6: + call(0x004AB4E0, regs); + break; + case 7: + call(0x004AB177, regs); + break; + case 8: + call(0x004AB2A7, regs); + break; + } +} diff --git a/src/openloco/things/vehicle.h b/src/openloco/things/vehicle.h index 967c5d03..1d0e9224 100644 --- a/src/openloco/things/vehicle.h +++ b/src/openloco/things/vehicle.h @@ -22,6 +22,8 @@ namespace openloco private: bool update(); void sub_4BAA76(); + int32_t sub_4AA1D0(); + void sub_4AAC4E(); }; #pragma pack(pop) } diff --git a/src/openloco/viewportmgr.cpp b/src/openloco/viewportmgr.cpp new file mode 100644 index 00000000..14610528 --- /dev/null +++ b/src/openloco/viewportmgr.cpp @@ -0,0 +1,19 @@ +#include "viewportmgr.h" +#include "interop/interop.hpp" +#include "ui.h" +#include "window.h" +#include + +using namespace openloco::ui; +using namespace openloco::interop; + +namespace openloco::ui::viewportmgr +{ + loco_global_array _viewports; + + std::array viewports() + { + auto arr = (std::array*)_viewports.get(); + return *arr; + } +} diff --git a/src/openloco/viewportmgr.h b/src/openloco/viewportmgr.h new file mode 100644 index 00000000..c7211a2b --- /dev/null +++ b/src/openloco/viewportmgr.h @@ -0,0 +1,10 @@ +#pragma once + +#include "window.h" +#include + +namespace openloco::ui::viewportmgr +{ + constexpr size_t max_viewports = 10; + std::array viewports(); +} \ No newline at end of file diff --git a/src/openloco/window.h b/src/openloco/window.h index 1f5f23c5..a1d44709 100644 --- a/src/openloco/window.h +++ b/src/openloco/window.h @@ -42,5 +42,19 @@ namespace openloco::ui void sub_4CA17F(); }; + struct viewport + { + int16_t width; // 0x00 + int16_t height; // 0x02 + int16_t x; // 0x04 + int16_t y; // 0x06 + int16_t view_x; // 0x08 + int16_t view_y; // 0x0A + int16_t view_width; // 0x0C + int16_t view_height; // 0x0E + uint8_t zoom; // 0x10 + uint8_t pad_11; + uint16_t var_12; // 0x12, maybe flags + }; #pragma pack(pop) }