mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Added special slots for war machines and arrow towers
This commit is contained in:
parent
ba017c443d
commit
16e0d18880
@ -469,7 +469,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
auto handleWarMachine= [&](int side, ArtifactPosition artslot, CreatureID cretype, BattleHex hex)
|
||||
{
|
||||
if(heroes[side] && heroes[side]->getArt(artslot))
|
||||
stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cretype, 1), !side, SlotID(255), hex));
|
||||
stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cretype, 1), !side, SlotID::WAR_MACHINES_SLOT, hex));
|
||||
};
|
||||
|
||||
handleWarMachine(0, ArtifactPosition::MACH1, CreatureID::BALLISTA, 52);
|
||||
@ -526,15 +526,15 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
if (curB->town && curB->town->fortLevel() >= CGTownInstance::CITADEL)
|
||||
{
|
||||
// keep tower
|
||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -2);
|
||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -2);
|
||||
stacks.push_back(stack);
|
||||
|
||||
if (curB->town->fortLevel() >= CGTownInstance::CASTLE)
|
||||
{
|
||||
// lower tower + upper tower
|
||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -4);
|
||||
CStack * stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -4);
|
||||
stacks.push_back(stack);
|
||||
stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID(255), -3);
|
||||
stack = curB->generateNewStack(CStackBasicDescriptor(CreatureID::ARROW_TOWERS, 1), false, SlotID::ARROW_TOWERS_SLOT, -3);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
|
||||
@ -712,7 +712,7 @@ std::shared_ptr<CObstacleInstance> BattleInfo::getObstacleOnTile(BattleHex tile)
|
||||
|
||||
BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldType)
|
||||
{
|
||||
static const std::map<BFieldType, BattlefieldBI::BattlefieldBI> theMap =
|
||||
static const std::map<BFieldType, BattlefieldBI::BattlefieldBI> theMap =
|
||||
{
|
||||
{BFieldType::CLOVER_FIELD, BattlefieldBI::CLOVER_FIELD},
|
||||
{BFieldType::CURSED_GROUND, BattlefieldBI::CURSED_GROUND},
|
||||
@ -1141,7 +1141,7 @@ bool CStack::ableToRetaliate() const //FIXME: crash after clone is killed
|
||||
|
||||
ui8 CStack::counterAttacksTotal() const
|
||||
{
|
||||
//after dispell bonus should remain during current round
|
||||
//after dispell bonus should remain during current round
|
||||
ui8 val = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
||||
vstd::amax(counterAttacksTotalCache, val);
|
||||
return counterAttacksTotalCache;
|
||||
@ -1183,9 +1183,9 @@ ui32 CStack::calculateHealedHealthPoints(ui32 toHeal, const bool resurrect) cons
|
||||
ui8 CStack::getSpellSchoolLevel(const CSpell * spell, int * outSelectedSchool) const
|
||||
{
|
||||
int skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->id));
|
||||
|
||||
|
||||
vstd::abetween(skill, 0, 3);
|
||||
|
||||
|
||||
return skill;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,10 @@
|
||||
#include "spells/CSpellHandler.h"
|
||||
|
||||
const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2);
|
||||
const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(255);
|
||||
const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(-3);
|
||||
const SlotID SlotID::WAR_MACHINES_SLOT = SlotID(-4);
|
||||
const SlotID SlotID::ARROW_TOWERS_SLOT = SlotID(-5);
|
||||
|
||||
const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253);
|
||||
const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254);
|
||||
const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255);
|
||||
|
@ -237,6 +237,8 @@ class SlotID : public BaseForID<SlotID, si32>
|
||||
|
||||
DLL_LINKAGE static const SlotID COMMANDER_SLOT_PLACEHOLDER;
|
||||
DLL_LINKAGE static const SlotID SUMMONED_SLOT_PLACEHOLDER; ///<for all summoned creatures, only during battle
|
||||
DLL_LINKAGE static const SlotID WAR_MACHINES_SLOT; ///<for all war machines during battle
|
||||
DLL_LINKAGE static const SlotID ARROW_TOWERS_SLOT; ///<for all arrow towers during battle
|
||||
|
||||
bool validSlot() const
|
||||
{
|
||||
@ -444,11 +446,11 @@ namespace ESpellCastProblem
|
||||
|
||||
namespace ECastingMode
|
||||
{
|
||||
enum ECastingMode
|
||||
enum ECastingMode
|
||||
{
|
||||
HERO_CASTING, AFTER_ATTACK_CASTING, //also includes cast before attack
|
||||
MAGIC_MIRROR, CREATURE_ACTIVE_CASTING, ENCHANTER_CASTING,
|
||||
SPELL_LIKE_ATTACK,
|
||||
SPELL_LIKE_ATTACK,
|
||||
PASSIVE_CASTING//f.e. opening battle spells
|
||||
};
|
||||
}
|
||||
|
@ -3914,7 +3914,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
BattleStackAdded bsa;
|
||||
bsa.attacker = summoner->attackerOwned;
|
||||
|
||||
bsa.creID = summonedType;
|
||||
bsa.creID = summonedType;
|
||||
ui64 risedHp = summoner->count * summoner->valOfBonuses(Bonus::DAEMON_SUMMONING, bsa.creID.toEnum());
|
||||
ui64 targetHealth = destStack->getCreature()->MaxHealth() * destStack->baseAmount;//todo: ignore AGE effect
|
||||
|
||||
@ -5887,7 +5887,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl
|
||||
PlayerColor color = army->tempOwner;
|
||||
if(color == PlayerColor::UNFLAGGABLE)
|
||||
color = PlayerColor::NEUTRAL;
|
||||
|
||||
|
||||
auto killStack = [&, this](const SlotID slot, const CStackInstance * instance)
|
||||
{
|
||||
StackLocation sl(army, slot);
|
||||
@ -5928,47 +5928,67 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance * _army, Battl
|
||||
|
||||
for(CStack *st : bat->stacks)
|
||||
{
|
||||
if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account summoned stacks
|
||||
if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account temporary summoned stacks
|
||||
continue;
|
||||
if (st->owner != color) //remove only our stacks
|
||||
continue;
|
||||
|
||||
logGlobal->debugStream() << "Calculating casualties for " << st->nodeName();
|
||||
|
||||
//FIXME: this info is also used in BattleInfo::calculateCasualties, refactor
|
||||
st->count = std::max (0, st->count - st->resurrected);
|
||||
|
||||
if (!st->count && !st->base) //we can imagine stacks of war machines that are not spawned by artifacts?
|
||||
if(st->slot == SlotID::ARROW_TOWERS_SLOT)
|
||||
{
|
||||
//do nothing
|
||||
logGlobal->debugStream() << "Ignored arrow towers stack";
|
||||
}
|
||||
else if(st->slot == SlotID::WAR_MACHINES_SLOT)
|
||||
{
|
||||
auto warMachine = VLC->arth->creatureToMachineID(st->type->idNumber);
|
||||
//catapult artifact remain even if "creature" killed in siege
|
||||
if(warMachine != ArtifactID::NONE && warMachine != ArtifactID::CATAPULT)
|
||||
|
||||
if(warMachine == ArtifactID::NONE)
|
||||
{
|
||||
logGlobal->errorStream() << "Invalid creature in war machine virtual slot: " << st->nodeName();
|
||||
}
|
||||
//catapult artifact remain even if "creature" killed in siege
|
||||
else if(warMachine != ArtifactID::CATAPULT && !st->count)
|
||||
{
|
||||
logGlobal->debugStream() << "War machine has been destroyed";
|
||||
auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
|
||||
if (hero)
|
||||
removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
|
||||
else
|
||||
logGlobal->errorStream() << "War machine in army without hero";
|
||||
}
|
||||
}
|
||||
|
||||
if(army->slotEmpty(st->slot))
|
||||
else if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER)
|
||||
{
|
||||
if(st->slot == SlotID::SUMMONED_SLOT_PLACEHOLDER && !vstd::contains(st->state, EBattleStackState::SUMMONED) && st->alive() && st->count > 0)
|
||||
if(st->alive() && st->count > 0)
|
||||
{
|
||||
logGlobal->debugStream() << "Stack has been permanently summoned";
|
||||
//this stack was permanently summoned
|
||||
const CreatureID summonedType = st->type->idNumber;
|
||||
summoned[summonedType] += st->count;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(st->base && !army->slotEmpty(st->slot))
|
||||
{
|
||||
if(st->count == 0 || !st->alive())
|
||||
{
|
||||
killStack(st->slot, st->base);
|
||||
logGlobal->debugStream() << "Stack has been destroyed";
|
||||
}
|
||||
else if(st->count < army->getStackCount(st->slot))
|
||||
{
|
||||
{
|
||||
StackLocation sl(army, st->slot);
|
||||
newStackCounts.push_back(TStackAndItsNewCount(sl, st->count));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->warnStream() << "Unhandled stack " << st->nodeName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user