1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

New non battle stack class. (Base for future improved bonus system, stack exp / arts)

Fixed #443
This commit is contained in:
Michał W. Urbańczyk 2010-04-02 02:07:40 +00:00
parent be42b7ff62
commit 993036e4a1
14 changed files with 265 additions and 403 deletions

View File

@ -316,8 +316,8 @@ float CGeniusAI::TownObjective::getValue() const
case upgradeCreatures:
UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which);
ID = whichTown->creaturesInGarrison.slots[which].first;
howMany = whichTown->creaturesInGarrison.slots[which].second;
ID = whichTown->creaturesInGarrison.slots[which].type->idNumber;
howMany = whichTown->creaturesInGarrison.slots[which].count;
newID = ui.newID.back();
int upgrade_serial = ui.newID.size() - 1;
@ -424,7 +424,7 @@ void CGeniusAI::TownObjective::print() const
case upgradeCreatures:
UpgradeInfo ui = AI->m_cb->getUpgradeInfo(whichTown->t,which);
ID = whichTown->creaturesInGarrison.slots[which].first;
ID = whichTown->creaturesInGarrison.slots[which].type->idNumber;
cout << "upgrade " << VLC->creh->creatures[ID].namePl;
//ui.cost
break;
@ -735,7 +735,7 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg,
//upgrade hero's units
cout << "visiting town" << endl;
CCreatureSet hcreatures = h->h->army;
for (std::map< si32, std::pair<ui32,si32> >::const_iterator
for (TSlots::const_iterator
i = hcreatures.slots.begin();
i != hcreatures.slots.end();
i++) { // For each hero slot.
@ -749,7 +749,7 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg,
j = ui.cost[ii].begin();
j != ui.cost[ii].end();
j++)
if (hgs.resourceAmounts[j->first] < j->second * i->second.second)
if (hgs.resourceAmounts[j->first] < j->second * i->second.count)
canUpgrade = false;
}
@ -757,7 +757,7 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg,
{
cg.m_cb->upgradeCreature(h->h, i->first, ui.newID.back());
cout << "upgrading hero's "
<< VLC->creh->creatures[i->second.first].namePl
<< i->second.type->namePl
<< endl;
}
}
@ -767,33 +767,33 @@ void CGeniusAI::HeroObjective::fulfill(CGeniusAI& cg,
int weakestCreatureStack;
int weakestCreatureAIValue = 99999; // TODO: Wtf??
for (std::map< si32, std::pair<ui32,si32> >::const_iterator
for (TSlots::const_iterator
i = tcreatures.slots.begin();
i != tcreatures.slots.end();
i++) {
if (VLC->creh->creatures[i->second.first].AIValue <
if (i->second.type->AIValue <
weakestCreatureAIValue) {
weakestCreatureAIValue = VLC->creh->creatures[i->second.first].AIValue;
weakestCreatureAIValue = i->second.type->AIValue;
weakestCreatureStack = i->first;
}
}
for (std::map< si32, std::pair<ui32, si32> >::const_iterator
for (TSlots::const_iterator
i = tcreatures.slots.begin();
i != tcreatures.slots.end();
i++) { // For each town slot.
hcreatures = h->h->army;
int hSlot = hcreatures.getSlotFor(i->second.first);
int hSlot = hcreatures.getSlotFor(i->second.type->idNumber);
if (hSlot == -1)
continue;
cout << "giving hero "
<< VLC->creh->creatures[i->second.first].namePl
<< i->second.type->namePl
<< endl;
if (hcreatures.slots.find(hSlot) != hcreatures.slots.end()) {
// Can't take garrisonHero's last unit.
if ( (i->first == weakestCreatureStack)
&& (town->garrisonHero != NULL) )
cg.m_cb->splitStack(town, h->h, i->first, hSlot, i->second.second - 1);
cg.m_cb->splitStack(town, h->h, i->first, hSlot, i->second.count - 1);
else
// TODO: the comment says that this code is not safe for the AI.
cg.m_cb->mergeStacks(town, h->h, i->first, hSlot);
@ -868,7 +868,7 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel& t,
}
// Upgrade creatures.
for (std::map< si32, std::pair<ui32, si32> >::iterator
for (TSlots::iterator
i = t.creaturesInGarrison.slots.begin();
i != t.creaturesInGarrison.slots.end();
i++) {
@ -881,7 +881,7 @@ void CGeniusAI::addTownObjectives(HypotheticalGameState::TownModel& t,
j = ui.cost[upgrade_serial].begin();
j != ui.cost[upgrade_serial].end();
j++)
if (hgs.resourceAmounts[j->first] < j->second * i->second.second)
if (hgs.resourceAmounts[j->first] < j->second * i->second.count)
canAfford = false;
if (canAfford) {
TownObjective to(hgs,AIObjective::upgradeCreatures,&t,i->first,this);
@ -942,7 +942,7 @@ void CGeniusAI::TownObjective::fulfill(CGeniusAI& cg,
case upgradeCreatures:
UpgradeInfo ui = cg.m_cb->getUpgradeInfo(whichTown->t, which);
ID = whichTown->creaturesInGarrison.slots[which].first;
ID = whichTown->creaturesInGarrison.slots[which].type->idNumber;
newID = ui.newID.back();
// TODO: reduce resources in hgs
cg.m_cb->upgradeCreature(whichTown->t, which, newID);

View File

@ -3652,12 +3652,12 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
{
int bestMonsterID = -1;
int bestPower = 0;
for(std::map<si32,std::pair<ui32,si32> >::const_iterator it = owner->army1->slots.begin(); it!=owner->army1->slots.end(); ++it)
for(TSlots::const_iterator it = owner->army1->slots.begin(); it!=owner->army1->slots.end(); ++it)
{
if( CGI->creh->creatures[it->first].AIValue > bestPower)
if( it->second.type->AIValue > bestPower)
{
bestPower = CGI->creh->creatures[it->first].AIValue;
bestMonsterID = it->first;
bestPower = it->second.type->AIValue;
bestMonsterID = it->second.type->idNumber;
}
}
SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 21, 38));
@ -3674,12 +3674,12 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
{
int bestMonsterID = -1;
int bestPower = 0;
for(std::map<si32,std::pair<ui32,si32> >::const_iterator it = owner->army2->slots.begin(); it!=owner->army2->slots.end(); ++it)
for(TSlots::const_iterator it = owner->army2->slots.begin(); it!=owner->army2->slots.end(); ++it)
{
if( CGI->creh->creatures[it->second.first].AIValue > bestPower)
if( it->second.type->AIValue > bestPower)
{
bestPower = CGI->creh->creatures[it->second.first].AIValue;
bestMonsterID = it->second.first;
bestPower = it->second.type->AIValue;
bestMonsterID = it->second.type->idNumber;
}
}
SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &genRect(64, 58, 391, 38));

View File

@ -528,6 +528,8 @@ void startGame(StartInfo * options)
ev.user.code = 1;
SDL_PushEvent(&ev);
}
else
setResolution = true;
client = new CClient;
if(options->mode == 0) //new game

View File

@ -487,17 +487,13 @@ void CGarrisonInt::createSlots()
if(set1)
{
sup = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL));
for
(std::map<si32,std::pair<ui32,si32> >::const_iterator i=set1->slots.begin();
i!=set1->slots.end(); i++)
{
(*sup)[i->first] =
new CGarrisonSlot(this, pos.x + (i->first*(w+interx)), pos.y,i->first, 0,
&CGI->creh->creatures[i->second.first],i->second.second);
}
for(TSlots::const_iterator i=set1->slots.begin(); i!=set1->slots.end(); i++)
(*sup)[i->first] = new CGarrisonSlot(this, pos.x + (i->first*(w+interx)), pos.y, i->first, 0, i->second.type,i->second.count);
for(int i=0; i<sup->size(); i++)
if((*sup)[i] == NULL)
(*sup)[i] = new CGarrisonSlot(this, pos.x + (i*(w+interx)), pos.y,i,0,NULL, 0);
if (shiftPos)
for (int i=shiftPos; i<sup->size(); i++)
{
@ -508,13 +504,10 @@ void CGarrisonInt::createSlots()
if(set2)
{
sdown = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL));
for
(std::map<si32,std::pair<ui32,si32> >::const_iterator i=set2->slots.begin();
i!=set2->slots.end(); i++)
for(TSlots::const_iterator i=set2->slots.begin(); i!=set2->slots.end(); i++)
{
(*sdown)[i->first] =
new CGarrisonSlot(this, pos.x + (i->first*(w+interx)) + garOffset.x, pos.y + garOffset.y,i->first,1,
&CGI->creh->creatures[i->second.first],i->second.second);
new CGarrisonSlot(this, pos.x + (i->first*(w+interx)) + garOffset.x, pos.y + garOffset.y,i->first,1, i->second.type,i->second.count);
}
for(int i=0; i<sdown->size(); i++)
if((*sdown)[i] == NULL)

View File

@ -51,17 +51,17 @@ SDL_Surface * Graphics::drawHeroInfoWin(const InfoAboutHero &curh)
blitAt(graphics->portraitLarge[curh.portrait],11,12,ret); //portrait
//army
for (std::map<si32,std::pair<ui32,si32> >::const_iterator i=curh.army.slots.begin(); i!=curh.army.slots.end();i++)
for (TSlots::const_iterator i = curh.army.slots.begin(); i!=curh.army.slots.end();i++)
{
blitAt(graphics->smallImgs[(*i).second.first],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
blitAt(graphics->smallImgs[(*i).second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
if(curh.details)
{
SDL_itoa((*i).second.second,buf,10);
SDL_itoa((*i).second.count,buf,10);
printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
else
{
printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*i->second.second],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*i->second.count],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
}
@ -108,15 +108,15 @@ SDL_Surface * Graphics::drawTownInfoWin( const InfoAboutTown & curh )
int pom = curh.fortLevel - 1; if(pom<0) pom = 3; //fort pic id
blitAt(forts->ourImages[pom].bitmap,115,42,ret); //fort
for (std::map<si32,std::pair<ui32,si32> >::const_iterator i=curh.army.slots.begin(); i!=curh.army.slots.end();i++)
for (TSlots::const_iterator i=curh.army.slots.begin(); i!=curh.army.slots.end();i++)
{
//if(!i->second.second)
// continue;
blitAt(graphics->smallImgs[(*i).second.first],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
blitAt(graphics->smallImgs[(*i).second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
if(curh.details)
{
// Show exact creature amount.
SDL_itoa((*i).second.second,buf,10);
SDL_itoa((*i).second.count,buf,10);
printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,zwykly,ret);
}
else

View File

@ -15,6 +15,8 @@ typedef boost::int32_t si32; //signed int 32 bits (4 bytes)
typedef boost::int16_t si16; //signed int 16 bits (2 bytes)
typedef boost::int8_t si8; //signed int 8 bits (1 byte)
#include "int3.h"
#include <map>
#include <vector>
#define CHECKTIME 1
#if CHECKTIME
#include "timeHandler.h"
@ -295,6 +297,7 @@ void delNull(T* &ptr) //deleted pointer and sets it to NULL
ptr = NULL;
}
#include "lib/CCreatureSet.h"
#include "CConsoleHandler.h"
extern DLL_EXPORT std::ostream *logfile;
extern DLL_EXPORT CConsoleHandler *console;

View File

@ -461,11 +461,11 @@ static int lowestSpeed(const CGHeroInstance * chi)
tlog1 << "Error! Hero " << chi->id << " ("<<chi->name<<") has no army!\n";
return 20;
}
std::map<si32,std::pair<ui32,si32> >::const_iterator i = chi->army.slots.begin();
ui32 ret = VLC->creh->creatures[(*i++).second.first].speed;
TSlots::const_iterator i = chi->army.slots.begin();
ui32 ret = (i++)->second.type->speed;
for (;i!=chi->army.slots.end();i++)
{
ret = std::min(ret,VLC->creh->creatures[(*i).second.first].speed);
ret = std::min(ret, i->second.type->speed);
}
return ret;
}
@ -709,6 +709,7 @@ void CGHeroInstance::initHero(int SUBID)
void CGHeroInstance::initHero()
{
assert(army.validTypes(true));
if(ID == HEROI_TYPE)
initHeroDefInfo();
if(!type)
@ -748,42 +749,45 @@ void CGHeroInstance::initHero()
level = VLC->heroh->level(exp);
}
army.formation = false;
if (!army.slots.size()) //standard army//initial army
{
int pom, pom2=0;
int howManyStacks = 0; //how many stacks will hero receives <1 - 3>
int pom = ran()%100;
int warMachinesGiven = 0;
int x = 0; //how many stacks will hero receives <1 - 3>
pom = ran()%100;
if(pom < 9)
x = 1;
howManyStacks = 1;
else if(pom < 79)
x = 2;
howManyStacks = 2;
else
x = 3;
howManyStacks = 3;
for(int x=0;x<3;x++)
for(int stackNo=0; stackNo<3; stackNo++)
{
pom = (VLC->creh->nameToID[type->refTypeStack[x]]);
if(pom>=145 && pom<=149) //war machine
int creID = (VLC->creh->nameToID[type->refTypeStack[stackNo]]);
int range = type->highStack[stackNo] - type->lowStack[stackNo];
int count = ran()%(range+1) + type->lowStack[stackNo];
if(creID>=145 && creID<=149) //war machine
{
pom2++;
switch (pom)
warMachinesGiven++;
switch (creID)
{
case 145: //catapult
VLC->arth->equipArtifact(artifWorn, 16, 3);
break;
default:
VLC->arth->equipArtifact(artifWorn, 9+CArtHandler::convertMachineID(pom,true), CArtHandler::convertMachineID(pom,true));
VLC->arth->equipArtifact(artifWorn, 9+CArtHandler::convertMachineID(creID,true), CArtHandler::convertMachineID(creID,true));
break;
}
continue;
}
army.slots[x-pom2].first = pom;
pom = type->highStack[x] - type->lowStack[x];
army.slots[x-pom2].second = ran()%(pom+1) + type->lowStack[x];
army.formation = false;
else
army.slots[stackNo-warMachinesGiven] = CStackInstance(creID, count);
}
}
assert(army.validTypes());
hoverName = VLC->generaltexth->allTexts[15];
boost::algorithm::replace_first(hoverName,"%s",name);
boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name);
@ -915,10 +919,10 @@ std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentMoraleModifie
{
bool archangelInArmy = false;
std::set<si8> factions;
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i=army.slots.begin(); i!=army.slots.end(); i++)
for(TSlots::const_iterator i=army.slots.begin(); i!=army.slots.end(); i++)
{
// Take Angelic Alliance troop-mixing freedom of non-evil, non-Conflux units into account.
const si8 faction = VLC->creh->creatures[i->second.first].faction;
const si8 faction = i->second.type->faction;
if (hasBonusOfType(HeroBonus::NONEVIL_ALIGNMENT_MIX)
&& ((faction >= 0 && faction <= 2) || faction == 6 || faction == 7))
{
@ -929,7 +933,7 @@ std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentMoraleModifie
factions.insert(faction);
}
if(i->second.first == 13)
if(i->second.type->idNumber == 13)
archangelInArmy = true;
}
@ -997,7 +1001,7 @@ const HeroBonus * CGHeroInstance::getBonus( int from, int id ) const
void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
{
if(what == 3)
army.slots[0].second = val;
army.slots[0].count = val;
}
double CGHeroInstance::getHeroStrength() const
@ -1063,7 +1067,7 @@ bool CGHeroInstance::canCastThisSpell(const CSpell * spell) const
* type and second value the amount. Both values are returned as -1 if necromancy
* could not be applied.
*/
std::pair<ui32, si32> CGHeroInstance::calculateNecromancy (const BattleResult &battleResult) const
CStackInstance CGHeroInstance::calculateNecromancy (const BattleResult &battleResult) const
{
const ui8 necromancyLevel = getSecSkillLevel(12);
@ -1099,10 +1103,10 @@ std::pair<ui32, si32> CGHeroInstance::calculateNecromancy (const BattleResult &b
if (raisedUnits <= 0)
raisedUnits = 1;
return std::pair<ui32, si32>(raisedUnitType->idNumber, raisedUnits);
return CStackInstance(raisedUnitType->idNumber, raisedUnits);
}
return std::pair<ui32, si32>(-1, -1);
return CStackInstance();
}
/**
@ -1110,21 +1114,23 @@ std::pair<ui32, si32> CGHeroInstance::calculateNecromancy (const BattleResult &b
* @param raisedStack Pair where the first element represents ID of the raised creature
* and the second element the amount.
*/
void CGHeroInstance::showNecromancyDialog (std::pair<ui32, si32> raisedStack) const
void CGHeroInstance::showNecromancyDialog(const CStackInstance &raisedStack) const
{
const CCreature &unitType = VLC->creh->creatures[raisedStack.first];
InfoWindow iw;
iw.soundID = soundBase::GENIE;
iw.player = tempOwner;
iw.components.push_back(Component(3, unitType.idNumber, raisedStack.second, 0));
iw.components.push_back(Component(raisedStack));
if (raisedStack.second > 1) { // Practicing the dark arts of necromancy, ... (plural)
if (raisedStack.count > 1) // Practicing the dark arts of necromancy, ... (plural)
{
iw.text.addTxt(MetaString::GENERAL_TXT, 145);
iw.text.addReplacement(raisedStack.second);
iw.text.addReplacement(MetaString::CRE_PL_NAMES, unitType.idNumber);
} else { // Practicing the dark arts of necromancy, ... (singular)
iw.text.addReplacement(raisedStack.count);
iw.text.addReplacement(MetaString::CRE_PL_NAMES, raisedStack.type->idNumber);
}
else // Practicing the dark arts of necromancy, ... (singular)
{
iw.text.addTxt(MetaString::GENERAL_TXT, 146);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, unitType.idNumber);
iw.text.addReplacement(MetaString::CRE_SING_NAMES, raisedStack.type->idNumber);
}
cb->showInfoDialog(&iw);
@ -1273,16 +1279,13 @@ void CGDwelling::initObj()
case 17:
{
int crid = VLC->objh->cregens[subID];
CCreature *crs = &VLC->creh->creatures[crid];
const CCreature *crs = &VLC->creh->creatures[crid];
creatures.resize(1);
creatures[0].second.push_back(crid);
hoverName = VLC->generaltexth->creGens[subID];
if(crs->level > 4)
{
army.slots[0].first = crs->idNumber;
army.slots[0].second = (8 - crs->level) * 3;
}
army.slots[0] = CStackInstance(crs, (8 - crs->level) * 3);
if (getOwner() != 255)
cb->gameState()->players[getOwner()].dwellings.push_back (this);
}
@ -1297,10 +1300,8 @@ void CGDwelling::initObj()
creatures[2].second.push_back(116); //Gold Golem
creatures[3].second.push_back(117); //Diamond Golem
//guards
army.slots[0].first = 116;
army.slots[0].second = 9;
army.slots[1].first = 117;
army.slots[1].second = 6;
army.slots[0] = CStackInstance(116, 9);
army.slots[1] = CStackInstance(117, 6);
}
else if(subID == 0) // Elemental Conflux
{
@ -1309,8 +1310,7 @@ void CGDwelling::initObj()
creatures[2].second.push_back(113); //Earth Elemental
creatures[3].second.push_back(115); //Water Elemental
//guards
army.slots[0].first = 113;
army.slots[0].second = 12;
army.slots[0] = CStackInstance(113, 12);
}
else
{
@ -1353,8 +1353,8 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
bd.flags = BlockingDialog::ALLOW_CANCEL;
bd.text.addTxt(MetaString::GENERAL_TXT, 421); //Much to your dismay, the %s is guarded by %s %s. Do you wish to fight the guards?
bd.text.addReplacement(ID == 17 ? MetaString::CREGENS : MetaString::CREGENS4, subID);
bd.text.addReplacement(MetaString::ARRAY_TXT, 176 + CCreature::getQuantityID(army.slots.begin()->second.second)*3);
bd.text.addReplacement(MetaString::CRE_PL_NAMES, army.slots.begin()->second.first);
bd.text.addReplacement(MetaString::ARRAY_TXT, 176 + army.slots.begin()->second.getQuantityID()*3);
bd.text.addReplacement(army.slots.begin()->second);
cb->showBlockingDialog(&bd, boost::bind(&CGDwelling::wantsFight, this, h, _1));
return;
}
@ -1435,8 +1435,8 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
SetGarrisons sg;
sg.garrs[h->id] = h->army;
sg.garrs[h->id].slots[slot].first = crid;
sg.garrs[h->id].slots[slot].second += creatures[0].first;
sg.garrs[h->id].slots[slot].setType(crid);
sg.garrs[h->id].slots[slot].count += creatures[0].first;
InfoWindow iw;
iw.player = h->tempOwner;
@ -2282,13 +2282,14 @@ bool CArmedInstance::needsLastStack() const
int CArmedInstance::getArmyStrength() const
{
int ret = 0;
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i=army.slots.begin(); i!=army.slots.end(); i++)
ret += VLC->creh->creatures[i->second.first].AIValue * i->second.second;
for(TSlots::const_iterator i = army.slots.begin(); i != army.slots.end(); i++)
ret += i->second.type->AIValue * i->second.count;
return ret;
}
ui64 CArmedInstance::getPower (TSlot slot) const
{
return VLC->creh->creatures[army.getCreature(slot)].AIValue * army.getAmount(slot);
return army.getCreature(slot)->AIValue * army.getAmount(slot);
}
std::string CArmedInstance::getRoughAmount (TSlot slot) const
{
@ -2344,7 +2345,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
BlockingDialog ynd(true,false);
ynd.player = h->tempOwner;
std::string tmp = VLC->generaltexth->advobtxt[90];
boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(army.slots.find(0)->second.second));
boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(army.slots.find(0)->second.count));
boost::algorithm::replace_first(tmp,"%d",boost::lexical_cast<std::string>(action));
boost::algorithm::replace_first(tmp,"%s",VLC->creh->creatures[subID].namePl);
ynd.text << tmp;
@ -2370,7 +2371,7 @@ void CGCreature::endBattle( BattleResult *result ) const
//cb->setAmount(id, army.slots.find(0)->second.second - killedAmount);
MetaString ms;
int pom = CCreature::getQuantityID(army.slots.find(0)->second.second);
int pom = army.slots.find(0)->second.getQuantityID();
pom = 174 + 3*pom + 1;
ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,subID);
cb->setHoverName(id,&ms);
@ -2399,8 +2400,8 @@ void CGCreature::initObj()
break;
}
army.slots[0].first = subID;
si32 &amount = army.slots[0].second;
army.slots[0].setType(subID);
si32 &amount = army.slots[0].count;
CCreature &c = VLC->creh->creatures[subID];
if(!amount)
if(c.ammMax == c.ammMin)
@ -2409,7 +2410,7 @@ void CGCreature::initObj()
amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
MetaString ms;
int pom = CCreature::getQuantityID(army.slots.find(0)->second.second);
int pom = army.slots.find(0)->second.getQuantityID();
pom = 174 + 3*pom + 1;
ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,subID);
ms.toString(hoverName);
@ -2446,11 +2447,12 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
int count = 0, //how many creatures of our kind has hero
totalCount = 0;
for (std::map<si32,std::pair<ui32,si32> >::const_iterator i = h->army.slots.begin(); i != h->army.slots.end(); i++)
for (TSlots::const_iterator i = h->army.slots.begin(); i != h->army.slots.end(); i++)
{
if(vstd::contains(myKindCres,i->second.first))
count += i->second.second;
totalCount += i->second.second;
if(vstd::contains(myKindCres,i->second.type->idNumber))
count += i->second.count;
totalCount += i->second.count;
}
if(count*2 > totalCount)
@ -2465,7 +2467,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
if(h->getSecSkillLevel(4) + sympathy + 1 >= character)
return 0; //join for free
else if(h->getSecSkillLevel(4) * 2 + sympathy + 1 >= character)
return VLC->creh->creatures[subID].cost[6] * army.slots.find(0)->second.second; //join for gold
return VLC->creh->creatures[subID].cost[6] * army.slots.find(0)->second.count; //join for gold
}
}
@ -2537,14 +2539,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
//add creatures
SetGarrisons sg;
sg.garrs[h->id] = h->army;
if(vstd::contains(h->army.slots,slot)) //add to already present stack
{
sg.garrs[h->id].slots[slot].second += army.slots.find(0)->second.second;
}
else //add as a new stack
{
sg.garrs[h->id].slots[slot] = army.slots.find(0)->second;
}
sg.garrs[h->id].addToSlot(slot, subID, army[0].count);
cb->sendAndApply(&sg);
cb->removeObject(id);
}
@ -3231,10 +3226,10 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
{
for (count = 0, it = h->army.slots.begin(); it != h->army.slots.end(); ++it)
{
if (it->second.first == cre->second.first)
count += it->second.second;
if (it->second.type == cre->second.type)
count += it->second.count;
}
if (count < cre->second.second) //not enough creatures of this kind
if (count < cre->second.count) //not enough creatures of this kind
return false;
}
}
@ -3323,24 +3318,20 @@ const std::string & CGSeerHut::getHoverText() const
ms.addReplacement(VLC->heroh->heroes[m13489val]->name);
break;
case MISSION_KILL_CREATURE:
{
const TStack* stack = cb->gameState()->map->monsters[m13489val]->army.getStack(0);
if (stack->first == 1)
ms.addReplacement (MetaString::CRE_SING_NAMES, stack->first);
else
ms.addReplacement (MetaString::CRE_PL_NAMES, stack->first);
}
{
ms.addReplacement(cb->gameState()->map->monsters[m13489val]->army[0]);
}
break;
case MISSION_ART:
{
MetaString loot;
for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
{
loot << "%s";
loot.addReplacement (MetaString::ART_NAMES, *it);
MetaString loot;
for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
{
loot << "%s";
loot.addReplacement (MetaString::ART_NAMES, *it);
}
ms.addReplacement(loot.buildList());
}
ms.addReplacement(loot.buildList());
}
break;
case MISSION_ARMY:
case MISSION_RESOURCES:
@ -3418,18 +3409,15 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
iw.text.addReplacement(VLC->heroh->heroes[m13489val]->name);
break;
case MISSION_KILL_CREATURE:
{
const TStack* stack = cb->gameState()->map->monsters[m13489val]->army.getStack(0);
iw.components.push_back (Component (Component::CREATURE, stack->first, stack->second, 0));
if (stack->first == 1)
iw.text.addReplacement (MetaString::CRE_SING_NAMES, stack->first);
else
iw.text.addReplacement (MetaString::CRE_PL_NAMES, stack->first);
if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
{
iw.text.addReplacement (VLC->generaltexth->arraytxt[147+checkDirection()]);
CStackInstance stack = cb->gameState()->map->monsters[m13489val]->army[0];
iw.components.push_back (Component(stack));
iw.text.addReplacement(stack);
if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
{
iw.text.addReplacement (VLC->generaltexth->arraytxt[147+checkDirection()]);
}
}
}
break;
case MISSION_ART:
{
@ -3448,12 +3436,9 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
MetaString loot;
for (TSlots::const_iterator it = m6creatures.begin(); it != m6creatures.end(); ++it)
{
iw.components.push_back (Component (Component::CREATURE, it->second.first, it->second.second, 0));
iw.components.push_back(Component(it->second));
loot << "%s";
if (it->second.second == 1)
loot.addReplacement (MetaString::CRE_SING_NAMES, it->second.first);
else
loot.addReplacement (MetaString::CRE_PL_NAMES, it->second.first);
loot.addReplacement(it->second);
}
iw.text.addReplacement (loot.buildList());
}
@ -3531,12 +3516,9 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
MetaString loot;
for (TSlots::const_iterator it = m6creatures.begin(); it != m6creatures.end(); ++it)
{
bd.components.push_back (Component (Component::CREATURE, it->second.first, it->second.second, 0));
bd.components.push_back(Component(it->second));
loot << "%s";
if (it->second.second == 1)
loot.addReplacement (MetaString::CRE_SING_NAMES, it->second.first);
else
loot.addReplacement (MetaString::CRE_PL_NAMES, it->second.first);
loot.addReplacement(it->second);
}
bd.text.addReplacement (loot.buildList());
}
@ -3565,11 +3547,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
break;
case MISSION_KILL_CREATURE:
{
const TStack* stack = cb->gameState()->map->monsters[m13489val]->army.getStack(0);
if (stack->first == 1)
bd.text.addReplacement (MetaString::CRE_SING_NAMES, stack->first);
else
bd.text.addReplacement (MetaString::CRE_PL_NAMES, stack->first);
bd.text.addReplacement(cb->gameState()->map->monsters[m13489val]->army[0]);
if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
{
bd.text.addReplacement (VLC->generaltexth->arraytxt[147+checkDirection()]);
@ -3893,9 +3871,9 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
case 94: //Stables TODO: upgrade Cavaliers
sound = soundBase::horse20;
std::set<ui32> slots;
for (std::map<si32,std::pair<ui32,si32> >::const_iterator i = h->army.slots.begin(); i != h->army.slots.end(); ++i)
for (TSlots::const_iterator i = h->army.slots.begin(); i != h->army.slots.end(); ++i)
{
if(i->second.first == 10)
if(i->second.type->idNumber == 10)
slots.insert(i->first);
}
if (!slots.empty())
@ -4232,17 +4210,14 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
{ //this part is taken straight from creature bank
MetaString loot;
CCreatureSet ourArmy = creatures;
for (std::map<si32,std::pair<ui32,si32> >::const_iterator i = ourArmy.slots.begin(); i != ourArmy.slots.end(); i++)
for(TSlots::const_iterator i = ourArmy.slots.begin(); i != ourArmy.slots.end(); i++)
{ //build list of joined creatures
iw.components.push_back (Component(Component::CREATURE, i->second.first, i->second.second, 0));
iw.components.push_back(Component(i->second));
loot << "%s";
if (i->second.second == 1)
loot.addReplacement (MetaString::CRE_SING_NAMES, i->second.first);
else
loot.addReplacement (MetaString::CRE_PL_NAMES, i->second.first);
loot.addReplacement(i->second);
}
if (ourArmy.slots.size() == 1 && ourArmy.slots.begin()->second.second == 1)
if (ourArmy.slots.size() == 1 && ourArmy.slots.begin()->second.count == 1)
iw.text.addTxt (MetaString::ADVOB_TXT, 185);
else
iw.text.addTxt (MetaString::ADVOB_TXT, 186);
@ -5063,23 +5038,19 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
CCreatureSet ourArmy;
for (std::vector< std::pair <ui16, ui32> >::const_iterator it = bc->creatures.begin(); it != bc->creatures.end(); it++)
{
int slot = ourArmy.getSlotFor (it->first);
ourArmy.slots[slot].first = it->first;
ourArmy.slots[slot].second += it->second;
int slot = ourArmy.getSlotFor(it->first);
ourArmy.addToSlot(slot, it->first, it->second);
}
for (std::map<si32,std::pair<ui32,si32> >::const_iterator i = ourArmy.slots.begin(); i != ourArmy.slots.end(); i++)
for (TSlots::const_iterator i = ourArmy.slots.begin(); i != ourArmy.slots.end(); i++)
{
iw.components.push_back (Component(Component::CREATURE, i->second.first, i->second.second, 0));
iw.components.push_back(Component(i->second));
loot << "%s";
if (i->second.second == 1)
loot.addReplacement (MetaString::CRE_SING_NAMES, i->second.first);
else
loot.addReplacement (MetaString::CRE_PL_NAMES, i->second.first);
loot.addReplacement (i->second);
}
if (ourArmy.slots.size())
{
if (ourArmy.slots.size() == 1 && ourArmy.slots.begin()->second.second == 1)
if (ourArmy.slots.size() == 1 && ourArmy.slots.begin()->second.count == 1)
iw.text.addTxt (MetaString::ADVOB_TXT, 185);
else
iw.text.addTxt (MetaString::ADVOB_TXT, 186);
@ -5351,13 +5322,13 @@ void CGSirens::onHeroVisit( const CGHeroInstance * h ) const
int xp = 0;
SetGarrisons sg;
sg.garrs[h->id] = h->army;
for (std::map<si32,std::pair<ui32,si32> >::const_iterator i = h->army.slots.begin(); i != h->army.slots.end(); i++)
for (TSlots::const_iterator i = h->army.slots.begin(); i != h->army.slots.end(); i++)
{
int drown = (int)(i->second.second * 0.3);
int drown = (int)(i->second.count * 0.3);
if(drown)
{
sg.garrs[h->id].slots[i->first].second -= drown;
xp += drown * VLC->creh->creatures[i->second.first].hitPoints;
sg.garrs[h->id].slots[i->first].count -= drown;
xp += drown * i->second.type->hitPoints;
}
}

View File

@ -341,8 +341,8 @@ public:
int getTotalStrength() const;
ui8 getSpellSchoolLevel(const CSpell * spell) const; //returns level on which given spell would be cast by this hero (0 - none, 1 - basic etc)
bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
std::pair<ui32, si32> calculateNecromancy (const BattleResult &battleResult) const;
void showNecromancyDialog (std::pair<ui32, si32> raisedStack) const;
CStackInstance calculateNecromancy (const BattleResult &battleResult) const;
void showNecromancyDialog(const CStackInstance &raisedStack) const;
//////////////////////////////////////////////////////////////////////////

120
int3.h
View File

@ -1,8 +1,6 @@
#ifndef __INT3_H__
#define __INT3_H__
#include <map>
#include <vector>
#include <cmath>
/*
* int3.h, part of VCMI engine
@ -14,122 +12,6 @@
*
*/
class CCreature;
//a few typedefs for CCreatureSet
typedef si32 TSlot, TQuantity;
typedef ui32 TCreature;
typedef std::pair<TCreature, TQuantity> TStack;
typedef std::map<TSlot, TStack> TSlots;
class CCreatureSet //seven combined creatures
{
public:
TSlots slots; //slots[slot_id]=> pair(creature_id,creature_quantity)
ui8 formation; //false - wide, true - tight
int getCreature (TSlot slot) const //workaround of map issue
{
std::map<TSlot, TStack>::const_iterator i = slots.find(slot);
if (i != slots.end())
return i->second.first;
else
return -1;
}
int getAmount (TSlot slot) const
{
std::map<TSlot, TStack>::const_iterator i = slots.find(slot);
if (i != slots.end())
return i->second.second;
else
return -1;
}
const TStack* getStack (TSlot slot) const
{
std::map<TSlot, TStack>::const_iterator i = slots.find(slot);
if (i != slots.end())
return &(i->second);
else
return NULL;
}
bool setCreature (TSlot slot, TCreature type, TQuantity quantity) //slots 0 to 6
{
slots[slot] = TStack(type, quantity); //brutal force
if (quantity == 0)
slots.erase(slot);
if (slots.size() > 7) return false;
else return true;
}
TSlot getSlotFor(TCreature creature, ui32 slotsAmount=7) const //returns -1 if no slot available
{
for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
{
if(i->second.first == creature)
{
return i->first; //if there is already such creature we return its slot id
}
}
for(ui32 i=0; i<slotsAmount; i++)
{
if(slots.find(i) == slots.end())
{
return i; //return first free slot
}
}
return -1; //no slot available
}
bool mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable = -1) //looks for two same stacks, returns slot positions
{
//try to match creature to our preferred stack
if(preferable >= 0 && slots.find(preferable) != slots.end())
{
TCreature id = slots[preferable].first;
for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
{
if(id == j->second.first && j->first != preferable)
{
out.first = preferable;
out.second = j->first;
return true;
}
}
}
for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
{
for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
{
if(i->second.first == j->second.first && i->first != j->first)
{
out.first = i->first;
out.second = j->first;
return true;
}
}
}
return false;
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & slots & formation;
}
operator bool() const
{
return slots.size() > 0;
}
void sweep()
{
for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i)
{
if(!i->second.second)
{
slots.erase(i);
sweep();
break;
}
}
}
};
class int3
{

View File

@ -322,6 +322,17 @@ DLL_EXPORT std::string MetaString::buildList () const
return lista;
}
void MetaString::addReplacement(const CStackInstance &stack)
{
assert(stack.count); //valid count
assert(stack.type); //valid type
if (stack.count == 1)
addReplacement (CRE_SING_NAMES, stack.type->idNumber);
else
addReplacement (CRE_PL_NAMES, stack.type->idNumber);
}
static CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
{
CGObjectInstance * nobj;
@ -1125,14 +1136,16 @@ std::pair<int,int> CGameState::pickObject (CGObjectInstance *obj)
void randomizeArmy(CArmedInstance * army, int type)
{
int max = VLC->creh->creatures.size();
for (std::map<si32,std::pair<ui32,si32> >::iterator j=army->army.slots.begin(); j!=army->army.slots.end();j++)
for (TSlots::iterator j=army->army.slots.begin(); j!=army->army.slots.end();j++)
{
if(j->second.first > max)
if(j->second.idRand > max)
{
if(j->second.first % 2)
j->second.first = VLC->townh->towns[type].basicCreatures[ (j->second.first-197) / 2 -1];
if(j->second.idRand % 2)
j->second.setType(VLC->townh->towns[type].basicCreatures[(j->second.idRand-197) / 2 -1]);
else
j->second.first = VLC->townh->towns[type].upgradedCreatures[ (j->second.first-197) / 2 -1];
j->second.setType(VLC->townh->towns[type].upgradedCreatures[(j->second.idRand-197) / 2 -1]);
j->second.idRand = -1;
}
}
return;
@ -1743,7 +1756,7 @@ const CGHeroInstance * CGameState::battleGetOwner(int stackID)
UpgradeInfo CGameState::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
{
UpgradeInfo ret;
const CCreature *base = &VLC->creh->creatures[obj->army.slots.find(stackPos)->second.first];
const CCreature *base = obj->army.slots.find(stackPos)->second.type;
if((obj->ID == TOWNI_TYPE) || ((obj->ID == HEROI_TYPE) && static_cast<const CGHeroInstance*>(obj)->visitedTown))
{
const CGTownInstance * t;
@ -2574,8 +2587,8 @@ std::pair<ui32, ui32> BattleInfo::calculateDmgRange(const CStack* attacker, cons
}
//damage cannot be less than 1
amin(returnedVal.first, 1);
amin(returnedVal.second, 1);
amax(returnedVal.first, 1);
amax(returnedVal.second, 1);
return returnedVal;
}
@ -2999,8 +3012,8 @@ int CGameState::victoryCheck( ui8 player ) const
&& (ai = dynamic_cast<const CArmedInstance*>(map->objects[i]))) //contains army
{
for(TSlots::const_iterator i=ai->army.slots.begin(); i!=ai->army.slots.end(); ++i) //iterate through army
if(i->second.first == map->victoryCondition.ID) //it's searched creature
total += i->second.second;
if(i->second.type->idNumber == map->victoryCondition.ID) //it's searched creature
total += i->second.count;
}
}
@ -3292,7 +3305,7 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
{
for(TSlots::const_iterator it = g->second.heroes[b]->army.slots.begin(); it != g->second.heroes[b]->army.slots.end(); ++it)
{
int toCmp = it->second.first; //ID of creature we should compare with the best one
int toCmp = it->second.type->idNumber; //ID of creature we should compare with the best one
if(bestCre == -1 || VLC->creh->creatures[bestCre].AIValue < VLC->creh->creatures[toCmp].AIValue)
{
bestCre = toCmp;
@ -3755,9 +3768,9 @@ void InfoAboutHero::initFromHero( const CGHeroInstance *h, bool detailed )
else
{
//hide info about hero stacks counts using descriptives names ids
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army.slots.begin(); i != army.slots.end(); ++i)
for(TSlots::iterator i = army.slots.begin(); i != army.slots.end(); ++i)
{
i->second.second = CCreature::getQuantityID(i->second.second);
i->second.count = i->second.getQuantityID();
}
}
}

View File

@ -123,6 +123,7 @@ public:
message.push_back(TREPLACE_NUMBER);
numbers.push_back(txt);
}
DLL_EXPORT void addReplacement(const CStackInstance &stack); //adds sing or plural name;
DLL_EXPORT std::string buildList () const;
void clear()
{
@ -679,8 +680,16 @@ struct Component : public CPack //2002 helper for object scrips informations
{
h & id & subtype & val & when;
}
Component(){type = 2002;};
Component(ui16 Type, ui16 Subtype, si32 Val, si16 When):id(Type),subtype(Subtype),val(Val),when(When){type = 2002;};
Component()
{
type = 2002;
}
DLL_EXPORT explicit Component(const CStackInstance &stack);
Component(ui16 Type, ui16 Subtype, si32 Val, si16 When)
:id(Type),subtype(Subtype),val(Val),when(When)
{
type = 2002;
}
};
struct InfoWindow : public CPackForClient //103 - displays simple info window

View File

@ -172,7 +172,7 @@ DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs )
if(h && flags & 1)
{
h->army.slots.clear();
h->army.slots[0] = std::pair<ui32,si32>(VLC->creh->nameToID[h->type->refTypeStack[0]],1);
h->army.slots[0] = CStackInstance(VLC->creh->nameToID[h->type->refTypeStack[0]],1);
}
h = (hid2>=0 ? gs->hpool.heroesPool[hid2] : NULL);
@ -180,7 +180,7 @@ DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs )
if(flags & 2)
{
h->army.slots.clear();
h->army.slots[0] = std::pair<ui32,si32>(VLC->creh->nameToID[h->type->refTypeStack[0]],1);
h->army.slots[0] = CStackInstance(VLC->creh->nameToID[h->type->refTypeStack[0]],1);
}
}
@ -1221,4 +1221,10 @@ DLL_EXPORT void YourTurn::applyGs( CGameState *gs )
DLL_EXPORT void SetSelection::applyGs( CGameState *gs )
{
gs->getPlayer(player)->currentSelection = id;
}
DLL_EXPORT Component::Component(const CStackInstance &stack)
:id(CREATURE), subtype(stack.type->idNumber), val(stack.count), when(0)
{
}

View File

@ -143,42 +143,32 @@ static EDefType getDefType(CGDefInfo * a)
static CCreatureSet readCreatureSet(const unsigned char * bufor, int &i, int number, bool version) //version==true for >RoE maps
{
if(version)
const int bytesPerCre = version ? 4 : 3,
idBytes = version ? 2 : 1,
maxID = version ? 0xffff : 0xff;
CCreatureSet ret;
for(int ir=0;ir < number; ir++)
{
CCreatureSet ret;
std::pair<ui32,si32> ins;
for(int ir=0;ir<number;ir++)
int creID = readNormalNr(bufor,i+ir*bytesPerCre, idBytes);
int count = readNormalNr(bufor,i+ir*bytesPerCre+idBytes, 2);
if(creID == maxID) //empty slot
continue;
if(creID > maxID - 0xf)
{
int rettt = readNormalNr(bufor,i+ir*4, 2);
if(rettt==0xffff) continue;
if(rettt>65520)
rettt = 65536-rettt+VLC->creh->creatures.size();//this will happens when random object has random army
ins.first = rettt;
ins.second = readNormalNr(bufor,i+ir*4+2, 2);
std::pair<si32,std::pair<ui32,si32> > tt(ir,ins);
ret.slots.insert(tt);
creID = maxID + 1 - creID + VLC->creh->creatures.size();//this will happen when random object has random army
ret.slots[ir].idRand = creID;
}
i+=number*4;
return ret;
}
else
{
CCreatureSet ret;
std::pair<ui32,si32> ins;
for(int ir=0;ir<number;ir++)
{
int rettt = readNormalNr(bufor,i+ir*3, 1);
if(rettt==0xff) continue;
if(rettt>240)
rettt = 256-rettt+VLC->creh->creatures.size();
ins.first = rettt;
ins.second = readNormalNr(bufor,i+ir*3+1, 2);
std::pair<si32,std::pair<ui32,si32> > tt(ir,ins);
ret.slots.insert(tt);
}
i+=number*3;
return ret;
else
ret.slots[ir].setType(creID);
ret.slots[ir].count = count;
}
i+=number*bytesPerCre;
ret.validTypes(true);
return ret;
}
CMapHeader::CMapHeader(const unsigned char *map)
{
@ -900,6 +890,7 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
}
if(readChar(bufor,i))//true if hero has nonstandard garrison
nhi->army = readCreatureSet(bufor,i,7,(version>RoE));
nhi->army.formation =bufor[i]; ++i; //formation
bool artSet = bufor[i]; ++i; //true if artifact set is not default (hero has some artifacts)
int artmask = version == RoE ? 0xff : 0xffff;
@ -1494,7 +1485,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
cre->identifier = readNormalNr(bufor,i); i+=4;
monsters[cre->identifier] = cre;
}
cre->army.slots[0].second = readNormalNr(bufor,i, 2); i+=2;
cre->army.slots[0].count = readNormalNr(bufor,i, 2); i+=2;
cre->character = bufor[i]; ++i;
bool isMesTre = bufor[i]; ++i; //true if there is message or treasury
if(isMesTre)
@ -2046,7 +2037,7 @@ void Mapa::loadQuest(CQuest * guard, const unsigned char * bufor, int & i)
{
ui32 creType = readNormalNr(bufor,i, 2); i+=2;
ui32 creNumb = readNormalNr(bufor,i, 2); i+=2;
guard->m6creatures[hh] = std::make_pair(creType,creNumb);
guard->m6creatures[hh] = CStackInstance(creType,creNumb);
}
break;
}

View File

@ -309,10 +309,10 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf
continue;
CStack *st = bat->stacks[i];
if(st->owner==color && vstd::contains(set.slots,st->slot) && st->amount < set.slots.find(st->slot)->second.second)
if(st->owner==color && vstd::contains(set.slots,st->slot) && st->amount < set.slots.find(st->slot)->second.count)
{
if(st->alive())
ret.slots[st->slot].second = st->amount;
ret.slots[st->slot].count = st->amount;
else
ret.slots.erase(st->slot);
}
@ -577,12 +577,12 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
const CGHeroInstance *winnerHero = battleResult.data->winner != 0 ? hero2 : hero1;
if (winnerHero)
{
std::pair<ui32, si32> raisedStack = winnerHero->calculateNecromancy(*battleResult.data);
CStackInstance raisedStack = winnerHero->calculateNecromancy(*battleResult.data);
// Give raised units to winner and show dialog, if any were raised.
if (raisedStack.first != -1)
if (raisedStack.type)
{
int slot = winnerHero->army.getSlotFor(raisedStack.first);
int slot = winnerHero->army.getSlotFor(raisedStack.type->idNumber);
if (slot != -1)
{
@ -590,7 +590,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
sg.garrs[winnerHero->id] = winnerHero->army;
if (vstd::contains(winnerHero->army.slots, slot)) // Add to existing stack.
sg.garrs[winnerHero->id].slots[slot].second += raisedStack.second;
sg.garrs[winnerHero->id].slots[slot].count += raisedStack.count;
else // Create a new stack.
sg.garrs[winnerHero->id].slots[slot] = raisedStack;
winnerHero->showNecromancyDialog(raisedStack);
@ -1039,8 +1039,6 @@ void CGameHandler::run(bool resume)
{
if(!resume)
newTurn();
else
resume = false;
std::map<ui8,PlayerState>::iterator i;
if(!resume)
@ -1048,6 +1046,7 @@ void CGameHandler::run(bool resume)
else
i = gs->players.find(gs->currentPlayer);
resume = false;
for(; i != gs->players.end(); i++)
{
@ -1059,12 +1058,11 @@ void CGameHandler::run(bool resume)
continue;
}
states.setFlag(i->first,&PlayerStatus::makingTurn,true);
gs->currentPlayer = i->first;
{
YourTurn yt;
yt.player = i->first;
boost::unique_lock<boost::mutex> lock(*connections[i->first]->wmx);
*connections[i->first] << &yt;
sendAndApply(&yt);
}
//wait till turn is done
@ -1151,7 +1149,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
//battleStartpos read
int k = 0; //stack serial
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++, k++)
for(TSlots::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++, k++)
{
int pos;
if(creatureBank)
@ -1161,12 +1159,12 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
else
pos = attackerLoose[army1.slots.size()-1][k];
CStack * stack = curB->generateNewStack(hero1, i->second.first, i->second.second, stacks.size(), true, i->first, gs->map->terrain[tile.x][tile.y][tile.z].tertype, pos);
CStack * stack = curB->generateNewStack(hero1, i->second.type->idNumber, i->second.count, stacks.size(), true, i->first, gs->map->terrain[tile.x][tile.y][tile.z].tertype, pos);
stacks.push_back(stack);
}
k = 0;
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++, k++)
for(TSlots::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++, k++)
{
int pos;
if(creatureBank)
@ -1176,7 +1174,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
else
pos = defenderLoose[army2.slots.size()-1][k];
CStack * stack = curB->generateNewStack(hero2, i->second.first, i->second.second, stacks.size(), false, i->first, gs->map->terrain[tile.x][tile.y][tile.z].tertype, pos);
CStack * stack = curB->generateNewStack(hero2, i->second.type->idNumber, i->second.count, stacks.size(), false, i->first, gs->map->terrain[tile.x][tile.y][tile.z].tertype, pos);
stacks.push_back(stack);
}
@ -1778,11 +1776,10 @@ void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, CCreature
CCreatureSet heroArmy = h->army;
while (creatures.slots.size() > 0)
{
int slot = heroArmy.getSlotFor (creatures.slots.begin()->second.first);
int slot = heroArmy.getSlotFor(creatures.slots.begin()->second.type->idNumber);
if (slot < 0)
break;
heroArmy.slots[slot].first = creatures.slots.begin()->second.first;
heroArmy.slots[slot].second += creatures.slots.begin()->second.second;
heroArmy.addToSlot(slot, creatures.slots.begin()->second);
creatures.slots.erase (creatures.slots.begin());
}
@ -1809,11 +1806,12 @@ void CGameHandler::takeCreatures (int objid, TSlots creatures) //probably we cou
CCreatureSet newArmy = obj->army;
while (creatures.size() > 0)
{
int slot = newArmy.getSlotFor (creatures.begin()->second.first);
int slot = newArmy.getSlotFor(creatures.begin()->second.type->idNumber);
if (slot < 0)
break;
newArmy.slots[slot].first = creatures.begin()->second.first;
newArmy.slots[slot].second -= creatures.begin()->second.second;
newArmy.slots[slot].type = creatures.begin()->second.type;
newArmy.slots[slot].count -= creatures.begin()->second.count;
creatures.erase (creatures.begin());
}
SetGarrisons sg;
@ -2242,20 +2240,20 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
std::swap(S1.slots[p1],S2.slots[p2]); //swap slots
//if one of them is empty, remove entry
if(!S1.slots[p1].second)
if(!S1.slots[p1].count)
S1.slots.erase(p1);
if(!S2.slots[p2].second)
if(!S2.slots[p2].count)
S2.slots.erase(p2);
}
else if(what==2)//merge
{
if(S1.slots[p1].first != S2.slots[p2].first) //not same creature
if(S1.slots[p1].type != S2.slots[p2].type) //not same creature
{
complain("Cannot merge different creatures stacks!");
return false;
}
S2.slots[p2].second += S1.slots[p1].second;
S2.slots[p2].count += S1.slots[p1].count;
S1.slots.erase(p1);
}
else if(what==3) //split
@ -2270,30 +2268,30 @@ bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2,
if(vstd::contains(S2.slots,p2)) //dest. slot not free - it must be "rebalancing"...
{
int total = S1.slots[p1].second + S2.slots[p2].second;
int total = S1.slots[p1].count + S2.slots[p2].count;
if( (total < val && complain("Cannot split that stack, not enough creatures!"))
|| (S2.slots[p2].first != S1.slots[p1].first && complain("Cannot rebalance different creatures stacks!"))
|| (S2.slots[p2].type != S1.slots[p1].type && complain("Cannot rebalance different creatures stacks!"))
)
{
return false;
}
S2.slots[p2].second = val;
S1.slots[p1].second = total - val;
S2.slots[p2].count = val;
S1.slots[p1].count = total - val;
}
else //split one stack to the two
{
if(S1.slots[p1].second < val)//not enough creatures
if(S1.slots[p1].count < val)//not enough creatures
{
complain("Cannot split that stack, not enough creatures!");
return false;
}
S2.slots[p2].first = S1.slots[p1].first;
S2.slots[p2].second = val;
S1.slots[p1].second -= val;
S2.slots[p2].type = S1.slots[p1].type;
S2.slots[p2].count = val;
S1.slots[p1].count -= val;
}
if(!S1.slots[p1].second) //if we've moved all creatures
if(!S1.slots[p1].count) //if we've moved all creatures
S1.slots.erase(p1);
}
if((s1->needsLastStack() && !S1.slots.size()) //it's not allowed to take last stack from hero army!
@ -2519,14 +2517,8 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
SetGarrisons sg;
sg.garrs[dst->id] = dst->army;
if(sg.garrs[dst->id].slots.find(slot) == sg.garrs[dst->id].slots.end()) //take a free slot
{
sg.garrs[dst->id].slots[slot] = std::make_pair(crid,cram);
}
else //add creatures to a already existing stack
{
sg.garrs[dst->id].slots[slot].second += cram;
}
sg.garrs[dst->id] .addToSlot(slot, crid, cram);
sendAndApply(&sr);
sendAndApply(&sac);
sendAndApply(&sg);
@ -2538,7 +2530,7 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid]);
UpgradeInfo ui = gs->getUpgradeInfo(obj,pos);
int player = obj->tempOwner;
int crQuantity = obj->army.slots[pos].second;
int crQuantity = obj->army.slots[pos].count;
//check if upgrade is possible
if((ui.oldID<0 || !vstd::contains(ui.newID,upgID)) && complain("That upgrade is not possible!"))
@ -2575,7 +2567,7 @@ bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
//upgrade creature
SetGarrisons sg;
sg.garrs[objid] = obj->army;
sg.garrs[objid].slots[pos].first = upgID;
sg.garrs[objid].slots[pos].setType(upgID);
sendAndApply(&sg);
return true;
}
@ -2588,7 +2580,7 @@ bool CGameHandler::garrisonSwap( si32 tid )
CCreatureSet csn = town->visitingHero->army, cso = town->army;
while(!cso.slots.empty())//while there are unmoved creatures
{
int pos = csn.getSlotFor(cso.slots.begin()->second.first);
int pos = csn.getSlotFor(cso.slots.begin()->second.type->idNumber);
if(pos<0)
{
//try to merge two other stacks to make place
@ -2596,7 +2588,7 @@ bool CGameHandler::garrisonSwap( si32 tid )
if(csn.mergableStacks(toMerge, cso.slots.begin()->first))
{
//merge
csn.slots[toMerge.second].second += csn.slots[toMerge.first].second;
csn.slots[toMerge.second].count += csn.slots[toMerge.first].count;
csn.slots[toMerge.first] = cso.slots.begin()->second;
}
else
@ -2607,12 +2599,12 @@ bool CGameHandler::garrisonSwap( si32 tid )
}
else if(csn.slots.find(pos) != csn.slots.end()) //add creatures to the existing stack
{
csn.slots[pos].second += cso.slots.begin()->second.second;
csn.slots[pos].count += cso.slots.begin()->second.count;
}
else //move stack on the free pos
{
csn.slots[pos].first = cso.slots.begin()->second.first;
csn.slots[pos].second = cso.slots.begin()->second.second;
csn.slots[pos].type = cso.slots.begin()->second.type;
csn.slots[pos].count = cso.slots.begin()->second.count;
}
cso.slots.erase(cso.slots.begin());
}
@ -3350,7 +3342,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
sg.garrs[hero->id] = hero->army;
for(int i=0;i<7;i++)
if(!vstd::contains(sg.garrs[hero->id].slots,i))
sg.garrs[hero->id].slots[i] = std::pair<ui32,si32>(13,5);
sg.garrs[hero->id].slots[i] = CStackInstance(13,5);
sendAndApply(&sg);
}
else if(message == "vcmiangband") //gives 10 black knight into each slot
@ -3361,7 +3353,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
sg.garrs[hero->id] = hero->army;
for(int i=0;i<7;i++)
if(!vstd::contains(sg.garrs[hero->id].slots,i))
sg.garrs[hero->id].slots[i] = std::pair<ui32,si32>(66,10);
sg.garrs[hero->id].slots[i] = CStackInstance(66,10);
sendAndApply(&sg);
}
else if(message == "vcminoldor") //all war machines