1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +02:00

Use variant identifier in netpacks where applicable

This commit is contained in:
Ivan Savenko 2023-11-06 18:27:16 +02:00
parent 63e99a32d7
commit 6b81012f31
54 changed files with 391 additions and 304 deletions

View File

@ -481,7 +481,7 @@ void AIGateway::objectPropertyChanged(const SetObjectProperty * sop)
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
if(sop->what == ObjProperty::OWNER) if(sop->what == ObjProperty::OWNER)
{ {
auto relations = myCb->getPlayerRelations(playerID, (PlayerColor)sop->val); auto relations = myCb->getPlayerRelations(playerID, sop->identifier.as<PlayerColor>());
auto obj = myCb->getObj(sop->id, false); auto obj = myCb->getObj(sop->id, false);
if(!nullkiller) // crash protection if(!nullkiller) // crash protection
@ -1419,7 +1419,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
//TODO trade only as much as needed //TODO trade only as much as needed
if (toGive) //don't try to sell 0 resources if (toGive) //don't try to sell 0 resources
{ {
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, g.resID, toGive); cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
accquiredResources = static_cast<int>(toGet * (it->resVal / toGive)); accquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName()); logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName());
} }

View File

@ -564,7 +564,7 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
if(sop->what == ObjProperty::OWNER) if(sop->what == ObjProperty::OWNER)
{ {
if(myCb->getPlayerRelations(playerID, (PlayerColor)sop->val) == PlayerRelations::ENEMIES) if(myCb->getPlayerRelations(playerID, sop->identifier.as<PlayerColor>()) == PlayerRelations::ENEMIES)
{ {
//we want to visit objects owned by oppponents //we want to visit objects owned by oppponents
auto obj = myCb->getObj(sop->id, false); auto obj = myCb->getObj(sop->id, false);
@ -2160,7 +2160,7 @@ void VCAI::tryRealize(Goals::Trade & g) //trade
//TODO trade only as much as needed //TODO trade only as much as needed
if (toGive) //don't try to sell 0 resources if (toGive) //don't try to sell 0 resources
{ {
cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, g.resID, toGive); cb->trade(m, EMarketMode::RESOURCE_RESOURCE, res, GameResID(g.resID), toGive);
accquiredResources = static_cast<int>(toGet * (it->resVal / toGive)); accquiredResources = static_cast<int>(toGet * (it->resVal / toGive));
logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName()); logAi->debug("Traded %d of %s for %d of %s at %s", toGive, res, accquiredResources, g.resID, obj->getObjectName());
} }

View File

@ -237,12 +237,12 @@ void CCallback::buyArtifact(const CGHeroInstance *hero, ArtifactID aid)
sendRequest(&pack); sendRequest(&pack);
} }
void CCallback::trade(const IMarket * market, EMarketMode mode, ui32 id1, ui32 id2, ui32 val1, const CGHeroInstance * hero) void CCallback::trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero)
{ {
trade(market, mode, std::vector<ui32>(1, id1), std::vector<ui32>(1, id2), std::vector<ui32>(1, val1), hero); trade(market, mode, std::vector(1, id1), std::vector(1, id2), std::vector(1, val1), hero);
} }
void CCallback::trade(const IMarket * market, EMarketMode mode, const std::vector<ui32> & id1, const std::vector<ui32> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero) void CCallback::trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero)
{ {
TradeOnMarketplace pack; TradeOnMarketplace pack;
pack.marketId = dynamic_cast<const CGObjectInstance *>(market)->id; pack.marketId = dynamic_cast<const CGObjectInstance *>(market)->id;
@ -254,9 +254,9 @@ void CCallback::trade(const IMarket * market, EMarketMode mode, const std::vecto
sendRequest(&pack); sendRequest(&pack);
} }
void CCallback::setFormation(const CGHeroInstance * hero, bool tight) void CCallback::setFormation(const CGHeroInstance * hero, EArmyFormation mode)
{ {
SetFormation pack(hero->id,tight); SetFormation pack(hero->id, mode);
sendRequest(&pack); sendRequest(&pack);
} }

View File

@ -12,6 +12,7 @@
#include "lib/CGameInfoCallback.h" #include "lib/CGameInfoCallback.h"
#include "lib/battle/CPlayerBattleCallback.h" #include "lib/battle/CPlayerBattleCallback.h"
#include "lib/int3.h" // for int3 #include "lib/int3.h" // for int3
#include "lib/networkPacks/TradeItem.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -78,8 +79,8 @@ public:
virtual bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made virtual bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made
virtual void swapGarrisonHero(const CGTownInstance *town)=0; virtual void swapGarrisonHero(const CGTownInstance *town)=0;
virtual void trade(const IMarket * market, EMarketMode mode, ui32 id1, ui32 id2, ui32 val1, const CGHeroInstance * hero = nullptr)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce virtual void trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce
virtual void trade(const IMarket * market, EMarketMode mode, const std::vector<ui32> & id1, const std::vector<ui32> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr)=0; virtual void trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr)=0;
virtual int selectionMade(int selection, QueryID queryID) =0; virtual int selectionMade(int selection, QueryID queryID) =0;
virtual int sendQueryReply(std::optional<int32_t> reply, QueryID queryID) =0; virtual int sendQueryReply(std::optional<int32_t> reply, QueryID queryID) =0;
@ -94,7 +95,7 @@ public:
virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0; virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0;
virtual void endTurn()=0; virtual void endTurn()=0;
virtual void buyArtifact(const CGHeroInstance *hero, ArtifactID aid)=0; //used to buy artifacts in towns (including spell book in the guild and war machines in blacksmith) virtual void buyArtifact(const CGHeroInstance *hero, ArtifactID aid)=0; //used to buy artifacts in towns (including spell book in the guild and war machines in blacksmith)
virtual void setFormation(const CGHeroInstance * hero, bool tight)=0; virtual void setFormation(const CGHeroInstance * hero, EArmyFormation mode)=0;
virtual void save(const std::string &fname) = 0; virtual void save(const std::string &fname) = 0;
virtual void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) = 0; virtual void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) = 0;
@ -181,9 +182,9 @@ public:
void endTurn() override; void endTurn() override;
void swapGarrisonHero(const CGTownInstance *town) override; void swapGarrisonHero(const CGTownInstance *town) override;
void buyArtifact(const CGHeroInstance *hero, ArtifactID aid) override; void buyArtifact(const CGHeroInstance *hero, ArtifactID aid) override;
void trade(const IMarket * market, EMarketMode mode, ui32 id1, ui32 id2, ui32 val1, const CGHeroInstance * hero = nullptr) override; void trade(const IMarket * market, EMarketMode mode, TradeItemSell id1, TradeItemBuy id2, ui32 val1, const CGHeroInstance * hero = nullptr) override;
void trade(const IMarket * market, EMarketMode mode, const std::vector<ui32> & id1, const std::vector<ui32> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override; void trade(const IMarket * market, EMarketMode mode, const std::vector<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override;
void setFormation(const CGHeroInstance * hero, bool tight) override; void setFormation(const CGHeroInstance * hero, EArmyFormation mode) override;
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero) override; void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero) override;
void save(const std::string &fname) override; void save(const std::string &fname) override;
void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) override; void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) override;

View File

@ -162,7 +162,7 @@ public:
void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> & spells) override {}; void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> & spells) override {};
bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override {return false;}; bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override {return false;};
void createObject(const int3 & visitablePosition, const PlayerColor & initiator, Obj type, int32_t subtype ) override {}; void createObject(const int3 & visitablePosition, const PlayerColor & initiator, MapObjectID type, MapObjectSubID subtype) override {};
void setOwner(const CGObjectInstance * obj, PlayerColor owner) override {}; void setOwner(const CGObjectInstance * obj, PlayerColor owner) override {};
void changePrimSkill(const CGHeroInstance * hero, PrimarySkill which, si64 val, bool abs = false) override {}; void changePrimSkill(const CGHeroInstance * hero, PrimarySkill which, si64 val, bool abs = false) override {};
void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs = false) override {}; void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs = false) override {};
@ -212,7 +212,8 @@ public:
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, ETileVisibility mode) override {} void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, ETileVisibility mode) override {}
void changeFogOfWar(std::unordered_set<int3> & tiles, PlayerColor player, ETileVisibility mode) override {} void changeFogOfWar(std::unordered_set<int3> & tiles, PlayerColor player, ETileVisibility mode) override {}
void setObjProperty(ObjectInstanceID objid, int prop, si64 val) override {} void setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value) override {};
void setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, ObjPropertyID identifier) override {};
void showInfoDialog(InfoWindow * iw) override {}; void showInfoDialog(InfoWindow * iw) override {};
void showInfoDialog(const std::string & msg, PlayerColor player) override {}; void showInfoDialog(const std::string & msg, PlayerColor player) override {};

View File

@ -350,15 +350,16 @@ void ApplyClientNetPackVisitor::visitGiveBonus(GiveBonus & pack)
cl.invalidatePaths(); cl.invalidatePaths();
switch(pack.who) switch(pack.who)
{ {
case GiveBonus::ETarget::HERO: case GiveBonus::ETarget::OBJECT:
{ {
const CGHeroInstance *h = gs.getHero(ObjectInstanceID(pack.id)); const CGHeroInstance *h = gs.getHero(pack.id.as<ObjectInstanceID>());
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, true); if (h)
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, true);
} }
break; break;
case GiveBonus::ETarget::PLAYER: case GiveBonus::ETarget::PLAYER:
{ {
callInterfaceIfPresent(cl, PlayerColor(pack.id), &IGameEventsReceiver::playerBonusChanged, pack.bonus, true); callInterfaceIfPresent(cl, pack.id.as<PlayerColor>(), &IGameEventsReceiver::playerBonusChanged, pack.bonus, true);
} }
break; break;
} }
@ -433,16 +434,17 @@ void ApplyClientNetPackVisitor::visitRemoveBonus(RemoveBonus & pack)
cl.invalidatePaths(); cl.invalidatePaths();
switch(pack.who) switch(pack.who)
{ {
case GiveBonus::ETarget::HERO: case GiveBonus::ETarget::OBJECT:
{ {
const CGHeroInstance *h = gs.getHero(ObjectInstanceID(pack.whoID)); const CGHeroInstance *h = gs.getHero(pack.whoID.as<ObjectInstanceID>());
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, false); if (h)
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, false);
} }
break; break;
case GiveBonus::ETarget::PLAYER: case GiveBonus::ETarget::PLAYER:
{ {
//const PlayerState *p = gs.getPlayerState(pack.id); //const PlayerState *p = gs.getPlayerState(pack.id);
callInterfaceIfPresent(cl, PlayerColor(pack.whoID), &IGameEventsReceiver::playerBonusChanged, pack.bonus, false); callInterfaceIfPresent(cl, pack.whoID.as<PlayerColor>(), &IGameEventsReceiver::playerBonusChanged, pack.bonus, false);
} }
break; break;
} }

View File

@ -99,14 +99,15 @@ TExpType CAltarArtifacts::calcExpAltarForHero()
void CAltarArtifacts::makeDeal() void CAltarArtifacts::makeDeal()
{ {
std::vector<ui32> positions; std::vector<TradeItemSell> positions;
for(const auto art : arts->artifactsOnAltar) for(const auto art : arts->artifactsOnAltar)
{ {
positions.push_back(hero->getSlotByInstance(art)); positions.push_back(hero->getSlotByInstance(art));
} }
std::sort(positions.begin(), positions.end(), std::greater<>()); std::sort(positions.begin(), positions.end());
std::reverse(positions.begin(), positions.end());
LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_EXP, positions, {}, {}, hero); LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_EXP, positions, std::vector<TradeItemBuy>(), std::vector<ui32>(), hero);
arts->artifactsOnAltar.clear(); arts->artifactsOnAltar.clear();
for(auto item : items[0]) for(auto item : items[0])
@ -374,14 +375,14 @@ void CAltarCreatures::makeDeal()
unitsSlider->scrollTo(0); unitsSlider->scrollTo(0);
expForHero->setText(std::to_string(0)); expForHero->setText(std::to_string(0));
std::vector<ui32> ids; std::vector<TradeItemSell> ids;
std::vector<ui32> toSacrifice; std::vector<ui32> toSacrifice;
for(int i = 0; i < unitsOnAltar.size(); i++) for(int i = 0; i < unitsOnAltar.size(); i++)
{ {
if(unitsOnAltar[i]) if(unitsOnAltar[i])
{ {
ids.push_back(i); ids.push_back(SlotID(i));
toSacrifice.push_back(unitsOnAltar[i]); toSacrifice.push_back(unitsOnAltar[i]);
} }
} }

View File

@ -306,7 +306,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
formations->resetCallback(); formations->resetCallback();
//setting formations //setting formations
formations->setSelected(curHero->formation == EArmyFormation::TIGHT ? 1 : 0); formations->setSelected(curHero->formation == EArmyFormation::TIGHT ? 1 : 0);
formations->addCallback([=](int value){ LOCPLINT->cb->setFormation(curHero, value);}); formations->addCallback([=](int value){ LOCPLINT->cb->setFormation(curHero, static_cast<EArmyFormation>(value));});
morale->set(curHero); morale->set(curHero);
luck->set(curHero); luck->set(curHero);

View File

@ -503,14 +503,27 @@ void CMarketplaceWindow::makeDeal()
if(allowDeal) if(allowDeal)
{ {
if(slider) switch(mode)
{ {
LOCPLINT->cb->trade(market, mode, leftIdToSend, hRight->id, slider->getValue() * r1, hero); case EMarketMode::RESOURCE_RESOURCE:
LOCPLINT->cb->trade(market, mode, GameResID(leftIdToSend), GameResID(hRight->id), slider->getValue() * r1, hero);
slider->scrollTo(0); slider->scrollTo(0);
} break;
else case EMarketMode::CREATURE_RESOURCE:
{ LOCPLINT->cb->trade(market, mode, SlotID(leftIdToSend), GameResID(hRight->id), slider->getValue() * r1, hero);
LOCPLINT->cb->trade(market, mode, leftIdToSend, hRight->id, r2, hero); slider->scrollTo(0);
break;
case EMarketMode::RESOURCE_PLAYER:
LOCPLINT->cb->trade(market, mode, GameResID(leftIdToSend), PlayerColor(hRight->id), slider->getValue() * r1, hero);
slider->scrollTo(0);
break;
case EMarketMode::RESOURCE_ARTIFACT:
LOCPLINT->cb->trade(market, mode, GameResID(leftIdToSend), ArtifactID(hRight->id), r2, hero);
break;
case EMarketMode::ARTIFACT_RESOURCE:
LOCPLINT->cb->trade(market, mode, ArtifactInstanceID(leftIdToSend), GameResID(hRight->id), r2, hero);
break;
} }
} }

View File

@ -988,7 +988,7 @@ void CTransformerWindow::makeDeal()
for(auto & elem : items) for(auto & elem : items)
{ {
if(!elem->left) if(!elem->left)
LOCPLINT->cb->trade(market, EMarketMode::CREATURE_UNDEAD, elem->id, 0, 0, hero); LOCPLINT->cb->trade(market, EMarketMode::CREATURE_UNDEAD, SlotID(elem->id), {}, {}, hero);
} }
} }
@ -1163,13 +1163,13 @@ void CUniversityWindow::close()
CStatusbarWindow::close(); CStatusbarWindow::close();
} }
void CUniversityWindow::makeDeal(int skill) void CUniversityWindow::makeDeal(SecondarySkill skill)
{ {
LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_SKILL, 6, skill, 1, hero); LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_SKILL, GameResID(GameResID::GOLD), skill, 1, hero);
} }
CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, int SKILL, bool available) CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, SecondarySkill SKILL, bool available)
: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("UNIVERS2.PCX")), : CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("UNIVERS2.PCX")),
owner(owner_) owner(owner_)
{ {
@ -1204,7 +1204,7 @@ CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * owner_, int SKILL, bo
statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
} }
void CUnivConfirmWindow::makeDeal(int skill) void CUnivConfirmWindow::makeDeal(SecondarySkill skill)
{ {
owner->makeDeal(skill); owner->makeDeal(skill);
close(); close();

View File

@ -403,7 +403,7 @@ class CUniversityWindow : public CStatusbarWindow
public: public:
CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market, const std::function<void()> & onWindowClosed); CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market, const std::function<void()> & onWindowClosed);
void makeDeal(int skill); void makeDeal(SecondarySkill skill);
void close(); void close();
}; };
@ -422,10 +422,10 @@ class CUnivConfirmWindow : public CStatusbarWindow
std::shared_ptr<CAnimImage> costIcon; std::shared_ptr<CAnimImage> costIcon;
std::shared_ptr<CLabel> cost; std::shared_ptr<CLabel> cost;
void makeDeal(int skill); void makeDeal(SecondarySkill skill);
public: public:
CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bool available); CUnivConfirmWindow(CUniversityWindow * PARENT, SecondarySkill SKILL, bool available);
}; };
/// Garrison window where you can take creatures out of the hero to place it on the garrison /// Garrison window where you can take creatures out of the hero to place it on the garrison

View File

@ -484,12 +484,14 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/networkPacks/EOpenWindowMode.h ${MAIN_LIB_DIR}/networkPacks/EOpenWindowMode.h
${MAIN_LIB_DIR}/networkPacks/NetPacksBase.h ${MAIN_LIB_DIR}/networkPacks/NetPacksBase.h
${MAIN_LIB_DIR}/networkPacks/NetPackVisitor.h ${MAIN_LIB_DIR}/networkPacks/NetPackVisitor.h
${MAIN_LIB_DIR}/networkPacks/ObjProperty.h
${MAIN_LIB_DIR}/networkPacks/PacksForClient.h ${MAIN_LIB_DIR}/networkPacks/PacksForClient.h
${MAIN_LIB_DIR}/networkPacks/PacksForClientBattle.h ${MAIN_LIB_DIR}/networkPacks/PacksForClientBattle.h
${MAIN_LIB_DIR}/networkPacks/PacksForLobby.h ${MAIN_LIB_DIR}/networkPacks/PacksForLobby.h
${MAIN_LIB_DIR}/networkPacks/PacksForServer.h ${MAIN_LIB_DIR}/networkPacks/PacksForServer.h
${MAIN_LIB_DIR}/networkPacks/SetStackEffect.h ${MAIN_LIB_DIR}/networkPacks/SetStackEffect.h
${MAIN_LIB_DIR}/networkPacks/StackLocation.h ${MAIN_LIB_DIR}/networkPacks/StackLocation.h
${MAIN_LIB_DIR}/networkPacks/TradeItem.h
${MAIN_LIB_DIR}/pathfinder/INodeStorage.h ${MAIN_LIB_DIR}/pathfinder/INodeStorage.h
${MAIN_LIB_DIR}/pathfinder/CGPathNode.h ${MAIN_LIB_DIR}/pathfinder/CGPathNode.h

View File

@ -415,12 +415,9 @@ int CCreatureSet::stacksCount() const
return static_cast<int>(stacks.size()); return static_cast<int>(stacks.size());
} }
void CCreatureSet::setFormation(bool tight) void CCreatureSet::setFormation(EArmyFormation mode)
{ {
if (tight) formation = mode;
formation = EArmyFormation::TIGHT;
else
formation = EArmyFormation::LOOSE;
} }
void CCreatureSet::setStackCount(const SlotID & slot, TQuantity count) void CCreatureSet::setStackCount(const SlotID & slot, TQuantity count)

View File

@ -203,12 +203,6 @@ public:
} }
}; };
enum class EArmyFormation : uint8_t
{
LOOSE,
TIGHT
};
namespace NArmyFormation namespace NArmyFormation
{ {
static const std::vector<std::string> names{ "wide", "tight" }; static const std::vector<std::string> names{ "wide", "tight" };
@ -235,7 +229,7 @@ public:
void addToSlot(const SlotID & slot, const CreatureID & cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature void addToSlot(const SlotID & slot, const CreatureID & cre, TQuantity count, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
void addToSlot(const SlotID & slot, CStackInstance * stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature void addToSlot(const SlotID & slot, CStackInstance * stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
void clearSlots() override; void clearSlots() override;
void setFormation(bool tight); void setFormation(EArmyFormation tight);
CArmedInstance *castToArmyObj(); CArmedInstance *castToArmyObj();
//basic operations //basic operations

View File

@ -13,6 +13,7 @@
#include "CGameInfoCallback.h" // for CGameInfoCallback #include "CGameInfoCallback.h" // for CGameInfoCallback
#include "CRandomGenerator.h" #include "CRandomGenerator.h"
#include "networkPacks/ObjProperty.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -73,14 +74,15 @@ public:
class DLL_LINKAGE IGameEventCallback class DLL_LINKAGE IGameEventCallback
{ {
public: public:
virtual void setObjProperty(ObjectInstanceID objid, int prop, si64 val) = 0; virtual void setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value = 0) = 0;
virtual void setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, ObjPropertyID identifier) = 0;
virtual void showInfoDialog(InfoWindow * iw) = 0; virtual void showInfoDialog(InfoWindow * iw) = 0;
virtual void showInfoDialog(const std::string & msg, PlayerColor player) = 0; virtual void showInfoDialog(const std::string & msg, PlayerColor player) = 0;
virtual void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells)=0; virtual void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells)=0;
virtual bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) = 0; virtual bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) = 0;
virtual void createObject(const int3 & visitablePosition, const PlayerColor & initiator, Obj type, int32_t subtype = 0) = 0; virtual void createObject(const int3 & visitablePosition, const PlayerColor & initiator, MapObjectID type, MapObjectSubID subtype) = 0;
virtual void setOwner(const CGObjectInstance * objid, PlayerColor owner)=0; virtual void setOwner(const CGObjectInstance * objid, PlayerColor owner)=0;
virtual void changePrimSkill(const CGHeroInstance * hero, PrimarySkill which, si64 val, bool abs=false)=0; virtual void changePrimSkill(const CGHeroInstance * hero, PrimarySkill which, si64 val, bool abs=false)=0;
virtual void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false)=0; virtual void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false)=0;

View File

@ -246,4 +246,10 @@ enum class ETileVisibility : int8_t // Fog of war change
REVEALED REVEALED
}; };
enum class EArmyFormation : int8_t
{
LOOSE,
TIGHT
};
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -13,7 +13,7 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
/// This class represents field that may contain value of multiple different identifer types /// This class represents field that may contain value of multiple different identifier types
template<typename... Types> template<typename... Types>
class VariantIdentifier class VariantIdentifier
{ {

View File

@ -94,12 +94,12 @@ void CBank::setConfig(const BankConfig & config)
setCreature (SlotID(stacksCount()), stack.type->getId(), stack.count); setCreature (SlotID(stacksCount()), stack.type->getId(), stack.count);
} }
void CBank::setPropertyDer (ui8 what, ui32 val) void CBank::setPropertyDer (ObjProperty what, ObjPropertyID identifier)
{ {
switch (what) switch (what)
{ {
case ObjProperty::BANK_DAYCOUNTER: //daycounter case ObjProperty::BANK_DAYCOUNTER: //daycounter
daycounter+=val; daycounter+= identifier.getNum();
break; break;
case ObjProperty::BANK_RESET: case ObjProperty::BANK_RESET:
// FIXME: Object reset must be done by separate netpack from server // FIXME: Object reset must be done by separate netpack from server
@ -119,9 +119,9 @@ void CBank::newTurn(CRandomGenerator & rand) const
if (resetDuration != 0) if (resetDuration != 0)
{ {
if (daycounter >= resetDuration) if (daycounter >= resetDuration)
cb->setObjProperty (id, ObjProperty::BANK_RESET, 0); //daycounter 0 cb->setObjPropertyValue(id, ObjProperty::BANK_RESET); //daycounter 0
else else
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 1); //daycounter++ cb->setObjPropertyValue(id, ObjProperty::BANK_DAYCOUNTER, 1); //daycounter++
} }
} }
} }
@ -210,7 +210,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
case Obj::CRYPT: case Obj::CRYPT:
{ {
GiveBonus gbonus; GiveBonus gbonus;
gbonus.id = hero->id.getNum(); gbonus.id = hero->id;
gbonus.bonus.duration = BonusDuration::ONE_BATTLE; gbonus.bonus.duration = BonusDuration::ONE_BATTLE;
gbonus.bonus.source = BonusSource::OBJECT_TYPE; gbonus.bonus.source = BonusSource::OBJECT_TYPE;
gbonus.bonus.sid = BonusSourceID(ID); gbonus.bonus.sid = BonusSourceID(ID);
@ -240,7 +240,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
{ {
GiveBonus gb; GiveBonus gb;
gb.bonus = Bonus(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT_INSTANCE, -2, BonusSourceID(id), VLC->generaltexth->arraytxt[70]); gb.bonus = Bonus(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT_INSTANCE, -2, BonusSourceID(id), VLC->generaltexth->arraytxt[70]);
gb.id = hero->id.getNum(); gb.id = hero->id;
cb->giveHeroBonus(&gb); cb->giveHeroBonus(&gb);
textID = 107; textID = 107;
iw.components.emplace_back(ComponentType::LUCK, -2); iw.components.emplace_back(ComponentType::LUCK, -2);
@ -369,7 +369,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
cb->giveCreatures(this, hero, ourArmy, false); cb->giveCreatures(this, hero, ourArmy, false);
} }
cb->setObjProperty(id, ObjProperty::BANK_CLEAR, 0); //bc = nullptr cb->setObjPropertyValue(id, ObjProperty::BANK_CLEAR); //bc = nullptr
} }
} }

View File

@ -23,7 +23,7 @@ class DLL_LINKAGE CBank : public CArmedInstance
ui32 resetDuration; ui32 resetDuration;
bool coastVisitable; bool coastVisitable;
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void doVisit(const CGHeroInstance * hero) const; void doVisit(const CGHeroInstance * hero) const;
public: public:

View File

@ -266,31 +266,28 @@ void CGCreature::newTurn(CRandomGenerator & rand) const
if (stacks.begin()->second->count < VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP) && cb->getDate(Date::DAY_OF_WEEK) == 1 && cb->getDate(Date::DAY) > 1) if (stacks.begin()->second->count < VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP) && cb->getDate(Date::DAY_OF_WEEK) == 1 && cb->getDate(Date::DAY) > 1)
{ {
ui32 power = static_cast<ui32>(temppower * (100 + VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT)) / 100); ui32 power = static_cast<ui32>(temppower * (100 + VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_PERCENT)) / 100);
cb->setObjProperty(id, ObjProperty::MONSTER_COUNT, std::min<uint32_t>(power / 1000, VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP))); //set new amount cb->setObjPropertyValue(id, ObjProperty::MONSTER_COUNT, std::min<uint32_t>(power / 1000, VLC->settings()->getInteger(EGameSettings::CREATURES_WEEKLY_GROWTH_CAP))); //set new amount
cb->setObjProperty(id, ObjProperty::MONSTER_POWER, power); //increase temppower cb->setObjPropertyValue(id, ObjProperty::MONSTER_POWER, power); //increase temppower
} }
} }
if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) if (VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
cb->setObjProperty(id, ObjProperty::MONSTER_EXP, VLC->settings()->getInteger(EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE)); //for testing purpose cb->setObjPropertyValue(id, ObjProperty::MONSTER_EXP, VLC->settings()->getInteger(EGameSettings::CREATURES_DAILY_STACK_EXPERIENCE)); //for testing purpose
} }
void CGCreature::setPropertyDer(ui8 what, ui32 val) void CGCreature::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{ {
switch (what) switch (what)
{ {
case ObjProperty::MONSTER_COUNT: case ObjProperty::MONSTER_COUNT:
stacks[SlotID(0)]->count = val; stacks[SlotID(0)]->count = identifier.getNum();
break; break;
case ObjProperty::MONSTER_POWER: case ObjProperty::MONSTER_POWER:
temppower = val; temppower = identifier.getNum();
break; break;
case ObjProperty::MONSTER_EXP: case ObjProperty::MONSTER_EXP:
giveStackExp(val); giveStackExp(identifier.getNum());
break;
case ObjProperty::MONSTER_RESTORE_TYPE:
formation.basicType = val;
break; break;
case ObjProperty::MONSTER_REFUSED_JOIN: case ObjProperty::MONSTER_REFUSED_JOIN:
refusedJoining = val; refusedJoining = identifier.getNum();
break; break;
} }
} }
@ -368,7 +365,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
void CGCreature::fleeDecision(const CGHeroInstance *h, ui32 pursue) const void CGCreature::fleeDecision(const CGHeroInstance *h, ui32 pursue) const
{ {
if(refusedJoining) if(refusedJoining)
cb->setObjProperty(id, ObjProperty::MONSTER_REFUSED_JOIN, false); cb->setObjPropertyValue(id, ObjProperty::MONSTER_REFUSED_JOIN, false);
if(pursue) if(pursue)
{ {
@ -386,7 +383,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
{ {
if(takenAction(h,false) == FLEE) if(takenAction(h,false) == FLEE)
{ {
cb->setObjProperty(id, ObjProperty::MONSTER_REFUSED_JOIN, true); cb->setObjPropertyValue(id, ObjProperty::MONSTER_REFUSED_JOIN, true);
flee(h); flee(h);
} }
else //they fight else //they fight
@ -421,10 +418,6 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
void CGCreature::fight( const CGHeroInstance *h ) const void CGCreature::fight( const CGHeroInstance *h ) const
{ {
//split stacks //split stacks
//TODO: multiple creature types in a stack?
int basicType = stacks.begin()->second->type->getId();
cb->setObjProperty(id, ObjProperty::MONSTER_RESTORE_TYPE, basicType); //store info about creature stack
int stacksCount = getNumberOfStacks(h); int stacksCount = getNumberOfStacks(h);
//source: http://heroescommunity.com/viewthread.php3?TID=27539&PID=1266335#focus //source: http://heroescommunity.com/viewthread.php3?TID=27539&PID=1266335#focus
@ -488,7 +481,7 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult &
{ {
//merge stacks into one //merge stacks into one
TSlots::const_iterator i; TSlots::const_iterator i;
CCreature * cre = VLC->creh->objects[formation.basicType]; const CCreature * cre = getCreature().toCreature();
for(i = stacks.begin(); i != stacks.end(); i++) for(i = stacks.begin(); i != stacks.end(); i++)
{ {
if(cre->isMyUpgrade(i->second->type)) if(cre->isMyUpgrade(i->second->type))
@ -513,7 +506,7 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult &
cb->moveStack(StackLocation(this, i->first), StackLocation(this, slot), i->second->count); cb->moveStack(StackLocation(this, i->first), StackLocation(this, slot), i->second->count);
} }
cb->setObjProperty(id, ObjProperty::MONSTER_POWER, stacks.begin()->second->count * 1000); //remember casualties cb->setObjPropertyValue(id, ObjProperty::MONSTER_POWER, stacks.begin()->second->count * 1000); //remember casualties
} }
} }

View File

@ -54,17 +54,6 @@ public:
bool containsUpgradedStack() const; bool containsUpgradedStack() const;
int getNumberOfStacks(const CGHeroInstance *hero) const; int getNumberOfStacks(const CGHeroInstance *hero) const;
struct DLL_LINKAGE formationInfo // info about merging stacks after battle back into one
{
si32 basicType;
ui8 upgrade; //random seed used to determine number of stacks and is there's upgraded stack
template <typename Handler> void serialize(Handler &h, const int version)
{
h & basicType;
h & upgrade;
}
} formation;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & static_cast<CArmedInstance&>(*this); h & static_cast<CArmedInstance&>(*this);
@ -80,7 +69,7 @@ public:
h & formation; h & formation;
} }
protected: protected:
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
private: private:

View File

@ -201,7 +201,7 @@ void CGDwelling::initObj(CRandomGenerator & rand)
} }
} }
void CGDwelling::setPropertyDer(ui8 what, ui32 val) void CGDwelling::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{ {
switch (what) switch (what)
{ {
@ -214,14 +214,14 @@ void CGDwelling::setPropertyDer(ui8 what, ui32 val)
std::vector<ConstTransitivePtr<CGDwelling> >* dwellings = &cb->gameState()->players[tempOwner].dwellings; std::vector<ConstTransitivePtr<CGDwelling> >* dwellings = &cb->gameState()->players[tempOwner].dwellings;
dwellings->erase (std::find(dwellings->begin(), dwellings->end(), this)); dwellings->erase (std::find(dwellings->begin(), dwellings->end(), this));
} }
if (PlayerColor(val) != PlayerColor::NEUTRAL) //can new owner be neutral? if (identifier.as<PlayerColor>().isValidPlayer())
cb->gameState()->players[PlayerColor(val)].dwellings.emplace_back(this); cb->gameState()->players[identifier.as<PlayerColor>()].dwellings.emplace_back(this);
} }
break; break;
case ObjProperty::AVAILABLE_CREATURE: case ObjProperty::AVAILABLE_CREATURE:
creatures.resize(1); creatures.resize(1);
creatures[0].second.resize(1); creatures[0].second.resize(1);
creatures[0].second[0] = CreatureID(val); creatures[0].second[0] = identifier.as<CreatureID>();
break; break;
} }
} }
@ -300,7 +300,7 @@ void CGDwelling::newTurn(CRandomGenerator & rand) const
if(ID == Obj::REFUGEE_CAMP) //if it's a refugee camp, we need to pick an available creature if(ID == Obj::REFUGEE_CAMP) //if it's a refugee camp, we need to pick an available creature
{ {
cb->setObjProperty(id, ObjProperty::AVAILABLE_CREATURE, VLC->creh->pickRandomMonster(rand)); cb->setObjPropertyID(id, ObjProperty::AVAILABLE_CREATURE, VLC->creh->pickRandomMonster(rand));
} }
bool change = false; bool change = false;

View File

@ -52,7 +52,7 @@ private:
void initObj(CRandomGenerator & rand) override; void initObj(CRandomGenerator & rand) override;
void onHeroVisit(const CGHeroInstance * h) const override; void onHeroVisit(const CGHeroInstance * h) const override;
void newTurn(CRandomGenerator & rand) const override; void newTurn(CRandomGenerator & rand) const override;
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
std::vector<Component> getPopupComponents(PlayerColor player) const override; std::vector<Component> getPopupComponents(PlayerColor player) const override;

View File

@ -348,7 +348,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
if (gender == EHeroGender::DEFAULT) if (gender == EHeroGender::DEFAULT)
gender = type->gender; gender = type->gender;
setFormation(false); setFormation(EArmyFormation::LOOSE);
if (!stacksCount()) //standard army//initial army if (!stacksCount()) //standard army//initial army
{ {
initArmy(rand); initArmy(rand);
@ -501,7 +501,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
SetMovePoints smp; SetMovePoints smp;
smp.hid = id; smp.hid = id;
cb->setManaPoints (id, manaLimit()); cb->setManaPoints (id, manaLimit());
ObjectInstanceID boatId; ObjectInstanceID boatId;
const auto boatPos = visitablePos(); const auto boatPos = visitablePos();
@ -520,7 +520,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
smp.val = movementPointsLimit(true); smp.val = movementPointsLimit(true);
} }
cb->giveHero(id, h->tempOwner, boatId); //recreates def and adds hero to player cb->giveHero(id, h->tempOwner, boatId); //recreates def and adds hero to player
cb->setObjProperty(id, ObjProperty::ID, Obj::HERO); //set ID to 34 AFTER hero gets correct flag color cb->setObjPropertyID(id, ObjProperty::ID, Obj(Obj::HERO)); //set ID to 34 AFTER hero gets correct flag color
cb->setMovePoints (&smp); cb->setMovePoints (&smp);
h->showInfoDialog(102); h->showInfoDialog(102);
@ -620,10 +620,10 @@ void CGHeroInstance::updateSkillBonus(const SecondarySkill & which, int val)
addNewBonus(std::make_shared<Bonus>(*b)); addNewBonus(std::make_shared<Bonus>(*b));
} }
void CGHeroInstance::setPropertyDer( ui8 what, ui32 val ) void CGHeroInstance::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{ {
if(what == ObjProperty::PRIMARY_STACK_COUNT) if(what == ObjProperty::PRIMARY_STACK_COUNT)
setStackCount(SlotID(0), val); setStackCount(SlotID(0), identifier.getNum());
} }
double CGHeroInstance::getFightingStrength() const double CGHeroInstance::getFightingStrength() const

View File

@ -307,7 +307,7 @@ public:
bool isCoastVisitable() const override; bool isCoastVisitable() const override;
BattleField getBattlefield() const override; BattleField getBattlefield() const override;
protected: protected:
void setPropertyDer(ui8 what, ui32 val) override;//synchr void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;//synchr
///common part of hero instance and hero definition ///common part of hero instance and hero definition
void serializeCommonOptions(JsonSerializeFormat & handler); void serializeCommonOptions(JsonSerializeFormat & handler);

View File

@ -91,7 +91,7 @@ void CGBlackMarket::newTurn(CRandomGenerator & rand) const
return; return;
SetAvailableArtifacts saa; SetAvailableArtifacts saa;
saa.id = id.getNum(); saa.id = id;
cb->pickAllowedArtsSet(saa.arts, rand); cb->pickAllowedArtsSet(saa.arts, rand);
cb->sendAndApply(&saa); cb->sendAndApply(&saa);
} }

View File

@ -181,23 +181,20 @@ void CGObjectInstance::initObj(CRandomGenerator & rand)
} }
} }
void CGObjectInstance::setProperty( ui8 what, ui32 val ) void CGObjectInstance::setProperty( ObjProperty what, ObjPropertyID identifier )
{ {
setPropertyDer(what, val); // call this before any actual changes (needed at least for dwellings) setPropertyDer(what, identifier); // call this before any actual changes (needed at least for dwellings)
switch(what) switch(what)
{ {
case ObjProperty::OWNER: case ObjProperty::OWNER:
tempOwner = PlayerColor(val); tempOwner = identifier.as<PlayerColor>();
break; break;
case ObjProperty::BLOCKVIS: case ObjProperty::BLOCKVIS:
blockVisit = val; blockVisit = identifier.getNum();
break; break;
case ObjProperty::ID: case ObjProperty::ID:
ID = Obj(val); ID = identifier.as<MapObjectID>();
break;
case ObjProperty::SUBID:
subID = val;
break; break;
} }
} }
@ -207,7 +204,7 @@ TObjectTypeHandler CGObjectInstance::getObjectHandler() const
return VLC->objtypeh->getHandlerFor(ID, subID); return VLC->objtypeh->getHandlerFor(ID, subID);
} }
void CGObjectInstance::setPropertyDer( ui8 what, ui32 val ) void CGObjectInstance::setPropertyDer( ObjProperty what, ObjPropertyID identifier )
{} {}
int3 CGObjectInstance::getSightCenter() const int3 CGObjectInstance::getSightCenter() const
@ -229,7 +226,7 @@ void CGObjectInstance::giveDummyBonus(const ObjectInstanceID & heroID, BonusDura
{ {
GiveBonus gbonus; GiveBonus gbonus;
gbonus.bonus.type = BonusType::NONE; gbonus.bonus.type = BonusType::NONE;
gbonus.id = heroID.getNum(); gbonus.id = heroID;
gbonus.bonus.duration = duration; gbonus.bonus.duration = duration;
gbonus.bonus.source = BonusSource::OBJECT_TYPE; gbonus.bonus.source = BonusSource::OBJECT_TYPE;
gbonus.bonus.sid = BonusSourceID(ID); gbonus.bonus.sid = BonusSourceID(ID);

View File

@ -127,7 +127,7 @@ public:
void pickRandomObject(CRandomGenerator & rand) override; void pickRandomObject(CRandomGenerator & rand) override;
void onHeroVisit(const CGHeroInstance * h) const override; void onHeroVisit(const CGHeroInstance * h) const override;
/// method for synchronous update. Note: For new properties classes should override setPropertyDer instead /// method for synchronous update. Note: For new properties classes should override setPropertyDer instead
void setProperty(ui8 what, ui32 val) final; void setProperty(ObjProperty what, ObjPropertyID identifier) final;
virtual void afterAddToMap(CMap * map); virtual void afterAddToMap(CMap * map);
virtual void afterRemoveFromMap(CMap * map); virtual void afterRemoveFromMap(CMap * map);
@ -154,7 +154,7 @@ public:
protected: protected:
/// virtual method that allows synchronously update object state on server and all clients /// virtual method that allows synchronously update object state on server and all clients
virtual void setPropertyDer(ui8 what, ui32 val); virtual void setPropertyDer(ObjProperty what, ObjPropertyID identifier);
/// Called mostly during map randomization to turn random object into a regular one (e.g. "Random Monster" into "Pikeman") /// Called mostly during map randomization to turn random object into a regular one (e.g. "Random Monster" into "Pikeman")
void setType(MapObjectID ID, MapObjectSubID subID); void setType(MapObjectID ID, MapObjectSubID subID);

View File

@ -120,12 +120,12 @@ COPWBonus::COPWBonus(const BuildingID & bid, BuildingSubID::EBuildingSubID subId
indexOnTV = static_cast<si32>(town->bonusingBuildings.size()); indexOnTV = static_cast<si32>(town->bonusingBuildings.size());
} }
void COPWBonus::setProperty(ui8 what, ui32 val) void COPWBonus::setProperty(ObjProperty what, ObjPropertyID identifier)
{ {
switch (what) switch (what)
{ {
case ObjProperty::VISITORS: case ObjProperty::VISITORS:
visitors.insert(val); visitors.insert(identifier.as<ObjectInstanceID>());
break; break;
case ObjProperty::STRUCTURE_CLEAR_VISITORS: case ObjProperty::STRUCTURE_CLEAR_VISITORS:
visitors.clear(); visitors.clear();
@ -148,7 +148,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
{ {
GiveBonus gb; GiveBonus gb;
gb.bonus = Bonus(BonusDuration::ONE_WEEK, BonusType::MOVEMENT, BonusSource::OBJECT_TYPE, 600, BonusSourceID(Obj(Obj::STABLES)), BonusCustomSubtype::heroMovementLand, VLC->generaltexth->arraytxt[100]); gb.bonus = Bonus(BonusDuration::ONE_WEEK, BonusType::MOVEMENT, BonusSource::OBJECT_TYPE, 600, BonusSourceID(Obj(Obj::STABLES)), BonusCustomSubtype::heroMovementLand, VLC->generaltexth->arraytxt[100]);
gb.id = heroID.getNum(); gb.id = heroID;
cb->giveHeroBonus(&gb); cb->giveHeroBonus(&gb);
SetMovePoints mp; SetMovePoints mp;
@ -187,10 +187,10 @@ CTownBonus::CTownBonus(const BuildingID & index, BuildingSubID::EBuildingSubID s
indexOnTV = static_cast<si32>(town->bonusingBuildings.size()); indexOnTV = static_cast<si32>(town->bonusingBuildings.size());
} }
void CTownBonus::setProperty (ui8 what, ui32 val) void CTownBonus::setProperty(ObjProperty what, ObjPropertyID identifier)
{ {
if(what == ObjProperty::VISITORS) if(what == ObjProperty::VISITORS)
visitors.insert(ObjectInstanceID(val)); visitors.insert(identifier.as<ObjectInstanceID>());
} }
void CTownBonus::onHeroVisit (const CGHeroInstance * h) const void CTownBonus::onHeroVisit (const CGHeroInstance * h) const
@ -272,7 +272,7 @@ void CTownBonus::applyBonuses(CGHeroInstance * h, const BonusList & bonuses) con
bonus->duration = BonusDuration::ONE_DAY; bonus->duration = BonusDuration::ONE_DAY;
} }
gb.bonus = * bonus; gb.bonus = * bonus;
gb.id = h->id.getNum(); gb.id = h->id;
cb->giveHeroBonus(&gb); cb->giveHeroBonus(&gb);
if(bonus->duration == BonusDuration::PERMANENT) if(bonus->duration == BonusDuration::PERMANENT)
@ -318,21 +318,21 @@ void CTownRewardableBuilding::newTurn(CRandomGenerator & rand) const
{ {
if(configuration.resetParameters.rewards) if(configuration.resetParameters.rewards)
{ {
cb->setObjProperty(town->id, ObjProperty::REWARD_RANDOMIZE, indexOnTV); cb->setObjPropertyValue(town->id, ObjProperty::REWARD_RANDOMIZE, indexOnTV);
} }
if(configuration.resetParameters.visitors) if(configuration.resetParameters.visitors)
{ {
cb->setObjProperty(town->id, ObjProperty::STRUCTURE_CLEAR_VISITORS, indexOnTV); cb->setObjPropertyValue(town->id, ObjProperty::STRUCTURE_CLEAR_VISITORS, indexOnTV);
} }
} }
} }
void CTownRewardableBuilding::setProperty(ui8 what, ui32 val) void CTownRewardableBuilding::setProperty(ObjProperty what, ObjPropertyID identifier)
{ {
switch (what) switch (what)
{ {
case ObjProperty::VISITORS: case ObjProperty::VISITORS:
visitors.insert(ObjectInstanceID(val)); visitors.insert(identifier.as<ObjectInstanceID>());
break; break;
case ObjProperty::STRUCTURE_CLEAR_VISITORS: case ObjProperty::STRUCTURE_CLEAR_VISITORS:
visitors.clear(); visitors.clear();
@ -341,7 +341,7 @@ void CTownRewardableBuilding::setProperty(ui8 what, ui32 val)
initObj(cb->gameState()->getRandomGenerator()); initObj(cb->gameState()->getRandomGenerator());
break; break;
case ObjProperty::REWARD_SELECT: case ObjProperty::REWARD_SELECT:
selectedReward = val; selectedReward = identifier.getNum();
break; break;
} }
} }

View File

@ -69,8 +69,8 @@ protected:
class DLL_LINKAGE COPWBonus : public CGTownBuilding class DLL_LINKAGE COPWBonus : public CGTownBuilding
{///used for OPW bonusing structures {///used for OPW bonusing structures
public: public:
std::set<si32> visitors; std::set<ObjectInstanceID> visitors;
void setProperty(ui8 what, ui32 val) override; void setProperty(ObjProperty what, ObjPropertyID identifier) override;
void onHeroVisit (const CGHeroInstance * h) const override; void onHeroVisit (const CGHeroInstance * h) const override;
COPWBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN); COPWBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN);
@ -89,7 +89,7 @@ class DLL_LINKAGE CTownBonus : public CGTownBuilding
///feel free to merge inheritance tree ///feel free to merge inheritance tree
public: public:
std::set<ObjectInstanceID> visitors; std::set<ObjectInstanceID> visitors;
void setProperty(ui8 what, ui32 val) override; void setProperty(ObjProperty what, ObjPropertyID identifier) override;
void onHeroVisit (const CGHeroInstance * h) const override; void onHeroVisit (const CGHeroInstance * h) const override;
CTownBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN); CTownBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN);
@ -117,7 +117,7 @@ class DLL_LINKAGE CTownRewardableBuilding : public CGTownBuilding, public Reward
void grantReward(ui32 rewardID, const CGHeroInstance * hero) const; void grantReward(ui32 rewardID, const CGHeroInstance * hero) const;
public: public:
void setProperty(ui8 what, ui32 val) override; void setProperty(ObjProperty what, ObjPropertyID identifier) override;
void onHeroVisit(const CGHeroInstance * h) const override; void onHeroVisit(const CGHeroInstance * h) const override;
void newTurn(CRandomGenerator & rand) const override; void newTurn(CRandomGenerator & rand) const override;

View File

@ -53,28 +53,28 @@ int CGTownInstance::getSightRadius() const //returns sight distance
return ret; return ret;
} }
void CGTownInstance::setPropertyDer(ui8 what, ui32 val) void CGTownInstance::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{ {
///this is freakin' overcomplicated solution ///this is freakin' overcomplicated solution
switch (what) switch (what)
{ {
case ObjProperty::STRUCTURE_ADD_VISITING_HERO: case ObjProperty::STRUCTURE_ADD_VISITING_HERO:
bonusingBuildings[val]->setProperty(ObjProperty::VISITORS, visitingHero->id.getNum()); bonusingBuildings[identifier.getNum()]->setProperty(ObjProperty::VISITORS, visitingHero->id);
break; break;
case ObjProperty::STRUCTURE_CLEAR_VISITORS: case ObjProperty::STRUCTURE_CLEAR_VISITORS:
bonusingBuildings[val]->setProperty(ObjProperty::STRUCTURE_CLEAR_VISITORS, 0); bonusingBuildings[identifier.getNum()]->setProperty(ObjProperty::STRUCTURE_CLEAR_VISITORS, NumericID(0));
break; break;
case ObjProperty::STRUCTURE_ADD_GARRISONED_HERO: //add garrisoned hero to visitors case ObjProperty::STRUCTURE_ADD_GARRISONED_HERO: //add garrisoned hero to visitors
bonusingBuildings[val]->setProperty(ObjProperty::VISITORS, garrisonHero->id.getNum()); bonusingBuildings[identifier.getNum()]->setProperty(ObjProperty::VISITORS, garrisonHero->id);
break; break;
case ObjProperty::BONUS_VALUE_FIRST: case ObjProperty::BONUS_VALUE_FIRST:
bonusValue.first = val; bonusValue.first = identifier.getNum();
break; break;
case ObjProperty::BONUS_VALUE_SECOND: case ObjProperty::BONUS_VALUE_SECOND:
bonusValue.second = val; bonusValue.second = identifier.getNum();
break; break;
case ObjProperty::REWARD_RANDOMIZE: case ObjProperty::REWARD_RANDOMIZE:
bonusingBuildings[val]->setProperty(ObjProperty::REWARD_RANDOMIZE, 0); bonusingBuildings[identifier.getNum()]->setProperty(ObjProperty::REWARD_RANDOMIZE, NumericID(0));
break; break;
} }
} }
@ -534,12 +534,12 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
resID = (resID==2)?1:resID; resID = (resID==2)?1:resID;
int resVal = rand.nextInt(1, 4);//with size 1..4 int resVal = rand.nextInt(1, 4);//with size 1..4
cb->giveResource(tempOwner, static_cast<EGameResID>(resID), resVal); cb->giveResource(tempOwner, static_cast<EGameResID>(resID), resVal);
cb->setObjProperty (id, ObjProperty::BONUS_VALUE_FIRST, resID); cb->setObjPropertyValue(id, ObjProperty::BONUS_VALUE_FIRST, resID);
cb->setObjProperty (id, ObjProperty::BONUS_VALUE_SECOND, resVal); cb->setObjPropertyValue(id, ObjProperty::BONUS_VALUE_SECOND, resVal);
} }
for(const auto * manaVortex : getBonusingBuildings(BuildingSubID::MANA_VORTEX)) for(const auto * manaVortex : getBonusingBuildings(BuildingSubID::MANA_VORTEX))
cb->setObjProperty(id, ObjProperty::STRUCTURE_CLEAR_VISITORS, manaVortex->indexOnTV); //reset visitors for Mana Vortex cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_CLEAR_VISITORS, manaVortex->indexOnTV); //reset visitors for Mana Vortex
//get Mana Vortex or Stables bonuses //get Mana Vortex or Stables bonuses
//same code is in the CGameHandler::buildStructure method //same code is in the CGameHandler::buildStructure method
@ -1072,9 +1072,9 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID &
void CGTownInstance::addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID ) const void CGTownInstance::addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID ) const
{ {
if(visitingHero == h) if(visitingHero == h)
cb->setObjProperty(id, ObjProperty::STRUCTURE_ADD_VISITING_HERO, structureInstanceID); //add to visitors cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_VISITING_HERO, structureInstanceID); //add to visitors
else if(garrisonHero == h) else if(garrisonHero == h)
cb->setObjProperty(id, ObjProperty::STRUCTURE_ADD_GARRISONED_HERO, structureInstanceID); //then it must be garrisoned hero cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_GARRISONED_HERO, structureInstanceID); //then it must be garrisoned hero
else else
{ {
//should never ever happen //should never ever happen

View File

@ -211,7 +211,7 @@ public:
return defendingHero && garrisonHero && defendingHero != garrisonHero; return defendingHero && garrisonHero && defendingHero != garrisonHero;
} }
protected: protected:
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;

View File

@ -544,18 +544,18 @@ std::vector<Component> CGSeerHut::getPopupComponents(const CGHeroInstance * hero
return result; return result;
} }
void CGSeerHut::setPropertyDer(ui8 what, ui32 val) void CGSeerHut::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{ {
switch(what) switch(what)
{ {
case CGSeerHut::SEERHUT_VISITED: case ObjProperty::SEERHUT_VISITED:
{ {
quest->activeForPlayers.emplace(val); quest->activeForPlayers.emplace(identifier.as<PlayerColor>());
break; break;
} }
case CGSeerHut::SEERHUT_COMPLETE: case ObjProperty::SEERHUT_COMPLETE:
{ {
quest->isCompleted = val; quest->isCompleted = identifier.getNum();
quest->activeForPlayers.clear(); quest->activeForPlayers.clear();
break; break;
} }
@ -567,7 +567,7 @@ void CGSeerHut::newTurn(CRandomGenerator & rand) const
CRewardableObject::newTurn(rand); CRewardableObject::newTurn(rand);
if(quest->lastDay >= 0 && quest->lastDay <= cb->getDate() - 1) //time is up if(quest->lastDay >= 0 && quest->lastDay <= cb->getDate() - 1) //time is up
{ {
cb->setObjProperty (id, CGSeerHut::SEERHUT_COMPLETE, true); cb->setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, true);
} }
} }
@ -582,7 +582,7 @@ void CGSeerHut::onHeroVisit(const CGHeroInstance * h) const
if(firstVisit) if(firstVisit)
{ {
cb->setObjProperty(id, CGSeerHut::SEERHUT_VISITED, h->getOwner()); cb->setObjPropertyID(id, ObjProperty::SEERHUT_VISITED, h->getOwner());
AddQuest aq; AddQuest aq;
aq.quest = QuestInfo (quest, this, visitablePos()); aq.quest = QuestInfo (quest, this, visitablePos());
@ -665,7 +665,7 @@ void CGSeerHut::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
if(answer) if(answer)
{ {
quest->completeQuest(cb, hero); quest->completeQuest(cb, hero);
cb->setObjProperty(id, CGSeerHut::SEERHUT_COMPLETE, !quest->repeatedQuest); //mission complete cb->setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, !quest->repeatedQuest); //mission complete
} }
} }
@ -764,7 +764,7 @@ void CGQuestGuard::onHeroVisit(const CGHeroInstance * h) const
if(!quest->isCompleted) if(!quest->isCompleted)
CGSeerHut::onHeroVisit(h); CGSeerHut::onHeroVisit(h);
else else
cb->setObjProperty(id, CGSeerHut::SEERHUT_COMPLETE, false); cb->setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, false);
} }
bool CGQuestGuard::passableFor(PlayerColor color) const bool CGQuestGuard::passableFor(PlayerColor color) const
@ -783,15 +783,14 @@ void CGKeys::reset()
playerKeyMap.clear(); playerKeyMap.clear();
} }
void CGKeys::setPropertyDer (ui8 what, ui32 val) //101-108 - enable key for player 1-8 void CGKeys::setPropertyDer (ObjProperty what, ObjPropertyID identifier)
{ {
if (what >= 101 && what <= (100 + PlayerColor::PLAYER_LIMIT_I)) if (what == ObjProperty::KEYMASTER_VISITED)
{ {
PlayerColor player(what-101); playerKeyMap[identifier.as<PlayerColor>()].insert(subID);
playerKeyMap[player].insert(static_cast<ui8>(val));
} }
else else
logGlobal->error("Unexpected properties requested to set: what=%d, val=%d", static_cast<int>(what), val); logGlobal->error("Unexpected properties requested to set: what=%d, val=%d", static_cast<int>(what), identifier.getNum());
} }
bool CGKeys::wasMyColorVisited(const PlayerColor & player) const bool CGKeys::wasMyColorVisited(const PlayerColor & player) const
@ -819,7 +818,7 @@ void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
int txt_id; int txt_id;
if (!wasMyColorVisited (h->getOwner()) ) if (!wasMyColorVisited (h->getOwner()) )
{ {
cb->setObjProperty(id, h->tempOwner.getNum()+101, subID); cb->setObjPropertyID(id, ObjProperty::KEYMASTER_VISITED, h->tempOwner);
txt_id=19; txt_id=19;
} }
else else

View File

@ -144,10 +144,7 @@ public:
h & seerName; h & seerName;
} }
protected: protected:
static constexpr int SEERHUT_VISITED = 10; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
static constexpr int SEERHUT_COMPLETE = 11;
void setPropertyDer(ui8 what, ui32 val) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override; void serializeJsonOptions(JsonSerializeFormat & handler) override;
}; };
@ -186,7 +183,7 @@ public:
h & static_cast<CGObjectInstance&>(*this); h & static_cast<CGObjectInstance&>(*this);
} }
protected: protected:
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
}; };
class DLL_LINKAGE CGKeymasterTent : public CGKeys class DLL_LINKAGE CGKeymasterTent : public CGKeys

View File

@ -169,7 +169,7 @@ void CRewardableObject::blockingDialogAnswered(const CGHeroInstance *hero, ui32
void CRewardableObject::markAsVisited(const CGHeroInstance * hero) const void CRewardableObject::markAsVisited(const CGHeroInstance * hero) const
{ {
cb->setObjProperty(id, ObjProperty::REWARD_CLEARED, true); cb->setObjPropertyValue(id, ObjProperty::REWARD_CLEARED, true);
ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_ADD, id, hero->id); ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_ADD, id, hero->id);
cb->sendAndApply(&cov); cb->sendAndApply(&cov);
@ -177,7 +177,7 @@ void CRewardableObject::markAsVisited(const CGHeroInstance * hero) const
void CRewardableObject::grantReward(ui32 rewardID, const CGHeroInstance * hero) const void CRewardableObject::grantReward(ui32 rewardID, const CGHeroInstance * hero) const
{ {
cb->setObjProperty(id, ObjProperty::REWARD_SELECT, rewardID); cb->setObjPropertyValue(id, ObjProperty::REWARD_SELECT, rewardID);
grantRewardBeforeLevelup(cb, configuration.info.at(rewardID), hero); grantRewardBeforeLevelup(cb, configuration.info.at(rewardID), hero);
// hero is not blocked by levelup dialog - grant remainer immediately // hero is not blocked by levelup dialog - grant remainer immediately
@ -338,7 +338,7 @@ std::vector<Component> CRewardableObject::getPopupComponents(const CGHeroInstanc
return getPopupComponentsImpl(hero->getOwner(), hero); return getPopupComponentsImpl(hero->getOwner(), hero);
} }
void CRewardableObject::setPropertyDer(ui8 what, ui32 val) void CRewardableObject::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{ {
switch (what) switch (what)
{ {
@ -346,10 +346,10 @@ void CRewardableObject::setPropertyDer(ui8 what, ui32 val)
initObj(cb->gameState()->getRandomGenerator()); initObj(cb->gameState()->getRandomGenerator());
break; break;
case ObjProperty::REWARD_SELECT: case ObjProperty::REWARD_SELECT:
selectedReward = val; selectedReward = identifier.getNum();
break; break;
case ObjProperty::REWARD_CLEARED: case ObjProperty::REWARD_CLEARED:
onceVisitableObjectCleared = val; onceVisitableObjectCleared = identifier.getNum();
break; break;
} }
} }
@ -360,11 +360,11 @@ void CRewardableObject::newTurn(CRandomGenerator & rand) const
{ {
if (configuration.resetParameters.rewards) if (configuration.resetParameters.rewards)
{ {
cb->setObjProperty(id, ObjProperty::REWARD_RANDOMIZE, 0); cb->setObjPropertyValue(id, ObjProperty::REWARD_RANDOMIZE, 0);
} }
if (configuration.resetParameters.visitors) if (configuration.resetParameters.visitors)
{ {
cb->setObjProperty(id, ObjProperty::REWARD_CLEARED, false); cb->setObjPropertyValue(id, ObjProperty::REWARD_CLEARED, false);
ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_CLEAR, id); ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_CLEAR, id);
cb->sendAndApply(&cov); cb->sendAndApply(&cov);
} }

View File

@ -65,7 +65,7 @@ public:
void initObj(CRandomGenerator & rand) override; void initObj(CRandomGenerator & rand) override;
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
CRewardableObject(); CRewardableObject();

View File

@ -49,7 +49,7 @@ void IObjectInterface::initObj(CRandomGenerator & rand)
void IObjectInterface::pickRandomObject(CRandomGenerator & rand) void IObjectInterface::pickRandomObject(CRandomGenerator & rand)
{} {}
void IObjectInterface::setProperty( ui8 what, ui32 val ) void IObjectInterface::setProperty(ObjProperty what, ObjPropertyID identifier)
{} {}
bool IObjectInterface::wasVisited (PlayerColor player) const bool IObjectInterface::wasVisited (PlayerColor player) const

View File

@ -10,6 +10,7 @@
#pragma once #pragma once
#include "../networkPacks/EInfoWindowMode.h" #include "../networkPacks/EInfoWindowMode.h"
#include "../networkPacks/ObjProperty.h"
#include "../constants/EntityIdentifiers.h" #include "../constants/EntityIdentifiers.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -46,7 +47,7 @@ public:
virtual void newTurn(CRandomGenerator & rand) const; virtual void newTurn(CRandomGenerator & rand) const;
virtual void initObj(CRandomGenerator & rand); //synchr virtual void initObj(CRandomGenerator & rand); //synchr
virtual void pickRandomObject(CRandomGenerator & rand); virtual void pickRandomObject(CRandomGenerator & rand);
virtual void setProperty(ui8 what, ui32 val);//synchr virtual void setProperty(ObjProperty what, ObjPropertyID identifier);//synchr
//Called when queries created DURING HERO VISIT are resolved //Called when queries created DURING HERO VISIT are resolved
//First parameter is always hero that visited object and triggered the query //First parameter is always hero that visited object and triggered the query

View File

@ -44,10 +44,10 @@ static std::string visitedTxt(const bool visited)
return VLC->generaltexth->allTexts[id]; return VLC->generaltexth->allTexts[id];
} }
void CTeamVisited::setPropertyDer(ui8 what, ui32 val) void CTeamVisited::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{ {
if(what == CTeamVisited::OBJPROP_VISITED) if(what == ObjProperty::VISITED)
players.insert(PlayerColor(val)); players.insert(identifier.as<PlayerColor>());
} }
bool CTeamVisited::wasVisited(PlayerColor player) const bool CTeamVisited::wasVisited(PlayerColor player) const
@ -1195,13 +1195,13 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
cb->sendAndApply(&iw); cb->sendAndApply(&iw);
// increment general visited obelisks counter // increment general visited obelisks counter
cb->setObjProperty(id, CGObelisk::OBJPROP_INC, team.getNum()); cb->setObjPropertyID(id, ObjProperty::OBELISK_VISITED, team);
cb->showObjectWindow(this, EOpenWindowMode::PUZZLE_MAP, h, false); cb->showObjectWindow(this, EOpenWindowMode::PUZZLE_MAP, h, false);
// mark that particular obelisk as visited for all players in the team // mark that particular obelisk as visited for all players in the team
for(const auto & color : ts->players) for(const auto & color : ts->players)
{ {
cb->setObjProperty(id, CGObelisk::OBJPROP_VISITED, color.getNum()); cb->setObjPropertyID(id, ObjProperty::VISITED, color);
} }
} }
else else
@ -1228,14 +1228,14 @@ std::string CGObelisk::getHoverText(PlayerColor player) const
return getObjectName() + " " + visitedTxt(wasVisited(player)); return getObjectName() + " " + visitedTxt(wasVisited(player));
} }
void CGObelisk::setPropertyDer( ui8 what, ui32 val ) void CGObelisk::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{ {
switch(what) switch(what)
{ {
case CGObelisk::OBJPROP_INC: case ObjProperty::OBELISK_VISITED:
{ {
auto progress = ++visited[TeamID(val)]; auto progress = ++visited[identifier.as<TeamID>()];
logGlobal->debug("Player %d: obelisk progress %d / %d", val, static_cast<int>(progress) , static_cast<int>(obeliskCount)); logGlobal->debug("Player %d: obelisk progress %d / %d", identifier.getNum(), static_cast<int>(progress) , static_cast<int>(obeliskCount));
if(progress > obeliskCount) if(progress > obeliskCount)
{ {
@ -1246,7 +1246,7 @@ void CGObelisk::setPropertyDer( ui8 what, ui32 val )
break; break;
} }
default: default:
CTeamVisited::setPropertyDer(what, val); CTeamVisited::setPropertyDer(what, identifier);
break; break;
} }
} }
@ -1263,7 +1263,7 @@ void CGLighthouse::onHeroVisit( const CGHeroInstance * h ) const
if(oldOwner.isValidPlayer()) //remove bonus from old owner if(oldOwner.isValidPlayer()) //remove bonus from old owner
{ {
RemoveBonus rb(GiveBonus::ETarget::PLAYER); RemoveBonus rb(GiveBonus::ETarget::PLAYER);
rb.whoID = oldOwner.getNum(); rb.whoID = oldOwner;
rb.source = BonusSource::OBJECT_INSTANCE; rb.source = BonusSource::OBJECT_INSTANCE;
rb.id = BonusSourceID(id); rb.id = BonusSourceID(id);
cb->sendAndApply(&rb); cb->sendAndApply(&rb);
@ -1285,7 +1285,7 @@ void CGLighthouse::giveBonusTo(const PlayerColor & player, bool onInit) const
GiveBonus gb(GiveBonus::ETarget::PLAYER); GiveBonus gb(GiveBonus::ETarget::PLAYER);
gb.bonus.type = BonusType::MOVEMENT; gb.bonus.type = BonusType::MOVEMENT;
gb.bonus.val = 500; gb.bonus.val = 500;
gb.id = player.getNum(); gb.id = player;
gb.bonus.duration = BonusDuration::PERMANENT; gb.bonus.duration = BonusDuration::PERMANENT;
gb.bonus.source = BonusSource::OBJECT_INSTANCE; gb.bonus.source = BonusSource::OBJECT_INSTANCE;
gb.bonus.sid = BonusSourceID(id); gb.bonus.sid = BonusSourceID(id);

View File

@ -29,15 +29,13 @@ public:
bool wasVisited (const CGHeroInstance * h) const override; bool wasVisited (const CGHeroInstance * h) const override;
bool wasVisited(PlayerColor player) const override; bool wasVisited(PlayerColor player) const override;
bool wasVisited(const TeamID & team) const; bool wasVisited(const TeamID & team) const;
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & static_cast<CGObjectInstance&>(*this); h & static_cast<CGObjectInstance&>(*this);
h & players; h & players;
} }
static constexpr int OBJPROP_VISITED = 10;
}; };
class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles
@ -361,7 +359,6 @@ class DLL_LINKAGE CGDenOfthieves : public CGObjectInstance
class DLL_LINKAGE CGObelisk : public CTeamVisited class DLL_LINKAGE CGObelisk : public CTeamVisited
{ {
public: public:
static constexpr int OBJPROP_INC = 20;
static ui8 obeliskCount; //how many obelisks are on map static ui8 obeliskCount; //how many obelisks are on map
static std::map<TeamID, ui8> visited; //map: team_id => how many obelisks has been visited static std::map<TeamID, ui8> visited; //map: team_id => how many obelisks has been visited
@ -375,7 +372,7 @@ public:
h & static_cast<CTeamVisited&>(*this); h & static_cast<CTeamVisited&>(*this);
} }
protected: protected:
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
}; };
class DLL_LINKAGE CGLighthouse : public CGObjectInstance class DLL_LINKAGE CGLighthouse : public CGObjectInstance

View File

@ -971,18 +971,15 @@ void GiveBonus::applyGs(CGameState *gs)
CBonusSystemNode *cbsn = nullptr; CBonusSystemNode *cbsn = nullptr;
switch(who) switch(who)
{ {
case ETarget::HERO: case ETarget::OBJECT:
cbsn = gs->getHero(ObjectInstanceID(id)); cbsn = dynamic_cast<CBonusSystemNode*>(gs->getObjInstance(id.as<ObjectInstanceID>()));
break; break;
case ETarget::PLAYER: case ETarget::PLAYER:
cbsn = gs->getPlayerState(PlayerColor(id)); cbsn = gs->getPlayerState(id.as<PlayerColor>());
break;
case ETarget::TOWN:
cbsn = gs->getTown(ObjectInstanceID(id));
break; break;
case ETarget::BATTLE: case ETarget::BATTLE:
assert(Bonus::OneBattle(&bonus)); assert(Bonus::OneBattle(&bonus));
cbsn = dynamic_cast<CBonusSystemNode*>(gs->getBattle(BattleID(id))); cbsn = dynamic_cast<CBonusSystemNode*>(gs->getBattle(id.as<BattleID>()));
break; break;
} }
@ -1114,11 +1111,20 @@ void PlayerReinitInterface::applyGs(CGameState *gs)
void RemoveBonus::applyGs(CGameState *gs) void RemoveBonus::applyGs(CGameState *gs)
{ {
CBonusSystemNode * node = nullptr; CBonusSystemNode *node = nullptr;
if (who == GiveBonus::ETarget::HERO) switch(who)
node = gs->getHero(ObjectInstanceID(whoID)); {
else case GiveBonus::ETarget::OBJECT:
node = gs->getPlayerState(PlayerColor(whoID)); node = dynamic_cast<CBonusSystemNode*>(gs->getObjInstance(whoID.as<ObjectInstanceID>()));
break;
case GiveBonus::ETarget::PLAYER:
node = gs->getPlayerState(whoID.as<PlayerColor>());
break;
case GiveBonus::ETarget::BATTLE:
assert(Bonus::OneBattle(&bonus));
node = dynamic_cast<CBonusSystemNode*>(gs->getBattle(whoID.as<BattleID>()));
break;
}
BonusList &bonuses = node->getExportedBonusList(); BonusList &bonuses = node->getExportedBonusList();
@ -1483,7 +1489,7 @@ void NewObject::applyGs(CGameState *gs)
const TerrainTile & t = gs->map->getTile(targetPos); const TerrainTile & t = gs->map->getTile(targetPos);
terrainType = t.terType->getId(); terrainType = t.terType->getId();
auto handler = VLC->objtypeh->getHandlerFor(ID, subID); auto handler = VLC->objtypeh->getHandlerFor(ID, subID.getNum());
CGObjectInstance * o = handler->create(); CGObjectInstance * o = handler->create();
handler->configureObject(o, gs->getRandomGenerator()); handler->configureObject(o, gs->getRandomGenerator());
@ -1499,13 +1505,13 @@ void NewObject::applyGs(CGameState *gs)
cre->character = 2; cre->character = 2;
cre->gainedArtifact = ArtifactID::NONE; cre->gainedArtifact = ArtifactID::NONE;
cre->identifier = -1; cre->identifier = -1;
cre->addToSlot(SlotID(0), new CStackInstance(CreatureID(subID), -1)); //add placeholder stack cre->addToSlot(SlotID(0), new CStackInstance(subID.as<CreatureID>(), -1)); //add placeholder stack
} }
assert(!handler->getTemplates(terrainType).empty()); assert(!handler->getTemplates(terrainType).empty());
if (handler->getTemplates().empty()) if (handler->getTemplates().empty())
{ {
logGlobal->error("Attempt to create object (%d %d) with no templates!", ID, subID); logGlobal->error("Attempt to create object (%d %d) with no templates!", ID, subID.getNum());
return; return;
} }
@ -2049,9 +2055,9 @@ void SetObjectProperty::applyGs(CGameState * gs) const
if(state->towns.empty()) if(state->towns.empty())
state->daysWithoutCastle = 0; state->daysWithoutCastle = 0;
} }
if(PlayerColor(val).isValidPlayer()) if(identifier.as<PlayerColor>().isValidPlayer())
{ {
PlayerState * p = gs->getPlayerState(PlayerColor(val)); PlayerState * p = gs->getPlayerState(identifier.as<PlayerColor>());
p->towns.emplace_back(t); p->towns.emplace_back(t);
//reset counter before NewTurn to avoid no town message if game loaded at turn when one already captured //reset counter before NewTurn to avoid no town message if game loaded at turn when one already captured
@ -2062,12 +2068,12 @@ void SetObjectProperty::applyGs(CGameState * gs) const
CBonusSystemNode & nodeToMove = cai->whatShouldBeAttached(); CBonusSystemNode & nodeToMove = cai->whatShouldBeAttached();
nodeToMove.detachFrom(cai->whereShouldBeAttached(gs)); nodeToMove.detachFrom(cai->whereShouldBeAttached(gs));
obj->setProperty(what,val); obj->setProperty(what, identifier);
nodeToMove.attachTo(cai->whereShouldBeAttached(gs)); nodeToMove.attachTo(cai->whereShouldBeAttached(gs));
} }
else //not an armed instance else //not an armed instance
{ {
obj->setProperty(what,val); obj->setProperty(what, identifier);
} }
} }

View File

@ -0,0 +1,69 @@
/*
* ObjProperty.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
#include "../constants/VariantIdentifier.h"
#include "../constants/EntityIdentifiers.h"
enum class ObjProperty : int8_t
{
INVALID,
OWNER,
BLOCKVIS,
PRIMARY_STACK_COUNT,
VISITORS,
VISITED,
ID,
AVAILABLE_CREATURE,
MONSTER_COUNT,
MONSTER_POWER,
MONSTER_EXP,
MONSTER_RESTORE_TYPE,
MONSTER_REFUSED_JOIN,
//town-specific
STRUCTURE_ADD_VISITING_HERO,
STRUCTURE_CLEAR_VISITORS,
STRUCTURE_ADD_GARRISONED_HERO, //changing buildings state
BONUS_VALUE_FIRST,
BONUS_VALUE_SECOND, //used in Rampart for special building that generates resources (storing resource type and quantity)
SEERHUT_VISITED,
SEERHUT_COMPLETE,
KEYMASTER_VISITED,
OBELISK_VISITED,
//creature-bank specific
BANK_DAYCOUNTER,
BANK_RESET,
BANK_CLEAR,
//object with reward
REWARD_RANDOMIZE,
REWARD_SELECT,
REWARD_CLEARED
};
class NumericID : public Identifier<NumericID>
{
public:
using Identifier<NumericID>::Identifier;
static si32 decode(const std::string & identifier)
{
return std::stoi(identifier);
}
static std::string encode(const si32 index)
{
return std::to_string(index);
}
};
using ObjPropertyID = VariantIdentifier<NumericID, MapObjectID, ObjectInstanceID, CreatureID, PlayerColor, TeamID>;

View File

@ -15,6 +15,7 @@
#include "EOpenWindowMode.h" #include "EOpenWindowMode.h"
#include "EntityChanges.h" #include "EntityChanges.h"
#include "NetPacksBase.h" #include "NetPacksBase.h"
#include "ObjProperty.h"
#include "../CCreatureSet.h" #include "../CCreatureSet.h"
#include "../MetaString.h" #include "../MetaString.h"
@ -366,17 +367,17 @@ struct DLL_LINKAGE SetAvailableHero : public CPackForClient
struct DLL_LINKAGE GiveBonus : public CPackForClient struct DLL_LINKAGE GiveBonus : public CPackForClient
{ {
enum class ETarget : ui8 { HERO, PLAYER, TOWN, BATTLE }; enum class ETarget : int8_t { OBJECT, PLAYER, BATTLE };
explicit GiveBonus(ETarget Who = ETarget::HERO) explicit GiveBonus(ETarget Who = ETarget::OBJECT)
:who(Who) :who(Who)
{ {
} }
void applyGs(CGameState * gs); void applyGs(CGameState * gs);
ETarget who = ETarget::HERO; //who receives bonus ETarget who = ETarget::OBJECT;
si32 id = 0; //hero. town or player id - whoever receives it VariantIdentifier<ObjectInstanceID, PlayerColor, BattleID> id;
Bonus bonus; Bonus bonus;
MetaString bdescr; MetaString bdescr;
@ -388,7 +389,7 @@ struct DLL_LINKAGE GiveBonus : public CPackForClient
h & id; h & id;
h & bdescr; h & bdescr;
h & who; h & who;
assert(id != -1); assert(id.getNum() != -1);
} }
}; };
@ -461,7 +462,7 @@ struct DLL_LINKAGE PlayerReinitInterface : public CPackForClient
struct DLL_LINKAGE RemoveBonus : public CPackForClient struct DLL_LINKAGE RemoveBonus : public CPackForClient
{ {
explicit RemoveBonus(GiveBonus::ETarget Who = GiveBonus::ETarget::HERO) explicit RemoveBonus(GiveBonus::ETarget Who = GiveBonus::ETarget::OBJECT)
:who(Who) :who(Who)
{ {
} }
@ -469,7 +470,7 @@ struct DLL_LINKAGE RemoveBonus : public CPackForClient
void applyGs(CGameState * gs); void applyGs(CGameState * gs);
GiveBonus::ETarget who; //who receives bonus GiveBonus::ETarget who; //who receives bonus
ui32 whoID = 0; //hero, town or player id - whoever loses bonus VariantIdentifier<HeroTypeID, PlayerColor, BattleID, ObjectInstanceID> whoID;
//vars to identify bonus: its source //vars to identify bonus: its source
BonusSource source; BonusSource source;
@ -574,7 +575,7 @@ struct DLL_LINKAGE UpdateCastleEvents : public CPackForClient
struct DLL_LINKAGE ChangeFormation : public CPackForClient struct DLL_LINKAGE ChangeFormation : public CPackForClient
{ {
ObjectInstanceID hid; ObjectInstanceID hid;
ui8 formation = 0; EArmyFormation formation{};
void applyGs(CGameState * gs) const; void applyGs(CGameState * gs) const;
void visitTyped(ICPackVisitor & visitor) override; void visitTyped(ICPackVisitor & visitor) override;
@ -781,9 +782,9 @@ struct DLL_LINKAGE NewObject : public CPackForClient
void applyGs(CGameState * gs); void applyGs(CGameState * gs);
/// Object ID to create /// Object ID to create
Obj ID; MapObjectID ID;
/// Object secondary ID to create /// Object secondary ID to create
ui32 subID = 0; VariantIdentifier<MapObjectSubID, HeroTypeID, CreatureID, BoatId> subID;
/// Position of visitable tile of created object /// Position of visitable tile of created object
int3 targetPos; int3 targetPos;
/// Which player initiated creation of this object /// Which player initiated creation of this object
@ -806,7 +807,8 @@ struct DLL_LINKAGE SetAvailableArtifacts : public CPackForClient
{ {
void applyGs(CGameState * gs) const; void applyGs(CGameState * gs) const;
si32 id = 0; //two variants: id < 0: set artifact pool for Artifact Merchants in towns; id >= 0: set pool for adv. map Black Market (id is the id of Black Market instance then) //two variants: id < 0: set artifact pool for Artifact Merchants in towns; id >= 0: set pool for adv. map Black Market (id is the id of Black Market instance then)
ObjectInstanceID id;
std::vector<const CArtifact *> arts; std::vector<const CArtifact *> arts;
void visitTyped(ICPackVisitor & visitor) override; void visitTyped(ICPackVisitor & visitor) override;
@ -1207,38 +1209,16 @@ struct DLL_LINKAGE InfoWindow : public CPackForClient //103 - displays simple i
InfoWindow() = default; InfoWindow() = default;
}; };
namespace ObjProperty
{
enum
{
OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8,
MONSTER_COUNT = 10, MONSTER_POWER = 11, MONSTER_EXP = 12, MONSTER_RESTORE_TYPE = 13, MONSTER_REFUSED_JOIN,
//town-specific
STRUCTURE_ADD_VISITING_HERO, STRUCTURE_CLEAR_VISITORS, STRUCTURE_ADD_GARRISONED_HERO, //changing buildings state
BONUS_VALUE_FIRST, BONUS_VALUE_SECOND, //used in Rampart for special building that generates resources (storing resource type and quantity)
//creature-bank specific
BANK_DAYCOUNTER, BANK_RESET, BANK_CLEAR,
//object with reward
REWARD_RANDOMIZE, REWARD_SELECT, REWARD_CLEARED
};
}
struct DLL_LINKAGE SetObjectProperty : public CPackForClient struct DLL_LINKAGE SetObjectProperty : public CPackForClient
{ {
void applyGs(CGameState * gs) const; void applyGs(CGameState * gs) const;
ObjectInstanceID id; ObjectInstanceID id;
ui8 what = 0; // see ObjProperty enum ObjProperty what{};
ui32 val = 0;
ObjPropertyID identifier;
int32_t value = 0;
SetObjectProperty() = default; SetObjectProperty() = default;
SetObjectProperty(const ObjectInstanceID & ID, ui8 What, ui32 Val)
: id(ID)
, what(What)
, val(Val)
{
}
void visitTyped(ICPackVisitor & visitor) override; void visitTyped(ICPackVisitor & visitor) override;
@ -1246,7 +1226,8 @@ struct DLL_LINKAGE SetObjectProperty : public CPackForClient
{ {
h & id; h & id;
h & what; h & what;
h & val; h & identifier;
h & value;
} }
}; };

View File

@ -11,6 +11,7 @@
#include "ArtifactLocation.h" #include "ArtifactLocation.h"
#include "NetPacksBase.h" #include "NetPacksBase.h"
#include "TradeItem.h"
#include "../int3.h" #include "../int3.h"
#include "../battle/BattleAction.h" #include "../battle/BattleAction.h"
@ -472,7 +473,8 @@ struct DLL_LINKAGE TradeOnMarketplace : public CPackForServer
ObjectInstanceID heroId; ObjectInstanceID heroId;
EMarketMode mode = EMarketMode::RESOURCE_RESOURCE; EMarketMode mode = EMarketMode::RESOURCE_RESOURCE;
std::vector<ui32> r1, r2; //mode 0: r1 - sold resource, r2 - bought res (exception: when sacrificing art r1 is art id [todo: make r2 preferred slot?] std::vector<TradeItemSell> r1;
std::vector<TradeItemBuy> r2; //mode 0: r1 - sold resource, r2 - bought res (exception: when sacrificing art r1 is art id [todo: make r2 preferred slot?]
std::vector<ui32> val; //units of sold resource std::vector<ui32> val; //units of sold resource
void visitTyped(ICPackVisitor & visitor) override; void visitTyped(ICPackVisitor & visitor) override;
@ -493,13 +495,13 @@ struct DLL_LINKAGE SetFormation : public CPackForServer
{ {
SetFormation() = default; SetFormation() = default;
; ;
SetFormation(const ObjectInstanceID & HID, ui8 Formation) SetFormation(const ObjectInstanceID & HID, EArmyFormation Formation)
: hid(HID) : hid(HID)
, formation(Formation) , formation(Formation)
{ {
} }
ObjectInstanceID hid; ObjectInstanceID hid;
ui8 formation = 0; EArmyFormation formation{};
void visitTyped(ICPackVisitor & visitor) override; void visitTyped(ICPackVisitor & visitor) override;

View File

@ -0,0 +1,20 @@
/*
* TradeItem.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
#include "../constants/VariantIdentifier.h"
#include "../constants/EntityIdentifiers.h"
VCMI_LIB_NAMESPACE_BEGIN
using TradeItemSell = VariantIdentifier<GameResID, SlotID, ArtifactPosition, ArtifactInstanceID>;
using TradeItemBuy = VariantIdentifier<GameResID, PlayerColor, ArtifactID, SecondarySkill>;
VCMI_LIB_NAMESPACE_END

View File

@ -150,9 +150,9 @@ void Rewardable::Interface::grantRewardAfterLevelup(IGameCallback * cb, const Re
for(const Bonus & bonus : info.reward.bonuses) for(const Bonus & bonus : info.reward.bonuses)
{ {
GiveBonus gb; GiveBonus gb;
gb.who = GiveBonus::ETarget::HERO; gb.who = GiveBonus::ETarget::OBJECT;
gb.bonus = bonus; gb.bonus = bonus;
gb.id = hero->id.getNum(); gb.id = hero->id;
cb->giveHeroBonus(&gb); cb->giveHeroBonus(&gb);
} }

View File

@ -83,7 +83,7 @@ ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(SpellCastEnviron
for(const Bonus & b : bonuses) for(const Bonus & b : bonuses)
{ {
GiveBonus gb; GiveBonus gb;
gb.id = parameters.caster->getCasterUnitId(); gb.id = ObjectInstanceID(parameters.caster->getCasterUnitId());
gb.bonus = b; gb.bonus = b;
env->apply(&gb); env->apply(&gb);
} }
@ -323,7 +323,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
} }
GiveBonus gb; GiveBonus gb;
gb.id = parameters.caster->getCasterUnitId(); gb.id = ObjectInstanceID(parameters.caster->getCasterUnitId());
gb.bonus = Bonus(BonusDuration::ONE_DAY, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, BonusSourceID(owner->id)); gb.bonus = Bonus(BonusDuration::ONE_DAY, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, BonusSourceID(owner->id));
env->apply(&gb); env->apply(&gb);

View File

@ -117,7 +117,7 @@ void Moat::apply(ServerCallback * server, const Mechanics * m, const EffectTarge
for(auto & b : converted) for(auto & b : converted)
{ {
GiveBonus gb(GiveBonus::ETarget::BATTLE); GiveBonus gb(GiveBonus::ETarget::BATTLE);
gb.id = m->battle()->getBattle()->getBattleID().getNum(); gb.id = m->battle()->getBattle()->getBattleID();
gb.bonus = b; gb.bonus = b;
server->apply(&gb); server->apply(&gb);
} }

View File

@ -101,7 +101,7 @@ bool ArmyWidget::commitChanges()
} }
} }
army.setFormation(ui->formationTight->isChecked()); army.setFormation(ui->formationTight->isChecked() ? EArmyFormation::TIGHT : EArmyFormation::LOOSE );
return isArmed; return isArmed;
} }

View File

@ -886,7 +886,7 @@ void CGameHandler::onNewTurn()
if (newMonth) if (newMonth)
{ {
SetAvailableArtifacts saa; SetAvailableArtifacts saa;
saa.id = -1; saa.id = ObjectInstanceID::NONE;
pickAllowedArtsSet(saa.arts, getRandomGenerator()); pickAllowedArtsSet(saa.arts, getRandomGenerator());
sendAndApply(&saa); sendAndApply(&saa);
} }
@ -1328,8 +1328,8 @@ bool CGameHandler::teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui
void CGameHandler::setOwner(const CGObjectInstance * obj, const PlayerColor owner) void CGameHandler::setOwner(const CGObjectInstance * obj, const PlayerColor owner)
{ {
PlayerColor oldOwner = getOwner(obj->id); PlayerColor oldOwner = getOwner(obj->id);
SetObjectProperty sop(obj->id, ObjProperty::OWNER, owner.getNum());
sendAndApply(&sop); setObjPropertyID(obj->id, ObjProperty::OWNER, owner);
std::set<PlayerColor> playerColors = {owner, oldOwner}; std::set<PlayerColor> playerColors = {owner, oldOwner};
checkVictoryLossConditions(playerColors); checkVictoryLossConditions(playerColors);
@ -2973,12 +2973,12 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, GameRe
SetAvailableArtifacts saa; SetAvailableArtifacts saa;
if(dynamic_cast<const CGTownInstance *>(m)) if(dynamic_cast<const CGTownInstance *>(m))
{ {
saa.id = -1; saa.id = ObjectInstanceID::NONE;
saa.arts = CGTownInstance::merchantArtifacts; saa.arts = CGTownInstance::merchantArtifacts;
} }
else if(const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(m)) //black market else if(const CGBlackMarket *bm = dynamic_cast<const CGBlackMarket *>(m)) //black market
{ {
saa.id = bm->id.getNum(); saa.id = bm->id;
saa.arts = bm->artifacts; saa.arts = bm->artifacts;
} }
else else
@ -3044,23 +3044,23 @@ bool CGameHandler::buySecSkill(const IMarket *m, const CGHeroInstance *h, Second
return true; return true;
} }
bool CGameHandler::tradeResources(const IMarket *market, ui32 val, PlayerColor player, ui32 id1, ui32 id2) bool CGameHandler::tradeResources(const IMarket *market, ui32 amountToSell, PlayerColor player, GameResID toSell, GameResID toBuy)
{ {
TResourceCap r1 = getPlayerState(player)->resources[id1]; TResourceCap haveToSell = getPlayerState(player)->resources[toSell];
vstd::amin(val, r1); //can't trade more resources than have vstd::amin(amountToSell, haveToSell); //can't trade more resources than have
int b1, b2; //base quantities for trade int b1, b2; //base quantities for trade
market->getOffer(id1, id2, b1, b2, EMarketMode::RESOURCE_RESOURCE); market->getOffer(toSell, toBuy, b1, b2, EMarketMode::RESOURCE_RESOURCE);
int units = val / b1; //how many base quantities we trade int amountToBoy = amountToSell / b1; //how many base quantities we trade
if (val%b1) //all offered units of resource should be used, if not -> somewhere in calculations must be an error if (amountToSell % b1 != 0) //all offered units of resource should be used, if not -> somewhere in calculations must be an error
{ {
COMPLAIN_RET("Invalid deal, not all offered units of resource were used."); COMPLAIN_RET("Invalid deal, not all offered units of resource were used.");
} }
giveResource(player, GameResID(id1), - b1 * units); giveResource(player, toSell, -b1 * amountToBoy);
giveResource(player, GameResID(id2), b2 * units); giveResource(player, toBuy, b2 * amountToBoy);
return true; return true;
} }
@ -3144,7 +3144,7 @@ bool CGameHandler::sendResources(ui32 val, PlayerColor player, GameResID r1, Pla
return true; return true;
} }
bool CGameHandler::setFormation(ObjectInstanceID hid, ui8 formation) bool CGameHandler::setFormation(ObjectInstanceID hid, EArmyFormation formation)
{ {
const CGHeroInstance *h = getHero(hid); const CGHeroInstance *h = getHero(hid);
if (!h) if (!h)
@ -4047,8 +4047,8 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID)
createObject(*tile, PlayerColor::NEUTRAL, Obj::MONSTER, creatureID); createObject(*tile, PlayerColor::NEUTRAL, Obj::MONSTER, creatureID);
auto monsterId = getTopObj(*tile)->id; auto monsterId = getTopObj(*tile)->id;
setObjProperty(monsterId, ObjProperty::MONSTER_COUNT, count); setObjPropertyValue(monsterId, ObjProperty::MONSTER_COUNT, count);
setObjProperty(monsterId, ObjProperty::MONSTER_POWER, (si64)1000*count); setObjPropertyValue(monsterId, ObjProperty::MONSTER_POWER, (si64)1000*count);
} }
tiles.erase(tile); //not use it again tiles.erase(tile); //not use it again
} }
@ -4170,12 +4170,21 @@ bool CGameHandler::isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, con
return true; return true;
} }
void CGameHandler::setObjProperty(ObjectInstanceID objid, int prop, si64 val) void CGameHandler::setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value)
{ {
SetObjectProperty sob; SetObjectProperty sob;
sob.id = objid; sob.id = objid;
sob.what = prop; sob.what = prop;
sob.val = static_cast<ui32>(val); sob.identifier = NumericID(value);
sendAndApply(&sob);
}
void CGameHandler::setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, ObjPropertyID identifier)
{
SetObjectProperty sob;
sob.id = objid;
sob.what = prop;
sob.identifier = identifier;
sendAndApply(&sob); sendAndApply(&sob);
} }
@ -4209,7 +4218,7 @@ scripting::Pool * CGameHandler::getGlobalContextPool() const
//} //}
#endif #endif
void CGameHandler::createObject(const int3 & visitablePosition, const PlayerColor & initiator, Obj type, int32_t subtype) void CGameHandler::createObject(const int3 & visitablePosition, const PlayerColor & initiator, MapObjectID type, MapObjectSubID subtype)
{ {
NewObject no; NewObject no;
no.ID = type; no.ID = type;

View File

@ -101,7 +101,7 @@ public:
//do sth //do sth
void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells) override; void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells) override;
bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override; bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override;
void createObject(const int3 & visitablePosition, const PlayerColor & initiator, Obj type, int32_t subtype ) override; void createObject(const int3 & visitablePosition, const PlayerColor & initiator, MapObjectID type, MapObjectSubID subtype) override;
void setOwner(const CGObjectInstance * obj, PlayerColor owner) override; void setOwner(const CGObjectInstance * obj, PlayerColor owner) override;
void changePrimSkill(const CGHeroInstance * hero, PrimarySkill which, si64 val, bool abs=false) override; void changePrimSkill(const CGHeroInstance * hero, PrimarySkill which, si64 val, bool abs=false) override;
void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) override; void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs=false) override;
@ -156,7 +156,8 @@ public:
/// Returns hero that is currently visiting this object, or nullptr if no visit is active /// Returns hero that is currently visiting this object, or nullptr if no visit is active
const CGHeroInstance * getVisitingHero(const CGObjectInstance *obj); const CGHeroInstance * getVisitingHero(const CGObjectInstance *obj);
bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) override; bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) override;
void setObjProperty(ObjectInstanceID objid, int prop, si64 val) override; void setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value) override;
void setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, ObjPropertyID identifier) override;
void showInfoDialog(InfoWindow * iw) override; void showInfoDialog(InfoWindow * iw) override;
void showInfoDialog(const std::string & msg, PlayerColor player) override; void showInfoDialog(const std::string & msg, PlayerColor player) override;
@ -182,8 +183,8 @@ public:
bool queryReply( QueryID qid, std::optional<int32_t> reply, PlayerColor player ); bool queryReply( QueryID qid, std::optional<int32_t> reply, PlayerColor player );
bool buildBoat( ObjectInstanceID objid, PlayerColor player ); bool buildBoat( ObjectInstanceID objid, PlayerColor player );
bool setFormation( ObjectInstanceID hid, ui8 formation ); bool setFormation( ObjectInstanceID hid, EArmyFormation formation );
bool tradeResources(const IMarket *market, ui32 val, PlayerColor player, ui32 id1, ui32 id2); bool tradeResources(const IMarket *market, ui32 amountToSell, PlayerColor player, GameResID toSell, GameResID toBuy);
bool sacrificeCreatures(const IMarket * market, const CGHeroInstance * hero, const std::vector<SlotID> & slot, const std::vector<ui32> & count); bool sacrificeCreatures(const IMarket * market, const CGHeroInstance * hero, const std::vector<SlotID> & slot, const std::vector<ui32> & count);
bool sendResources(ui32 val, PlayerColor player, GameResID r1, PlayerColor r2); bool sendResources(ui32 val, PlayerColor player, GameResID r1, PlayerColor r2);
bool sellCreatures(ui32 count, const IMarket *market, const CGHeroInstance * hero, SlotID slot, GameResID resourceID); bool sellCreatures(ui32 count, const IMarket *market, const CGHeroInstance * hero, SlotID slot, GameResID resourceID);

View File

@ -221,42 +221,49 @@ void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
{ {
case EMarketMode::RESOURCE_RESOURCE: case EMarketMode::RESOURCE_RESOURCE:
for(int i = 0; i < pack.r1.size(); ++i) for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.tradeResources(market, pack.val[i], pack.player, pack.r1[i], pack.r2[i]); result &= gh.tradeResources(market, pack.val[i], pack.player, pack.r1[i].as<GameResID>(), pack.r2[i].as<GameResID>());
break; break;
case EMarketMode::RESOURCE_PLAYER: case EMarketMode::RESOURCE_PLAYER:
for(int i = 0; i < pack.r1.size(); ++i) for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.sendResources(pack.val[i], pack.player, GameResID(pack.r1[i]), PlayerColor(pack.r2[i])); result &= gh.sendResources(pack.val[i], pack.player, pack.r1[i].as<GameResID>(), pack.r2[i].as<PlayerColor>());
break; break;
case EMarketMode::CREATURE_RESOURCE: case EMarketMode::CREATURE_RESOURCE:
for(int i = 0; i < pack.r1.size(); ++i) for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.sellCreatures(pack.val[i], market, hero, SlotID(pack.r1[i]), GameResID(pack.r2[i])); result &= gh.sellCreatures(pack.val[i], market, hero, pack.r1[i].as<SlotID>(), pack.r2[i].as<GameResID>());
break; break;
case EMarketMode::RESOURCE_ARTIFACT: case EMarketMode::RESOURCE_ARTIFACT:
for(int i = 0; i < pack.r1.size(); ++i) for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.buyArtifact(market, hero, GameResID(pack.r1[i]), ArtifactID(pack.r2[i])); result &= gh.buyArtifact(market, hero, pack.r1[i].as<GameResID>(), pack.r2[i].as<ArtifactID>());
break; break;
case EMarketMode::ARTIFACT_RESOURCE: case EMarketMode::ARTIFACT_RESOURCE:
for(int i = 0; i < pack.r1.size(); ++i) for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.sellArtifact(market, hero, ArtifactInstanceID(pack.r1[i]), GameResID(pack.r2[i])); result &= gh.sellArtifact(market, hero, pack.r1[i].as<ArtifactInstanceID>(), pack.r2[i].as<GameResID>());
break; break;
case EMarketMode::CREATURE_UNDEAD: case EMarketMode::CREATURE_UNDEAD:
for(int i = 0; i < pack.r1.size(); ++i) for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.transformInUndead(market, hero, SlotID(pack.r1[i])); result &= gh.transformInUndead(market, hero, pack.r1[i].as<SlotID>());
break; break;
case EMarketMode::RESOURCE_SKILL: case EMarketMode::RESOURCE_SKILL:
for(int i = 0; i < pack.r2.size(); ++i) for(int i = 0; i < pack.r2.size(); ++i)
result &= gh.buySecSkill(market, hero, SecondarySkill(pack.r2[i])); result &= gh.buySecSkill(market, hero, pack.r2[i].as<SecondarySkill>());
break; break;
case EMarketMode::CREATURE_EXP: case EMarketMode::CREATURE_EXP:
{ {
std::vector<SlotID> slotIDs(pack.r1.begin(), pack.r1.end()); std::vector<SlotID> slotIDs;
std::vector<ui32> count(pack.val.begin(), pack.val.end()); std::vector<ui32> count(pack.val.begin(), pack.val.end());
for(auto const & slot : pack.r1)
slotIDs.push_back(slot.as<SlotID>());
result = gh.sacrificeCreatures(market, hero, slotIDs, count); result = gh.sacrificeCreatures(market, hero, slotIDs, count);
return; return;
} }
case EMarketMode::ARTIFACT_EXP: case EMarketMode::ARTIFACT_EXP:
{ {
std::vector<ArtifactPosition> positions(pack.r1.begin(), pack.r1.end()); std::vector<ArtifactPosition> positions;
for(auto const & slot : pack.r1)
positions.push_back(slot.as<ArtifactPosition>());
result = gh.sacrificeArtifact(market, hero, positions); result = gh.sacrificeArtifact(market, hero, positions);
return; return;
} }

View File

@ -122,8 +122,8 @@ void BattleProcessor::startBattlePrimary(const CArmedInstance *army1, const CArm
{ {
for(auto bonus : attackerInfo->battleBonuses) for(auto bonus : attackerInfo->battleBonuses)
{ {
GiveBonus giveBonus(GiveBonus::ETarget::HERO); GiveBonus giveBonus(GiveBonus::ETarget::OBJECT);
giveBonus.id = hero1->id.getNum(); giveBonus.id = hero1->id;
giveBonus.bonus = bonus; giveBonus.bonus = bonus;
gameHandler->sendAndApply(&giveBonus); gameHandler->sendAndApply(&giveBonus);
} }

View File

@ -139,8 +139,8 @@ void PlayerMessageProcessor::cheatGiveSpells(PlayerColor player, const CGHeroIns
gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
///Give all spells with bonus (to allow banned spells) ///Give all spells with bonus (to allow banned spells)
GiveBonus giveBonus(GiveBonus::ETarget::HERO); GiveBonus giveBonus(GiveBonus::ETarget::OBJECT);
giveBonus.id = hero->id.getNum(); giveBonus.id = hero->id;
giveBonus.bonus = Bonus(BonusDuration::PERMANENT, BonusType::SPELLS_OF_LEVEL, BonusSource::OTHER, 0, BonusSourceID()); giveBonus.bonus = Bonus(BonusDuration::PERMANENT, BonusType::SPELLS_OF_LEVEL, BonusSource::OTHER, 0, BonusSourceID());
//start with level 0 to skip abilities //start with level 0 to skip abilities
for (int level = 1; level <= GameConstants::SPELL_LEVELS; level++) for (int level = 1; level <= GameConstants::SPELL_LEVELS; level++)
@ -300,11 +300,11 @@ void PlayerMessageProcessor::cheatMovement(PlayerColor player, const CGHeroInsta
gameHandler->sendAndApply(&smp); gameHandler->sendAndApply(&smp);
GiveBonus gb(GiveBonus::ETarget::HERO); GiveBonus gb(GiveBonus::ETarget::OBJECT);
gb.bonus.type = BonusType::FREE_SHIP_BOARDING; gb.bonus.type = BonusType::FREE_SHIP_BOARDING;
gb.bonus.duration = BonusDuration::ONE_DAY; gb.bonus.duration = BonusDuration::ONE_DAY;
gb.bonus.source = BonusSource::OTHER; gb.bonus.source = BonusSource::OTHER;
gb.id = hero->id.getNum(); gb.id = hero->id;
gameHandler->giveHeroBonus(&gb); gameHandler->giveHeroBonus(&gb);
} }