From 7dc0d6878ece48e9e03f834a59cf59f8f07f8ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Mon, 23 Apr 2012 19:56:37 +0000 Subject: [PATCH] Rewritten battle obstacles. New file for lib: CObstacleInstance.cpp. Now obstacles should be placed exactly like they were in OH3. All problems with displaying obstacles in battlefield should be gone. They should be now matched to the single pixel. If there are still some discrepancies, please report them. --- client/BattleInterface/CBattleInterface.cpp | 58 +- client/BattleInterface/CBattleInterface.h | 2 + config/obstacles.json | 1348 +++++++++++++++++-- lib/BattleState.cpp | 224 ++- lib/BattleState.h | 3 + lib/CCreatureSet.cpp | 2 +- lib/CGameState.cpp | 24 +- lib/CGameState.h | 2 +- lib/CHeroHandler.cpp | 131 +- lib/CHeroHandler.h | 31 +- lib/CMapInfo.cpp | 4 +- lib/CObstacleInstance.h | 19 +- lib/GameConstants.h | 31 + lib/JsonNode.h | 13 + lib/VCMI_lib.vcxproj | 1 + server/CGameHandler.cpp | 13 +- 16 files changed, 1606 insertions(+), 300 deletions(-) diff --git a/client/BattleInterface/CBattleInterface.cpp b/client/BattleInterface/CBattleInterface.cpp index 9e627d0a5..07417d250 100644 --- a/client/BattleInterface/CBattleInterface.cpp +++ b/client/BattleInterface/CBattleInterface.cpp @@ -270,10 +270,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe for(int h = 0; h < bfield.size(); ++h) { bfield[h].myNumber = h; - - int x = 14 + ((h/GameConstants::BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(h%GameConstants::BFIELD_WIDTH); - int y = 86 + 42 * (h/GameConstants::BFIELD_WIDTH); - bfield[h].pos = genRect(cellShade->h, cellShade->w, x + pos.x, y + pos.y); + bfield[h].pos = hexPosition(h); bfield[h].accessible = true; bfield[h].myInterface = this; } @@ -341,10 +338,20 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe std::vector obst = curInt->cb->battleGetAllObstacles(); for(size_t t = 0; t < obst.size(); ++t) { - idToObstacle[obst[t].ID] = CDefHandler::giveDef(CGI->heroh->obstacles.find(obst[t].ID)->second.defName); - for(size_t n = 0; n < idToObstacle[obst[t].ID]->ourImages.size(); ++n) + int ID = obst[t].ID; + std::string gfxName = obst[t].getInfo().defName; + + if(!obst[t].isAbsoluteObstacle) { - SDL_SetColorKey(idToObstacle[obst[t].ID]->ourImages[n].bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(idToObstacle[obst[t].ID]->ourImages[n].bitmap->format,0,255,255)); + idToObstacle[ID] = CDefHandler::giveDef(gfxName); + for(size_t n = 0; n < idToObstacle[ID]->ourImages.size(); ++n) + { + SDL_SetColorKey(idToObstacle[ID]->ourImages[n].bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(idToObstacle[ID]->ourImages[n].bitmap->format,0,255,255)); + } + } + else + { + idToAbsoluteObstacle[ID] = BitmapHandler::loadBitmap(gfxName); } } @@ -625,10 +632,15 @@ void CBattleInterface::show(SDL_Surface * to) //preparing obstacles to be shown std::vector obstacles = curInt->cb->battleGetAllObstacles(); std::multimap hexToObstacle; + for(size_t b = 0; b < obstacles.size(); ++b) { - BattleHex position = CGI->heroh->obstacles.find(obstacles[b].ID)->second.getMaxBlocked(obstacles[b].pos); - hexToObstacle.insert(std::make_pair(position, b)); + const CObstacleInstance &oi = obstacles[b]; + if(!oi.isAbsoluteObstacle) + { + //BattleHex position = CGI->heroh->obstacles.find(obstacles[b].ID)->second.getMaxBlocked(obstacles[b].pos); + hexToObstacle.insert(std::make_pair(oi.pos, b)); + } } ////showing units //a lot of work... @@ -892,11 +904,15 @@ void CBattleInterface::showObstacles(std::multimap *hexToObstacl for(std::multimap::const_iterator it = obstRange.first; it != obstRange.second; ++it) { CObstacleInstance & curOb = obstacles[it->second]; - std::pair shift = CGI->heroh->obstacles.find(curOb.ID)->second.posShift; - int x = ((curOb.pos/GameConstants::BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(curOb.pos%GameConstants::BFIELD_WIDTH) + pos.x + shift.first; - int y = 86 + 42 * (curOb.pos/GameConstants::BFIELD_WIDTH) + pos.y + shift.second; std::vector &images = idToObstacle[curOb.ID]->ourImages; //reference to animation of obstacle - blitAt(images[((animCount+1)/(4/getAnimSpeed()))%images.size()].bitmap, x, y, to); + Rect r = hexPosition(hex); + int offset = images.front().bitmap->h % 42; + if(offset > 15) //experimental value, may need tweaking if some obstacles are shown too low/high + offset -= 42; + + r.y += 42 - images.front().bitmap->h + offset; + //r.y -= cellShade->h*CGI->heroh->obstacles.find(curOb.ID)->second.height - images.front().bitmap->h; + blitAt(images[((animCount+1)/(4/getAnimSpeed()))%images.size()].bitmap, r.x, r.y, to); } } @@ -2251,6 +2267,12 @@ void CBattleInterface::redrawBackgroundWithHexes(const CStack * activeStack) curInt->cb->battleGetStackCountOutsideHexes(stackCountOutsideHexes); //preparating background graphic with hexes and shaded hexes blitAt(background, 0, 0, backgroundWithHexes); + + //draw absolute obstacles (cliffs and so on) + BOOST_FOREACH(const CObstacleInstance &oi, curInt->cb->battleGetAllObstacles()) + if(oi.isAbsoluteObstacle) + blitAt(idToAbsoluteObstacle[oi.ID], oi.getInfo().width, oi.getInfo().height, backgroundWithHexes); + if(settings["battle"]["cellBorders"].Bool()) CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, backgroundWithHexes, NULL); @@ -3182,6 +3204,16 @@ BattleHex CBattleInterface::fromWhichHexAttack(BattleHex myNumber) } return -1; } + +Rect CBattleInterface::hexPosition(BattleHex hex) const +{ + int x = 14 + ((hex.getY())%2==0 ? 22 : 0) + 44*hex.getX() + pos.x; + int y = 86 + 42 * hex.getY() + pos.y; + int w = cellShade->w; + int h = cellShade->h; + return Rect(x, y, w, h); +} + std::string CBattleInterface::SiegeHelper::townTypeInfixes[GameConstants::F_NUMBER] = {"CS", "RM", "TW", "IN", "NC", "DN", "ST", "FR", "EL"}; CBattleInterface::SiegeHelper::SiegeHelper(const CGTownInstance *siegeTown, const CBattleInterface * _owner) diff --git a/client/BattleInterface/CBattleInterface.h b/client/BattleInterface/CBattleInterface.h index 6d11328fb..884e69465 100644 --- a/client/BattleInterface/CBattleInterface.h +++ b/client/BattleInterface/CBattleInterface.h @@ -111,6 +111,7 @@ private: std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID) std::map< int, CDefHandler * > idToProjectile; //projectiles of creatures (creatureID, defhandler) std::map< int, CDefHandler * > idToObstacle; //obstacles located on the battlefield + std::map< int, SDL_Surface * > idToAbsoluteObstacle; //obstacles located on the battlefield std::map< int, bool > creDir; // ui8 animCount; const CStack * activeStack; //number of active stack; NULL - no one @@ -261,6 +262,7 @@ public: void hideQueue(); void showQueue(); PossibleActions selectionTypeByPositiveness(const CSpell & spell); + Rect hexPosition(BattleHex hex) const; void handleHex(BattleHex myNumber, int eventType); bool isCastingPossibleHere (const CStack * sactive, const CStack * shere, BattleHex myNumber); diff --git a/config/obstacles.json b/config/obstacles.json index 7b91a722e..949be7e01 100644 --- a/config/obstacles.json +++ b/config/obstacles.json @@ -1,113 +1,1235 @@ -{ - // Battle obstacles - // id: - // defname: graphics - // blockmap: X - blocked, N - not blocked, L - description goes to the next line, starting with the left bottom hex - // terrains: bitmap of allowed terrains - - // 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills - // 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean - // 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools - // 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background - // 22. cursed ground 23. rough 24. ship to ship 25. ship - // shift_x, shift_y: shift of obstacle's position in the battlefield , - // eg. if it's <-1, 2> obstacle will be printed one pixel to the left and two to the bottom] - - "obstacles": [ - { "id": 5, "defname": "OBBDT01.DEF", "blockmap": "LNXXX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 56, "defname": "OBBHS02.DEF", "blockmap": "XXLNX", "terrains": "1100000000000000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 57, "defname": "OBBHS03.DEF", "blockmap": "LXXX", "terrains": "1111100000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 91, "defname": "OBBHS04.DEF", "blockmap": "XXLNXX", "terrains": "1100000000000000000000000", "shift_x": -40, "shift_y": -20 }, - { "id": 58, "defname": "OBBHS11A.DEF", "blockmap": "XXXLNXXX", "terrains": "1100000000000000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 59, "defname": "OBBHS12B.DEF", "blockmap": "NXXLNXX", "terrains": "1100000000000000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 60, "defname": "OBBHS14B.DEF", "blockmap": "NXLNXX", "terrains": "1111100000000000000000100", "shift_x": 36, "shift_y": 0 }, - { "id": 92, "defname": "OBBHS16A.DEF", "blockmap": "XLNXX", "terrains": "1100000000000000000000000", "shift_x": -8, "shift_y": -28 }, - { "id": 55, "defname": "OBBTS04.DEF", "blockmap": "XLXX", "terrains": "0000000000000000000000011", "shift_x": -30, "shift_y": -1 }, - { "id": 71, "defname": "OBCFS00.DEF", "blockmap": "X", "terrains": "0000000000000000001000000", "shift_x": 14, "shift_y": 0 }, - { "id": 72, "defname": "OBCFS01.DEF", "blockmap": "XX", "terrains": "0000000000000000001000000", "shift_x": 14, "shift_y": 0 }, - { "id": 73, "defname": "OBCFS02.DEF", "blockmap": "XXLNXX", "terrains": "0000000000000000001000000", "shift_x": -8, "shift_y": 0 }, - { "id": 74, "defname": "OBCFS03.DEF", "blockmap": "NXXLNXX", "terrains": "0000000000000000001000000", "shift_x": -8, "shift_y": 0 }, - { "id": 0, "defname": "OBDINO1.DEF", "blockmap": "XX", "terrains": "1111110000000000000000100", "shift_x": 14, "shift_y": 0 }, - { "id": 2, "defname": "OBDINO2.DEF", "blockmap": "LXXX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 1, "defname": "OBDINO3.DEF", "blockmap": "XXXLXX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 6, "defname": "OBDRK01.DEF", "blockmap": "XX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 7, "defname": "OBDRK02.DEF", "blockmap": "LXX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 8, "defname": "OBDRK03.DEF", "blockmap": "X", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": -8 }, - { "id": 9, "defname": "OBDRK04.DEF", "blockmap": "LXX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 10, "defname": "OBDSH01.DEF", "blockmap": "LXX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 93, "defname": "OBDSM01.DEF", "blockmap": "NNXXXLNNXXXLNNXX", "terrains": "1100000000000000000000000", "shift_x": 36, "shift_y": 0 }, - { "id": 17, "defname": "OBDSM02.DEF", "blockmap": "XXLNX", "terrains": "1111100000000000000000100", "shift_x": -9, "shift_y": -2 }, - { "id": 18, "defname": "OBDSS17.DEF", "blockmap": "XXLNXXX", "terrains": "1111100000000000000000100", "shift_x": -8, "shift_y": 0 }, - { "id": 11, "defname": "OBDTF03.DEF", "blockmap": "XX", "terrains": "1111100000000000000001100", "shift_x": 14, "shift_y": 0 }, - { "id": 12, "defname": "OBDTS03.DEF", "blockmap": "LLNXXXX", "terrains": "1111100000000000000001100", "shift_x": 14, "shift_y": 0 }, - { "id": 13, "defname": "OBDTS04.DEF", "blockmap": "LNXX", "terrains": "1111100000000000000001100", "shift_x": -8, "shift_y": 0 }, - { "id": 14, "defname": "OBDTS14.DEF", "blockmap": "XXLNNX", "terrains": "1111100000000000000001100", "shift_x": -8, "shift_y": 0 }, - { "id": 15, "defname": "OBDTS15.DEF", "blockmap": "XLXLNX", "terrains": "1111100000000000000001100", "shift_x": -30, "shift_y": 0 }, - { "id": 66, "defname": "OBEFS00.DEF", "blockmap": "X", "terrains": "0000000000000000000100000", "shift_x": 14, "shift_y": 0 }, - { "id": 67, "defname": "OBEFS01.DEF", "blockmap": "XX", "terrains": "0000000000000000000100000", "shift_x": 14, "shift_y": 0 }, - { "id": 68, "defname": "OBEFS02.DEF", "blockmap": "NXLXXX", "terrains": "0000000000000000000100000", "shift_x": -8, "shift_y": 0 }, - { "id": 69, "defname": "OBEFS03.DEF", "blockmap": "LNXX", "terrains": "0000000000000000000100000", "shift_x": 0, "shift_y": 0 }, - { "id": 70, "defname": "OBEFS04.DEF", "blockmap": "NNXXXLNXXX", "terrains": "0000000000000000000100000", "shift_x": -8, "shift_y": 0 }, - { "id": 79, "defname": "OBFFS00.DEF", "blockmap": "X", "terrains": "0000000000000100000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 80, "defname": "OBFFS01.DEF", "blockmap": "XX", "terrains": "0000000000000100000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 81, "defname": "OBFFS02.DEF", "blockmap": "NXLXXX", "terrains": "0000000000000100000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 82, "defname": "OBFFS03.DEF", "blockmap": "XXLNXXX", "terrains": "0000000000000100000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 83, "defname": "OBFFS04.DEF", "blockmap": "XXXLXXXX", "terrains": "0000000000000100000000000", "shift_x": -8, "shift_y": -42 }, - { "id": 19, "defname": "OBGLG01.DEF", "blockmap": "XX", "terrains": "0000000000001000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 94, "defname": "OBGRK01.DEF", "blockmap": "XX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": -42 }, - { "id": 23, "defname": "OBGRK02.DEF", "blockmap": "XX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 20, "defname": "OBGRS02.DEF", "blockmap": "NXX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 22, "defname": "OBGRS01.DEF", "blockmap": "XXXXLNXXXX", "terrains": "0000011010001000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 35, "defname": "OBGRS03.DEF", "blockmap": "XXXXXXX", "terrains": "1111111010000000000000100", "shift_x": 0, "shift_y": 0 }, - { "id": 21, "defname": "OBGST01.DEF", "blockmap": "X", "terrains": "1111111010000000000000100", "shift_x": 14, "shift_y": 0 }, - { "id": 61, "defname": "OBHGS00.DEF", "blockmap": "X", "terrains": "0000000000000000010000000", "shift_x": 14, "shift_y": 0 }, - { "id": 62, "defname": "OBHGS01.DEF", "blockmap": "XX", "terrains": "0000000000000000010000000", "shift_x": 14, "shift_y": 0 }, - { "id": 63, "defname": "OBHGS02.DEF", "blockmap": "X", "terrains": "0000000000000000010000000", "shift_x": -30, "shift_y": -84 }, - { "id": 64, "defname": "OBHGS03.DEF", "blockmap": "XXX", "terrains": "0000000000000000010000000", "shift_x": 14, "shift_y": -42 }, - { "id": 65, "defname": "OBHGS04.DEF", "blockmap": "XXXX", "terrains": "0000000000000000010000000", "shift_x": 14, "shift_y": -84 }, - { "id": 75, "defname": "OBLPS00.DEF", "blockmap": "X", "terrains": "0000000000000000100000000", "shift_x": 14, "shift_y": 0 }, - { "id": 76, "defname": "OBLPS01.DEF", "blockmap": "XX", "terrains": "0000000000000000100000000", "shift_x": 14, "shift_y": 0 }, - { "id": 77, "defname": "OBLPS02.DEF", "blockmap": "NXXLNX", "terrains": "0000000000000000100000000", "shift_x": 36, "shift_y": 0 }, - { "id": 78, "defname": "OBLPS03.DEF", "blockmap": "XXXXLNXXXX", "terrains": "0000000000000000100000000", "shift_x": -8, "shift_y": 0 }, - { "id": 48, "defname": "OBLVS01.DEF", "blockmap": "XXLNNX", "terrains": "0000000100000000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 49, "defname": "OBLVS02.DEF", "blockmap": "XXXLXXX", "terrains": "0000000100000000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 50, "defname": "OBLVS03.DEF", "blockmap": "XXXXLNXXX", "terrains": "0000000100000000000000000", "shift_x": -30, "shift_y": 0 }, - { "id": 51, "defname": "OBLVS04.DEF", "blockmap": "XXX", "terrains": "0000000100000000000000000", "shift_x": 14, "shift_y": -42 }, - { "id": 52, "defname": "OBLVS09.DEF", "blockmap": "XXLNXXLNNXX", "terrains": "0000000100000000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 53, "defname": "OBLVS17.DEF", "blockmap": "NNXLXXXX", "terrains": "0000000100000000000000000", "shift_x": -30, "shift_y": 0 }, - { "id": 54, "defname": "OBLVS22.DEF", "blockmap": "XXXLXXXX", "terrains": "0000000100000000000000000", "shift_x": -30, "shift_y": 0 }, - { "id": 88, "defname": "OBMCS00.DEF", "blockmap": "X", "terrains": "0000000000000001000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 89, "defname": "OBMCS01.DEF", "blockmap": "XLNX", "terrains": "0000000000000001000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 90, "defname": "OBMCS02.DEF", "blockmap": "NXXLXX", "terrains": "0000000000000001000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 41, "defname": "OBRGS01.DEF", "blockmap": "XLXX", "terrains": "1111100000000000000001100", "shift_x": -8, "shift_y": 0 }, - { "id": 40, "defname": "OBRGS02.DEF", "blockmap": "NXXLNXXX", "terrains": "1111100000000000000001100", "shift_x": 14, "shift_y": 0 }, - { "id": 42, "defname": "OBRGS03.DEF", "blockmap": "XXLNX", "terrains": "1111100000000000000001100", "shift_x": -8, "shift_y": 0 }, - { "id": 43, "defname": "OBRGS04.DEF", "blockmap": "XXLX", "terrains": "1111100000000000000001100", "shift_x": -30, "shift_y": 0 }, - { "id": 44, "defname": "OBRGS05.DEF", "blockmap": "NXLXX", "terrains": "1111100000000000000001100", "shift_x": -30, "shift_y": 0 }, - { "id": 16, "defname": "OBRGS06.DEF", "blockmap": "NXXXXXXLNNNNNNNXLNNNNNNNNX", "terrains": "1111100000000000000001100", "shift_x": -30, "shift_y": -30 }, - { "id": 84, "defname": "OBRLS00.DEF", "blockmap": "X", "terrains": "0000000000000010000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 85, "defname": "OBRLS01.DEF", "blockmap": "XX", "terrains": "0000000000000010000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 86, "defname": "OBRLS02.DEF", "blockmap": "XXX", "terrains": "0000000000000010000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 87, "defname": "OBRLS03.DEF", "blockmap": "XLNXX", "terrains": "0000000000000010000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 4, "defname": "OBSKEL1.DEF", "blockmap": "XX", "terrains": "1111110000000000000001100", "shift_x": 14, "shift_y": 0 }, - { "id": 3, "defname": "OBSKEL2.DEF", "blockmap": "XX", "terrains": "1111110000000000000001100", "shift_x": 14, "shift_y": 0 }, - { "id": 24, "defname": "OBSNS01.DEF", "blockmap": "XXX", "terrains": "0000000001100000000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 25, "defname": "OBSNS02.DEF", "blockmap": "NXXXX", "terrains": "0000000001100000000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 26, "defname": "OBSNS03.DEF", "blockmap": "XLXLX", "terrains": "0000000001100000000000000", "shift_x": -30, "shift_y": 0 }, - { "id": 27, "defname": "OBSNS04.DEF", "blockmap": "XXX", "terrains": "0000000001100000000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 28, "defname": "OBSNS05.DEF", "blockmap": "X", "terrains": "0000000001100000000000000", "shift_x": -30, "shift_y": 0 }, - { "id": 29, "defname": "OBSNS06.DEF", "blockmap": "LNXX", "terrains": "0000000001100000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 30, "defname": "OBSNS07.DEF", "blockmap": "XX", "terrains": "0000000001100000000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 31, "defname": "OBSNS08.DEF", "blockmap": "LNXXX", "terrains": "0000000001100000000000000", "shift_x": 36, "shift_y": 0 }, - { "id": 32, "defname": "OBSNS09.DEF", "blockmap": "XXXXLNNXXXX", "terrains": "0000000001100000000000000", "shift_x": -8, "shift_y": 0 }, - { "id": 33, "defname": "OBSNS10.DEF", "blockmap": "XXLNXLNXXLNNXXX", "terrains": "0000000001100000000000000", "shift_x": -30, "shift_y": -30 }, - { "id": 45, "defname": "OBSUS01.DEF", "blockmap": "XXLXXX", "terrains": "0000000000010000000000000", "shift_x": -8, "shift_y": -42 }, - { "id": 46, "defname": "OBSUS02.DEF", "blockmap": "XXX", "terrains": "0000000000010000000000000", "shift_x": 14, "shift_y": -42 }, - { "id": 47, "defname": "OBSUS11B.DEF", "blockmap": "XXXLXXXX", "terrains": "0000000000010000000000000", "shift_x": -9, "shift_y": -43 }, - { "id": 34, "defname": "OBSWS01.DEF", "blockmap": "LNX", "terrains": "0000000000001000000000000", "shift_x": 36, "shift_y": 0 }, - { "id": 95, "defname": "OBSWS02.DEF", "blockmap": "XXXXXXX", "terrains": "0000000000001000000000000", "shift_x": -8, "shift_y": -42 }, - { "id": 36, "defname": "OBSWS03.DEF", "blockmap": "XX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 37, "defname": "OBSWS04.DEF", "blockmap": "XXX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 }, - { "id": 38, "defname": "OBSWS11B.DEF", "blockmap": "XXXXLXXXX", "terrains": "0000000000001000000000000", "shift_x": -30, "shift_y": -40 }, - { "id": 39, "defname": "OBSWS13A.DEF", "blockmap": "XXXXLXX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 } - ] -} +// Defines battle obstacles. We have two vectors of them: +// * "obstacles" are usual obtacles, that are randomly placed in the battlefield. +// * "absoluteObstacles" are a little special: there can be only one such obstacle in the battlefield and its position is always the same. +// +// Their properties: +// * "allowedTerrain" vector of terrain types (TT format) where obstacle is appropriate +// * "specialBattlefields" vector of battlefield images (BI format) where obstacle is appropriate. If there is a special battlefield image, then only this list is checked. Otherwise it's ignored. +// * "blockedTiles": for absolute obstacles contains absolute coordinates. For usual obstacles contains offsets relative to the obstacle position (that is bottom left corner). If obstacle is placed in an odd row (counting from 0) and the blocked tile is in an even row, position will be shifted one tile to the left. Thanks to that ie. -16 is always top-right hex, no matter where the obstale will get placed. +// * "width" for usual obstacles it's count of tiles that must be free to the right for obstacle to be placed. For absolute obstacles, it's x offset for the graphics. +// * "height" for usual obstacles it's count of tiles that must be free to the top for obstacle to be placed. For absolute obstacles, it's y offset for the graphics. +// * "defname" is name of the graphics. It's def file for usual obstacles and bitmap for the absolute ones. + +{ +"obstacles" : [ + { + "id" : 0, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObDino1.def", + "unknown" : 1 + }, + { + "id" : 1, + "allowedTerrain" : [0, 1, 5, 6], + "specialBattlefields" : [0], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, 1, 2], + "defname" : "ObDino2.def", + "unknown" : 0 + }, + { + "id" : 2, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 4, + "height" : 2, + "blockedTiles" : [0, 1, -14, -15, -16], + "defname" : "ObDino3.def", + "unknown" : 1 + }, + { + "id" : 3, + "allowedTerrain" : [0, 5], + "specialBattlefields" : [2], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObSkel1.def", + "unknown" : 1 + }, + { + "id" : 4, + "allowedTerrain" : [0, 5, 6], + "specialBattlefields" : [0, 2], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObSkel2.def", + "unknown" : 1 + }, + { + "id" : 5, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 4, + "height" : 2, + "blockedTiles" : [1, 2, 3], + "defname" : "ObBDT01.def", + "unknown" : 1 + }, + { + "id" : 6, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 3, + "height" : 2, + "blockedTiles" : [-15, -16], + "defname" : "ObDRk01.def", + "unknown" : 1 + }, + { + "id" : 7, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 2, + "height" : 2, + "blockedTiles" : [0, 1], + "defname" : "ObDRk02.def", + "unknown" : 0 + }, + { + "id" : 8, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 2, + "height" : 2, + "blockedTiles" : [-16], + "defname" : "ObDRk03.def", + "unknown" : 1 + }, + { + "id" : 9, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 2, + "height" : 2, + "blockedTiles" : [0, 1], + "defname" : "ObDRk04.def", + "unknown" : 0 + }, + { + "id" : 10, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 2, + "height" : 2, + "blockedTiles" : [0, 1], + "defname" : "ObDSh01.def", + "unknown" : 0 + }, + { + "id" : 11, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObDTF03.def", + "unknown" : 0 + }, + { + "id" : 12, + "allowedTerrain" : [0, 5], + "specialBattlefields" : [2], + "width" : 3, + "height" : 3, + "blockedTiles" : [0, 1, 2, 3], + "defname" : "ObDtS03.def", + "unknown" : 0 + }, + { + "id" : 13, + "allowedTerrain" : [0, 5], + "specialBattlefields" : [2], + "width" : 3, + "height" : 2, + "blockedTiles" : [1, 2, -15], + "defname" : "ObDtS04.def", + "unknown" : 1 + }, + { + "id" : 14, + "allowedTerrain" : [0, 5], + "specialBattlefields" : [2], + "width" : 3, + "height" : 2, + "blockedTiles" : [2, -15, -16], + "defname" : "ObDtS14.def", + "unknown" : 1 + }, + { + "id" : 15, + "allowedTerrain" : [0, 5], + "specialBattlefields" : [2], + "width" : 3, + "height" : 3, + "blockedTiles" : [1, -16, -33], + "defname" : "ObDtS15.def", + "unknown" : 1 + }, + { + "id" : 16, + "allowedTerrain" : [1], + "specialBattlefields" : [], + "width" : 4, + "height" : 4, + "blockedTiles" : [-15, -16, -32, -33, -48, -49], + "defname" : "ObDsM01.def", + "unknown" : 1 + }, + { + "id" : 17, + "allowedTerrain" : [1], + "specialBattlefields" : [], + "width" : 3, + "height" : 2, + "blockedTiles" : [1, -15, -16], + "defname" : "ObDsS02.def", + "unknown" : 1 + }, + { + "id" : 18, + "allowedTerrain" : [1], + "specialBattlefields" : [], + "width" : 4, + "height" : 2, + "blockedTiles" : [1, 2, 3, -15, -16], + "defname" : "ObDsS17.def", + "unknown" : 1 + }, + { + "id" : 19, + "allowedTerrain" : [2, 4], + "specialBattlefields" : [], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObGLg01.def", + "unknown" : 1 + }, + { + "id" : 20, + "allowedTerrain" : [2, 4], + "specialBattlefields" : [1], + "width" : 2, + "height" : 2, + "blockedTiles" : [0, 1], + "defname" : "ObGRk01.def", + "unknown" : 0 + }, + { + "id" : 21, + "allowedTerrain" : [2, 4], + "specialBattlefields" : [], + "width" : 1, + "height" : 1, + "blockedTiles" : [0], + "defname" : "ObGSt01.def", + "unknown" : 1 + }, + { + "id" : 22, + "allowedTerrain" : [2], + "specialBattlefields" : [1], + "width" : 6, + "height" : 2, + "blockedTiles" : [1, 2, 3, 4, -13, -14, -15, -16], + "defname" : "ObGrS01.def", + "unknown" : 1 + }, + { + "id" : 23, + "allowedTerrain" : [2], + "specialBattlefields" : [], + "width" : 7, + "height" : 1, + "blockedTiles" : [1, 2], + "defname" : "OBGrS02.def", + "unknown" : 1 + }, + { + "id" : 24, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 3, + "height" : 1, + "blockedTiles" : [0, 1, 2], + "defname" : "ObSnS01.def", + "unknown" : 1 + }, + { + "id" : 25, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 5, + "height" : 1, + "blockedTiles" : [1, 2, 3, 4], + "defname" : "ObSnS02.def", + "unknown" : 1 + }, + { + "id" : 26, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 3, + "height" : 3, + "blockedTiles" : [0, -16, -33], + "defname" : "ObSnS03.def", + "unknown" : 1 + }, + { + "id" : 27, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 3, + "height" : 1, + "blockedTiles" : [0, 1, 2], + "defname" : "ObSnS04.def", + "unknown" : 1 + }, + { + "id" : 28, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 3, + "height" : 1, + "blockedTiles" : [1], + "defname" : "ObSnS05.def", + "unknown" : 1 + }, + { + "id" : 29, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 3, + "height" : 2, + "blockedTiles" : [1, 2], + "defname" : "ObSnS06.def", + "unknown" : 0 + }, + { + "id" : 30, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObSnS07.def", + "unknown" : 1 + }, + { + "id" : 31, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, 1, 2], + "defname" : "ObSnS08.def", + "unknown" : 0 + }, + { + "id" : 32, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 7, + "height" : 2, + "blockedTiles" : [2, 3, 4, 5, -13, -14, -15, -16], + "defname" : "ObSnS09.def", + "unknown" : 1 + }, + { + "id" : 33, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 5, + "height" : 5, + "blockedTiles" : [3, -13, -14, -15, -33, -49, -66], + "defname" : "ObSnS10.def", + "unknown" : 1 + }, + { + "id" : 34, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 2, + "height" : 2, + "blockedTiles" : [0], + "defname" : "ObSwS01.def", + "unknown" : 0 + }, + { + "id" : 35, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 8, + "height" : 3, + "blockedTiles" : [-10, -11, -12, -13, -14, -15, -16], + "defname" : "ObSwS02.def", + "unknown" : 1 + }, + { + "id" : 36, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObSwS03.def", + "unknown" : 0 + }, + { + "id" : 37, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 3, + "height" : 1, + "blockedTiles" : [0, 1, 2], + "defname" : "ObSwS04.def", + "unknown" : 0 + }, + { + "id" : 38, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 5, + "height" : 4, + "blockedTiles" : [-13, -14, -15, -16, -30, -31, -32, -33], + "defname" : "ObSwS11b.def", + "unknown" : 1 + }, + { + "id" : 39, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 4, + "height" : 3, + "blockedTiles" : [-16, -17, -31, -32, -33, -34], + "defname" : "ObSwS13a.def", + "unknown" : 1 + }, + { + "id" : 40, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 2, + "height" : 2, + "blockedTiles" : [0, 1, -16], + "defname" : "ObRgS01.def", + "unknown" : 1 + }, + { + "id" : 41, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 4, + "height" : 3, + "blockedTiles" : [-14, -15, -16, -32, -33], + "defname" : "ObRgS02.def", + "unknown" : 1 + }, + { + "id" : 42, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 3, + "height" : 2, + "blockedTiles" : [1, 2, -15, -16], + "defname" : "ObRgS03.def", + "unknown" : 1 + }, + { + "id" : 43, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 3, + "height" : 3, + "blockedTiles" : [-16, -32, -33], + "defname" : "ObRgS04.def", + "unknown" : 1 + }, + { + "id" : 44, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 3, + "height" : 3, + "blockedTiles" : [-15, -16, -32], + "defname" : "ObRgS05.def", + "unknown" : 1 + }, + { + "id" : 45, + "allowedTerrain" : [6], + "specialBattlefields" : [], + "width" : 3, + "height" : 3, + "blockedTiles" : [0, 1, 2, -15, -16], + "defname" : "ObSuS01.def", + "unknown" : 0 + }, + { + "id" : 46, + "allowedTerrain" : [6], + "specialBattlefields" : [], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, 1, 2], + "defname" : "ObSuS02.def", + "unknown" : 0 + }, + { + "id" : 47, + "allowedTerrain" : [6], + "specialBattlefields" : [], + "width" : 4, + "height" : 3, + "blockedTiles" : [0, 1, 2, 3, -14, -15, -16], + "defname" : "ObSuS11b.def", + "unknown" : 0 + }, + { + "id" : 48, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 4, + "height" : 3, + "blockedTiles" : [-14, -32, -33], + "defname" : "ObLvS01.def", + "unknown" : 1 + }, + { + "id" : 49, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 4, + "height" : 2, + "blockedTiles" : [0, 1, 2, -14, -15, -16], + "defname" : "ObLvS02.def", + "unknown" : 1 + }, + { + "id" : 50, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 5, + "height" : 3, + "blockedTiles" : [-13, -14, -15, -30, -31, -32, -33], + "defname" : "ObLvS03.def", + "unknown" : 1 + }, + { + "id" : 51, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, 1, 2], + "defname" : "ObLvS04.def", + "unknown" : 0 + }, + { + "id" : 52, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 4, + "height" : 4, + "blockedTiles" : [-14, -15, -32, -33, -49, -50], + "defname" : "ObLvS09.def", + "unknown" : 1 + }, + { + "id" : 53, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 5, + "height" : 3, + "blockedTiles" : [-13, -14, -15, -16, -30, -31], + "defname" : "ObLvS17.def", + "unknown" : 1 + }, + { + "id" : 54, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 5, + "height" : 3, + "blockedTiles" : [-13, -14, -15, -16, -31, -32, -33], + "defname" : "ObLvS22.def", + "unknown" : 1 + }, + { + "id" : 55, + "allowedTerrain" : [8], + "specialBattlefields" : [], + "width" : 3, + "height" : 3, + "blockedTiles" : [-15, -16, -33], + "defname" : "ObBtS04.def", + "unknown" : 1 + }, + { + "id" : 56, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 3, + "height" : 2, + "blockedTiles" : [1, -15, -16], + "defname" : "ObBhS02.def", + "unknown" : 1 + }, + { + "id" : 57, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, 1, 2], + "defname" : "ObBhS03.def", + "unknown" : 0 + }, + { + "id" : 58, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 5, + "height" : 2, + "blockedTiles" : [1, 2, 3, -14, -15, -16], + "defname" : "ObBhS11a.def", + "unknown" : 1 + }, + { + "id" : 59, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 4, + "height" : 2, + "blockedTiles" : [1, 2, -14, -15], + "defname" : "ObBhS12b.def", + "unknown" : 1 + }, + { + "id" : 60, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 2, + "height" : 2, + "blockedTiles" : [0, 1, -16], + "defname" : "ObBhS14b.def", + "unknown" : 1 + }, + { + "id" : 61, + "allowedTerrain" : [], + "specialBattlefields" : [3], + "width" : 1, + "height" : 1, + "blockedTiles" : [0], + "defname" : "ObHGs00.def", + "unknown" : 0 + }, + { + "id" : 62, + "allowedTerrain" : [], + "specialBattlefields" : [3], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObHGs01.def", + "unknown" : 0 + }, + { + "id" : 63, + "allowedTerrain" : [], + "specialBattlefields" : [3], + "width" : 3, + "height" : 3, + "blockedTiles" : [1], + "defname" : "ObHGs02.def", + "unknown" : 0 + }, + { + "id" : 64, + "allowedTerrain" : [], + "specialBattlefields" : [3], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, 1, 2], + "defname" : "ObHGs03.def", + "unknown" : 0 + }, + { + "id" : 65, + "allowedTerrain" : [], + "specialBattlefields" : [3], + "width" : 4, + "height" : 3, + "blockedTiles" : [0, 1, 2, 3], + "defname" : "ObHGs04.def", + "unknown" : 0 + }, + { + "id" : 66, + "allowedTerrain" : [], + "specialBattlefields" : [4], + "width" : 1, + "height" : 1, + "blockedTiles" : [0], + "defname" : "ObEFs00.def", + "unknown" : 0 + }, + { + "id" : 67, + "allowedTerrain" : [], + "specialBattlefields" : [4], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObEFs01.def", + "unknown" : 0 + }, + { + "id" : 68, + "allowedTerrain" : [], + "specialBattlefields" : [4], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, 1, 2], + "defname" : "ObEFs02.def", + "unknown" : 0 + }, + { + "id" : 69, + "allowedTerrain" : [], + "specialBattlefields" : [4], + "width" : 4, + "height" : 2, + "blockedTiles" : [1, 2], + "defname" : "ObEFs03.def", + "unknown" : 0 + }, + { + "id" : 70, + "allowedTerrain" : [], + "specialBattlefields" : [4], + "width" : 6, + "height" : 2, + "blockedTiles" : [1, 2, 3, -12, -13], + "defname" : "ObEFs04.def", + "unknown" : 0 + }, + { + "id" : 71, + "allowedTerrain" : [], + "specialBattlefields" : [5], + "width" : 1, + "height" : 1, + "blockedTiles" : [0], + "defname" : "ObCFs00.def", + "unknown" : 1 + }, + { + "id" : 72, + "allowedTerrain" : [], + "specialBattlefields" : [5], + "width" : 3, + "height" : 1, + "blockedTiles" : [0, 1, 2], + "defname" : "ObCFs01.def", + "unknown" : 1 + }, + { + "id" : 73, + "allowedTerrain" : [], + "specialBattlefields" : [5], + "width" : 3, + "height" : 2, + "blockedTiles" : [1, 2, -15, -16], + "defname" : "ObCFs02.def", + "unknown" : 1 + }, + { + "id" : 74, + "allowedTerrain" : [], + "specialBattlefields" : [5], + "width" : 4, + "height" : 2, + "blockedTiles" : [0, 1, 2, -14, -15, -16], + "defname" : "ObCFs03.def", + "unknown" : 1 + }, + { + "id" : 75, + "allowedTerrain" : [], + "specialBattlefields" : [6], + "width" : 1, + "height" : 1, + "blockedTiles" : [0], + "defname" : "ObLPs00.def", + "unknown" : 1 + }, + { + "id" : 76, + "allowedTerrain" : [], + "specialBattlefields" : [6], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObLPs01.def", + "unknown" : 1 + }, + { + "id" : 77, + "allowedTerrain" : [], + "specialBattlefields" : [6], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, -15, -16], + "defname" : "ObLPs02.def", + "unknown" : 1 + }, + { + "id" : 78, + "allowedTerrain" : [], + "specialBattlefields" : [6], + "width" : 5, + "height" : 2, + "blockedTiles" : [1, 2, 3, -13, -14, -15, -16], + "defname" : "ObLPs03.def", + "unknown" : 1 + }, + { + "id" : 79, + "allowedTerrain" : [], + "specialBattlefields" : [7], + "width" : 1, + "height" : 1, + "blockedTiles" : [0], + "defname" : "ObFFs00.def", + "unknown" : 0 + }, + { + "id" : 80, + "allowedTerrain" : [], + "specialBattlefields" : [7], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObFFs01.def", + "unknown" : 0 + }, + { + "id" : 81, + "allowedTerrain" : [], + "specialBattlefields" : [7], + "width" : 3, + "height" : 2, + "blockedTiles" : [0, 1, 2, -15], + "defname" : "ObFFs02.def", + "unknown" : 0 + }, + { + "id" : 82, + "allowedTerrain" : [], + "specialBattlefields" : [7], + "width" : 4, + "height" : 2, + "blockedTiles" : [1, 2, 3, -15, -16], + "defname" : "ObFFs03.def", + "unknown" : 0 + }, + { + "id" : 83, + "allowedTerrain" : [], + "specialBattlefields" : [7], + "width" : 3, + "height" : 3, + "blockedTiles" : [0, 1, 2, 3, -14, -15, -16], + "defname" : "ObFFs04.def", + "unknown" : 0 + }, + { + "id" : 84, + "allowedTerrain" : [], + "specialBattlefields" : [8], + "width" : 1, + "height" : 1, + "blockedTiles" : [0], + "defname" : "ObRLs00.def", + "unknown" : 0 + }, + { + "id" : 85, + "allowedTerrain" : [], + "specialBattlefields" : [8], + "width" : 2, + "height" : 1, + "blockedTiles" : [0, 1], + "defname" : "ObRLs01.def", + "unknown" : 0 + }, + { + "id" : 86, + "allowedTerrain" : [], + "specialBattlefields" : [8], + "width" : 3, + "height" : 1, + "blockedTiles" : [0, 1, 2], + "defname" : "ObRLs02.def", + "unknown" : 0 + }, + { + "id" : 87, + "allowedTerrain" : [], + "specialBattlefields" : [8], + "width" : 4, + "height" : 2, + "blockedTiles" : [1, 2, 3, -15, -16], + "defname" : "ObRLs03.def", + "unknown" : 0 + }, + { + "id" : 88, + "allowedTerrain" : [], + "specialBattlefields" : [9], + "width" : 1, + "height" : 1, + "blockedTiles" : [0], + "defname" : "ObMCs00.def", + "unknown" : 1 + }, + { + "id" : 89, + "allowedTerrain" : [], + "specialBattlefields" : [9], + "width" : 2, + "height" : 2, + "blockedTiles" : [1, -16], + "defname" : "ObMCs01.def", + "unknown" : 1 + }, + { + "id" : 90, + "allowedTerrain" : [], + "specialBattlefields" : [9], + "width" : 4, + "height" : 2, + "blockedTiles" : [0, 1, -14, -15], + "defname" : "ObMCs02.def", + "unknown" : 1 + }, +], +"absoluteObstacles" : [ + { + "id" : 0, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 124, + "height" : 254, + "blockedTiles" : [80, 94, 95, 96, 97, 105, 106, 107, 108, 109, 110], + "defname" : "ObDtL04.pcx", + }, + { + "id" : 1, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 256, + "height" : 254, + "blockedTiles" : [73, 91, 108, 109, 110, 111, 112, 113], + "defname" : "ObDtL06.pcx", + }, + { + "id" : 2, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 168, + "height" : 212, + "blockedTiles" : [60, 61, 62, 63, 64, 72, 73, 74, 75, 76, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149], + "defname" : "ObDtL10.pcx", + }, + { + "id" : 3, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 124, + "height" : 254, + "blockedTiles" : [88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98], + "defname" : "ObDtL02.pcx", + }, + { + "id" : 4, + "allowedTerrain" : [0], + "specialBattlefields" : [], + "width" : 146, + "height" : 254, + "blockedTiles" : [76, 77, 78, 79, 80, 89, 90, 91, 92, 93], + "defname" : "ObDtL03.pcx", + }, + { + "id" : 5, + "allowedTerrain" : [2], + "specialBattlefields" : [], + "width" : 173, + "height" : 221, + "blockedTiles" : [55, 56, 57, 58, 75, 76, 77, 95, 112, 113, 131], + "defname" : "ObGrL01.pcx", + }, + { + "id" : 6, + "allowedTerrain" : [2], + "specialBattlefields" : [], + "width" : 180, + "height" : 264, + "blockedTiles" : [81, 91, 92, 93, 94, 95, 96, 97, 98, 106, 107, 123], + "defname" : "ObGrL02.pcx", + }, + { + "id" : 7, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 166, + "height" : 255, + "blockedTiles" : [76, 77, 78, 79, 91, 92, 93, 97, 98, 106, 107, 108], + "defname" : "ObSnL01.pcx", + }, + { + "id" : 8, + "allowedTerrain" : [3], + "specialBattlefields" : [], + "width" : 302, + "height" : 172, + "blockedTiles" : [41, 42, 43, 58, 75, 92, 108, 126, 143], + "defname" : "ObSnL14.pcx", + }, + { + "id" : 9, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 300, + "height" : 170, + "blockedTiles" : [40, 41, 58, 59, 74, 75, 92, 93, 109, 110, 111, 127, 128, 129, 130], + "defname" : "ObSwL15.pcx", + }, + { + "id" : 10, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 278, + "height" : 171, + "blockedTiles" : [43, 60, 61, 77, 93, 94, 95, 109, 110, 126, 127], + "defname" : "ObSwL14.pcx", + }, + { + "id" : 11, + "allowedTerrain" : [4], + "specialBattlefields" : [], + "width" : 256, + "height" : 254, + "blockedTiles" : [74, 75, 76, 77, 91, 92, 93, 94, 95, 109, 110, 111, 112], + "defname" : "ObSwL22.pcx", + }, + { + "id" : 12, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 124, + "height" : 254, + "blockedTiles" : [77, 78, 79, 80, 81, 91, 92, 93, 94, 105, 106, 107], + "defname" : "ObLvL01.pcx", + }, + { + "id" : 13, + "allowedTerrain" : [7], + "specialBattlefields" : [], + "width" : 256, + "height" : 128, + "blockedTiles" : [43, 60, 61, 76, 77, 93, 109, 126, 127, 142, 143], + "defname" : "OBLvL02.pcx", + }, + { + "id" : 14, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 186, + "height" : 212, + "blockedTiles" : [55, 72, 90, 107, 125, 126, 127, 128, 129, 130, 131, 132], + "defname" : "ObRgL01.pcx", + }, + { + "id" : 15, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 347, + "height" : 174, + "blockedTiles" : [41, 59, 76, 94, 111, 129, 143, 144, 145], + "defname" : "ObRgL02.pcx", + }, + { + "id" : 16, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 294, + "height" : 169, + "blockedTiles" : [40, 41, 42, 43, 58, 75, 93, 110, 128, 145], + "defname" : "ObRgL03.pcx", + }, + { + "id" : 17, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 165, + "height" : 257, + "blockedTiles" : [72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 89, 105], + "defname" : "ObRgL04.pcx", + }, + { + "id" : 18, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 208, + "height" : 268, + "blockedTiles" : [72, 73, 74, 75, 76, 77, 78, 79, 80, 90, 91, 92, 93, 94, 95, 96, 97], + "defname" : "ObRgL05.pcx", + }, + { + "id" : 19, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 252, + "height" : 254, + "blockedTiles" : [73, 74, 75, 76, 77, 78, 91, 92, 93, 94], + "defname" : "ObRgL06.pcx", + }, + { + "id" : 20, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 278, + "height" : 128, + "blockedTiles" : [23, 40, 58, 75, 93, 110, 128, 145, 163], + "defname" : "ObRgL15.pcx", + }, + { + "id" : 21, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 208, + "height" : 268, + "blockedTiles" : [72, 73, 74, 75, 76, 77, 78, 79, 80, 90, 91, 92, 93, 94, 95, 96, 97], + "defname" : "ObRgL05.pcx", + }, + { + "id" : 22, + "allowedTerrain" : [5], + "specialBattlefields" : [2], + "width" : 168, + "height" : 212, + "blockedTiles" : [73, 74, 75, 76, 77, 78, 79, 90, 91, 92, 93, 94, 95, 96, 97, 106, 107, 108, 109, 110, 111, 112], + "defname" : "ObRgL22.pcx", + }, + { + "id" : 23, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 147, + "height" : 264, + "blockedTiles" : [72, 73, 74, 75, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98], + "defname" : "ObBhL02.pcx", + }, + { + "id" : 24, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 178, + "height" : 262, + "blockedTiles" : [71, 72, 73, 74, 75, 76, 77, 78, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98], + "defname" : "ObBhL03.pcx", + }, + { + "id" : 25, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 173, + "height" : 257, + "blockedTiles" : [72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 89, 90, 105, 106], + "defname" : "ObBhL05.pcx", + }, + { + "id" : 26, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 241, + "height" : 272, + "blockedTiles" : [73, 91, 108, 109, 110, 111, 112, 113], + "defname" : "ObBhL06.pcx", + }, + { + "id" : 27, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 261, + "height" : 129, + "blockedTiles" : [27, 28, 43, 44, 60, 61, 76, 77, 93, 94, 109, 110, 126, 127, 142, 143, 159], + "defname" : "ObBhL14.pcx", + }, + { + "id" : 28, + "allowedTerrain" : [], + "specialBattlefields" : [0], + "width" : 180, + "height" : 154, + "blockedTiles" : [22, 38, 39, 40, 44, 45, 46, 55, 56, 57, 62, 63, 123, 124, 125, 130, 131, 140, 141, 146, 147, 148], + "defname" : "ObBhL16.pcx", + }, + { + "id" : 29, + "allowedTerrain" : [], + "specialBattlefields" : [5], + "width" : 304, + "height" : 264, + "blockedTiles" : [76, 77, 92, 93, 94, 95, 109, 110, 111], + "defname" : "ObCFL00.pcx", + }, + { + "id" : 30, + "allowedTerrain" : [], + "specialBattlefields" : [6], + "width" : 256, + "height" : 257, + "blockedTiles" : [76, 77, 78, 92, 93, 94, 107, 108, 109], + "defname" : "ObLPL00.pcx", + }, + { + "id" : 31, + "allowedTerrain" : [], + "specialBattlefields" : [7], + "width" : 257, + "height" : 255, + "blockedTiles" : [76, 77, 91, 92, 93, 94, 95, 108, 109, 110, 111], + "defname" : "ObFFL00.pcx", + }, + { + "id" : 32, + "allowedTerrain" : [], + "specialBattlefields" : [8], + "width" : 277, + "height" : 218, + "blockedTiles" : [60, 61, 75, 76, 77, 91, 92, 93, 94, 95], + "defname" : "ObRLL00.pcx", + }, + { + "id" : 33, + "allowedTerrain" : [], + "specialBattlefields" : [9], + "width" : 300, + "height" : 214, + "blockedTiles" : [59, 60, 74, 75, 76, 93, 94, 95, 111, 112], + "defname" : "ObMCL00.pcx", + } +] + +} \ No newline at end of file diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index 027e76fd7..ee1656ad9 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -153,7 +153,7 @@ void BattleInfo::getAccessibilityMap(bool *accessibility, bool twoHex, bool atta //obstacles for(ui32 b=0; b blocked = VLC->heroh->obstacles[obstacles[b].ID].getBlocked(obstacles[b].pos); + std::vector blocked = obstacles[b].getBlocked(); for(ui32 c=0; c=0 && blocked[c] < GameConstants::BFIELD_SIZE) @@ -1501,6 +1501,81 @@ namespace CGH } } +//RNG that works like H3 one +struct RandGen +{ + int seed; + + void srand(int s) + { + seed = s; + } + void srand(int3 pos) + { + srand(110291 * pos.x + 167801 * pos.y + 81569); + } + int rand() + { + seed = 214013 * seed + 2531011; + return (seed >> 16) & 0x7FFF; + } + int rand(int min, int max) + { + if(min == max) + return min; + if(min > max) + return min; + return min + rand() % (max - min + 1); + } +}; + +struct RangeGenerator +{ + class ExhaustedPossibilities : public std::exception + { + }; + + RangeGenerator(int _min, int _max, boost::function _myRand) + { + myRand = _myRand; + min = _min; + remainingCount = _max - _min + 1; + remaining.resize(remainingCount, true); + } + + //get number fulfilling predicate. Never gives the same number twice. + int getSuchNumber(boost::function goodNumberPred = 0) + { + int ret = -1; + do + { + if(!remainingCount) + throw ExhaustedPossibilities(); + + int n = myRand() % remainingCount; + int i = 0; + for(;;i++) + { + assert(i < (int)remaining.size()); + if(!remaining[i]) + continue; + if(!n) + break; + n--; + } + + remainingCount--; + remaining[i] = false; + ret = i + min; + } while(goodNumberPred && !goodNumberPred(ret)); + return ret; + } + + int min, remainingCount; + std::vector remaining; + boost::function myRand; +}; + BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town ) { CMP_stack cmpst; @@ -1577,7 +1652,8 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const stacks.push_back(stack); } - for(unsigned g=0; gdoubleWide() && stacks[g]->attackerOwned) @@ -1667,61 +1743,96 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, int terrain, int terType, const } //randomize obstacles - if(town == NULL && !creatureBank) //do it only when it's not siege and not creature bank - { - bool obAv[GameConstants::BFIELD_SIZE]; //availability of hexes for obstacles; - std::vector possibleObstacles; + if(town == NULL && !creatureBank) //do it only when it's not siege and not creature bank + { + const int ABSOLUTE_OBSTACLES_COUNT = 34, USUAL_OBSTACLES_COUNT = 91; //shouldn't be changes if we want H3-like obstacle placement - for(int i=0; i 12) - { - obAv[i] = false; - } - else - { - obAv[i] = true; - } - } + RandGen r; + auto ourRand = [&]{ return r.rand(); }; + r.srand(tile); + const int sound = r.rand(1,8); //battle sound ID to play... can't do anything with it here + int tilesToBlock = r.rand(5,12); + const int specialBattlefield = battlefieldTypeToBI(terType); - for(std::map::const_iterator g=VLC->heroh->obstacles.begin(); g!=VLC->heroh->obstacles.end(); ++g) - { - if(g->second.allowedTerrains[terType-1] == '1') //we need to take terType with -1 because terrain ids start from 1 and allowedTerrains array is indexed from 0 - { - possibleObstacles.push_back(g->first); - } - } + std::vector blockedTiles; - srand(time(NULL)); - if(possibleObstacles.size() > 0) //we cannot place any obstacles when we don't have them + auto appropriateAbsoluteObstacle = [&](int id) { - int toBlock = rand()%6 + 6; //how many hexes should be blocked by obstacles - while(toBlock>0) + return VLC->heroh->absoluteObstacles[id].isAppropriate(terrain, specialBattlefield); + }; + auto appropriateUsualObstacle = [&](int id) -> bool + { + return VLC->heroh->obstacles[id].isAppropriate(terrain, specialBattlefield); + }; + + if(r.rand(1,100) <= 40) //put cliff-like obstacle + { + RangeGenerator obidgen(0, ABSOLUTE_OBSTACLES_COUNT-1, ourRand); + + try { CObstacleInstance coi; + coi.isAbsoluteObstacle = true; + coi.ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle); coi.uniqueID = curB->obstacles.size(); - coi.ID = possibleObstacles[rand()%possibleObstacles.size()]; - coi.pos = rand()%GameConstants::BFIELD_SIZE; - std::vector block = VLC->heroh->obstacles[coi.ID].getBlocked(coi.pos); - bool badObstacle = false; - for(int b=0; b= GameConstants::BFIELD_SIZE || !obAv[block[b]]) - { - badObstacle = true; - break; - } - } - if(badObstacle) continue; - //obstacle can be placed curB->obstacles.push_back(coi); - for(int b=0; b= 0 && block[b] < GameConstants::BFIELD_SIZE) - obAv[block[b]] = false; - } - toBlock -= block.size(); + + BOOST_FOREACH(BattleHex blocked, coi.getBlocked()) + blockedTiles.push_back(blocked); + tilesToBlock -= VLC->heroh->absoluteObstacles[coi.ID].blockedTiles.size() / 2; } + catch(RangeGenerator::ExhaustedPossibilities &) + { + //silently ignore, if we can't place absolute obstacle, we'll go wityh the usual ones + } + } + + RangeGenerator obidgen(0, USUAL_OBSTACLES_COUNT-1, ourRand); + try + { + while(tilesToBlock > 0) + { + const int obid = obidgen.getSuchNumber(appropriateUsualObstacle); + const CObstacleInfo &obi = VLC->heroh->obstacles[obid]; + + auto validPosition = [&](BattleHex pos) -> bool + { + if(obi.height >= pos.getY()) + return false; + if(pos.getX() == 0) + return false; + if(pos.getX() + obi.width > 15) + return false; + if(vstd::contains(blockedTiles, pos)) + return false; + + BOOST_FOREACH(BattleHex blocked, obi.getBlocked(pos)) + { + if(vstd::contains(blockedTiles, blocked)) + return false; + int x = blocked.getX(); + if(x <= 2 || x >= 14) + return false; + } + + return true; + }; + + RangeGenerator posgenerator(18, 168, ourRand); + + CObstacleInstance oi; + oi.ID = obid; + oi.pos = posgenerator.getSuchNumber(validPosition); + oi.uniqueID = curB->obstacles.size(); + curB->obstacles.push_back(oi); + + BOOST_FOREACH(BattleHex blocked, oi.getBlocked()) + blockedTiles.push_back(blocked); + tilesToBlock -= obi.blockedTiles.size(); + } + } + catch(RangeGenerator::ExhaustedPossibilities &) + { } } @@ -2400,7 +2511,7 @@ bool BattleInfo::isObstacleOnTile(BattleHex tile) const std::set coveredHexes; BOOST_FOREACH(const CObstacleInstance &obs, obstacles) { - std::vector blocked = VLC->heroh->obstacles.find(obs.ID)->second.getBlocked(obs.pos); + std::vector blocked = obs.getBlocked(); for(size_t w = 0; w < blocked.size(); ++w) coveredHexes.insert(blocked[w]); } @@ -2415,6 +2526,21 @@ const CStack * BattleInfo::getStackIf(boost::function pred) : *stackItr; } +int BattleInfo::battlefieldTypeToBI(int bfieldType) +{ + static const std::map theMap = boost::assign::map_list_of(19, BattlefieldBI::CLOVER_FIELD) + (22, BattlefieldBI::CURSED_GROUND)(20, BattlefieldBI::EVIL_FOG)(21, BattlefieldBI::NONE) + (14, BattlefieldBI::FIERY_FIELDS)(18, BattlefieldBI::HOLY_GROUND)(17, BattlefieldBI::LUCID_POOLS) + (16, BattlefieldBI::MAGIC_CLOUDS)(9, BattlefieldBI::MAGIC_PLAINS)(15, BattlefieldBI::ROCKLANDS) + (1, BattlefieldBI::COASTAL); + + auto itr = theMap.find(bfieldType); + if(itr != theMap.end()) + return itr->second; + + return BattlefieldBI::NONE; +} + CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S) : base(Base), ID(I), owner(O), slot(S), attackerOwned(AO), counterAttacks(1) diff --git a/lib/BattleState.h b/lib/BattleState.h index 70be0bf3a..9a0980875 100644 --- a/lib/BattleState.h +++ b/lib/BattleState.h @@ -155,6 +155,9 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode int theOtherPlayer(int player) const; ui8 whatSide(int player) const; + + static int battlefieldTypeToBI(int bfieldType); //converts above to ERM BI format + static int battlefieldTypeToTerrain(int bfieldType); //converts above to ERM BI format }; class DLL_LINKAGE CStack : public CBonusSystemNode, public CStackBasicDescriptor diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 938754810..c2ea7144c 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -915,7 +915,7 @@ void CStackInstance::deserializationFix() { const CCreature *backup = type; type = NULL; - setType(backup); + setType(backup); const CArmedInstance *armyBackup = _armyObj; _armyObj = NULL; setArmyObj(armyBackup); diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 0ecfa97bd..b6b5e53b2 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -1589,7 +1589,7 @@ void CGameState::init(StartInfo * si) } } -int CGameState::battleGetBattlefieldType(int3 tile) +int CGameState::battleGetBattlefieldType(int3 tile) const { if(tile==int3() && curB) tile = curB->tile; @@ -1609,27 +1609,28 @@ int CGameState::battleGetBattlefieldType(int3 tile) || !objs[g]->coveringAt(objs[g]->pos.x - tile.x, tile.y - objs[g]->pos.y + 5) ) //look only for objects covering given tile continue; + switch(objs[g]->ID) { - case 222: //clover field + case Obj::CLOVER_FIELD: return 19; - case 21: case 223: //cursed ground + case Obj::CURSED_GROUND1: case Obj::CURSED_GROUND2: return 22; - case 224: //evil fog + case Obj::EVIL_FOG: return 20; - case 225: //favourable winds + case Obj::FAVORABLE_WINDS: return 21; - case 226: //fiery fields + case Obj::FIERY_FIELDS: return 14; - case 227: //holy ground + case Obj::HOLY_GROUNDS: return 18; - case 228: //lucid pools + case Obj::LUCID_POOLS: return 17; - case 229: //magic clouds + case Obj::MAGIC_CLOUDS: return 16; - case 46: case 230: //magic plains + case Obj::MAGIC_PLAINS1: case Obj::MAGIC_PLAINS2: return 9; - case 231: //rocklands + case Obj::ROCKLANDS: return 15; } } @@ -1664,6 +1665,7 @@ int CGameState::battleGetBattlefieldType(int3 tile) } } + std::set > costDiff(const std::vector &a, const std::vector &b, const int modifier = 100) //modifer % { std::set > ret; diff --git a/lib/CGameState.h b/lib/CGameState.h index e2c54e038..0d62a8b78 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -381,7 +381,7 @@ public: void giveHeroArtifact(CGHeroInstance *h, int aid); void apply(CPack *pack); - int battleGetBattlefieldType(int3 tile = int3());// 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship + int battleGetBattlefieldType(int3 tile) const;// 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship UpgradeInfo getUpgradeInfo(const CStackInstance &stack); int getPlayerRelations(ui8 color1, ui8 color2);// 0 = enemy, 1 = ally, 2 = same player bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index b05a0bdd8..3b186a4c8 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -6,13 +6,7 @@ #include "../lib/JsonNode.h" #include "GameConstants.h" #include -#if BOOST_VERSION >= 103800 -#include -#else -#include -#endif - -using namespace boost::spirit; +#include "BattleHex.h" extern CLodHandler * bitmaph; void loadToIt(std::string &dest, const std::string &src, int &iter, int mode); @@ -57,74 +51,37 @@ EAlignment::EAlignment CHeroClass::getAlignment() return (EAlignment::EAlignment)alignment; } -int CObstacleInfo::getWidth() const -{ - int ret = 1; - int line = 1; - for(int h=0; h ret) - ret = cur; - ++line; - break; - } - } - return ret; -} - -int CObstacleInfo::getHeight() const -{ - int ret = 1; - for(int h=0; h CObstacleInfo::getBlocked(BattleHex hex) const { std::vector ret; - int cur = hex; //currently browsed hex - int curBeg = hex; //beginning of current line - for(int h=0; h blocked = getBlocked(hex); - return *std::max_element(blocked.begin(), blocked.end()); + if(specialBattlefield != -1) + return vstd::contains(allowedSpecialBfields, specialBattlefield); + + return vstd::contains(allowedTerrains, terrainType); } CHeroHandler::~CHeroHandler() @@ -141,21 +98,27 @@ CHeroHandler::CHeroHandler() void CHeroHandler::loadObstacles() { + auto loadObstacles = [](const JsonNode &node, bool absolute, std::map &out) + { + BOOST_FOREACH(const JsonNode &obs, node.Vector()) + { + int ID = obs["id"].Float(); + CObstacleInfo & obi = out[ID]; + obi.ID = ID; + obi.defName = obs["defname"].String(); + obi.width = obs["width"].Float(); + obi.height = obs["height"].Float(); + obi.allowedTerrains = obs["allowedTerrain"].StdVector(); + obi.allowedSpecialBfields = obs["specialBattlefields"].StdVector(); + obi.blockedTiles = obs["blockedTiles"].StdVector(); + obi.isAbsoluteObstacle = absolute; + } + }; + + const JsonNode config(GameConstants::DATA_DIR + "/config/obstacles.json"); - - BOOST_FOREACH(const JsonNode &obs, config["obstacles"].Vector()) { - CObstacleInfo obi; - - obi.ID = obs["id"].Float(); - obi.defName = obs["defname"].String(); - obi.blockmap = obs["blockmap"].String(); - obi.allowedTerrains = obs["terrains"].String(); - assert(obi.allowedTerrains.size() >= 25); - obi.posShift.first = obs["shift_x"].Float(); - obi.posShift.second = obs["shift_y"].Float(); - - obstacles[obi.ID] = obi; - } + loadObstacles(config["obstacles"], false, obstacles); + loadObstacles(config["absoluteObstacles"], true, absoluteObstacles); } void CHeroHandler::loadPuzzleInfo() @@ -164,12 +127,12 @@ void CHeroHandler::loadPuzzleInfo() int faction = 0; - BOOST_FOREACH(const JsonNode &puzzle, config["puzzles"].Vector()) { - + BOOST_FOREACH(const JsonNode &puzzle, config["puzzles"].Vector()) + { int idx = 0; - BOOST_FOREACH(const JsonNode &piece, puzzle.Vector()) { - + BOOST_FOREACH(const JsonNode &piece, puzzle.Vector()) + { SPuzzleInfo spi; spi.x = piece["x"].Float(); diff --git a/lib/CHeroHandler.h b/lib/CHeroHandler.h index d19abb32c..104b15b2f 100644 --- a/lib/CHeroHandler.h +++ b/lib/CHeroHandler.h @@ -1,7 +1,6 @@ #pragma once -#include "BattleHex.h" #include "../lib/ConstTransitivePtr.h" #include "GameConstants.h" @@ -18,6 +17,7 @@ class CHeroClass; class CDefHandler; class CGameInfo; class CGHeroInstance; +struct BattleHex; struct SSpecialtyInfo { si32 type; @@ -85,22 +85,22 @@ public: struct DLL_LINKAGE CObstacleInfo { - int ID; - std::string defName, - blockmap, //blockmap: X - blocked, N - not blocked, L - description goes to the next line, staring with the left bottom hex - allowedTerrains; /*terrains[i]: 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills - 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees - 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field - 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough - 24. ship to ship 25. ship*/ - std::pair posShift; //shift of obstacle's position in the battlefield , eg. if it's <-1, 2> obstacle will be printed one pixel to the left and two to the bottom - int getWidth() const; //returns width of obstacle in hexes - int getHeight() const; //returns height of obstacle in hexes + si32 ID; + std::string defName; + std::vector allowedTerrains; + std::vector allowedSpecialBfields; + + ui8 isAbsoluteObstacle; //there may only one such obstacle in battle and its position is always the same + si32 width, height; //how much space to the right and up is needed to place obstacle (affects only placement algorithm) + std::vector blockedTiles; //offsets relative to obstacle position (that is its left bottom corner) + std::vector getBlocked(BattleHex hex) const; //returns vector of hexes blocked by obstacle when it's placed on hex 'hex' - BattleHex getMaxBlocked(BattleHex hex) const; //returns maximal hex (max number) covered by this obstacle + + bool isAppropriate(int terrainType, int specialBattlefield = -1) const; + template void serialize(Handler &h, const int version) { - h & ID & defName & blockmap & allowedTerrains & posShift; + h & ID & defName & allowedTerrains & allowedSpecialBfields & isAbsoluteObstacle & width & height & blockedTiles; } }; @@ -140,6 +140,7 @@ public: std::vector ballistics; //info about ballistics ability per level; [0] - none; [1] - basic; [2] - adv; [3] - expert std::map obstacles; //info about obstacles that may be placed on battlefield + std::map absoluteObstacles; //info about obstacles that may be placed on battlefield std::vector nativeTerrains; //info about native terrains of different factions void loadObstacles(); //loads info about obstacles @@ -159,7 +160,7 @@ public: template void serialize(Handler &h, const int version) { - h & heroClasses & heroes & expPerLevel & ballistics & obstacles & nativeTerrains & puzzleInfo; + h & heroClasses & heroes & expPerLevel & ballistics & obstacles & absoluteObstacles & nativeTerrains & puzzleInfo; if(!h.saving) { //restore class pointers diff --git a/lib/CMapInfo.cpp b/lib/CMapInfo.cpp index 6f4bd169e..caabff232 100644 --- a/lib/CMapInfo.cpp +++ b/lib/CMapInfo.cpp @@ -45,9 +45,9 @@ void CMapInfo::mapInit(const std::string &fname, const ui8 *map ) mapHeader->initFromMemory(map, i); countPlayers(); } - catch (const std::string &e) + catch (const std::exception &e) { - tlog1 << "\t\tWarning: evil map file: " << fname << ": " << e << std::endl; + tlog1 << "\t\tWarning: evil map file: " << fname << ": " << e.what() << std::endl; delete mapHeader; mapHeader = NULL; } diff --git a/lib/CObstacleInstance.h b/lib/CObstacleInstance.h index f80907245..9a5fcaccb 100644 --- a/lib/CObstacleInstance.h +++ b/lib/CObstacleInstance.h @@ -1,12 +1,23 @@ #pragma once +#include "BattleHex.h" + +struct CObstacleInfo; struct DLL_LINKAGE CObstacleInstance { - int uniqueID; - int ID; //ID of obstacle (defines type of it) - int pos; //position on battlefield + si32 uniqueID; + si32 ID; //ID of obstacle (defines type of it) + BattleHex pos; //position on battlefield + + ui8 isAbsoluteObstacle; //if true, then position is meaningless + + CObstacleInstance(); + + const CObstacleInfo &getInfo() const; + std::vector getBlocked() const; + template void serialize(Handler &h, const int version) { - h & ID & pos & uniqueID; + h & ID & pos & isAbsoluteObstacle & uniqueID; } }; \ No newline at end of file diff --git a/lib/GameConstants.h b/lib/GameConstants.h index e7c1df9f8..fdce5e403 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -187,6 +187,7 @@ namespace Obj BOAT = 8, CREATURE_BANK = 16, CREATURE_GENERATOR1 = 17, + CURSED_GROUND1 = 21, DERELICT_SHIP = 24, DRAGON_UTOPIA = 25, GARRISON = 33, @@ -194,6 +195,7 @@ namespace Obj MONOLITH1 = 43, MONOLITH2 = 44, MONOLITH3 = 45, + MAGIC_PLAINS1 = 46, SCHOOL_OF_MAGIC = 47, MINE = 53, MONSTER = 54, @@ -209,6 +211,35 @@ namespace Obj WHIRLPOOL = 111, BORDER_GATE = 212, GARRISON2 = 219, + CLOVER_FIELD = 222, + CURSED_GROUND2 = 223, + EVIL_FOG = 224, + FAVORABLE_WINDS = 225, + FIERY_FIELDS = 226, + HOLY_GROUNDS = 227, + LUCID_POOLS = 228, + MAGIC_CLOUDS = 229, + MAGIC_PLAINS2 = 230, + ROCKLANDS = 231, + }; +} + +//follows ERM BI (battle image) format +namespace BattlefieldBI +{ + enum + { + NONE = -1, + COASTAL, + CURSED_GROUND, + MAGIC_PLAINS, + HOLY_GROUND, + EVIL_FOG, + CLOVER_FIELD, + LUCID_POOLS, + FIERY_FIELDS, + ROCKLANDS, + MAGIC_CLOUDS, }; } diff --git a/lib/JsonNode.h b/lib/JsonNode.h index cc6b7910a..2b612524a 100644 --- a/lib/JsonNode.h +++ b/lib/JsonNode.h @@ -75,6 +75,19 @@ public: const JsonVector & Vector() const; const JsonMap & Struct() const; + template + std::vector StdVector() const + { + + static_assert(typename std::is_arithmetic::value, "This works with numbers only."); + std::vector ret; + BOOST_FOREACH(const JsonNode &node, Vector()) + { + ret.push_back(node.Float()); + } + return ret; + } + //operator [], for structs only - get child node by name JsonNode & operator[](std::string child); const JsonNode & operator[](std::string child) const; diff --git a/lib/VCMI_lib.vcxproj b/lib/VCMI_lib.vcxproj index 8f2d5c785..b2673f927 100644 --- a/lib/VCMI_lib.vcxproj +++ b/lib/VCMI_lib.vcxproj @@ -239,6 +239,7 @@ + diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index f665982f3..4032e87d4 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3884,17 +3884,16 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest case Spells::REMOVE_OBSTACLE: { ObstaclesRemoved obr; - for(int g=0; gcurB->obstacles.size(); ++g) + BOOST_FOREACH(const CObstacleInstance &obstacle, battleGetAllObstacles()) { - std::vector blockedHexes = VLC->heroh->obstacles[gs->curB->obstacles[g].ID].getBlocked(gs->curB->obstacles[g].pos); - - if(vstd::contains(blockedHexes, destination)) //this obstacle covers given hex - { - obr.obstacles.insert(gs->curB->obstacles[g].uniqueID); - } + if(vstd::contains(obstacle.getBlocked(), destination)) + obr.obstacles.insert(obstacle.uniqueID); } + if(!obr.obstacles.empty()) sendAndApply(&obr); + else + complain("There's no obstacle to remove!"); break; } break;