mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
* next part of sieges
* partial implementation of berserk spell (unit does not always attack the nearest creature, wrong handling of situation when nearest stack is too far) * ballista can shoot (it was considered to be always blocked instead of always free)
This commit is contained in:
@@ -650,6 +650,14 @@ std::pair<ui32, ui32> CCallback::battleEstimateDamage(int attackerID, int defend
|
||||
return BattleInfo::calculateDmgRange(attacker, defender, attackerHero, defenderHero, battleCanShoot(attacker->ID, defender->position), 0);
|
||||
}
|
||||
|
||||
ui8 CCallback::battleGetSiegeLevel()
|
||||
{
|
||||
if(!gs->curB)
|
||||
return 0;
|
||||
|
||||
return gs->curB->siege;
|
||||
}
|
||||
|
||||
void CCallback::swapGarrisonHero( const CGTownInstance *town )
|
||||
{
|
||||
if(town->tempOwner != player) return;
|
||||
|
@@ -184,6 +184,7 @@ public:
|
||||
virtual ui8 battleGetWallState(int partOfWall)=0; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
|
||||
virtual int battleGetWallUnderHex(int hex)=0; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||
virtual std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID)=0; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
virtual ui8 battleGetSiegeLevel()=0; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||
};
|
||||
|
||||
struct HeroMoveDetails
|
||||
@@ -292,6 +293,7 @@ public:
|
||||
ui8 battleGetWallState(int partOfWall); //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
|
||||
int battleGetWallUnderHex(int hex); //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||
std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID); //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
ui8 battleGetSiegeLevel(); //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||
|
||||
//XXX hmmm _tmain on _GNUC_ wtf?
|
||||
//friends
|
||||
|
@@ -102,6 +102,19 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
|
||||
if(siegeH)
|
||||
{
|
||||
background = BitmapHandler::loadBitmap( siegeH->getSiegeName(0) );
|
||||
ui8 siegeLevel = LOCPLINT->cb->battleGetSiegeLevel();
|
||||
if(siegeLevel >= 2) //citadel or castle
|
||||
{
|
||||
//print moat/mlip
|
||||
SDL_Surface * moat = BitmapHandler::loadBitmap( siegeH->getSiegeName(13) ),
|
||||
* mlip = BitmapHandler::loadBitmap( siegeH->getSiegeName(14) );
|
||||
|
||||
blitAt(moat, 410, background->h - moat->h, background);
|
||||
blitAt(mlip, 410, background->h - mlip->h, background);
|
||||
|
||||
SDL_FreeSurface(moat);
|
||||
SDL_FreeSurface(mlip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3304,6 +3317,10 @@ std::string CBattleInterface::SiegeHelper::getSiegeName(ui16 what, ui16 additInf
|
||||
return "SG" + townTypeInfixes[town->town->typeID] + "WA2.BMP";
|
||||
case 12: //upper static wall
|
||||
return "SG" + townTypeInfixes[town->town->typeID] + "WA5.BMP";
|
||||
case 13: //moat
|
||||
return "SG" + townTypeInfixes[town->town->typeID] + "MOAT.BMP";
|
||||
case 14: //mlip
|
||||
return "SG" + townTypeInfixes[town->town->typeID] + "MLIP.BMP";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
@@ -242,7 +242,7 @@ private:
|
||||
~SiegeHelper(); //d-tor
|
||||
|
||||
//filename getters
|
||||
std::string getSiegeName(ui16 what, ui16 additInfo = 1) const; //what: 0 - background, 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall, 5 - below gate, 6 - over gate, 7 - upper wall, 8 - uppert tower, 9 - gate, 10 - gate arch, 11 - bottom static wall, 12 - upper static wall; additInfo: 1 - intact, 2 - damaged, 3 - destroyed
|
||||
std::string getSiegeName(ui16 what, ui16 additInfo = 1) const; //what: 0 - background, 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall, 5 - below gate, 6 - over gate, 7 - upper wall, 8 - uppert tower, 9 - gate, 10 - gate arch, 11 - bottom static wall, 12 - upper static wall, 13 - moat, 14 - mlip; additInfo: 1 - intact, 2 - damaged, 3 - destroyed
|
||||
|
||||
void printPartOfWall(SDL_Surface * to, int what);//what: 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall, 5 - below gate, 6 - over gate, 7 - upper wall, 8 - uppert tower, 9 - gate, 10 - gate arch, 11 - bottom static wall, 12 - upper static wall
|
||||
|
||||
|
@@ -239,6 +239,7 @@ static CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
|
||||
nobj->defInfo = VLC->dobjinfo->gobjs[id][subid];
|
||||
return nobj;
|
||||
}
|
||||
|
||||
CStack * BattleInfo::getStack(int stackID, bool onlyAlive)
|
||||
{
|
||||
for(unsigned int g=0; g<stacks.size(); ++g)
|
||||
@@ -248,6 +249,17 @@ CStack * BattleInfo::getStack(int stackID, bool onlyAlive)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const CStack * BattleInfo::getStack(int stackID, bool onlyAlive) const
|
||||
{
|
||||
for(unsigned int g=0; g<stacks.size(); ++g)
|
||||
{
|
||||
if(stacks[g]->ID == stackID && (!onlyAlive || stacks[g]->alive()))
|
||||
return stacks[g];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CStack * BattleInfo::getStackT(int tileID, bool onlyAlive)
|
||||
{
|
||||
for(unsigned int g=0; g<stacks.size(); ++g)
|
||||
@@ -264,7 +276,25 @@ CStack * BattleInfo::getStackT(int tileID, bool onlyAlive)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<int> & occupyable, bool flying, int stackToOmmit)
|
||||
|
||||
const CStack * BattleInfo::getStackT(int tileID, bool onlyAlive) const
|
||||
{
|
||||
for(unsigned int g=0; g<stacks.size(); ++g)
|
||||
{
|
||||
if(stacks[g]->position == tileID
|
||||
|| (stacks[g]->hasFeatureOfType(StackFeature::DOUBLE_WIDE) && stacks[g]->attackerOwned && stacks[g]->position-1 == tileID)
|
||||
|| (stacks[g]->hasFeatureOfType(StackFeature::DOUBLE_WIDE) && !stacks[g]->attackerOwned && stacks[g]->position+1 == tileID))
|
||||
{
|
||||
if(!onlyAlive || stacks[g]->alive())
|
||||
{
|
||||
return stacks[g];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<int> & occupyable, bool flying, int stackToOmmit) const
|
||||
{
|
||||
memset(accessibility, 1, BFIELD_SIZE); //initialize array with trues
|
||||
|
||||
@@ -303,14 +333,14 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool atta
|
||||
//walls
|
||||
if(siege > 0)
|
||||
{
|
||||
static const int permanentlyLocked[] = {12, 45, 78, 112, 147, 182};
|
||||
static const int permanentlyLocked[] = {12, 45, 78, 112, 147, 165};
|
||||
for(int b=0; b<ARRAY_COUNT(permanentlyLocked); ++b)
|
||||
{
|
||||
accessibility[permanentlyLocked[b]] = false;
|
||||
}
|
||||
|
||||
static const std::pair<int, int> lockedIfNotDestroyed[] = //(which part of wall, which hex is blocked if this part of wall is not destroyed
|
||||
{std::make_pair(2, 165), std::make_pair(3, 130), std::make_pair(4, 62), std::make_pair(5, 29)};
|
||||
{std::make_pair(2, 182), std::make_pair(3, 130), std::make_pair(4, 62), std::make_pair(5, 29)};
|
||||
for(int b=0; b<ARRAY_COUNT(lockedIfNotDestroyed); ++b)
|
||||
{
|
||||
if(si.wallState[lockedIfNotDestroyed[b].first] < 3)
|
||||
@@ -318,6 +348,12 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool atta
|
||||
accessibility[lockedIfNotDestroyed[b].second] = false;
|
||||
}
|
||||
}
|
||||
|
||||
//gate
|
||||
if(attackerOwned && si.wallState[7] < 3) //if it attacker's unit and gate is not destroyed
|
||||
{
|
||||
accessibility[95] = accessibility[96] = false; //block gate's hexes
|
||||
}
|
||||
}
|
||||
|
||||
//occupyability
|
||||
@@ -359,7 +395,7 @@ bool BattleInfo::isAccessible(int hex, bool * accessibility, bool twoHex, bool a
|
||||
}
|
||||
}
|
||||
|
||||
void BattleInfo::makeBFS(int start, bool *accessibility, int *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying) //both pointers must point to the at least 187-elements int arrays
|
||||
void BattleInfo::makeBFS(int start, bool *accessibility, int *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying) const //both pointers must point to the at least 187-elements int arrays
|
||||
{
|
||||
//inits
|
||||
for(int b=0; b<BFIELD_SIZE; ++b)
|
||||
@@ -379,20 +415,24 @@ void BattleInfo::makeBFS(int start, bool *accessibility, int *predecessor, int *
|
||||
for(unsigned int nr=0; nr<neighbours.size(); nr++)
|
||||
{
|
||||
curNext = neighbours[nr]; //if(!accessibility[curNext] || (dists[curHex]+1)>=dists[curNext])
|
||||
if(!isAccessible(curNext, accessibility, twoHex, attackerOwned, flying, dists[curHex]+1 == dists[curNext]) || (dists[curHex]+1)>=dists[curNext])
|
||||
bool accessible = isAccessible(curNext, accessibility, twoHex, attackerOwned, flying, dists[curHex]+1 == dists[curNext]);
|
||||
if( dists[curHex]+1 >= dists[curNext] )
|
||||
continue;
|
||||
hexq.push(curNext);
|
||||
dists[curNext] = dists[curHex] + 1;
|
||||
if(accessible)
|
||||
{
|
||||
hexq.push(curNext);
|
||||
dists[curNext] = dists[curHex] + 1;
|
||||
}
|
||||
predecessor[curNext] = curHex;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<int> BattleInfo::getAccessibility(int stackID, bool addOccupiable)
|
||||
std::vector<int> BattleInfo::getAccessibility(int stackID, bool addOccupiable) const
|
||||
{
|
||||
std::vector<int> ret;
|
||||
bool ac[BFIELD_SIZE];
|
||||
CStack *s = getStack(stackID);
|
||||
const CStack *s = getStack(stackID);
|
||||
std::set<int> occupyable;
|
||||
|
||||
getAccessibilityMap(ac, s->hasFeatureOfType(StackFeature::DOUBLE_WIDE), s->attackerOwned, addOccupiable, occupyable, s->hasFeatureOfType(StackFeature::FLYING), stackID);
|
||||
@@ -446,7 +486,7 @@ bool BattleInfo::isStackBlocked(int ID)
|
||||
{
|
||||
CStack *our = getStack(ID);
|
||||
if(our->hasFeatureOfType(StackFeature::SIEGE_WEAPON)) //siege weapons cannot be blocked
|
||||
return true;
|
||||
return false;
|
||||
|
||||
for(unsigned int i=0; i<stacks.size();i++)
|
||||
{
|
||||
@@ -2291,7 +2331,7 @@ ui32 BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, co
|
||||
return range.first;
|
||||
}
|
||||
|
||||
void BattleInfo::calculateCasualties( std::set<std::pair<ui32,si32> > *casualties )
|
||||
void BattleInfo::calculateCasualties( std::set<std::pair<ui32,si32> > *casualties ) const
|
||||
{
|
||||
for(unsigned int i=0; i<stacks.size();i++)//setting casualties
|
||||
{
|
||||
@@ -2408,7 +2448,7 @@ int BattleInfo::calculateSpellDuration(const CSpell * spell, const CGHeroInstanc
|
||||
}
|
||||
}
|
||||
|
||||
CStack * BattleInfo::generateNewStack(const CGHeroInstance * owner, int creatureID, int amount, int stackID, bool attackerOwned, int slot, int /*TerrainTile::EterrainType*/ terrain, int position)
|
||||
CStack * BattleInfo::generateNewStack(const CGHeroInstance * owner, int creatureID, int amount, int stackID, bool attackerOwned, int slot, int /*TerrainTile::EterrainType*/ terrain, int position) const
|
||||
{
|
||||
CStack * ret = new CStack(&VLC->creh->creatures[creatureID], amount, attackerOwned ? side1 : side2, stackID, attackerOwned, slot);
|
||||
if(owner)
|
||||
@@ -2456,7 +2496,7 @@ CStack * BattleInfo::generateNewStack(const CGHeroInstance * owner, int creature
|
||||
return ret;
|
||||
}
|
||||
|
||||
ui32 BattleInfo::getSpellCost(const CSpell * sp, const CGHeroInstance * caster)
|
||||
ui32 BattleInfo::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
|
||||
{
|
||||
ui32 ret = VLC->spellh->spells[sp->id].costs[caster->getSpellSchoolLevel(sp)];
|
||||
|
||||
@@ -2473,13 +2513,13 @@ ui32 BattleInfo::getSpellCost(const CSpell * sp, const CGHeroInstance * caster)
|
||||
return ret + manaReduction;
|
||||
}
|
||||
|
||||
int BattleInfo::hexToWallPart(int hex)
|
||||
int BattleInfo::hexToWallPart(int hex) const
|
||||
{
|
||||
if(siege == 0) //there is no battle!
|
||||
return -1;
|
||||
|
||||
static const std::pair<int, int> attackable[] = //potentially attackable parts of wall
|
||||
{std::make_pair(50, 0), std::make_pair(182, 1), std::make_pair(165, 2), std::make_pair(130, 3),
|
||||
{std::make_pair(50, 0), std::make_pair(183, 1), std::make_pair(182, 2), std::make_pair(130, 3),
|
||||
std::make_pair(62, 4), std::make_pair(29, 5), std::make_pair(12, 6), std::make_pair(95, 7), std::make_pair(96, 7)};
|
||||
|
||||
for(int g = 0; g < ARRAY_COUNT(attackable); ++g)
|
||||
@@ -2491,6 +2531,45 @@ int BattleInfo::hexToWallPart(int hex)
|
||||
return -1; //not found!
|
||||
}
|
||||
|
||||
std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const
|
||||
{
|
||||
bool ac[BFIELD_SIZE];
|
||||
std::set<int> occupyable;
|
||||
|
||||
getAccessibilityMap(ac, closest->hasFeatureOfType(StackFeature::DOUBLE_WIDE), closest->attackerOwned, false, occupyable, closest->hasFeatureOfType(StackFeature::FLYING), closest->ID);
|
||||
|
||||
int predecessor[BFIELD_SIZE], dist[BFIELD_SIZE];
|
||||
makeBFS(closest->position, ac, predecessor, dist, closest->hasFeatureOfType(StackFeature::DOUBLE_WIDE), closest->attackerOwned, closest->hasFeatureOfType(StackFeature::FLYING));
|
||||
|
||||
std::vector< std::pair< std::pair<int, int>, const CStack *> > stackPairs; //pairs <<distance, hex>, stack>
|
||||
for(int g=0; g<BFIELD_SIZE; ++g)
|
||||
{
|
||||
const CStack * atG = getStackT(g);
|
||||
if(!atG || atG->ID == closest->ID) //if there is not stack or we are the closest one
|
||||
continue;
|
||||
if(boost::logic::indeterminate(attackerOwned) || atG->attackerOwned == attackerOwned)
|
||||
{
|
||||
if(predecessor[g] == -1) //TODO: is it really the best solution?
|
||||
continue;
|
||||
stackPairs.push_back( std::make_pair( std::make_pair(dist[predecessor[g]], g), atG) );
|
||||
}
|
||||
}
|
||||
|
||||
if(stackPairs.size() > 0)
|
||||
{
|
||||
std::pair< std::pair<int, int>, const CStack *> minimalPair = stackPairs[0];
|
||||
|
||||
for(int b=1; b<stackPairs.size(); ++b)
|
||||
{
|
||||
if(stackPairs[b].first.first < minimalPair.first.first)
|
||||
minimalPair = stackPairs[b];
|
||||
}
|
||||
return std::make_pair(minimalPair.second, predecessor[minimalPair.first.second]);
|
||||
}
|
||||
|
||||
return std::make_pair<const CStack * , int>(NULL, -1);
|
||||
}
|
||||
|
||||
CStack * BattleInfo::getNextStack()
|
||||
{
|
||||
CStack *current = getStack(activeStack);
|
||||
|
@@ -138,24 +138,27 @@ struct DLL_EXPORT BattleInfo
|
||||
CStack * getNextStack(); //which stack will have turn after current one
|
||||
std::vector<CStack> getStackQueue(); //returns stack in order of their movement action
|
||||
CStack * getStack(int stackID, bool onlyAlive = true);
|
||||
const CStack * getStack(int stackID, bool onlyAlive = true) const;
|
||||
CStack * getStackT(int tileID, bool onlyAlive = true);
|
||||
void getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<int> & occupyable, bool flying, int stackToOmmit=-1); //send pointer to at least 187 allocated bytes
|
||||
const CStack * getStackT(int tileID, bool onlyAlive = true) const;
|
||||
void getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<int> & occupyable, bool flying, int stackToOmmit=-1) const; //send pointer to at least 187 allocated bytes
|
||||
static bool isAccessible(int hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS
|
||||
void makeBFS(int start, bool*accessibility, int *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying); //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result
|
||||
void makeBFS(int start, bool*accessibility, int *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying) const; //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result
|
||||
std::pair< std::vector<int>, int > getPath(int start, int dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
|
||||
std::vector<int> getAccessibility(int stackID, bool addOccupiable); //returns vector of accessible tiles (taking into account the creature range)
|
||||
std::vector<int> getAccessibility(int stackID, bool addOccupiable) const; //returns vector of accessible tiles (taking into account the creature range)
|
||||
|
||||
bool isStackBlocked(int ID); //returns true if there is neighbouring enemy stack
|
||||
static signed char mutualPosition(int hex1, int hex2); //returns info about mutual position of given hexes (-1 - they're distant, 0 - left top, 1 - right top, 2 - right, 3 - right bottom, 4 - left bottom, 5 - left)
|
||||
static std::vector<int> neighbouringTiles(int hex);
|
||||
static ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge); //charge - number of hexes travelled before attack (for champion's jousting)
|
||||
static std::pair<ui32, ui32> calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge); //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
|
||||
void calculateCasualties(std::set<std::pair<ui32,si32> > *casualties);
|
||||
void calculateCasualties(std::set<std::pair<ui32,si32> > *casualties) const;
|
||||
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);
|
||||
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
|
||||
ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster); //returns cost of given spell
|
||||
int hexToWallPart(int hex); //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||
CStack * generateNewStack(const CGHeroInstance * owner, int creatureID, int amount, int stackID, bool attackerOwned, int slot, int /*TerrainTile::EterrainType*/ terrain, int position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
|
||||
ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
|
||||
int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||
std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
|
||||
};
|
||||
|
||||
class DLL_EXPORT CStack
|
||||
|
@@ -907,6 +907,9 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
|
||||
case 58: //counterstrike
|
||||
sf.push_back(featureGenerator(StackFeature::ADDITIONAL_RETALIATION, 0, VLC->spellh->spells[sse.id].powers[sse.level], sse.turnsRemain));
|
||||
break;
|
||||
case 59: //bersek
|
||||
sf.push_back(featureGenerator(StackFeature::ATTACKS_NEAREST_CREATURE, 0, sse.level, sse.turnsRemain));
|
||||
break;
|
||||
case 60: //hypnotize
|
||||
sf.push_back(featureGenerator(StackFeature::HYPNOTIZED, 0, sse.level, sse.turnsRemain));
|
||||
break;
|
||||
|
@@ -376,6 +376,26 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
|
||||
}
|
||||
}
|
||||
|
||||
if(next->hasFeatureOfType(StackFeature::ATTACKS_NEAREST_CREATURE)) //while in berserk
|
||||
{
|
||||
std::pair<const CStack *, int> attackInfo = curB.getNearestStack(next, boost::logic::indeterminate);
|
||||
if(attackInfo.first != NULL)
|
||||
{
|
||||
BattleAction attack;
|
||||
attack.actionType = 6;
|
||||
attack.side = !next->attackerOwned;
|
||||
attack.stackNumber = next->ID;
|
||||
|
||||
attack.additionalInfo = attackInfo.first->position;
|
||||
attack.destinationTile = attackInfo.second;
|
||||
|
||||
makeBattleAction(attack);
|
||||
|
||||
checkForBattleEnd(stacks);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
askInterfaceForMove:
|
||||
//ask interface and wait for answer
|
||||
if(!battleResult.get())
|
||||
@@ -1037,62 +1057,65 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
|
||||
curB->si.wallState[b] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//randomize obstacles
|
||||
bool obAv[BFIELD_SIZE]; //availability of hexes for obstacles;
|
||||
std::vector<int> possibleObstacles;
|
||||
|
||||
for(int i=0; i<BFIELD_SIZE; ++i)
|
||||
{
|
||||
if(i%17 < 4 || i%17 > 12)
|
||||
{
|
||||
obAv[i] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
obAv[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int terType = gs->battleGetBattlefieldType(tile);
|
||||
|
||||
for(std::map<int, CObstacleInfo>::const_iterator g=VLC->heroh->obstacles.begin(); g!=VLC->heroh->obstacles.end(); ++g)
|
||||
//randomize obstacles
|
||||
if(town == NULL) //do it only when it's not siege
|
||||
{
|
||||
if(g->second.allowedTerrains[terType-1] == '1') //we need to take terType with -1 because terrain ids start from 1 and allowedTerrains array is indexed from 0
|
||||
{
|
||||
possibleObstacles.push_back(g->first);
|
||||
}
|
||||
}
|
||||
bool obAv[BFIELD_SIZE]; //availability of hexes for obstacles;
|
||||
std::vector<int> possibleObstacles;
|
||||
|
||||
srand(time(NULL));
|
||||
if(possibleObstacles.size() > 0) //we cannot place any obstacles when we don't have them
|
||||
{
|
||||
int toBlock = rand()%6 + 6; //how many hexes should be blocked by obstacles
|
||||
while(toBlock>0)
|
||||
for(int i=0; i<BFIELD_SIZE; ++i)
|
||||
{
|
||||
CObstacleInstance coi;
|
||||
coi.uniqueID = curB->obstacles.size();
|
||||
coi.ID = possibleObstacles[rand()%possibleObstacles.size()];
|
||||
coi.pos = rand()%BFIELD_SIZE;
|
||||
std::vector<int> block = VLC->heroh->obstacles[coi.ID].getBlocked(coi.pos);
|
||||
bool badObstacle = false;
|
||||
for(int b=0; b<block.size(); ++b)
|
||||
if(i%17 < 4 || i%17 > 12)
|
||||
{
|
||||
if(block[b] < 0 || block[b] >= BFIELD_SIZE || !obAv[block[b]])
|
||||
obAv[i] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
obAv[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(std::map<int, CObstacleInfo>::const_iterator g=VLC->heroh->obstacles.begin(); g!=VLC->heroh->obstacles.end(); ++g)
|
||||
{
|
||||
if(g->second.allowedTerrains[terType-1] == '1') //we need to take terType with -1 because terrain ids start from 1 and allowedTerrains array is indexed from 0
|
||||
{
|
||||
possibleObstacles.push_back(g->first);
|
||||
}
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
if(possibleObstacles.size() > 0) //we cannot place any obstacles when we don't have them
|
||||
{
|
||||
int toBlock = rand()%6 + 6; //how many hexes should be blocked by obstacles
|
||||
while(toBlock>0)
|
||||
{
|
||||
CObstacleInstance coi;
|
||||
coi.uniqueID = curB->obstacles.size();
|
||||
coi.ID = possibleObstacles[rand()%possibleObstacles.size()];
|
||||
coi.pos = rand()%BFIELD_SIZE;
|
||||
std::vector<int> block = VLC->heroh->obstacles[coi.ID].getBlocked(coi.pos);
|
||||
bool badObstacle = false;
|
||||
for(int b=0; b<block.size(); ++b)
|
||||
{
|
||||
badObstacle = true;
|
||||
break;
|
||||
if(block[b] < 0 || block[b] >= BFIELD_SIZE || !obAv[block[b]])
|
||||
{
|
||||
badObstacle = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(badObstacle) continue;
|
||||
//obstacle can be placed
|
||||
curB->obstacles.push_back(coi);
|
||||
for(int b=0; b<block.size(); ++b)
|
||||
{
|
||||
if(block[b] >= 0 && block[b] < BFIELD_SIZE)
|
||||
obAv[block[b]] = false;
|
||||
}
|
||||
toBlock -= block.size();
|
||||
}
|
||||
if(badObstacle) continue;
|
||||
//obstacle can be placed
|
||||
curB->obstacles.push_back(coi);
|
||||
for(int b=0; b<block.size(); ++b)
|
||||
{
|
||||
if(block[b] >= 0 && block[b] < BFIELD_SIZE)
|
||||
obAv[block[b]] = false;
|
||||
}
|
||||
toBlock -= block.size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2955,6 +2978,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
case 55: //slayer
|
||||
case 56: //frenzy
|
||||
case 58: //counterstrike
|
||||
case 59: //berserk
|
||||
case 60: //hypnotize
|
||||
case 61: //forgetfulness
|
||||
case 62: //blind
|
||||
|
Reference in New Issue
Block a user