mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +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:
@ -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);
|
||||
|
Reference in New Issue
Block a user