* Fix: #366. Implement deliver cargo to nearby stations Original game had a bug where it would write to bad memory and end up delivering cargo to stations that it shouldn't * Add note and break * Update changelog * Adjust variable name
This commit is contained in:
parent
44f5210c2f
commit
cba3bd06d1
|
@ -1,5 +1,6 @@
|
|||
21.07+ (???)
|
||||
------------------------------------------------------------------------
|
||||
- Fix: [#366] People and mail cargo incorrectly delivered to far away stations.
|
||||
- Fix: [#1035] Incorrect colour selection when building buildings.
|
||||
- Fix: [#1070] Crash when naming stations after exhausting natural names.
|
||||
- Fix: [#1094] Repeated clicking on construction window not always working.
|
||||
|
|
|
@ -203,7 +203,7 @@ namespace OpenLoco::Map
|
|||
town->var_19C[i][0] += producedAmount;
|
||||
|
||||
const auto size = (buildingObj->flags & BuildingObjectFlags::large_tile) ? Map::TilePos2(2, 2) : Map::TilePos2(1, 1);
|
||||
town->var_19C[i][1] += StationManager::sendProducedCargoToStations(buildingObj->producedCargoType[i], producedAmount, loc, size) & 0xFF;
|
||||
town->var_19C[i][1] += StationManager::deliverCargoToNearbyStations(buildingObj->producedCargoType[i], producedAmount, loc, size) & 0xFF;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -528,6 +528,16 @@ namespace OpenLoco
|
|||
twn->monthly_cargo_delivered[cargoType] = Math::Bound::add(twn->monthly_cargo_delivered[cargoType], cargoQuantity);
|
||||
}
|
||||
|
||||
// 0x0042F489
|
||||
void Station::deliverCargoToStation(const uint8_t cargoType, const uint8_t cargoQuantity)
|
||||
{
|
||||
auto& cargoStats = cargo_stats[cargoType];
|
||||
cargoStats.quantity = Math::Bound::add(cargoStats.quantity, cargoQuantity);
|
||||
cargoStats.enroute_age = 0;
|
||||
cargoStats.origin = id();
|
||||
updateCargoDistribution();
|
||||
}
|
||||
|
||||
// 0x0048F7D1
|
||||
void Station::sub_48F7D1()
|
||||
{
|
||||
|
|
|
@ -111,6 +111,7 @@ namespace OpenLoco
|
|||
void invalidate();
|
||||
void invalidateWindow();
|
||||
void setCatchmentDisplay(uint8_t flags);
|
||||
void deliverCargoToStation(const uint8_t cargoType, const uint8_t cargoQuantity);
|
||||
void deliverCargoToTown(uint8_t cargoType, uint16_t cargoQuantity);
|
||||
void updateCargoDistribution();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Window.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <numeric>
|
||||
|
||||
using namespace OpenLoco::Interop;
|
||||
using namespace OpenLoco::Ui;
|
||||
|
@ -412,17 +413,95 @@ namespace OpenLoco::StationManager
|
|||
}
|
||||
|
||||
// 0x0042F2FE
|
||||
uint16_t sendProducedCargoToStations(const uint8_t cargoType, const uint8_t cargoQty, const Map::Pos2& pos, const Map::TilePos2& size)
|
||||
uint16_t deliverCargoToNearbyStations(const uint8_t cargoType, const uint8_t cargoQty, const Map::Pos2& pos, const Map::TilePos2& size)
|
||||
{
|
||||
registers regs;
|
||||
regs.ax = pos.x;
|
||||
regs.cx = pos.y;
|
||||
regs.dx = size.x | (size.y << 8);
|
||||
regs.bh = cargoType;
|
||||
regs.bl = cargoQty;
|
||||
call(0x0042F2FE, regs);
|
||||
return regs.bx;
|
||||
const auto initialLoc = TilePos2(pos) - TilePos2(4, 4);
|
||||
const auto catchmentSize = size + TilePos2(8, 8);
|
||||
// TODO: Use a fixed size array (max size 15)
|
||||
std::vector<std::pair<StationId_t, uint8_t>> foundStations;
|
||||
for (TilePos2 searchOffset{ 0, 0 }; searchOffset.y < catchmentSize.y; ++searchOffset.y)
|
||||
{
|
||||
for (; searchOffset.x < catchmentSize.x; ++searchOffset.x)
|
||||
{
|
||||
const auto searchLoc = initialLoc + searchOffset;
|
||||
if (!Map::validCoords(searchLoc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto tile = TileManager::get(searchLoc);
|
||||
for (const auto& el : tile)
|
||||
{
|
||||
auto* elStation = el.asStation();
|
||||
if (elStation == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (elStation->isFlag5() || elStation->isGhost())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (foundStations.size() > 15)
|
||||
{
|
||||
break;
|
||||
}
|
||||
auto res = std::find_if(foundStations.begin(), foundStations.end(), [stationId = elStation->stationId()](const std::pair<StationId_t, uint8_t>& item) { return item.first == stationId; });
|
||||
if (res != foundStations.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto* station = get(elStation->stationId());
|
||||
if (station == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(station->cargo_stats[cargoType].flags & (1 << 1)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foundStations.push_back(std::make_pair(elStation->stationId(), station->cargo_stats[cargoType].rating));
|
||||
}
|
||||
}
|
||||
searchOffset.x = 0;
|
||||
}
|
||||
|
||||
if (foundStations.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto ratingTotal = std::accumulate(foundStations.begin(), foundStations.end(), 0, [](const int32_t a, const std::pair<StationId_t, uint8_t>& b) { return a + b.second * b.second; });
|
||||
if (ratingTotal == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t cargoQtyDelivered = 0;
|
||||
for (const auto& [stationId, rating] : foundStations)
|
||||
{
|
||||
auto* station = get(stationId);
|
||||
if (station == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto defaultShare = (rating * rating * cargoQty) / ratingTotal;
|
||||
const auto alternateShare = (rating * cargoQty) / 256;
|
||||
auto share = std::min(defaultShare, alternateShare);
|
||||
if (rating > 66)
|
||||
{
|
||||
share++;
|
||||
}
|
||||
cargoQtyDelivered += share;
|
||||
station->deliverCargoToStation(cargoType, share);
|
||||
}
|
||||
|
||||
return std::min<uint16_t>(cargoQtyDelivered, cargoQty);
|
||||
}
|
||||
|
||||
void registerHooks()
|
||||
{
|
||||
// Can be removed once the createStation function has been implemented (used by place.*Station game commands)
|
||||
|
|
|
@ -18,5 +18,5 @@ namespace OpenLoco::StationManager
|
|||
string_id generateNewStationName(StationId_t stationId, TownId_t townId, Map::Pos3 position, uint8_t mode);
|
||||
void zeroUnused();
|
||||
void registerHooks();
|
||||
uint16_t sendProducedCargoToStations(const uint8_t cargoType, const uint8_t cargoQty, const Map::Pos2& pos, const Map::TilePos2& size);
|
||||
uint16_t deliverCargoToNearbyStations(const uint8_t cargoType, const uint8_t cargoQty, const Map::Pos2& pos, const Map::TilePos2& size);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue