Implement cargo ratings window

Uncover more information about stations and cargo ratings with minor refactoring.
This commit is contained in:
Ted John 2018-01-16 14:31:51 +00:00
parent 995faed42b
commit bfc82a80c6
15 changed files with 289 additions and 7 deletions

View File

@ -30,6 +30,65 @@ namespace openloco::gfx
call(0x00447485, regs);
}
void clear_single(drawpixelinfo_t &dpi, uint8_t paletteId)
{
auto fill = (paletteId << 24) | (paletteId << 16) | (paletteId << 8) | paletteId;
clear(dpi, fill);
}
// 0x00494B3F
// al: colour
// bx: string id
// cx: x
// dx: y
// esi: args
// edi: dpi
void draw_string_494B3F(
drawpixelinfo_t &dpi,
int16_t x,
int16_t y,
uint8_t colour,
string_id stringId,
const void * args)
{
registers regs;
regs.al = colour;
regs.bx = stringId;
regs.cx = x;
regs.dx = y;
regs.esi = (int32_t)args;
regs.edi = (int32_t)&dpi;
call(0x00494B3F, regs);
}
// 0x00494BBF
// al: colour
// bx: string id
// cx: x
// dx: y
// esi: args
// edi: dpi
// bp: width
void draw_string_494BBF(
drawpixelinfo_t &dpi,
int16_t x,
int16_t y,
int16_t width,
uint8_t colour,
string_id stringId,
const void * args)
{
registers regs;
regs.al = colour;
regs.bx = stringId;
regs.cx = x;
regs.dx = y;
regs.esi = (int32_t)args;
regs.edi = (int32_t)&dpi;
regs.bp = width;
call(0x00494BBF, regs);
}
// 0x004CD406
void invalidate_screen()
{

View File

@ -1,6 +1,8 @@
#pragma once
#include <cstdint>
#include "../localisation/stringmgr.h"
#include "../openloco.h"
namespace openloco::gfx
{
@ -23,6 +25,22 @@ namespace openloco::gfx
void load_g1();
void clear(drawpixelinfo_t &dpi, uint32_t fill);
void clear_single(drawpixelinfo_t &dpi, uint8_t paletteId);
void draw_string_494B3F(
drawpixelinfo_t &dpi,
int16_t x,
int16_t y,
uint8_t colour,
string_id stringId,
const void * args);
void draw_string_494BBF(
drawpixelinfo_t &dpi,
int16_t x,
int16_t y,
int16_t width,
uint8_t colour,
string_id stringId,
const void * args);
void invalidate_screen();
void set_dirty_blocks(int32_t left, int32_t top, int32_t right, int32_t bottom);
}

View File

@ -1,4 +1,5 @@
#include "../environment.h"
#include "../graphics/gfx.h"
#include "../input.h"
#include "../things/vehicle.h"
#include "../ui.h"
@ -78,6 +79,16 @@ void openloco::interop::register_hooks()
return 0;
});
register_hook(0x0048ED2F,
[](registers &regs) -> uint8_t
{
ui::windows::station_2_scroll_paint(
*((ui::window *)regs.esi),
*((gfx::drawpixelinfo_t *)regs.edi));
return 0;
});
register_hook(0x00498E9B,
[](registers &regs) -> uint8_t
{

View File

@ -0,0 +1,9 @@
#pragma once
#include "stringmgr.h"
namespace openloco::string_ids
{
constexpr string_id wcolour2_stringid2 = 457;
constexpr string_id station_cargo_rating_percent = 1423;
}

View File

@ -0,0 +1,14 @@
#include "../interop/interop.hpp"
#include "stringmgr.h"
using namespace openloco::interop;
namespace openloco::stringmgr
{
static loco_global_array<char *, 0xFFFF, 0x005183FC> _strings;
const char * get_string(string_id id)
{
return _strings[id];
}
}

View File

@ -0,0 +1,13 @@
#pragma once
#include <cstdint>
namespace openloco
{
using string_id = uint32_t;
}
namespace openloco::stringmgr
{
const char * get(string_id id);
}

View File

@ -5,8 +5,6 @@
namespace openloco
{
using string_id = uint32_t;
namespace screen_flags
{
constexpr uint8_t title = 1 << 0;

View File

@ -19,6 +19,8 @@
<ClCompile Include="envionment.cpp" />
<ClCompile Include="input.cpp" />
<ClCompile Include="interop\hooks.cpp" />
<ClCompile Include="localisation\stringmgr.cpp" />
<ClCompile Include="stationmgr.cpp" />
<ClCompile Include="things\thing.cpp" />
<ClCompile Include="things\thingmgr.cpp" />
<ClCompile Include="things\vehicle.cpp" />
@ -37,6 +39,7 @@
<ClCompile Include="openloco.cpp" />
<ClCompile Include="windows\promptbrowsewnd.cpp" />
<ClCompile Include="windows\promptokcancelwnd.cpp" />
<ClCompile Include="windows\stationwnd.cpp" />
<ClCompile Include="windows\textinputwnd.cpp" />
<ClCompile Include="windows\townwnd.cpp" />
</ItemGroup>
@ -47,8 +50,11 @@
<ClInclude Include="graphics\colours.h" />
<ClInclude Include="input.h" />
<ClInclude Include="intro.h" />
<ClInclude Include="localisation\stringmgr.h" />
<ClInclude Include="localisation\string_ids.h" />
<ClInclude Include="objects\objectmgr.h" />
<ClInclude Include="scenariomgr.h" />
<ClInclude Include="stationmgr.h" />
<ClInclude Include="things\thing.h" />
<ClInclude Include="things\thingmgr.h" />
<ClInclude Include="things\vehicle.h" />
@ -64,6 +70,7 @@
<ClInclude Include="ui.h" />
<ClInclude Include="progressbar.h" />
<ClInclude Include="interop\interop.hpp" />
<ClInclude Include="station.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{42A6B551-4EC5-4B66-A130-628622CD98C4}</ProjectGuid>

36
src/openloco/station.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <cstdint>
#include <limits>
namespace openloco
{
using station_id_t = uint16_t;
namespace station_id
{
constexpr station_id_t null = std::numeric_limits<station_id_t>::max();
}
#pragma pack(push, 1)
struct station_cargo_stats
{
int16_t status;
int8_t pad_02[2];
uint8_t rating;
int8_t pad_05[8];
bool empty() const
{
return status == -1;
}
};
struct station
{
uint8_t pad_00[0x30];
station_cargo_stats cargo[32]; // 0x30
uint8_t pad_1D0[0x3D2 - 0x1D0];
};
#pragma pack(pop)
}

View File

@ -0,0 +1,19 @@
#include "interop/interop.hpp"
#include "stationmgr.h"
using namespace openloco::interop;
namespace openloco::stationmgr
{
static loco_global_array<station, 1024, 0x005E6EDC> _stations;
station * get(station_id_t id)
{
auto index = (size_t)id;
if (index < _stations.size())
{
return &_stations[index];
}
return nullptr;
}
}

View File

@ -0,0 +1,9 @@
#pragma once
#include <cstdint>
#include "station.h"
namespace openloco::stationmgr
{
station * get(station_id_t id);
}

View File

@ -22,7 +22,8 @@ namespace openloco::ui
uint32_t enabled_widgets; // 0x0C
uint8_t pad_10[0x2C - 0x10];
widget * widgets; // 0x2C
uint8_t pad_30[0x42 - 0x30];
uint8_t pad_30[0x40 - 0x30];
uint16_t var_40;
uint32_t var_42;
uint8_t pad_46[0x83E - 0x46];
uint16_t var_83E;
@ -31,7 +32,7 @@ namespace openloco::ui
uint8_t pad_85C[0x882 - 0x85C];
uint8_t type; // 0x882
uint8_t pad_883[0x886 - 0x883];
uint8_t colours[2];
uint8_t colours[2]; // 0x886
};
};

View File

@ -1,13 +1,19 @@
#pragma once
#include "openloco.h"
#include "localisation/stringmgr.h"
#include "window.h"
namespace openloco::gfx
{
struct drawpixelinfo_t;
}
namespace openloco::ui
{
enum class window_type
{
vehicle = 23,
station = 24,
town = 33,
industry = 34,
window_39 = 39,
@ -43,6 +49,8 @@ namespace openloco::ui::windows
save = 2
};
void station_2_scroll_paint(window &w, gfx::drawpixelinfo_t &dpi);
window * open_town_window(uint16_t townId);
void sub_498E9B(window * w);

View File

@ -0,0 +1,80 @@
#include "../graphics/colours.h"
#include "../graphics/gfx.h"
#include "../interop/interop.hpp"
#include "../localisation/string_ids.h"
#include "../stationmgr.h"
#include "../windowmgr.h"
using namespace openloco::interop;
namespace openloco::ui::windows
{
static loco_global_array<uint8_t, 256, 0x001136BA4> byte_1136BA4;
static station_id_t get_station_id(const window &w)
{
return w.var_40;
}
static station& get_station(const window &w)
{
return *(stationmgr::get(get_station_id(w)));
}
static string_id get_cargo_string_id(uint32_t cargoId)
{
auto stringIdPtrs = (uint16_t * *)0x0050C700;
auto stringIdPtr = stringIdPtrs[cargoId];
auto stringId = *stringIdPtr;
return stringId;
}
// 0x0048EF02
static void draw_rating_bar(window &w, gfx::drawpixelinfo_t &dpi, int16_t x, int16_t y, uint8_t amount, colour_t colour)
{
registers regs;
regs.al = amount;
regs.cx = x;
regs.dx = y;
regs.esi = (int32_t)&w;
regs.edi = (int32_t)&dpi;
regs.ebp = colour;
call(0x0048EF02, regs);
}
// 0x0048ED2F
void station_2_scroll_paint(window &w, gfx::drawpixelinfo_t &dpi)
{
auto paletteId = byte_1136BA4[w.colours[1] * 8];
gfx::clear_single(dpi, paletteId);
const auto &station = get_station(w);
int16_t y = 0;
for (int i = 0; i < 32; i++)
{
auto &cargo = station.cargo[i];
if (!cargo.empty())
{
auto cargoStringId = get_cargo_string_id(i);
gfx::draw_string_494BBF(dpi, 1, y, 98, 0, string_ids::wcolour2_stringid2, &cargoStringId);
auto rating = cargo.rating;
auto colour = colour::moss_green;
if (rating < 100)
{
colour = colour::dark_olive_green;
if (rating < 50)
{
colour = colour::saturated_red;
}
}
uint8_t amount = (rating * 327) / 256;
draw_rating_bar(w, dpi, 100, y, amount, colour);
uint16_t percent = rating / 2;
gfx::draw_string_494B3F(dpi, 201, y, 0, string_ids::station_cargo_rating_percent, &percent);
y += 10;
}
}
}
}

View File

@ -18,14 +18,14 @@ namespace openloco::ui::windows
#endif
}
// 0x00446F6B
// 0x00499B7E
// dx: townId
// esi: {return}
window * open_town_window(uint16_t townId)
{
registers regs;
regs.dx = townId;
call(0x00446F6B, regs);
call(0x00499B7E, regs);
return (window *)regs.esi;
}
}