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:
parent
be42b7ff62
commit
993036e4a1
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
3
global.h
3
global.h
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
120
int3.h
@ -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
|
||||
{
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
59
lib/map.cpp
59
lib/map.cpp
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user