|
@@ -10,6 +10,7 @@
|
|
|
|
|
|
#include "StdInc.h"
|
|
|
#include "CGTownInstance.h"
|
|
|
+#include "CGTownBuilding.h"
|
|
|
#include "CObjectClassesHandler.h"
|
|
|
#include "../spells/CSpellHandler.h"
|
|
|
#include "../bonuses/Bonus.h"
|
|
@@ -52,14 +53,14 @@ void CGTownInstance::setPropertyDer(ui8 what, ui32 val)
|
|
|
///this is freakin' overcomplicated solution
|
|
|
switch (what)
|
|
|
{
|
|
|
- case ObjProperty::STRUCTURE_ADD_VISITING_HERO:
|
|
|
- bonusingBuildings[val]->setProperty (ObjProperty::VISITORS, visitingHero->id.getNum());
|
|
|
+ case ObjProperty::STRUCTURE_ADD_VISITING_HERO:
|
|
|
+ bonusingBuildings[val]->setProperty(ObjProperty::VISITORS, visitingHero->id.getNum());
|
|
|
break;
|
|
|
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
|
|
|
- bonusingBuildings[val]->setProperty (ObjProperty::STRUCTURE_CLEAR_VISITORS, 0);
|
|
|
+ bonusingBuildings[val]->setProperty(ObjProperty::STRUCTURE_CLEAR_VISITORS, 0);
|
|
|
break;
|
|
|
case ObjProperty::STRUCTURE_ADD_GARRISONED_HERO: //add garrisoned hero to visitors
|
|
|
- bonusingBuildings[val]->setProperty (ObjProperty::VISITORS, garrisonHero->id.getNum());
|
|
|
+ bonusingBuildings[val]->setProperty(ObjProperty::VISITORS, garrisonHero->id.getNum());
|
|
|
break;
|
|
|
case ObjProperty::BONUS_VALUE_FIRST:
|
|
|
bonusValue.first = val;
|
|
@@ -67,6 +68,9 @@ void CGTownInstance::setPropertyDer(ui8 what, ui32 val)
|
|
|
case ObjProperty::BONUS_VALUE_SECOND:
|
|
|
bonusValue.second = val;
|
|
|
break;
|
|
|
+ case ObjProperty::REWARD_RANDOMIZE:
|
|
|
+ bonusingBuildings[val]->setProperty(ObjProperty::REWARD_RANDOMIZE, 0);
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
CGTownInstance::EFortLevel CGTownInstance::fortLevel() const //0 - none, 1 - fort, 2 - citadel, 3 - castle
|
|
@@ -259,6 +263,12 @@ void CGTownInstance::setOwner(const PlayerColor & player) const
|
|
|
cb->setOwner(this, player);
|
|
|
}
|
|
|
|
|
|
+void CGTownInstance::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
|
|
+{
|
|
|
+ for (auto building : bonusingBuildings)
|
|
|
+ building->blockingDialogAnswered(hero, answer);
|
|
|
+}
|
|
|
+
|
|
|
void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
|
|
|
{
|
|
|
if(!cb->gameState()->getPlayerRelations( getOwner(), h->getOwner() ))//if this is enemy
|
|
@@ -365,7 +375,7 @@ bool CGTownInstance::isBonusingBuildingAdded(BuildingID::EBuildingID bid) const
|
|
|
return present != bonusingBuildings.end();
|
|
|
}
|
|
|
|
|
|
-void CGTownInstance::addTownBonuses()
|
|
|
+void CGTownInstance::addTownBonuses(CRandomGenerator & rand)
|
|
|
{
|
|
|
for(const auto & kvp : town->buildings)
|
|
|
{
|
|
@@ -377,6 +387,9 @@ void CGTownInstance::addTownBonuses()
|
|
|
|
|
|
if(kvp.second->IsWeekBonus())
|
|
|
bonusingBuildings.push_back(new COPWBonus(kvp.second->bid, kvp.second->subId, this));
|
|
|
+
|
|
|
+ if(kvp.second->subId == BuildingSubID::CUSTOM_VISITING_REWARD)
|
|
|
+ bonusingBuildings.push_back(new CTownRewardableBuilding(kvp.second->bid, kvp.second->subId, this, rand));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -465,7 +478,7 @@ void CGTownInstance::initObj(CRandomGenerator & rand) ///initialize town structu
|
|
|
}
|
|
|
}
|
|
|
initOverriddenBids();
|
|
|
- addTownBonuses(); //add special bonuses from buildings to the bonusingBuildings vector.
|
|
|
+ addTownBonuses(rand); //add special bonuses from buildings to the bonusingBuildings vector.
|
|
|
recreateBuildingsBonuses();
|
|
|
updateAppearance();
|
|
|
}
|
|
@@ -487,10 +500,8 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
|
|
|
cb->setObjProperty (id, ObjProperty::BONUS_VALUE_FIRST, resID);
|
|
|
cb->setObjProperty (id, ObjProperty::BONUS_VALUE_SECOND, resVal);
|
|
|
}
|
|
|
-
|
|
|
- const auto * manaVortex = getBonusingBuilding(BuildingSubID::MANA_VORTEX);
|
|
|
-
|
|
|
- if (manaVortex != nullptr)
|
|
|
+
|
|
|
+ for(const auto * manaVortex : getBonusingBuildings(BuildingSubID::MANA_VORTEX))
|
|
|
cb->setObjProperty(id, ObjProperty::STRUCTURE_CLEAR_VISITORS, manaVortex->indexOnTV); //reset visitors for Mana Vortex
|
|
|
|
|
|
//get Mana Vortex or Stables bonuses
|
|
@@ -502,57 +513,60 @@ void CGTownInstance::newTurn(CRandomGenerator & rand) const
|
|
|
cb->visitCastleObjects(this, garrisonHero);
|
|
|
|
|
|
if (tempOwner == PlayerColor::NEUTRAL) //garrison growth for neutral towns
|
|
|
+ {
|
|
|
+ std::vector<SlotID> nativeCrits; //slots
|
|
|
+ for(const auto & elem : Slots())
|
|
|
{
|
|
|
- std::vector<SlotID> nativeCrits; //slots
|
|
|
- for(const auto & elem : Slots())
|
|
|
+ if (elem.second->type->getFaction() == subID) //native
|
|
|
{
|
|
|
- if (elem.second->type->getFaction() == subID) //native
|
|
|
- {
|
|
|
- nativeCrits.push_back(elem.first); //collect matching slots
|
|
|
- }
|
|
|
+ nativeCrits.push_back(elem.first); //collect matching slots
|
|
|
}
|
|
|
- if(!nativeCrits.empty())
|
|
|
+ }
|
|
|
+ if(!nativeCrits.empty())
|
|
|
+ {
|
|
|
+ SlotID pos = *RandomGeneratorUtil::nextItem(nativeCrits, rand);
|
|
|
+ StackLocation sl(this, pos);
|
|
|
+
|
|
|
+ const CCreature *c = getCreature(pos);
|
|
|
+ if (rand.nextInt(99) < 90 || c->upgrades.empty()) //increase number if no upgrade available
|
|
|
{
|
|
|
- SlotID pos = *RandomGeneratorUtil::nextItem(nativeCrits, rand);
|
|
|
- StackLocation sl(this, pos);
|
|
|
-
|
|
|
- const CCreature *c = getCreature(pos);
|
|
|
- if (rand.nextInt(99) < 90 || c->upgrades.empty()) //increase number if no upgrade available
|
|
|
- {
|
|
|
- cb->changeStackCount(sl, c->getGrowth());
|
|
|
- }
|
|
|
- else //upgrade
|
|
|
- {
|
|
|
- cb->changeStackType(sl, VLC->creh->objects[*c->upgrades.begin()]);
|
|
|
- }
|
|
|
+ cb->changeStackCount(sl, c->getGrowth());
|
|
|
}
|
|
|
- if ((stacksCount() < GameConstants::ARMY_SIZE && rand.nextInt(99) < 25) || Slots().empty()) //add new stack
|
|
|
+ else //upgrade
|
|
|
+ {
|
|
|
+ cb->changeStackType(sl, VLC->creh->objects[*c->upgrades.begin()]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ((stacksCount() < GameConstants::ARMY_SIZE && rand.nextInt(99) < 25) || Slots().empty()) //add new stack
|
|
|
+ {
|
|
|
+ int i = rand.nextInt(std::min(GameConstants::CREATURES_PER_TOWN, cb->getDate(Date::MONTH) << 1) - 1);
|
|
|
+ if (!town->creatures[i].empty())
|
|
|
{
|
|
|
- int i = rand.nextInt(std::min(GameConstants::CREATURES_PER_TOWN, cb->getDate(Date::MONTH) << 1) - 1);
|
|
|
- if (!town->creatures[i].empty())
|
|
|
- {
|
|
|
- CreatureID c = town->creatures[i][0];
|
|
|
- SlotID n;
|
|
|
-
|
|
|
- TQuantity count = creatureGrowth(i);
|
|
|
- if (!count) // no dwelling
|
|
|
- count = VLC->creh->objects[c]->getGrowth();
|
|
|
-
|
|
|
- {//no lower tiers or above current month
|
|
|
-
|
|
|
- if ((n = getSlotFor(c)).validSlot())
|
|
|
- {
|
|
|
- StackLocation sl(this, n);
|
|
|
- if (slotEmpty(n))
|
|
|
- cb->insertNewStack(sl, VLC->creh->objects[c], count);
|
|
|
- else //add to existing
|
|
|
- cb->changeStackCount(sl, count);
|
|
|
- }
|
|
|
+ CreatureID c = town->creatures[i][0];
|
|
|
+ SlotID n;
|
|
|
+
|
|
|
+ TQuantity count = creatureGrowth(i);
|
|
|
+ if (!count) // no dwelling
|
|
|
+ count = VLC->creatures()->getByIndex(c)->getGrowth();
|
|
|
+
|
|
|
+ {//no lower tiers or above current month
|
|
|
+
|
|
|
+ if ((n = getSlotFor(c)).validSlot())
|
|
|
+ {
|
|
|
+ StackLocation sl(this, n);
|
|
|
+ if (slotEmpty(n))
|
|
|
+ cb->insertNewStack(sl, VLC->creh->objects[c], count);
|
|
|
+ else //add to existing
|
|
|
+ cb->changeStackCount(sl, count);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ for(const auto * rewardableBuilding : getBonusingBuildings(BuildingSubID::CUSTOM_VISITING_REWARD))
|
|
|
+ rewardableBuilding->newTurn(rand);
|
|
|
}
|
|
|
/*
|
|
|
int3 CGTownInstance::getSightCenter() const
|
|
@@ -805,7 +819,9 @@ void CGTownInstance::recreateBuildingsBonuses()
|
|
|
|
|
|
void CGTownInstance::setVisitingHero(CGHeroInstance *h)
|
|
|
{
|
|
|
- assert(!!visitingHero == !h);
|
|
|
+ if(visitingHero.get() == h)
|
|
|
+ return;
|
|
|
+
|
|
|
if(h)
|
|
|
{
|
|
|
PlayerState *p = cb->gameState()->getPlayerState(h->tempOwner);
|
|
@@ -828,7 +844,9 @@ void CGTownInstance::setVisitingHero(CGHeroInstance *h)
|
|
|
|
|
|
void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
|
|
|
{
|
|
|
- assert(!!garrisonHero == !h);
|
|
|
+ if(garrisonHero.get() == h)
|
|
|
+ return;
|
|
|
+
|
|
|
if(h)
|
|
|
{
|
|
|
PlayerState *p = cb->gameState()->getPlayerState(h->tempOwner);
|
|
@@ -906,14 +924,15 @@ const CArmedInstance * CGTownInstance::getUpperArmy() const
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
-const CGTownBuilding * CGTownInstance::getBonusingBuilding(BuildingSubID::EBuildingSubID subId) const
|
|
|
+std::vector<const CGTownBuilding *> CGTownInstance::getBonusingBuildings(BuildingSubID::EBuildingSubID subId) const
|
|
|
{
|
|
|
+ std::vector<const CGTownBuilding *> ret;
|
|
|
for(auto * const building : bonusingBuildings)
|
|
|
{
|
|
|
if(building->getBuildingSubtype() == subId)
|
|
|
- return building;
|
|
|
+ ret.push_back(building);
|
|
|
}
|
|
|
- return nullptr;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
|