mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
commit
bf62e47481
@ -405,7 +405,10 @@ std::optional<BattleAction> CBattleCallback::makeSurrenderRetreatDecision(const
|
||||
|
||||
std::shared_ptr<CPlayerBattleCallback> CBattleCallback::getBattle(const BattleID & battleID)
|
||||
{
|
||||
return activeBattles.at(battleID);
|
||||
if (activeBattles.count(battleID))
|
||||
return activeBattles.at(battleID);
|
||||
|
||||
throw std::runtime_error("Failed to find battle " + std::to_string(battleID.getNum()) + " of player " + player->toString() + ". Number of ongoing battles: " + std::to_string(activeBattles.size()));
|
||||
}
|
||||
|
||||
std::optional<PlayerColor> CBattleCallback::getPlayerID() const
|
||||
@ -415,10 +418,18 @@ std::optional<PlayerColor> CBattleCallback::getPlayerID() const
|
||||
|
||||
void CBattleCallback::onBattleStarted(const IBattleInfo * info)
|
||||
{
|
||||
if (activeBattles.count(info->getBattleID()) > 0)
|
||||
throw std::runtime_error("Player " + player->toString() + " is already engaged in battle " + std::to_string(info->getBattleID().getNum()));
|
||||
|
||||
logGlobal->debug("Battle %d started for player %s", info->getBattleID(), player->toString());
|
||||
activeBattles[info->getBattleID()] = std::make_shared<CPlayerBattleCallback>(info, *getPlayerID());
|
||||
}
|
||||
|
||||
void CBattleCallback::onBattleEnded(const BattleID & battleID)
|
||||
{
|
||||
if (activeBattles.count(battleID) == 0)
|
||||
throw std::runtime_error("Player " + player->toString() + " is not engaged in battle " + std::to_string(battleID.getNum()));
|
||||
|
||||
logGlobal->debug("Battle %d ended for player %s", battleID, player->toString());
|
||||
activeBattles.erase(battleID);
|
||||
}
|
||||
|
@ -560,18 +560,16 @@ int CClient::sendRequest(const CPackForServer * request, PlayerColor player)
|
||||
|
||||
void CClient::battleStarted(const BattleInfo * info)
|
||||
{
|
||||
std::shared_ptr<CPlayerInterface> att, def;
|
||||
auto & leftSide = info->sides[0];
|
||||
auto & rightSide = info->sides[1];
|
||||
|
||||
for(auto & battleCb : battleCallbacks)
|
||||
{
|
||||
if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; })
|
||||
|| !battleCb.first.isValidPlayer())
|
||||
{
|
||||
if(!battleCb.first.isValidPlayer() || battleCb.first == leftSide.color || battleCb.first == rightSide.color)
|
||||
battleCb.second->onBattleStarted(info);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CPlayerInterface> att, def;
|
||||
auto & leftSide = info->sides[0], & rightSide = info->sides[1];
|
||||
|
||||
//If quick combat is not, do not prepare interfaces for battleint
|
||||
auto callBattleStart = [&](PlayerColor color, ui8 side)
|
||||
{
|
||||
|
@ -202,6 +202,7 @@ public:
|
||||
bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, bool transit = false, PlayerColor asker = PlayerColor::NEUTRAL) override {return false;};
|
||||
void giveHeroBonus(GiveBonus * bonus) override {};
|
||||
void setMovePoints(SetMovePoints * smp) override {};
|
||||
void setMovePoints(ObjectInstanceID hid, int val, bool absolute) override {};
|
||||
void setManaPoints(ObjectInstanceID hid, int val) override {};
|
||||
void giveHero(ObjectInstanceID id, PlayerColor player, ObjectInstanceID boatId = ObjectInstanceID()) override {};
|
||||
void changeObjPos(ObjectInstanceID objid, int3 newPos, const PlayerColor & initiator) override {};
|
||||
|
@ -691,7 +691,7 @@ void AdventureMapInterface::onTileHovered(const int3 &mapPos)
|
||||
if(pathNode->layer == EPathfindingLayer::LAND)
|
||||
CCS->curh->set(cursorMove[turns]);
|
||||
else
|
||||
CCS->curh->set(cursorSailVisit[turns]);
|
||||
CCS->curh->set(cursorSail[turns]);
|
||||
break;
|
||||
|
||||
case EPathNodeAction::VISIT:
|
||||
@ -706,6 +706,15 @@ void AdventureMapInterface::onTileHovered(const int3 &mapPos)
|
||||
}
|
||||
else if(pathNode->layer == EPathfindingLayer::LAND)
|
||||
CCS->curh->set(cursorVisit[turns]);
|
||||
else if (pathNode->layer == EPathfindingLayer::SAIL &&
|
||||
objAtTile &&
|
||||
objAtTile->isCoastVisitable() &&
|
||||
pathNode->theNodeBefore &&
|
||||
pathNode->theNodeBefore->layer == EPathfindingLayer::LAND )
|
||||
{
|
||||
// exception - when visiting shipwreck located on coast from land - show 'horse' cursor, not 'ship' cursor
|
||||
CCS->curh->set(cursorVisit[turns]);
|
||||
}
|
||||
else
|
||||
CCS->curh->set(cursorSailVisit[turns]);
|
||||
break;
|
||||
|
@ -411,12 +411,6 @@
|
||||
"type" : "LEVEL_SPELL_IMMUNITY",
|
||||
"val" : 5
|
||||
},
|
||||
"hateGiants" :
|
||||
{
|
||||
"type" : "HATE",
|
||||
"subtype" : "creature.giant",
|
||||
"val" : 50
|
||||
},
|
||||
"hateTitans" :
|
||||
{
|
||||
"type" : "HATE",
|
||||
|
@ -61,6 +61,10 @@
|
||||
"positive": true,
|
||||
},
|
||||
|
||||
// If true, then creature capable of casting this spell can cast this spell on itself
|
||||
// If false, then creature can only cast this spell on other units
|
||||
"canCastOnSelf" : false,
|
||||
|
||||
// If true, spell won't be available on a map without water
|
||||
"onlyOnWaterMap" : true,
|
||||
|
||||
|
@ -185,7 +185,7 @@ Following options can be used to configure simultaneous turns:
|
||||
|
||||
While simultaneous turns are active, VCMI tracks contacts for each pair of player separately.
|
||||
|
||||
Players are considered to be "in contact" if movement range of their heroes at the start of turn overlaps, or, in other words - if their heroes can meet on this turn if both walk towards each other. When calculating movement range, game uses same rules as standard movement range calculation in vcmi, meaning that game will track movement through monoliths and subterranean gates, but will not account for any removable obstacles, such as wandering monsters or treasures that block path between heroes. At the moment, game will not account for any ways to extend movement range - Dimension Door or Town Portal spells, visiting map objects such as Stables, releasing heroes from prisons, etc.
|
||||
Players are considered to be "in contact" if movement range of their heroes at the start of turn overlaps, or, in other words - if their heroes can meet on this turn if both walk towards each other. When calculating movement range, game uses rules similar to standard movement range calculation in vcmi, meaning that game will track movement through monoliths and subterranean gates, but will not account for any removable obstacles, such as pickable treasures that block path between heroes. Any existing wandering monsters that block path between heroes are ignored for range calculation. At the moment, game will not account for any ways to extend movement range - Dimension Door or Town Portal spells, visiting map objects such as Stables, releasing heroes from prisons, etc.
|
||||
|
||||
Once detected, contact can never be "lost". If game detected contact between two players, this contact will remain active till the end of the game, even if their heroes move far enough from each other.
|
||||
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
virtual bool isMagical() const = 0; //Should this spell considered as magical effect or as ability (like dendroid's bind)
|
||||
|
||||
virtual bool hasSchool(SpellSchool school) const = 0;
|
||||
virtual bool canCastOnSelf() const = 0;
|
||||
virtual void forEachSchool(const SchoolCallback & cb) const = 0;
|
||||
virtual int32_t getCost(const int32_t skillLevel) const = 0;
|
||||
|
||||
|
@ -397,7 +397,10 @@ void CCreature::serializeJson(JsonSerializeFormat & handler)
|
||||
if(!handler.saving)
|
||||
{
|
||||
if(ammMin > ammMax)
|
||||
{
|
||||
logMod->error("Invalid creature '%s' configuration, advMapAmount.min > advMapAmount.max", identifier);
|
||||
std::swap(ammMin, ammMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -622,7 +625,7 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->error("Mod %s: creature %s has minimal damage (%d) greater than maximal damage (%d)!", scope, identifier, minDamage, maxDamage);
|
||||
logMod->error("Mod %s: creature %s has minimal damage (%d) greater than maximal damage (%d)!", scope, identifier, minDamage, maxDamage);
|
||||
cre->addBonus(maxDamage, BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin);
|
||||
cre->addBonus(minDamage, BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax);
|
||||
}
|
||||
|
@ -473,7 +473,11 @@ void CHeroHandler::loadHeroArmy(CHero * hero, const JsonNode & node) const
|
||||
hero->initialArmy[i].minAmount = static_cast<ui32>(source["min"].Float());
|
||||
hero->initialArmy[i].maxAmount = static_cast<ui32>(source["max"].Float());
|
||||
|
||||
assert(hero->initialArmy[i].minAmount <= hero->initialArmy[i].maxAmount);
|
||||
if (hero->initialArmy[i].minAmount > hero->initialArmy[i].maxAmount)
|
||||
{
|
||||
logMod->error("Hero %s has minimal army size (%d) greater than maximal size (%d)!", hero->getJsonKey(), hero->initialArmy[i].minAmount, hero->initialArmy[i].maxAmount);
|
||||
std::swap(hero->initialArmy[i].minAmount, hero->initialArmy[i].maxAmount);
|
||||
}
|
||||
|
||||
VLC->identifiers()->requestIdentifier("creature", source["creature"], [=](si32 creature)
|
||||
{
|
||||
|
@ -37,21 +37,25 @@ void CRandomGenerator::resetSeed()
|
||||
|
||||
TRandI CRandomGenerator::getIntRange(int lower, int upper)
|
||||
{
|
||||
assert(lower <= upper);
|
||||
return std::bind(TIntDist(lower, upper), std::ref(rand));
|
||||
}
|
||||
|
||||
vstd::TRandI64 CRandomGenerator::getInt64Range(int64_t lower, int64_t upper)
|
||||
{
|
||||
assert(lower <= upper);
|
||||
return std::bind(TInt64Dist(lower, upper), std::ref(rand));
|
||||
}
|
||||
|
||||
int CRandomGenerator::nextInt(int upper)
|
||||
{
|
||||
assert(0 <= upper);
|
||||
return getIntRange(0, upper)();
|
||||
}
|
||||
|
||||
int CRandomGenerator::nextInt(int lower, int upper)
|
||||
{
|
||||
assert(lower <= upper);
|
||||
return getIntRange(lower, upper)();
|
||||
}
|
||||
|
||||
@ -62,16 +66,19 @@ int CRandomGenerator::nextInt()
|
||||
|
||||
vstd::TRand CRandomGenerator::getDoubleRange(double lower, double upper)
|
||||
{
|
||||
return std::bind(TRealDist(lower, upper), std::ref(rand));
|
||||
assert(lower <= upper);
|
||||
return std::bind(TRealDist(lower, upper), std::ref(rand));
|
||||
}
|
||||
|
||||
double CRandomGenerator::nextDouble(double upper)
|
||||
{
|
||||
assert(0 <= upper);
|
||||
return getDoubleRange(0, upper)();
|
||||
}
|
||||
|
||||
double CRandomGenerator::nextDouble(double lower, double upper)
|
||||
{
|
||||
assert(lower <= upper);
|
||||
return getDoubleRange(lower, upper)();
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,7 @@ public:
|
||||
virtual bool swapGarrisonOnSiege(ObjectInstanceID tid)=0;
|
||||
virtual void giveHeroBonus(GiveBonus * bonus)=0;
|
||||
virtual void setMovePoints(SetMovePoints * smp)=0;
|
||||
virtual void setMovePoints(ObjectInstanceID hid, int val, bool absolute)=0;
|
||||
virtual void setManaPoints(ObjectInstanceID hid, int val)=0;
|
||||
virtual void giveHero(ObjectInstanceID id, PlayerColor player, ObjectInstanceID boatId = ObjectInstanceID()) = 0;
|
||||
virtual void changeObjPos(ObjectInstanceID objid, int3 newPos, const PlayerColor & initiator)=0;
|
||||
|
@ -210,17 +210,21 @@ void CGameStateCampaign::placeCampaignHeroes()
|
||||
// with the same hero type id
|
||||
std::vector<CGHeroInstance *> removedHeroes;
|
||||
|
||||
std::set<HeroTypeID> heroesToRemove = campaignState->getReservedHeroes();
|
||||
std::set<HeroTypeID> reservedHeroes = campaignState->getReservedHeroes();
|
||||
std::set<HeroTypeID> heroesToRemove;
|
||||
|
||||
for (auto const & heroID : reservedHeroes )
|
||||
{
|
||||
// Do not replace reserved heroes initially, e.g. in 1st campaign scenario in which they appear
|
||||
if (!campaignState->getHeroByType(heroID).isNull())
|
||||
heroesToRemove.insert(heroID);
|
||||
}
|
||||
|
||||
for(auto & campaignHeroReplacement : campaignHeroReplacements)
|
||||
heroesToRemove.insert(campaignHeroReplacement.hero->getHeroType());
|
||||
|
||||
for(auto & heroID : heroesToRemove)
|
||||
{
|
||||
// Do not replace reserved heroes initially, e.g. in 1st campaign scenario in which they appear
|
||||
if (campaignState->getHeroByType(heroID).isNull())
|
||||
continue;
|
||||
|
||||
auto * hero = gameState->getUsedHero(heroID);
|
||||
if(hero)
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ TavernSlotRole TavernHeroesPool::getSlotRole(HeroTypeID hero) const
|
||||
return TavernSlotRole::NONE;
|
||||
}
|
||||
|
||||
void TavernHeroesPool::setHeroForPlayer(PlayerColor player, TavernHeroSlot slot, HeroTypeID hero, CSimpleArmy & army, TavernSlotRole role)
|
||||
void TavernHeroesPool::setHeroForPlayer(PlayerColor player, TavernHeroSlot slot, HeroTypeID hero, CSimpleArmy & army, TavernSlotRole role, bool replenishPoints)
|
||||
{
|
||||
vstd::erase_if(currentTavern, [&](const TavernSlot & entry){
|
||||
return entry.player == player && entry.slot == slot;
|
||||
@ -54,6 +54,12 @@ void TavernHeroesPool::setHeroForPlayer(PlayerColor player, TavernHeroSlot slot,
|
||||
if (h && army)
|
||||
h->setToArmy(army);
|
||||
|
||||
if (h && replenishPoints)
|
||||
{
|
||||
h->setMovementPoints(h->movementPointsLimit(true));
|
||||
h->mana = h->manaLimit();
|
||||
}
|
||||
|
||||
TavernSlot newSlot;
|
||||
newSlot.hero = h;
|
||||
newSlot.player = player;
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
void setAvailability(HeroTypeID hero, std::set<PlayerColor> mask);
|
||||
|
||||
/// Makes hero available in tavern of specified player
|
||||
void setHeroForPlayer(PlayerColor player, TavernHeroSlot slot, HeroTypeID hero, CSimpleArmy & army, TavernSlotRole role);
|
||||
void setHeroForPlayer(PlayerColor player, TavernHeroSlot slot, HeroTypeID hero, CSimpleArmy & army, TavernSlotRole role, bool replenishPoints);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -436,14 +436,14 @@ void CGHeroInstance::initArmy(CRandomGenerator & rand, IArmyDescriptor * dst)
|
||||
|
||||
int count = rand.nextInt(stack.minAmount, stack.maxAmount);
|
||||
|
||||
const CCreature * creature = stack.creature.toCreature();
|
||||
|
||||
if(creature == nullptr)
|
||||
if(stack.creature == CreatureID::NONE)
|
||||
{
|
||||
logGlobal->error("Hero %s has invalid creature with id %d in initial army", getNameTranslated(), stack.creature.toEnum());
|
||||
logGlobal->error("Hero %s has invalid creature in initial army", getNameTranslated());
|
||||
continue;
|
||||
}
|
||||
|
||||
const CCreature * creature = stack.creature.toCreature();
|
||||
|
||||
if(creature->warMachine != ArtifactID::NONE) //war machine
|
||||
{
|
||||
warMachinesGiven++;
|
||||
|
@ -151,11 +151,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
|
||||
gb.id = heroID;
|
||||
cb->giveHeroBonus(&gb);
|
||||
|
||||
SetMovePoints mp;
|
||||
mp.val = 600;
|
||||
mp.absolute = false;
|
||||
mp.hid = heroID;
|
||||
cb->setMovePoints(&mp);
|
||||
cb->setMovePoints(heroID, 600, false);
|
||||
|
||||
iw.text.appendRawString(VLC->generaltexth->allTexts[580]);
|
||||
cb->showInfoDialog(&iw);
|
||||
|
@ -959,7 +959,7 @@ void FoWChange::applyGs(CGameState *gs)
|
||||
|
||||
void SetAvailableHero::applyGs(CGameState *gs)
|
||||
{
|
||||
gs->heroesPool->setHeroForPlayer(player, slotID, hid, army, roleID);
|
||||
gs->heroesPool->setHeroForPlayer(player, slotID, hid, army, roleID, replenishPoints);
|
||||
}
|
||||
|
||||
void GiveBonus::applyGs(CGameState *gs)
|
||||
|
@ -352,6 +352,7 @@ struct DLL_LINKAGE SetAvailableHero : public CPackForClient
|
||||
PlayerColor player;
|
||||
HeroTypeID hid; //HeroTypeID::NONE if no hero
|
||||
CSimpleArmy army;
|
||||
bool replenishPoints;
|
||||
|
||||
void visitTyped(ICPackVisitor & visitor) override;
|
||||
|
||||
@ -362,6 +363,7 @@ struct DLL_LINKAGE SetAvailableHero : public CPackForClient
|
||||
h & player;
|
||||
h & hid;
|
||||
h & army;
|
||||
h & replenishPoints;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -213,7 +213,24 @@ bool BattleSpellMechanics::canBeCastAt(const Target & target, Problem & problem)
|
||||
|
||||
Target spellTarget = transformSpellTarget(target);
|
||||
|
||||
return effects->applicable(problem, this, target, spellTarget);
|
||||
const battle::Unit * mainTarget = nullptr;
|
||||
|
||||
if (!getSpell()->canCastOnSelf())
|
||||
{
|
||||
if(spellTarget.front().unitValue)
|
||||
{
|
||||
mainTarget = target.front().unitValue;
|
||||
}
|
||||
else if(spellTarget.front().hexValue.isValid())
|
||||
{
|
||||
mainTarget = battle()->battleGetUnitByPos(target.front().hexValue, true);
|
||||
}
|
||||
|
||||
if (mainTarget && mainTarget == caster)
|
||||
return false; // can't cast on self
|
||||
}
|
||||
|
||||
return effects->applicable(problem, this, target, spellTarget);
|
||||
}
|
||||
|
||||
std::vector<const CStack *> BattleSpellMechanics::getAffectedStacks(const Target & target) const
|
||||
|
@ -76,6 +76,7 @@ CSpell::CSpell():
|
||||
power(0),
|
||||
combat(false),
|
||||
creatureAbility(false),
|
||||
castOnSelf(false),
|
||||
positiveness(ESpellPositiveness::NEUTRAL),
|
||||
defaultProbability(0),
|
||||
rising(false),
|
||||
@ -285,6 +286,11 @@ bool CSpell::hasBattleEffects() const
|
||||
return levels[0].battleEffects.getType() == JsonNode::JsonType::DATA_STRUCT && !levels[0].battleEffects.Struct().empty();
|
||||
}
|
||||
|
||||
bool CSpell::canCastOnSelf() const
|
||||
{
|
||||
return castOnSelf;
|
||||
}
|
||||
|
||||
const std::string & CSpell::getIconImmune() const
|
||||
{
|
||||
return iconImmune;
|
||||
@ -702,6 +708,7 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode &
|
||||
spell->school[info.id] = schoolNames[info.jsonName].Bool();
|
||||
}
|
||||
|
||||
spell->castOnSelf = json["canCastOnSelf"].Bool();
|
||||
spell->level = static_cast<si32>(json["level"].Integer());
|
||||
spell->power = static_cast<si32>(json["power"].Integer());
|
||||
|
||||
|
@ -203,6 +203,7 @@ public:
|
||||
int64_t calculateDamage(const spells::Caster * caster) const override;
|
||||
|
||||
bool hasSchool(SpellSchool school) const override;
|
||||
bool canCastOnSelf() const override;
|
||||
|
||||
/**
|
||||
* Calls cb for each school this spell belongs to
|
||||
@ -329,6 +330,7 @@ private:
|
||||
si32 power; //spell's power
|
||||
bool combat; //is this spell combat (true) or adventure (false)
|
||||
bool creatureAbility; //if true, only creatures can use this spell
|
||||
bool castOnSelf; // if set, creature caster can cast this spell on itself
|
||||
si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative
|
||||
|
||||
std::unique_ptr<spells::ISpellMechanicsFactory> mechanics;//(!) do not serialize
|
||||
|
@ -169,7 +169,6 @@ void Timed::apply(ServerCallback * server, const Mechanics * m, const EffectTarg
|
||||
case 1:
|
||||
//Coronius style specialty bonus.
|
||||
//Please note that actual Coronius isnt here, because Slayer is a spell that doesnt affect monster stats and is used only in calculateDmgRange
|
||||
power = std::max(5 - tier, 0);
|
||||
break;
|
||||
}
|
||||
if(m->isNegativeSpell())
|
||||
|
@ -1467,6 +1467,9 @@ void CGameHandler::heroVisitCastle(const CGTownInstance * obj, const CGHeroInsta
|
||||
sendAndApply(&vc);
|
||||
visitCastleObjects(obj, hero);
|
||||
giveSpells (obj, hero);
|
||||
|
||||
if (obj->visitingHero && obj->garrisonHero)
|
||||
useScholarSkill(obj->visitingHero->id, obj->garrisonHero->id);
|
||||
checkVictoryLossConditionsForPlayer(hero->tempOwner); //transported artifact?
|
||||
}
|
||||
|
||||
@ -1510,6 +1513,15 @@ void CGameHandler::setMovePoints(SetMovePoints * smp)
|
||||
sendAndApply(smp);
|
||||
}
|
||||
|
||||
void CGameHandler::setMovePoints(ObjectInstanceID hid, int val, bool absolute)
|
||||
{
|
||||
SetMovePoints smp;
|
||||
smp.hid = hid;
|
||||
smp.val = val;
|
||||
smp.absolute = absolute;
|
||||
sendAndApply(&smp);
|
||||
}
|
||||
|
||||
void CGameHandler::setManaPoints(ObjectInstanceID hid, int val)
|
||||
{
|
||||
SetMana sm;
|
||||
|
@ -142,6 +142,7 @@ public:
|
||||
bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, bool transit = false, PlayerColor asker = PlayerColor::NEUTRAL) override;
|
||||
void giveHeroBonus(GiveBonus * bonus) override;
|
||||
void setMovePoints(SetMovePoints * smp) override;
|
||||
void setMovePoints(ObjectInstanceID hid, int val, bool absolute) override;
|
||||
void setManaPoints(ObjectInstanceID hid, int val) override;
|
||||
void giveHero(ObjectInstanceID id, PlayerColor player, ObjectInstanceID boatId = ObjectInstanceID()) override;
|
||||
void changeObjPos(ObjectInstanceID objid, int3 newPos, const PlayerColor & initiator) override;
|
||||
|
@ -74,6 +74,7 @@ void HeroPoolProcessor::onHeroSurrendered(const PlayerColor & color, const CGHer
|
||||
sah.slotID = selectSlotForRole(color, sah.roleID);
|
||||
sah.player = color;
|
||||
sah.hid = hero->getHeroType();
|
||||
sah.replenishPoints = false;
|
||||
gameHandler->sendAndApply(&sah);
|
||||
}
|
||||
|
||||
@ -87,6 +88,7 @@ void HeroPoolProcessor::onHeroEscaped(const PlayerColor & color, const CGHeroIns
|
||||
sah.hid = hero->getHeroType();
|
||||
sah.army.clearSlots();
|
||||
sah.army.setCreature(SlotID(0), hero->type->initialArmy.at(0).creature, 1);
|
||||
sah.replenishPoints = false;
|
||||
|
||||
gameHandler->sendAndApply(&sah);
|
||||
}
|
||||
@ -98,6 +100,7 @@ void HeroPoolProcessor::clearHeroFromSlot(const PlayerColor & color, TavernHeroS
|
||||
sah.roleID = TavernSlotRole::NONE;
|
||||
sah.slotID = slot;
|
||||
sah.hid = HeroTypeID::NONE;
|
||||
sah.replenishPoints = false;
|
||||
gameHandler->sendAndApply(&sah);
|
||||
}
|
||||
|
||||
@ -106,6 +109,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe
|
||||
SetAvailableHero sah;
|
||||
sah.player = color;
|
||||
sah.slotID = slot;
|
||||
sah.replenishPoints = true;
|
||||
|
||||
CGHeroInstance *newHero = pickHeroFor(needNativeHero, color);
|
||||
|
||||
@ -129,6 +133,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe
|
||||
{
|
||||
sah.hid = HeroTypeID::NONE;
|
||||
}
|
||||
|
||||
gameHandler->sendAndApply(&sah);
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,7 @@ public:
|
||||
bool swapGarrisonOnSiege(ObjectInstanceID tid) override {return false;}
|
||||
void giveHeroBonus(GiveBonus * bonus) override {}
|
||||
void setMovePoints(SetMovePoints * smp) override {}
|
||||
void setMovePoints(ObjectInstanceID hid, int val, bool absolute) override {};
|
||||
void setManaPoints(ObjectInstanceID hid, int val) override {}
|
||||
void giveHero(ObjectInstanceID id, PlayerColor player, ObjectInstanceID boatId = ObjectInstanceID()) override {}
|
||||
void changeObjPos(ObjectInstanceID objid, int3 newPos, const PlayerColor & initiator) override {}
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
MOCK_CONST_METHOD0(isOffensive, bool());
|
||||
MOCK_CONST_METHOD0(isSpecial, bool());
|
||||
MOCK_CONST_METHOD0(isMagical, bool());
|
||||
MOCK_CONST_METHOD0(canCastOnSelf, bool());
|
||||
MOCK_CONST_METHOD1(hasSchool, bool(SpellSchool));
|
||||
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
|
||||
MOCK_CONST_METHOD0(getCastSound, const std::string &());
|
||||
|
Loading…
x
Reference in New Issue
Block a user