Skip to content

Commit

Permalink
Merge pull request #1 from Flamefire/wineaddon
Browse files Browse the repository at this point in the history
Merge for wine addon
  • Loading branch information
ottml authored Aug 4, 2024
2 parents b30e4ec + 532f147 commit bbc6968
Show file tree
Hide file tree
Showing 22 changed files with 157 additions and 175 deletions.
16 changes: 16 additions & 0 deletions libs/s25main/Replay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Replay.h"
#include "Savegame.h"
#include "enum_cast.hpp"
#include "helpers/format.hpp"
#include "network/PlayerGameCommands.h"
#include "gameTypes/MapInfo.h"
#include <s25util/tmpFile.h>
Expand Down Expand Up @@ -194,10 +195,25 @@ bool Replay::LoadHeader(const boost::filesystem::path& filepath)
// TODO(Replay): Move before mapType to have it as early as possible.
// Previously mapType was an unsigned short, i.e. in little endian the 2nd byte was always unused/zero
subVersion_ = file_.ReadUnsignedChar();
if(subVersion_ > currentReplayDataVersion)
{
lastErrorMsg =
helpers::format(_("Cannot play replay created with a more recent version (Current: %1%, Replay: %2%)"),
currentReplayDataVersion, subVersion_);
return false;
}

if(subVersion_ >= 1)
gcVersion_ = file_.ReadUnsignedChar();
else
gcVersion_ = 0;
if(gcVersion_ > gc::Deserializer::getCurrentVersion())
{
lastErrorMsg =
helpers::format(_("Cannot play replay created with a more recent GC version (Current: %1%, Replay: %2%)"),
gc::Deserializer::getCurrentVersion(), gcVersion_);
return false;
}

if(mapType_ == MapType::Savegame)
{
Expand Down
80 changes: 33 additions & 47 deletions libs/s25main/buildings/BurnedWarehouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,22 @@
#include "EventManager.h"
#include "GamePlayer.h"
#include "SerializedGameData.h"
#include "WineLoader.h"
#include "figures/nofPassiveWorker.h"
#include "helpers/Range.h"
#include "pathfinding/PathConditionHuman.h"
#include "random/Random.h"
#include "world/GameWorld.h"
#include <boost/container/static_vector.hpp>

/// Anzahl der Rausgeh-Etappen
const unsigned GO_OUT_PHASES = 10;
/// Länge zwischen zwei solchen Phasen
const unsigned PHASE_LENGTH = 2;
/// Number of "waves" of workers leaving
constexpr unsigned GO_OUT_PHASES = 10;
/// Time between those phases
constexpr unsigned PHASE_LENGTH = 2;

BurnedWarehouse::BurnedWarehouse(const MapPoint pos, const unsigned char player, const PeopleArray& people)
: noCoordBase(NodalObjectType::BurnedWarehouse, pos), player(player), go_out_phase(0), people(people)
{
// Erstes Event anmelden
// First event
GetEvMgr().AddEvent(this, PHASE_LENGTH, 0);
}

Expand Down Expand Up @@ -51,23 +52,19 @@ void BurnedWarehouse::HandleEvent(const unsigned /*id*/)
{
RTTR_Assert(go_out_phase != GO_OUT_PHASES);

std::array<Direction, helpers::NumEnumValues_v<Direction>> possibleDirs;
unsigned possibleDirCt = 0;

// Mögliche Richtungen zählen und speichern
// Determine valid directions for people
boost::container::static_vector<Direction, helpers::NumEnumValues_v<Direction>> possibleDirs;
PathConditionHuman pathChecker(*world);
for(const auto dir : helpers::EnumRange<Direction>{})
{
if(pathChecker.IsNodeOk(world->GetNeighbour(pos, dir)))
possibleDirs[possibleDirCt++] = dir;
possibleDirs.push_back(dir);
}

// GAR KEINE Richtungen?
if(possibleDirCt == 0)
if(possibleDirs.empty())
{
// Das ist traurig, dann muss die Titanic mit allen restlichen an Board leider untergehen
// No way out for figures -> all die and we can remove this object
GetEvMgr().AddToKillList(world->RemoveFigure(pos, *this));
// restliche Leute von der Inventur abziehen
for(const auto i : helpers::enumRange<Job>())
world->GetPlayer(player).DecreaseInventoryJob(i, people[i]);

Expand All @@ -76,60 +73,49 @@ void BurnedWarehouse::HandleEvent(const unsigned /*id*/)

for(const auto job : helpers::enumRange<Job>())
{
// Anzahl ausrechnen, die in dieser Runde rausgeht
// In the last phase all remaining ones leave, else only some
unsigned count;
if(go_out_phase + 1 >= GO_OUT_PHASES)
count = people[job]; // Take all on last round
count = people[job];
else
count = people[job] / (GO_OUT_PHASES - go_out_phase);

if(count == 0 && wineaddon::isWineAddonJobType(job))
if(count == 0)
continue;

// Von der vorhandenen Abzahl abziehen
// Remove from inventory
people[job] -= count;

// In Alle Richtungen verteilen
// Startrichtung zufällig bestimmen
unsigned start_dir = RANDOM_RAND(helpers::NumEnumValues_v<Direction>);
// Distribute in all directions starting at a random one of the possible ones
const unsigned startIdx = (possibleDirs.size() <= 1u) ? 0 : RANDOM_RAND(possibleDirs.size());
const unsigned numPeoplePerDir = count / possibleDirs.size();

for(unsigned j = 0; j < possibleDirCt; ++j)
for(const unsigned j : helpers::range(possibleDirs.size()))
{
// Aktuelle Richtung, die jetzt dran ist bestimmen
Direction dir = possibleDirs[j] + start_dir;

// Anzahl jetzt für diese Richtung ausrechnen
unsigned numPeopleInDir = count / possibleDirCt;
// Bei letzter Richtung noch den übriggebliebenen Rest dazuaddieren
if(j + 1 == possibleDirCt)
numPeopleInDir += count % possibleDirCt;

// Die Figuren schließlich rausschicken
for(unsigned z = 0; z < numPeopleInDir; ++z)
// Get current direction accounting for startIdx and hence possible wrap around
const unsigned idx = j + startIdx;
const Direction curDir = possibleDirs[idx < possibleDirs.size() ? idx : idx - possibleDirs.size()];
// Take all in last direction
const auto curNumPeople = (j + 1u < possibleDirs.size()) ? numPeoplePerDir : count;
count -= curNumPeople;
for(const auto z : helpers::range(curNumPeople))
{
// Job erzeugen
// Create job and send moving into the current direction
auto& figure = world->AddFigure(pos, std::make_unique<nofPassiveWorker>(job, pos, player, nullptr));
// Losrumirren in die jeweilige Richtung
figure.StartWandering(GetObjId());
figure.StartWalking(dir);
figure.StartWalking(curDir);
}
}
}

// Nächste Runde
// Prepare next phase if any
++go_out_phase;

// Nächste Runde anmelden bzw. sich selbst killen, wenn alle Runden erledigt sind
if(go_out_phase == GO_OUT_PHASES)
{
// fertig, sich selbst töten
// All done
GetEvMgr().AddToKillList(world->RemoveFigure(pos, *this));
// Prüfen, ob alle evakuiert wurden und keiner mehr an Board ist
// There shouldn't be any more
for(unsigned int it : people)
RTTR_Assert(it == 0);
} else
{
// Nächstes Event anmelden
} else // Not done yet
GetEvMgr().AddEvent(this, PHASE_LENGTH, 0);
}
}
14 changes: 7 additions & 7 deletions libs/s25main/figures/nofCharburner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ void nofCharburner::WorkFinished()
if(GetPointQuality(pos) != PointQuality::NotPossible)
{
// Delete previous elements
// Only environt objects and signs are allowed to be removed by the worker!
// Only environ objects and signs are allowed to be removed by the worker!
// Otherwise just do nothing
NodalObjectType noType = no->GetType();

Expand All @@ -105,7 +105,7 @@ void nofCharburner::WorkFinished()
}

/// Fragt abgeleitete Klasse, ob hier Platz bzw ob hier ein Baum etc steht, den z.B. der Holzfäller braucht
nofFarmhand::PointQuality nofCharburner::GetPointQuality(const MapPoint pt) const
nofFarmhand::PointQuality nofCharburner::GetPointQuality(const MapPoint pt, const bool isBeforeWork) const
{
noBase* no = world->GetNO(pt);

Expand All @@ -117,11 +117,11 @@ nofFarmhand::PointQuality nofCharburner::GetPointQuality(const MapPoint pt) cons
if(pileState == noCharburnerPile::State::Smoldering)
return PointQuality::NotPossible;

// Wood stack which stell need resources?
// Wood stack which still need resources?
if(pileState == noCharburnerPile::State::Wood)
{
// Does it need resources and I don't have them hen starting new work (state = Waiting1)?
if(!workplace->WaresAvailable() && this->state == State::Waiting1)
// Only check for resources before going out
if(isBeforeWork && !workplace->WaresAvailable())
return PointQuality::NotPossible;
else
// Only second class, harvest all piles first before continue
Expand All @@ -134,8 +134,8 @@ nofFarmhand::PointQuality nofCharburner::GetPointQuality(const MapPoint pt) cons
}

// Try to "plant" a new pile
// Still enough wares when starting new work (state = Waiting1)?
if(!workplace->WaresAvailable() && state == State::Waiting1)
// Enough wares when starting new work?
if(isBeforeWork && !workplace->WaresAvailable())
return PointQuality::NotPossible;

// Der Platz muss frei sein
Expand Down
8 changes: 3 additions & 5 deletions libs/s25main/figures/nofCharburner.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,16 @@ class nofCharburner : public nofFarmhand
friend constexpr auto maxEnumValue(WareType) { return WareType::Grain; }

private:
/// Malt den Arbeiter beim Arbeiten
void DrawWorking(DrawPoint drawPt) override;
/// Id in jobs.bob or carrier.bob when carrying a ware
/// Has no ID in jobs.bob or carrier.bob
[[noreturn]] unsigned short GetCarryID() const override;

/// Abgeleitete Klasse informieren, wenn sie anfängt zu arbeiten (Vorbereitungen)
void WorkStarted() override;
/// Abgeleitete Klasse informieren, wenn fertig ist mit Arbeiten
void WorkFinished() override;

/// Returns the quality of this working point or determines if the worker can work here at all
PointQuality GetPointQuality(MapPoint pt) const override;
PointQuality GetPointQuality(MapPoint pt, bool isBeforeWork) const override;
using nofFarmhand::GetPointQuality;

/// Inform derived class about the start of the whole working process (at the beginning when walking out of the
/// house)
Expand Down
2 changes: 1 addition & 1 deletion libs/s25main/figures/nofFarmer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ void nofFarmer::WorkFinished()
}

/// Returns the quality of this working point or determines if the worker can work here at all
nofFarmhand::PointQuality nofFarmer::GetPointQuality(const MapPoint pt) const
nofFarmhand::PointQuality nofFarmer::GetPointQuality(const MapPoint pt, bool /* isBeforeWork */) const
{
// Entweder gibts ein Getreidefeld, das wir abernten können...
if(world->GetNO(pt)->GetType() == NodalObjectType::Grainfield)
Expand Down
3 changes: 2 additions & 1 deletion libs/s25main/figures/nofFarmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class nofFarmer : public nofFarmhand
void WorkAborted() override;

/// Returns the quality of this working point or determines if the worker can work here at all
PointQuality GetPointQuality(MapPoint pt) const override;
PointQuality GetPointQuality(MapPoint pt, bool isBeforeWork) const override;
using nofFarmhand::GetPointQuality;

public:
nofFarmer(MapPoint pos, unsigned char player, nobUsual* workplace);
Expand Down
Loading

0 comments on commit bbc6968

Please sign in to comment.