mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
* partial support for arrow turrets
This commit is contained in:
parent
5bfbcfb000
commit
a4df8e8831
@ -71,6 +71,10 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
|
|||||||
typedef std::map<int, CStack> map_stacks;
|
typedef std::map<int, CStack> map_stacks;
|
||||||
map_stacks allStacks = m_cb->battleGetStacks();
|
map_stacks allStacks = m_cb->battleGetStacks();
|
||||||
const CStack *currentStack = m_cb->battleGetStackByID(currentCreatureId);
|
const CStack *currentStack = m_cb->battleGetStackByID(currentCreatureId);
|
||||||
|
if(currentStack->position < 0) //turret
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
// find all creatures belong to the enemy
|
// find all creatures belong to the enemy
|
||||||
std::for_each(allStacks.begin(), allStacks.end(),
|
std::for_each(allStacks.begin(), allStacks.end(),
|
||||||
@ -249,6 +253,11 @@ void CBattleLogic::MakeStatistics(int currentCreatureId)
|
|||||||
|
|
||||||
BattleAction CBattleLogic::MakeDecision(int stackID)
|
BattleAction CBattleLogic::MakeDecision(int stackID)
|
||||||
{
|
{
|
||||||
|
const CStack *currentStack = m_cb->battleGetStackByID(stackID);
|
||||||
|
if(currentStack->position < 0) //turret
|
||||||
|
{
|
||||||
|
return MakeDefend(stackID);
|
||||||
|
}
|
||||||
MakeStatistics(stackID);
|
MakeStatistics(stackID);
|
||||||
|
|
||||||
list<int> creatures;
|
list<int> creatures;
|
||||||
|
@ -556,33 +556,14 @@ bool CCallback::battleIsStackMine(int ID)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCallback::battleCanShoot(int ID, int dest)
|
bool CCallback::battleCanShoot(int ID, int dest)
|
||||||
{
|
{
|
||||||
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||||
const CStack *our = battleGetStackByID(ID), *dst = battleGetStackByPos(dest);
|
|
||||||
|
|
||||||
if(!our || !dst || !gs->curB) return false;
|
if(!gs->curB) return false;
|
||||||
|
|
||||||
int ourHero = our->attackerOwned ? gs->curB->hero1 : gs->curB->hero2;
|
return gs->battleCanShoot(ID, dest);
|
||||||
|
|
||||||
//for(size_t g=0; g<our->effects.size(); ++g)
|
|
||||||
//{
|
|
||||||
// if(61 == our->effects[g].id) //forgetfulness
|
|
||||||
// return false;
|
|
||||||
//}
|
|
||||||
if(our->hasFeatureOfType(StackFeature::FORGETFULL)) //forgetfulness
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
if(our->hasFeatureOfType(StackFeature::SHOOTER)//it's shooter
|
|
||||||
&& our->owner != dst->owner
|
|
||||||
&& dst->alive()
|
|
||||||
&& (!gs->curB->isStackBlocked(ID) ||
|
|
||||||
( gs->getHero(ourHero) && gs->getHero(ourHero)->hasBonusOfType(HeroBonus::FREE_SHOOTING) ) )
|
|
||||||
&& our->shots
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCallback::battleCanCastSpell()
|
bool CCallback::battleCanCastSpell()
|
||||||
|
@ -81,6 +81,14 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
|
|||||||
pos = myRect;
|
pos = myRect;
|
||||||
strongInterest = true;
|
strongInterest = true;
|
||||||
givenCommand = new CondSh<BattleAction *>(NULL);
|
givenCommand = new CondSh<BattleAction *>(NULL);
|
||||||
|
|
||||||
|
//preparing siege info
|
||||||
|
const CGTownInstance * town = LOCPLINT->cb->battleGetDefendedTown();
|
||||||
|
if(town)
|
||||||
|
{
|
||||||
|
siegeH = new SiegeHelper(town, this);
|
||||||
|
}
|
||||||
|
|
||||||
//initializing armies
|
//initializing armies
|
||||||
this->army1 = army1;
|
this->army1 = army1;
|
||||||
this->army2 = army2;
|
this->army2 = army2;
|
||||||
@ -90,14 +98,6 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
|
|||||||
newStack(b->second.ID);
|
newStack(b->second.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//preparing siege info
|
|
||||||
const CGTownInstance * town = LOCPLINT->cb->battleGetDefendedTown();
|
|
||||||
if(town)
|
|
||||||
{
|
|
||||||
siegeH = new SiegeHelper(town, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//preparing menu background and terrain
|
//preparing menu background and terrain
|
||||||
if(siegeH)
|
if(siegeH)
|
||||||
{
|
{
|
||||||
@ -204,7 +204,8 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
|
|||||||
//locking occupied positions on batlefield
|
//locking occupied positions on batlefield
|
||||||
for(std::map<int, CStack>::iterator it = stacks.begin(); it!=stacks.end(); ++it) //stacks gained at top of this function
|
for(std::map<int, CStack>::iterator it = stacks.begin(); it!=stacks.end(); ++it) //stacks gained at top of this function
|
||||||
{
|
{
|
||||||
bfield[it->second.position].accesible = false;
|
if(it->second.position >= 0) //turrets have position < 0
|
||||||
|
bfield[it->second.position].accesible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//loading projectiles for units
|
//loading projectiles for units
|
||||||
@ -460,10 +461,6 @@ void CBattleInterface::show(SDL_Surface * to)
|
|||||||
|
|
||||||
SDL_SetClipRect(to, &buf); //restoring previous clip_rect
|
SDL_SetClipRect(to, &buf); //restoring previous clip_rect
|
||||||
|
|
||||||
//showing menu background and console
|
|
||||||
blitAt(menu, pos.x, 556 + pos.y, to);
|
|
||||||
console->show(to);
|
|
||||||
|
|
||||||
//showing buttons
|
//showing buttons
|
||||||
bOptions->show(to);
|
bOptions->show(to);
|
||||||
bSurrender->show(to);
|
bSurrender->show(to);
|
||||||
@ -501,7 +498,7 @@ void CBattleInterface::show(SDL_Surface * to)
|
|||||||
//double loop because dead stacks should be printed first
|
//double loop because dead stacks should be printed first
|
||||||
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
|
for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
|
||||||
{
|
{
|
||||||
if(j->second.alive())
|
if(j->second.alive() && j->second.position >= 0) //don't show turrets here
|
||||||
stackAliveByHex[j->second.position].push_back(j->second.ID);
|
stackAliveByHex[j->second.position].push_back(j->second.ID);
|
||||||
}
|
}
|
||||||
std::vector<int> stackDeadByHex[BFIELD_SIZE];
|
std::vector<int> stackDeadByHex[BFIELD_SIZE];
|
||||||
@ -529,7 +526,7 @@ void CBattleInterface::show(SDL_Surface * to)
|
|||||||
showAliveStack(stackAliveByHex[b][v], stacks, to);
|
showAliveStack(stackAliveByHex[b][v], stacks, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
showPieceOfWall(to, b);
|
showPieceOfWall(to, b, stacks);
|
||||||
}
|
}
|
||||||
//units shown
|
//units shown
|
||||||
projectileShowHelper(to);//showing projectiles
|
projectileShowHelper(to);//showing projectiles
|
||||||
@ -608,13 +605,17 @@ void CBattleInterface::show(SDL_Surface * to)
|
|||||||
|
|
||||||
SDL_SetClipRect(to, &buf); //restoring previous clip_rect
|
SDL_SetClipRect(to, &buf); //restoring previous clip_rect
|
||||||
|
|
||||||
|
//showing menu background and console
|
||||||
|
blitAt(menu, pos.x, 556 + pos.y, to);
|
||||||
|
console->show(to);
|
||||||
|
|
||||||
//showing window with result of battle
|
//showing window with result of battle
|
||||||
if(resWindow)
|
if(resWindow)
|
||||||
{
|
{
|
||||||
resWindow->show(to);
|
resWindow->show(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
//showing in-gmae console
|
//showing in-game console
|
||||||
LOCPLINT->cingconsole->show(to);
|
LOCPLINT->cingconsole->show(to);
|
||||||
|
|
||||||
//printing border around interface
|
//printing border around interface
|
||||||
@ -1110,11 +1111,34 @@ void CBattleInterface::newStack(int stackID)
|
|||||||
{
|
{
|
||||||
const CStack * newStack = LOCPLINT->cb->battleGetStackByID(stackID);
|
const CStack * newStack = LOCPLINT->cb->battleGetStackByID(stackID);
|
||||||
|
|
||||||
std::pair <int, int> coords = CBattleHex::getXYUnitAnim(newStack->position, newStack->owner == attackingHeroInstance->tempOwner, newStack);
|
std::pair <int, int> coords;
|
||||||
creAnims[stackID] = (new CCreatureAnimation(newStack->creature->animDefName));
|
|
||||||
|
if(newStack->position < 0) //turret
|
||||||
|
{
|
||||||
|
static const int townToTurretAnim[] = {2, 18, 34, 44, 64, 76, 88, 100, 127};
|
||||||
|
|
||||||
|
switch(newStack->position)
|
||||||
|
{
|
||||||
|
case -2: //keep
|
||||||
|
coords = std::make_pair(505, -66);
|
||||||
|
break;
|
||||||
|
case -3: //lower turret
|
||||||
|
coords = std::make_pair(368, 304);
|
||||||
|
break;
|
||||||
|
case -4: //upper turret
|
||||||
|
coords = std::make_pair(339, -192);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
creAnims[stackID] = new CCreatureAnimation(CGI->creh->creatures[ townToTurretAnim[siegeH->town->town->typeID] ].animDefName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
coords = CBattleHex::getXYUnitAnim(newStack->position, newStack->owner == attackingHeroInstance->tempOwner, newStack);
|
||||||
|
creAnims[stackID] = new CCreatureAnimation(newStack->creature->animDefName);
|
||||||
|
}
|
||||||
creAnims[stackID]->setType(2);
|
creAnims[stackID]->setType(2);
|
||||||
creAnims[stackID]->pos = genRect(creAnims[newStack->ID]->fullHeight, creAnims[newStack->ID]->fullWidth, coords.first, coords.second);
|
creAnims[stackID]->pos = genRect(creAnims[newStack->ID]->fullHeight, creAnims[newStack->ID]->fullWidth, coords.first, coords.second);
|
||||||
creDir[stackID] = newStack->owner == attackingHeroInstance->tempOwner;
|
creDir[stackID] = newStack->attackerOwned;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::stackRemoved(int stackID)
|
void CBattleInterface::stackRemoved(int stackID)
|
||||||
@ -2473,24 +2497,67 @@ void CBattleInterface::showAliveStack(int ID, const std::map<int, CStack> & stac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::showPieceOfWall(SDL_Surface * to, int hex)
|
void CBattleInterface::showPieceOfWall(SDL_Surface * to, int hex, const std::map<int, CStack> & stacks)
|
||||||
{
|
{
|
||||||
if(!siegeH)
|
if(!siegeH)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static const std::map<int, int> hexToPart = boost::assign::map_list_of(12, 8)(16, 1)(29, 7)(50, 2)(62, 12)(78, 6)(112, 10)(147, 5)(165, 11)(182, 4);
|
static const std::map<int, int> hexToPart = boost::assign::map_list_of(12, 8)(16, 1)(29, 7)(50, 2)(62, 12)(78, 6)(112, 10)(147, 5)(165, 11)(182, 3)(186, 0);
|
||||||
|
|
||||||
|
//additionally print bottom wall
|
||||||
|
if(hex == 182)
|
||||||
|
{
|
||||||
|
siegeH->printPartOfWall(to, 4);
|
||||||
|
}
|
||||||
|
|
||||||
std::map<int, int>::const_iterator it = hexToPart.find(hex);
|
std::map<int, int>::const_iterator it = hexToPart.find(hex);
|
||||||
if(it != hexToPart.end())
|
if(it != hexToPart.end())
|
||||||
{
|
{
|
||||||
siegeH->printPartOfWall(to, it->second);
|
siegeH->printPartOfWall(to, it->second);
|
||||||
|
|
||||||
|
//print creature in turret
|
||||||
|
int posToSeek = -1;
|
||||||
|
switch(it->second)
|
||||||
|
{
|
||||||
|
case 3: //bottom turret
|
||||||
|
posToSeek = -3;
|
||||||
|
break;
|
||||||
|
case 8: //upper turret
|
||||||
|
posToSeek = -4;
|
||||||
|
break;
|
||||||
|
case 2: //keep
|
||||||
|
posToSeek = -2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(posToSeek != -1)
|
||||||
|
{
|
||||||
|
int ID = -1;
|
||||||
|
for(std::map<int, CStack>::const_iterator it = stacks.begin(); it != stacks.end(); ++it)
|
||||||
|
{
|
||||||
|
if(it->second.position == posToSeek)
|
||||||
|
{
|
||||||
|
ID = it->second.ID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showAliveStack(ID, stacks, to);
|
||||||
|
//blitting creature cover
|
||||||
|
switch(posToSeek)
|
||||||
|
{
|
||||||
|
case -3: //bottom turret
|
||||||
|
siegeH->printPartOfWall(to, 16);
|
||||||
|
break;
|
||||||
|
case -4: //upper turret
|
||||||
|
siegeH->printPartOfWall(to, 17);
|
||||||
|
break;
|
||||||
|
case -2: //keep
|
||||||
|
siegeH->printPartOfWall(to, 15);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//additionally print lower tower
|
|
||||||
if(hex == 182)
|
|
||||||
{
|
|
||||||
siegeH->printPartOfWall(to, 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::redrawBackgroundWithHexes(int activeStack)
|
void CBattleInterface::redrawBackgroundWithHexes(int activeStack)
|
||||||
@ -3321,6 +3388,12 @@ std::string CBattleInterface::SiegeHelper::getSiegeName(ui16 what, ui16 additInf
|
|||||||
return "SG" + townTypeInfixes[town->town->typeID] + "MOAT.BMP";
|
return "SG" + townTypeInfixes[town->town->typeID] + "MOAT.BMP";
|
||||||
case 14: //mlip
|
case 14: //mlip
|
||||||
return "SG" + townTypeInfixes[town->town->typeID] + "MLIP.BMP";
|
return "SG" + townTypeInfixes[town->town->typeID] + "MLIP.BMP";
|
||||||
|
case 15: //keep creature cover
|
||||||
|
return "SG" + townTypeInfixes[town->town->typeID] + "MANC.BMP";
|
||||||
|
case 16: //bottom turret creature cover
|
||||||
|
return "SG" + townTypeInfixes[town->town->typeID] + "TW1C.BMP";
|
||||||
|
case 17: //upper turret creature cover
|
||||||
|
return "SG" + townTypeInfixes[town->town->typeID] + "TW2C.BMP";
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -3350,6 +3423,17 @@ void CBattleInterface::SiegeHelper::printPartOfWall(SDL_Surface * to, int what)
|
|||||||
pos.x = CGI->heroh->wallPositions[town->town->typeID][what - 3].first + owner->pos.x;
|
pos.x = CGI->heroh->wallPositions[town->town->typeID][what - 3].first + owner->pos.x;
|
||||||
pos.y = CGI->heroh->wallPositions[town->town->typeID][what - 3].second + owner->pos.y;
|
pos.y = CGI->heroh->wallPositions[town->town->typeID][what - 3].second + owner->pos.y;
|
||||||
break;
|
break;
|
||||||
|
case 15: //keep creature cover
|
||||||
|
pos = Point(owner->pos.w + owner->pos.x - walls[2]->w, 154 + owner->pos.y);
|
||||||
|
break;
|
||||||
|
case 16: //bottom turret creature cover
|
||||||
|
pos.x = CGI->heroh->wallPositions[town->town->typeID][0].first + owner->pos.x;
|
||||||
|
pos.y = CGI->heroh->wallPositions[town->town->typeID][0].second + owner->pos.y;
|
||||||
|
break;
|
||||||
|
case 17: //upper turret creature cover
|
||||||
|
pos.x = CGI->heroh->wallPositions[town->town->typeID][5].first + owner->pos.x;
|
||||||
|
pos.y = CGI->heroh->wallPositions[town->town->typeID][5].second + owner->pos.y;
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if(pos.x != -1)
|
if(pos.x != -1)
|
||||||
|
@ -198,7 +198,7 @@ private:
|
|||||||
} * attackingInfo;
|
} * attackingInfo;
|
||||||
void attackingShowHelper();
|
void attackingShowHelper();
|
||||||
void showAliveStack(int ID, const std::map<int, CStack> & stacks, SDL_Surface * to); //helper function for function show
|
void showAliveStack(int ID, const std::map<int, CStack> & stacks, SDL_Surface * to); //helper function for function show
|
||||||
void showPieceOfWall(SDL_Surface * to, int hex); //helper function for show
|
void showPieceOfWall(SDL_Surface * to, int hex, const std::map<int, CStack> & stacks); //helper function for show
|
||||||
void redrawBackgroundWithHexes(int activeStack);
|
void redrawBackgroundWithHexes(int activeStack);
|
||||||
void printConsoleAttacked(int ID, int dmg, int killed, int IDby);
|
void printConsoleAttacked(int ID, int dmg, int killed, int IDby);
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ private:
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static std::string townTypeInfixes[F_NUMBER]; //for internal use only - to build filenames
|
static std::string townTypeInfixes[F_NUMBER]; //for internal use only - to build filenames
|
||||||
SDL_Surface * walls[13];
|
SDL_Surface * walls[18];
|
||||||
const CBattleInterface * owner;
|
const CBattleInterface * owner;
|
||||||
public:
|
public:
|
||||||
const CGTownInstance * town; //besieged town
|
const CGTownInstance * town; //besieged town
|
||||||
@ -242,9 +242,9 @@ private:
|
|||||||
~SiegeHelper(); //d-tor
|
~SiegeHelper(); //d-tor
|
||||||
|
|
||||||
//filename getters
|
//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, 13 - moat, 14 - mlip; 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, 15 - keep creature cover, 16 - bottom turret creature cover, 17 - upper turret creature cover; 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
|
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, 15 - keep creature cover, 16 - bottom turret creature cover, 17 - upper turret creature cover
|
||||||
|
|
||||||
friend class CPlayerInterface;
|
friend class CPlayerInterface;
|
||||||
} * siegeH;
|
} * siegeH;
|
||||||
|
@ -307,7 +307,7 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool atta
|
|||||||
|
|
||||||
for(unsigned int g=0; g<stacks.size(); ++g)
|
for(unsigned int g=0; g<stacks.size(); ++g)
|
||||||
{
|
{
|
||||||
if(!stacks[g]->alive() || stacks[g]->ID==stackToOmmit) //we don't want to lock position of this stack
|
if(!stacks[g]->alive() || stacks[g]->ID==stackToOmmit || stacks[g]->position < 0) //we don't want to lock position of this stack (eg. if it's a turret)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
accessibility[stacks[g]->position] = false;
|
accessibility[stacks[g]->position] = false;
|
||||||
@ -433,6 +433,10 @@ std::vector<int> BattleInfo::getAccessibility(int stackID, bool addOccupiable) c
|
|||||||
std::vector<int> ret;
|
std::vector<int> ret;
|
||||||
bool ac[BFIELD_SIZE];
|
bool ac[BFIELD_SIZE];
|
||||||
const CStack *s = getStack(stackID);
|
const CStack *s = getStack(stackID);
|
||||||
|
|
||||||
|
if(s->position < 0) //turrets
|
||||||
|
return std::vector<int>();
|
||||||
|
|
||||||
std::set<int> occupyable;
|
std::set<int> occupyable;
|
||||||
|
|
||||||
getAccessibilityMap(ac, s->hasFeatureOfType(StackFeature::DOUBLE_WIDE), s->attackerOwned, addOccupiable, occupyable, s->hasFeatureOfType(StackFeature::FLYING), stackID);
|
getAccessibilityMap(ac, s->hasFeatureOfType(StackFeature::DOUBLE_WIDE), s->attackerOwned, addOccupiable, occupyable, s->hasFeatureOfType(StackFeature::FLYING), stackID);
|
||||||
@ -713,7 +717,7 @@ si32 CStack::Attack() const
|
|||||||
|
|
||||||
if(hasFeatureOfType(StackFeature::IN_FRENZY)) //frenzy for attacker
|
if(hasFeatureOfType(StackFeature::IN_FRENZY)) //frenzy for attacker
|
||||||
{
|
{
|
||||||
ret += (VLC->spellh->spells[56].powers[getEffect(56)->level]/100.0) * Defense(false);
|
ret += si32(VLC->spellh->spells[56].powers[getEffect(56)->level]/100.0) * Defense(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret += valOfFeatures(StackFeature::ATTACK_BONUS);
|
ret += valOfFeatures(StackFeature::ATTACK_BONUS);
|
||||||
@ -2110,10 +2114,25 @@ bool CGameState::checkForVisitableDir( const int3 & src, const TerrainTile *pom,
|
|||||||
}
|
}
|
||||||
std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge)
|
std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge)
|
||||||
{
|
{
|
||||||
int attackDefenseBonus,
|
float attackDefenseBonus,
|
||||||
minDmg = attacker->creature->damageMin * attacker->amount,
|
minDmg = attacker->creature->damageMin * attacker->amount,
|
||||||
maxDmg = attacker->creature->damageMax * attacker->amount;
|
maxDmg = attacker->creature->damageMax * attacker->amount;
|
||||||
|
|
||||||
|
if(attacker->creature->idNumber == 149) //arrow turret
|
||||||
|
{
|
||||||
|
switch(attacker->position)
|
||||||
|
{
|
||||||
|
case -2: //keep
|
||||||
|
minDmg = 15;
|
||||||
|
maxDmg = 15;
|
||||||
|
break;
|
||||||
|
case -3: case -4: //turrets
|
||||||
|
minDmg = 7.5f;
|
||||||
|
maxDmg = 7.5f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(attacker->hasFeatureOfType(StackFeature::SIEGE_WEAPON)) //any siege weapon, but only ballista can attack
|
if(attacker->hasFeatureOfType(StackFeature::SIEGE_WEAPON)) //any siege weapon, but only ballista can attack
|
||||||
{ //minDmg and maxDmg are multiplied by hero attack + 1
|
{ //minDmg and maxDmg are multiplied by hero attack + 1
|
||||||
minDmg *= attackerHero->getPrimSkillLevel(0) + 1;
|
minDmg *= attackerHero->getPrimSkillLevel(0) + 1;
|
||||||
@ -2305,16 +2324,16 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, cons
|
|||||||
if(attacker->getEffect(42)) //curse handling (rest)
|
if(attacker->getEffect(42)) //curse handling (rest)
|
||||||
{
|
{
|
||||||
minDmg -= VLC->spellh->spells[42].powers[attacker->getEffect(42)->level];
|
minDmg -= VLC->spellh->spells[42].powers[attacker->getEffect(42)->level];
|
||||||
return std::make_pair(minDmg, minDmg);
|
return std::make_pair(int(minDmg), int(minDmg));
|
||||||
}
|
}
|
||||||
else if(attacker->getEffect(41)) //bless handling
|
else if(attacker->getEffect(41)) //bless handling
|
||||||
{
|
{
|
||||||
maxDmg += VLC->spellh->spells[41].powers[attacker->getEffect(41)->level];
|
maxDmg += VLC->spellh->spells[41].powers[attacker->getEffect(41)->level];
|
||||||
return std::make_pair(maxDmg, maxDmg);
|
return std::make_pair(int(maxDmg), int(maxDmg));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return std::make_pair(minDmg, maxDmg);
|
return std::make_pair(int(minDmg), int(maxDmg));
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog1 << "We are too far in calculateDmg...\n";
|
tlog1 << "We are too far in calculateDmg...\n";
|
||||||
@ -2570,6 +2589,32 @@ std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closes
|
|||||||
return std::make_pair<const CStack * , int>(NULL, -1);
|
return std::make_pair<const CStack * , int>(NULL, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGameState::battleCanShoot(int ID, int dest)
|
||||||
|
{
|
||||||
|
if(!curB)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const CStack *our = curB->getStack(ID),
|
||||||
|
*dst = curB->getStackT(dest);
|
||||||
|
|
||||||
|
if(!our || !dst) return false;
|
||||||
|
|
||||||
|
int ourHero = our->attackerOwned ? curB->hero1 : curB->hero2;
|
||||||
|
|
||||||
|
if(our->hasFeatureOfType(StackFeature::FORGETFULL)) //forgetfulness
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(our->hasFeatureOfType(StackFeature::SHOOTER)//it's shooter
|
||||||
|
&& our->owner != dst->owner
|
||||||
|
&& dst->alive()
|
||||||
|
&& (!curB->isStackBlocked(ID) ||
|
||||||
|
( getHero(ourHero) && getHero(ourHero)->hasBonusOfType(HeroBonus::FREE_SHOOTING) ) )
|
||||||
|
&& our->shots
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CStack * BattleInfo::getNextStack()
|
CStack * BattleInfo::getNextStack()
|
||||||
{
|
{
|
||||||
CStack *current = getStack(activeStack);
|
CStack *current = getStack(activeStack);
|
||||||
|
@ -170,7 +170,7 @@ public:
|
|||||||
ui32 firstHPleft; //HP of first creature in stack
|
ui32 firstHPleft; //HP of first creature in stack
|
||||||
ui8 owner, slot; //owner - player colour (255 for neutrals), slot - position in garrison (may be 255 for neutrals/called creatures)
|
ui8 owner, slot; //owner - player colour (255 for neutrals), slot - position in garrison (may be 255 for neutrals/called creatures)
|
||||||
ui8 attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
|
ui8 attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
|
||||||
ui16 position; //position on battlefield
|
si16 position; //position on battlefield; -2 - keep, -3 - lower tower, -4 - upper tower
|
||||||
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
||||||
si16 shots; //how many shots left
|
si16 shots; //how many shots left
|
||||||
si8 morale, luck; //base stack luck/morale
|
si8 morale, luck; //base stack luck/morale
|
||||||
@ -331,6 +331,7 @@ public:
|
|||||||
int battleGetStack(int pos, bool onlyAlive); //returns ID of stack at given tile
|
int battleGetStack(int pos, bool onlyAlive); //returns ID of stack at given tile
|
||||||
int battleGetBattlefieldType(int3 tile = int3());// 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
int battleGetBattlefieldType(int3 tile = int3());// 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
||||||
si8 battleMaxSpellLevel(); //calculates maximum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, SPELL_LEVELS is returned
|
si8 battleMaxSpellLevel(); //calculates maximum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, SPELL_LEVELS is returned
|
||||||
|
bool battleCanShoot(int ID, int dest); //determines if stack with given ID shoot at the selected destination
|
||||||
UpgradeInfo getUpgradeInfo(CArmedInstance *obj, int stackPos);
|
UpgradeInfo getUpgradeInfo(CArmedInstance *obj, int stackPos);
|
||||||
float getMarketEfficiency(int player, int mode=0);
|
float getMarketEfficiency(int player, int mode=0);
|
||||||
int canBuildStructure(const CGTownInstance *t, int ID);// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
int canBuildStructure(const CGTownInstance *t, int ID);// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
||||||
|
@ -1047,6 +1047,24 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
|
|||||||
stacks.push_back(stack);
|
stacks.push_back(stack);
|
||||||
}
|
}
|
||||||
//war machines added
|
//war machines added
|
||||||
|
|
||||||
|
switch(curB->siege) //adding towers
|
||||||
|
{
|
||||||
|
|
||||||
|
case 3: //castle
|
||||||
|
{//lower tower / upper tower
|
||||||
|
CStack * stack = curB->generateNewStack(hero2, 149, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, -4);
|
||||||
|
stacks.push_back(stack);
|
||||||
|
stack = curB->generateNewStack(hero2, 149, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, -3);
|
||||||
|
stacks.push_back(stack);
|
||||||
|
}
|
||||||
|
case 2: //citadel
|
||||||
|
{//main tower
|
||||||
|
CStack * stack = curB->generateNewStack(hero2, 149, 1, stacks.size(), false, 255, gs->map->terrain[tile.x][tile.y][tile.z].tertype, -2);
|
||||||
|
stacks.push_back(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::stable_sort(stacks.begin(),stacks.end(),cmpst);
|
std::stable_sort(stacks.begin(),stacks.end(),cmpst);
|
||||||
|
|
||||||
//seting up siege
|
//seting up siege
|
||||||
@ -2468,19 +2486,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
{
|
{
|
||||||
CStack *curStack = gs->curB->getStack(ba.stackNumber),
|
CStack *curStack = gs->curB->getStack(ba.stackNumber),
|
||||||
*destStack= gs->curB->getStackT(ba.destinationTile);
|
*destStack= gs->curB->getStackT(ba.destinationTile);
|
||||||
if(!curStack //our stack exists
|
if( !gs->battleCanShoot(ba.stackNumber, ba.destinationTile) )
|
||||||
|| !destStack //there is a stack at destination tile
|
|
||||||
|| !curStack->shots //stack has shots
|
|
||||||
|| gs->curB->isStackBlocked(curStack->ID) //we are not blocked
|
|
||||||
|| !curStack->hasFeatureOfType(StackFeature::SHOOTER) //our stack is shooting unit
|
|
||||||
)
|
|
||||||
break;
|
|
||||||
//for(int g=0; g<curStack->effects.size(); ++g)
|
|
||||||
//{
|
|
||||||
// if(61 == curStack->effects[g].id) //forgetfulness
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
if(curStack->hasFeatureOfType(StackFeature::FORGETFULL)) //forgetfulness
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
sendAndApply(&StartAction(ba)); //start shooting
|
sendAndApply(&StartAction(ba)); //start shooting
|
||||||
|
Loading…
Reference in New Issue
Block a user