mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-15 13:33:36 +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 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 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 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
|
class CAIHandler
|
||||||
{
|
{
|
||||||
|
@ -496,6 +496,10 @@ void CBattleInterface::show(SDL_Surface * to)
|
|||||||
for(size_t v=0; v<stackAliveByHex[b].size(); ++v)
|
for(size_t v=0; v<stackAliveByHex[b].size(); ++v)
|
||||||
{
|
{
|
||||||
int curStackID = stackAliveByHex[b][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];
|
const CStack &curStack = stacks[curStackID];
|
||||||
int animType = creAnims[curStackID]->getType();
|
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
|
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);
|
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 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 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 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);
|
cl->playerint[GS(cl)->curB->side1]->battleSpellCast(this);
|
||||||
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end())
|
||||||
cl->playerint[GS(cl)->curB->side2]->battleSpellCast(this);
|
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 )
|
void SetStackEffect::applyCl( CClient *cl )
|
||||||
|
@ -34,9 +34,9 @@
|
|||||||
31 1 24 0 0 0 X
|
31 1 24 0 0 0 X
|
||||||
32 1 23 0 0 0 X
|
32 1 23 0 0 0 X
|
||||||
33 1 26 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
|
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
|
37 1 39 0 0 0 0
|
||||||
38 1 79 0 0 0 0
|
38 1 79 0 0 0 0
|
||||||
39 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;
|
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 * BattleInfo::getNextStack()
|
||||||
{
|
{
|
||||||
CStack *current = getStack(activeStack);
|
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
|
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);
|
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
|
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
|
class DLL_EXPORT CStack
|
||||||
|
@ -900,8 +900,8 @@ struct SpellCast : public CPackForClient//3009
|
|||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
|
|
||||||
ui8 side; //which hero did cast spell: 0 - attacker, 1 - defender
|
ui8 side; //which hero did cast spell: 0 - attacker, 1 - defender
|
||||||
ui32 id;
|
ui32 id; //id of spell
|
||||||
ui8 skill;
|
ui8 skill; //caster's skill level
|
||||||
ui16 tile; //destination tile (may not be set in some global/mass spells
|
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::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)
|
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);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
|
|
||||||
std::set<ui32> stacks;
|
std::set<ui32> stacks; //affected stacks (IDs)
|
||||||
CStack::StackEffect effect;
|
CStack::StackEffect effect; //type of effect
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & stacks & effect;
|
h & stacks & effect;
|
||||||
|
@ -695,6 +695,7 @@ DLL_EXPORT void SpellCast::applyGs( CGameState *gs )
|
|||||||
gs->curB->castSpells[side]++;
|
gs->curB->castSpells[side]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(gs->curB && id == 35) //dispel
|
if(gs->curB && id == 35) //dispel
|
||||||
{
|
{
|
||||||
for(std::set<ui32>::const_iterator it = affectedCres.begin(); it != affectedCres.end(); ++it)
|
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)
|
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
|
case 33: //protection from earth
|
||||||
sf.push_back(featureGenerator(StackFeature::SPELL_DAMAGE_REDUCTION, 3, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
|
sf.push_back(featureGenerator(StackFeature::SPELL_DAMAGE_REDUCTION, 3, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
|
||||||
break;
|
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
|
case 41: //bless
|
||||||
sf.push_back(featureGenerator(StackFeature::ALWAYS_MAXIMUM_DAMAGE, -1, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
|
sf.push_back(featureGenerator(StackFeature::ALWAYS_MAXIMUM_DAMAGE, -1, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
|
||||||
break;
|
break;
|
||||||
|
@ -307,6 +307,9 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf
|
|||||||
CCreatureSet ret(set);
|
CCreatureSet ret(set);
|
||||||
for(int i=0; i<bat->stacks.size();i++)
|
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];
|
CStack *st = bat->stacks[i];
|
||||||
if(st->owner==color && vstd::contains(set.slots,st->slot) && st->amount < set.slots.find(st->slot)->second.second)
|
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->side2=(hero2)?(hero2->tempOwner):(-1);
|
||||||
curB->round = -2;
|
curB->round = -2;
|
||||||
curB->activeStack = -1;
|
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;
|
//reading battleStartpos
|
||||||
}
|
|
||||||
//initialization of positions
|
|
||||||
std::ifstream positions;
|
std::ifstream positions;
|
||||||
positions.open("config" PATHSEPARATOR "battleStartpos.txt", std::ios_base::in|std::ios_base::binary);
|
positions.open("config" PATHSEPARATOR "battleStartpos.txt", std::ios_base::in|std::ios_base::binary);
|
||||||
if(!positions.is_open())
|
if(!positions.is_open())
|
||||||
@ -911,49 +892,31 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
|
|||||||
positions>>dump;
|
positions>>dump;
|
||||||
CGH::readItTo(positions, defenderTight);
|
CGH::readItTo(positions, defenderTight);
|
||||||
positions.close();
|
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)
|
||||||
|
pos = attackerTight[army1.slots.size()-1][i->first];
|
||||||
|
else
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
if(army1.formation)
|
|
||||||
for(int b=0; b<army1.slots.size(); ++b) //tight
|
|
||||||
{
|
|
||||||
stacks[b]->position = attackerTight[army1.slots.size()-1][b];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
for(int b=0; b<army1.slots.size(); ++b) //loose
|
|
||||||
{
|
|
||||||
stacks[b]->position = attackerLoose[army1.slots.size()-1][b];
|
|
||||||
}
|
|
||||||
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
|
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));
|
int pos;
|
||||||
//base luck/morale calculations
|
if(army2.formation)
|
||||||
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
pos = defenderTight[army2.slots.size()-1][i->first];
|
||||||
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
|
else
|
||||||
{
|
pos = defenderLoose[army2.slots.size()-1][i->first];
|
||||||
stacks.back()->morale = 0;
|
|
||||||
stacks.back()->luck = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(army2.formation)
|
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);
|
||||||
for(int b=0; b<army2.slots.size(); ++b) //tight
|
stacks.push_back(stack);
|
||||||
{
|
}
|
||||||
stacks[b+army1.slots.size()]->position = defenderTight[army2.slots.size()-1][b];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
for(int b=0; b<army2.slots.size(); ++b) //loose
|
|
||||||
{
|
|
||||||
stacks[b+army1.slots.size()]->position = defenderLoose[army2.slots.size()-1][b];
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unsigned g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
|
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
|
//adding war machines
|
||||||
if(hero1)
|
if(hero1)
|
||||||
{
|
{
|
||||||
if(hero1->getArt(13)) //ballista
|
if(hero1->getArt(13)) //ballista
|
||||||
{
|
{
|
||||||
stacks.push_back(new CStack(&VLC->creh->creatures[146], 1, hero1->tempOwner, stacks.size(), true, 255));
|
CStack * stack = BattleInfo::generateNewStack(hero1, 146, 1, stacks.size(), true, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 52);
|
||||||
stacks[stacks.size()-1]->position = 52;
|
stacks.push_back(stack);
|
||||||
stacks.back()->morale = hero1->getCurrentMorale(stacks.back()->ID,false);
|
|
||||||
stacks.back()->luck = hero1->getCurrentLuck(stacks.back()->ID,false);
|
|
||||||
}
|
}
|
||||||
if(hero1->getArt(14)) //ammo cart
|
if(hero1->getArt(14)) //ammo cart
|
||||||
{
|
{
|
||||||
stacks.push_back(new CStack(&VLC->creh->creatures[148], 1, hero1->tempOwner, stacks.size(), true, 255));
|
CStack * stack = BattleInfo::generateNewStack(hero1, 148, 1, stacks.size(), true, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 18);
|
||||||
stacks[stacks.size()-1]->position = 18;
|
stacks.push_back(stack);
|
||||||
stacks.back()->morale = hero1->getCurrentMorale(stacks.back()->ID,false);
|
|
||||||
stacks.back()->luck = hero1->getCurrentLuck(stacks.back()->ID,false);
|
|
||||||
}
|
}
|
||||||
if(hero1->getArt(15)) //first aid tent
|
if(hero1->getArt(15)) //first aid tent
|
||||||
{
|
{
|
||||||
stacks.push_back(new CStack(&VLC->creh->creatures[147], 1, hero1->tempOwner, stacks.size(), true, 255));
|
CStack * stack = BattleInfo::generateNewStack(hero1, 147, 1, stacks.size(), true, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 154);
|
||||||
stacks[stacks.size()-1]->position = 154;
|
stacks.push_back(stack);
|
||||||
stacks.back()->morale = hero1->getCurrentMorale(stacks.back()->ID,false);
|
|
||||||
stacks.back()->luck = hero1->getCurrentLuck(stacks.back()->ID,false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(hero2)
|
if(hero2)
|
||||||
{
|
{
|
||||||
if(hero2->getArt(13)) //ballista
|
if(hero2->getArt(13)) //ballista
|
||||||
{
|
{
|
||||||
stacks.push_back(new CStack(&VLC->creh->creatures[146], 1, hero2->tempOwner, stacks.size(), false, 255));
|
CStack * stack = BattleInfo::generateNewStack(hero2, 146, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 66);
|
||||||
stacks[stacks.size()-1]->position = 66;
|
stacks.push_back(stack);
|
||||||
stacks.back()->morale = hero2->getCurrentMorale(stacks.back()->ID,false);
|
|
||||||
stacks.back()->luck = hero2->getCurrentLuck(stacks.back()->ID,false);
|
|
||||||
}
|
}
|
||||||
if(hero2->getArt(14)) //ammo cart
|
if(hero2->getArt(14)) //ammo cart
|
||||||
{
|
{
|
||||||
stacks.push_back(new CStack(&VLC->creh->creatures[148], 1, hero2->tempOwner, stacks.size(), false, 255));
|
CStack * stack = BattleInfo::generateNewStack(hero2, 148, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 32);
|
||||||
stacks[stacks.size()-1]->position = 32;
|
stacks.push_back(stack);
|
||||||
stacks.back()->morale = hero2->getCurrentMorale(stacks.back()->ID,false);
|
|
||||||
stacks.back()->luck = hero2->getCurrentLuck(stacks.back()->ID,false);
|
|
||||||
}
|
}
|
||||||
if(hero2->getArt(15)) //first aid tent
|
if(hero2->getArt(15)) //first aid tent
|
||||||
{
|
{
|
||||||
stacks.push_back(new CStack(&VLC->creh->creatures[147], 1, hero2->tempOwner, stacks.size(), false, 255));
|
CStack * stack = BattleInfo::generateNewStack(hero2, 147, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, 168);
|
||||||
stacks[stacks.size()-1]->position = 168;
|
stacks.push_back(stack);
|
||||||
stacks.back()->morale = hero2->getCurrentMorale(stacks.back()->ID,false);
|
|
||||||
stacks.back()->luck = hero2->getCurrentLuck(stacks.back()->ID,false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//war machines added
|
//war machines added
|
||||||
@ -1070,7 +1009,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
|
|||||||
bool badObstacle = false;
|
bool badObstacle = false;
|
||||||
for(int b=0; b<block.size(); ++b)
|
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;
|
badObstacle = true;
|
||||||
break;
|
break;
|
||||||
@ -2811,6 +2750,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
case 31: //protection from fire
|
case 31: //protection from fire
|
||||||
case 32: //protection from water
|
case 32: //protection from water
|
||||||
case 33: //protection from earth
|
case 33: //protection from earth
|
||||||
|
case 34: //anti-magic
|
||||||
case 41: //bless
|
case 41: //bless
|
||||||
case 42: //curse
|
case 42: //curse
|
||||||
case 43: //bloodlust
|
case 43: //bloodlust
|
||||||
@ -2826,6 +2766,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
case 53: //haste
|
case 53: //haste
|
||||||
case 54: //slow
|
case 54: //slow
|
||||||
case 55: //slayer
|
case 55: //slayer
|
||||||
|
case 56: //frenzy
|
||||||
case 61: //forgetfulness
|
case 61: //forgetfulness
|
||||||
{
|
{
|
||||||
SetStackEffect sse;
|
SetStackEffect sse;
|
||||||
@ -2837,23 +2778,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
}
|
}
|
||||||
sse.effect.id = ba.additionalInfo;
|
sse.effect.id = ba.additionalInfo;
|
||||||
sse.effect.level = h->getSpellSchoolLevel(s);
|
sse.effect.level = h->getSpellSchoolLevel(s);
|
||||||
sse.effect.turnsRemain = h->getPrimSkillLevel(2) + h->valOfBonuses(HeroBonus::SPELL_DURATION);
|
sse.effect.turnsRemain = BattleInfo::calculateSpellDuration(s, h);
|
||||||
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;
|
|
||||||
if(!sse.stacks.empty())
|
if(!sse.stacks.empty())
|
||||||
sendAndApply(&sse);
|
sendAndApply(&sse);
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user