#define VCMI_DLL #include "stdafx.h" #include "map.h" #include "hch/CObjectHandler.h" #include "hch/CDefObjInfoHandler.h" #include "lib/VCMI_Lib.h" #include #include std::set convertBuildings(const std::set h3m, int castleID) { std::map mapa; std::set ret; std::ifstream b5("config/buildings5.txt"); while(!b5.eof()) { int a, b; b5 >> a >> b; if(castleID==8 && b==17) //magic university ID 17 (h3m) => 21 (vcmi) b=21; mapa[a]=b; } for(std::set::const_iterator i=h3m.begin();i!=h3m.end();i++) { if(mapa[*i]>=0) ret.insert(mapa[*i]); else if(mapa[*i] >= (-CREATURES_PER_TOWN)) // horde buildings { int level = (-mapa[*i]); if(h3m.find(20+(level*3)) != h3m.end()) //upgraded creature horde building { if(((castleID==1) || (castleID==3)) && ((level==3) || (level==5))) ret.insert(25); else ret.insert(19); } else { if(((castleID==1) || (castleID==3)) && ((level==3) || (level==5))) ret.insert(24); else ret.insert(18); } } else { std::cout<<"Conversion warning: unknown building "<<*i<<" in castle "<>i) { ret |= (128>>i); } } return ret; } EDefType getDefType(CGDefInfo * a) { switch(a->id) { case 5: case 65: case 66: case 67: case 68: case 69: return EDefType::ARTIFACT_DEF; //handled case 6: return EDefType::PANDORA_DEF; //hanled case 26: return EDefType::EVENTOBJ_DEF; //handled case 33: return EDefType::GARRISON_DEF; //handled case 34: case 70: case 62: //70 - random hero //62 - prison return EDefType::HERO_DEF; //handled case 36: return EDefType::GRAIL_DEF; //hanled case 53: case 17: case 18: case 19: case 20: case 42: case 87: case 220://cases 17 - 20 and 42 - tests return EDefType::PLAYERONLY_DEF; //handled case 54: case 71: case 72: case 73: case 74: case 75: case 162: case 163: case 164: return EDefType::CREATURES_DEF; //handled case 59: return EDefType::SIGN_DEF; //handled case 77: return EDefType::TOWN_DEF; //can be problematic, but handled case 79: case 76: return EDefType::RESOURCE_DEF; //handled case 81: return EDefType::SCHOLAR_DEF; //handled case 83: return EDefType::SEERHUT_DEF; //handled case 91: return EDefType::SIGN_DEF; //handled case 88: case 89: case 90: return SHRINE_DEF; //handled case 93: return SPELLSCROLL_DEF; //handled case 98: return EDefType::TOWN_DEF; //handled case 113: return EDefType::WITCHHUT_DEF; //handled case 214: return EDefType::HEROPLACEHOLDER_DEF; //partially handled case 215: return EDefType::BORDERGUARD_DEF; //handled by analogy to seer huts ;] case 216: return EDefType::CREGEN2_DEF; //handled case 217: return EDefType::CREGEN_DEF; //handled case 218: return EDefType::CREGEN3_DEF; //handled case 219: return EDefType::GARRISON_DEF; //handled default: return EDefType::TERRAINOBJ_DEF; // nothing to be handled } } int readNormalNr (unsigned char * bufor, int pos, int bytCon = 4, bool cyclic = false) { int ret=0; int amp=1; for (int ir=0; ir=amp/2) { ret = ret-amp; } return ret; } char readChar(unsigned char * bufor, int &i) { return bufor[i++]; } std::string readString(unsigned char * bufor, int &i) { int len = readNormalNr(bufor,i); i+=4; std::string ret; ret.reserve(len); for(int gg=0; ggRoE maps { if(version) { CCreatureSet ret; std::pair ins; for(int ir=0;ir32768) rettt = 65536-rettt+VLC->creh->creatures.size()-16; ins.first = &(VLC->creh->creatures[rettt]); ins.second = readNormalNr(bufor,i+ir*4+2, 2); std::pair > tt(ir,ins); ret.slots.insert(tt); } i+=number*4; return ret; } else { CCreatureSet ret; std::pair ins; for(int ir=0;ir220) rettt = 256-rettt+VLC->creh->creatures.size()-16; ins.first = &(VLC->creh->creatures[rettt]); ins.second = readNormalNr(bufor,i+ir*3+1, 2); std::pair > tt(ir,ins); ret.slots.insert(tt); } i+=number*3; return ret; } } 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-14name+=map[i++]; length = map[i] + map[i+1]*256; //description length i+=4; for (pom=0;pomdescription+=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;ppplayers[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++]; } } } void Mapa::initFromBytes(unsigned char * bufor) { THC timeHandler th; th.getDif(); int i=0; version = (Eformat)(readNormalNr(bufor,i)); i+=4; //map version areAnyPLayers = readChar(bufor,i); //invalid on some maps height = width = (readNormalNr(bufor,i)); i+=4; // wymiary mapy twoLevel = readChar(bufor,i); //czy sa lochy terrain = new TerrainTile*[width]; // allocate memory for (int ii=0;iiArtifactID = bufor[i+2]; nr=(version==RoE ? 1 : 2); break; } case gatherTroop: { vicConDetails = new VicCon1(); int temp1 = bufor[i+2]; int temp2 = bufor[i+3]; ((VicCon1*)vicConDetails)->monsterID = bufor[i+2]; ((VicCon1*)vicConDetails)->neededQuantity=readNormalNr(bufor,i+(version==RoE ? 3 : 4)); nr=(version==RoE ? 5 : 6); break; } case gatherResource: { vicConDetails = new VicCon2(); ((VicCon2*)vicConDetails)->resourceID = bufor[i+2]; ((VicCon2*)vicConDetails)->neededQuantity=readNormalNr(bufor,i+3); nr=5; break; } case buildCity: { vicConDetails = new VicCon3(); ((VicCon3*)vicConDetails)->posOfCity.x = bufor[i+2]; ((VicCon3*)vicConDetails)->posOfCity.y = bufor[i+3]; ((VicCon3*)vicConDetails)->posOfCity.z = bufor[i+4]; ((VicCon3*)vicConDetails)->councilNeededLevel = bufor[i+5]; ((VicCon3*)vicConDetails)->fortNeededLevel = bufor[i+6]; nr=5; break; } case buildGrail: { vicConDetails = new VicCon4(); if (bufor[i+4]>2) ((VicCon4*)vicConDetails)->anyLocation = true; else { ((VicCon4*)vicConDetails)->whereBuildGrail.x = bufor[i+2]; ((VicCon4*)vicConDetails)->whereBuildGrail.y = bufor[i+3]; ((VicCon4*)vicConDetails)->whereBuildGrail.z = bufor[i+4]; } nr=3; break; } case beatHero: { vicConDetails = new VicCon5(); ((VicCon5*)vicConDetails)->locationOfHero.x = bufor[i+2]; ((VicCon5*)vicConDetails)->locationOfHero.y = bufor[i+3]; ((VicCon5*)vicConDetails)->locationOfHero.z = bufor[i+4]; nr=3; break; } case captureCity: { vicConDetails = new VicCon6(); ((VicCon6*)vicConDetails)->locationOfTown.x = bufor[i+2]; ((VicCon6*)vicConDetails)->locationOfTown.y = bufor[i+3]; ((VicCon6*)vicConDetails)->locationOfTown.z = bufor[i+4]; nr=3; break; } case beatMonster: { vicConDetails = new VicCon7(); ((VicCon7*)vicConDetails)->locationOfMonster.x = bufor[i+2]; ((VicCon7*)vicConDetails)->locationOfMonster.y = bufor[i+3]; ((VicCon7*)vicConDetails)->locationOfMonster.z = bufor[i+4]; nr=3; break; } case takeDwellings: { vicConDetails = new CspecificVictoryConidtions(); nr=0; break; } case takeMines: { vicConDetails = new CspecificVictoryConidtions(); nr=0; break; } case transportItem: { vicConDetails = new VicCona(); ((VicCona*)vicConDetails)->artifactID = bufor[i+2]; ((VicCona*)vicConDetails)->destinationPlace.x = bufor[i+3]; ((VicCona*)vicConDetails)->destinationPlace.y = bufor[i+4]; ((VicCona*)vicConDetails)->destinationPlace.z = bufor[i+5]; nr=4; break; } } vicConDetails->allowNormalVictory = bufor[i++]; vicConDetails->appliesToAI = bufor[i++]; i+=nr; } lossCondition.typeOfLossCon = (ElossCon)bufor[i++]; switch (lossCondition.typeOfLossCon) //read loss conditions { case lossCastle: { lossCondition.castlePos.x=bufor[i++]; lossCondition.castlePos.y=bufor[i++]; lossCondition.castlePos.z=bufor[i++]; break; } case lossHero: { lossCondition.heroPos.x=bufor[i++]; lossCondition.heroPos.y=bufor[i++]; lossCondition.heroPos.z=bufor[i++]; break; } case timeExpires: { lossCondition.timeLimit = readNormalNr(bufor,i++,2); i++; break; } } howManyTeams=bufor[i++]; //read number of teams if(howManyTeams>0) //read team numbers { for(int rr=0; rr<8; ++rr) { players[rr].team=bufor[i++]; } } //reading allowed heroes (20 bytes) int ist; ist=i; //starting i for loop allowedHeroes.resize(HEROES_QUANTITY); for(int xx=0;xxRoE) //probably reserved for further heroes i+=4; unsigned char disp = 0; if(version>=SoD) { disp = bufor[i++]; disposedHeroes.resize(disp); for(int g=0; g=SoD) { //reading allowed spells (9 bytes) ist=i; //starting i for loop for(i; iID = 34; cgh->subID = z; if(readChar(bufor,i))//true if hore's experience is greater than 0 { cgh->exp = readNormalNr(bufor,i); i+=4; } else cgh->exp = 0; if(readChar(bufor,i))//true if hero has specified abilities { int howMany = readNormalNr(bufor,i); i+=4; cgh->secSkills.resize(howMany); for(int yy=0; yysecSkills[yy].first = readNormalNr(bufor,i, 1); ++i; cgh->secSkills[yy].second = readNormalNr(bufor,i, 1); ++i; } } bool artSet = bufor[i]; ++i; //true if artifact set is not default (hero has some artifacts) int artmask = version == RoE ? 0xff : 0xffff; int artidlen = version == RoE ? 1 : 2; if(artSet) { for(int pom=0;pom<16;pom++) { int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) cgh->artifWorn[pom] = id; } //misc5 art //17 if(version>=SoD) { i+=2; //int id = readNormalNr(bufor,i, artidlen); i+=artidlen; //if(id!=artmask) // spec->artifWorn[16] = id; } //spellbook int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) cgh->artifWorn[17] = id; //19 //???what is that? gap in file or what? - it's probably fifth slot.. if(version>RoE) { id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) cgh->artifWorn[18] = id; } else i+=1; //bag artifacts //20 int amount = readNormalNr(bufor,i, 2); i+=2; //number of artifacts in hero's bag if(amount>0) { for(int ss=0; ssartifacts.push_back(id); } } } //artifacts if(readChar(bufor,i))//customBio cgh->biography = readString(bufor,i); int sex = bufor[i++]; // 0xFF is default, 00 male, 01 female if(readChar(bufor,i))//are spells { int ist = i; for(i; ispells.insert((i-ist)*8+yy); } } } } if(readChar(bufor,i))//customPrimSkills { cgh->primSkills.resize(4); for(int xx=0;xx<4;xx++) cgh->primSkills[xx] = bufor[i++]; } predefinedHeroes.push_back(cgh); } break; } case RoE: i+=0; break; } for (int c=0; cname.reserve(nameLength); for (int cd=0;cdname += bufor[i++]; } std::transform(vinya->name.begin(),vinya->name.end(),vinya->name.begin(),(int(*)(int))toupper); unsigned char bytes[12]; for (int v=0; v<12; v++) // read info { bytes[v] = bufor[i++]; } vinya->terrainAllowed = readNormalNr(bufor,i,2);i+=2; vinya->terrainMenu = readNormalNr(bufor,i,2);i+=2; vinya->id = readNormalNr(bufor,i,4);i+=4; vinya->subid = readNormalNr(bufor,i,4);i+=4; vinya->type = bufor[i++]; vinya->printPriority = bufor[i++]; for (int zi=0; zi<6; zi++) { vinya->blockMap[zi] = reverse(bytes[zi]); } for (int zi=0; zi<6; zi++) { vinya->visitMap[zi] = reverse(bytes[6+zi]); } i+=16; defy.push_back(vinya); // add this def to the vector } THC std::cout<<"\tReading defs info: "<defInfo->id; int p = 99; switch(getDefType(nobj->defInfo)) { case EDefType::EVENTOBJ_DEF: //for event - objects { CEventObjInfo * spec = new CEventObjInfo; bool guardMess; guardMess = bufor[i]; ++i; if(guardMess) { int messLong = readNormalNr(bufor,i, 4); i+=4; if(messLong>0) { spec->isMessage = true; for(int yy=0; yymessage +=bufor[i+yy]; } i+=messLong; } spec->areGuarders = bufor[i]; ++i; if(spec->areGuarders) { spec->guarders = readCreatureSet(bufor,i,7,(version>RoE)); } i+=4; } else { spec->isMessage = false; spec->areGuarders = false; spec->message = std::string(""); } spec->gainedExp = readNormalNr(bufor,i, 4); i+=4; spec->manaDiff = readNormalNr(bufor,i, 4); i+=4; spec->moraleDiff = readNormalNr(bufor,i, 1, true); ++i; spec->luckDiff = readNormalNr(bufor,i, 1, true); ++i; spec->wood = readNormalNr(bufor,i); i+=4; spec->mercury = readNormalNr(bufor,i); i+=4; spec->ore = readNormalNr(bufor,i); i+=4; spec->sulfur = readNormalNr(bufor,i); i+=4; spec->crystal = readNormalNr(bufor,i); i+=4; spec->gems = readNormalNr(bufor,i); i+=4; spec->gold = readNormalNr(bufor,i); i+=4; spec->attack = readNormalNr(bufor,i, 1); ++i; spec->defence = readNormalNr(bufor,i, 1); ++i; spec->power = readNormalNr(bufor,i, 1); ++i; spec->knowledge = readNormalNr(bufor,i, 1); ++i; int gabn; //number of gained abilities gabn = readNormalNr(bufor,i, 1); ++i; for(int oo = 0; ooabilities.push_back(readNormalNr(bufor,i, 1)); ++i; spec->abilityLevels.push_back(readNormalNr(bufor,i, 1)); ++i; } int gart = readNormalNr(bufor,i, 1); ++i; //number of gained artifacts for(int oo = 0; ooartifacts.push_back(readNormalNr(bufor,i, (version == RoE ? 1 : 2))); i+=(version == RoE ? 1 : 2); } int gspel = readNormalNr(bufor,i, 1); ++i; //number of gained spells for(int oo = 0; oospells.push_back(readNormalNr(bufor,i, 1)); ++i; } int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures spec->creatures = readCreatureSet(bufor,i,gcre,(version>RoE)); if(version>RoE) i+=gcre; i+=8; spec->availableFor = readNormalNr(bufor,i, 1); ++i; spec->computerActivate = readNormalNr(bufor,i, 1); ++i; spec->humanActivate = readNormalNr(bufor,i, 1); ++i; i+=4; nobj->info = spec; break; } case EDefType::HERO_DEF: { CGHeroInstance * nhi = new CGHeroInstance; (*(static_cast(nhi))) = *nobj; delete nobj; nobj=nhi; if(version>RoE) { nhi->identifier = readNormalNr(bufor,i, 4); i+=4; } nhi->setOwner(bufor[i]); ++i; nhi->subID = readNormalNr(bufor,i, 1); ++i; if(readChar(bufor,i))//true if hero has nonstandard name nhi->name = readString(bufor,i); if(version>AB) { if(readChar(bufor,i))//true if hore's experience is greater than 0 { nhi->exp = readNormalNr(bufor,i); i+=4; } else nhi->exp = -1; } else { nhi->exp = readNormalNr(bufor,i); i+=4; } bool portrait=bufor[i]; ++i; if (portrait) i++; //TODO read portrait nr, save, open if(readChar(bufor,i))//true if hero has specified abilities { int howMany = readNormalNr(bufor,i); i+=4; nhi->secSkills.resize(howMany); for(int yy=0; yysecSkills[yy].first = readNormalNr(bufor,i, 1); ++i; nhi->secSkills[yy].second = readNormalNr(bufor,i, 1); ++i; } } 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; int artidlen = version == RoE ? 1 : 2; if(artSet) { for(int pom=0;pom<16;pom++) { int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) nhi->artifWorn[pom] = id; } //misc5 art //17 if(version>=SoD) { int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) nhi->artifWorn[16] = id; } //spellbook int id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) nhi->artifWorn[17] = id; //19 //???what is that? gap in file or what? - it's probably fifth slot.. if(version>RoE) { id = readNormalNr(bufor,i, artidlen); i+=artidlen; if(id!=artmask) nhi->artifWorn[18] = id; } else i+=1; //bag artifacts //20 int amount = readNormalNr(bufor,i, 2); i+=2; //number of artifacts in hero's bag if(amount>0) { for(int ss=0; ssartifacts.push_back(id); } } } //artifacts nhi->patrol.patrolRadious = readNormalNr(bufor,i, 1); ++i; if(nhi->patrol.patrolRadious == 0xff) nhi->patrol.patrolling = false; else nhi->patrol.patrolling = true; if(version>RoE) { if(readChar(bufor,i))//true if hero has nonstandard (mapmaker defined) biography nhi->biography = readString(bufor,i); nhi->sex = !(bufor[i]); ++i; } //spells if(version>AB) { bool areSpells = bufor[i]; ++i; if(areSpells) //TODO: sprawdzić //seems to be ok - tow { int ist = i; for(i; ispells.insert((i-ist)*8+yy); } } } } } else if(version==AB) //we can read one spell { unsigned char buff = bufor[i]; ++i; if(buff!=254) { nhi->spells.insert(buff); } } //spells loaded if(version>AB) { if(readChar(bufor,i))//customPrimSkills { nhi->primSkills.resize(4); for(int xx=0;xx<4;xx++) nhi->primSkills[xx] = bufor[i++]; } } i+=16; nhi->moveDir = 4; nhi->isStanding = true; nhi->level = -1; nhi->mana = -1; nhi->movement = -1; if(nhi->ID==34) heroes.push_back(nhi); break; } case CREATURES_DEF: { CCreatureObjInfo * spec = new CCreatureObjInfo; if(version>RoE) { spec->bytes[0] = bufor[i]; ++i; spec->bytes[1] = bufor[i]; ++i; spec->bytes[2] = bufor[i]; ++i; spec->bytes[3] = bufor[i]; ++i; } spec->number = readNormalNr(bufor,i, 2); i+=2; spec->character = bufor[i]; ++i; bool isMesTre = bufor[i]; ++i; //true if there is message or treasury if(isMesTre) { int messLength = readNormalNr(bufor,i); i+=4; if(messLength>0) { for(int tt=0; ttmessage += bufor[i]; ++i; } } spec->wood = readNormalNr(bufor,i); i+=4; spec->mercury = readNormalNr(bufor,i); i+=4; spec->ore = readNormalNr(bufor,i); i+=4; spec->sulfur = readNormalNr(bufor,i); i+=4; spec->crytal = readNormalNr(bufor,i); i+=4; spec->gems = readNormalNr(bufor,i); i+=4; spec->gold = readNormalNr(bufor,i); i+=4; int artID = readNormalNr(bufor,i, (version == RoE ? 1 : 2)); i+=(version == RoE ? 1 : 2); if(version==RoE) { if(artID!=0xff) spec->gainedArtifact = artID; else spec->gainedArtifact = -1; } else { if(artID!=0xffff) spec->gainedArtifact = artID; else spec->gainedArtifact = -1; } } spec->neverFlees = bufor[i]; ++i; spec->notGrowingTeam = bufor[i]; ++i; i+=2; nobj->info = spec; break; } case EDefType::SIGN_DEF: { CSignObjInfo * spec = new CSignObjInfo; int length = readNormalNr(bufor,i); i+=4; for(int rr=0; rrmessage += bufor[i]; ++i; } i+=4; nobj->info = spec; break; } case EDefType::SEERHUT_DEF: { CSeerHutObjInfo * spec = new CSeerHutObjInfo; if(version>RoE) { spec->missionType = bufor[i]; ++i; switch(spec->missionType) { case 0: i+=3; continue; case 1: { spec->m1level = readNormalNr(bufor,i); i+=4; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 2: { spec->m2attack = bufor[i]; ++i; spec->m2defence = bufor[i]; ++i; spec->m2power = bufor[i]; ++i; spec->m2knowledge = bufor[i]; ++i; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 3: { spec->m3bytes[0] = bufor[i]; ++i; spec->m3bytes[1] = bufor[i]; ++i; spec->m3bytes[2] = bufor[i]; ++i; spec->m3bytes[3] = bufor[i]; ++i; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 4: { spec->m4bytes[0] = bufor[i]; ++i; spec->m4bytes[1] = bufor[i]; ++i; spec->m4bytes[2] = bufor[i]; ++i; spec->m4bytes[3] = bufor[i]; ++i; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 5: { int artNumber = bufor[i]; ++i; for(int yy=0; yym5arts.push_back(artid); } int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 6: { int typeNumber = bufor[i]; ++i; for(int hh=0; hhm6cre.push_back(&(VLC->creh->creatures[creType])); spec->m6number.push_back(creNumb); } int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 7: { spec->m7wood = readNormalNr(bufor,i); i+=4; spec->m7mercury = readNormalNr(bufor,i); i+=4; spec->m7ore = readNormalNr(bufor,i); i+=4; spec->m7sulfur = readNormalNr(bufor,i); i+=4; spec->m7crystal = readNormalNr(bufor,i); i+=4; spec->m7gems = readNormalNr(bufor,i); i+=4; spec->m7gold = readNormalNr(bufor,i); i+=4; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 8: { int heroType = bufor[i]; ++i; spec->m8hero = heroType; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 9: { spec->m9player = bufor[i]; ++i; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } }//internal switch end (seer huts) int len1 = readNormalNr(bufor,i); i+=4; for(int ee=0; eefirstVisitText += bufor[i]; ++i; } int len2 = readNormalNr(bufor,i); i+=4; for(int ee=0; eenextVisitText += bufor[i]; ++i; } int len3 = readNormalNr(bufor,i); i+=4; for(int ee=0; eecompletedText += bufor[i]; ++i; } } else //RoE { int artID = bufor[i]; ++i; if(artID!=255) //not none quest { spec->m5arts.push_back(artID); spec->missionType = 5; } else { spec->missionType = 255; } } if(spec->missionType!=255) { unsigned char rewardType = bufor[i]; ++i; spec->rewardType = rewardType; switch(rewardType) { case 1: { spec->r1exp = readNormalNr(bufor,i); i+=4; break; } case 2: { spec->r2mana = readNormalNr(bufor,i); i+=4; break; } case 3: { spec->r3morale = bufor[i]; ++i; break; } case 4: { spec->r4luck = bufor[i]; ++i; break; } case 5: { spec->r5type = bufor[i]; ++i; spec->r5amount = readNormalNr(bufor,i, 3); i+=3; i+=1; break; } case 6: { spec->r6type = bufor[i]; ++i; spec->r6amount = bufor[i]; ++i; break; } case 7: { spec->r7ability = bufor[i]; ++i; spec->r7level = bufor[i]; ++i; break; } case 8: { spec->r8art = readNormalNr(bufor,i, (version == RoE ? 1 : 2)); i+=(version == RoE ? 1 : 2); break; } case 9: { spec->r9spell = bufor[i]; ++i; break; } case 10: { if(version>RoE) { spec->r10creature = readNormalNr(bufor,i, 2); i+=2; spec->r10amount = readNormalNr(bufor,i, 2); i+=2; } else { spec->r10creature = bufor[i]; ++i; spec->r10amount = readNormalNr(bufor,i, 2); i+=2; } break; } }// end of internal switch i+=2; } else //missionType==255 { i+=3; } nobj->info = spec; break; } case EDefType::WITCHHUT_DEF: { CWitchHutObjInfo * spec = new CWitchHutObjInfo; if(version>RoE) //in reo we cannot specify it - all are allowed (I hope) { ist=i; //starting i for loop for(i; iallowedAbilities.push_back((i-ist)*8+yy); } } } } else //(RoE map) { for(int gg=0; ggallowedAbilities.push_back(gg); } } nobj->info = spec; break; } case EDefType::SCHOLAR_DEF: { CScholarObjInfo * spec = new CScholarObjInfo; spec->bonusType = bufor[i]; ++i; switch(spec->bonusType) { case 0xff: ++i; break; case 0: spec->r0type = bufor[i]; ++i; break; case 1: spec->r1 = bufor[i]; ++i; break; case 2: spec->r2 = bufor[i]; ++i; break; } i+=6; nobj->info = spec; break; } case EDefType::GARRISON_DEF: { CGarrisonObjInfo * spec = new CGarrisonObjInfo; spec->player = bufor[i]; ++i; i+=3; spec->units = readCreatureSet(bufor,i,7,(version>RoE)); if(version > RoE) { spec->movableUnits = bufor[i]; ++i; } else spec->movableUnits = true; i+=8; nobj->setOwner(spec->player); nobj->info = spec; break; } case EDefType::ARTIFACT_DEF: { CArtifactObjInfo * spec = new CArtifactObjInfo; bool areSettings = bufor[i]; ++i; if(areSettings) { int messLength = readNormalNr(bufor,i, 4); i+=4; for(int hh=0; hhmessage += bufor[i]; ++i; } bool areGuards = bufor[i]; ++i; if(areGuards) { spec->areGuards = true; spec->guards = readCreatureSet(bufor,i,7,(version>RoE)); } else spec->areGuards = false; i+=4; } nobj->info = spec; break; } case EDefType::RESOURCE_DEF: { CResourceObjInfo * spec = new CResourceObjInfo; bool isMessGuard = bufor[i]; ++i; if(isMessGuard) { int messLength = readNormalNr(bufor,i); i+=4; for(int mm=0; mmmessage+=bufor[i]; ++i; } spec->areGuards = bufor[i]; ++i; if(spec->areGuards) { spec->guards = readCreatureSet(bufor,i,7,(version>RoE)); } i+=4; } else { spec->areGuards = false; } spec->amount = readNormalNr(bufor,i); i+=4; i+=4; nobj->info = spec; break; } case EDefType::TOWN_DEF: { CGTownInstance * nt = new CGTownInstance(); (*(static_cast(nt))) = *nobj; delete nobj; nobj = nt; nt->identifier = 0; if(version>RoE) { readNormalNr(bufor,i); i+=4; } nt->tempOwner = bufor[i]; ++i; if(readChar(bufor,i)) //has name nt->name = readString(bufor,i); if(readChar(bufor,i))//true if garrison isn't empty nt->army = readCreatureSet(bufor,i,7,(version>RoE)); nt->army.formation = bufor[i]; ++i; if(readChar(bufor,i)) //unusualBuildings { //built buildings for(int byte=0;byte<6;byte++) { for(int bit=0;bit<8;bit++) if(bufor[i] & (1<builtBuildings.insert(byte*8+bit); i++; } //forbidden buildings for(int byte=6;byte<12;byte++) { for(int bit=0;bit<8;bit++) if(bufor[i] & (1<forbiddenBuildings.insert(byte*8+bit); i++; } nt->builtBuildings = convertBuildings(nt->builtBuildings,nt->subID); nt->forbiddenBuildings = convertBuildings(nt->forbiddenBuildings,nt->subID); } else //standard buildings { if(readChar(bufor,i)) //has fort nt->builtBuildings.insert(7); nt->builtBuildings.insert(-50); //means that set of standard building should be included } int ist = i; if(version>RoE) { for(i; iobligatorySpells.push_back((i-ist)*8+yy); } } } } ist = i; for(i; ipossibleSpells.push_back((i-ist)*8+yy); } } } /////// reading castle events ////////////////////////////////// int numberOfEvent = readNormalNr(bufor,i); i+=4; for(int gh = 0; gh AB) { nce.forHuman = bufor[i]; ++i; } else nce.forHuman = true; nce.forComputer = bufor[i]; ++i; nce.firstShow = readNormalNr(bufor,i, 2); i+=2; nce.forEvery = bufor[i]; ++i; i+=17; for(int kk=0; kk<6; ++kk) { nce.bytes[kk] = bufor[i]; ++i; } for(int vv=0; vv<7; ++vv) { nce.gen[vv] = readNormalNr(bufor,i, 2); i+=2; } i+=4; nt->events.insert(nce); }//castle events have been read if(version > AB) { nt->alignment = bufor[i]; ++i; } else nt->alignment = 0xff; i+=3; nt->builded = 0; nt->destroyed = 0; nt->garrisonHero = NULL; if(nt->ID==98) towns.push_back(nt); break; } case EDefType::PLAYERONLY_DEF: { CPlayerOnlyObjInfo * spec = new CPlayerOnlyObjInfo; spec->player = bufor[i]; ++i; i+=3; nobj->setOwner(spec->player); nobj->info = spec; break; } case EDefType::SHRINE_DEF: { CShrineObjInfo * spec = new CShrineObjInfo; spec->spell = bufor[i]; i+=4; nobj->info = spec; break; } case EDefType::SPELLSCROLL_DEF: { CSpellScrollObjinfo * spec = new CSpellScrollObjinfo; bool messg = bufor[i]; ++i; if(messg) { int mLength = readNormalNr(bufor,i); i+=4; for(int vv=0; vvmessage += bufor[i]; ++i; } spec->areGuarders = bufor[i]; ++i; if(spec->areGuarders) { spec->guarders = readCreatureSet(bufor,i,7,(version>RoE)); } i+=4; } spec->spell = bufor[i]; ++i; i+=3; nobj->info = spec; break; } case EDefType::PANDORA_DEF: { CPandorasBoxObjInfo * spec = new CPandorasBoxObjInfo; bool messg = bufor[i]; ++i; if(messg) { int mLength = readNormalNr(bufor,i); i+=4; for(int vv=0; vvmessage += bufor[i]; ++i; } spec->areGuarders = bufor[i]; ++i; if(spec->areGuarders) { spec->guarders = readCreatureSet(bufor,i,7,(version>RoE)); } i+=4; } ////// copied form event handling (seems to be similar) spec->gainedExp = readNormalNr(bufor,i, 4); i+=4; spec->manaDiff = readNormalNr(bufor,i, 4); i+=4; spec->moraleDiff = readNormalNr(bufor,i, 1, true); ++i; spec->luckDiff = readNormalNr(bufor,i, 1, true); ++i; spec->wood = readNormalNr(bufor,i); i+=4; spec->mercury = readNormalNr(bufor,i); i+=4; spec->ore = readNormalNr(bufor,i); i+=4; spec->sulfur = readNormalNr(bufor,i); i+=4; spec->crystal = readNormalNr(bufor,i); i+=4; spec->gems = readNormalNr(bufor,i); i+=4; spec->gold = readNormalNr(bufor,i); i+=4; spec->attack = readNormalNr(bufor,i, 1); ++i; spec->defence = readNormalNr(bufor,i, 1); ++i; spec->power = readNormalNr(bufor,i, 1); ++i; spec->knowledge = readNormalNr(bufor,i, 1); ++i; int gabn; //number of gained abilities gabn = readNormalNr(bufor,i, 1); ++i; for(int oo = 0; ooabilities.push_back(readNormalNr(bufor,i, 1)); ++i; spec->abilityLevels.push_back(readNormalNr(bufor,i, 1)); ++i; } int gart = readNormalNr(bufor,i, 1); ++i; //number of gained artifacts for(int oo = 0; oo RoE) { spec->artifacts.push_back(readNormalNr(bufor,i, 2)); i+=2; } else { spec->artifacts.push_back(readNormalNr(bufor,i, 1)); i+=1; } } int gspel = readNormalNr(bufor,i, 1); ++i; //number of gained spells for(int oo = 0; oospells.push_back(readNormalNr(bufor,i, 1)); ++i; } int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures spec->creatures = readCreatureSet(bufor,i,gcre,(version>RoE)); if(version > RoE) i+=gcre; i+=8; nobj->info = spec; ///////end of copied fragment break; } case EDefType::GRAIL_DEF: { CGrailObjInfo * spec = new CGrailObjInfo; spec->radius = readNormalNr(bufor,i); i+=4; nobj->info = spec; break; } case EDefType::CREGEN_DEF: { CCreGenObjInfo * spec = new CCreGenObjInfo; spec->player = readNormalNr(bufor,i); i+=4; spec->identifier = readNormalNr(bufor,i); i+=4; if(!spec->identifier) { spec->asCastle = false; spec->castles[0] = bufor[i]; ++i; spec->castles[1] = bufor[i]; ++i; } else { spec->asCastle = true; } nobj->setOwner(spec->player); nobj->info = spec; break; } case EDefType::CREGEN2_DEF: { CCreGen2ObjInfo * spec = new CCreGen2ObjInfo; spec->player = readNormalNr(bufor,i); i+=4; spec->identifier = readNormalNr(bufor,i); i+=4; if(!spec->identifier) { spec->asCastle = false; spec->castles[0] = bufor[i]; ++i; spec->castles[1] = bufor[i]; ++i; } else { spec->asCastle = true; } spec->minLevel = bufor[i]; ++i; spec->maxLevel = bufor[i]; ++i; //if(spec->maxLevel>7) // spec->maxLevel = 7; //if(spec->minLevel<1) // spec->minLevel = 1; nobj->setOwner(spec->player); nobj->info = spec; break; } case EDefType::CREGEN3_DEF: { CCreGen3ObjInfo * spec = new CCreGen3ObjInfo; spec->player = bufor[i]; ++i; i+=3; spec->minLevel = bufor[i]; ++i; spec->maxLevel = bufor[i]; ++i; if(spec->maxLevel>7) spec->maxLevel = 7; if(spec->minLevel<1) spec->minLevel = 1; nobj->setOwner(spec->player); nobj->info = spec; break; } case EDefType::BORDERGUARD_DEF: { CBorderGuardObjInfo * spec = new CBorderGuardObjInfo; spec->missionType = bufor[i]; ++i; switch(spec->missionType) { case 0: { goto borderguardend; break; } case 1: { spec->m1level = readNormalNr(bufor,i); i+=4; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 2: { spec->m2attack = bufor[i]; ++i; spec->m2defence = bufor[i]; ++i; spec->m2power = bufor[i]; ++i; spec->m2knowledge = bufor[i]; ++i; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 3: { spec->m3bytes[0] = bufor[i]; ++i; spec->m3bytes[1] = bufor[i]; ++i; spec->m3bytes[2] = bufor[i]; ++i; spec->m3bytes[3] = bufor[i]; ++i; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 4: { spec->m4bytes[0] = bufor[i]; ++i; spec->m4bytes[1] = bufor[i]; ++i; spec->m4bytes[2] = bufor[i]; ++i; spec->m4bytes[3] = bufor[i]; ++i; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 5: { int artNumber = bufor[i]; ++i; for(int yy=0; yym5arts.push_back(readNormalNr(bufor,i, 2)); i+=2; } int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 6: { int typeNumber = bufor[i]; ++i; for(int hh=0; hhm6cre.push_back(&(VLC->creh->creatures[creType])); spec->m6number.push_back(creNumb); } int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 7: { spec->m7wood = readNormalNr(bufor,i); i+=4; spec->m7mercury = readNormalNr(bufor,i); i+=4; spec->m7ore = readNormalNr(bufor,i); i+=4; spec->m7sulfur = readNormalNr(bufor,i); i+=4; spec->m7crystal = readNormalNr(bufor,i); i+=4; spec->m7gems = readNormalNr(bufor,i); i+=4; spec->m7gold = readNormalNr(bufor,i); i+=4; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 8: { int heroType = bufor[i]; ++i; spec->m8hero = heroType; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } case 9: { spec->m9player = bufor[i]; ++i; int limit = readNormalNr(bufor,i); i+=4; if(limit == ((int)0xffffffff)) { spec->isDayLimit = false; spec->lastDay = -1; } else { spec->isDayLimit = true; spec->lastDay = limit; } break; } }//internal switch end (seer huts) int len1 = readNormalNr(bufor,i); i+=4; for(int ee=0; eefirstVisitText += bufor[i]; ++i; } int len2 = readNormalNr(bufor,i); i+=4; for(int ee=0; eenextVisitText += bufor[i]; ++i; } int len3 = readNormalNr(bufor,i); i+=4; for(int ee=0; eecompletedText += bufor[i]; ++i; } nobj->info = spec; borderguardend: break; } case EDefType::HEROPLACEHOLDER_DEF: { i+=3; //TODO: handle it more properly break; } } //end of main switch objects.push_back(nobj); }//end of loading objects THC std::cout<<"\tReading objects: "<AB) { ne.humanAffected = bufor[i]; ++i; } else ne.humanAffected = true; ne.computerAffected = bufor[i]; ++i; ne.firstOccurence = bufor[i]; ++i; ne.nextOccurence = bufor[i]; ++i; i+=18; events.push_back(ne); } //map readed, bufor no longer needed delete[] bufor; bufor=NULL; for(int f=0; fdefInfo) continue; CDefHandler * curd = objects[f]->defInfo->handler; for(int fx=0; fx<8; ++fx) { for(int fy=0; fy<6; ++fy) { int xVal = objects[f]->pos.x + fx - 7; int yVal = objects[f]->pos.y + fy - 5; int zVal = objects[f]->pos.z; if(xVal>=0 && xVal=0 && yValdefInfo->visitMap[fy] >> (7 - fx)) & 1)) { curt.visitableObjects.push_back(objects[f]); curt.visitable = true; } if(!((objects[f]->defInfo->blockMap[fy] >> (7 - fx)) & 1)) curt.blocked = true; } } } } } Mapa::Mapa(std::string filename) { std::cout<<"Opening map file: "< mapstr; int pom; while((pom=gzgetc(map))>=0) { mapstr.push_back(pom); } gzclose(map); unsigned char *initTable = new unsigned char[mapstr.size()]; for(int ss=0; ssgetHero: This mode is not supported!"); for(int i=0; isubID == ID) return heroes[i]; return NULL; }