mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge branch 'develop' of https://github.com/vcmi/vcmi into test/advMapFading
This commit is contained in:
commit
4c636c15e9
@ -12,7 +12,7 @@ before_install:
|
||||
#new Qt
|
||||
- sudo add-apt-repository --yes ppa:beineri/opt-qt532
|
||||
#new FFmpeg
|
||||
- sudo add-apt-repository --yes ppa:djcj/vlc-stable
|
||||
- sudo add-apt-repository --yes ppa:jon-severinsson/ffmpeg
|
||||
#new CMake
|
||||
- sudo add-apt-repository --yes ppa:andykimpe/cmake
|
||||
|
||||
|
@ -496,9 +496,19 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
|
||||
NET_EVENT_HANDLER;
|
||||
if(sop->what == ObjProperty::OWNER)
|
||||
{
|
||||
//we don't want to visit know object twice (do we really?)
|
||||
if(sop->val == playerID.getNum())
|
||||
erase_if_present(visitableObjs, myCb->getObj(sop->id));
|
||||
//TODO restore lost obj
|
||||
else if (myCb->getPlayerRelations(playerID, (PlayerColor)sop->val) == PlayerRelations::ENEMIES)
|
||||
{
|
||||
//we want to visit objects owned by oppponents
|
||||
auto obj = myCb->getObj(sop->id, false);
|
||||
if (obj)
|
||||
{
|
||||
visitableObjs.insert(obj);
|
||||
erase_if_present(alreadyVisited, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
0.97 -> 0.98
|
||||
ADVENTURE MAP:
|
||||
* Implemented world veiw
|
||||
|
||||
SPELLS:
|
||||
* implemented CURE spell negative dispell effect
|
||||
@ -8,6 +10,7 @@ BATTLES:
|
||||
* Implemented OH3 stack split / upgrade formulas according to AlexSpl
|
||||
|
||||
RANDOM MAP GENERATOR:
|
||||
* Implemented "junction" zone type
|
||||
* Improved zone placing algorithm
|
||||
* More balanced distribution of treasure piles
|
||||
* More obstacles within zones
|
||||
|
@ -2317,7 +2317,10 @@ void OptionsTab::nextCastle( PlayerColor player, int dir )
|
||||
}
|
||||
|
||||
if(s.hero >= 0 && !SEL->current->mapHeader->players[s.color.getNum()].hasCustomMainHero()) // remove hero unless it set to fixed one in map editor
|
||||
{
|
||||
usedHeroes.erase(s.hero); // restore previously selected hero back to available pool
|
||||
s.hero = PlayerSettings::RANDOM;
|
||||
}
|
||||
if(cur < 0 && s.bonus == PlayerSettings::RESOURCE)
|
||||
s.bonus = PlayerSettings::RANDOM;
|
||||
|
||||
@ -2352,7 +2355,7 @@ void OptionsTab::nextHero( PlayerColor player, int dir )
|
||||
if(dir > 0)
|
||||
s.hero = nextAllowedHero(player, s.hero, CGI->heroh->heroes.size(), 1, dir);
|
||||
else
|
||||
s.hero = nextAllowedHero(player, 0, s.hero, 1, dir);
|
||||
s.hero = nextAllowedHero(player, -1, s.hero, 1, dir); // min needs to be -1 -- hero at index 0 would be skipped otherwise
|
||||
}
|
||||
|
||||
if(old != s.hero)
|
||||
@ -2530,6 +2533,7 @@ void OptionsTab::flagPressed( PlayerColor color )
|
||||
usedHeroes.erase(old->hero);
|
||||
|
||||
old->hero = entries[old->color]->pi.defaultHero();
|
||||
entries[old->color]->update(); // update previous frame images in case entries were auto-updated
|
||||
}
|
||||
|
||||
SEL->propagateOptions();
|
||||
|
@ -261,7 +261,7 @@ bool CVideoPlayer::nextFrame()
|
||||
if (doLoop && !gotError)
|
||||
{
|
||||
// Rewind
|
||||
if (av_seek_frame(format, stream, 0, 0) < 0)
|
||||
if (av_seek_frame(format, stream, 0, AVSEEK_FLAG_BYTE) < 0)
|
||||
break;
|
||||
gotError = true;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
|
||||
class CEmptyVideoPlayer : public IMainVideoPlayer
|
||||
{
|
||||
public:
|
||||
public:
|
||||
int curFrame() const override {return -1;};
|
||||
int frameCount() const override {return -1;};
|
||||
void redraw( int x, int y, SDL_Surface *dst, bool update = true ) override {};
|
||||
@ -54,6 +54,18 @@ public:
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
// compatibility with different versions od libavutil
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 42, 0)) || \
|
||||
(LIBAVUTIL_VERSION_INT == AV_VERSION_INT(51, 73, 101))
|
||||
|
||||
#define AV_PIX_FMT_NONE PIX_FMT_NONE
|
||||
#define AV_PIX_FMT_NV12 PIX_FMT_NV12
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#define AV_PIX_FMT_UYVY422 PIX_FMT_UYVY422
|
||||
#define AV_PIX_FMT_YUYV422 PIX_FMT_YUYV422
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
class CVideoPlayer : public IMainVideoPlayer
|
||||
|
@ -1788,14 +1788,19 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack)
|
||||
|
||||
void CBattleInterface::printConsoleAttacked( const CStack * defender, int dmg, int killed, const CStack * attacker, bool multiple )
|
||||
{
|
||||
boost::format txt;
|
||||
std::string formattedText;
|
||||
if (attacker) //ignore if stacks were killed by spell
|
||||
{
|
||||
txt = boost::format (CGI->generaltexth->allTexts[attacker->count > 1 ? 377 : 376]) %
|
||||
boost::format txt = boost::format (CGI->generaltexth->allTexts[attacker->count > 1 ? 377 : 376]) %
|
||||
(attacker->count > 1 ? attacker->getCreature()->namePl : attacker->getCreature()->nameSing) % dmg;
|
||||
formattedText.append(boost::to_string(txt));
|
||||
}
|
||||
if(killed > 0)
|
||||
{
|
||||
if (attacker)
|
||||
formattedText.append(" ");
|
||||
|
||||
boost::format txt;
|
||||
if(killed > 1)
|
||||
{
|
||||
txt = boost::format (CGI->generaltexth->allTexts[379]) % killed % (multiple ? CGI->generaltexth->allTexts[43] : defender->getCreature()->namePl); // creatures perish
|
||||
@ -1804,9 +1809,12 @@ void CBattleInterface::printConsoleAttacked( const CStack * defender, int dmg, i
|
||||
{
|
||||
txt = boost::format (CGI->generaltexth->allTexts[378]) % (multiple ? CGI->generaltexth->allTexts[42] : defender->getCreature()->nameSing); // creature perishes
|
||||
}
|
||||
std::string trimmed = boost::to_string(txt);
|
||||
boost::algorithm::trim(trimmed); // these default h3 texts have unnecessary new lines, so get rid of them before displaying
|
||||
formattedText.append(trimmed);
|
||||
}
|
||||
console->addText(formattedText);
|
||||
|
||||
console->addText(boost::to_string (txt));
|
||||
}
|
||||
|
||||
|
||||
|
@ -713,11 +713,11 @@ void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo)
|
||||
tileSize = (int) floorf(32.0f * info->scale);
|
||||
halfTileSizeCeil = (int)ceilf(tileSize / 2.0f);
|
||||
|
||||
tileCount.x = (int) ceilf((float)info->drawBounds->w / tileSize) + 1;
|
||||
tileCount.y = (int) ceilf((float)info->drawBounds->h / tileSize) + 1;
|
||||
tileCount.x = (int) ceilf((float)info->drawBounds->w / tileSize);
|
||||
tileCount.y = (int) ceilf((float)info->drawBounds->h / tileSize);
|
||||
|
||||
initPos.x = parent->offsetX + info->drawBounds->x;
|
||||
initPos.y = parent->offsetY + info->drawBounds->y;
|
||||
initPos.x = info->drawBounds->x;
|
||||
initPos.y = info->drawBounds->y;
|
||||
|
||||
realTileRect = Rect(initPos.x, initPos.y, tileSize, tileSize);
|
||||
defaultTileRect = Rect(0, 0, tileSize, tileSize);
|
||||
@ -732,8 +732,9 @@ SDL_Rect CMapHandler::CMapWorldViewBlitter::clip(SDL_Surface * targetSurf) const
|
||||
|
||||
SDL_FillRect(targetSurf, info->drawBounds, SDL_MapRGB(targetSurf->format, 0, 0, 0));
|
||||
// makes the clip area smaller if the map is smaller than the screen frame
|
||||
Rect clipRect(std::max(info->drawBounds->x, -topTile.x * tileSize),
|
||||
std::max(info->drawBounds->y, -topTile.y * tileSize),
|
||||
// (actually, it could be made 1 tile bigger so that overlay icons on edge tiles could be drawn partly outside)
|
||||
Rect clipRect(std::max(info->drawBounds->x, info->drawBounds->x - topTile.x * tileSize),
|
||||
std::max(info->drawBounds->y, info->drawBounds->y - topTile.y * tileSize),
|
||||
std::min(info->drawBounds->w, parent->sizes.x * tileSize),
|
||||
std::min(info->drawBounds->h, parent->sizes.y * tileSize));
|
||||
SDL_GetClipRect(targetSurf, &prevClip);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CPreGame.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../CMessage.h"
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Pixels.h"
|
||||
@ -1234,6 +1235,11 @@ CAdvMapPanel::CAdvMapPanel(SDL_Surface * bg, Point position)
|
||||
recActions = 255;
|
||||
pos.x += position.x;
|
||||
pos.y += position.y;
|
||||
if (bg)
|
||||
{
|
||||
pos.w = bg->w;
|
||||
pos.h = bg->h;
|
||||
}
|
||||
}
|
||||
|
||||
CAdvMapPanel::~CAdvMapPanel()
|
||||
@ -1270,13 +1276,26 @@ void CAdvMapPanel::addChildToPanel(CIntObject * obj, ui8 actions /* = 0 */)
|
||||
addChild(obj, false);
|
||||
}
|
||||
|
||||
CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(SDL_Surface * bg, Point position)
|
||||
: CAdvMapPanel(bg, position)
|
||||
CAdvMapWorldViewPanel::CAdvMapWorldViewPanel(SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color)
|
||||
: CAdvMapPanel(bg, position)
|
||||
{
|
||||
|
||||
fillerHeight = bg ? spaceBottom - pos.y - pos.h : 0;
|
||||
|
||||
if (fillerHeight > 0)
|
||||
{
|
||||
tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color);
|
||||
}
|
||||
else
|
||||
tmpBackgroundFiller = nullptr;
|
||||
}
|
||||
|
||||
void CAdvMapWorldViewPanel::recolorIcons(const CDefHandler *def, int indexOffset)
|
||||
CAdvMapWorldViewPanel::~CAdvMapWorldViewPanel()
|
||||
{
|
||||
if (tmpBackgroundFiller)
|
||||
SDL_FreeSurface(tmpBackgroundFiller);
|
||||
}
|
||||
|
||||
void CAdvMapWorldViewPanel::recolorIcons(const PlayerColor &color, const CDefHandler *def, int indexOffset)
|
||||
{
|
||||
for (auto &pic : currentIcons)
|
||||
{
|
||||
@ -1292,6 +1311,13 @@ void CAdvMapWorldViewPanel::recolorIcons(const CDefHandler *def, int indexOffset
|
||||
currentIcons.push_back(pic);
|
||||
addChildToPanel(pic);
|
||||
}
|
||||
|
||||
if (fillerHeight > 0)
|
||||
{
|
||||
if (tmpBackgroundFiller)
|
||||
SDL_FreeSurface(tmpBackgroundFiller);
|
||||
tmpBackgroundFiller = CMessage::drawDialogBox(pos.w, fillerHeight, color);
|
||||
}
|
||||
}
|
||||
|
||||
void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, const CDefHandler *def, int indexOffset)
|
||||
@ -1301,3 +1327,13 @@ void CAdvMapWorldViewPanel::addChildIcon(std::pair<int, Point> data, const CDefH
|
||||
currentIcons.push_back(pic);
|
||||
addChildToPanel(pic);
|
||||
}
|
||||
|
||||
void CAdvMapWorldViewPanel::showAll(SDL_Surface * to)
|
||||
{
|
||||
if (tmpBackgroundFiller)
|
||||
{
|
||||
blitAt(tmpBackgroundFiller, pos.x, pos.y + pos.h, to);
|
||||
}
|
||||
|
||||
CAdvMapPanel::showAll(to);
|
||||
}
|
||||
|
@ -341,13 +341,17 @@ class CAdvMapWorldViewPanel : public CAdvMapPanel
|
||||
std::vector<std::pair<int, Point>> iconsData;
|
||||
/// ptrs to child-pictures constructed from iconsData
|
||||
std::vector<CPicture *> currentIcons;
|
||||
/// temporary surface drawn below world view panel on higher resolutions (won't be needed when world view panel is configured for extraResolutions mod)
|
||||
SDL_Surface * tmpBackgroundFiller;
|
||||
int fillerHeight;
|
||||
public:
|
||||
CAdvMapWorldViewPanel(SDL_Surface * bg, Point position);
|
||||
virtual ~CAdvMapWorldViewPanel(){}
|
||||
CAdvMapWorldViewPanel(SDL_Surface * bg, Point position, int spaceBottom, const PlayerColor &color);
|
||||
virtual ~CAdvMapWorldViewPanel();
|
||||
|
||||
void addChildIcon(std::pair<int, Point> data, const CDefHandler *def, int indexOffset);
|
||||
/// recreates all pictures from given def to recolor them according to current player color
|
||||
void recolorIcons(const CDefHandler *def, int indexOffset);
|
||||
void recolorIcons(const PlayerColor &color, const CDefHandler *def, int indexOffset);
|
||||
void showAll(SDL_Surface * to);
|
||||
};
|
||||
|
||||
class CInGameConsole : public CIntObject
|
||||
|
@ -239,17 +239,20 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
const CGHeroInstance *srcHero = commonInfo->src.AOH->getHero();
|
||||
artSelected = true;
|
||||
ArtifactLocation src(srcHero, commonInfo->src.slotID);
|
||||
ArtifactLocation dst(myStack, ArtifactPosition::CREATURE_SLOT);
|
||||
if (art->canBePutAt(dst, true))
|
||||
{ //equip clicked stack
|
||||
if(dst.getArt())
|
||||
{
|
||||
//creature can wear only one active artifact
|
||||
//if we are placing a new one, the old one will be returned to the hero's backpack
|
||||
LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero, dst.getArt()->firstBackpackSlot(srcHero)));
|
||||
if (myStack) // try dropping the artifact only if the slot isn't empty
|
||||
{
|
||||
ArtifactLocation src(srcHero, commonInfo->src.slotID);
|
||||
ArtifactLocation dst(myStack, ArtifactPosition::CREATURE_SLOT);
|
||||
if (art->canBePutAt(dst, true))
|
||||
{ //equip clicked stack
|
||||
if(dst.getArt())
|
||||
{
|
||||
//creature can wear only one active artifact
|
||||
//if we are placing a new one, the old one will be returned to the hero's backpack
|
||||
LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero, dst.getArt()->firstBackpackSlot(srcHero)));
|
||||
}
|
||||
LOCPLINT->cb->swapArtifacts(src, dst);
|
||||
}
|
||||
LOCPLINT->cb->swapArtifacts(src, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -499,8 +499,11 @@ CAdvMapInt::CAdvMapInt():
|
||||
nextHero = makeButton(301, std::bind(&CAdvMapInt::fnextHero,this), ADVOPT.nextHero, SDLK_h);
|
||||
endTurn = makeButton(302, std::bind(&CAdvMapInt::fendTurn,this), ADVOPT.endTurn, SDLK_e);
|
||||
|
||||
int panelSpaceBottom = screen->h - resdatabar.pos.h - 4;
|
||||
|
||||
panelMain = new CAdvMapPanel(nullptr, Point(0, 0));
|
||||
panelWorldView = new CAdvMapWorldViewPanel(bgWorldView, Point(heroList.pos.x - 2, 195)); // TODO correct drawing position
|
||||
// TODO correct drawing position
|
||||
panelWorldView = new CAdvMapWorldViewPanel(bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
|
||||
|
||||
panelMain->addChildColorableButton(kingOverview);
|
||||
panelMain->addChildColorableButton(underground);
|
||||
@ -1072,6 +1075,10 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
|
||||
if(isActive())
|
||||
LOCPLINT->showPuzzleMap();
|
||||
return;
|
||||
case SDLK_v:
|
||||
if(isActive())
|
||||
LOCPLINT->viewWorldMap();
|
||||
return;
|
||||
case SDLK_r:
|
||||
if(isActive() && LOCPLINT->ctrlPressed())
|
||||
{
|
||||
@ -1331,7 +1338,7 @@ void CAdvMapInt::setPlayer(PlayerColor Player)
|
||||
|
||||
panelMain->setPlayerColor(player);
|
||||
panelWorldView->setPlayerColor(player);
|
||||
panelWorldView->recolorIcons(worldViewIconsDef, player.getNum() * 19);
|
||||
panelWorldView->recolorIcons(player, worldViewIconsDef, player.getNum() * 19);
|
||||
graphics->blueToPlayersAdv(resdatabar.bg,player);
|
||||
|
||||
//heroList.updateHList();
|
||||
@ -1791,8 +1798,7 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale /* = 0.4f */)
|
||||
else if (worldViewScale != newScale) // still in world view mode, but the scale changed
|
||||
{
|
||||
worldViewScale = newScale;
|
||||
terrain.redraw();
|
||||
minimap.redraw(); // to recalculate radar rect on minimap
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1801,7 +1807,7 @@ CAdventureOptions::CAdventureOptions():
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
viewWorld = new CButton(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&]{ close(); }, SDLK_x);
|
||||
viewWorld = new CButton(Point(24, 23), "ADVVIEW.DEF", CButton::tooltip(), [&]{ close(); }, SDLK_v);
|
||||
viewWorld->addCallback(std::bind(&CPlayerInterface::viewWorldMap, LOCPLINT));
|
||||
|
||||
exit = new CButton(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), std::bind(&CAdventureOptions::close, this), SDLK_RETURN);
|
||||
|
@ -316,11 +316,18 @@ void CStackWindow::CWindowSection::createActiveSpells()
|
||||
std::vector<si32> spells = battleStack->activeSpells();
|
||||
for(si32 effect : spells)
|
||||
{
|
||||
const CSpell * sp = CGI->spellh->objects[effect];
|
||||
|
||||
std::string spellText;
|
||||
if (effect < 77) //not all effects have graphics (for eg. Acid Breath)
|
||||
|
||||
//not all effects have graphics (for eg. Acid Breath)
|
||||
//for modded spells iconEffect is added to SpellInt.def
|
||||
const bool hasGraphics = (effect < SpellID::THUNDERBOLT) || (effect >= SpellID::AFTER_LAST);
|
||||
|
||||
if (hasGraphics)
|
||||
{
|
||||
spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds."
|
||||
boost::replace_first (spellText, "%s", CGI->spellh->objects[effect]->name);
|
||||
boost::replace_first (spellText, "%s", sp->name);
|
||||
int duration = battleStack->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT,effect))->turnsRemain;
|
||||
boost::replace_first (spellText, "%d", boost::lexical_cast<std::string>(duration));
|
||||
|
||||
|
@ -120,6 +120,11 @@ void CTileInfo::setOccupied(ETileType::ETileType value)
|
||||
occupied = value;
|
||||
}
|
||||
|
||||
ETileType::ETileType CTileInfo::getTileType() const
|
||||
{
|
||||
return occupied;
|
||||
}
|
||||
|
||||
ETerrainType CTileInfo::getTerrainType() const
|
||||
{
|
||||
return terrain;
|
||||
@ -371,6 +376,11 @@ void CRmgTemplateZone::discardDistantTiles (CMapGenerator* gen, float distance)
|
||||
});
|
||||
}
|
||||
|
||||
void CRmgTemplateZone::clearTiles()
|
||||
{
|
||||
tileinfo.clear();
|
||||
}
|
||||
|
||||
void CRmgTemplateZone::initFreeTiles (CMapGenerator* gen)
|
||||
{
|
||||
vstd::copy_if (tileinfo, vstd::set_inserter(possibleTiles), [gen](const int3 &tile) -> bool
|
||||
@ -413,7 +423,7 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
|
||||
int totalDensity = 0;
|
||||
for (auto ti : treasureInfo)
|
||||
totalDensity =+ ti.density;
|
||||
const float minDistance = totalDensity * 4; //squared
|
||||
const float minDistance = 10 * 10; //squared
|
||||
|
||||
for (auto tile : tileinfo)
|
||||
{
|
||||
@ -424,57 +434,62 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
|
||||
}
|
||||
assert (clearedTiles.size()); //this should come from zone connections
|
||||
|
||||
while (possibleTiles.size())
|
||||
if (type != ETemplateZoneType::JUNCTION)
|
||||
{
|
||||
//link tiles in random order
|
||||
std::vector<int3> tilesToMakePath(possibleTiles.begin(), possibleTiles.end());
|
||||
RandomGeneratorUtil::randomShuffle(tilesToMakePath, gen->rand);
|
||||
|
||||
for (auto tileToMakePath : tilesToMakePath)
|
||||
//junction is not fractalized, has only one straight path
|
||||
//everything else remains blocked
|
||||
while (possibleTiles.size())
|
||||
{
|
||||
//find closest free tile
|
||||
float currentDistance = 1e10;
|
||||
int3 closestTile (-1,-1,-1);
|
||||
//link tiles in random order
|
||||
std::vector<int3> tilesToMakePath(possibleTiles.begin(), possibleTiles.end());
|
||||
RandomGeneratorUtil::randomShuffle(tilesToMakePath, gen->rand);
|
||||
|
||||
for (auto clearTile : clearedTiles)
|
||||
for (auto tileToMakePath : tilesToMakePath)
|
||||
{
|
||||
float distance = tileToMakePath.dist2dSQ(clearTile);
|
||||
|
||||
if (distance < currentDistance)
|
||||
//find closest free tile
|
||||
float currentDistance = 1e10;
|
||||
int3 closestTile(-1, -1, -1);
|
||||
|
||||
for (auto clearTile : clearedTiles)
|
||||
{
|
||||
currentDistance = distance;
|
||||
closestTile = clearTile;
|
||||
float distance = tileToMakePath.dist2dSQ(clearTile);
|
||||
|
||||
if (distance < currentDistance)
|
||||
{
|
||||
currentDistance = distance;
|
||||
closestTile = clearTile;
|
||||
}
|
||||
if (currentDistance <= minDistance)
|
||||
{
|
||||
//this tile is close enough. Forget about it and check next one
|
||||
tilesToIgnore.insert(tileToMakePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currentDistance <= minDistance)
|
||||
//if tiles is not close enough, make path to it
|
||||
if (currentDistance > minDistance)
|
||||
{
|
||||
//this tile is close enough. Forget about it and check next one
|
||||
tilesToIgnore.insert (tileToMakePath);
|
||||
break;
|
||||
crunchPath(gen, tileToMakePath, closestTile, id, &tilesToClear);
|
||||
break; //next iteration - use already cleared tiles
|
||||
}
|
||||
}
|
||||
//if tiles is not close enough, make path to it
|
||||
if (currentDistance > minDistance)
|
||||
{
|
||||
crunchPath (gen, tileToMakePath, closestTile, id, &tilesToClear);
|
||||
break; //next iteration - use already cleared tiles
|
||||
}
|
||||
}
|
||||
|
||||
for (auto tileToClear : tilesToClear)
|
||||
{
|
||||
//move cleared tiles from one set to another
|
||||
clearedTiles.push_back(tileToClear);
|
||||
vstd::erase_if_present(possibleTiles, tileToClear);
|
||||
for (auto tileToClear : tilesToClear)
|
||||
{
|
||||
//move cleared tiles from one set to another
|
||||
clearedTiles.push_back(tileToClear);
|
||||
vstd::erase_if_present(possibleTiles, tileToClear);
|
||||
}
|
||||
for (auto tileToClear : tilesToIgnore)
|
||||
{
|
||||
//these tiles are already connected, ignore them
|
||||
vstd::erase_if_present(possibleTiles, tileToClear);
|
||||
}
|
||||
if (tilesToClear.empty()) //nothing else can be done (?)
|
||||
break;
|
||||
tilesToClear.clear(); //empty this container
|
||||
tilesToIgnore.clear();
|
||||
}
|
||||
for (auto tileToClear : tilesToIgnore)
|
||||
{
|
||||
//these tiles are already connected, ignore them
|
||||
vstd::erase_if_present(possibleTiles, tileToClear);
|
||||
}
|
||||
if (tilesToClear.empty()) //nothing else can be done (?)
|
||||
break;
|
||||
tilesToClear.clear(); //empty this container
|
||||
tilesToIgnore.clear();
|
||||
}
|
||||
|
||||
for (auto tile : clearedTiles)
|
||||
@ -484,10 +499,13 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
|
||||
|
||||
//now block most distant tiles away from passages
|
||||
|
||||
float blockDistance = minDistance * 0.6f;
|
||||
float blockDistance = minDistance * 0.25f;
|
||||
|
||||
for (auto tile : possibleTiles)
|
||||
for (auto tile : tileinfo)
|
||||
{
|
||||
if (!gen->isPossible(tile))
|
||||
continue;
|
||||
|
||||
bool closeTileFound = false;
|
||||
|
||||
for (auto clearTile : freePaths)
|
||||
@ -504,7 +522,8 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
|
||||
gen->setOccupied(tile, ETileType::BLOCKED);
|
||||
}
|
||||
|
||||
if (0) //enable to debug
|
||||
#define PRINT_FRACTALIZED_MAP false
|
||||
if (PRINT_FRACTALIZED_MAP) //enable to debug
|
||||
{
|
||||
std::ofstream out(boost::to_string(boost::format("zone %d") % id));
|
||||
int levels = gen->map->twoLevel ? 2 : 1;
|
||||
@ -516,12 +535,26 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
|
||||
{
|
||||
for (int i=0; i<width; i++)
|
||||
{
|
||||
out << (int)vstd::contains(freePaths, int3(i,j,k));
|
||||
char t = '?';
|
||||
switch (gen->getTile(int3(i, j, k)).getTileType())
|
||||
{
|
||||
case ETileType::FREE:
|
||||
t = ' '; break;
|
||||
case ETileType::BLOCKED:
|
||||
t = '#'; break;
|
||||
case ETileType::POSSIBLE:
|
||||
t = '-'; break;
|
||||
case ETileType::USED:
|
||||
t = 'O'; break;
|
||||
}
|
||||
|
||||
out << t;
|
||||
}
|
||||
out << std::endl;
|
||||
}
|
||||
out << std::endl;
|
||||
}
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
//logGlobal->infoStream() << boost::format ("Zone %d subdivided fractally") %id;
|
||||
@ -814,7 +847,9 @@ bool CRmgTemplateZone::createTreasurePile(CMapGenerator* gen, int3 &pos, float m
|
||||
}
|
||||
if (placeFound.valid())
|
||||
info.nextTreasurePos = placeFound;
|
||||
}
|
||||
else
|
||||
break; //no more place to add any objects
|
||||
}
|
||||
}
|
||||
|
||||
if (treasures.size())
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
bool isUsed() const;
|
||||
void setOccupied(ETileType::ETileType value);
|
||||
ETerrainType getTerrainType() const;
|
||||
ETileType::ETileType getTileType() const;
|
||||
void setTerrainType(ETerrainType value);
|
||||
|
||||
private:
|
||||
@ -148,6 +149,7 @@ public:
|
||||
void initFreeTiles (CMapGenerator* gen);
|
||||
std::set<int3> getTileInfo () const;
|
||||
void discardDistantTiles (CMapGenerator* gen, float distance);
|
||||
void clearTiles();
|
||||
|
||||
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
|
||||
void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0);
|
||||
|
@ -323,7 +323,7 @@ d = 0.01 * dx^3 - 0.1618 * dx^2 + 1 * dx + ...
|
||||
|
||||
void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
||||
{
|
||||
logGlobal->infoStream() << "Starting zone colouring";
|
||||
logGlobal->infoStream() << "Starting zone colouring";
|
||||
|
||||
auto width = mapGenOptions->getWidth();
|
||||
auto height = mapGenOptions->getHeight();
|
||||
@ -338,12 +338,62 @@ void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
||||
std::vector <Dpair> distances;
|
||||
distances.reserve(zones.size());
|
||||
|
||||
//now place zones correctly and assign tiles to each zone
|
||||
|
||||
auto compareByDistance = [](const Dpair & lhs, const Dpair & rhs) -> bool
|
||||
{
|
||||
return lhs.second < rhs.second;
|
||||
};
|
||||
|
||||
auto moveZoneToCenterOfMass = [](CRmgTemplateZone * zone) -> void
|
||||
{
|
||||
int3 total(0, 0, 0);
|
||||
auto tiles = zone->getTileInfo();
|
||||
for (auto tile : tiles)
|
||||
{
|
||||
total += tile;
|
||||
}
|
||||
int size = tiles.size();
|
||||
assert(size);
|
||||
zone->setPos(int3(total.x / size, total.y / size, total.z / size));
|
||||
};
|
||||
|
||||
int levels = gen->map->twoLevel ? 2 : 1;
|
||||
|
||||
/*
|
||||
1. Create Voronoi diagram
|
||||
2. find current center of mass for each zone. Move zone to that center to balance zones sizes
|
||||
*/
|
||||
|
||||
for (int i = 0; i<width; i++)
|
||||
{
|
||||
for (int j = 0; j<height; j++)
|
||||
{
|
||||
for (int k = 0; k < levels; k++)
|
||||
{
|
||||
distances.clear();
|
||||
int3 pos(i, j, k);
|
||||
for (auto zone : zones)
|
||||
{
|
||||
if (zone.second->getPos().z == k)
|
||||
distances.push_back(std::make_pair(zone.second, pos.dist2dSQ(zone.second->getPos())));
|
||||
else
|
||||
distances.push_back(std::make_pair(zone.second, std::numeric_limits<float>::max()));
|
||||
}
|
||||
boost::sort(distances, compareByDistance);
|
||||
distances.front().first->addTile(pos); //closest tile belongs to zone
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto zone : zones)
|
||||
moveZoneToCenterOfMass(zone.second);
|
||||
|
||||
//assign actual tiles to each zone using nonlinear norm for fine edges
|
||||
|
||||
for (auto zone : zones)
|
||||
zone.second->clearTiles(); //now populate them again
|
||||
|
||||
for (int i=0; i<width; i++)
|
||||
{
|
||||
for(int j=0; j<height; j++)
|
||||
@ -364,18 +414,10 @@ void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
//set position to center of mass
|
||||
//set position (town position) to center of mass of irregular zone
|
||||
for (auto zone : zones)
|
||||
{
|
||||
int3 total(0,0,0);
|
||||
auto tiles = zone.second->getTileInfo();
|
||||
for (auto tile : tiles)
|
||||
{
|
||||
total += tile;
|
||||
}
|
||||
int size = tiles.size();
|
||||
assert (size);
|
||||
zone.second->setPos (int3(total.x/size, total.y/size, total.z/size));
|
||||
moveZoneToCenterOfMass(zone.second);
|
||||
|
||||
//TODO: similiar for islands
|
||||
#define CREATE_FULL_UNDERGROUND true //consider linking this with water amount
|
||||
|
Loading…
Reference in New Issue
Block a user