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;
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);
if(!nullkiller) // crash protection
@ -1419,7 +1419,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
//TODO trade only as much as needed
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));
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;
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
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
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));
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);
}
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;
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);
}
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);
}

View File

@ -12,6 +12,7 @@
#include "lib/CGameInfoCallback.h"
#include "lib/battle/CPlayerBattleCallback.h"
#include "lib/int3.h" // for int3
#include "lib/networkPacks/TradeItem.h"
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 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, 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, 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<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 sendQueryReply(std::optional<int32_t> reply, QueryID queryID) =0;
@ -94,7 +95,7 @@ public:
virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=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 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 sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) = 0;
@ -181,9 +182,9 @@ public:
void endTurn() override;
void swapGarrisonHero(const CGTownInstance *town) 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, const std::vector<ui32> & id1, const std::vector<ui32> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override;
void setFormation(const CGHeroInstance * hero, bool tight) 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<TradeItemSell> & id1, const std::vector<TradeItemBuy> & id2, const std::vector<ui32> & val1, const CGHeroInstance * hero = nullptr) override;
void setFormation(const CGHeroInstance * hero, EArmyFormation mode) override;
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero) override;
void save(const std::string &fname) 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 {};
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 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 {};
@ -212,7 +212,8 @@ public:
void changeFogOfWar(int3 center, ui32 radius, 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(const std::string & msg, PlayerColor player) override {};

View File

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

View File

@ -99,14 +99,15 @@ TExpType CAltarArtifacts::calcExpAltarForHero()
void CAltarArtifacts::makeDeal()
{
std::vector<ui32> positions;
std::vector<TradeItemSell> positions;
for(const auto art : arts->artifactsOnAltar)
{
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();
for(auto item : items[0])
@ -374,14 +375,14 @@ void CAltarCreatures::makeDeal()
unitsSlider->scrollTo(0);
expForHero->setText(std::to_string(0));
std::vector<ui32> ids;
std::vector<TradeItemSell> ids;
std::vector<ui32> toSacrifice;
for(int i = 0; i < unitsOnAltar.size(); i++)
{
if(unitsOnAltar[i])
{
ids.push_back(i);
ids.push_back(SlotID(i));
toSacrifice.push_back(unitsOnAltar[i]);
}
}

View File

@ -306,7 +306,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
formations->resetCallback();
//setting formations
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);
luck->set(curHero);

View File

@ -503,14 +503,27 @@ void CMarketplaceWindow::makeDeal()
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);
}
else
{
LOCPLINT->cb->trade(market, mode, leftIdToSend, hRight->id, r2, hero);
break;
case EMarketMode::CREATURE_RESOURCE:
LOCPLINT->cb->trade(market, mode, SlotID(leftIdToSend), GameResID(hRight->id), slider->getValue() * r1, 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)
{
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();
}
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")),
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));
}
void CUnivConfirmWindow::makeDeal(int skill)
void CUnivConfirmWindow::makeDeal(SecondarySkill skill)
{
owner->makeDeal(skill);
close();

View File

@ -403,7 +403,7 @@ class CUniversityWindow : public CStatusbarWindow
public:
CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market, const std::function<void()> & onWindowClosed);
void makeDeal(int skill);
void makeDeal(SecondarySkill skill);
void close();
};
@ -422,10 +422,10 @@ class CUnivConfirmWindow : public CStatusbarWindow
std::shared_ptr<CAnimImage> costIcon;
std::shared_ptr<CLabel> cost;
void makeDeal(int skill);
void makeDeal(SecondarySkill skill);
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

View File

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

View File

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

View File

@ -203,12 +203,6 @@ public:
}
};
enum class EArmyFormation : uint8_t
{
LOOSE,
TIGHT
};
namespace NArmyFormation
{
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, CStackInstance * stack, bool allowMerging = true); //Adds stack to slot. Slot must be empty or with same type creature
void clearSlots() override;
void setFormation(bool tight);
void setFormation(EArmyFormation tight);
CArmedInstance *castToArmyObj();
//basic operations

View File

@ -13,6 +13,7 @@
#include "CGameInfoCallback.h" // for CGameInfoCallback
#include "CRandomGenerator.h"
#include "networkPacks/ObjProperty.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -73,14 +74,15 @@ public:
class DLL_LINKAGE IGameEventCallback
{
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(const std::string & msg, PlayerColor player) = 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 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 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;

View File

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

View File

@ -13,7 +13,7 @@
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>
class VariantIdentifier
{

View File

@ -94,12 +94,12 @@ void CBank::setConfig(const BankConfig & config)
setCreature (SlotID(stacksCount()), stack.type->getId(), stack.count);
}
void CBank::setPropertyDer (ui8 what, ui32 val)
void CBank::setPropertyDer (ObjProperty what, ObjPropertyID identifier)
{
switch (what)
{
case ObjProperty::BANK_DAYCOUNTER: //daycounter
daycounter+=val;
daycounter+= identifier.getNum();
break;
case ObjProperty::BANK_RESET:
// 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 (daycounter >= resetDuration)
cb->setObjProperty (id, ObjProperty::BANK_RESET, 0); //daycounter 0
cb->setObjPropertyValue(id, ObjProperty::BANK_RESET); //daycounter 0
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:
{
GiveBonus gbonus;
gbonus.id = hero->id.getNum();
gbonus.id = hero->id;
gbonus.bonus.duration = BonusDuration::ONE_BATTLE;
gbonus.bonus.source = BonusSource::OBJECT_TYPE;
gbonus.bonus.sid = BonusSourceID(ID);
@ -240,7 +240,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
{
GiveBonus gb;
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);
textID = 107;
iw.components.emplace_back(ComponentType::LUCK, -2);
@ -369,7 +369,7 @@ void CBank::doVisit(const CGHeroInstance * hero) const
cb->showInfoDialog(&iw);
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;
bool coastVisitable;
void setPropertyDer(ui8 what, ui32 val) override;
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void doVisit(const CGHeroInstance * hero) const;
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)
{
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->setObjProperty(id, ObjProperty::MONSTER_POWER, power); //increase temppower
cb->setObjPropertyValue(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_POWER, power); //increase temppower
}
}
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)
{
case ObjProperty::MONSTER_COUNT:
stacks[SlotID(0)]->count = val;
stacks[SlotID(0)]->count = identifier.getNum();
break;
case ObjProperty::MONSTER_POWER:
temppower = val;
temppower = identifier.getNum();
break;
case ObjProperty::MONSTER_EXP:
giveStackExp(val);
break;
case ObjProperty::MONSTER_RESTORE_TYPE:
formation.basicType = val;
giveStackExp(identifier.getNum());
break;
case ObjProperty::MONSTER_REFUSED_JOIN:
refusedJoining = val;
refusedJoining = identifier.getNum();
break;
}
}
@ -368,7 +365,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
void CGCreature::fleeDecision(const CGHeroInstance *h, ui32 pursue) const
{
if(refusedJoining)
cb->setObjProperty(id, ObjProperty::MONSTER_REFUSED_JOIN, false);
cb->setObjPropertyValue(id, ObjProperty::MONSTER_REFUSED_JOIN, false);
if(pursue)
{
@ -386,7 +383,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
{
if(takenAction(h,false) == FLEE)
{
cb->setObjProperty(id, ObjProperty::MONSTER_REFUSED_JOIN, true);
cb->setObjPropertyValue(id, ObjProperty::MONSTER_REFUSED_JOIN, true);
flee(h);
}
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
{
//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);
//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
TSlots::const_iterator i;
CCreature * cre = VLC->creh->objects[formation.basicType];
const CCreature * cre = getCreature().toCreature();
for(i = stacks.begin(); i != stacks.end(); i++)
{
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->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;
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)
{
h & static_cast<CArmedInstance&>(*this);
@ -80,7 +69,7 @@ public:
h & formation;
}
protected:
void setPropertyDer(ui8 what, ui32 val) override;
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override;
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)
{
@ -214,14 +214,14 @@ void CGDwelling::setPropertyDer(ui8 what, ui32 val)
std::vector<ConstTransitivePtr<CGDwelling> >* dwellings = &cb->gameState()->players[tempOwner].dwellings;
dwellings->erase (std::find(dwellings->begin(), dwellings->end(), this));
}
if (PlayerColor(val) != PlayerColor::NEUTRAL) //can new owner be neutral?
cb->gameState()->players[PlayerColor(val)].dwellings.emplace_back(this);
if (identifier.as<PlayerColor>().isValidPlayer())
cb->gameState()->players[identifier.as<PlayerColor>()].dwellings.emplace_back(this);
}
break;
case ObjProperty::AVAILABLE_CREATURE:
creatures.resize(1);
creatures[0].second.resize(1);
creatures[0].second[0] = CreatureID(val);
creatures[0].second[0] = identifier.as<CreatureID>();
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
{
cb->setObjProperty(id, ObjProperty::AVAILABLE_CREATURE, VLC->creh->pickRandomMonster(rand));
cb->setObjPropertyID(id, ObjProperty::AVAILABLE_CREATURE, VLC->creh->pickRandomMonster(rand));
}
bool change = false;

View File

@ -52,7 +52,7 @@ private:
void initObj(CRandomGenerator & rand) override;
void onHeroVisit(const CGHeroInstance * h) 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 blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) 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)
gender = type->gender;
setFormation(false);
setFormation(EArmyFormation::LOOSE);
if (!stacksCount()) //standard army//initial army
{
initArmy(rand);
@ -501,7 +501,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
SetMovePoints smp;
smp.hid = id;
cb->setManaPoints (id, manaLimit());
cb->setManaPoints (id, manaLimit());
ObjectInstanceID boatId;
const auto boatPos = visitablePos();
@ -520,7 +520,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
smp.val = movementPointsLimit(true);
}
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);
h->showInfoDialog(102);
@ -620,10 +620,10 @@ void CGHeroInstance::updateSkillBonus(const SecondarySkill & which, int val)
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)
setStackCount(SlotID(0), val);
setStackCount(SlotID(0), identifier.getNum());
}
double CGHeroInstance::getFightingStrength() const

View File

@ -307,7 +307,7 @@ public:
bool isCoastVisitable() const override;
BattleField getBattlefield() const override;
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
void serializeCommonOptions(JsonSerializeFormat & handler);

View File

@ -91,7 +91,7 @@ void CGBlackMarket::newTurn(CRandomGenerator & rand) const
return;
SetAvailableArtifacts saa;
saa.id = id.getNum();
saa.id = id;
cb->pickAllowedArtsSet(saa.arts, rand);
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)
{
case ObjProperty::OWNER:
tempOwner = PlayerColor(val);
tempOwner = identifier.as<PlayerColor>();
break;
case ObjProperty::BLOCKVIS:
blockVisit = val;
blockVisit = identifier.getNum();
break;
case ObjProperty::ID:
ID = Obj(val);
break;
case ObjProperty::SUBID:
subID = val;
ID = identifier.as<MapObjectID>();
break;
}
}
@ -207,7 +204,7 @@ TObjectTypeHandler CGObjectInstance::getObjectHandler() const
return VLC->objtypeh->getHandlerFor(ID, subID);
}
void CGObjectInstance::setPropertyDer( ui8 what, ui32 val )
void CGObjectInstance::setPropertyDer( ObjProperty what, ObjPropertyID identifier )
{}
int3 CGObjectInstance::getSightCenter() const
@ -229,7 +226,7 @@ void CGObjectInstance::giveDummyBonus(const ObjectInstanceID & heroID, BonusDura
{
GiveBonus gbonus;
gbonus.bonus.type = BonusType::NONE;
gbonus.id = heroID.getNum();
gbonus.id = heroID;
gbonus.bonus.duration = duration;
gbonus.bonus.source = BonusSource::OBJECT_TYPE;
gbonus.bonus.sid = BonusSourceID(ID);

View File

@ -127,7 +127,7 @@ public:
void pickRandomObject(CRandomGenerator & rand) override;
void onHeroVisit(const CGHeroInstance * h) const override;
/// 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 afterRemoveFromMap(CMap * map);
@ -154,7 +154,7 @@ public:
protected:
/// 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")
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());
}
void COPWBonus::setProperty(ui8 what, ui32 val)
void COPWBonus::setProperty(ObjProperty what, ObjPropertyID identifier)
{
switch (what)
{
case ObjProperty::VISITORS:
visitors.insert(val);
visitors.insert(identifier.as<ObjectInstanceID>());
break;
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
visitors.clear();
@ -148,7 +148,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
{
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.id = heroID.getNum();
gb.id = heroID;
cb->giveHeroBonus(&gb);
SetMovePoints mp;
@ -187,10 +187,10 @@ CTownBonus::CTownBonus(const BuildingID & index, BuildingSubID::EBuildingSubID s
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)
visitors.insert(ObjectInstanceID(val));
visitors.insert(identifier.as<ObjectInstanceID>());
}
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;
}
gb.bonus = * bonus;
gb.id = h->id.getNum();
gb.id = h->id;
cb->giveHeroBonus(&gb);
if(bonus->duration == BonusDuration::PERMANENT)
@ -318,21 +318,21 @@ void CTownRewardableBuilding::newTurn(CRandomGenerator & rand) const
{
if(configuration.resetParameters.rewards)
{
cb->setObjProperty(town->id, ObjProperty::REWARD_RANDOMIZE, indexOnTV);
cb->setObjPropertyValue(town->id, ObjProperty::REWARD_RANDOMIZE, indexOnTV);
}
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)
{
case ObjProperty::VISITORS:
visitors.insert(ObjectInstanceID(val));
visitors.insert(identifier.as<ObjectInstanceID>());
break;
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
visitors.clear();
@ -341,7 +341,7 @@ void CTownRewardableBuilding::setProperty(ui8 what, ui32 val)
initObj(cb->gameState()->getRandomGenerator());
break;
case ObjProperty::REWARD_SELECT:
selectedReward = val;
selectedReward = identifier.getNum();
break;
}
}

View File

@ -69,8 +69,8 @@ protected:
class DLL_LINKAGE COPWBonus : public CGTownBuilding
{///used for OPW bonusing structures
public:
std::set<si32> visitors;
void setProperty(ui8 what, ui32 val) override;
std::set<ObjectInstanceID> visitors;
void setProperty(ObjProperty what, ObjPropertyID identifier) override;
void onHeroVisit (const CGHeroInstance * h) const override;
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
public:
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;
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;
public:
void setProperty(ui8 what, ui32 val) override;
void setProperty(ObjProperty what, ObjPropertyID identifier) override;
void onHeroVisit(const CGHeroInstance * h) const override;
void newTurn(CRandomGenerator & rand) const override;

View File

@ -53,28 +53,28 @@ int CGTownInstance::getSightRadius() const //returns sight distance
return ret;
}
void CGTownInstance::setPropertyDer(ui8 what, ui32 val)
void CGTownInstance::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{
///this is freakin' overcomplicated solution
switch (what)
{
case ObjProperty::STRUCTURE_ADD_VISITING_HERO:
bonusingBuildings[val]->setProperty(ObjProperty::VISITORS, visitingHero->id.getNum());
bonusingBuildings[identifier.getNum()]->setProperty(ObjProperty::VISITORS, visitingHero->id);
break;
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
bonusingBuildings[val]->setProperty(ObjProperty::STRUCTURE_CLEAR_VISITORS, 0);
bonusingBuildings[identifier.getNum()]->setProperty(ObjProperty::STRUCTURE_CLEAR_VISITORS, NumericID(0));
break;
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;
case ObjProperty::BONUS_VALUE_FIRST:
bonusValue.first = val;
bonusValue.first = identifier.getNum();
break;
case ObjProperty::BONUS_VALUE_SECOND:
bonusValue.second = val;
bonusValue.second = identifier.getNum();
break;
case ObjProperty::REWARD_RANDOMIZE:
bonusingBuildings[val]->setProperty(ObjProperty::REWARD_RANDOMIZE, 0);
bonusingBuildings[identifier.getNum()]->setProperty(ObjProperty::REWARD_RANDOMIZE, NumericID(0));
break;
}
}
@ -534,12 +534,12 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
resID = (resID==2)?1:resID;
int resVal = rand.nextInt(1, 4);//with size 1..4
cb->giveResource(tempOwner, static_cast<EGameResID>(resID), resVal);
cb->setObjProperty (id, ObjProperty::BONUS_VALUE_FIRST, resID);
cb->setObjProperty (id, ObjProperty::BONUS_VALUE_SECOND, resVal);
cb->setObjPropertyValue(id, ObjProperty::BONUS_VALUE_FIRST, resID);
cb->setObjPropertyValue(id, ObjProperty::BONUS_VALUE_SECOND, resVal);
}
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
//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
{
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)
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
{
//should never ever happen

View File

@ -211,7 +211,7 @@ public:
return defendingHero && garrisonHero && defendingHero != garrisonHero;
}
protected:
void setPropertyDer(ui8 what, ui32 val) override;
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void serializeJsonOptions(JsonSerializeFormat & handler) 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;
}
void CGSeerHut::setPropertyDer(ui8 what, ui32 val)
void CGSeerHut::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{
switch(what)
{
case CGSeerHut::SEERHUT_VISITED:
case ObjProperty::SEERHUT_VISITED:
{
quest->activeForPlayers.emplace(val);
quest->activeForPlayers.emplace(identifier.as<PlayerColor>());
break;
}
case CGSeerHut::SEERHUT_COMPLETE:
case ObjProperty::SEERHUT_COMPLETE:
{
quest->isCompleted = val;
quest->isCompleted = identifier.getNum();
quest->activeForPlayers.clear();
break;
}
@ -567,7 +567,7 @@ void CGSeerHut::newTurn(CRandomGenerator & rand) const
CRewardableObject::newTurn(rand);
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)
{
cb->setObjProperty(id, CGSeerHut::SEERHUT_VISITED, h->getOwner());
cb->setObjPropertyID(id, ObjProperty::SEERHUT_VISITED, h->getOwner());
AddQuest aq;
aq.quest = QuestInfo (quest, this, visitablePos());
@ -665,7 +665,7 @@ void CGSeerHut::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
if(answer)
{
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)
CGSeerHut::onHeroVisit(h);
else
cb->setObjProperty(id, CGSeerHut::SEERHUT_COMPLETE, false);
cb->setObjPropertyValue(id, ObjProperty::SEERHUT_COMPLETE, false);
}
bool CGQuestGuard::passableFor(PlayerColor color) const
@ -783,15 +783,14 @@ void CGKeys::reset()
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[player].insert(static_cast<ui8>(val));
playerKeyMap[identifier.as<PlayerColor>()].insert(subID);
}
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
@ -819,7 +818,7 @@ void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
int txt_id;
if (!wasMyColorVisited (h->getOwner()) )
{
cb->setObjProperty(id, h->tempOwner.getNum()+101, subID);
cb->setObjPropertyID(id, ObjProperty::KEYMASTER_VISITED, h->tempOwner);
txt_id=19;
}
else

View File

@ -144,10 +144,7 @@ public:
h & seerName;
}
protected:
static constexpr int SEERHUT_VISITED = 10;
static constexpr int SEERHUT_COMPLETE = 11;
void setPropertyDer(ui8 what, ui32 val) override;
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
void serializeJsonOptions(JsonSerializeFormat & handler) override;
};
@ -186,7 +183,7 @@ public:
h & static_cast<CGObjectInstance&>(*this);
}
protected:
void setPropertyDer(ui8 what, ui32 val) override;
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
};
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
{
cb->setObjProperty(id, ObjProperty::REWARD_CLEARED, true);
cb->setObjPropertyValue(id, ObjProperty::REWARD_CLEARED, true);
ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_ADD, id, hero->id);
cb->sendAndApply(&cov);
@ -177,7 +177,7 @@ void CRewardableObject::markAsVisited(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);
// 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);
}
void CRewardableObject::setPropertyDer(ui8 what, ui32 val)
void CRewardableObject::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{
switch (what)
{
@ -346,10 +346,10 @@ void CRewardableObject::setPropertyDer(ui8 what, ui32 val)
initObj(cb->gameState()->getRandomGenerator());
break;
case ObjProperty::REWARD_SELECT:
selectedReward = val;
selectedReward = identifier.getNum();
break;
case ObjProperty::REWARD_CLEARED:
onceVisitableObjectCleared = val;
onceVisitableObjectCleared = identifier.getNum();
break;
}
}
@ -360,11 +360,11 @@ void CRewardableObject::newTurn(CRandomGenerator & rand) const
{
if (configuration.resetParameters.rewards)
{
cb->setObjProperty(id, ObjProperty::REWARD_RANDOMIZE, 0);
cb->setObjPropertyValue(id, ObjProperty::REWARD_RANDOMIZE, 0);
}
if (configuration.resetParameters.visitors)
{
cb->setObjProperty(id, ObjProperty::REWARD_CLEARED, false);
cb->setObjPropertyValue(id, ObjProperty::REWARD_CLEARED, false);
ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_CLEAR, id);
cb->sendAndApply(&cov);
}

View File

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

View File

@ -49,7 +49,7 @@ void IObjectInterface::initObj(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

View File

@ -10,6 +10,7 @@
#pragma once
#include "../networkPacks/EInfoWindowMode.h"
#include "../networkPacks/ObjProperty.h"
#include "../constants/EntityIdentifiers.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -46,7 +47,7 @@ public:
virtual void newTurn(CRandomGenerator & rand) const;
virtual void initObj(CRandomGenerator & rand); //synchr
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
//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];
}
void CTeamVisited::setPropertyDer(ui8 what, ui32 val)
void CTeamVisited::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{
if(what == CTeamVisited::OBJPROP_VISITED)
players.insert(PlayerColor(val));
if(what == ObjProperty::VISITED)
players.insert(identifier.as<PlayerColor>());
}
bool CTeamVisited::wasVisited(PlayerColor player) const
@ -1195,13 +1195,13 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
cb->sendAndApply(&iw);
// 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);
// mark that particular obelisk as visited for all players in the team
for(const auto & color : ts->players)
{
cb->setObjProperty(id, CGObelisk::OBJPROP_VISITED, color.getNum());
cb->setObjPropertyID(id, ObjProperty::VISITED, color);
}
}
else
@ -1228,14 +1228,14 @@ std::string CGObelisk::getHoverText(PlayerColor player) const
return getObjectName() + " " + visitedTxt(wasVisited(player));
}
void CGObelisk::setPropertyDer( ui8 what, ui32 val )
void CGObelisk::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{
switch(what)
{
case CGObelisk::OBJPROP_INC:
case ObjProperty::OBELISK_VISITED:
{
auto progress = ++visited[TeamID(val)];
logGlobal->debug("Player %d: obelisk progress %d / %d", val, static_cast<int>(progress) , static_cast<int>(obeliskCount));
auto progress = ++visited[identifier.as<TeamID>()];
logGlobal->debug("Player %d: obelisk progress %d / %d", identifier.getNum(), static_cast<int>(progress) , static_cast<int>(obeliskCount));
if(progress > obeliskCount)
{
@ -1246,7 +1246,7 @@ void CGObelisk::setPropertyDer( ui8 what, ui32 val )
break;
}
default:
CTeamVisited::setPropertyDer(what, val);
CTeamVisited::setPropertyDer(what, identifier);
break;
}
}
@ -1263,7 +1263,7 @@ void CGLighthouse::onHeroVisit( const CGHeroInstance * h ) const
if(oldOwner.isValidPlayer()) //remove bonus from old owner
{
RemoveBonus rb(GiveBonus::ETarget::PLAYER);
rb.whoID = oldOwner.getNum();
rb.whoID = oldOwner;
rb.source = BonusSource::OBJECT_INSTANCE;
rb.id = BonusSourceID(id);
cb->sendAndApply(&rb);
@ -1285,7 +1285,7 @@ void CGLighthouse::giveBonusTo(const PlayerColor & player, bool onInit) const
GiveBonus gb(GiveBonus::ETarget::PLAYER);
gb.bonus.type = BonusType::MOVEMENT;
gb.bonus.val = 500;
gb.id = player.getNum();
gb.id = player;
gb.bonus.duration = BonusDuration::PERMANENT;
gb.bonus.source = BonusSource::OBJECT_INSTANCE;
gb.bonus.sid = BonusSourceID(id);

View File

@ -29,15 +29,13 @@ public:
bool wasVisited (const CGHeroInstance * h) const override;
bool wasVisited(PlayerColor player) const override;
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)
{
h & static_cast<CGObjectInstance&>(*this);
h & players;
}
static constexpr int OBJPROP_VISITED = 10;
};
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
{
public:
static constexpr int OBJPROP_INC = 20;
static ui8 obeliskCount; //how many obelisks are on map
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);
}
protected:
void setPropertyDer(ui8 what, ui32 val) override;
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
};
class DLL_LINKAGE CGLighthouse : public CGObjectInstance

View File

@ -971,18 +971,15 @@ void GiveBonus::applyGs(CGameState *gs)
CBonusSystemNode *cbsn = nullptr;
switch(who)
{
case ETarget::HERO:
cbsn = gs->getHero(ObjectInstanceID(id));
case ETarget::OBJECT:
cbsn = dynamic_cast<CBonusSystemNode*>(gs->getObjInstance(id.as<ObjectInstanceID>()));
break;
case ETarget::PLAYER:
cbsn = gs->getPlayerState(PlayerColor(id));
break;
case ETarget::TOWN:
cbsn = gs->getTown(ObjectInstanceID(id));
cbsn = gs->getPlayerState(id.as<PlayerColor>());
break;
case ETarget::BATTLE:
assert(Bonus::OneBattle(&bonus));
cbsn = dynamic_cast<CBonusSystemNode*>(gs->getBattle(BattleID(id)));
cbsn = dynamic_cast<CBonusSystemNode*>(gs->getBattle(id.as<BattleID>()));
break;
}
@ -1114,11 +1111,20 @@ void PlayerReinitInterface::applyGs(CGameState *gs)
void RemoveBonus::applyGs(CGameState *gs)
{
CBonusSystemNode * node = nullptr;
if (who == GiveBonus::ETarget::HERO)
node = gs->getHero(ObjectInstanceID(whoID));
else
node = gs->getPlayerState(PlayerColor(whoID));
CBonusSystemNode *node = nullptr;
switch(who)
{
case GiveBonus::ETarget::OBJECT:
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();
@ -1483,7 +1489,7 @@ void NewObject::applyGs(CGameState *gs)
const TerrainTile & t = gs->map->getTile(targetPos);
terrainType = t.terType->getId();
auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
auto handler = VLC->objtypeh->getHandlerFor(ID, subID.getNum());
CGObjectInstance * o = handler->create();
handler->configureObject(o, gs->getRandomGenerator());
@ -1499,13 +1505,13 @@ void NewObject::applyGs(CGameState *gs)
cre->character = 2;
cre->gainedArtifact = ArtifactID::NONE;
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());
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;
}
@ -2049,9 +2055,9 @@ void SetObjectProperty::applyGs(CGameState * gs) const
if(state->towns.empty())
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);
//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();
nodeToMove.detachFrom(cai->whereShouldBeAttached(gs));
obj->setProperty(what,val);
obj->setProperty(what, identifier);
nodeToMove.attachTo(cai->whereShouldBeAttached(gs));
}
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 "EntityChanges.h"
#include "NetPacksBase.h"
#include "ObjProperty.h"
#include "../CCreatureSet.h"
#include "../MetaString.h"
@ -366,17 +367,17 @@ struct DLL_LINKAGE SetAvailableHero : 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)
{
}
void applyGs(CGameState * gs);
ETarget who = ETarget::HERO; //who receives bonus
si32 id = 0; //hero. town or player id - whoever receives it
ETarget who = ETarget::OBJECT;
VariantIdentifier<ObjectInstanceID, PlayerColor, BattleID> id;
Bonus bonus;
MetaString bdescr;
@ -388,7 +389,7 @@ struct DLL_LINKAGE GiveBonus : public CPackForClient
h & id;
h & bdescr;
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
{
explicit RemoveBonus(GiveBonus::ETarget Who = GiveBonus::ETarget::HERO)
explicit RemoveBonus(GiveBonus::ETarget Who = GiveBonus::ETarget::OBJECT)
:who(Who)
{
}
@ -469,7 +470,7 @@ struct DLL_LINKAGE RemoveBonus : public CPackForClient
void applyGs(CGameState * gs);
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
BonusSource source;
@ -574,7 +575,7 @@ struct DLL_LINKAGE UpdateCastleEvents : public CPackForClient
struct DLL_LINKAGE ChangeFormation : public CPackForClient
{
ObjectInstanceID hid;
ui8 formation = 0;
EArmyFormation formation{};
void applyGs(CGameState * gs) const;
void visitTyped(ICPackVisitor & visitor) override;
@ -781,9 +782,9 @@ struct DLL_LINKAGE NewObject : public CPackForClient
void applyGs(CGameState * gs);
/// Object ID to create
Obj ID;
MapObjectID ID;
/// Object secondary ID to create
ui32 subID = 0;
VariantIdentifier<MapObjectSubID, HeroTypeID, CreatureID, BoatId> subID;
/// Position of visitable tile of created object
int3 targetPos;
/// Which player initiated creation of this object
@ -806,7 +807,8 @@ struct DLL_LINKAGE SetAvailableArtifacts : public CPackForClient
{
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;
void visitTyped(ICPackVisitor & visitor) override;
@ -1207,38 +1209,16 @@ struct DLL_LINKAGE InfoWindow : public CPackForClient //103 - displays simple i
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
{
void applyGs(CGameState * gs) const;
ObjectInstanceID id;
ui8 what = 0; // see ObjProperty enum
ui32 val = 0;
ObjProperty what{};
ObjPropertyID identifier;
int32_t value = 0;
SetObjectProperty() = default;
SetObjectProperty(const ObjectInstanceID & ID, ui8 What, ui32 Val)
: id(ID)
, what(What)
, val(Val)
{
}
void visitTyped(ICPackVisitor & visitor) override;
@ -1246,7 +1226,8 @@ struct DLL_LINKAGE SetObjectProperty : public CPackForClient
{
h & id;
h & what;
h & val;
h & identifier;
h & value;
}
};

View File

@ -11,6 +11,7 @@
#include "ArtifactLocation.h"
#include "NetPacksBase.h"
#include "TradeItem.h"
#include "../int3.h"
#include "../battle/BattleAction.h"
@ -472,7 +473,8 @@ struct DLL_LINKAGE TradeOnMarketplace : public CPackForServer
ObjectInstanceID heroId;
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
void visitTyped(ICPackVisitor & visitor) override;
@ -493,13 +495,13 @@ struct DLL_LINKAGE SetFormation : public CPackForServer
{
SetFormation() = default;
;
SetFormation(const ObjectInstanceID & HID, ui8 Formation)
SetFormation(const ObjectInstanceID & HID, EArmyFormation Formation)
: hid(HID)
, formation(Formation)
{
}
ObjectInstanceID hid;
ui8 formation = 0;
EArmyFormation formation{};
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)
{
GiveBonus gb;
gb.who = GiveBonus::ETarget::HERO;
gb.who = GiveBonus::ETarget::OBJECT;
gb.bonus = bonus;
gb.id = hero->id.getNum();
gb.id = hero->id;
cb->giveHeroBonus(&gb);
}

View File

@ -83,7 +83,7 @@ ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(SpellCastEnviron
for(const Bonus & b : bonuses)
{
GiveBonus gb;
gb.id = parameters.caster->getCasterUnitId();
gb.id = ObjectInstanceID(parameters.caster->getCasterUnitId());
gb.bonus = b;
env->apply(&gb);
}
@ -323,7 +323,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
}
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));
env->apply(&gb);

View File

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

View File

@ -886,7 +886,7 @@ void CGameHandler::onNewTurn()
if (newMonth)
{
SetAvailableArtifacts saa;
saa.id = -1;
saa.id = ObjectInstanceID::NONE;
pickAllowedArtsSet(saa.arts, getRandomGenerator());
sendAndApply(&saa);
}
@ -1328,8 +1328,8 @@ bool CGameHandler::teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui
void CGameHandler::setOwner(const CGObjectInstance * obj, const PlayerColor owner)
{
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};
checkVictoryLossConditions(playerColors);
@ -2973,12 +2973,12 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, GameRe
SetAvailableArtifacts saa;
if(dynamic_cast<const CGTownInstance *>(m))
{
saa.id = -1;
saa.id = ObjectInstanceID::NONE;
saa.arts = CGTownInstance::merchantArtifacts;
}
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;
}
else
@ -3044,23 +3044,23 @@ bool CGameHandler::buySecSkill(const IMarket *m, const CGHeroInstance *h, Second
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
market->getOffer(id1, id2, b1, b2, EMarketMode::RESOURCE_RESOURCE);
int units = val / b1; //how many base quantities we trade
market->getOffer(toSell, toBuy, b1, b2, EMarketMode::RESOURCE_RESOURCE);
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.");
}
giveResource(player, GameResID(id1), - b1 * units);
giveResource(player, GameResID(id2), b2 * units);
giveResource(player, toSell, -b1 * amountToBoy);
giveResource(player, toBuy, b2 * amountToBoy);
return true;
}
@ -3144,7 +3144,7 @@ bool CGameHandler::sendResources(ui32 val, PlayerColor player, GameResID r1, Pla
return true;
}
bool CGameHandler::setFormation(ObjectInstanceID hid, ui8 formation)
bool CGameHandler::setFormation(ObjectInstanceID hid, EArmyFormation formation)
{
const CGHeroInstance *h = getHero(hid);
if (!h)
@ -4047,8 +4047,8 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID)
createObject(*tile, PlayerColor::NEUTRAL, Obj::MONSTER, creatureID);
auto monsterId = getTopObj(*tile)->id;
setObjProperty(monsterId, ObjProperty::MONSTER_COUNT, count);
setObjProperty(monsterId, ObjProperty::MONSTER_POWER, (si64)1000*count);
setObjPropertyValue(monsterId, ObjProperty::MONSTER_COUNT, count);
setObjPropertyValue(monsterId, ObjProperty::MONSTER_POWER, (si64)1000*count);
}
tiles.erase(tile); //not use it again
}
@ -4170,12 +4170,21 @@ bool CGameHandler::isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, con
return true;
}
void CGameHandler::setObjProperty(ObjectInstanceID objid, int prop, si64 val)
void CGameHandler::setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value)
{
SetObjectProperty sob;
sob.id = objid;
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);
}
@ -4209,7 +4218,7 @@ scripting::Pool * CGameHandler::getGlobalContextPool() const
//}
#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;
no.ID = type;

View File

@ -101,7 +101,7 @@ public:
//do sth
void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> &spells) 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 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;
@ -156,7 +156,8 @@ public:
/// Returns hero that is currently visiting this object, or nullptr if no visit is active
const CGHeroInstance * getVisitingHero(const CGObjectInstance *obj);
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(const std::string & msg, PlayerColor player) override;
@ -182,8 +183,8 @@ public:
bool queryReply( QueryID qid, std::optional<int32_t> reply, PlayerColor player );
bool buildBoat( ObjectInstanceID objid, PlayerColor player );
bool setFormation( ObjectInstanceID hid, ui8 formation );
bool tradeResources(const IMarket *market, ui32 val, PlayerColor player, ui32 id1, ui32 id2);
bool setFormation( ObjectInstanceID hid, EArmyFormation formation );
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 sendResources(ui32 val, PlayerColor player, GameResID r1, PlayerColor r2);
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:
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;
case EMarketMode::RESOURCE_PLAYER:
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;
case EMarketMode::CREATURE_RESOURCE:
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;
case EMarketMode::RESOURCE_ARTIFACT:
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;
case EMarketMode::ARTIFACT_RESOURCE:
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;
case EMarketMode::CREATURE_UNDEAD:
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;
case EMarketMode::RESOURCE_SKILL:
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;
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());
for(auto const & slot : pack.r1)
slotIDs.push_back(slot.as<SlotID>());
result = gh.sacrificeCreatures(market, hero, slotIDs, count);
return;
}
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);
return;
}

View File

@ -122,8 +122,8 @@ void BattleProcessor::startBattlePrimary(const CArmedInstance *army1, const CArm
{
for(auto bonus : attackerInfo->battleBonuses)
{
GiveBonus giveBonus(GiveBonus::ETarget::HERO);
giveBonus.id = hero1->id.getNum();
GiveBonus giveBonus(GiveBonus::ETarget::OBJECT);
giveBonus.id = hero1->id;
giveBonus.bonus = bonus;
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);
///Give all spells with bonus (to allow banned spells)
GiveBonus giveBonus(GiveBonus::ETarget::HERO);
giveBonus.id = hero->id.getNum();
GiveBonus giveBonus(GiveBonus::ETarget::OBJECT);
giveBonus.id = hero->id;
giveBonus.bonus = Bonus(BonusDuration::PERMANENT, BonusType::SPELLS_OF_LEVEL, BonusSource::OTHER, 0, BonusSourceID());
//start with level 0 to skip abilities
for (int level = 1; level <= GameConstants::SPELL_LEVELS; level++)
@ -300,11 +300,11 @@ void PlayerMessageProcessor::cheatMovement(PlayerColor player, const CGHeroInsta
gameHandler->sendAndApply(&smp);
GiveBonus gb(GiveBonus::ETarget::HERO);
GiveBonus gb(GiveBonus::ETarget::OBJECT);
gb.bonus.type = BonusType::FREE_SHIP_BOARDING;
gb.bonus.duration = BonusDuration::ONE_DAY;
gb.bonus.source = BonusSource::OTHER;
gb.id = hero->id.getNum();
gb.id = hero->id;
gameHandler->giveHeroBonus(&gb);
}