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

Fixed fighting guardians of Dwellings (and other objs as well).

Most of creature generators should work fine.
This commit is contained in:
Michał W. Urbańczyk 2009-07-20 23:34:06 +00:00
parent ec3b254c83
commit 9206a13390
8 changed files with 79 additions and 59 deletions

View File

@ -1025,12 +1025,7 @@ void CPlayerInterface::receivedResource(int type, int val)
void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16>& skills, boost::function<void(ui32)> &callback)
{
{
boost::unique_lock<boost::mutex> un(showingDialog->mx);
while(showingDialog->data)
showingDialog->cond.wait(un);
}
waitWhileDialog();
CGI->soundh->playSound(soundBase::heroNewLevel);
boost::unique_lock<boost::recursive_mutex> un(*pim);
@ -1378,12 +1373,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, int soundID)
{
{
boost::unique_lock<boost::mutex> un(showingDialog->mx);
while(showingDialog->data)
showingDialog->cond.wait(un);
}
waitWhileDialog();
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(stillMoveHero.get() == DURING_MOVE)//if we are in the middle of hero movement
@ -1424,6 +1414,7 @@ void CPlayerInterface::showYesNoDialog(const std::string &text, const std::vecto
void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel )
{
waitWhileDialog();
boost::unique_lock<boost::recursive_mutex> un(*pim);
CGI->soundh->playSound(static_cast<soundBase::soundID>(soundID));
@ -1734,6 +1725,7 @@ const CGHeroInstance * CPlayerInterface::getWHero( int pos )
void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int level)
{
waitWhileDialog();
std::vector<std::pair<int,int> > cres;
for(int i = 0; i < dwelling->creatures.size(); i++)
{
@ -1745,6 +1737,13 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int lev
pushInt(cr);
}
void CPlayerInterface::waitWhileDialog()
{
boost::unique_lock<boost::mutex> un(showingDialog->mx);
while(showingDialog->data)
showingDialog->cond.wait(un);
}
void SystemOptions::setMusicVolume( int newVolume )
{
musicVolume = newVolume;

View File

@ -192,6 +192,7 @@ public:
//-------------//
void waitWhileDialog();
bool shiftPressed() const; //determines if shift key is pressed (left or right or both)
void redrawHeroWin(const CGHeroInstance * hero);
void updateWater();

View File

@ -96,8 +96,9 @@ public:
void heroVisitCastle(int obj, int heroID){};
void stopHeroVisitCastle(int obj, int heroID){};
void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb){}; //use hero=NULL for no hero
void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb){}; //for hero<=>neutral army
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb = 0){}; //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0){}; //if any of armies is hero, hero will be used
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
void setAmount(int objid, ui32 val){};
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){return false;};
void giveHeroBonus(GiveBonus * bonus){};

View File

@ -652,13 +652,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
else
{
//battle
cb->startBattleI(
&h->army,
&army,
h->pos,
h,
this,
0);
cb->startBattleI(h, this);
}
}
else if(ID == 62) //prison
@ -1113,7 +1107,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
void CGDwelling::wantsFight( const CGHeroInstance *h, ui32 answer ) const
{
if(answer)
cb->startBattleI(h->id,army,pos,boost::bind(&CGDwelling::fightOver, this, h, _1));
cb->startBattleI(h, this, boost::bind(&CGDwelling::fightOver, this, h, _1));
}
void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const
@ -1667,11 +1661,11 @@ void CGCreature::endBattle( BattleResult *result ) const
}
else
{
int killedAmount=0;
for(std::set<std::pair<ui32,si32> >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++)
if(i->first == subID)
killedAmount += i->second;
cb->setAmount(id, army.slots.find(0)->second.second - killedAmount);
//int killedAmount=0;
//for(std::set<std::pair<ui32,si32> >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++)
// if(i->first == subID)
// killedAmount += i->second;
//cb->setAmount(id, army.slots.find(0)->second.second - killedAmount);
MetaString ms;
int pom = CCreature::getQuantityID(army.slots.find(0)->second.second);
@ -1861,7 +1855,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
void CGCreature::fight( const CGHeroInstance *h ) const
{
cb->startBattleI(h->id,army,pos,boost::bind(&CGCreature::endBattle,this,_1));
cb->startBattleI(h, this, boost::bind(&CGCreature::endBattle,this,_1));
}
void CGCreature::flee( const CGHeroInstance * h ) const
@ -1997,7 +1991,7 @@ void CGResource::collectRes( int player ) const
void CGResource::fightForRes(ui32 agreed, const CGHeroInstance *h) const
{
if(agreed)
cb->startBattleI(h->id,army,pos,boost::bind(&CGResource::endBattle,this,_1,h));
cb->startBattleI(h, this, boost::bind(&CGResource::endBattle,this,_1,h));
}
void CGResource::endBattle( BattleResult *result, const CGHeroInstance *h ) const
@ -2164,6 +2158,7 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
if(ID == 5)
{
InfoWindow iw;
iw.soundID = soundBase::treasure;
iw.player = h->tempOwner;
iw.components.push_back(Component(4,subID,0,0));
if(message.length())
@ -2206,7 +2201,7 @@ void CGArtifact::pick(const CGHeroInstance * h) const
void CGArtifact::fightForArt( ui32 agreed, const CGHeroInstance *h ) const
{
if(agreed)
cb->startBattleI(h->id,army,pos,boost::bind(&CGArtifact::endBattle,this,_1,h));
cb->startBattleI(h, this, boost::bind(&CGArtifact::endBattle,this,_1,h));
}
void CGArtifact::endBattle( BattleResult *result, const CGHeroInstance *h ) const
@ -2695,7 +2690,7 @@ void CGEvent::activated( const CGHeroInstance * h ) const
else
iw.text.addTxt(MetaString::ADVOB_TXT, 16);
cb->showInfoDialog(&iw);
cb->startBattleI(h->id,army,pos,boost::bind(&CGEvent::endBattle,this,h,_1));
cb->startBattleI(h, this, boost::bind(&CGEvent::endBattle,this,h,_1));
}
else
{

View File

@ -31,6 +31,7 @@ struct PlayerSettings;
struct CPackForClient;
class CArtHandler;
class CArtifact;
class CArmedInstance;
class DLL_EXPORT IGameCallback
{
@ -73,8 +74,10 @@ public:
virtual void heroVisitCastle(int obj, int heroID)=0;
virtual void stopHeroVisitCastle(int obj, int heroID)=0;
virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
virtual void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)=0; //use hero=NULL for no hero
virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb)=0; //for hero<=>neutral army
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb = 0)=0; //use hero=NULL for no hero
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb = 0)=0; //if any of armies is hero, hero will be used
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
//virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb)=0; //for hero<=>neutral army
virtual void setAmount(int objid, ui32 val)=0;
virtual bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0;
virtual void giveHeroBonus(GiveBonus * bonus)=0;

View File

@ -288,7 +288,7 @@ void TryMoveHero::applyGs( CGameState *gs )
CGHeroInstance *h = gs->getHero(id);
h->movement = movePoints;
if(result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK)
if((result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK) && start != end)
h->moveDir = getDir(start,end);
if(result == EMBARK) //hero enters boat at dest tile

View File

@ -294,6 +294,8 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInfo *bat)
{
if(color == 254)
color = 255;
CCreatureSet ret(set);
for(int i=0; i<bat->stacks.size();i++)
{
@ -309,10 +311,10 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf
return ret;
}
void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)
void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)
{
BattleInfo *curB = new BattleInfo;
setupBattle(curB, tile, army1, army2, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
setupBattle(curB, tile, army1->army, army2->army, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
NEW_ROUND;
//TODO: pre-tactic stuff, call scripts etc.
@ -401,10 +403,8 @@ askInterfaceForMove:
//casualties among heroes armies
SetGarrisons sg;
if(hero1)
sg.garrs[hero1->id] = takeCasualties(hero1->tempOwner,hero1->army,gs->curB);
if(hero2)
sg.garrs[hero2->id] = takeCasualties(hero2->tempOwner,hero2->army,gs->curB);
sg.garrs[army1->id] = takeCasualties(army1->tempOwner,army1->army,gs->curB);
sg.garrs[army2->id] = takeCasualties(army2->tempOwner,army2->army,gs->curB);
sendAndApply(&sg);
//end battle, remove all info, free memory
@ -822,7 +822,7 @@ namespace CGH
}
}
void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 )
void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 )
{
battleResult.set(NULL);
std::vector<CStack*> & stacks = (curB->stacks);
@ -837,7 +837,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
curB->side2=(hero2)?(hero2->tempOwner):(-1);
curB->round = -2;
curB->activeStack = -1;
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
{
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
if(hero1)
@ -890,7 +890,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
{
stacks[b]->position = attackerLoose[army1.slots.size()-1][b];
}
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
{
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false, i->first));
//base luck/morale calculations
@ -1170,7 +1170,8 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
&& complain("Cannot move hero, destination tile is on water!")
|| (h->boat && t.tertype != TerrainTile::water && t.blocked)
&& complain("Cannot disembark hero, tile is blocked!")
|| !h->movement && complain("Hero don't have any movement points left!"))
|| (!h->movement && dst != h->pos)
&& complain("Hero don't have any movement points left!"))
{
//send info about movement failure
sendAndApply(&tmh);
@ -1266,11 +1267,15 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
{
if(obj->ID==HEROI_TYPE)
{
if(obj->tempOwner==h->tempOwner)
return true;//TODO: exchange
//TODO: check for ally
CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj);
startBattleI(&h->army,&dh->army,dst,h,dh,0);
if(obj->tempOwner==h->tempOwner)
{
heroExchange(h->id, dh->id);
return true;
}
//TODO: check for ally
startBattleI(h, dh);
return true;
}
}
@ -1397,17 +1402,31 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
sendAndApply(&sha);
}
void CGameHandler::startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb) //use hero=NULL for no hero
void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb) //use hero=NULL for no hero
{
boost::thread(boost::bind(&CGameHandler::startBattle,this,*const_cast<CCreatureSet *>(army1),*const_cast<CCreatureSet *>(army2),tile,const_cast<CGHeroInstance *>(hero1), const_cast<CGHeroInstance *>(hero2),cb));
boost::thread(boost::bind(&CGameHandler::startBattle,this,army1,army2,tile,hero1,hero2,cb));
}
void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb )
{
CGHeroInstance* h = const_cast<CGHeroInstance*>(getHero(heroID));
startBattleI(&h->army,&army,tile,h,NULL,cb);
//battle(&h->army,army,tile,h,NULL);
startBattleI(army1, army2, tile,
army1->ID == 34 ? static_cast<const CGHeroInstance*>(army1) : NULL,
army2->ID == 34 ? static_cast<const CGHeroInstance*>(army2) : NULL,
cb);
}
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb)
{
startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), cb);
}
//void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army
//{
// CGHeroInstance* h = const_cast<CGHeroInstance*>(getHero(heroID));
// startBattleI(&h->army,&army,tile,h,NULL,cb);
// //battle(&h->army,army,tile,h,NULL);
//}
void CGameHandler::changeSpells( int hid, bool give, const std::set<ui32> &spells )
{
ChangeSpells cs;

View File

@ -84,11 +84,11 @@ public:
bool isAllowedExchange(int id1, int id2);
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
void moveStack(int stack, int dest);
void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void prepareAttack(BattleAttack &bat, CStack *att, CStack *def); //if last parameter is true, attack is by shooting, if false it's a melee attack
void prepareAttacked(BattleStackAttacked &bsa, CStack *def);
void checkForBattleEnd( std::vector<CStack*> &stacks );
void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 );
void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 );
CGameHandler(void);
@ -121,8 +121,10 @@ public:
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack
void moveArtifact(int hid, int oldPosition, int destPos);
void removeArtifact(int hid, int pos);
void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function<void(BattleResult*)> cb);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb = 0); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void setAmount(int objid, ui32 val);
bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255);
void giveHeroBonus(GiveBonus * bonus);