1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

* corrected per-stack spell immunity handling

* support for new artifacts: * of Legion, shackles of war
This commit is contained in:
mateuszb 2009-08-16 13:44:17 +00:00
parent 2b44cd35b6
commit 4fc25c7b98
9 changed files with 66 additions and 13 deletions

View File

@ -577,6 +577,11 @@ bool CCallback::battleCanCastSpell()
return gs->curB->castSpells[1] == 0 && gs->getHero(gs->curB->hero2)->getArt(17);
}
bool CCallback:: battleCanFlee()
{
return gs->battleCanFlee(player);
}
void CCallback::swapGarrisonHero( const CGTownInstance *town )
{
if(town->tempOwner != player) return;

View File

@ -172,6 +172,7 @@ public:
virtual bool battleIsStackMine(int ID)=0; //returns true if stack with id ID belongs to caller
virtual bool battleCanShoot(int ID, int dest)=0; //returns true if unit with id ID can shoot to dest
virtual bool battleCanCastSpell()=0; //returns true, if caller can cast a spell
virtual bool battleCanFlee()=0; //returns true if caller can flee from the battle
};
struct HeroMoveDetails
@ -270,6 +271,7 @@ public:
bool battleIsStackMine(int ID); //returns true if stack with id ID belongs to caller
bool battleCanShoot(int ID, int dest); //returns true if unit with id ID can shoot to dest
bool battleCanCastSpell(); //returns true, if caller can cast a spell
bool battleCanFlee(); //returns true if caller can flee from the battle
//XXX hmmm _tmain on _GNUC_ wtf?
//friends

View File

@ -985,8 +985,29 @@ void CBattleInterface::bSurrenderf()
void CBattleInterface::bFleef()
{
CFunctionList<void()> ony = boost::bind(&CBattleInterface::reallyFlee,this);
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[28],std::vector<SComponent*>(), ony, 0, false);
if( LOCPLINT->cb->battleCanFlee() )
{
CFunctionList<void()> ony = boost::bind(&CBattleInterface::reallyFlee,this);
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[28],std::vector<SComponent*>(), ony, 0, false);
}
else
{
std::vector<SComponent*> comps;
std::string heroName;
//calculating fleeing hero's name
if(attackingHeroInstance)
if(attackingHeroInstance->tempOwner == LOCPLINT->cb->getMyColor())
heroName = attackingHeroInstance->name;
if(defendingHeroInstance)
if(defendingHeroInstance->tempOwner == LOCPLINT->cb->getMyColor())
heroName = defendingHeroInstance->name;
//calculating text
char buffer[1000];
sprintf(buffer, CGI->generaltexth->allTexts[340].c_str(), heroName.c_str());
//printing message
LOCPLINT->showInfoDialog(std::string(buffer), comps);
}
}
void CBattleInterface::reallyFlee()

View File

@ -314,11 +314,11 @@ void CArtHandler::addBonuses()
giveArtBonus(116,HeroBonus::GENERATE_RESOURCE,+750,6); //Endless Bag of Gold
giveArtBonus(117,HeroBonus::GENERATE_RESOURCE,+500,6); //Endless Purse of Gold
giveArtBonus(118,HeroBonus::CREATURE_GROWTH,+5,2); //Legs of Legion
giveArtBonus(119,HeroBonus::CREATURE_GROWTH,+4,3); //Loins of Legion
giveArtBonus(120,HeroBonus::CREATURE_GROWTH,+3,4); //Torso of Legion
giveArtBonus(121,HeroBonus::CREATURE_GROWTH,+2,5); //Arms of Legion
giveArtBonus(122,HeroBonus::CREATURE_GROWTH,+1,6); //Head of Legion
giveArtBonus(118,HeroBonus::CREATURE_GROWTH,+5,1); //Legs of Legion
giveArtBonus(119,HeroBonus::CREATURE_GROWTH,+4,2); //Loins of Legion
giveArtBonus(120,HeroBonus::CREATURE_GROWTH,+3,3); //Torso of Legion
giveArtBonus(121,HeroBonus::CREATURE_GROWTH,+2,4); //Arms of Legion
giveArtBonus(122,HeroBonus::CREATURE_GROWTH,+1,5); //Head of Legion
//Sea Captain's Hat
giveArtBonus(123,HeroBonus::WHIRLPOOL_PROTECTION,0);

View File

@ -28,7 +28,7 @@ public:
ui32 price;
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed
EartClass aClass;
int id;
ui32 id;
std::list<HeroBonus> bonuses; //bonuses given by artifact
template <typename Handler> void serialize(Handler &h, const int version)

View File

@ -1173,7 +1173,7 @@ void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const
int CGTownInstance::getSightRadious() const //returns sight distance
{
if (subID == 2 && (builtBuildings.find(21))!=builtBuildings.end())
if (subID == 2 && (builtBuildings.find(21))!=builtBuildings.end()) //town has lookout tower
return 20;
return 5;
}
@ -1241,6 +1241,13 @@ int CGTownInstance::creatureGrowth(const int & level) const
if(getHordeLevel(1)==level)
if((builtBuildings.find(24)!=builtBuildings.end()) || (builtBuildings.find(25)!=builtBuildings.end()))
ret+=VLC->creh->creatures[town->basicCreatures[level]].hordeGrowth;
//support for legs of legion etc.
if(garrisonHero)
ret += garrisonHero->valOfBonuses(HeroBonus::CREATURE_GROWTH, level);
if(visitingHero)
ret += visitingHero->valOfBonuses(HeroBonus::CREATURE_GROWTH, level);
return ret;
}
int CGTownInstance::dailyIncome() const

View File

@ -1373,6 +1373,21 @@ bool CGameState::battleShootCreatureStack(int ID, int dest)
return true;
}
bool CGameState::battleCanFlee(int player)
{
if(!curB) //there is no battle
return false;
const CGHeroInstance *h1 = getHero(curB->hero1);
const CGHeroInstance *h2 = getHero(curB->hero2);
if(h1->hasBonusOfType(HeroBonus::ENEMY_CANT_ESCAPE) //eg. one of heroes is wearing shakles of war
|| h2->hasBonusOfType(HeroBonus::ENEMY_CANT_ESCAPE))
return false;
return true;
}
int CGameState::battleGetStack(int pos, bool onlyAlive)
{
if(!curB)

View File

@ -275,6 +275,7 @@ public:
bool battleMoveCreatureStack(int ID, int dest);
bool battleAttackCreatureStack(int ID, int dest);
bool battleShootCreatureStack(int ID, int dest);
bool battleCanFlee(int player); //returns true if player can flee from the battle
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
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

View File

@ -2287,8 +2287,8 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
}
case 4: //retreat/flee
{
//TODO: check if fleeing is possible (e.g. enemy may have Shackles of War)
//TODO: calculate casualties
if( !gs->battleCanFlee(ba.side ? gs->curB->side2 : gs->curB->side1) )
break;
//TODO: remove retreating hero from map and place it in recruitment list
BattleResult *br = new BattleResult;
br->result = 1;
@ -2681,7 +2681,8 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
if(prob > 100) prob = 100;
if(rand()%100 < prob)
if( (*it)->hasFeatureOfType(StackFeature::SPELL_IMMUNITY, sp->id) //100% sure spell immunity
|| rand()%100 < prob) //immunity from resistance
ret.push_back((*it)->ID);
}
@ -2690,7 +2691,8 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
{
for(std::set<CStack*>::const_iterator it = affectedCreatures.begin(); it != affectedCreatures.end(); ++it)
{
if( (*it)->amount * (*it)->MaxHealth() + (*it)->firstHPleft
if( (*it)->hasFeatureOfType(StackFeature::SPELL_IMMUNITY, sp->id) //100% sure spell immunity
|| (*it)->amount * (*it)->MaxHealth() + (*it)->firstHPleft
>
caster->getPrimSkillLevel(2) * 25 + sp->powers[caster->getSpellSchoolLevel(sp)]
)