mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-20 20:23:03 +02:00
Unified income handling, added IOwnableObject interface
This commit is contained in:
parent
189cb1c762
commit
0fd9dbf240
@ -314,9 +314,7 @@ void BuildAnalyzer::updateDailyIncome()
|
||||
const CGMine* mine = dynamic_cast<const CGMine*>(obj);
|
||||
|
||||
if(mine)
|
||||
{
|
||||
dailyIncome[mine->producedResource.getNum()] += mine->getProducedQuantity();
|
||||
}
|
||||
dailyIncome += mine->dailyIncome();
|
||||
}
|
||||
|
||||
for(const CGTownInstance* town : towns)
|
||||
|
@ -585,9 +585,7 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
|
||||
const CGMine * mine = dynamic_cast<const CGMine *>(object);
|
||||
assert(mine);
|
||||
minesCount[mine->producedResource]++;
|
||||
|
||||
if (mine->producedResource == EGameResID::GOLD)
|
||||
totalIncome += mine->getProducedQuantity();
|
||||
totalIncome += mine->dailyIncome()[EGameResID::GOLD];
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,7 +594,7 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
|
||||
auto * playerSettings = LOCPLINT->cb->getPlayerSettings(LOCPLINT->playerID);
|
||||
for(auto & hero : heroes)
|
||||
{
|
||||
totalIncome += hero->valOfBonuses(Selector::typeSubtype(BonusType::GENERATE_RESOURCE, BonusSubtypeID(GameResID(EGameResID::GOLD)))) * playerSettings->handicap.percentIncome / 100;
|
||||
totalIncome += hero->dailyIncome()[EGameResID::GOLD];
|
||||
}
|
||||
|
||||
//Add town income of all towns
|
||||
|
@ -504,6 +504,7 @@ set(lib_MAIN_HEADERS
|
||||
mapObjects/CRewardableObject.h
|
||||
mapObjects/IMarket.h
|
||||
mapObjects/IObjectInterface.h
|
||||
mapObjects/IOwnableObject.h
|
||||
mapObjects/MapObjects.h
|
||||
mapObjects/MiscObjects.h
|
||||
mapObjects/ObjectTemplate.h
|
||||
|
@ -64,6 +64,12 @@ void ResourceSet::positive()
|
||||
vstd::amax(elem, 0);
|
||||
}
|
||||
|
||||
void ResourceSet::applyHandicap(int percentage)
|
||||
{
|
||||
for(auto & elem : *this)
|
||||
elem = vstd::divideAndCeil(elem * percentage, 100);
|
||||
}
|
||||
|
||||
static bool canAfford(const ResourceSet &res, const ResourceSet &price)
|
||||
{
|
||||
assert(res.size() == price.size() && price.size() == GameConstants::RESOURCE_QUANTITY);
|
||||
|
@ -190,6 +190,7 @@ public:
|
||||
DLL_LINKAGE void amax(const TResourceCap &val); //performs vstd::amax on each element
|
||||
DLL_LINKAGE void amin(const TResourceCap &val); //performs vstd::amin on each element
|
||||
DLL_LINKAGE void positive(); //values below 0 are set to 0 - upgrade cost can't be negative, for example
|
||||
DLL_LINKAGE void applyHandicap(int percentage);
|
||||
DLL_LINKAGE bool nonZero() const; //returns true if at least one value is non-zero;
|
||||
DLL_LINKAGE bool canAfford(const ResourceSet &price) const;
|
||||
DLL_LINKAGE bool canBeAfforded(const ResourceSet &res) const;
|
||||
|
@ -255,20 +255,18 @@ si64 Statistic::getTotalExperience(const PlayerState * ps)
|
||||
// get total gold income
|
||||
int Statistic::getIncome(const CGameState * gs, const PlayerState * ps)
|
||||
{
|
||||
int percentIncome = gs->getStartInfo()->getIthPlayersSettings(ps->color).handicap.percentIncome;
|
||||
int totalIncome = 0;
|
||||
|
||||
//Heroes can produce gold as well - skill, specialty or arts
|
||||
for(const auto & h : ps->heroes)
|
||||
totalIncome += h->valOfBonuses(Selector::typeSubtype(BonusType::GENERATE_RESOURCE, BonusSubtypeID(GameResID(GameResID::GOLD)))) * percentIncome / 100;
|
||||
totalIncome += h->dailyIncome()[EGameResID::GOLD];
|
||||
|
||||
//Add town income of all towns
|
||||
for(const auto & t : ps->towns)
|
||||
totalIncome += t->dailyIncome()[EGameResID::GOLD];
|
||||
|
||||
for(const CGMine * mine : getMines(gs, ps))
|
||||
if(mine->producedResource == EGameResID::GOLD)
|
||||
totalIncome += mine->getProducedQuantity();
|
||||
totalIncome += mine->dailyIncome()[EGameResID::GOLD];
|
||||
|
||||
return totalIncome;
|
||||
}
|
||||
|
@ -1822,4 +1822,22 @@ bool CGHeroInstance::isCampaignGem() const
|
||||
return true;
|
||||
}
|
||||
|
||||
ResourceSet CGHeroInstance::dailyIncome() const
|
||||
{
|
||||
ResourceSet income;
|
||||
|
||||
for (GameResID k : GameResID::ALL_RESOURCES())
|
||||
income[k] += valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k));
|
||||
|
||||
const auto & playerSettings = cb->getPlayerSettings(getOwner());
|
||||
income.applyHandicap(playerSettings->handicap.percentIncome);
|
||||
return income;
|
||||
}
|
||||
|
||||
const IOwnableObject * CGHeroInstance::asOwnable() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <vcmi/spells/Caster.h>
|
||||
|
||||
#include "CArmedInstance.h"
|
||||
#include "IOwnableObject.h"
|
||||
|
||||
#include "../CArtHandler.h" // For CArtifactSet
|
||||
|
||||
@ -48,7 +49,7 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public spells::Caster, public AFactionMember, public ICreatureUpgrader
|
||||
class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public spells::Caster, public AFactionMember, public ICreatureUpgrader, public IOwnableObject
|
||||
{
|
||||
// We serialize heroes into JSON for crossover
|
||||
friend class CampaignState;
|
||||
@ -165,6 +166,9 @@ public:
|
||||
EAlignment getAlignment() const;
|
||||
bool needsLastStack()const override;
|
||||
|
||||
ResourceSet dailyIncome() const override;
|
||||
const IOwnableObject * asOwnable() const final;
|
||||
|
||||
//INativeTerrainProvider
|
||||
FactionID getFaction() const override;
|
||||
TerrainId getNativeTerrain() const override;
|
||||
|
@ -395,4 +395,9 @@ BattleField CGObjectInstance::getBattlefield() const
|
||||
return VLC->objtypeh->getHandlerFor(ID, subID)->getBattlefield();
|
||||
}
|
||||
|
||||
const IOwnableObject * CGObjectInstance::asOwnable() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -126,6 +126,8 @@ public:
|
||||
virtual std::vector<Component> getPopupComponents(PlayerColor player) const;
|
||||
virtual std::vector<Component> getPopupComponents(const CGHeroInstance * hero) const;
|
||||
|
||||
const IOwnableObject * asOwnable() const override;
|
||||
|
||||
/** OVERRIDES OF IObjectInterface **/
|
||||
|
||||
void initObj(vstd::RNG & rand) override;
|
||||
|
@ -225,13 +225,16 @@ TResources CGTownInstance::dailyIncome() const
|
||||
}
|
||||
}
|
||||
|
||||
auto playerSettings = cb->gameState()->scenarioOps->getIthPlayersSettings(getOwner());
|
||||
for(TResources::nziterator it(ret); it.valid(); it++)
|
||||
// always round up income - we don't want to always produce zero if handicap in use
|
||||
ret[it->resType] = vstd::divideAndCeil(ret[it->resType] * playerSettings.handicap.percentIncome, 100);
|
||||
const auto & playerSettings = cb->getPlayerSettings(getOwner());
|
||||
ret.applyHandicap(playerSettings->handicap.percentIncome);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const IOwnableObject * CGTownInstance::asOwnable() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
bool CGTownInstance::hasFort() const
|
||||
{
|
||||
return hasBuilt(BuildingID::FORT);
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "IMarket.h"
|
||||
#include "CGDwelling.h"
|
||||
#include "IOwnableObject.h"
|
||||
#include "../entities/faction/CFaction.h" // TODO: remove
|
||||
#include "../entities/faction/CTown.h" // TODO: remove
|
||||
|
||||
@ -47,7 +48,7 @@ struct DLL_LINKAGE GrowthInfo
|
||||
int handicapPercentage;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket, public INativeTerrainProvider, public ICreatureUpgrader
|
||||
class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket, public INativeTerrainProvider, public ICreatureUpgrader, public IOwnableObject
|
||||
{
|
||||
std::string nameTextId; // name of town
|
||||
|
||||
@ -181,7 +182,9 @@ public:
|
||||
std::set<BuildingID> getBuildings() const;
|
||||
|
||||
TResources getBuildingCost(const BuildingID & buildingID) const;
|
||||
TResources dailyIncome() const; //calculates daily income of this town
|
||||
ResourceSet dailyIncome() const override;
|
||||
const IOwnableObject * asOwnable() const final;
|
||||
|
||||
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
|
||||
bool armedGarrison() const; //true if town has creatures in garrison or garrisoned hero
|
||||
int getTownLevel() const;
|
||||
|
@ -33,6 +33,7 @@ class ResourceSet;
|
||||
class int3;
|
||||
class MetaString;
|
||||
class PlayerColor;
|
||||
class IOwnableObject;
|
||||
|
||||
class DLL_LINKAGE IObjectInterface : public GameCallbackHolder, public virtual Serializeable
|
||||
{
|
||||
@ -68,6 +69,8 @@ public:
|
||||
//unified helper to show info dialog for object owner
|
||||
virtual void showInfoDialog(const ui32 txtID, const ui16 soundID = 0, EInfoWindowMode mode = EInfoWindowMode::AUTO) const;
|
||||
|
||||
virtual const IOwnableObject * asOwnable() const = 0;
|
||||
|
||||
//unified interface, AI helpers
|
||||
virtual bool wasVisited (PlayerColor player) const;
|
||||
virtual bool wasVisited (const CGHeroInstance * h) const;
|
||||
|
23
lib/mapObjects/IOwnableObject.h
Normal file
23
lib/mapObjects/IOwnableObject.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* IOwnableObject.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class ResourceSet;
|
||||
|
||||
class DLL_LINKAGE IOwnableObject
|
||||
{
|
||||
public:
|
||||
virtual ResourceSet dailyIncome() const = 0;
|
||||
virtual ~IOwnableObject() = default;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
@ -93,18 +93,6 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
|
||||
flagMine(h->tempOwner);
|
||||
|
||||
}
|
||||
|
||||
void CGMine::newTurn(vstd::RNG & rand) const
|
||||
{
|
||||
if(cb->getDate() == 1)
|
||||
return;
|
||||
|
||||
if (tempOwner == PlayerColor::NEUTRAL)
|
||||
return;
|
||||
|
||||
cb->giveResource(tempOwner, producedResource, getProducedQuantity());
|
||||
}
|
||||
|
||||
void CGMine::initObj(vstd::RNG & rand)
|
||||
@ -139,11 +127,19 @@ bool CGMine::isAbandoned() const
|
||||
return subID.getNum() >= 7;
|
||||
}
|
||||
|
||||
const IOwnableObject * CGMine::asOwnable() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
ResourceSet CGMine::dailyIncome() const
|
||||
{
|
||||
ResourceSet result;
|
||||
result[producedResource] += defaultResProduction();
|
||||
|
||||
const auto & playerSettings = cb->getPlayerSettings(getOwner());
|
||||
result.applyHandicap(playerSettings->handicap.percentIncome);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CArmedInstance.h"
|
||||
#include "IOwnableObject.h"
|
||||
#include "../texts/MetaString.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@ -148,16 +149,13 @@ protected:
|
||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGMine : public CArmedInstance
|
||||
class DLL_LINKAGE CGMine : public CArmedInstance, public IOwnableObject
|
||||
{
|
||||
public:
|
||||
GameResID producedResource;
|
||||
ui32 producedQuantity;
|
||||
std::set<GameResID> abandonedMineResources;
|
||||
|
||||
bool isAbandoned() const;
|
||||
ResourceSet dailyIncome() const;
|
||||
|
||||
private:
|
||||
using CArmedInstance::CArmedInstance;
|
||||
|
||||
@ -166,7 +164,6 @@ private:
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override;
|
||||
|
||||
void flagMine(const PlayerColor & player) const;
|
||||
void newTurn(vstd::RNG & rand) const override;
|
||||
void initObj(vstd::RNG & rand) override;
|
||||
|
||||
std::string getObjectName() const override;
|
||||
@ -183,6 +180,9 @@ public:
|
||||
ui32 defaultResProduction() const;
|
||||
ui32 getProducedQuantity() const;
|
||||
|
||||
ResourceSet dailyIncome() const override;
|
||||
const IOwnableObject * asOwnable() const final;
|
||||
|
||||
protected:
|
||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||
};
|
||||
|
@ -50,6 +50,11 @@ MapObjectSubID TownBuildingInstance::getObjTypeIndex() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
const IOwnableObject * TownBuildingInstance::asOwnable() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int3 TownBuildingInstance::visitablePos() const
|
||||
{
|
||||
return town->visitablePos();
|
||||
|
@ -35,6 +35,7 @@ public:
|
||||
PlayerColor getOwner() const override;
|
||||
MapObjectID getObjGroupIndex() const override;
|
||||
MapObjectSubID getObjTypeIndex() const override;
|
||||
const IOwnableObject * asOwnable() const override;
|
||||
|
||||
int3 visitablePos() const override;
|
||||
int3 getPosition() const override;
|
||||
|
@ -643,8 +643,11 @@ void CGameHandler::onNewTurn()
|
||||
throw std::runtime_error("Invalid player in player state! Player " + std::to_string(player.first.getNum()) + ", map name: " + gs->map->name.toString() + ", map description: " + gs->map->description.toString());
|
||||
}
|
||||
|
||||
for (const auto & player : gs->players)
|
||||
n.playerIncome[player.first] = newTurnProcessor->generatePlayerIncome(player.first, newWeek && !firstTurn);
|
||||
if (!firstTurn)
|
||||
{
|
||||
for (const auto & player : gs->players)
|
||||
n.playerIncome[player.first] = newTurnProcessor->generatePlayerIncome(player.first, newWeek);
|
||||
}
|
||||
|
||||
if (newWeek && !firstTurn)
|
||||
{
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "../../lib/gameState/CGameState.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapObjects/IOwnableObject.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/networkPacks/PacksForClient.h"
|
||||
#include "../../lib/pathfinder/TurnInfo.h"
|
||||
@ -87,20 +88,12 @@ void NewTurnProcessor::onPlayerTurnEnded(PlayerColor which)
|
||||
|
||||
ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool newWeek)
|
||||
{
|
||||
const auto & playerSettings = gameHandler->gameState()->scenarioOps->getIthPlayersSettings(playerID);
|
||||
const auto & playerSettings = gameHandler->getPlayerSettings(playerID);
|
||||
const PlayerState & state = gameHandler->gameState()->players.at(playerID);
|
||||
ResourceSet income;
|
||||
|
||||
for (const auto & hero : state.heroes)
|
||||
{
|
||||
for (GameResID k : GameResID::ALL_RESOURCES())
|
||||
income[k] += hero->valOfBonuses(BonusType::GENERATE_RESOURCE, BonusSubtypeID(k));
|
||||
}
|
||||
|
||||
for (const auto & town : state.towns)
|
||||
{
|
||||
income += town->dailyIncome();
|
||||
|
||||
if (newWeek && town->hasBuilt(BuildingSubID::TREASURY))
|
||||
{
|
||||
//give 10% of starting gold
|
||||
@ -150,7 +143,15 @@ ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool ne
|
||||
income[EGameResID::CRYSTAL] += 3;
|
||||
}
|
||||
|
||||
TResources incomeHandicapped = income * playerSettings.handicap.percentIncome / 100;
|
||||
TResources incomeHandicapped = income;
|
||||
incomeHandicapped.applyHandicap(playerSettings->handicap.percentIncome);
|
||||
|
||||
// FIXME: store pre-filtered, all owned objects in PlayerState
|
||||
for (auto obj : gameHandler->gameState()->map->objects)
|
||||
{
|
||||
if (obj && obj->asOwnable() && obj->getOwner() == playerID)
|
||||
incomeHandicapped += obj->asOwnable()->dailyIncome();
|
||||
}
|
||||
|
||||
return incomeHandicapped;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user