1
0
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:
DjWarmonger 2012-06-16 14:25:39 +00:00
parent 8c6965c5ee
commit 4d62525ff7
3 changed files with 119 additions and 164 deletions

View File

@ -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)

View File

@ -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));

View File

@ -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);