mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
Refactored loadObject() monstrocity into set of smaller methods.
This commit is contained in:
parent
c0e9eb6eb1
commit
3790661fa6
@ -936,81 +936,366 @@ void CMapLoaderH3M::readDefInfo()
|
||||
}
|
||||
}
|
||||
|
||||
void CMapLoaderH3M::readObjects()
|
||||
CGObjectInstance * CMapLoaderH3M::readEvent(const int3 & objPos)
|
||||
{
|
||||
uint32_t howManyObjs = reader->readUInt32();
|
||||
auto * object = new CGEvent();
|
||||
|
||||
for(uint32_t ww = 0; ww < howManyObjs; ++ww)
|
||||
readBoxContent(object, objPos);
|
||||
|
||||
object->availableFor = reader->readUInt8();
|
||||
object->computerActivate = reader->readBool();
|
||||
object->removeAfterVisit = reader->readBool();
|
||||
object->humanActivate = true;
|
||||
|
||||
reader->skipZero(4);
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readPandora(const int3 & position)
|
||||
{
|
||||
auto * object = new CGPandoraBox();
|
||||
readBoxContent(object, position);
|
||||
return object;
|
||||
}
|
||||
|
||||
void CMapLoaderH3M::readBoxContent(CGPandoraBox * object, const int3 & position)
|
||||
{
|
||||
readMessageAndGuards(object->message, object, position);
|
||||
|
||||
object->gainedExp = reader->readUInt32();
|
||||
object->manaDiff = reader->readInt32();
|
||||
object->moraleDiff = reader->readInt8();
|
||||
object->luckDiff = reader->readInt8();
|
||||
|
||||
reader->readResourses(object->resources);
|
||||
|
||||
object->primskills.resize(GameConstants::PRIMARY_SKILLS);
|
||||
for(int x = 0; x < GameConstants::PRIMARY_SKILLS; ++x)
|
||||
object->primskills[x] = static_cast<PrimarySkill::PrimarySkill>(reader->readUInt8());
|
||||
|
||||
int gabn = reader->readUInt8();//number of gained abilities
|
||||
for(int oo = 0; oo < gabn; ++oo)
|
||||
{
|
||||
CGObjectInstance * nobj = nullptr;
|
||||
object->abilities.emplace_back(reader->readSkill());
|
||||
object->abilityLevels.push_back(reader->readUInt8());
|
||||
}
|
||||
int gart = reader->readUInt8(); //number of gained artifacts
|
||||
for(int oo = 0; oo < gart; ++oo)
|
||||
object->artifacts.emplace_back(reader->readArtifact());
|
||||
|
||||
int3 objPos = reader->readInt3();
|
||||
int gspel = reader->readUInt8(); //number of gained spells
|
||||
for(int oo = 0; oo < gspel; ++oo)
|
||||
object->spells.emplace_back(reader->readSpell());
|
||||
|
||||
uint32_t defnum = reader->readUInt32();
|
||||
ObjectInstanceID idToBeGiven = ObjectInstanceID(static_cast<si32>(map->objects.size()));
|
||||
int gcre = reader->readUInt8(); //number of gained creatures
|
||||
readCreatureSet(&object->creatures, gcre);
|
||||
reader->skipZero(8);
|
||||
}
|
||||
|
||||
std::shared_ptr<const ObjectTemplate> objTempl = templates.at(defnum);
|
||||
reader->skipZero(5);
|
||||
CGObjectInstance * CMapLoaderH3M::readMonster(const int3 & objPos, const ObjectInstanceID & idToBeGiven)
|
||||
{
|
||||
auto * object = new CGCreature();
|
||||
|
||||
switch(objTempl->id)
|
||||
if(features.levelAB)
|
||||
{
|
||||
object->identifier = reader->readUInt32();
|
||||
map->questIdentifierToId[object->identifier] = idToBeGiven;
|
||||
}
|
||||
|
||||
auto * hlp = new CStackInstance();
|
||||
hlp->count = reader->readUInt16();
|
||||
|
||||
//type will be set during initialization
|
||||
object->putStack(SlotID(0), hlp);
|
||||
|
||||
object->character = reader->readInt8();
|
||||
|
||||
bool hasMessage = reader->readBool();
|
||||
if(hasMessage)
|
||||
{
|
||||
object->message = readLocalizedString(TextIdentifier("monster", objPos.x, objPos.y, objPos.z, "message"));
|
||||
reader->readResourses(object->resources);
|
||||
object->gainedArtifact = reader->readArtifact();
|
||||
}
|
||||
object->neverFlees = reader->readBool();
|
||||
object->notGrowingTeam = reader->readBool();
|
||||
reader->skipZero(2);
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readSign(const int3 & objPos)
|
||||
{
|
||||
auto * object = new CGSignBottle();
|
||||
object->message = readLocalizedString(TextIdentifier("sign", objPos.x, objPos.y, objPos.z, "message"));
|
||||
reader->skipZero(4);
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readWitchHut(const int3 & position)
|
||||
{
|
||||
auto * object = new CGWitchHut();
|
||||
|
||||
// AB and later maps have allowed abilities defined in H3M
|
||||
if(features.levelAB)
|
||||
{
|
||||
reader->readBitmask(object->allowedAbilities, features.skillsBytes, features.skillsCount, false);
|
||||
|
||||
if(object->allowedAbilities.size() != 1)
|
||||
{
|
||||
auto defaultAllowed = VLC->skillh->getDefaultAllowed();
|
||||
|
||||
for(int skillID = 0; skillID < VLC->skillh->size(); ++skillID)
|
||||
if (defaultAllowed[skillID])
|
||||
object->allowedAbilities.insert(skillID);
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readScholar(const int3 & position)
|
||||
{
|
||||
auto * object = new CGScholar();
|
||||
object->bonusType = static_cast<CGScholar::EBonusType>(reader->readUInt8());
|
||||
object->bonusID = reader->readUInt8();
|
||||
reader->skipZero(6);
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readGarrison(const int3 & position)
|
||||
{
|
||||
auto * object = new CGGarrison();
|
||||
|
||||
object->setOwner(reader->readPlayer32());
|
||||
readCreatureSet(object, 7);
|
||||
if(features.levelAB)
|
||||
object->removableUnits = reader->readBool();
|
||||
else
|
||||
object->removableUnits = true;
|
||||
|
||||
reader->skipZero(8);
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readArtifact(const int3 & objPos, std::shared_ptr<const ObjectTemplate> objTempl)
|
||||
{
|
||||
auto artID = ArtifactID::NONE; //random, set later
|
||||
int spellID = -1;
|
||||
auto * object = new CGArtifact();
|
||||
|
||||
readMessageAndGuards(object->message, object, objPos);
|
||||
|
||||
if(objTempl->id == Obj::SPELL_SCROLL)
|
||||
{
|
||||
spellID = reader->readSpell32();
|
||||
artID = ArtifactID::SPELL_SCROLL;
|
||||
}
|
||||
else if(objTempl->id == Obj::ARTIFACT)
|
||||
{
|
||||
//specific artifact
|
||||
artID = ArtifactID(objTempl->subid);
|
||||
}
|
||||
|
||||
object->storedArtifact = CArtifactInstance::createArtifact(map, artID, spellID);
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readResource(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl)
|
||||
{
|
||||
auto * object = new CGResource();
|
||||
|
||||
readMessageAndGuards(object->message, object, position);
|
||||
|
||||
object->amount = reader->readUInt32();
|
||||
if(objTempl->subid == GameResID(EGameResID::GOLD))
|
||||
{
|
||||
// Gold is multiplied by 100.
|
||||
object->amount *= 100;
|
||||
}
|
||||
reader->skipZero(4);
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readMine(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl)
|
||||
{
|
||||
auto * object = new CGMine();
|
||||
if (objTempl->subid < 7 )
|
||||
{
|
||||
object->setOwner(reader->readPlayer32());
|
||||
}
|
||||
else
|
||||
{
|
||||
object->setOwner(PlayerColor::NEUTRAL);
|
||||
reader->readBitmask(object->abandonedMineResources, features.resourcesBytes, features.resourcesCount, false);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readDwelling(const int3 & position)
|
||||
{
|
||||
auto * object = new CGDwelling();
|
||||
object->setOwner(reader->readPlayer32());
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl )
|
||||
{
|
||||
auto * object = new CGDwelling();
|
||||
|
||||
CSpecObjInfo * spec = nullptr;
|
||||
switch(objTempl->id)
|
||||
{
|
||||
case Obj::RANDOM_DWELLING:
|
||||
spec = new CCreGenLeveledCastleInfo();
|
||||
break;
|
||||
case Obj::RANDOM_DWELLING_LVL:
|
||||
spec = new CCreGenAsCastleInfo();
|
||||
break;
|
||||
case Obj::RANDOM_DWELLING_FACTION:
|
||||
spec = new CCreGenLeveledInfo();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid random dwelling format");
|
||||
}
|
||||
spec->owner = object;
|
||||
|
||||
object->setOwner(reader->readPlayer32());
|
||||
|
||||
//216 and 217
|
||||
if(auto * castleSpec = dynamic_cast<CCreGenAsCastleInfo *>(spec))
|
||||
{
|
||||
castleSpec->instanceId = "";
|
||||
castleSpec->identifier = reader->readUInt32();
|
||||
if(!castleSpec->identifier)
|
||||
{
|
||||
castleSpec->asCastle = false;
|
||||
const int MASK_SIZE = 8;
|
||||
ui8 mask[2];
|
||||
mask[0] = reader->readUInt8();
|
||||
mask[1] = reader->readUInt8();
|
||||
|
||||
castleSpec->allowedFactions.clear();
|
||||
castleSpec->allowedFactions.resize(VLC->townh->size(), false);
|
||||
|
||||
for(int i = 0; i < MASK_SIZE; i++)
|
||||
castleSpec->allowedFactions[i] = ((mask[0] & (1 << i))>0);
|
||||
|
||||
for(int i = 0; i < (GameConstants::F_NUMBER-MASK_SIZE); i++)
|
||||
castleSpec->allowedFactions[i+MASK_SIZE] = ((mask[1] & (1 << i))>0);
|
||||
}
|
||||
else
|
||||
{
|
||||
castleSpec->asCastle = true;
|
||||
}
|
||||
}
|
||||
|
||||
//216 and 218
|
||||
if(auto * lvlSpec = dynamic_cast<CCreGenLeveledInfo *>(spec))
|
||||
{
|
||||
lvlSpec->minLevel = std::max(reader->readUInt8(), static_cast<ui8>(1));
|
||||
lvlSpec->maxLevel = std::min(reader->readUInt8(), static_cast<ui8>(7));
|
||||
}
|
||||
object->info = spec;
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readShrine(const int3 & position)
|
||||
{
|
||||
auto * object = new CGShrine();
|
||||
object->spell = reader->readSpell32();
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readHeroPlaceholder(const int3 & position)
|
||||
{
|
||||
auto * object = new CGHeroPlaceholder();
|
||||
|
||||
object->setOwner(reader->readPlayer());
|
||||
|
||||
HeroTypeID htid = reader->readHero(); //hero type id
|
||||
object->subID = htid.getNum();
|
||||
|
||||
if(htid.getNum() == -1)
|
||||
{
|
||||
object->power = reader->readUInt8();
|
||||
logGlobal->debug("Hero placeholder: by power at %s", position.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
object->power = 0;
|
||||
logGlobal->debug("Hero placeholder: %s at %s", VLC->heroh->getById(htid)->getNameTranslated(), position.toString());
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readGrail(const int3 & position)
|
||||
{
|
||||
map->grailPos = position;
|
||||
map->grailRadius = reader->readInt32();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readBlank(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl)
|
||||
{
|
||||
if (VLC->objtypeh->knownSubObjects(objTempl->id).count(objTempl->subid))
|
||||
return VLC->objtypeh->getHandlerFor(objTempl->id, objTempl->subid)->create(objTempl);
|
||||
|
||||
logGlobal->warn("Unrecognized object: %d:%d ('%s') at %s on map '%s'", objTempl->id.toEnum(), objTempl->subid, objTempl->animationFile, position.toString(), map->name);
|
||||
return new CGObjectInstance();
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readPyramid(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl)
|
||||
{
|
||||
if(objTempl->subid == 0)
|
||||
return new CBank();
|
||||
|
||||
return new CGObjectInstance();
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readQuestGuard(const int3 & position)
|
||||
{
|
||||
auto * guard = new CGQuestGuard();
|
||||
readQuest(guard, position);
|
||||
return guard;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readShipyard(const int3 & position)
|
||||
{
|
||||
auto * object = new CGShipyard();
|
||||
object->setOwner(reader->readPlayer32());
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readBorderGuard(const int3 & position)
|
||||
{
|
||||
return new CGBorderGuard();
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readBorderGate(const int3 & position)
|
||||
{
|
||||
return new CGBorderGate();
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readLighthouse(const int3 & position)
|
||||
{
|
||||
auto * object = new CGLighthouse();
|
||||
object->tempOwner = reader->readPlayer32();
|
||||
return object;
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readObject(std::shared_ptr<const ObjectTemplate> objectTemplate, const int3 & objectPosition, const ObjectInstanceID & idToBeGiven)
|
||||
{
|
||||
switch(objectTemplate->id)
|
||||
{
|
||||
case Obj::EVENT:
|
||||
{
|
||||
auto * evnt = new CGEvent();
|
||||
nobj = evnt;
|
||||
return readEvent(objectPosition);
|
||||
|
||||
readMessageAndGuards(evnt->message, evnt, objPos);
|
||||
|
||||
evnt->gainedExp = reader->readUInt32();
|
||||
evnt->manaDiff = reader->readInt32();
|
||||
evnt->moraleDiff = reader->readInt8();
|
||||
evnt->luckDiff = reader->readInt8();
|
||||
|
||||
reader->readResourses(evnt->resources);
|
||||
|
||||
evnt->primskills.resize(GameConstants::PRIMARY_SKILLS);
|
||||
for(int x = 0; x < 4; ++x)
|
||||
{
|
||||
evnt->primskills[x] = static_cast<PrimarySkill::PrimarySkill>(reader->readUInt8());
|
||||
}
|
||||
|
||||
int gabn = reader->readUInt8(); // Number of gained abilities
|
||||
for(int oo = 0; oo < gabn; ++oo)
|
||||
{
|
||||
evnt->abilities.emplace_back(reader->readSkill());
|
||||
evnt->abilityLevels.push_back(reader->readUInt8());
|
||||
}
|
||||
|
||||
int gart = reader->readUInt8(); // Number of gained artifacts
|
||||
for(int oo = 0; oo < gart; ++oo)
|
||||
evnt->artifacts.emplace_back(reader->readArtifact());
|
||||
|
||||
int gspel = reader->readUInt8(); // Number of gained spells
|
||||
for(int oo = 0; oo < gspel; ++oo)
|
||||
{
|
||||
evnt->spells.emplace_back(reader->readSpell());
|
||||
}
|
||||
|
||||
int gcre = reader->readUInt8(); //number of gained creatures
|
||||
readCreatureSet(&evnt->creatures, gcre);
|
||||
|
||||
reader->skipZero(8);
|
||||
evnt->availableFor = reader->readUInt8();
|
||||
evnt->computerActivate = reader->readBool();
|
||||
evnt->removeAfterVisit = reader->readBool();
|
||||
evnt->humanActivate = true;
|
||||
|
||||
reader->skipZero(4);
|
||||
break;
|
||||
}
|
||||
case Obj::HERO:
|
||||
case Obj::RANDOM_HERO:
|
||||
case Obj::PRISON:
|
||||
{
|
||||
nobj = readHero(idToBeGiven, objPos);
|
||||
break;
|
||||
}
|
||||
case Obj::MONSTER: //Monster
|
||||
return readHero(objectPosition, idToBeGiven);
|
||||
|
||||
case Obj::MONSTER:
|
||||
case Obj::RANDOM_MONSTER:
|
||||
case Obj::RANDOM_MONSTER_L1:
|
||||
case Obj::RANDOM_MONSTER_L2:
|
||||
@ -1019,95 +1304,24 @@ void CMapLoaderH3M::readObjects()
|
||||
case Obj::RANDOM_MONSTER_L5:
|
||||
case Obj::RANDOM_MONSTER_L6:
|
||||
case Obj::RANDOM_MONSTER_L7:
|
||||
{
|
||||
auto * cre = new CGCreature();
|
||||
nobj = cre;
|
||||
return readMonster(objectPosition, idToBeGiven);
|
||||
|
||||
if(features.levelAB)
|
||||
{
|
||||
cre->identifier = reader->readUInt32();
|
||||
map->questIdentifierToId[cre->identifier] = idToBeGiven;
|
||||
}
|
||||
|
||||
auto * hlp = new CStackInstance();
|
||||
hlp->count = reader->readUInt16();
|
||||
|
||||
//type will be set during initialization
|
||||
cre->putStack(SlotID(0), hlp);
|
||||
|
||||
cre->character = reader->readInt8();
|
||||
|
||||
bool hasMessage = reader->readBool();
|
||||
if(hasMessage)
|
||||
{
|
||||
cre->message = readLocalizedString(TextIdentifier("monster", objPos.x, objPos.y, objPos.z, "message"));
|
||||
reader->readResourses(cre->resources);
|
||||
cre->gainedArtifact = reader->readArtifact();
|
||||
}
|
||||
cre->neverFlees = reader->readBool();
|
||||
cre->notGrowingTeam = reader->readBool();
|
||||
reader->skipZero(2);
|
||||
break;
|
||||
}
|
||||
case Obj::OCEAN_BOTTLE:
|
||||
case Obj::SIGN:
|
||||
{
|
||||
auto * sb = new CGSignBottle();
|
||||
nobj = sb;
|
||||
sb->message = readLocalizedString(TextIdentifier("sign", objPos.x, objPos.y, objPos.z, "message"));
|
||||
reader->skipZero(4);
|
||||
break;
|
||||
}
|
||||
return readSign(objectPosition);
|
||||
|
||||
case Obj::SEER_HUT:
|
||||
{
|
||||
nobj = readSeerHut(objPos);
|
||||
break;
|
||||
}
|
||||
return readSeerHut(objectPosition);
|
||||
|
||||
case Obj::WITCH_HUT:
|
||||
{
|
||||
auto * wh = new CGWitchHut();
|
||||
nobj = wh;
|
||||
|
||||
// AB and later maps have allowed abilities defined in H3M
|
||||
if(features.levelAB)
|
||||
{
|
||||
reader->readBitmask(wh->allowedAbilities, features.skillsBytes, features.skillsCount, false);
|
||||
|
||||
if(wh->allowedAbilities.size() != 1)
|
||||
{
|
||||
auto defaultAllowed = VLC->skillh->getDefaultAllowed();
|
||||
|
||||
for(int skillID = 0; skillID < VLC->skillh->size(); ++skillID)
|
||||
if (defaultAllowed[skillID])
|
||||
wh->allowedAbilities.insert(skillID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return readWitchHut(objectPosition);
|
||||
case Obj::SCHOLAR:
|
||||
{
|
||||
auto * sch = new CGScholar();
|
||||
nobj = sch;
|
||||
sch->bonusType = static_cast<CGScholar::EBonusType>(reader->readUInt8());
|
||||
sch->bonusID = reader->readUInt8();
|
||||
reader->skipZero(6);
|
||||
break;
|
||||
}
|
||||
return readScholar(objectPosition);
|
||||
|
||||
case Obj::GARRISON:
|
||||
case Obj::GARRISON2:
|
||||
{
|
||||
auto * gar = new CGGarrison();
|
||||
nobj = gar;
|
||||
nobj->setOwner(reader->readPlayer32());
|
||||
readCreatureSet(gar, 7);
|
||||
if(features.levelAB)
|
||||
gar->removableUnits = reader->readBool();
|
||||
else
|
||||
gar->removableUnits = true;
|
||||
return readGarrison(objectPosition);
|
||||
|
||||
reader->skipZero(8);
|
||||
break;
|
||||
}
|
||||
case Obj::ARTIFACT:
|
||||
case Obj::RANDOM_ART:
|
||||
case Obj::RANDOM_TREASURE_ART:
|
||||
@ -1115,271 +1329,85 @@ void CMapLoaderH3M::readObjects()
|
||||
case Obj::RANDOM_MAJOR_ART:
|
||||
case Obj::RANDOM_RELIC_ART:
|
||||
case Obj::SPELL_SCROLL:
|
||||
{
|
||||
auto artID = ArtifactID::NONE; //random, set later
|
||||
int spellID = -1;
|
||||
auto * art = new CGArtifact();
|
||||
nobj = art;
|
||||
return readArtifact(objectPosition, objectTemplate);
|
||||
|
||||
readMessageAndGuards(art->message, art, objPos);
|
||||
|
||||
if(objTempl->id == Obj::SPELL_SCROLL)
|
||||
{
|
||||
spellID = reader->readSpell32();
|
||||
artID = ArtifactID::SPELL_SCROLL;
|
||||
}
|
||||
else if(objTempl->id == Obj::ARTIFACT)
|
||||
{
|
||||
//specific artifact
|
||||
artID = ArtifactID(objTempl->subid);
|
||||
}
|
||||
|
||||
art->storedArtifact = CArtifactInstance::createArtifact(map, artID, spellID);
|
||||
break;
|
||||
}
|
||||
case Obj::RANDOM_RESOURCE:
|
||||
case Obj::RESOURCE:
|
||||
{
|
||||
auto * res = new CGResource();
|
||||
nobj = res;
|
||||
|
||||
readMessageAndGuards(res->message, res, objPos);
|
||||
|
||||
res->amount = reader->readUInt32();
|
||||
if(objTempl->subid == GameResID(EGameResID::GOLD))
|
||||
{
|
||||
// Gold is multiplied by 100.
|
||||
res->amount *= 100;
|
||||
}
|
||||
reader->skipZero(4);
|
||||
break;
|
||||
}
|
||||
return readResource(objectPosition, objectTemplate);
|
||||
case Obj::RANDOM_TOWN:
|
||||
case Obj::TOWN:
|
||||
{
|
||||
nobj = readTown(objTempl->subid, objPos);
|
||||
break;
|
||||
}
|
||||
return readTown(objectPosition, objectTemplate);
|
||||
|
||||
case Obj::MINE:
|
||||
case Obj::ABANDONED_MINE:
|
||||
{
|
||||
auto * mine = new CGMine();
|
||||
nobj = mine;
|
||||
if (objTempl->subid < 7 )
|
||||
{
|
||||
mine->setOwner(reader->readPlayer32());
|
||||
}
|
||||
else
|
||||
{
|
||||
mine->setOwner(PlayerColor::NEUTRAL);
|
||||
reader->readBitmask(mine->abandonedMineResources, features.resourcesBytes, features.resourcesCount, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return readMine(objectPosition, objectTemplate);
|
||||
|
||||
case Obj::CREATURE_GENERATOR1:
|
||||
case Obj::CREATURE_GENERATOR2:
|
||||
case Obj::CREATURE_GENERATOR3:
|
||||
case Obj::CREATURE_GENERATOR4:
|
||||
{
|
||||
nobj = new CGDwelling();
|
||||
nobj->setOwner(reader->readPlayer32());
|
||||
break;
|
||||
}
|
||||
return readDwelling(objectPosition);
|
||||
|
||||
case Obj::SHRINE_OF_MAGIC_INCANTATION:
|
||||
case Obj::SHRINE_OF_MAGIC_GESTURE:
|
||||
case Obj::SHRINE_OF_MAGIC_THOUGHT:
|
||||
{
|
||||
auto * shr = new CGShrine();
|
||||
nobj = shr;
|
||||
shr->spell = reader->readSpell32();
|
||||
break;
|
||||
}
|
||||
return readShrine(objectPosition);
|
||||
|
||||
case Obj::PANDORAS_BOX:
|
||||
{
|
||||
auto * box = new CGPandoraBox();
|
||||
nobj = box;
|
||||
readMessageAndGuards(box->message, box, objPos);
|
||||
return readPandora(objectPosition);
|
||||
|
||||
box->gainedExp = reader->readUInt32();
|
||||
box->manaDiff = reader->readInt32();
|
||||
box->moraleDiff = reader->readInt8();
|
||||
box->luckDiff = reader->readInt8();
|
||||
|
||||
reader->readResourses(box->resources);
|
||||
|
||||
box->primskills.resize(GameConstants::PRIMARY_SKILLS);
|
||||
for(int x = 0; x < GameConstants::PRIMARY_SKILLS; ++x)
|
||||
{
|
||||
box->primskills[x] = static_cast<PrimarySkill::PrimarySkill>(reader->readUInt8());
|
||||
}
|
||||
|
||||
int gabn = reader->readUInt8();//number of gained abilities
|
||||
for(int oo = 0; oo < gabn; ++oo)
|
||||
{
|
||||
box->abilities.emplace_back(reader->readSkill());
|
||||
box->abilityLevels.push_back(reader->readUInt8());
|
||||
}
|
||||
int gart = reader->readUInt8(); //number of gained artifacts
|
||||
for(int oo = 0; oo < gart; ++oo)
|
||||
box->artifacts.emplace_back(reader->readArtifact());
|
||||
|
||||
int gspel = reader->readUInt8(); //number of gained spells
|
||||
for(int oo = 0; oo < gspel; ++oo)
|
||||
box->spells.emplace_back(reader->readSpell());
|
||||
|
||||
int gcre = reader->readUInt8(); //number of gained creatures
|
||||
readCreatureSet(&box->creatures, gcre);
|
||||
reader->skipZero(8);
|
||||
break;
|
||||
}
|
||||
case Obj::GRAIL:
|
||||
{
|
||||
map->grailPos = objPos;
|
||||
map->grailRadius = reader->readInt32();
|
||||
continue;
|
||||
}
|
||||
case Obj::RANDOM_DWELLING: //same as castle + level range
|
||||
case Obj::RANDOM_DWELLING_LVL: //same as castle, fixed level
|
||||
case Obj::RANDOM_DWELLING_FACTION: //level range, fixed faction
|
||||
{
|
||||
auto * dwelling = new CGDwelling();
|
||||
nobj = dwelling;
|
||||
CSpecObjInfo * spec = nullptr;
|
||||
switch(objTempl->id)
|
||||
{
|
||||
case Obj::RANDOM_DWELLING:
|
||||
spec = new CCreGenLeveledCastleInfo();
|
||||
break;
|
||||
case Obj::RANDOM_DWELLING_LVL:
|
||||
spec = new CCreGenAsCastleInfo();
|
||||
break;
|
||||
case Obj::RANDOM_DWELLING_FACTION:
|
||||
spec = new CCreGenLeveledInfo();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid random dwelling format");
|
||||
}
|
||||
spec->owner = dwelling;
|
||||
return readGrail(objectPosition);
|
||||
|
||||
nobj->setOwner(reader->readPlayer32());
|
||||
case Obj::RANDOM_DWELLING:
|
||||
case Obj::RANDOM_DWELLING_LVL:
|
||||
case Obj::RANDOM_DWELLING_FACTION:
|
||||
return readDwellingRandom(objectPosition, objectTemplate);
|
||||
|
||||
//216 and 217
|
||||
if(auto * castleSpec = dynamic_cast<CCreGenAsCastleInfo *>(spec))
|
||||
{
|
||||
castleSpec->instanceId = "";
|
||||
castleSpec->identifier = reader->readUInt32();
|
||||
if(!castleSpec->identifier)
|
||||
{
|
||||
castleSpec->asCastle = false;
|
||||
const int MASK_SIZE = 8;
|
||||
ui8 mask[2];
|
||||
mask[0] = reader->readUInt8();
|
||||
mask[1] = reader->readUInt8();
|
||||
|
||||
castleSpec->allowedFactions.clear();
|
||||
castleSpec->allowedFactions.resize(VLC->townh->size(), false);
|
||||
|
||||
for(int i = 0; i < MASK_SIZE; i++)
|
||||
castleSpec->allowedFactions[i] = ((mask[0] & (1 << i))>0);
|
||||
|
||||
for(int i = 0; i < (GameConstants::F_NUMBER-MASK_SIZE); i++)
|
||||
castleSpec->allowedFactions[i+MASK_SIZE] = ((mask[1] & (1 << i))>0);
|
||||
}
|
||||
else
|
||||
{
|
||||
castleSpec->asCastle = true;
|
||||
}
|
||||
}
|
||||
|
||||
//216 and 218
|
||||
if(auto * lvlSpec = dynamic_cast<CCreGenLeveledInfo *>(spec))
|
||||
{
|
||||
lvlSpec->minLevel = std::max(reader->readUInt8(), static_cast<ui8>(1));
|
||||
lvlSpec->maxLevel = std::min(reader->readUInt8(), static_cast<ui8>(7));
|
||||
}
|
||||
dwelling->info = spec;
|
||||
break;
|
||||
}
|
||||
case Obj::QUEST_GUARD:
|
||||
{
|
||||
auto * guard = new CGQuestGuard();
|
||||
readQuest(guard, objPos);
|
||||
nobj = guard;
|
||||
break;
|
||||
}
|
||||
return readQuestGuard(objectPosition);
|
||||
|
||||
case Obj::SHIPYARD:
|
||||
{
|
||||
nobj = new CGShipyard();
|
||||
nobj->setOwner(reader->readPlayer32());
|
||||
break;
|
||||
}
|
||||
case Obj::HERO_PLACEHOLDER: //hero placeholder
|
||||
{
|
||||
auto * hp = new CGHeroPlaceholder();
|
||||
nobj = hp;
|
||||
return readShipyard(objectPosition);
|
||||
|
||||
hp->setOwner(reader->readPlayer());
|
||||
case Obj::HERO_PLACEHOLDER:
|
||||
return readHeroPlaceholder(objectPosition);
|
||||
|
||||
HeroTypeID htid = reader->readHero(); //hero type id
|
||||
nobj->subID = htid.getNum();
|
||||
|
||||
if(htid.getNum() == -1)
|
||||
{
|
||||
hp->power = reader->readUInt8();
|
||||
logGlobal->debug("Hero placeholder: by power at %s", objPos.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->debug("Hero placeholder: %s at %s", VLC->heroh->getById(htid)->getNameTranslated(), objPos.toString());
|
||||
hp->power = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Obj::BORDERGUARD:
|
||||
{
|
||||
nobj = new CGBorderGuard();
|
||||
break;
|
||||
}
|
||||
return readBorderGuard(objectPosition);
|
||||
|
||||
case Obj::BORDER_GATE:
|
||||
{
|
||||
nobj = new CGBorderGate();
|
||||
break;
|
||||
}
|
||||
case Obj::PYRAMID: //Pyramid of WoG object
|
||||
{
|
||||
if(objTempl->subid == 0)
|
||||
{
|
||||
nobj = new CBank();
|
||||
}
|
||||
else
|
||||
{
|
||||
//WoG object
|
||||
//TODO: possible special handling
|
||||
nobj = new CGObjectInstance();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Obj::LIGHTHOUSE: //Lighthouse
|
||||
{
|
||||
nobj = new CGLighthouse();
|
||||
nobj->tempOwner = reader->readPlayer32();
|
||||
break;
|
||||
}
|
||||
return readBorderGate(objectPosition);
|
||||
|
||||
case Obj::PYRAMID:
|
||||
return readPyramid(objectPosition, objectTemplate);
|
||||
|
||||
case Obj::LIGHTHOUSE:
|
||||
return readLighthouse(objectPosition);
|
||||
|
||||
default: //any other object
|
||||
{
|
||||
if (VLC->objtypeh->knownSubObjects(objTempl->id).count(objTempl->subid))
|
||||
{
|
||||
nobj = VLC->objtypeh->getHandlerFor(objTempl->id, objTempl->subid)->create(objTempl);
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->warn("Unrecognized object: %d:%d ('%s') at %s on map '%s'", objTempl->id.toEnum(), objTempl->subid, objTempl->animationFile, objPos.toString(), map->name);
|
||||
nobj = new CGObjectInstance();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return readBlank(objectPosition, objectTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
void CMapLoaderH3M::readObjects()
|
||||
{
|
||||
uint32_t howManyObjs = reader->readUInt32();
|
||||
|
||||
for(uint32_t ww = 0; ww < howManyObjs; ++ww)
|
||||
{
|
||||
int3 objPos = reader->readInt3();
|
||||
|
||||
uint32_t defnum = reader->readUInt32();
|
||||
ObjectInstanceID idToBeGiven = ObjectInstanceID(static_cast<si32>(map->objects.size()));
|
||||
|
||||
std::shared_ptr<const ObjectTemplate> objTempl = templates.at(defnum);
|
||||
reader->skipZero(5);
|
||||
|
||||
CGObjectInstance * nobj = readObject(objTempl, objPos, idToBeGiven);
|
||||
|
||||
if (!nobj)
|
||||
continue;
|
||||
|
||||
nobj->pos = objPos;
|
||||
nobj->ID = objTempl->id;
|
||||
@ -1443,7 +1471,7 @@ void CMapLoaderH3M::readCreatureSet(CCreatureSet * out, int number)
|
||||
out->validTypes(true);
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readHero(const ObjectInstanceID & idToBeGiven, const int3 & initialPos)
|
||||
CGObjectInstance * CMapLoaderH3M::readHero(const int3 & initialPos, const ObjectInstanceID & idToBeGiven)
|
||||
{
|
||||
auto * nhi = new CGHeroInstance();
|
||||
|
||||
@ -1601,7 +1629,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const ObjectInstanceID & idToBeGiven,
|
||||
return nhi;
|
||||
}
|
||||
|
||||
CGSeerHut * CMapLoaderH3M::readSeerHut(const int3 & position)
|
||||
CGObjectInstance * CMapLoaderH3M::readSeerHut(const int3 & position)
|
||||
{
|
||||
auto * hut = new CGSeerHut();
|
||||
|
||||
@ -1791,7 +1819,7 @@ void CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & position)
|
||||
guard->quest->isCustomComplete = !guard->quest->completedText.empty();
|
||||
}
|
||||
|
||||
CGTownInstance * CMapLoaderH3M::readTown(int castleID, const int3 & position)
|
||||
CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl)
|
||||
{
|
||||
auto * nt = new CGTownInstance();
|
||||
if(features.levelAB)
|
||||
@ -1815,8 +1843,8 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID, const int3 & position)
|
||||
reader->readBitmask(nt->builtBuildings, features.buildingsBytes,features.buildingsCount,false);
|
||||
reader->readBitmask(nt->forbiddenBuildings,features.buildingsBytes,features.buildingsCount,false);
|
||||
|
||||
nt->builtBuildings = convertBuildings(nt->builtBuildings, castleID);
|
||||
nt->forbiddenBuildings = convertBuildings(nt->forbiddenBuildings, castleID);
|
||||
nt->builtBuildings = convertBuildings(nt->builtBuildings, objTempl->subid);
|
||||
nt->forbiddenBuildings = convertBuildings(nt->forbiddenBuildings, objTempl->subid);
|
||||
}
|
||||
// Standard buildings
|
||||
else
|
||||
@ -1879,7 +1907,7 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID, const int3 & position)
|
||||
|
||||
reader->readBitmask(nce.buildings, features.buildingsBytes, features.buildingsCount, false);
|
||||
|
||||
nce.buildings = convertBuildings(nce.buildings, castleID, false);
|
||||
nce.buildings = convertBuildings(nce.buildings, objTempl->subid, false);
|
||||
|
||||
nce.creatures.resize(7);
|
||||
for(int vv = 0; vv < 7; ++vv)
|
||||
|
@ -25,6 +25,7 @@ class CGTownInstance;
|
||||
class CCreatureSet;
|
||||
class CInputStream;
|
||||
class TextIdentifier;
|
||||
class CGPandoraBox;
|
||||
|
||||
class ObjectInstanceID;
|
||||
class BuildingID;
|
||||
@ -153,6 +154,35 @@ private:
|
||||
*/
|
||||
void readObjects();
|
||||
|
||||
/// Reads single object from input stream based on template
|
||||
CGObjectInstance * readObject(std::shared_ptr<const ObjectTemplate> objectTemplate, const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
|
||||
|
||||
CGObjectInstance * readEvent(const int3 & objectPosition);
|
||||
CGObjectInstance * readMonster(const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
|
||||
CGObjectInstance * readHero(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
|
||||
CGObjectInstance * readSeerHut(const int3 & initialPos);
|
||||
CGObjectInstance * readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readSign(const int3 & position);
|
||||
CGObjectInstance * readWitchHut(const int3 & position);
|
||||
CGObjectInstance * readScholar(const int3 & position);
|
||||
CGObjectInstance * readGarrison(const int3 & position);
|
||||
CGObjectInstance * readArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readResource(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readMine(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readPandora(const int3 & position);
|
||||
CGObjectInstance * readDwelling(const int3 & position);
|
||||
CGObjectInstance * readDwellingRandom(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readShrine(const int3 & position);
|
||||
CGObjectInstance * readHeroPlaceholder(const int3 & position);
|
||||
CGObjectInstance * readGrail(const int3 & position);
|
||||
CGObjectInstance * readPyramid(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
|
||||
CGObjectInstance * readBorderGuard(const int3 & position);
|
||||
CGObjectInstance * readBorderGate(const int3 & position);
|
||||
CGObjectInstance * readQuestGuard(const int3 & position);
|
||||
CGObjectInstance * readShipyard(const int3 & position);
|
||||
CGObjectInstance * readLighthouse(const int3 & position);
|
||||
CGObjectInstance * readBlank(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
|
||||
|
||||
/**
|
||||
* Reads a creature set.
|
||||
*
|
||||
@ -162,19 +192,11 @@ private:
|
||||
void readCreatureSet(CCreatureSet * out, int number);
|
||||
|
||||
/**
|
||||
* Reads a hero.
|
||||
* Reads a quest for the given quest guard.
|
||||
*
|
||||
* @param idToBeGiven the object id which should be set for the hero
|
||||
* @return a object instance
|
||||
* @param guard the quest guard where that quest should be applied to
|
||||
*/
|
||||
CGObjectInstance * readHero(const ObjectInstanceID & idToBeGiven, const int3 & initialPos);
|
||||
|
||||
/**
|
||||
* Reads a seer hut.
|
||||
*
|
||||
* @return the initialized seer hut object
|
||||
*/
|
||||
CGSeerHut * readSeerHut(const int3 & position);
|
||||
void readBoxContent(CGPandoraBox * object, const int3 & position);
|
||||
|
||||
/**
|
||||
* Reads a quest for the given quest guard.
|
||||
@ -183,14 +205,6 @@ private:
|
||||
*/
|
||||
void readQuest(IQuestObject * guard, const int3 & position);
|
||||
|
||||
/**
|
||||
* Reads a town.
|
||||
*
|
||||
* @param castleID the id of the castle type
|
||||
* @return the loaded town object
|
||||
*/
|
||||
CGTownInstance * readTown(int castleID, const int3 & position);
|
||||
|
||||
/**
|
||||
* Converts buildings to the specified castle id.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user