1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

Various fixes and improvements around kill hero and kill monster quests. A few minor unrelated fixes.

This commit is contained in:
Michał W. Urbańczyk 2011-02-11 12:27:38 +00:00
parent c0f2b3f32b
commit ab20e024c0
12 changed files with 149 additions and 100 deletions

View File

@ -2386,6 +2386,12 @@ void CBattleInterface::hexLclicked(int whichOne)
{
const CStack * actSt = activeStack;
const CStack* dest = curInt->cb->battleGetStackByPos(whichOne); //creature at destination tile; -1 if there is no one
if(!actSt)
{
tlog3 << "Hex l-clicked when no active stack!\n";
return;
}
if( ((whichOne%BFIELD_WIDTH)!=0 && (whichOne%BFIELD_WIDTH)!=(BFIELD_WIDTH-1)) //if player is trying to attack enemey unit or move creature stack
|| (actSt->hasBonusOfType(Bonus::CATAPULT) && !spellDestSelectMode || dest ) //enemy's first aid tent can stand there and we want to shoot it
)

View File

@ -850,7 +850,7 @@ ui32 BattleInfo::calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const C
else if(sp->earth)
ret *= (100.0f + caster->valOfBonuses(Bonus::EARTH_SPELL_DMG_PREMY)) / 100.0f;
if (affectedCreature) //Hero specials like Solmyr, Deemer
if (affectedCreature && affectedCreature->getCreature()->level) //Hero specials like Solmyr, Deemer
ret *= (100.f + ((caster->valOfBonuses(Bonus::SPECIAL_SPELL_LEV, sp->id) * caster->level) / affectedCreature->getCreature()->level)) / 100.0f;
}
return ret;

View File

@ -486,6 +486,7 @@ void CCreatureHandler::loadCreatures()
if(!ifs.good())
break;
CCreature *c = creatures[id];
c->level = lvl;
if(isbetw(lvl, 0, ARRAY_COUNT(creaturesOfLevel)))
c->attachTo(&creaturesOfLevel[lvl]);
else

View File

@ -337,7 +337,7 @@ void MetaString::addReplacement(const CStackBasicDescriptor &stack)
{
assert(stack.count); //valid count
assert(stack.type); //valid type
addReplacement(stack.type->idNumber, stack.count);
addCreReplacement(stack.type->idNumber, stack.count);
}
static CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)

View File

@ -1116,6 +1116,7 @@ void CGHeroInstance::initObj()
UpdateSpeciality();
mana = manaLimit(); //after all bonuses are taken into account, make sure this line is the last one
type->name = name;
}
void CGHeroInstance::UpdateSpeciality()
{
@ -3871,12 +3872,10 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
{
case MISSION_NONE:
return true;
break;
case MISSION_LEVEL:
if (m13489val <= h->level)
return true;
return false;
break;
case MISSION_PRIMARY_STAT:
for (int i = 0; i < 4; ++i)
{
@ -3884,17 +3883,11 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
return false;
}
return true;
break;
case MISSION_KILL_HERO:
if (h->cb->gameState()->map->heroesToBeat[m13489val]->tempOwner < PLAYER_LIMIT)
return false; //if the pointer is not NULL
return true;
break;
case MISSION_KILL_CREATURE:
if (h->cb->gameState()->map->monsters[m13489val]->pos == int3(-1,-1,-1))
if (!h->cb->getObjByQuestIdentifier(m13489val))
return true;
return false;
break;
case MISSION_ART:
for (int i = 0; i < m5arts.size(); ++i)
{
@ -3903,7 +3896,6 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
return false; //if the artifact was not found
}
return true;
break;
case MISSION_ARMY:
{
std::vector<CStackBasicDescriptor>::const_iterator cre;
@ -3921,7 +3913,6 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
}
}
return true;
break;
case MISSION_RESOURCES:
for (int i = 0; i < 7; ++i) //including Mithril ?
{ //Quest has no direct access to callback
@ -3929,17 +3920,14 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
return false;
}
return true;
break;
case MISSION_HERO:
if (m13489val == h->type->ID)
return true;
return false;
break;
case MISSION_PLAYER:
if (m13489val == h->getOwner())
return true;
return false;
break;
default:
return false;
}
@ -3958,6 +3946,17 @@ void CGSeerHut::initObj()
nextVisitText = VLC->generaltexth->quests[missionType-1][1][textOption];
completedText = VLC->generaltexth->quests[missionType-1][2][textOption];
}
if(missionType == MISSION_KILL_CREATURE)
{
stackToKill = getCreatureToKill(false)->getStack(0);
stackDirection = checkDirection();
}
else if(missionType == MISSION_KILL_HERO)
{
heroName = getHeroToKill(false)->name;
heroPortrait = getHeroToKill(false)->portrait;
}
}
else
firstVisitText = VLC->generaltexth->seerEmpty[textOption];
@ -3989,30 +3988,25 @@ const std::string & CGSeerHut::getHoverText() const
ms.addReplacement(m13489val);
break;
case MISSION_PRIMARY_STAT:
{
MetaString loot;
for (int i = 0; i < 4; ++i)
{
if (m2stats[i])
MetaString loot;
for (int i = 0; i < 4; ++i)
{
loot << "%d %s";
loot.addReplacement(m2stats[i]);
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
}
if (m2stats[i])
{
loot << "%d %s";
loot.addReplacement(m2stats[i]);
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
}
}
ms.addReplacement(loot.buildList());
}
ms.addReplacement(loot.buildList());
}
break;
case MISSION_KILL_HERO:
ms.addReplacement(cb->gameState()->map->heroesToBeat[m13489val]->name);
break;
case MISSION_HERO:
ms.addReplacement(VLC->heroh->heroes[m13489val]->name);
ms.addReplacement(heroName);
break;
case MISSION_KILL_CREATURE:
{
ms.addReplacement(cb->gameState()->map->monsters[m13489val]->getStack(0));
}
ms.addReplacement(stackToKill);
break;
case MISSION_ART:
{
@ -4051,6 +4045,9 @@ const std::string & CGSeerHut::getHoverText() const
ms.addReplacement(loot.buildList());
}
break;
case MISSION_HERO:
ms.addReplacement(VLC->heroh->heroes[m13489val]->name);
break;
case MISSION_PLAYER:
ms.addReplacement(VLC->generaltexth->colors[m13489val]);
break;
@ -4096,7 +4093,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
switch (missionType)
{
case MISSION_LEVEL:
iw.components.push_back (Component (Component::EXPERIENCE, 1, m13489val, 0));
iw.components.push_back(Component (Component::EXPERIENCE, 1, m13489val, 0));
if (!isCustom)
iw.text.addReplacement(m13489val);
break;
@ -4107,7 +4104,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
{
if (m2stats[i])
{
iw.components.push_back (Component (Component::PRIM_SKILL, i, m2stats[i], 0));
iw.components.push_back(Component (Component::PRIM_SKILL, i, m2stats[i], 0));
loot << "%d %s";
loot.addReplacement(m2stats[i]);
loot.addReplacement(VLC->generaltexth->primarySkillNames[i]);
@ -4118,28 +4115,20 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
}
break;
case MISSION_KILL_HERO:
iw.components.push_back (Component (Component::HERO,
cb->gameState()->map->heroesToBeat[m13489val]->type->ID, 0, 0));
iw.components.push_back(Component(Component::HERO, heroPortrait, 0, 0));
if (!isCustom)
iw.text.addReplacement(cb->gameState()->map->heroesToBeat[m13489val]->name);
addReplacements(iw.text, firstVisitText);
break;
case MISSION_HERO:
iw.components.push_back (Component (Component::HERO, m13489val, 0, 0));
iw.components.push_back(Component (Component::HERO, m13489val, 0, 0));
if (!isCustom)
iw.text.addReplacement(VLC->heroh->heroes[m13489val]->name);
break;
case MISSION_KILL_CREATURE:
{
CStackInstance stack = cb->gameState()->map->monsters[m13489val]->getStack(0);
iw.components.push_back (Component(stack));
iw.components.push_back(Component(stackToKill));
if (!isCustom)
{
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()]);
}
}
addReplacements(iw.text, firstVisitText);
}
break;
case MISSION_ART:
@ -4147,12 +4136,12 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
MetaString loot;
for (std::vector<ui16>::const_iterator it = m5arts.begin(); it != m5arts.end(); ++it)
{
iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
iw.components.push_back(Component (Component::ARTIFACT, *it, 0, 0));
loot << "%s";
loot.addReplacement(MetaString::ART_NAMES, *it);
}
if (!isCustom)
iw.text.addReplacement (loot.buildList());
iw.text.addReplacement(loot.buildList());
}
break;
case MISSION_ARMY:
@ -4165,7 +4154,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
loot.addReplacement(*it);
}
if (!isCustom)
iw.text.addReplacement (loot.buildList());
iw.text.addReplacement(loot.buildList());
}
break;
case MISSION_RESOURCES:
@ -4175,20 +4164,20 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
{
if (m7resources[i])
{
iw.components.push_back (Component (Component::RESOURCE, i, m7resources[i], 0));
iw.components.push_back(Component (Component::RESOURCE, i, m7resources[i], 0));
loot << "%d %s";
loot.addReplacement(m7resources[i]);
loot.addReplacement(MetaString::RES_NAMES, i);
}
}
if (!isCustom)
iw.text.addReplacement (loot.buildList());
iw.text.addReplacement(loot.buildList());
}
break;
case MISSION_PLAYER:
iw.components.push_back (Component (Component::FLAG, m13489val, 0, 0));
iw.components.push_back(Component (Component::FLAG, m13489val, 0, 0));
if (!isCustom)
iw.text.addReplacement (VLC->generaltexth->colors[m13489val]);
iw.text.addReplacement(VLC->generaltexth->colors[m13489val]);
break;
}
cb->setObjProperty (id,10,1);
@ -4197,6 +4186,8 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
else if (!checkQuest(h))
{
iw.text << nextVisitText;
if(!isCustom)
addReplacements(iw.text, nextVisitText);
cb->showInfoDialog(&iw);
}
if (checkQuest(h)) // propose completion, also on first visit
@ -4269,23 +4260,14 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
}
break;
case MISSION_KILL_HERO:
case MISSION_KILL_CREATURE:
if (!isCustom)
bd.text.addReplacement(cb->gameState()->map->heroesToBeat[m13489val]->name);
addReplacements(bd.text, completedText);
break;
case MISSION_HERO:
if (!isCustom)
bd.text.addReplacement(VLC->heroh->heroes[m13489val]->name);
break;
case MISSION_KILL_CREATURE:
{
{
bd.text.addReplacement(cb->gameState()->map->monsters[m13489val]->getArmy()[0]);
if (std::count(firstVisitText.begin(), firstVisitText.end(), '%') == 2) //say where is placed monster
{
bd.text.addReplacement(VLC->generaltexth->arraytxt[147+checkDirection()]);
}
}
}
case MISSION_PLAYER:
if (!isCustom)
bd.text.addReplacement(VLC->generaltexth->colors[m13489val]);
@ -4294,25 +4276,25 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
switch (rewardType)
{
case 1: bd.components.push_back (Component (Component::EXPERIENCE, 0, rVal*(100+h->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0f, 0));
case 1: bd.components.push_back(Component (Component::EXPERIENCE, 0, rVal*(100+h->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0f, 0));
break;
case 2: bd.components.push_back (Component (Component::PRIM_SKILL, 5, rVal, 0));
case 2: bd.components.push_back(Component (Component::PRIM_SKILL, 5, rVal, 0));
break;
case 3: bd.components.push_back (Component (Component::MORALE, 0, rVal, 0));
case 3: bd.components.push_back(Component (Component::MORALE, 0, rVal, 0));
break;
case 4: bd.components.push_back (Component (Component::LUCK, 0, rVal, 0));
case 4: bd.components.push_back(Component (Component::LUCK, 0, rVal, 0));
break;
case 5: bd.components.push_back (Component (Component::RESOURCE, rID, rVal, 0));
case 5: bd.components.push_back(Component (Component::RESOURCE, rID, rVal, 0));
break;
case 6: bd.components.push_back (Component (Component::PRIM_SKILL, rID, rVal, 0));
case 6: bd.components.push_back(Component (Component::PRIM_SKILL, rID, rVal, 0));
break;
case 7: bd.components.push_back (Component (Component::SEC_SKILL, rID, rVal, 0));
case 7: bd.components.push_back(Component (Component::SEC_SKILL, rID, rVal, 0));
break;
case 8: bd.components.push_back (Component (Component::ARTIFACT, rID, 0, 0));
case 8: bd.components.push_back(Component (Component::ARTIFACT, rID, 0, 0));
break;
case 9: bd.components.push_back (Component (Component::SPELL, rID, 0, 0));
case 9: bd.components.push_back(Component (Component::SPELL, rID, 0, 0));
break;
case 10: bd.components.push_back (Component (Component::CREATURE, rID, rVal, 0));
case 10: bd.components.push_back(Component (Component::CREATURE, rID, rVal, 0));
break;
}
@ -4330,7 +4312,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
}
int CGSeerHut::checkDirection() const
{
int3 cord = cb->gameState()->map->monsters[m13489val]->pos;
int3 cord = getCreatureToKill()->pos;
if ((double)cord.x/(double)cb->getMapSize().x < 0.34) //north
{
if ((double)cord.y/(double)cb->getMapSize().y < 0.34) //northwest
@ -4443,6 +4425,41 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
}
}
const CGHeroInstance * CGSeerHut::getHeroToKill(bool allowNull) const
{
const CGObjectInstance *o = cb->getObjByQuestIdentifier(m13489val);
if(allowNull && !o)
return NULL;
assert(o && o->ID == HEROI_TYPE);
return static_cast<const CGHeroInstance*>(o);
}
const CGCreature * CGSeerHut::getCreatureToKill(bool allowNull) const
{
const CGObjectInstance *o = cb->getObjByQuestIdentifier(m13489val);
if(allowNull && !o)
return NULL;
assert(o && o->ID == 54);
return static_cast<const CGCreature*>(o);
}
void CGSeerHut::addReplacements(MetaString &out, const std::string &base) const
{
switch(missionType)
{
case MISSION_KILL_CREATURE:
out.addReplacement(stackToKill);
if (std::count(base.begin(), base.end(), '%') == 2) //say where is placed monster
{
out.addReplacement(VLC->generaltexth->arraytxt[147+stackDirection]);
}
break;
case MISSION_KILL_HERO:
out.addReplacement(heroName);
break;
}
}
void CGQuestGuard::initObj()
{
blockVisit = true;

View File

@ -309,7 +309,7 @@ public:
//////////////////////////////////////////////////////////////////////////
const CHero * type;
ConstTransitivePtr<CHero> type;
ui64 exp; //experience points
si32 level; //current level of hero
std::string name; //may be custom
@ -760,6 +760,14 @@ public:
ui8 textOption; //store randomized mission write-ups rather than entire string (?)
std::string seerName;
//following field are used only for kill creature/hero missions, the original objects became inaccessible after their removal, so we need to store info needed for messages / hover text
//TODO? organize
CStackBasicDescriptor stackToKill;
ui8 stackDirection;
std::string heroName; //backup of hero name
si32 heroPortrait;
void initObj();
const std::string & getHoverText() const;
void setPropertyDer (ui8 what, ui32 val);
@ -769,10 +777,16 @@ public:
void finishQuest (const CGHeroInstance * h, ui32 accept) const; //common for both objects
void completeQuest (const CGHeroInstance * h) const;
const CGHeroInstance *getHeroToKill(bool allowNull = false) const;
const CGCreature *getCreatureToKill(bool allowNull = false) const;
void addReplacements(MetaString &out, const std::string &base) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this) & static_cast<CQuest&>(*this);
h & rewardType & rID & rVal & textOption & seerName;
h & stackToKill & stackDirection & heroName & heroPortrait;
}
};

View File

@ -266,4 +266,10 @@ const PlayerState * IGameCallback::getPlayerState( int color )
const CTown * IGameCallback::getNativeTown(int color)
{
return &VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(color).castle];
}
const CGObjectInstance * IGameCallback::getObjByQuestIdentifier(int identifier)
{
assert(vstd::contains(gs->map->questIdentifierToId, identifier));
return getObj(gs->map->questIdentifierToId[identifier]);
}

View File

@ -56,6 +56,7 @@ public:
virtual const CGHeroInstance* getHero(int objid);
virtual const CGTownInstance* getTown(int objid);
virtual const CGHeroInstance* getSelectedHero(int player); //NULL if no hero is selected
virtual const CGObjectInstance *getObjByQuestIdentifier(int identifier); //NULL if object has been removed (eg. killed)
virtual int getCurrentPlayer()=0;
virtual int getSelectedHero()=0;
virtual const PlayerSettings * getPlayerSettings(int color);

View File

@ -243,11 +243,8 @@ DLL_EXPORT void RemoveObject::applyGs( CGameState *gs )
if(obj->ID==HEROI_TYPE)
{
CGHeroInstance *h = static_cast<CGHeroInstance*>(obj);
std::vector<ConstTransitivePtr<CGHeroInstance> >::iterator nitr = std::find(gs->map->heroes.begin(), gs->map->heroes.end(),h);
gs->map->heroes.erase(nitr);
int player = h->tempOwner;
nitr = std::find(gs->getPlayer(player)->heroes.begin(), gs->getPlayer(player)->heroes.end(), h);
gs->getPlayer(player)->heroes.erase(nitr);
gs->map->heroes -= h;
gs->getPlayer(h->tempOwner)->heroes -= h;
h->tempOwner = 255; //no one owns beaten hero
if(CGTownInstance *t = const_cast<CGTownInstance *>(h->visitedTown))
@ -264,13 +261,16 @@ DLL_EXPORT void RemoveObject::applyGs( CGameState *gs )
if(!vstd::contains(gs->hpool.pavailable, h->subID))
gs->hpool.pavailable[h->subID] = 0xff;
gs->map->objects[id] = NULL;
return;
}
else if (obj->ID==CREI_TYPE && gs->map->version > CMapHeader::RoE) //only fixed monsters can be a part of quest
{
CGCreature *cre = static_cast<CGCreature*>(obj);
gs->map->monsters[cre->identifier]->pos = int3 (-1,-1,-1); //use nonexistent monster for quest :>
}
// else if (obj->ID==CREI_TYPE && gs->map->version > CMapHeader::RoE) //only fixed monsters can be a part of quest
// {
// CGCreature *cre = static_cast<CGCreature*>(obj);
// gs->map->monsters[cre->identifier]->pos = int3 (-1,-1,-1); //use nonexistent monster for quest :>
// }
gs->map->objects[id].dellNull();
}

View File

@ -779,14 +779,15 @@ void Mapa::loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int
nt->garrisonHero = NULL;
}
CGObjectInstance * Mapa::loadHero(const unsigned char * bufor, int &i)
CGObjectInstance * Mapa::loadHero(const unsigned char * bufor, int &i, int idToBeGiven)
{
CGHeroInstance * nhi = new CGHeroInstance();
int identifier = 0;
if(version>RoE)
if(version > RoE)
{
identifier = readNormalNr(bufor,i, 4); i+=4;
questIdentifierToId[identifier] = idToBeGiven;
}
ui8 owner = bufor[i++];
@ -815,7 +816,6 @@ CGObjectInstance * Mapa::loadHero(const unsigned char * bufor, int &i)
break;
}
}
heroesToBeat[identifier] = nhi;
if(readChar(bufor,i))//true if hero has nonstandard name
nhi->name = readString(bufor,i);
if(version>AB)
@ -1224,6 +1224,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
pos.z = bufor[i++];
int defnum = readNormalNr(bufor,i, 4); i+=4;
int idToBeGiven = objects.size();
CGDefInfo * defInfo = defy[defnum];
i+=5;
@ -1306,7 +1307,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
}
case 34: case 70: case 62: //34 - hero; 70 - random hero; 62 - prison
{
nobj = loadHero(bufor, i);
nobj = loadHero(bufor, i, idToBeGiven);
break;
}
case 4: //Arena
@ -1358,7 +1359,8 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
if(version>RoE)
{
cre->identifier = readNormalNr(bufor,i); i+=4;
monsters[cre->identifier] = cre;
questIdentifierToId[cre->identifier] = idToBeGiven;
//monsters[cre->identifier] = cre;
}
CStackInstance *hlp = new CStackInstance();
@ -1846,10 +1848,11 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
nobj->pos = pos;
nobj->ID = defInfo->id;
nobj->id = objects.size();
nobj->id = idToBeGiven;
if(nobj->ID != HEROI_TYPE && nobj->ID != 214 && nobj->ID != 62)
nobj->subID = defInfo->subid;
nobj->defInfo = defInfo;
assert(idToBeGiven == objects.size());
objects.push_back(nobj);
if(nobj->ID==TOWNI_TYPE)
towns.push_back(static_cast<CGTownInstance*>(nobj));

View File

@ -287,8 +287,10 @@ struct DLL_EXPORT Mapa : public CMapHeader
std::vector< ConstTransitivePtr<CGHeroInstance> > heroes;
std::vector< ConstTransitivePtr<CGTownInstance> > towns;
std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances; //stores all artifacts
bmap<ui16, ConstTransitivePtr<CGCreature> > monsters;
bmap<ui16, ConstTransitivePtr<CGHeroInstance> > heroesToBeat;
//bmap<ui16, ConstTransitivePtr<CGCreature> > monsters;
//bmap<ui16, ConstTransitivePtr<CGHeroInstance> > heroesToBeat;
bmap<si32, si32> questIdentifierToId;
void initFromBytes( const unsigned char * bufor); //creates map from decompressed .h3m data
@ -300,7 +302,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
void readPredefinedHeroes( const unsigned char * bufor, int &i);
void readHeader( const unsigned char * bufor, int &i);
void readRumors( const unsigned char * bufor, int &i);
CGObjectInstance *loadHero(const unsigned char * bufor, int &i);
CGObjectInstance *loadHero(const unsigned char * bufor, int &i, int idToBeGiven);
void loadArtifactsOfHero(const unsigned char * bufor, int & i, CGHeroInstance * nhi);
bool loadArtifactToSlot(CGHeroInstance *h, int slot, const unsigned char * bufor, int &i);
void loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int &i, int subid);
@ -326,9 +328,8 @@ struct DLL_EXPORT Mapa : public CMapHeader
{
h & static_cast<CMapHeader&>(*this);
h & rumors & allowedSpell & allowedAbilities & allowedArtifact & allowedHeroes & events & grailPos;
h & monsters;
h & heroesToBeat;
h & artInstances; //hopefully serialization is now automagical?
h & questIdentifierToId;
//TODO: viccondetails
if(h.saving)

View File

@ -1529,7 +1529,7 @@ void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance
COMPLAIN_RET_IF(creatures.stacksCount() > ARMY_SIZE, "Too many stacks to give!");
//first we move creatures to give to make them army of object-source
for(int i = 0; creatures.stacksCount(); i++)
for(int i = 0; i != creatures.stacksCount(); i++)
{
TSlots::const_iterator stack = creatures.Slots().begin();
addToSlot(StackLocation(obj, i), stack->second->type, stack->second->count);