Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions libs/s25main/BuildingRegister.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,15 @@ helpers::EnumArray<uint16_t, BuildingType> BuildingRegister::CalcProductivities(
return productivities;
}

helpers::EnumArray<uint16_t, BuildingType> BuildingRegister::CalcDisplayProductivities() const
{
helpers::EnumArray<uint16_t, BuildingType> productivities;

for(const auto bld : helpers::enumRange<BuildingType>())
productivities[bld] = static_cast<uint16_t>(CalcAverageDisplayProductivity(bld));
return productivities;
}

unsigned BuildingRegister::CalcAverageProductivity(BuildingType bldType) const
{
if(holds_alternative<boost::none_t>(BLD_WORK_DESC[bldType].producedWare))
Expand All @@ -171,6 +180,22 @@ unsigned BuildingRegister::CalcAverageProductivity(BuildingType bldType) const
return productivity;
}

unsigned BuildingRegister::CalcAverageDisplayProductivity(BuildingType bldType) const
{
if(holds_alternative<boost::none_t>(BLD_WORK_DESC[bldType].producedWare))
return 0;
unsigned productivity = 0;
const auto& buildings = GetBuildings(bldType);
const unsigned numBlds = buildings.size();
if(numBlds > 0)
{
for(const nobUsual* bld : buildings)
productivity += bld->GetDisplayProductivity();
productivity /= numBlds;
}
return productivity;
}

unsigned short BuildingRegister::CalcAverageProductivity() const
{
unsigned totalProductivity = 0;
Expand Down
4 changes: 4 additions & 0 deletions libs/s25main/BuildingRegister.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ class BuildingRegister
BuildingCount GetBuildingNums() const;
/// Calculate and fill the average productivities for all buildings.
helpers::EnumArray<uint16_t, BuildingType> CalcProductivities() const;
/// Calculate and fill the average productivities shown in UI.
helpers::EnumArray<uint16_t, BuildingType> CalcDisplayProductivities() const;
/// Calculate the average productivity for a building type
unsigned CalcAverageProductivity(BuildingType bldType) const;
/// Calculate the average productivity shown in UI for a building type
unsigned CalcAverageDisplayProductivity(BuildingType bldType) const;
/// Calculate the average productivity for all buildings
unsigned short CalcAverageProductivity() const;

Expand Down
6 changes: 6 additions & 0 deletions libs/s25main/GlobalGameSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ void GlobalGameSettings::registerAllAddons()
AddonHalfCostMilEquip,
AddonInexhaustibleFish,
AddonInexhaustibleGraniteMines,
AddonGraniteMinesWorkEverywhere,
AddonCoalMineResourceBehavior,
AddonIronMineResourceBehavior,
AddonGoldMineResourceBehavior,
AddonGraniteMineResourceBehavior,
AddonMineNoOutputFallback,
AddonInexhaustibleMines,
AddonLimitCatapults,
AddonManualRoadEnlargement,
Expand Down
21 changes: 21 additions & 0 deletions libs/s25main/addons/AddonGraniteMinesWorkEverywhere.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "AddonBool.h"
#include "const_addons.h"
#include "mygettext/mygettext.h"

/**
* Addon for creating finite granite resources below granite mines without explicit stone resources.
*/
class AddonGraniteMinesWorkEverywhere : public AddonBool
{
public:
AddonGraniteMinesWorkEverywhere()
: AddonBool(AddonId::GRANITEMINES_WORK_EVERYWHERE, AddonGroup::Economy, _("Granite Mines Work Everywhere"),
_("Granite mines can create a finite stone resource on otherwise empty mountain spots."))
{}
};
4 changes: 2 additions & 2 deletions libs/s25main/addons/AddonInexhaustibleGraniteMines.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
#include "mygettext/mygettext.h"

/**
* Addon for allowing to have unlimited resources.
* Addon for allowing granite mines to have unlimited resources.
*/
class AddonInexhaustibleGraniteMines : public AddonBool
{
public:
AddonInexhaustibleGraniteMines()
: AddonBool(AddonId::INEXHAUSTIBLE_GRANITEMINES, AddonGroup::Economy, _("Inexhaustible Granite Mines"),
_("Granite mines will never be depleted."))
_("Granite mines will never deplete stone resources."))
{}
};
22 changes: 22 additions & 0 deletions libs/s25main/addons/AddonMineNoOutputFallback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "AddonList.h"
#include "const_addons.h"
#include "mygettext/mygettext.h"
#include "gameTypes/MineNoOutputFallback.h"

class AddonMineNoOutputFallback : public AddonList
{
public:
AddonMineNoOutputFallback()
: AddonList(AddonId::MINE_NO_OUTPUT_FALLBACK, AddonGroup::Economy, _("Mine No-Output Fallback"),
_("Configures what mines produce when S4-like exhaustion would produce nothing."),
{_("Produce nothing"), _("Produce granite 25%"), _("Produce granite 50%"),
_("Produce granite 100%"), _("Produce lower grade resource")},
static_cast<unsigned>(MineNoOutputFallback::ProduceNothing))
{}
};
57 changes: 57 additions & 0 deletions libs/s25main/addons/AddonMineResourceBehavior.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org)
//
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "AddonList.h"
#include "const_addons.h"
#include "mygettext/mygettext.h"
#include "gameTypes/MineResourceBehavior.h"
#include <string>

class AddonMineResourceBehaviorBase : public AddonList
{
protected:
AddonMineResourceBehaviorBase(AddonId id, const std::string& name, const std::string& description)
: AddonList(id, AddonGroup::Economy, name, description,
{_("Default"), _("S4-like exhaustion"), _("Inexhaustible"), _("Work everywhere")},
static_cast<unsigned>(MineResourceBehavior::Default))
{}
};

class AddonCoalMineResourceBehavior : public AddonMineResourceBehaviorBase
{
public:
AddonCoalMineResourceBehavior()
: AddonMineResourceBehaviorBase(AddonId::COALMINE_RESOURCE_BEHAVIOR, _("Coal Mine Resource Behavior"),
_("Configures how coal mines consume and exhaust coal deposits."))
{}
};

class AddonIronMineResourceBehavior : public AddonMineResourceBehaviorBase
{
public:
AddonIronMineResourceBehavior()
: AddonMineResourceBehaviorBase(AddonId::IRONMINE_RESOURCE_BEHAVIOR, _("Iron Mine Resource Behavior"),
_("Configures how iron mines consume and exhaust iron deposits."))
{}
};

class AddonGoldMineResourceBehavior : public AddonMineResourceBehaviorBase
{
public:
AddonGoldMineResourceBehavior()
: AddonMineResourceBehaviorBase(AddonId::GOLDMINE_RESOURCE_BEHAVIOR, _("Gold Mine Resource Behavior"),
_("Configures how gold mines consume and exhaust gold deposits."))
{}
};

class AddonGraniteMineResourceBehavior : public AddonMineResourceBehaviorBase
{
public:
AddonGraniteMineResourceBehavior()
: AddonMineResourceBehaviorBase(AddonId::GRANITEMINE_RESOURCE_BEHAVIOR, _("Granite Mine Resource Behavior"),
_("Configures how granite mines consume and exhaust stone deposits."))
{}
};
3 changes: 3 additions & 0 deletions libs/s25main/addons/Addons.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@

#include "addons/AddonToolOrdering.h"

#include "addons/AddonGraniteMinesWorkEverywhere.h"
#include "addons/AddonInexhaustibleFish.h"
#include "addons/AddonInexhaustibleGraniteMines.h"
#include "addons/AddonMaxRank.h"
#include "addons/AddonMilitaryAid.h"
#include "addons/AddonMineNoOutputFallback.h"
#include "addons/AddonMineResourceBehavior.h"
#include "addons/AddonSeaAttack.h"

#include "addons/AddonBattlefieldPromotion.h"
Expand Down
5 changes: 4 additions & 1 deletion libs/s25main/addons/const_addons.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ ENUM_WITH_STRING(AddonId, LIMIT_CATAPULTS = 0x00000000, INEXHAUSTIBLE_MINES = 0x

MILITARY_AID = 0x00700000,

INEXHAUSTIBLE_GRANITEMINES = 0x00800000,
INEXHAUSTIBLE_GRANITEMINES = 0x00800000, GRANITEMINES_WORK_EVERYWHERE = 0x00800001,
COALMINE_RESOURCE_BEHAVIOR = 0x00800002, IRONMINE_RESOURCE_BEHAVIOR = 0x00800003,
GOLDMINE_RESOURCE_BEHAVIOR = 0x00800004, GRANITEMINE_RESOURCE_BEHAVIOR = 0x00800005,
MINE_NO_OUTPUT_FALLBACK = 0x00800006,

MAX_RANK = 0x00900000, SEA_ATTACK = 0x00900001, INEXHAUSTIBLE_FISH = 0x00900002,
MORE_ANIMALS = 0x00900003, BURN_DURATION = 0x00900004, NO_ALLIED_PUSH = 0x00900005,
Expand Down
45 changes: 45 additions & 0 deletions libs/s25main/ai/AIInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "pathfinding/RoadPathFinder.h"
#include "nodeObjs/noFlag.h"
#include "nodeObjs/noTree.h"
#include "gameTypes/MineResourceBehavior.h"
#include "gameData/TerrainDesc.h"
#include <limits>
#include <numeric>
Expand Down Expand Up @@ -45,6 +46,26 @@ bool IsPointOK_RoadPathEvenStep(const GameWorldBase& gwb, const MapPoint pt, con
const auto* prp = static_cast<const Param_RoadPath*>(param);
return prp->boat_road || gwb.GetBQ(pt, gwb.GetNode(pt).owner - 1) != BuildingQuality::Nothing;
}

helpers::OptionalEnum<BuildingType> GetMineBuildingType(const AIResource res)
{
switch(res)
{
case AIResource::Gold: return BuildingType::GoldMine;
case AIResource::Ironore: return BuildingType::IronMine;
case AIResource::Coal: return BuildingType::CoalMine;
case AIResource::Granite: return BuildingType::GraniteMine;
default: return boost::none;
}
}

int GetS4LikeMineResourceRating(const Resource resource, const unsigned defaultRating)
{
if(resource.getAmount() == 0u)
return 0;

return std::max(1u, std::min(static_cast<unsigned>(resource.getAmount()), defaultRating));
}
} // namespace

AIInterface::AIInterface(const GameWorldBase& gwb, std::vector<gc::GameCommandPtr>& gcs, unsigned char playerID)
Expand Down Expand Up @@ -158,6 +179,23 @@ int AIInterface::GetResourceRating(const MapPoint pt, AIResource res) const
case AIResource::Ironore:
case AIResource::Coal:
case AIResource::Granite:
{
const Resource subres = gwb.GetNode(pt).resources;
if(convertToNodeResource(GetSubsurfaceResource(pt)) == res)
{
const auto mineBuildingType = GetMineBuildingType(res);
if(mineBuildingType
&& GetEffectiveMineResourceBehavior(gwb.GetGGS(), *mineBuildingType)
== MineResourceBehavior::S4LikeExhaustion)
return GetS4LikeMineResourceRating(subres, RES_RADIUS[res]);

return RES_RADIUS[res];
}
if(IsMineResourceWorkEverywhere(res) && subres.getType() == ResourceType::Nothing
&& gwb.IsOfTerrain(pt, [](const TerrainDesc& desc) { return desc.Is(ETerrain::Mineable); }))
return RES_RADIUS[res];
break;
}
case AIResource::Fish:
if(convertToNodeResource(GetSubsurfaceResource(pt)) == res)
return RES_RADIUS[res];
Expand All @@ -166,6 +204,13 @@ int AIInterface::GetResourceRating(const MapPoint pt, AIResource res) const
return 0;
}

bool AIInterface::IsMineResourceWorkEverywhere(const AIResource res) const
{
const auto mineBuildingType = GetMineBuildingType(res);
return mineBuildingType
&& GetEffectiveMineResourceBehavior(gwb.GetGGS(), *mineBuildingType) == MineResourceBehavior::WorkEverywhere;
}

int AIInterface::CalcResourceValue(const MapPoint pt, AIResource res, helpers::OptionalEnum<Direction> direction,
int lastval) const
{
Expand Down
2 changes: 2 additions & 0 deletions libs/s25main/ai/AIInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class AIInterface : public GameCommandFactory
int lastval = 0xffff) const;
/// Calculate the resource value for a given point
int GetResourceRating(MapPoint pt, AIResource res) const;
/// Check whether the given mine resource can be produced on otherwise empty mineable mountain.
bool IsMineResourceWorkEverywhere(AIResource res) const;
/// Test whether a given point is part of the border or not
bool IsBorder(const MapPoint pt) const
{
Expand Down
10 changes: 5 additions & 5 deletions libs/s25main/ai/aijh/AIPlayerJH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "nodeObjs/noFlag.h"
#include "nodeObjs/noShip.h"
#include "nodeObjs/noTree.h"
#include "gameTypes/MineResourceBehavior.h"
#include "gameData/BuildingConsts.h"
#include "gameData/BuildingProperties.h"
#include "gameData/GameConsts.h"
Expand Down Expand Up @@ -139,11 +140,10 @@ static bool isUnlimitedResource(const AIResource res, const GlobalGameSettings&
{
switch(res)
{
case AIResource::Gold:
case AIResource::Ironore:
case AIResource::Coal: return ggs.isEnabled(AddonId::INEXHAUSTIBLE_MINES);
case AIResource::Granite:
return ggs.isEnabled(AddonId::INEXHAUSTIBLE_MINES) || ggs.isEnabled(AddonId::INEXHAUSTIBLE_GRANITEMINES);
case AIResource::Gold: return !IsMineResourceDepletable(ggs, BuildingType::GoldMine);
case AIResource::Ironore: return !IsMineResourceDepletable(ggs, BuildingType::IronMine);
case AIResource::Coal: return !IsMineResourceDepletable(ggs, BuildingType::CoalMine);
case AIResource::Granite: return !IsMineResourceDepletable(ggs, BuildingType::GraniteMine);
case AIResource::Fish: return ggs.isEnabled(AddonId::INEXHAUSTIBLE_FISH);
default: return false;
}
Expand Down
22 changes: 22 additions & 0 deletions libs/s25main/buildings/nobUsual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
#include "ogl/glArchivItem_Bitmap_Player.h"
#include "postSystem/PostMsgWithBuilding.h"
#include "world/GameWorld.h"
#include "gameTypes/MineResourceBehavior.h"
#include "gameTypes/Resource.h"
#include "gameData/BuildingConsts.h"
#include "gameData/BuildingProperties.h"
#include "gameData/GameConsts.h"
#include <numeric>

/// Number of GFs after which the productivity is recalculated, i.e. productivity is averaged over intervals of this
Expand Down Expand Up @@ -519,6 +522,25 @@ bool nobUsual::HasWorker() const
return worker && worker->GetState() != nofBuildingWorker::State::FigureWork;
}

unsigned short nobUsual::GetDisplayProductivity() const
{
if(!BuildingProperties::IsMine(bldType_)
|| GetEffectiveMineResourceBehavior(world->GetGGS(), bldType_) != MineResourceBehavior::S4LikeExhaustion)
return productivity;

const ResourceType resourceType = GetMineResourceType(bldType_);
const std::vector<MapPoint> resourcePts = world->GetMatchingPointsInRadius<1>(
pos, MINER_RADIUS,
[this, resourceType](const MapPoint pt) { return world->GetNode(pt).resources.has(resourceType); }, true);

unsigned resourceAmount = 0;
for(const MapPoint pt : resourcePts)
resourceAmount += world->GetNode(pt).resources.getAmount();

return static_cast<unsigned short>(
(static_cast<unsigned>(productivity) * GetS4LikeMineProductionChance(resourceAmount)) / 100u);
}

void nobUsual::OnOutOfResources()
{
// Post verschicken, keine Rohstoffe mehr da
Expand Down
1 change: 1 addition & 0 deletions libs/s25main/buildings/nobUsual.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class nobUsual : public noBuilding
/// Gibt Pointer auf Produktivität zurück
const unsigned short* GetProductivityPointer() const { return &productivity; }
unsigned short GetProductivity() const { return productivity; }
unsigned short GetDisplayProductivity() const;
const nofBuildingWorker* GetWorker() const { return worker; }

/// Stoppt/Erlaubt Produktion (visuell)
Expand Down
Loading