mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
33fd0d22a6
* new discoveries in h3m specification VCMI handles correctly all known maps again :)
261 lines
6.9 KiB
C++
261 lines
6.9 KiB
C++
#include "stdafx.h"
|
|
#include "map.h"
|
|
|
|
int readNormalNr (unsigned char * bufor, int pos, int bytCon = 4)
|
|
{
|
|
int ret=0;
|
|
int amp=1;
|
|
for (int i=0; i<bytCon; i++)
|
|
{
|
|
ret+=bufor[pos+i]*amp;
|
|
amp<<=8;
|
|
}
|
|
return ret;
|
|
}
|
|
bool DefInfo::isVisitable()
|
|
{
|
|
for (int i=6; i<12; i++)
|
|
{
|
|
if (bytes[i])
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
CMapHeader::CMapHeader(unsigned char *map)
|
|
{
|
|
this->version = (Eformat)map[0]; //wersja mapy
|
|
this->areAnyPLayers = map[4]; //seems to be invalid
|
|
this->height = this->width = map[5]; // wymiary mapy
|
|
this->twoLevel = map[9]; //czy sa lochy
|
|
|
|
int length = map[10]; //name length
|
|
int i=14, pom;
|
|
while (i-14<length) //read name
|
|
this->name+=map[i++];
|
|
length = map[i] + map[i+1]*256; //description length
|
|
i+=4;
|
|
for (pom=0;pom<length;pom++)
|
|
this->description+=map[i++];
|
|
this->difficulty = map[i++]; // reading map difficulty
|
|
if(version!=Eformat::RoE)
|
|
{
|
|
this->levelLimit = map[i++]; // hero level limit
|
|
}
|
|
else
|
|
{
|
|
levelLimit = 0;
|
|
}
|
|
for (pom=0;pom<8;pom++)
|
|
{
|
|
this->players[pom].canHumanPlay = map[i++];
|
|
this->players[pom].canComputerPlay = map[i++];
|
|
if ((!(this->players[pom].canHumanPlay || this->players[pom].canComputerPlay)))
|
|
{
|
|
switch(version)
|
|
{
|
|
case Eformat::SoD: case Eformat::WoG:
|
|
i+=13;
|
|
break;
|
|
case Eformat::AB:
|
|
i+=12;
|
|
break;
|
|
case Eformat::RoE:
|
|
i+=6;
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
this->players[pom].AITactic = map[i++];
|
|
|
|
if(version == Eformat::SoD || version == Eformat::WoG)
|
|
i++;
|
|
|
|
this->players[pom].allowedFactions = 0;
|
|
this->players[pom].allowedFactions += map[i++];
|
|
if(version != Eformat::RoE)
|
|
this->players[pom].allowedFactions += (map[i++])*256;
|
|
|
|
this->players[pom].isFactionRandom = map[i++];
|
|
this->players[pom].hasMainTown = map[i++];
|
|
if (this->players[pom].hasMainTown)
|
|
{
|
|
if(version != Eformat::RoE)
|
|
{
|
|
this->players[pom].generateHeroAtMainTown = map[i++];
|
|
this->players[pom].generateHero = map[i++];
|
|
}
|
|
this->players[pom].posOfMainTown.x = map[i++];
|
|
this->players[pom].posOfMainTown.y = map[i++];
|
|
this->players[pom].posOfMainTown.z = map[i++];
|
|
}
|
|
players[pom].p8= map[i++];
|
|
players[pom].p9= map[i++];
|
|
if(players[pom].p9!=0xff)
|
|
{
|
|
players[pom].mainHeroPortrait = map[i++];
|
|
int nameLength = map[i++];
|
|
i+=3;
|
|
for (int pp=0;pp<nameLength;pp++)
|
|
players[pom].mainHeroName+=map[i++];
|
|
}
|
|
|
|
if(version!=Eformat::RoE)
|
|
{
|
|
i++; ////heroes placeholders //domostwa
|
|
int heroCount = map[i++];
|
|
i+=3;
|
|
for (int pp=0;pp<heroCount;pp++)
|
|
{
|
|
SheroName vv;
|
|
vv.heroID=map[i++];
|
|
int hnl = map[i++];
|
|
i+=3;
|
|
for (int zz=0;zz<hnl;zz++)
|
|
{
|
|
vv.heroName+=map[i++];
|
|
}
|
|
this->players[pom].heroesNames.push_back(vv);
|
|
}
|
|
}
|
|
}
|
|
this->victoryCondition = (EvictoryConditions)map[i++];
|
|
if (this->victoryCondition != winStandard) //specific victory conditions
|
|
{
|
|
int nr;
|
|
switch (this->victoryCondition) //read victory conditions
|
|
{
|
|
case artifact:
|
|
{
|
|
this->vicConDetails = new VicCon0();
|
|
((VicCon0*)this->vicConDetails)->ArtifactID = map[i+2];
|
|
nr=(version==RoE ? 1 : 2);
|
|
break;
|
|
}
|
|
case gatherTroop:
|
|
{
|
|
this->vicConDetails = new VicCon1();
|
|
int temp1 = map[i+2];
|
|
int temp2 = map[i+3];
|
|
((VicCon1*)this->vicConDetails)->monsterID = map[i+2];
|
|
((VicCon1*)this->vicConDetails)->neededQuantity=readNormalNr(map, i+(version==RoE ? 3 : 4));
|
|
nr=(version==RoE ? 5 : 6);
|
|
break;
|
|
}
|
|
case gatherResource:
|
|
{
|
|
this->vicConDetails = new VicCon2();
|
|
((VicCon2*)this->vicConDetails)->resourceID = map[i+2];
|
|
((VicCon2*)this->vicConDetails)->neededQuantity=readNormalNr(map, i+3);
|
|
nr=5;
|
|
break;
|
|
}
|
|
case buildCity:
|
|
{
|
|
this->vicConDetails = new VicCon3();
|
|
((VicCon3*)this->vicConDetails)->posOfCity.x = map[i+2];
|
|
((VicCon3*)this->vicConDetails)->posOfCity.y = map[i+3];
|
|
((VicCon3*)this->vicConDetails)->posOfCity.z = map[i+4];
|
|
((VicCon3*)this->vicConDetails)->councilNeededLevel = map[i+5];
|
|
((VicCon3*)this->vicConDetails)->fortNeededLevel = map[i+6];
|
|
nr=5;
|
|
break;
|
|
}
|
|
case buildGrail:
|
|
{
|
|
this->vicConDetails = new VicCon4();
|
|
if (map[i+4]>2)
|
|
((VicCon4*)this->vicConDetails)->anyLocation = true;
|
|
else
|
|
{
|
|
((VicCon4*)this->vicConDetails)->whereBuildGrail.x = map[i+2];
|
|
((VicCon4*)this->vicConDetails)->whereBuildGrail.y = map[i+3];
|
|
((VicCon4*)this->vicConDetails)->whereBuildGrail.z = map[i+4];
|
|
}
|
|
nr=3;
|
|
break;
|
|
}
|
|
case beatHero:
|
|
{
|
|
this->vicConDetails = new VicCon5();
|
|
((VicCon5*)this->vicConDetails)->locationOfHero.x = map[i+2];
|
|
((VicCon5*)this->vicConDetails)->locationOfHero.y = map[i+3];
|
|
((VicCon5*)this->vicConDetails)->locationOfHero.z = map[i+4];
|
|
nr=3;
|
|
break;
|
|
}
|
|
case captureCity:
|
|
{
|
|
this->vicConDetails = new VicCon6();
|
|
((VicCon6*)this->vicConDetails)->locationOfTown.x = map[i+2];
|
|
((VicCon6*)this->vicConDetails)->locationOfTown.y = map[i+3];
|
|
((VicCon6*)this->vicConDetails)->locationOfTown.z = map[i+4];
|
|
nr=3;
|
|
break;
|
|
}
|
|
case beatMonster:
|
|
{
|
|
this->vicConDetails = new VicCon7();
|
|
((VicCon7*)this->vicConDetails)->locationOfMonster.x = map[i+2];
|
|
((VicCon7*)this->vicConDetails)->locationOfMonster.y = map[i+3];
|
|
((VicCon7*)this->vicConDetails)->locationOfMonster.z = map[i+4];
|
|
nr=3;
|
|
break;
|
|
}
|
|
case takeDwellings:
|
|
{
|
|
this->vicConDetails = new CspecificVictoryConidtions();
|
|
nr=3;
|
|
break;
|
|
}
|
|
case takeMines:
|
|
{
|
|
this->vicConDetails = new CspecificVictoryConidtions();
|
|
nr=3;
|
|
break;
|
|
}
|
|
case transportItem:
|
|
{
|
|
this->vicConDetails = new VicCona();
|
|
((VicCona*)this->vicConDetails)->artifactID = map[i+2];
|
|
((VicCona*)this->vicConDetails)->destinationPlace.x = map[i+3];
|
|
((VicCona*)this->vicConDetails)->destinationPlace.y = map[i+4];
|
|
((VicCona*)this->vicConDetails)->destinationPlace.z = map[i+5];
|
|
nr=4;
|
|
break;
|
|
}
|
|
}
|
|
this->vicConDetails->allowNormalVictory = map[i++];
|
|
this->vicConDetails->appliesToAI = map[i++];
|
|
i+=nr;
|
|
}
|
|
this->lossCondition.typeOfLossCon = (ElossCon)map[i++];
|
|
switch (this->lossCondition.typeOfLossCon) //read loss conditions
|
|
{
|
|
case lossCastle:
|
|
{
|
|
this->lossCondition.castlePos.x=map[i++];
|
|
this->lossCondition.castlePos.y=map[i++];
|
|
this->lossCondition.castlePos.z=map[i++];
|
|
}
|
|
case lossHero:
|
|
{
|
|
this->lossCondition.heroPos.x=map[i++];
|
|
this->lossCondition.heroPos.y=map[i++];
|
|
this->lossCondition.heroPos.z=map[i++];
|
|
}
|
|
case timeExpires:
|
|
{
|
|
this->lossCondition.timeLimit = readNormalNr(map, i++,2);
|
|
i++;
|
|
}
|
|
}
|
|
this->howManyTeams=map[i++]; //read number of teams
|
|
if(this->howManyTeams>0) //read team numbers
|
|
{
|
|
for(int rr=0; rr<8; ++rr)
|
|
{
|
|
this->players[rr].team=map[i++];
|
|
}
|
|
}
|
|
} |