mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
- Restored missing code for BattleInfo::getAvaliableHex - Elementals will now be placed correctly
- Fixes for BattleHex::getDistance returning 0 for adjacent hexes - All stacks will now be placed after obstacles (fixes #1004) - Removed unused code from ArtHandler
This commit is contained in:
parent
8c6965c5ee
commit
4d62525ff7
@ -81,7 +81,7 @@ char BattleHex::getDistance(BattleHex hex1, BattleHex hex2)
|
||||
{
|
||||
int xDst = std::abs(hex1 % GameConstants::BFIELD_WIDTH - hex2 % GameConstants::BFIELD_WIDTH),
|
||||
yDst = std::abs(hex1 / GameConstants::BFIELD_WIDTH - hex2 / GameConstants::BFIELD_WIDTH);
|
||||
return std::max(xDst, yDst) + std::min(xDst, yDst) - (yDst + 1)/2;
|
||||
return std::max(xDst, yDst) + std::min(xDst, yDst) - (yDst + (yDst + xDst < 2 ? 0 : 1))/2;
|
||||
}
|
||||
|
||||
void BattleHex::checkAndPush(int tile, std::vector<BattleHex> & ret)
|
||||
|
@ -421,8 +421,19 @@ int BattleInfo::getAvaliableHex(TCreature creID, bool attackerOwned, int initial
|
||||
bool twoHex = VLC->creh->creatures[creID]->isDoubleWide();
|
||||
bool flying = VLC->creh->creatures[creID]->isFlying();
|
||||
|
||||
int pos;
|
||||
if (initialPos > -1)
|
||||
pos = initialPos;
|
||||
else //summon elementals depending on player side
|
||||
{
|
||||
if (attackerOwned)
|
||||
pos = 0; //top left
|
||||
else
|
||||
pos = GameConstants::BFIELD_WIDTH - 1; //top right
|
||||
}
|
||||
|
||||
std::set<BattleHex> occupyable;
|
||||
getAccessibilityMap (ac, twoHex, attackerOwned, false, occupyable, flying);
|
||||
getAccessibilityMap (ac, twoHex, attackerOwned, true, occupyable, flying);
|
||||
|
||||
for (int i = 0; i < GameConstants::BFIELD_SIZE; ++i)
|
||||
{
|
||||
@ -432,7 +443,7 @@ int BattleInfo::getAvaliableHex(TCreature creID, bool attackerOwned, int initial
|
||||
if (!occupyable.size())
|
||||
return -1; //all tiles are covered
|
||||
|
||||
return getClosestTile (attackerOwned, initialPos, occupyable);
|
||||
return getClosestTile (attackerOwned, pos, occupyable);
|
||||
}
|
||||
|
||||
bool BattleInfo::isStackBlocked(const CStack * stack) const
|
||||
@ -1005,7 +1016,7 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, bool attackerO
|
||||
(base.armyObj && base.armyObj->tempOwner == owner));
|
||||
|
||||
CStack * ret = new CStack(&base, owner, stackID, attackerOwned, slot);
|
||||
ret->position = position;
|
||||
ret->position = getAvaliableHex (base.getCreatureID(), attackerOwned, position); //TODO: what if no free tile on battlefield was found?
|
||||
return ret;
|
||||
}
|
||||
CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, int slot, BattleHex position) const
|
||||
@ -1648,7 +1659,110 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
|
||||
curB->terrainType = terrain;
|
||||
}
|
||||
|
||||
//reading battleStartpos
|
||||
//setting up siege obstacles
|
||||
if (town && town->hasFort())
|
||||
{
|
||||
for (int b = 0; b < ARRAY_COUNT (curB->si.wallState); ++b)
|
||||
{
|
||||
curB->si.wallState[b] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//randomize obstacles
|
||||
if (town == NULL && !creatureBank) //do it only when it's not siege and not creature bank
|
||||
{
|
||||
const int ABSOLUTE_OBSTACLES_COUNT = 34, USUAL_OBSTACLES_COUNT = 91; //shouldn't be changes if we want H3-like obstacle placement
|
||||
|
||||
RandGen r;
|
||||
auto ourRand = [&]{ return r.rand(); };
|
||||
r.srand(tile);
|
||||
r.rand(1,8); //battle sound ID to play... can't do anything with it here
|
||||
int tilesToBlock = r.rand(5,12);
|
||||
const int specialBattlefield = battlefieldTypeToBI(battlefieldType);
|
||||
|
||||
std::vector<BattleHex> blockedTiles;
|
||||
|
||||
auto appropriateAbsoluteObstacle = [&](int id)
|
||||
{
|
||||
return VLC->heroh->absoluteObstacles[id].isAppropriate(curB->terrainType, specialBattlefield);
|
||||
};
|
||||
auto appropriateUsualObstacle = [&](int id) -> bool
|
||||
{
|
||||
return VLC->heroh->obstacles[id].isAppropriate(curB->terrainType, specialBattlefield);
|
||||
};
|
||||
|
||||
if(r.rand(1,100) <= 40) //put cliff-like obstacle
|
||||
{
|
||||
RangeGenerator obidgen(0, ABSOLUTE_OBSTACLES_COUNT-1, ourRand);
|
||||
|
||||
try
|
||||
{
|
||||
auto obstPtr = make_shared<CObstacleInstance>();
|
||||
obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE;
|
||||
obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle);
|
||||
obstPtr->uniqueID = curB->obstacles.size();
|
||||
curB->obstacles.push_back(obstPtr);
|
||||
|
||||
BOOST_FOREACH(BattleHex blocked, obstPtr->getBlockedTiles())
|
||||
blockedTiles.push_back(blocked);
|
||||
tilesToBlock -= VLC->heroh->absoluteObstacles[obstPtr->ID].blockedTiles.size() / 2;
|
||||
}
|
||||
catch(RangeGenerator::ExhaustedPossibilities &)
|
||||
{
|
||||
//silently ignore, if we can't place absolute obstacle, we'll go with the usual ones
|
||||
}
|
||||
}
|
||||
|
||||
RangeGenerator obidgen(0, USUAL_OBSTACLES_COUNT-1, ourRand);
|
||||
try
|
||||
{
|
||||
while(tilesToBlock > 0)
|
||||
{
|
||||
const int obid = obidgen.getSuchNumber(appropriateUsualObstacle);
|
||||
const CObstacleInfo &obi = VLC->heroh->obstacles[obid];
|
||||
|
||||
auto validPosition = [&](BattleHex pos) -> bool
|
||||
{
|
||||
if(obi.height >= pos.getY())
|
||||
return false;
|
||||
if(pos.getX() == 0)
|
||||
return false;
|
||||
if(pos.getX() + obi.width > 15)
|
||||
return false;
|
||||
if(vstd::contains(blockedTiles, pos))
|
||||
return false;
|
||||
|
||||
BOOST_FOREACH(BattleHex blocked, obi.getBlocked(pos))
|
||||
{
|
||||
if(vstd::contains(blockedTiles, blocked))
|
||||
return false;
|
||||
int x = blocked.getX();
|
||||
if(x <= 2 || x >= 14)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
RangeGenerator posgenerator(18, 168, ourRand);
|
||||
|
||||
auto obstPtr = make_shared<CObstacleInstance>();
|
||||
obstPtr->ID = obid;
|
||||
obstPtr->pos = posgenerator.getSuchNumber(validPosition);
|
||||
obstPtr->uniqueID = curB->obstacles.size();
|
||||
curB->obstacles.push_back(obstPtr);
|
||||
|
||||
BOOST_FOREACH(BattleHex blocked, obstPtr->getBlockedTiles())
|
||||
blockedTiles.push_back(blocked);
|
||||
tilesToBlock -= obi.blockedTiles.size();
|
||||
}
|
||||
}
|
||||
catch(RangeGenerator::ExhaustedPossibilities &)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//reading battleStartpos - add creatures AFTER random obstacles are generated
|
||||
//TODO: parse once to some structure
|
||||
std::vector< std::vector<int> > attackerLoose, defenderLoose, attackerTight, defenderTight, attackerCreBank, defenderCreBank;
|
||||
std::vector <int> commanderField, commanderBank;
|
||||
@ -1802,109 +1916,6 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int battlefieldTyp
|
||||
|
||||
std::stable_sort(stacks.begin(),stacks.end(),cmpst);
|
||||
|
||||
//setting up siege
|
||||
if(town && town->hasFort())
|
||||
{
|
||||
for(int b=0; b<ARRAY_COUNT(curB->si.wallState); ++b)
|
||||
{
|
||||
curB->si.wallState[b] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//randomize obstacles
|
||||
if(town == NULL && !creatureBank) //do it only when it's not siege and not creature bank
|
||||
{
|
||||
const int ABSOLUTE_OBSTACLES_COUNT = 34, USUAL_OBSTACLES_COUNT = 91; //shouldn't be changes if we want H3-like obstacle placement
|
||||
|
||||
RandGen r;
|
||||
auto ourRand = [&]{ return r.rand(); };
|
||||
r.srand(tile);
|
||||
r.rand(1,8); //battle sound ID to play... can't do anything with it here
|
||||
int tilesToBlock = r.rand(5,12);
|
||||
const int specialBattlefield = battlefieldTypeToBI(battlefieldType);
|
||||
|
||||
std::vector<BattleHex> blockedTiles;
|
||||
|
||||
auto appropriateAbsoluteObstacle = [&](int id)
|
||||
{
|
||||
return VLC->heroh->absoluteObstacles[id].isAppropriate(curB->terrainType, specialBattlefield);
|
||||
};
|
||||
auto appropriateUsualObstacle = [&](int id) -> bool
|
||||
{
|
||||
return VLC->heroh->obstacles[id].isAppropriate(curB->terrainType, specialBattlefield);
|
||||
};
|
||||
|
||||
if(r.rand(1,100) <= 40) //put cliff-like obstacle
|
||||
{
|
||||
RangeGenerator obidgen(0, ABSOLUTE_OBSTACLES_COUNT-1, ourRand);
|
||||
|
||||
try
|
||||
{
|
||||
auto obstPtr = make_shared<CObstacleInstance>();
|
||||
obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE;
|
||||
obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle);
|
||||
obstPtr->uniqueID = curB->obstacles.size();
|
||||
curB->obstacles.push_back(obstPtr);
|
||||
|
||||
BOOST_FOREACH(BattleHex blocked, obstPtr->getBlockedTiles())
|
||||
blockedTiles.push_back(blocked);
|
||||
tilesToBlock -= VLC->heroh->absoluteObstacles[obstPtr->ID].blockedTiles.size() / 2;
|
||||
}
|
||||
catch(RangeGenerator::ExhaustedPossibilities &)
|
||||
{
|
||||
//silently ignore, if we can't place absolute obstacle, we'll go with the usual ones
|
||||
}
|
||||
}
|
||||
|
||||
RangeGenerator obidgen(0, USUAL_OBSTACLES_COUNT-1, ourRand);
|
||||
try
|
||||
{
|
||||
while(tilesToBlock > 0)
|
||||
{
|
||||
const int obid = obidgen.getSuchNumber(appropriateUsualObstacle);
|
||||
const CObstacleInfo &obi = VLC->heroh->obstacles[obid];
|
||||
|
||||
auto validPosition = [&](BattleHex pos) -> bool
|
||||
{
|
||||
if(obi.height >= pos.getY())
|
||||
return false;
|
||||
if(pos.getX() == 0)
|
||||
return false;
|
||||
if(pos.getX() + obi.width > 15)
|
||||
return false;
|
||||
if(vstd::contains(blockedTiles, pos))
|
||||
return false;
|
||||
|
||||
BOOST_FOREACH(BattleHex blocked, obi.getBlocked(pos))
|
||||
{
|
||||
if(vstd::contains(blockedTiles, blocked))
|
||||
return false;
|
||||
int x = blocked.getX();
|
||||
if(x <= 2 || x >= 14)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
RangeGenerator posgenerator(18, 168, ourRand);
|
||||
|
||||
auto obstPtr = make_shared<CObstacleInstance>();
|
||||
obstPtr->ID = obid;
|
||||
obstPtr->pos = posgenerator.getSuchNumber(validPosition);
|
||||
obstPtr->uniqueID = curB->obstacles.size();
|
||||
curB->obstacles.push_back(obstPtr);
|
||||
|
||||
BOOST_FOREACH(BattleHex blocked, obstPtr->getBlockedTiles())
|
||||
blockedTiles.push_back(blocked);
|
||||
tilesToBlock -= obi.blockedTiles.size();
|
||||
}
|
||||
}
|
||||
catch(RangeGenerator::ExhaustedPossibilities &)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//spell level limiting bonus
|
||||
curB->addNewBonus(new Bonus(Bonus::ONE_BATTLE, Bonus::LEVEL_SPELL_IMMUNITY, Bonus::OTHER,
|
||||
0, -1, -1, Bonus::INDEPENDENT_MAX));
|
||||
|
@ -161,62 +161,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// class DLL_LINKAGE IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner
|
||||
// { //used only for dynamic cast :P
|
||||
// public:
|
||||
// si32 ID; //used for smart serialization
|
||||
//
|
||||
// template <typename Handler> void serialize(Handler &h, const int version)
|
||||
// {
|
||||
// h & static_cast<CArtifact&>(*this);
|
||||
// h & ID;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// class DLL_LINKAGE CScroll : public IModableArt // Spell Scroll
|
||||
// {
|
||||
// public:
|
||||
// CScroll(){spellid=0;};
|
||||
// CScroll(spelltype sid){spellid = sid;};
|
||||
// spelltype spellid;
|
||||
// void Init();
|
||||
// void SetProperty (int mod){spellid = mod;};
|
||||
// template <typename Handler> void serialize(Handler &h, const int version)
|
||||
// {
|
||||
// h & static_cast<IModableArt&>(*this);
|
||||
// h & spellid;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// class DLL_LINKAGE CCustomizableArt : public IModableArt // Warlord's Banner with multiple options
|
||||
// {
|
||||
// public:
|
||||
// ui8 mode;
|
||||
// CCustomizableArt(){mode=0;};
|
||||
// void Init(){};
|
||||
// void SetProperty (int mod){};
|
||||
// template <typename Handler> void serialize(Handler &h, const int version)
|
||||
// {
|
||||
// h & static_cast<IModableArt&>(*this);
|
||||
// h & mode;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// class DLL_LINKAGE CCommanderArt : public IModableArt // Growing with time
|
||||
// {
|
||||
// public:
|
||||
// ui32 level;
|
||||
// CCommanderArt(){level = 0;};
|
||||
// void Init(){};
|
||||
// void SetProperty (int mod){level = mod;};
|
||||
// void Upgrade(){level++;};
|
||||
// template <typename Handler> void serialize(Handler &h, const int version)
|
||||
// {
|
||||
// h & static_cast<IModableArt&>(*this);
|
||||
// h & level;
|
||||
// }
|
||||
// };
|
||||
|
||||
class DLL_LINKAGE CArtHandler //handles artifacts
|
||||
{
|
||||
void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype = -1, int valType = Bonus::BASE_NUMBER, ILimiter * limiter = NULL, int additionalinfo = 0);
|
||||
|
Loading…
Reference in New Issue
Block a user