1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

Fixed some issues with hiring heroes: #25, #232, #333

This commit is contained in:
Michał W. Urbańczyk
2010-07-08 05:52:11 +00:00
parent 78789ef7fc
commit 94f7ee41e2
8 changed files with 166 additions and 116 deletions

View File

@ -545,6 +545,7 @@ askInterfaceForMove:
void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
{
BattleResultsApplied resultsApplied;
resultsApplied.player1 = bEndArmy1->tempOwner;
resultsApplied.player2 = bEndArmy2->tempOwner;
@ -565,6 +566,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
sides[0] = gs->curB->side1;
sides[1] = gs->curB->side2;
ui8 loser = sides[!battleResult.data->winner];
//end battle, remove all info, free memory
giveExp(*battleResult.data);
sendAndApply(battleResult.data);
@ -598,6 +601,8 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
// Necromancy if applicable.
const CGHeroInstance *winnerHero = battleResult.data->winner != 0 ? hero2 : hero1;
const CGHeroInstance *loserHero = battleResult.data->winner != 0 ? hero1 : hero2;
if (winnerHero)
{
CStackInstance raisedStack = winnerHero->calculateNecromancy(*battleResult.data);
@ -630,6 +635,27 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
visitObjectAfterVictory = false;
winLoseHandle(1<<sides[0] | 1<<sides[1]); //handle victory/loss of engaged players
int result = battleResult.get()->result;
if(result == 1 || result == 2) //loser has escaped or surrendered
{
SetAvailableHeroes sah;
sah.player = loser;
sah.hid[0] = loserHero->subID;
if(result == 1) //retreat
{
sah.army[0] = new CCreatureSet();
sah.army[0]->addToSlot(0, VLC->creh->nameToID[loserHero->type->refTypeStack[0]],1);
}
if(const CGHeroInstance *another = getPlayerState(loser)->availableHeroes[1])
sah.hid[1] = another->subID;
else
sah.hid[1] = -1;
sendAndApply(&sah);
}
delete battleResult.data;
}
@ -916,29 +942,37 @@ void CGameHandler::newTurn()
for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
{
if(i->first == 255) continue;
else if(i->first > PLAYER_LIMIT) assert(0); //illegal player number!
if(i->first == 255)
continue;
else if(i->first >= PLAYER_LIMIT)
assert(0); //illegal player number!
std::pair<ui8,si32> playerGold(i->first,i->second.resources[6]);
hadGold.insert(playerGold);
if(gs->getDate(1)==7) //first day of week - new heroes in tavern
{
const CTown *nativeTownType = &VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(i->first).castle];
SetAvailableHeroes sah;
sah.player = i->first;
CGHeroInstance *h = gs->hpool.pickHeroFor(true,i->first,&VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(i->first).castle], pool);
if(h)
sah.hid1 = h->subID;
else
sah.hid1 = -1;
h = gs->hpool.pickHeroFor(false,i->first,&VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(i->first).castle], pool);
if(h)
sah.hid2 = h->subID;
else
sah.hid2 = -1;
//pick heroes and their armies
CHeroClass *banned = NULL;
for (int j = 0; j < AVAILABLE_HEROES_PER_PLAYER; j++)
{
if(CGHeroInstance *h = gs->hpool.pickHeroFor(j == 0, i->first, nativeTownType, pool, banned)) //first hero - native if possible, second hero -> any other class
{
sah.hid[j] = h->subID;
h->initArmy(sah.army[j] = new CCreatureSet());
banned = h->type->heroClass;
}
else
sah.hid[j] = -1;
}
sendAndApply(&sah);
}
if(i->first>=PLAYER_LIMIT) continue;
n.res[i->first] = i->second.resources;
// SetResources r;
@ -3247,14 +3281,16 @@ bool CGameHandler::setFormation( si32 hid, ui8 formation )
bool CGameHandler::hireHero( ui32 tid, ui8 hid )
{
CGTownInstance *t = gs->getTown(tid);
const CGTownInstance *t = gs->getTown(tid);
const PlayerState *p = gs->getPlayer(t->tempOwner);
if(!vstd::contains(t->builtBuildings,5) && complain("No tavern!")
|| gs->getPlayer(t->tempOwner)->resources[6]<2500 && complain("Not enough gold for buying hero!")
|| p->resources[6]<2500 && complain("Not enough gold for buying hero!")
|| t->visitingHero && complain("There is visiting hero - no place!")
|| getHeroCount(t->tempOwner,false) >= 8 && complain("Cannot hire hero, only 8 wandering heroes are allowed!")
)
return false;
CGHeroInstance *nh = gs->getPlayer(t->tempOwner)->availableHeroes[hid];
CGHeroInstance *nh = p->availableHeroes[hid];
assert(nh);
HeroRecruited hr;
@ -3265,25 +3301,30 @@ bool CGameHandler::hireHero( ui32 tid, ui8 hid )
sendAndApply(&hr);
std::map<ui32,CGHeroInstance *> pool = gs->hpool.heroesPool;
for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
for(std::vector<CGHeroInstance *>::iterator j = i->second.availableHeroes.begin(); j != i->second.availableHeroes.end(); j++)
if(*j)
pool.erase((**j).subID);
std::map<ui32,CGHeroInstance *> pool = gs->unusedHeroesFromPool();
const CGHeroInstance *theOtherHero = p->availableHeroes[!hid];
const CGHeroInstance *newHero = gs->hpool.pickHeroFor(false, t->tempOwner,t->town, pool, theOtherHero->type->heroClass);
SetAvailableHeroes sah;
CGHeroInstance *h1 = gs->hpool.pickHeroFor(false,t->tempOwner,t->town, pool),
*h2 = gs->getPlayer(t->tempOwner)->availableHeroes[!hid];
(hid ? sah.hid2 : sah.hid1) = h1 ? h1->subID : -1;
(hid ? sah.hid1 : sah.hid2) = h2 ? h2->subID : -1;
sah.player = t->tempOwner;
sah.flags = hid+1;
if(newHero)
{
sah.hid[hid] = newHero->subID;
sah.army[hid] = new CCreatureSet();
sah.army[hid]->addToSlot(0, VLC->creh->nameToID[newHero->type->refTypeStack[0]],1);
}
else
sah.hid[hid] = -1;
sah.hid[!hid] = theOtherHero ? theOtherHero->subID : -1;
sendAndApply(&sah);
SetResource sr;
sr.player = t->tempOwner;
sr.resid = 6;
sr.val = gs->getPlayer(t->tempOwner)->resources[6] - 2500;
sr.val = p->resources[6] - 2500;
sendAndApply(&sr);
vistiCastleObjects (t, nh);