1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

* flaggable objects change their color on minimap when taken over

* corrected damage inflicted by spells and ballista
* minor changes
This commit is contained in:
mateuszb 2009-07-30 12:49:45 +00:00
parent fec75cdc04
commit 8e63c73cf8
16 changed files with 227 additions and 69 deletions

View File

@ -185,6 +185,11 @@ const CGHeroInstance * CCallback::getHeroInfo(int val, int mode) const //mode =
return NULL;
}
const CGObjectInstance * CCallback::getObjectInfo(int ID) const
{
return gs->map->objects[ID];
}
bool CCallback::getHeroInfo( const CGObjectInstance *hero, InfoAboutHero &dest ) const
{
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(hero);
@ -264,7 +269,7 @@ std::vector< std::vector< std::vector<unsigned char> > > & CCallback::getVisibil
bool CCallback::isVisible(int3 pos, int Player) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->players[Player].fogOfWarMap[pos.x][pos.y][pos.z];
return gs->isVisible(pos, Player);
}
std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur) const
@ -306,24 +311,14 @@ bool CCallback::isVisible(int3 pos) const
bool CCallback::isVisible( const CGObjectInstance *obj, int Player ) const
{
//object is visible when at least one blocked tile is visible
for(int fx=0; fx<8; ++fx)
{
for(int fy=0; fy<6; ++fy)
{
int3 pos = obj->pos + int3(fx-7,fy-5,0);
if(gs->map->isInTheMap(pos)
&& !((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1)
&& isVisible(pos,Player) )
return true;
}
}
return false;
return gs->isVisible(obj, Player);
}
int CCallback::getMyColor() const
{
return player;
}
int CCallback::getHeroSerial(const CGHeroInstance * hero) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
@ -334,6 +329,7 @@ int CCallback::getHeroSerial(const CGHeroInstance * hero) const
}
return -1;
}
const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);

View File

@ -205,6 +205,7 @@ public:
int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
std::vector< std::vector< std::vector<unsigned char> > > & getVisibilityMap() const; //returns visibility map (TODO: make it const)
const CGHeroInstance * getHeroInfo(int val, int mode=2) const; //mode = 0 -> val = serial; mode = 1 -> val = hero type id (subID); mode = 2 -> val = global object serial id (id)
const CGObjectInstance * getObjectInfo(int ID) const; //global object serial id (ID)
int getResourceAmount(int type) const;
std::vector<si32> getResourceAmount() const;
int howManyHeroes(bool includeGarrisoned = true) const;

View File

@ -39,6 +39,7 @@ struct SpellCast;
struct SetStackEffect;
struct HeroBonus;
struct PackageApplied;
struct SetObjectProperty;
class CLoadFile;
class CSaveFile;
template <typename Serializer> class CISer;
@ -59,6 +60,7 @@ struct StackState
int shotsLeft;
std::set<int> effects; //IDs of spells affecting stack
int morale, luck;
int dmgMultiplier; //for ballista dmg bonus handling
};
class CGameInterface
@ -97,6 +99,7 @@ public:
virtual void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
virtual void requestRealized(PackageApplied *pa){};
virtual void heroExchangeStarted(si32 hero1, si32 hero2){};
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
virtual void serialize(COSer<CSaveFile> &h, const int version){}; //saving
virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading

View File

@ -45,6 +45,7 @@ extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX; //fonts
using namespace boost::logic;
using namespace boost::assign;
using namespace CSDL_Ext;
CMinimap::CMinimap(bool draw)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
@ -157,6 +158,26 @@ void CMinimap::draw(SDL_Surface * to)
}
void CMinimap::redraw(int level)// (level==-1) => redraw all levels
{
initMap(level);
//FoW
initFoW(level);
//flaggable objects
initFlaggableObjs(level);
//showing tiles
showVisibleTiles();
}
void CMinimap::initMap(int level)
{
/*for(int g=0; g<map.size(); ++g)
{
SDL_FreeSurface(map[g]);
}
map.clear();*/
int3 mapSizes = LOCPLINT->cb->getMapSize();
for (size_t i=0; i<CGI->mh->sizes.z; i++)
{
@ -184,8 +205,17 @@ void CMinimap::redraw(int level)// (level==-1) => redraw all levels
map.push_back(pom);
}
}
//FoW
void CMinimap::initFoW(int level)
{
/*for(int g=0; g<FoW.size(); ++g)
{
SDL_FreeSurface(FoW[g]);
}
FoW.clear();*/
int3 mapSizes = LOCPLINT->cb->getMapSize();
int mw = map[0]->w, mh = map[0]->h;//,
//wo = mw/mapSizes.x, ho = mh/mapSizes.y; //TODO use me
for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
@ -206,8 +236,18 @@ void CMinimap::redraw(int level)// (level==-1) => redraw all levels
}
FoW.push_back(pt);
}
//FoW end
//flaggable objects
}
void CMinimap::initFlaggableObjs(int level)
{
/*for(int g=0; g<flObjs.size(); ++g)
{
SDL_FreeSurface(flObjs[g]);
}
flObjs.clear();*/
int3 mapSizes = LOCPLINT->cb->getMapSize();
int mw = map[0]->w, mh = map[0]->h;
for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
{
if(level>=0 && d!=level)
@ -222,30 +262,16 @@ void CMinimap::redraw(int level)// (level==-1) => redraw all levels
}
flObjs.push_back(pt);
}
//showing tiles
for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
{
if(level>=0 && d!=level)
continue;
for(int x=0; x<mapSizes.x; ++x)
{
for(int y=0; y<mapSizes.y; ++y)
{
if(LOCPLINT->cb->isVisible(int3(x, y, d)))
{
showTile(int3(x, y, d));
}
}
}
}
}
void CMinimap::updateRadar()
{}
void CMinimap::clickRight (tribool down)
{
LOCPLINT->adventureInt->handleRightClick(rcText,down,this);
}
void CMinimap::clickLeft (tribool down)
{
if (down && (!pressedL))
@ -268,6 +294,7 @@ void CMinimap::clickLeft (tribool down)
newCPos.z = LOCPLINT->adventureInt->position.z;
LOCPLINT->adventureInt->centerOn(newCPos);
}
void CMinimap::hover (bool on)
{
Hoverable::hover(on);
@ -276,6 +303,7 @@ void CMinimap::hover (bool on)
else if (LOCPLINT->adventureInt->statusbar.current==statusbarTxt)
LOCPLINT->adventureInt->statusbar.clear();
}
void CMinimap::mouseMoved (const SDL_MouseMotionEvent & sEvent)
{
if (pressedL)
@ -291,6 +319,7 @@ void CMinimap::activate()
if (pressedL)
MotionInterested::activate();
}
void CMinimap::deactivate()
{
if (pressedL)
@ -299,6 +328,7 @@ void CMinimap::deactivate()
ClickableR::deactivate();
Hoverable::deactivate();
}
void CMinimap::showTile(const int3 &pos)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
@ -371,6 +401,27 @@ void CMinimap::showTile(const int3 &pos)
}
//flaggable objects drawn
}
void CMinimap::showVisibleTiles(int level)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
{
if(level>=0 && d!=level)
continue;
for(int x=0; x<mapSizes.x; ++x)
{
for(int y=0; y<mapSizes.y; ++y)
{
if(LOCPLINT->cb->isVisible(int3(x, y, d)))
{
showTile(int3(x, y, d));
}
}
}
}
}
void CMinimap::hideTile(const int3 &pos)
{
}

View File

@ -40,6 +40,10 @@ public:
~CMinimap();
void draw(SDL_Surface * to);
void redraw(int level=-1);// (level==-1) => redraw all levels
void initMap(int level=-1);// (level==-1) => redraw all levels
void initFoW(int level=-1);// (level==-1) => redraw all levels
void initFlaggableObjs(int level=-1);// (level==-1) => redraw all levels
void updateRadar();
void clickRight (boost::logic::tribool down);
@ -50,6 +54,7 @@ public:
void deactivate(); // makes button inactive (but don't deletes)
void hideTile(const int3 &pos); //puts FoW
void showTile(const int3 &pos); //removes FoW
void showVisibleTiles(int level=-1);// (level==-1) => redraw all levels
};
class CTerrainRect
: public ClickableL, public ClickableR, public Hoverable, public MotionInterested

View File

@ -2607,6 +2607,10 @@ void CBattleHex::clickRight(boost::logic::tribool down)
pom->morale = myst.Morale();
pom->speedBonus = myst.Speed() - myst.creature->speed;
pom->healthBonus = myst.MaxHealth() - myst.creature->hitPoints;
if(myst.hasFeatureOfType(StackFeature::SIEGE_WEAPON))
pom->dmgMultiplier = h->getPrimSkillLevel(0) + 1;
else
pom->dmgMultiplier = 1;
pom->shotsLeft = myst.shots;
for(int vb=0; vb<myst.effects.size(); ++vb)
@ -2614,7 +2618,7 @@ void CBattleHex::clickRight(boost::logic::tribool down)
pom->effects.insert(myst.effects[vb].id);
}
pom->currentHealth = myst.firstHPleft;
LOCPLINT->pushInt(new CCreInfoWindow(myst.creature->idNumber,0,myst.amount,pom,0,0,NULL));
LOCPLINT->pushInt(new CCreInfoWindow(myst.creature->idNumber, 0, myst.amount, pom, 0, 0, NULL));
}
delete pom;
}

View File

@ -1712,6 +1712,22 @@ void CPlayerInterface::heroExchangeStarted(si32 hero1, si32 hero2)
pushInt(new CExchangeWindow(hero2, hero1));
}
void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
{
//redraw minimap if owner changed
if(sop->what == 1)
{
LOCPLINT->adventureInt->minimap.initFlaggableObjs();
const CGObjectInstance * obj = LOCPLINT->cb->getObjectInfo(sop->id);
std::set<int3> pos = obj->getBlockedPos();
for(std::set<int3>::const_iterator it = pos.begin(); it != pos.end(); ++it)
{
LOCPLINT->adventureInt->minimap.showTile(*it);
}
}
}
void CPlayerInterface::recreateWanderingHeroes()
{
wanderingHeroes.clear();

View File

@ -174,6 +174,7 @@ public:
void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain);//if gain hero received bonus, else he lost it
void requestRealized(PackageApplied *pa);
void heroExchangeStarted(si32 hero1, si32 hero2);
void objectPropertyChanged(const SetObjectProperty * sop);
void serialize(COSer<CSaveFile> &h, const int version); //saving
void serialize(CISer<CLoadFile> &h, const int version); //loading

View File

@ -75,6 +75,7 @@ static StackState* getStackState(const CGObjectInstance *obj, int pos, bool town
pom->luck = h->getCurrentLuck();
pom->morale = h->getCurrentMorale(pos,town);
pom->speedBonus = h->valOfBonuses(HeroBonus::STACKS_SPEED);
pom->dmgMultiplier = 1;
return pom;
}
@ -170,7 +171,7 @@ void CGarrisonSlot::clickRight (tribool down)
StackState *pom = getStackState(getObj(),ID, LOCPLINT->topInt() == LOCPLINT->castleInt);
if(down && creature)
{
LOCPLINT->pushInt(new CCreInfoWindow(creature->idNumber,0,count,pom,0,0,NULL));
LOCPLINT->pushInt(new CCreInfoWindow(creature->idNumber, 0, count, pom, 0, 0, NULL));
}
delete pom;
}
@ -196,15 +197,15 @@ void CGarrisonSlot::clickLeft(tribool down)
{
creWindow = new CCreInfoWindow(
creature->idNumber,1,count,pom2,
boost::bind(&CCallback::upgradeCreature,LOCPLINT->cb,getObj(),ID,pom.newID[0]), //bind upgrade function
boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID),&pom);
creature->idNumber, 1, count, pom2,
boost::bind(&CCallback::upgradeCreature, LOCPLINT->cb, getObj(), ID, pom.newID[0]), //bind upgrade function
boost::bind(&CCallback::dismissCreature, LOCPLINT->cb, getObj(), ID), &pom);
}
else
{
creWindow = new CCreInfoWindow(
creature->idNumber,1,count,pom2,0,
boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID), NULL);
creature->idNumber, 1, count, pom2, 0,
boost::bind(&CCallback::dismissCreature, LOCPLINT->cb, getObj(), ID), NULL);
}
LOCPLINT->pushInt(creWindow);
@ -1681,7 +1682,7 @@ void CRecruitmentWindow::clickRight( boost::logic::tribool down )
{
if(isItIn(&genRect(132,102,pos.x+curx,pos.y+64),LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
{
CCreInfoWindow *popup = new CCreInfoWindow(creatures[i].ID,0,0,NULL,NULL,NULL,NULL);
CCreInfoWindow *popup = new CCreInfoWindow(creatures[i].ID, 0, 0, NULL, NULL, NULL, NULL);
LOCPLINT->pushInt(popup);
break;
}
@ -2007,7 +2008,7 @@ void CCreInfoWindow::show(SDL_Surface * to)
}
CCreInfoWindow::CCreInfoWindow(int Cid, int Type, int creatureCount, StackState *State, boost::function<void()> Upg, boost::function<void()> Dsm, UpgradeInfo *ui)
:type(Type),dsm(Dsm),dismiss(0),upgrade(0),ok(0)
: type(Type), dsm(Dsm), dismiss(0), upgrade(0), ok(0)
{
//active = false;
anf = 0;
@ -2069,24 +2070,27 @@ CCreInfoWindow::CCreInfoWindow(int Cid, int Type, int creatureCount, StackState
//shots
if(c->shots)
{
printAt(CGI->generaltexth->allTexts[198],155,86,GEOR13,zwykly,bitmap);
printAt(CGI->generaltexth->allTexts[198], 155, 86, GEOR13, zwykly, bitmap);
if(State && State->shotsLeft >= 0)
sprintf(pom,"%d (%d)",c->shots,State->shotsLeft);
sprintf(pom,"%d (%d)", c->shots, State->shotsLeft);
else
SDL_itoa(c->shots,pom,10);
printToWR(pom,276,99,GEOR13,zwykly,bitmap);
SDL_itoa(c->shots, pom, 10);
printToWR(pom, 276, 99, GEOR13, zwykly, bitmap);
}
//damage
printAt(CGI->generaltexth->allTexts[199],155,105,GEOR13,zwykly,bitmap);
SDL_itoa(c->damageMin,pom,10);
if(c->damageMin > 0)
hlp = log10f(c->damageMin)+2;
int dmgMin = c->damageMin * State->dmgMultiplier;
int dmgMax = c->damageMax * State->dmgMultiplier;
printAt(CGI->generaltexth->allTexts[199], 155, 105, GEOR13, zwykly, bitmap);
SDL_itoa(dmgMin, pom, 10);
if(dmgMin > 0)
hlp = log10f(dmgMin) + 2;
else
hlp = 2;
pom[hlp-1]=' '; pom[hlp]='-'; pom[hlp+1]=' ';
SDL_itoa(c->damageMax,pom+hlp+2,10);
printToWR(pom,276,118,GEOR13,zwykly,bitmap);
SDL_itoa(dmgMax, pom+hlp+2, 10);
printToWR(pom, 276, 118, GEOR13, zwykly, bitmap);
//health
printAt(CGI->generaltexth->allTexts[388],155,124,GEOR13,zwykly,bitmap);

View File

@ -280,6 +280,16 @@ void InfoWindow::applyCl( CClient *cl )
tlog2 << "We received InfoWindow for not our player...\n";
}
void SetObjectProperty::applyCl( CClient *cl )
{
//inform all players that see this object
for(std::map<ui8,CGameInterface *>::const_iterator it = cl->playerint.begin(); it != cl->playerint.end(); ++it)
{
//if(cl->gs->isVisible(cl->gs->map->objects[id]), it->first)
INTERFACE_CALL_IF_PRESENT(it->first, objectPropertyChanged, this);
}
}
void HeroLevelUp::applyCl( CClient *cl )
{
CGHeroInstance *h = GS(cl)->getHero(heroid);

View File

@ -185,8 +185,8 @@ bool CGObjectInstance::blockingAt(int x, int y) const
if(x<0 || y<0 || x>=getWidth() || y>=getHeight() || defInfo==NULL)
return false;
if((defInfo->blockMap[y+6-getHeight()] >> (7-(8-getWidth()+x) )) & 1)
return true;
return false;
return false;
return true;
}
bool CGObjectInstance::coveringAt(int x, int y) const
@ -196,6 +196,20 @@ bool CGObjectInstance::coveringAt(int x, int y) const
return false;
}
std::set<int3> CGObjectInstance::getBlockedPos() const
{
std::set<int3> ret;
for(int w=0; w<getWidth(); ++w)
{
for(int h=0; h<getHeight(); ++h)
{
if(blockingAt(w, h))
ret.insert(int3(pos.x - getWidth() + w + 1, pos.y - getHeight() + h + 1, pos.z));
}
}
return ret;
}
bool CGObjectInstance::operator<(const CGObjectInstance & cmp) const //screen printing priority comparing
{
if(defInfo->printPriority==1 && cmp.defInfo->printPriority==0)

View File

@ -147,6 +147,7 @@ public:
int3 getVisitableOffset() const; //returns (x,y,0) offset to first visitable tile from bottom right obj tile (0,0,0) (h3m pos)
bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) form left top tile of image (x, y in tiles)
bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) form left top tile of maximal possible image (8 x 6 tiles) (x, y in tiles)
std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object
bool operator<(const CGObjectInstance & cmp) const; //screen printing priority comparing
CGObjectInstance();
virtual ~CGObjectInstance();

View File

@ -1754,6 +1754,28 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
return true;
}
bool CGameState::isVisible(int3 pos, int player)
{
return players[player].fogOfWarMap[pos.x][pos.y][pos.z];
}
bool CGameState::isVisible( const CGObjectInstance *obj, int player )
{
//object is visible when at least one blocked tile is visible
for(int fx=0; fx<8; ++fx)
{
for(int fy=0; fy<6; ++fy)
{
int3 pos = obj->pos + int3(fx-7,fy-5,0);
if(map->isInTheMap(pos)
&& !((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1)
&& isVisible(pos, player) )
return true;
}
}
return false;
}
bool CGameState::checkForVisitableDir(const int3 & src, const int3 & dst) const
{
const TerrainTile * pom = &map->getTile(dst);
@ -1805,6 +1827,12 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
minDmg = attacker->creature->damageMin * attacker->amount,
maxDmg = attacker->creature->damageMax * attacker->amount;
if(attacker->hasFeatureOfType(StackFeature::SIEGE_WEAPON)) //any siege weapon, but only ballista can attack
{ //minDmg and maxDmg are multiplied by hero attack + 1
minDmg *= attackerHero->getPrimSkillLevel(0) + 1;
maxDmg *= attackerHero->getPrimSkillLevel(0) + 1;
}
//calculating total attack/defense skills modifier
if(!shooting && attacker->hasFeatureOfType(StackFeature::ATTACK_BONUS, 0)) //bloodlust handling (etc.)

View File

@ -282,6 +282,9 @@ public:
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if dst tile is visitable from dst tile
bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret); //calculates path between src and dest; returns pointer to newly allocated CPath or NULL if path does not exists
bool isVisible(int3 pos, int player);
bool isVisible(const CGObjectInstance *obj, int player);
CGameState(); //c-tor
~CGameState(); //d-tor
void getNeighbours(int3 tile, std::vector<int3> &vec, const boost::logic::tribool &onLand);

View File

@ -610,6 +610,7 @@ struct InfoWindow : public CPackForClient //103 - displays simple info window
struct SetObjectProperty : public CPackForClient//1001
{
DLL_EXPORT void applyGs(CGameState *gs);
void applyCl(CClient *cl);
ui32 id;
ui8 what; //1 - owner; 2 - blockvis; 3 - first stack count; 4 - visitors; 5 - visited; 6 - ID (if 34 then also def is replaced)

View File

@ -2499,46 +2499,57 @@ static ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster,
case 15: //magic arrow
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 16: //ice bolt
{
ret = caster->getPrimSkillLevel(2) * 20 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 17: //lightning bolt
{
ret = caster->getPrimSkillLevel(2) * 25 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 18: //implosion
{
ret = caster->getPrimSkillLevel(2) * 75 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 20: //frost ring
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 21: //fireball
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 22: //inferno
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 23: //meteor shower
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 24: //death ripple
{
ret = caster->getPrimSkillLevel(2) * 5 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 25: //destroy undead
{
ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
case 26: //armageddon
{
ret = caster->getPrimSkillLevel(2) * 50 + sp->powers[caster->getSpellSchoolLevel(sp)];
break;
}
}
//applying sorcerery secondary skill
@ -2604,7 +2615,7 @@ static ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster,
return ret;
}
static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const std::set<CStack*> affectedCreatures)
static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::set<CStack*> affectedCreatures)
{
std::vector<ui32> ret;
for(std::set<CStack*>::const_iterator it = affectedCreatures.begin(); it != affectedCreatures.end(); ++it)
@ -2613,21 +2624,30 @@ static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHero
if(sp->positiveness >= 0 && (*it)->owner == caster->tempOwner)
continue;
int prob = (*it)->valOfFeatures(StackFeature::MAGIC_RESISTANCE); //probability of resistance in %
//caster's resistance support (secondary skils and artifacts)
prob += caster->valOfBonuses(HeroBonus::MAGIC_RESISTANCE);
const CGHeroInstance * bonusHero; //hero we should take bonuses from
if((*it)->owner == caster->tempOwner)
bonusHero = caster;
else
bonusHero = hero2;
switch(caster->getSecSkillLevel(26)) //resistance
int prob = (*it)->valOfFeatures(StackFeature::MAGIC_RESISTANCE); //probability of resistance in %
if(bonusHero)
{
case 1: //basic
prob += 5;
break;
case 2: //advanced
prob += 10;
break;
case 3: //expert
prob += 20;
break;
//bonusHero's resistance support (secondary skils and artifacts)
prob += bonusHero->valOfBonuses(HeroBonus::MAGIC_RESISTANCE);
switch(bonusHero->getSecSkillLevel(26)) //resistance
{
case 1: //basic
prob += 5;
break;
case 2: //advanced
prob += 10;
break;
case 3: //expert
prob += 20;
break;
}
}
if(prob > 100) prob = 100;
@ -2685,7 +2705,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
std::set<CStack*> attackedCres = gs->curB->getAttackedCreatures(s, h, ba.destinationTile);
//checking if creatures resist
sc.resisted = calculateResistedStacks(s, h, attackedCres);
sc.resisted = calculateResistedStacks(s, h, secondHero, attackedCres);
sendAndApply(&sc);