mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
* support for new spells: anti-magic and elemental summoning
* obstacles in battles should fit now the battlefield * minor changes
This commit is contained in:
parent
184676d7c4
commit
ea6ab102a7
@ -118,6 +118,7 @@ public:
|
||||
virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
|
||||
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
|
||||
virtual void battleNewStackAppeared(int stackID){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
||||
};
|
||||
class CAIHandler
|
||||
{
|
||||
|
@ -496,6 +496,10 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
for(size_t v=0; v<stackAliveByHex[b].size(); ++v)
|
||||
{
|
||||
int curStackID = stackAliveByHex[b][v];
|
||||
|
||||
if(creAnims.find(curStackID) == creAnims.end()) //eg. for summoned but not yet handled stacks
|
||||
continue;
|
||||
|
||||
const CStack &curStack = stacks[curStackID];
|
||||
int animType = creAnims[curStackID]->getType();
|
||||
|
||||
|
@ -1171,6 +1171,18 @@ void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, u
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleNewStackAppeared(int stackID)
|
||||
{
|
||||
const CStack * newStack = cb->battleGetStackByID(stackID);
|
||||
|
||||
//changing necessary things in battle interface
|
||||
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(newStack->position, newStack->owner == battleInt->attackingHeroInstance->tempOwner, newStack);
|
||||
battleInt->creAnims[newStack->ID] = (new CCreatureAnimation(newStack->creature->animDefName));
|
||||
battleInt->creAnims[newStack->ID]->setType(2);
|
||||
battleInt->creAnims[newStack->ID]->pos = genRect(battleInt->creAnims[newStack->ID]->fullHeight, battleInt->creAnims[newStack->ID]->fullWidth, coords.first, coords.second);
|
||||
battleInt->creDir[newStack->ID] = newStack->owner == battleInt->attackingHeroInstance->tempOwner;
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleNewRound(int round) //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
|
@ -193,6 +193,7 @@ public:
|
||||
void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
|
||||
void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks); //called when stacks are healed / resurrected
|
||||
void battleNewStackAppeared(int stackID); //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
||||
|
||||
|
||||
//-------------//
|
||||
|
@ -406,6 +406,14 @@ void SpellCast::applyCl( CClient *cl )
|
||||
cl->playerint[GS(cl)->curB->side1]->battleSpellCast(this);
|
||||
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side2]->battleSpellCast(this);
|
||||
|
||||
if(id >= 66 && id <= 69) //elemental summoning
|
||||
{
|
||||
if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side1]->battleNewStackAppeared(GS(cl)->curB->stacks.size() - 1);
|
||||
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||
cl->playerint[GS(cl)->curB->side2]->battleNewStackAppeared(GS(cl)->curB->stacks.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SetStackEffect::applyCl( CClient *cl )
|
||||
|
@ -34,9 +34,9 @@
|
||||
31 1 24 0 0 0 X
|
||||
32 1 23 0 0 0 X
|
||||
33 1 26 0 0 0 X
|
||||
34 1 -1 0 0 0 X
|
||||
34 1 5 0 0 0 X
|
||||
35 0 41 0 0 0 X
|
||||
36 1 -1 0 0 0 0
|
||||
36 1 3 0 0 0 0
|
||||
37 1 39 0 0 0 0
|
||||
38 1 79 0 0 0 0
|
||||
39 1 79 0 0 0 0
|
||||
|
@ -2159,6 +2159,52 @@ std::set<CStack*> BattleInfo::getAttackedCreatures(const CSpell * s, const CGHer
|
||||
return attackedCres;
|
||||
}
|
||||
|
||||
int BattleInfo::calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster)
|
||||
{
|
||||
switch(spell->id)
|
||||
{
|
||||
case 56: //frenzy
|
||||
return 1;
|
||||
default: //other spells
|
||||
return caster->getPrimSkillLevel(2) + caster->valOfBonuses(HeroBonus::SPELL_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
CStack * BattleInfo::generateNewStack(const CGHeroInstance * owner, int creatureID, int amount, int stackID, bool attackerOwned, int slot, int /*TerrainTile::EterrainType*/ terrain, int position)
|
||||
{
|
||||
CStack * ret = new CStack(&VLC->creh->creatures[creatureID], amount, owner ? owner->tempOwner : 255, stackID, attackerOwned, slot);
|
||||
if(owner)
|
||||
{
|
||||
ret->features.push_back(makeFeature(StackFeature::SPEED_BONUS, StackFeature::WHOLE_BATTLE, 0, owner->valOfBonuses(HeroBonus::STACKS_SPEED), StackFeature::BONUS_FROM_HERO));
|
||||
//base luck/morale calculations
|
||||
ret->morale = owner->getCurrentMorale(slot, false);
|
||||
ret->luck = owner->getCurrentLuck(slot, false);
|
||||
//other bonuses
|
||||
ret->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, owner->getPrimSkillLevel(0), StackFeature::BONUS_FROM_HERO));
|
||||
ret->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, owner->getPrimSkillLevel(1), StackFeature::BONUS_FROM_HERO));
|
||||
ret->features.push_back(makeFeature(StackFeature::HP_BONUS, StackFeature::WHOLE_BATTLE, 0, owner->valOfBonuses(HeroBonus::STACK_HEALTH), StackFeature::BONUS_FROM_HERO));
|
||||
ret->firstHPleft = ret->MaxHealth();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret->morale = 0;
|
||||
ret->luck = 0;
|
||||
}
|
||||
|
||||
//native terrain bonuses
|
||||
int faction = ret->creature->faction;
|
||||
if(faction >= 0 && VLC->heroh->nativeTerrains[faction] == terrain)
|
||||
{
|
||||
ret->features.push_back(makeFeature(StackFeature::SPEED_BONUS, StackFeature::WHOLE_BATTLE, 0, 1, StackFeature::OTHER_SOURCE));
|
||||
ret->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, 1, StackFeature::OTHER_SOURCE));
|
||||
ret->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, 1, StackFeature::OTHER_SOURCE));
|
||||
}
|
||||
|
||||
ret->position = position;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CStack * BattleInfo::getNextStack()
|
||||
{
|
||||
CStack *current = getStack(activeStack);
|
||||
|
@ -137,6 +137,8 @@ struct DLL_EXPORT BattleInfo
|
||||
static int calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting); //TODO: add additional conditions and require necessary data
|
||||
void calculateCasualties(std::set<std::pair<ui32,si32> > *casualties);
|
||||
std::set<CStack*> getAttackedCreatures(const CSpell * s, const CGHeroInstance * caster, int destinationTile); //calculates stack affected by given spell
|
||||
static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster);
|
||||
static CStack * generateNewStack(const CGHeroInstance * owner, int creatureID, int amount, int stackID, bool attackerOwned, int slot, int /*TerrainTile::EterrainType*/ terrain, int position); //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
||||
};
|
||||
|
||||
class DLL_EXPORT CStack
|
||||
|
@ -900,8 +900,8 @@ struct SpellCast : public CPackForClient//3009
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
ui8 side; //which hero did cast spell: 0 - attacker, 1 - defender
|
||||
ui32 id;
|
||||
ui8 skill;
|
||||
ui32 id; //id of spell
|
||||
ui8 skill; //caster's skill level
|
||||
ui16 tile; //destination tile (may not be set in some global/mass spells
|
||||
std::vector<ui32> resisted; //ids of creatures that resisted this spell
|
||||
std::set<ui32> affectedCres; //ids of creatures affected by this spell, generally used if spell does not set any effect (like dispel or cure)
|
||||
@ -917,8 +917,8 @@ struct SetStackEffect : public CPackForClient //3010
|
||||
DLL_EXPORT void applyGs(CGameState *gs);
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
std::set<ui32> stacks;
|
||||
CStack::StackEffect effect;
|
||||
std::set<ui32> stacks; //affected stacks (IDs)
|
||||
CStack::StackEffect effect; //type of effect
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & stacks & effect;
|
||||
|
@ -695,6 +695,7 @@ DLL_EXPORT void SpellCast::applyGs( CGameState *gs )
|
||||
gs->curB->castSpells[side]++;
|
||||
}
|
||||
|
||||
|
||||
if(gs->curB && id == 35) //dispel
|
||||
{
|
||||
for(std::set<ui32>::const_iterator it = affectedCres.begin(); it != affectedCres.end(); ++it)
|
||||
@ -716,6 +717,50 @@ DLL_EXPORT void SpellCast::applyGs( CGameState *gs )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//elemental summoning
|
||||
if(id >= 66 && id <= 69)
|
||||
{
|
||||
int creID;
|
||||
switch(id)
|
||||
{
|
||||
case 66:
|
||||
creID = 114; //fire elemental
|
||||
break;
|
||||
case 67:
|
||||
creID = 113; //earth elemental
|
||||
break;
|
||||
case 68:
|
||||
creID = 115; //water elemental
|
||||
break;
|
||||
case 69:
|
||||
creID = 112; //air elemental
|
||||
break;
|
||||
}
|
||||
const int3 & tile = gs->curB->tile;
|
||||
TerrainTile::EterrainType ter = gs->map->terrain[tile.x][tile.y][tile.z].tertype;
|
||||
|
||||
int pos; //position of stack on the battlefield - to be calculated
|
||||
|
||||
bool ac[BFIELD_SIZE];
|
||||
std::set<int> occupyable;
|
||||
bool twoHex = vstd::contains(VLC->creh->creatures[creID].abilities, StackFeature::DOUBLE_WIDE);
|
||||
bool flying = vstd::contains(VLC->creh->creatures[creID].abilities, StackFeature::FLYING);
|
||||
gs->curB->getAccessibilityMap(ac, twoHex, !side, true, occupyable, flying);
|
||||
for(int g=0; g<BFIELD_SIZE; ++g)
|
||||
{
|
||||
if(g % BFIELD_WIDTH != 0 && g % BFIELD_WIDTH != BFIELD_WIDTH-1 && BattleInfo::isAccessible(g, ac, twoHex, !side, flying, true) )
|
||||
{
|
||||
pos = g;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CStack * summonedStack = BattleInfo::generateNewStack(h, creID, h->getPrimSkillLevel(2) * VLC->spellh->spells[id].powers[skill], gs->curB->stacks.size(), !side, 255, ter, pos);
|
||||
summonedStack->features.push_back( makeFeature(StackFeature::SUMMONED, StackFeature::WHOLE_BATTLE, 0, 0, StackFeature::BONUS_FROM_HERO) );
|
||||
|
||||
gs->curB->stacks.push_back(summonedStack);
|
||||
}
|
||||
}
|
||||
|
||||
static inline StackFeature featureGenerator(StackFeature::ECombatFeatures type, si16 subtype, si32 value, ui16 turnsRemain, si32 additionalInfo = 0)
|
||||
@ -746,6 +791,9 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
|
||||
case 33: //protection from earth
|
||||
sf.push_back(featureGenerator(StackFeature::SPELL_DAMAGE_REDUCTION, 3, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
|
||||
break;
|
||||
case 34: //anti-magic
|
||||
sf.push_back(featureGenerator(StackFeature::LEVEL_SPELL_IMMUNITY, 0, VLC->spellh->spells[sse.id].powers[sse.level] - 1, sse.turnsRemain));
|
||||
break;
|
||||
case 41: //bless
|
||||
sf.push_back(featureGenerator(StackFeature::ALWAYS_MAXIMUM_DAMAGE, -1, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
|
||||
break;
|
||||
|
@ -307,6 +307,9 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf
|
||||
CCreatureSet ret(set);
|
||||
for(int i=0; i<bat->stacks.size();i++)
|
||||
{
|
||||
if(bat->stacks[i]->hasFeatureOfType(StackFeature::SUMMONED)) //don't take into account sumoned stacks
|
||||
continue;
|
||||
|
||||
CStack *st = bat->stacks[i];
|
||||
if(st->owner==color && vstd::contains(set.slots,st->slot) && st->amount < set.slots.find(st->slot)->second.second)
|
||||
{
|
||||
@ -869,30 +872,8 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
|
||||
curB->side2=(hero2)?(hero2->tempOwner):(-1);
|
||||
curB->round = -2;
|
||||
curB->activeStack = -1;
|
||||
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
|
||||
{
|
||||
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
|
||||
if(hero1)
|
||||
{
|
||||
stacks.back()->features.push_back(makeFeature(StackFeature::SPEED_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->valOfBonuses(HeroBonus::STACKS_SPEED), StackFeature::BONUS_FROM_HERO));
|
||||
//base luck/morale calculations
|
||||
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
||||
stacks.back()->morale = hero1->getCurrentMorale(i->first,false);
|
||||
stacks.back()->luck = hero1->getCurrentLuck(i->first,false);
|
||||
stacks.back()->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->getPrimSkillLevel(0), StackFeature::BONUS_FROM_HERO));
|
||||
stacks.back()->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->getPrimSkillLevel(1), StackFeature::BONUS_FROM_HERO));
|
||||
stacks.back()->features.push_back(makeFeature(StackFeature::HP_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->valOfBonuses(HeroBonus::STACK_HEALTH), StackFeature::BONUS_FROM_HERO));
|
||||
stacks.back()->firstHPleft = stacks.back()->MaxHealth();
|
||||
}
|
||||
else
|
||||
{
|
||||
stacks.back()->morale = 0;
|
||||
stacks.back()->luck = 0;
|
||||
}
|
||||
|
||||
stacks[stacks.size()-1]->ID = stacks.size()-1;
|
||||
}
|
||||
//initialization of positions
|
||||
//reading battleStartpos
|
||||
std::ifstream positions;
|
||||
positions.open("config" PATHSEPARATOR "battleStartpos.txt", std::ios_base::in|std::ios_base::binary);
|
||||
if(!positions.is_open())
|
||||
@ -911,48 +892,30 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
|
||||
positions>>dump;
|
||||
CGH::readItTo(positions, defenderTight);
|
||||
positions.close();
|
||||
//battleStartpos read
|
||||
|
||||
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
|
||||
{
|
||||
int pos;
|
||||
if(army1.formation)
|
||||
for(int b=0; b<army1.slots.size(); ++b) //tight
|
||||
{
|
||||
stacks[b]->position = attackerTight[army1.slots.size()-1][b];
|
||||
}
|
||||
pos = attackerTight[army1.slots.size()-1][i->first];
|
||||
else
|
||||
for(int b=0; b<army1.slots.size(); ++b) //loose
|
||||
{
|
||||
stacks[b]->position = attackerLoose[army1.slots.size()-1][b];
|
||||
pos = attackerLoose[army1.slots.size()-1][i->first];
|
||||
|
||||
CStack * stack = BattleInfo::generateNewStack(hero1, i->second.first, i->second.second, stacks.size(), true, i->first, gs->map->terrain[tile.x][tile.y][tile.z].tertype, pos);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
|
||||
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
|
||||
{
|
||||
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false, i->first));
|
||||
//base luck/morale calculations
|
||||
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
||||
if(hero2)
|
||||
{
|
||||
stacks.back()->features.push_back(makeFeature(StackFeature::SPEED_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->valOfBonuses(HeroBonus::STACKS_SPEED), StackFeature::BONUS_FROM_HERO));
|
||||
stacks.back()->morale = hero2->getCurrentMorale(i->first,false);
|
||||
stacks.back()->luck = hero2->getCurrentLuck(i->first,false);
|
||||
stacks.back()->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->getPrimSkillLevel(0), StackFeature::BONUS_FROM_HERO));
|
||||
stacks.back()->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->getPrimSkillLevel(1), StackFeature::BONUS_FROM_HERO));
|
||||
stacks.back()->features.push_back(makeFeature(StackFeature::HP_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->valOfBonuses(HeroBonus::STACK_HEALTH), StackFeature::BONUS_FROM_HERO));
|
||||
stacks.back()->firstHPleft = stacks.back()->MaxHealth();
|
||||
}
|
||||
else
|
||||
{
|
||||
stacks.back()->morale = 0;
|
||||
stacks.back()->luck = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int pos;
|
||||
if(army2.formation)
|
||||
for(int b=0; b<army2.slots.size(); ++b) //tight
|
||||
{
|
||||
stacks[b+army1.slots.size()]->position = defenderTight[army2.slots.size()-1][b];
|
||||
}
|
||||
pos = defenderTight[army2.slots.size()-1][i->first];
|
||||
else
|
||||
for(int b=0; b<army2.slots.size(); ++b) //loose
|
||||
{
|
||||
stacks[b+army1.slots.size()]->position = defenderLoose[army2.slots.size()-1][b];
|
||||
pos = defenderLoose[army2.slots.size()-1][i->first];
|
||||
|
||||
CStack * stack = BattleInfo::generateNewStack(hero2, i->second.first, i->second.second, stacks.size(), false, i->first, gs->map->terrain[tile.x][tile.y][tile.z].tertype, pos);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
|
||||
for(unsigned g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
|
||||
@ -967,65 +930,41 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
|
||||
}
|
||||
}
|
||||
|
||||
//adding native terrain bonuses
|
||||
for(int g=0; g<stacks.size(); ++g)
|
||||
{
|
||||
int faction = stacks[g]->creature->faction;
|
||||
if(faction >= 0 && VLC->heroh->nativeTerrains[faction] == gs->map->terrain[tile.x][tile.y][tile.z].tertype )
|
||||
{
|
||||
stacks[g]->features.push_back(makeFeature(StackFeature::SPEED_BONUS, StackFeature::WHOLE_BATTLE, 0, 1, StackFeature::OTHER_SOURCE));
|
||||
stacks[g]->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, 1, StackFeature::OTHER_SOURCE));
|
||||
stacks[g]->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, 1, StackFeature::OTHER_SOURCE));
|
||||
}
|
||||
}
|
||||
|
||||
//adding war machines
|
||||
if(hero1)
|
||||
{
|
||||
if(hero1->getArt(13)) //ballista
|
||||
{
|
||||
stacks.push_back(new CStack(&VLC->creh->creatures[146], 1, hero1->tempOwner, stacks.size(), true, 255));
|
||||
stacks[stacks.size()-1]->position = 52;
|
||||
stacks.back()->morale = hero1->getCurrentMorale(stacks.back()->ID,false);
|
||||
stacks.back()->luck = hero1->getCurrentLuck(stacks.back()->ID,false);
|
||||
CStack * stack = BattleInfo::generateNewStack(hero1, 146, 1, stacks.size(), true, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 52);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
if(hero1->getArt(14)) //ammo cart
|
||||
{
|
||||
stacks.push_back(new CStack(&VLC->creh->creatures[148], 1, hero1->tempOwner, stacks.size(), true, 255));
|
||||
stacks[stacks.size()-1]->position = 18;
|
||||
stacks.back()->morale = hero1->getCurrentMorale(stacks.back()->ID,false);
|
||||
stacks.back()->luck = hero1->getCurrentLuck(stacks.back()->ID,false);
|
||||
CStack * stack = BattleInfo::generateNewStack(hero1, 148, 1, stacks.size(), true, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 18);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
if(hero1->getArt(15)) //first aid tent
|
||||
{
|
||||
stacks.push_back(new CStack(&VLC->creh->creatures[147], 1, hero1->tempOwner, stacks.size(), true, 255));
|
||||
stacks[stacks.size()-1]->position = 154;
|
||||
stacks.back()->morale = hero1->getCurrentMorale(stacks.back()->ID,false);
|
||||
stacks.back()->luck = hero1->getCurrentLuck(stacks.back()->ID,false);
|
||||
CStack * stack = BattleInfo::generateNewStack(hero1, 147, 1, stacks.size(), true, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 154);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
}
|
||||
if(hero2)
|
||||
{
|
||||
if(hero2->getArt(13)) //ballista
|
||||
{
|
||||
stacks.push_back(new CStack(&VLC->creh->creatures[146], 1, hero2->tempOwner, stacks.size(), false, 255));
|
||||
stacks[stacks.size()-1]->position = 66;
|
||||
stacks.back()->morale = hero2->getCurrentMorale(stacks.back()->ID,false);
|
||||
stacks.back()->luck = hero2->getCurrentLuck(stacks.back()->ID,false);
|
||||
CStack * stack = BattleInfo::generateNewStack(hero2, 146, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 66);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
if(hero2->getArt(14)) //ammo cart
|
||||
{
|
||||
stacks.push_back(new CStack(&VLC->creh->creatures[148], 1, hero2->tempOwner, stacks.size(), false, 255));
|
||||
stacks[stacks.size()-1]->position = 32;
|
||||
stacks.back()->morale = hero2->getCurrentMorale(stacks.back()->ID,false);
|
||||
stacks.back()->luck = hero2->getCurrentLuck(stacks.back()->ID,false);
|
||||
CStack * stack = BattleInfo::generateNewStack(hero2, 148, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 32);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
if(hero2->getArt(15)) //first aid tent
|
||||
{
|
||||
stacks.push_back(new CStack(&VLC->creh->creatures[147], 1, hero2->tempOwner, stacks.size(), false, 255));
|
||||
stacks[stacks.size()-1]->position = 168;
|
||||
stacks.back()->morale = hero2->getCurrentMorale(stacks.back()->ID,false);
|
||||
stacks.back()->luck = hero2->getCurrentLuck(stacks.back()->ID,false);
|
||||
CStack * stack = BattleInfo::generateNewStack(hero2, 147, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 168);
|
||||
stacks.push_back(stack);
|
||||
}
|
||||
}
|
||||
//war machines added
|
||||
@ -1070,7 +1009,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
|
||||
bool badObstacle = false;
|
||||
for(int b=0; b<block.size(); ++b)
|
||||
{
|
||||
if(!obAv[block[b]])
|
||||
if(block[b] < 0 || block[b] >= BFIELD_SIZE || !obAv[block[b]])
|
||||
{
|
||||
badObstacle = true;
|
||||
break;
|
||||
@ -2811,6 +2750,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
case 31: //protection from fire
|
||||
case 32: //protection from water
|
||||
case 33: //protection from earth
|
||||
case 34: //anti-magic
|
||||
case 41: //bless
|
||||
case 42: //curse
|
||||
case 43: //bloodlust
|
||||
@ -2826,6 +2766,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
case 53: //haste
|
||||
case 54: //slow
|
||||
case 55: //slayer
|
||||
case 56: //frenzy
|
||||
case 61: //forgetfulness
|
||||
{
|
||||
SetStackEffect sse;
|
||||
@ -2837,23 +2778,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
}
|
||||
sse.effect.id = ba.additionalInfo;
|
||||
sse.effect.level = h->getSpellSchoolLevel(s);
|
||||
sse.effect.turnsRemain = h->getPrimSkillLevel(2) + h->valOfBonuses(HeroBonus::SPELL_DURATION);
|
||||
if(!sse.stacks.empty())
|
||||
sendAndApply(&sse);
|
||||
break;
|
||||
}
|
||||
case 56: //frenzy
|
||||
{
|
||||
SetStackEffect sse;
|
||||
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
||||
{
|
||||
if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
|
||||
continue;
|
||||
sse.stacks.insert((*it)->ID);
|
||||
}
|
||||
sse.effect.id = ba.additionalInfo;
|
||||
sse.effect.level = h->getSpellSchoolLevel(s);
|
||||
sse.effect.turnsRemain = 1;
|
||||
sse.effect.turnsRemain = BattleInfo::calculateSpellDuration(s, h);
|
||||
if(!sse.stacks.empty())
|
||||
sendAndApply(&sse);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user