1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- rewrote most of classes from adventure map window

-- new files: client/AdventureMapClasses.*
-- implemented all missing details from infobox
- textinput can handle numbers as input
- fixed several bugs caused by CIntObject changes
- fixed #988
This commit is contained in:
Ivan Savenko 2012-06-13 13:04:06 +00:00
parent fff602d4f6
commit 9d2711fb51
37 changed files with 2131 additions and 2062 deletions

View File

@ -185,11 +185,12 @@ namespace vstd
}
//returns position of first element in vector c equal to s, if there is no such element, -1 is returned
template <typename T1, typename T2>
int find_pos(const std::vector<T1> & c, const T2 &s)
template <typename Container, typename T2>
int find_pos(const Container & c, const T2 &s)
{
for(size_t i=0; i < c.size(); ++i)
if(c[i] == s)
size_t i=0;
for (auto iter = c.begin(); iter != c.end(); iter++, i++)
if(*iter == s)
return i;
return -1;
}

View File

@ -0,0 +1,935 @@
#include "StdInc.h"
#include "AdventureMapClasses.h"
#include "../CCallback.h"
#include "../lib/JsonNode.h"
#include "../lib/map.h"
#include "../lib/CObjectHandler.h"
#include "../lib/CGameState.h"
#include "../lib/CGeneralTextHandler.h"
#include "../lib/NetPacks.h"
#include "CAdvmapInterface.h"
#include "CAnimation.h"
#include "CGameInfo.h"
#include "CPlayerInterface.h"
#include "CMusicHandler.h"
#include "Graphics.h"
#include "GUIClasses.h"
#include "UIFramework/CGuiHandler.h"
#include "UIFramework/SDL_Pixels.h"
/*
* CAdventureMapClasses.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
CList::CListItem::CListItem(CList * Parent):
CIntObject(LCLICK | RCLICK | HOVER),
parent(Parent),
selection(nullptr)
{
}
CList::CListItem::~CListItem()
{
// select() method in this was already destroyed so we can't safely call method in parent
if (parent->selected == this)
parent->selected = nullptr;
}
void CList::CListItem::clickRight(tribool down, bool previousState)
{
if (down == true)
showTooltip();
}
void CList::CListItem::clickLeft(tribool down, bool previousState)
{
if (down == true)
{
//second click on already selected item
if (parent->selected == this)
open();
else
{
//first click - switch selection
parent->select(this);
}
}
}
void CList::CListItem::hover(bool on)
{
if (on)
GH.statusbar->print(getHoverText());
else
GH.statusbar->clear();
}
void CList::CListItem::onSelect(bool on)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
vstd::clear_pointer(selection);
if (on)
selection = genSelection();
select(on);
GH.totalRedraw();
}
CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, size_t listAmount,
int helpUp, int helpDown, CListBox::CreateFunc create, CListBox::DestroyFunc destroy):
CIntObject(0, position),
size(Size),
selected(nullptr)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
scrollUp = new CAdventureMapButton(CGI->generaltexth->zelp[helpUp], 0, 0, 0, btnUp);
list = new CListBox(create, destroy, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount);
//assign callback only after list was created
scrollUp->callback = boost::bind(&CListBox::moveToPrev, list);
scrollDown = new CAdventureMapButton(CGI->generaltexth->zelp[helpDown], boost::bind(&CListBox::moveToNext, list), 0, scrollUp->pos.h + 32*size, btnDown);
scrollDown->callback += boost::bind(&CList::update, this);
scrollUp->callback += boost::bind(&CList::update, this);
update();
}
void CList::update()
{
bool onTop = list->getPos() == 0;
bool onBottom = list->getPos() + size >= list->size();
scrollUp->block(onTop);
scrollDown->block(onBottom);
}
void CList::select(CListItem *which)
{
if (selected == which)
return;
if (selected)
selected->onSelect(false);
selected = which;
if (which)
{
which->onSelect(true);
onSelect();
}
}
int CList::getSelectedIndex()
{
return list->getIndexOf(selected);
}
void CList::selectIndex(int which)
{
if (which < 0)
{
if (selected)
select(nullptr);
}
else
{
list->scrollTo(which);
update();
select(dynamic_cast<CListItem*>(list->getItem(which)));
}
}
void CList::selectNext()
{
int index = getSelectedIndex();
if (index < 0)
selectIndex(0);
else if (index + 1 < list->size())
selectIndex(index+1);
}
void CList::selectPrev()
{
int index = getSelectedIndex();
if (index <= 0)
selectIndex(0);
else
selectIndex(index-1);
}
CHeroList::CEmptyHeroItem::CEmptyHeroItem()
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
auto move = new CAnimImage("IMOBIL", 0, 0, 0, 1);
auto img = new CPicture("HPSXXX", move->pos.w + 1);
auto mana = new CAnimImage("IMANA", 0, 0, move->pos.w + img->pos.w + 2, 1 );
pos.w = mana->pos.w + mana->pos.x - pos.x;
pos.h = std::max(std::max<ui16>(move->pos.h + 1, mana->pos.h + 1), img->pos.h);
}
CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero):
CListItem(parent),
hero(Hero)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
movement = new CAnimImage("IMOBIL", 0, 0, 0, 1);
portrait = new CAnimImage("PortraitsSmall", hero->portrait, 0, movement->pos.w + 1);
mana = new CAnimImage("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
pos.w = mana->pos.w + mana->pos.x - pos.x;
pos.h = std::max(std::max<ui16>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
update();
}
void CHeroList::CHeroItem::update()
{
movement->setFrame(std::min<size_t>(movement->size(), hero->movement / 100));
mana->setFrame(std::min<size_t>(mana->size(), hero->mana / 5));
redraw();
}
CIntObject * CHeroList::CHeroItem::genSelection()
{
return new CPicture("HPSYYY", movement->pos.w + 1);
}
void CHeroList::CHeroItem::select(bool on)
{
if (on && adventureInt->selection != hero)
adventureInt->select(hero);
}
void CHeroList::CHeroItem::open()
{
LOCPLINT->openHeroWindow(hero);
}
void CHeroList::CHeroItem::showTooltip()
{
CRClickPopup::createAndPush(hero, GH.current->motion);
}
std::string CHeroList::CHeroItem::getHoverText()
{
return boost::str(boost::format(CGI->generaltexth->allTexts[15]) % hero->name % hero->type->heroClass->name);
}
CIntObject * CHeroList::createHeroItem(size_t index)
{
if (LOCPLINT->wanderingHeroes.size() > index)
return new CHeroItem(this, LOCPLINT->wanderingHeroes[index]);
return new CEmptyHeroItem();
}
CHeroList::CHeroList(int size, Point position, std::string btnUp, std::string btnDown):
CList(size, position, btnUp, btnDown, LOCPLINT->wanderingHeroes.size(), 303, 304, boost::bind(&CHeroList::createHeroItem, this, _1))
{
}
void CHeroList::select(const CGHeroInstance * hero)
{
selectIndex(vstd::find_pos(LOCPLINT->wanderingHeroes, hero));
}
void CHeroList::update(const CGHeroInstance * hero)
{
if (vstd::contains(LOCPLINT->wanderingHeroes, hero))
{
//this hero is already present, update its status
for (auto iter = list->getItems().begin(); iter != list->getItems().end(); iter++)
{
auto item = dynamic_cast<CHeroItem*>(*iter);
if (item && item->hero == hero)
{
item->update();
return;
}
}
return;
}
//simplest solution for now: reset list and restore selection
list->resize(LOCPLINT->wanderingHeroes.size());
if (adventureInt->selection)
{
auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
if (hero)
select(hero);
}
CList::update();
}
CIntObject * CTownList::createTownItem(size_t index)
{
if (LOCPLINT->towns.size() > index)
return new CTownItem(this, LOCPLINT->towns[index]);
return new CAnimImage("ITPA", 0);
}
CTownList::CTownItem::CTownItem(CTownList *parent, const CGTownInstance *Town):
CListItem(parent),
town(Town)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
picture = new CAnimImage("ITPA", 0);
pos = picture->pos;
update();
}
CIntObject * CTownList::CTownItem::genSelection()
{
return new CAnimImage("ITPA", 1);
}
void CTownList::CTownItem::update()
{
size_t iconIndex = town->subID*2;
if (!town->hasFort())
iconIndex += GameConstants::F_NUMBER*2;
if(town->builded >= GameConstants::MAX_BUILDING_PER_TURN)
iconIndex++;
picture->setFrame(iconIndex + 2);
redraw();
}
void CTownList::CTownItem::select(bool on)
{
if (on && adventureInt->selection != town)
adventureInt->select(town);
}
void CTownList::CTownItem::open()
{
LOCPLINT->openTownWindow(town);
}
void CTownList::CTownItem::showTooltip()
{
CRClickPopup::createAndPush(town, GH.current->motion);
}
std::string CTownList::CTownItem::getHoverText()
{
return town->hoverName;
}
CTownList::CTownList(int size, Point position, std::string btnUp, std::string btnDown):
CList(size, position, btnUp, btnDown, LOCPLINT->towns.size(), 306, 307, boost::bind(&CTownList::createTownItem, this, _1))
{
}
void CTownList::select(const CGTownInstance * town)
{
selectIndex(vstd::find_pos(LOCPLINT->towns, town));
}
void CTownList::update(const CGTownInstance *)
{
//simplest solution for now: reset list and restore selection
list->resize(LOCPLINT->towns.size());
if (adventureInt->selection)
{
auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection);
if (town)
select(town);
}
CList::update();
}
const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos)
{
static const SDL_Color fogOfWar = {0, 0, 0, 255};
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
// if tile is not visible it will be black on minimap
if(!tile)
return fogOfWar;
// if object at tile is owned - it will be colored as its owner
BOOST_FOREACH(const CGObjectInstance *obj, tile->blockingObjects)
{
//heroes will be blitted later
if (obj->ID == GameConstants::HEROI_TYPE)
continue;
int player = obj->getOwner();
if(player == GameConstants::NEUTRAL_PLAYER)
return *graphics->neutralColor;
else
if (player < GameConstants::PLAYER_LIMIT)
return graphics->playerColors[player];
}
// else - use terrain color (blocked version or normal)
if (tile->blocked && (!tile->visitable))
return parent->colors.find(tile->tertype)->second.second;
else
return parent->colors.find(tile->tertype)->second.first;
}
void CMinimapInstance::blitTileWithColor(const SDL_Color &color, const int3 &tile, SDL_Surface *to, int toX, int toY)
{
//method is mostly copy-pasted from drawScaled()
int3 mapSizes = LOCPLINT->cb->getMapSize();
double stepX = double(pos.w) / mapSizes.x;
double stepY = double(pos.h) / mapSizes.y;
//coordinates of rectangle on minimap representing this tile
// begin - first to blit, end - first NOT to blit
int xBegin = toX + stepX * tile.x;
int yBegin = toY + stepY * tile.y;
int xEnd = toX + stepX * (tile.x + 1);
int yEnd = toY + stepY * (tile.y + 1);
for (int y=yBegin; y<yEnd; y++)
{
Uint8 *ptr = (Uint8*)to->pixels + y * to->pitch + xBegin * minimap->format->BytesPerPixel;
for (int x=xBegin; x<xEnd; x++)
ColorPutter<4, 1>::PutColor(ptr, color);
}
}
void CMinimapInstance::refreshTile(const int3 &tile)
{
blitTileWithColor(getTileColor(int3(tile.x, tile.y, level)), tile, minimap, 0, 0);
}
void CMinimapInstance::drawScaled(int level)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
//size of one map tile on our minimap
double stepX = double(pos.w) / mapSizes.x;
double stepY = double(pos.h) / mapSizes.y;
double currY = 0;
for (int y=0; y<mapSizes.y; y++, currY += stepY)
{
double currX = 0;
for (int x=0; x<mapSizes.x; x++, currX += stepX)
{
const SDL_Color &color = getTileColor(int3(x,y,level));
//coordinates of rectangle on minimap representing this tile
// begin - first to blit, end - first NOT to blit
int xBegin = currX;
int yBegin = currY;
int xEnd = currX + stepX;
int yEnd = currY + stepY;
for (int y=yBegin; y<yEnd; y++)
{
Uint8 *ptr = (Uint8*)minimap->pixels + y * minimap->pitch + xBegin * minimap->format->BytesPerPixel;
for (int x=xBegin; x<xEnd; x++)
ColorPutter<4, 1>::PutColor(ptr, color);
}
}
}
}
CMinimapInstance::CMinimapInstance(CMinimap *Parent, int Level):
parent(Parent),
minimap(CSDL_Ext::createSurfaceWithBpp<4>(parent->pos.w, parent->pos.h)),
level(Level)
{
pos.w = parent->pos.w;
pos.h = parent->pos.h;
drawScaled(level);
}
CMinimapInstance::~CMinimapInstance()
{
SDL_FreeSurface(minimap);
}
void CMinimapInstance::showAll(SDL_Surface *to)
{
blitAtLoc(minimap, 0, 0, to);
//draw heroes
std::vector <const CGHeroInstance *> heroes = LOCPLINT->cb->getHeroesInfo(false);
BOOST_FOREACH(auto & hero, heroes)
{
int3 position = hero->getPosition(false);
if (position.z == level)
{
const SDL_Color & color = graphics->playerColors[hero->getOwner()];
blitTileWithColor(color, position, to, pos.x, pos.y);
}
}
}
std::map<int, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors(std::string from)
{
std::map<int, std::pair<SDL_Color, SDL_Color> > ret;
const JsonNode config(GameConstants::DATA_DIR + from);
BOOST_FOREACH(const JsonNode &m, config["MinimapColors"].Vector())
{
int id = m["terrain_id"].Float();
const JsonVector &unblockedVec = m["unblocked"].Vector();
SDL_Color normal =
{
ui8(unblockedVec[0].Float()),
ui8(unblockedVec[1].Float()),
ui8(unblockedVec[2].Float()),
ui8(255)
};
const JsonVector &blockedVec = m["blocked"].Vector();
SDL_Color blocked =
{
ui8(blockedVec[0].Float()),
ui8(blockedVec[1].Float()),
ui8(blockedVec[2].Float()),
ui8(255)
};
ret.insert(std::make_pair(id, std::make_pair(normal, blocked)));
}
return ret;
}
CMinimap::CMinimap(const Rect &position):
CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
aiShield(nullptr),
minimap(nullptr),
level(0),
colors(loadColors("/config/minimap.json"))
{
pos.w = position.w;
pos.h = position.h;
}
void CMinimap::moveAdvMapSelection()
{
// 0 = top-left corner, 1 = bottom-right corner
double dx = double(GH.current->motion.x - pos.x) / pos.w;
double dy = double(GH.current->motion.y - pos.y) / pos.h;
int3 mapSizes = LOCPLINT->cb->getMapSize();
int3 newLocation =
{
si32(mapSizes.x * dx),
si32(mapSizes.y * dy),
si32(level)
};
adventureInt->centerOn(newLocation);
redraw();
}
void CMinimap::clickLeft(tribool down, bool previousState)
{
if (down)
moveAdvMapSelection();
}
void CMinimap::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(CGI->generaltexth->zelp[291].second, down);
}
void CMinimap::hover(bool on)
{
if (on)
GH.statusbar->print(CGI->generaltexth->zelp[291].first);
else
GH.statusbar->clear();
}
void CMinimap::mouseMoved(const SDL_MouseMotionEvent & sEvent)
{
if (pressedL)
moveAdvMapSelection();
}
void CMinimap::showAll(SDL_Surface * to)
{
CIntObject::showAll(to);
if (minimap)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
//draw radar
SDL_Rect oldClip;
SDL_Rect radar =
{
si16(adventureInt->position.x * pos.w / mapSizes.x + pos.x),
si16(adventureInt->position.y * pos.h / mapSizes.y + pos.y),
ui16(adventureInt->terrain.tilesw * pos.w / mapSizes.x),
ui16(adventureInt->terrain.tilesh * pos.h / mapSizes.y)
};
SDL_GetClipRect(to, &oldClip);
SDL_SetClipRect(to, &pos);
CSDL_Ext::drawDashedBorder(to, radar, int3(255,75,125));
SDL_SetClipRect(to, &oldClip);
}
}
void CMinimap::update()
{
if (aiShield) //AI turn is going on. There is no need to update minimap
return;
OBJ_CONSTRUCTION_CAPTURING_ALL;
vstd::clear_pointer(minimap);
minimap = new CMinimapInstance(this, level);
}
void CMinimap::setLevel(int newLevel)
{
level = newLevel;
update();
}
void CMinimap::setAIRadar(bool on)
{
if (on)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
vstd::clear_pointer(minimap);
if (!aiShield)
aiShield = new CPicture("AIShield");
}
else
{
vstd::clear_pointer(aiShield);
update();
}
}
void CMinimap::hideTile(const int3 &pos)
{
if (minimap)
minimap->refreshTile(pos);
}
void CMinimap::showTile(const int3 &pos)
{
if (minimap)
minimap->refreshTile(pos);
}
CInfoBar::CVisibleInfo::CVisibleInfo(Point position):
CIntObject(0, position),
aiProgress(nullptr)
{
}
void CInfoBar::CVisibleInfo::show(SDL_Surface *to)
{
CIntObject::show(to);
BOOST_FOREACH(auto object, forceRefresh)
object->showAll(to);
}
void CInfoBar::CVisibleInfo::loadHero(const CGHeroInstance * hero)
{
assert(children.empty()); // visible info should be re-created to change type
OBJ_CONSTRUCTION_CAPTURING_ALL;
new CPicture("ADSTATHR");
new CHeroTooltip(Point(0,0), hero);
}
void CInfoBar::CVisibleInfo::loadTown(const CGTownInstance *town)
{
assert(children.empty()); // visible info should be re-created to change type
OBJ_CONSTRUCTION_CAPTURING_ALL;
new CPicture("ADSTATCS");
new CTownTooltip(Point(0,0), town);
}
void CInfoBar::CVisibleInfo::playNewDaySound()
{
if (LOCPLINT->cb->getDate(1) != 1) // not first day of the week
CCS->soundh->playSound(soundBase::newDay);
else
if (LOCPLINT->cb->getDate(2) != 1) // not first week in month
CCS->soundh->playSound(soundBase::newWeek);
else
if (LOCPLINT->cb->getDate(3) != 1) // not first month
CCS->soundh->playSound(soundBase::newMonth);
else
CCS->soundh->playSound(soundBase::newDay);
}
std::string CInfoBar::CVisibleInfo::getNewDayName()
{
if (LOCPLINT->cb->getDate(0) == 1)
return "NEWDAY";
if (LOCPLINT->cb->getDate(1) != 1)
return "NEWDAY";
switch(LOCPLINT->cb->getDate(2))
{
case 1: return "NEWWEEK1";
case 2: return "NEWWEEK2";
case 3: return "NEWWEEK3";
case 4: return "NEWWEEK4";
default: assert(0); return "";
}
}
void CInfoBar::CVisibleInfo::loadDay()
{
assert(children.empty()); // visible info should be re-created first to change type
playNewDaySound();
OBJ_CONSTRUCTION_CAPTURING_ALL;
new CShowableAnim(1, 0, getNewDayName(), CShowableAnim::PLAY_ONCE);
std::string labelText;
if (LOCPLINT->cb->getDate(1) == 1 && LOCPLINT->cb->getDate(0) != 1) // monday of any week but first - show new week info
labelText = CGI->generaltexth->allTexts[63] + " " + boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(2));
else
labelText = CGI->generaltexth->allTexts[64] + " " + boost::lexical_cast<std::string>(LOCPLINT->cb->getDate(1));
forceRefresh.push_back(new CLabel(95, 31, FONT_MEDIUM, CENTER, Colors::Cornsilk, labelText));
}
void CInfoBar::CVisibleInfo::loadEnemyTurn(int player)
{
assert(children.empty()); // visible info should be re-created to change type
OBJ_CONSTRUCTION_CAPTURING_ALL;
new CPicture("ADSTATNX");
new CAnimImage("CREST58", player, 0, 20, 51);
new CShowableAnim(99, 51, "HOURSAND");
// FIXME: currently there is no way to get progress from VCAI
// if this will change at some point switch this ifdef to enable correct code
#if 0
//prepare hourglass for updating AI turn
aiProgress = new CAnimImage("HOURGLAS", 0, 0, 99, 51);
forceRefresh.push_back(aiProgress);
#else
//create hourglass that will be always animated ignoring AI status
new CShowableAnim(99, 51, "HOURGLAS", CShowableAnim::PLAY_ONCE, 40);
#endif
}
void CInfoBar::CVisibleInfo::loadGameStatus()
{
assert(children.empty()); // visible info should be re-created to change type
//get amount of halls of each level
std::vector<int> halls(4, 0);
BOOST_FOREACH(auto town, LOCPLINT->towns)
halls[town->hallLevel()]++;
std::vector<int> allies, enemies;
//generate list of allies and enemies
for(int i = 0; i < GameConstants::PLAYER_LIMIT; i++)
{
if(LOCPLINT->cb->getPlayerStatus(i) == PlayerState::INGAME)
{
if (LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, i) > 0)
allies.push_back(i);
else
enemies.push_back(i);
}
}
//generate component
OBJ_CONSTRUCTION_CAPTURING_ALL;
new CPicture("ADSTATIN");
auto allyLabel = new CLabel(10, 106, FONT_SMALL, TOPLEFT, Colors::Cornsilk, CGI->generaltexth->allTexts[390] + ":");
auto enemyLabel = new CLabel(10, 136, FONT_SMALL, TOPLEFT, Colors::Cornsilk, CGI->generaltexth->allTexts[391] + ":");
int posx = allyLabel->pos.w + allyLabel->pos.x - pos.x + 4;
BOOST_FOREACH(int & player, allies)
{
auto image = new CAnimImage("ITGFLAGS", player, 0, posx, 102);
posx += image->pos.w;
}
posx = enemyLabel->pos.w + enemyLabel->pos.x - pos.x + 4;
BOOST_FOREACH(int & player, enemies)
{
auto image = new CAnimImage("ITGFLAGS", player, 0, posx, 132);
posx += image->pos.w;
}
for (size_t i=0; i<halls.size(); i++)
{
new CAnimImage("itmtl", i, 0, 6 + 42 * i , 11);
if (halls[i])
new CLabel( 26 + 42 * i, 64, FONT_SMALL, CENTER, Colors::Cornsilk, boost::lexical_cast<std::string>(halls[i]));
}
}
void CInfoBar::CVisibleInfo::loadComponent(const Component compToDisplay, std::string message)
{
assert(children.empty()); // visible info should be re-created to change type
OBJ_CONSTRUCTION_CAPTURING_ALL;
new CPicture("ADSTATOT");
auto comp = new CComponent(compToDisplay);
comp->moveTo(Point(pos.x+52, pos.y+54));
new CTextBox(message, Rect(8, 8, 164, 50), 0, FONT_SMALL, CENTER, Colors::Cornsilk);
new CLabel(91, 158, FONT_SMALL, CENTER, Colors::Cornsilk, comp->subtitle);
}
void CInfoBar::CVisibleInfo::updateEnemyTurn(double progress)
{
if (aiProgress)
aiProgress->setFrame((aiProgress->size() - 1) * progress);
}
void CInfoBar::reset(EState newState = EMPTY)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
vstd::clear_pointer(visibleInfo);
currentObject = nullptr;
state = newState;
visibleInfo = new CVisibleInfo(Point(8, 12));
}
void CInfoBar::showSelection()
{
if (adventureInt->selection)
{
auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
if (hero)
{
showHeroSelection(hero, false);
return;
}
auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection);
if (town)
{
showTownSelection(town, false);
return;
}
}
showGameStatus();//FIXME: may be incorrect but shouldn't happen in general
}
void CInfoBar::tick()
{
removeUsedEvents(TIME);
showSelection();
}
void CInfoBar::clickLeft(tribool down, bool previousState)
{
if (down)
{
if (state == HERO || state == TOWN)
showGameStatus();
else if (state == GAME)
showDate();
else
showSelection();
}
}
void CInfoBar::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(CGI->generaltexth->allTexts[109], down);
}
void CInfoBar::hover(bool on)
{
if (on)
GH.statusbar->print(CGI->generaltexth->zelp[292].first);
else
GH.statusbar->clear();
}
CInfoBar::CInfoBar(const Rect &position):
CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()),
visibleInfo(nullptr),
state(EMPTY),
currentObject(nullptr)
{
pos.w = position.w;
pos.h = position.h;
//FIXME: enable some mode? Should be done by advMap::select() when game starts but just in case?
}
void CInfoBar::showDate()
{
reset(DATE);
visibleInfo->loadDay();
setTimer(3000);
redraw();
}
void CInfoBar::showComponent(const Component comp, std::string message)
{
reset(COMPONENT);
visibleInfo->loadComponent(comp, message);
setTimer(3000);
redraw();
}
void CInfoBar::startEnemyTurn(ui8 color)
{
reset(AITURN);
visibleInfo->loadEnemyTurn(color);
redraw();
}
void CInfoBar::updateEnemyTurn(double progress)
{
assert(state == AITURN);
visibleInfo->updateEnemyTurn(progress);
redraw();
}
void CInfoBar::showHeroSelection(const CGHeroInstance * hero, bool onlyUpdate)
{
reset(HERO);
currentObject = hero;
visibleInfo->loadHero(hero);
redraw();
}
void CInfoBar::showTownSelection(const CGTownInstance * town, bool onlyUpdate)
{
reset(TOWN);
currentObject = town;
visibleInfo->loadTown(town);
redraw();
}
void CInfoBar::showGameStatus()
{
reset(GAME);
visibleInfo->loadGameStatus();
setTimer(3000);
redraw();
}

View File

@ -0,0 +1,311 @@
#pragma once
#include "UIFramework/CIntObject.h"
#include "UIFramework/CIntObjectClasses.h"
class CArmedInstance;
class CShowableAnim;
class CGGarrison;
class CGObjectInstance;
class CGHeroInstance;
class CGTownInstance;
struct Component;
struct InfoAboutArmy;
struct InfoAboutHero;
struct InfoAboutTown;
/*
* CAdventureMapClasses.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
/// Base UI Element for hero\town lists
class CList : public CIntObject
{
protected:
class CListItem : public CIntObject
{
CList * parent;
CIntObject * selection;
public:
CListItem(CList * parent);
~CListItem();
void clickRight(tribool down, bool previousState);
void clickLeft(tribool down, bool previousState);
void hover(bool on);
void onSelect(bool on);
/// create object with selection rectangle
virtual CIntObject * genSelection()=0;
/// reaction on item selection (e.g. enable selection border)
/// NOTE: item may be deleted in selected state
virtual void select(bool on)=0;
/// open item (town or hero screen)
virtual void open()=0;
/// show right-click tooltip
virtual void showTooltip()=0;
/// get hover text for status bar
virtual std::string getHoverText()=0;
};
CListBox * list;
const size_t size;
/**
* @brief CList - protected constructor
* @param Size - maximal amount of visible at once items
* @param position - cordinates
* @param btnUp - path to image to use as top button
* @param btnDown - path to image to use as bottom button
* @param listAmount - amount of items in the list
* @param helpUp - index in zelp.txt for button help tooltip
* @param helpDown - index in zelp.txt for button help tooltip
* @param create - function for creating items in listbox
* @param destroy - function for deleting items in listbox
*/
CList(int size, Point position, std::string btnUp, std::string btnDown, size_t listAmount, int helpUp, int helpDown,
CListBox::CreateFunc create, CListBox::DestroyFunc destroy = CListBox::DestroyFunc());
//for selection\deselection
CListItem *selected;
void select(CListItem * which);
friend class CListItem;
/// should be called when list is invalidated
void update();
public:
CAdventureMapButton * scrollUp;
CAdventureMapButton * scrollDown;
/// functions that will be called when selection changes
CFunctionList<void()> onSelect;
/// return index of currently selected element
int getSelectedIndex();
/// set of methods to switch selection
void selectIndex(int which);
void selectNext();
void selectPrev();
};
/// List of heroes which is shown at the right of the adventure map screen
class CHeroList : public CList
{
/// Empty hero item used as placeholder for unused entries in list
class CEmptyHeroItem : public CIntObject
{
public:
CEmptyHeroItem();
};
class CHeroItem : public CListItem
{
CAnimImage * movement;
CAnimImage * mana;
CAnimImage * portrait;
public:
const CGHeroInstance * const hero;
CHeroItem(CHeroList *parent, const CGHeroInstance * hero);
CIntObject * genSelection();
void update();
void select(bool on);
void open();
void showTooltip();
std::string getHoverText();
};
CIntObject * createHeroItem(size_t index);
public:
/**
* @brief CHeroList
* @param Size, position, btnUp, btnDown @see CList::CList
*/
CHeroList(int size, Point position, std::string btnUp, std::string btnDown);
/// Select specific hero and scroll if needed
void select(const CGHeroInstance * hero = nullptr);
/// Update hero. Will add or remove it from the list if needed
void update(const CGHeroInstance * hero = nullptr);
};
/// List of towns which is shown at the right of the adventure map screen or in the town screen
class CTownList : public CList
{
class CTownItem : public CListItem
{
CAnimImage * picture;
public:
const CGTownInstance * const town;
CTownItem(CTownList *parent, const CGTownInstance * town);
CIntObject * genSelection();
void update();
void select(bool on);
void open();
void showTooltip();
std::string getHoverText();
};
CIntObject * createTownItem(size_t index);
public:
/**
* @brief CTownList
* @param Size, position, btnUp, btnDown @see CList::CList
*/
CTownList(int size, Point position, std::string btnUp, std::string btnDown);
/// Select specific town and scroll if needed
void select(const CGTownInstance * town = nullptr);
/// Update town. Will add or remove it from the list if needed
void update(const CGTownInstance * town = nullptr);
};
class CMinimap;
class CMinimapInstance : public CIntObject
{
CMinimap *parent;
SDL_Surface * minimap;
int level;
//get color of selected tile on minimap
const SDL_Color & getTileColor(const int3 & pos);
void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface *to, int x, int y);
//draw minimap already scaled.
//result is not antialiased. Will result in "missing" pixels on huge maps (>144)
void drawScaled(int level);
public:
CMinimapInstance(CMinimap * parent, int level);
~CMinimapInstance();
void showAll(SDL_Surface *to);
void refreshTile(const int3 &pos);
};
/// Minimap which is displayed at the right upper corner of adventure map
class CMinimap : public CIntObject
{
CPicture *aiShield; //the graphic displayed during AI turn
CMinimapInstance * minimap;
int level;
//to initialize colors
std::map<int, std::pair<SDL_Color, SDL_Color> > loadColors(std::string from);
void moveAdvMapSelection();
void clickLeft(tribool down, bool previousState);
void clickRight(tribool down, bool previousState);
void hover (bool on);
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
public:
// terrainID -> (normal color, blocked color)
const std::map<int, std::pair<SDL_Color, SDL_Color> > colors;
CMinimap(const Rect & position);
//should be called to invalidate whole map - different player or level
void update();
void setLevel(int level);
void setAIRadar(bool on);
void showAll(SDL_Surface * to);
void hideTile(const int3 &pos); //puts FoW
void showTile(const int3 &pos); //removes FoW
};
/// Info box which shows next week/day information, hold the current date
class CInfoBar : public CIntObject
{
//all visible information located in one object - for ease of replacing
class CVisibleInfo : public CIntObject
{
//list of objects that must be redrawed on each frame on a top of animation
std::list<CIntObject *> forceRefresh;
//the only part of gui we need to know about for updating - AI progress
CAnimImage *aiProgress;
std::string getNewDayName();
void playNewDaySound();
public:
CVisibleInfo(Point position);
void show(SDL_Surface *to);
//functions that must be called only once
void loadHero(const CGHeroInstance * hero);
void loadTown(const CGTownInstance * town);
void loadDay();
void loadEnemyTurn(int player);
void loadGameStatus();
void loadComponent(const Component comp, std::string message);
//can be called multiple times
void updateEnemyTurn(double progress);
};
enum EState
{
EMPTY, HERO, TOWN, DATE, GAME, AITURN, COMPONENT
};
CVisibleInfo * visibleInfo;
EState state;
//currently displayed object. May be null if state is not hero or town
const CGObjectInstance * currentObject;
//removes all information about current state, deactivates timer (if any)
void reset(EState newState);
//reset to default view - selected object
void showSelection();
void tick();
void clickLeft(tribool down, bool previousState);
void clickRight(tribool down, bool previousState);
void hover(bool on);
public:
CInfoBar(const Rect & pos);
/// show new day/week animation
void showDate();
/// show component for 3 seconds. Used to display picked up resources
void showComponent(const Component comp, std::string message);
/// print enemy turn progress
void startEnemyTurn(ui8 color);
/// updates enemy turn.
/// NOTE: currently DISABLED. Check comments in CInfoBar::CVisibleInfo::loadEnemyTurn()
void updateEnemyTurn(double progress);
/// show hero\town information
/// if onlyUpdate set to true this call won't switch to town\hero but only update current view
void showHeroSelection(const CGHeroInstance * hero, bool onlyUpdate);
void showTownSelection(const CGTownInstance * town, bool onlyUpdate);
/// for 3 seconds shows amount of town halls and players status
void showGameStatus();
};

View File

@ -428,12 +428,10 @@ if( !isEarliest(false) )
}
//unit reversed
if(owner->moveSh >= 0)
if (owner->moveSh == -1)
{
CCS->soundh->stopSound(owner->moveSh);
owner->moveSh = -1;
owner->moveSh = CCS->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
}
owner->moveSh = CCS->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
//step shift calculation
posX = myAnim()->pos.x, posY = myAnim()->pos.y; // for precise calculations ;]
@ -540,7 +538,6 @@ void CMovementAnimation::endAnim()
CCS->soundh->stopSound(owner->moveSh);
owner->moveSh = -1;
}
delete this;
}

View File

@ -53,414 +53,6 @@ using namespace CSDL_Ext;
CAdvMapInt *adventureInt;
CMinimap::CMinimap()
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
addUsedEvents(LCLICK | RCLICK | HOVER);
int3 mapSizes = LOCPLINT->cb->getMapSize();
statusbarTxt = CGI->generaltexth->zelp[291].first;
rcText = CGI->generaltexth->zelp[291].second;
pos.x=ADVOPT.minimapX;
pos.y=ADVOPT.minimapY;
pos.h=ADVOPT.minimapW;
pos.w=ADVOPT.minimapH;
temps = CSDL_Ext::createSurfaceWithBpp<4>(pos.w,pos.h);
aiShield = new CPicture("AISHIELD.bmp");
const JsonNode config(GameConstants::DATA_DIR + "/config/minimap.json");
const JsonVector &minimap_vec = config["MinimapColors"].Vector();
BOOST_FOREACH(const JsonNode &m, minimap_vec) {
std::pair<int,SDL_Color> vinya;
vinya.first = m["terrain_id"].Float();
const JsonVector &unblocked_vec = m["unblocked"].Vector();
vinya.second.r = unblocked_vec[0].Float();
vinya.second.g = unblocked_vec[1].Float();
vinya.second.b = unblocked_vec[2].Float();
vinya.second.unused = 255;
colors.insert(vinya);
const JsonVector &blocked_vec = m["blocked"].Vector();
vinya.second.r = blocked_vec[0].Float();
vinya.second.g = blocked_vec[1].Float();
vinya.second.b = blocked_vec[2].Float();
vinya.second.unused = 255;
colorsBlocked.insert(vinya);
}
}
CMinimap::~CMinimap()
{
SDL_FreeSurface(temps);
for (std::map<int, CMinimapSurfacesRef>::iterator it = surfs.begin(); it != surfs.end(); ++it)
{
it->second.free();
}
}
void CMinimap::draw(SDL_Surface * to)
{
int player = adventureInt->player;
if(LOCPLINT->makingTurn)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
//draw terrain
blitAt(surfs[player].map()[adventureInt->position.z],0,0,temps);
//draw heroes
std::vector <const CGHeroInstance *> hh = LOCPLINT->cb->getHeroesInfo(false);
int mw = surfs[player].map()[0]->w, mh = surfs[player].map()[0]->h,
wo = mw/mapSizes.x, ho = mh/mapSizes.y;
for (size_t i=0; i < hh.size(); ++i)
{
int3 hpos = hh[i]->getPosition(false);
if(hpos.z!=adventureInt->position.z)
continue;
int3 maplgp ( (hpos.x*mw)/mapSizes.x, (hpos.y*mh)/mapSizes.y, hpos.z );
for (int ii=0; ii<wo; ii++)
{
for (int jj=0; jj<ho; jj++)
{
SDL_PutPixelWithoutRefresh(temps,maplgp.x+ii,maplgp.y+jj,graphics->playerColors[hh[i]->getOwner()].r,
graphics->playerColors[hh[i]->getOwner()].g,graphics->playerColors[hh[i]->getOwner()].b);
}
}
}
blitAt(surfs[player].flObjs()[adventureInt->position.z],0,0,temps);
blitAt(surfs[player].FoW()[adventureInt->position.z],0,0,temps);
//draw radar
const int tilesw=(ADVOPT.advmapW+31)/32;
const int tilesh=(ADVOPT.advmapH+31)/32;
int bx = static_cast<int>((adventureInt->position.x / static_cast<double>(mapSizes.x)) * pos.w),
by = static_cast<int>((adventureInt->position.y / static_cast<double>(mapSizes.y)) * pos.h),
rx = static_cast<int>((tilesw / static_cast<double>(mapSizes.x)) * pos.w), //width
ry = static_cast<int>((tilesh / static_cast<double>(mapSizes.y)) * pos.h); //height
CSDL_Ext::drawDashedBorder(temps, Rect(bx, by, rx, ry), int3(255,75,125));
//blitAt(radar,bx,by,temps);
blitAt(temps,pos.x,pos.y,to);
}
else
{
aiShield->showAll(to);
}
}
CMinimapSurfacesRef::CMinimapSurfacesRef() : ready(false)
{
}
void CMinimapSurfacesRef::redraw(int level)
{
ready = true;
initMap(level);
//FoW
initFoW(level);
//flaggable objects
initFlaggableObjs(level);
//showing tiles
showVisibleTiles();
}
void CMinimapSurfacesRef::initMap(int level)
{
const Rect &minimap_pos = adventureInt->minimap.pos;
std::map<int,SDL_Color> &colors = adventureInt->minimap.colors;
std::map<int,SDL_Color> &colorsBlocked = adventureInt->minimap.colorsBlocked;
int3 mapSizes = LOCPLINT->cb->getMapSize();
for (size_t i=0; i<CGI->mh->sizes.z; i++)
{
SDL_Surface *pom;
if ((level>=0) && (i!=level))
continue;
if (map_.size()<i+1)
pom = CSDL_Ext::newSurface(minimap_pos.w,minimap_pos.h,screen);
else pom = map_[i];
for (int x=0;x<minimap_pos.w;x++)
{
for (int y=0;y<minimap_pos.h;y++)
{
int mx=(mapSizes.x*x)/minimap_pos.w;
int my=(mapSizes.y*y)/minimap_pos.h;
const TerrainTile * tile = LOCPLINT->cb->getTile(int3(mx, my, i), false);
if(tile)
{
if (tile->blocked && (!tile->visitable))
SDL_PutPixelWithoutRefresh(pom, x, y, colorsBlocked[tile->tertype].r, colorsBlocked[tile->tertype].g, colorsBlocked[tile->tertype].b);
else
SDL_PutPixelWithoutRefresh(pom, x, y, colors[tile->tertype].r, colors[tile->tertype].g, colors[tile->tertype].b);
}
}
}
map_.push_back(pom);
}
}
void CMinimapSurfacesRef::initFoW(int level)
{
const Rect &minimap_pos = adventureInt->minimap.pos;
int3 mapSizes = LOCPLINT->cb->getMapSize();
int mw = map_[0]->w, mh = map_[0]->h;//,
//wo = mw/mapSizes.x, ho = mh/mapSizes.y; //TODO use me
for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
{
if(level>=0 && d!=level)
continue;
SDL_Surface * pt = CSDL_Ext::createSurfaceWithBpp<4>(minimap_pos.w, minimap_pos.h);
for (int i=0; i<mw; i++)
{
for (int j=0; j<mh; j++)
{
int3 pp( ((i*mapSizes.x)/mw), ((j*mapSizes.y)/mh), d );
if ( !LOCPLINT->cb->isVisible(pp) )
{
CSDL_Ext::SDL_PutPixelWithoutRefresh(pt,i,j,0,0,0);
}
}
}
FoW_.push_back(pt);
}
}
void CMinimapSurfacesRef::initFlaggableObjs(int level)
{
const Rect &minimap_pos = adventureInt->minimap.pos;
int mw = map_[0]->w, mh = map_[0]->h;
for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
{
if(level>=0 && d!=level)
continue;
SDL_Surface * pt = CSDL_Ext::createSurfaceWithBpp<4>(minimap_pos.w, minimap_pos.h);
for (int i=0; i<mw; i++)
{
for (int j=0; j<mh; j++)
{
CSDL_Ext::SDL_PutPixelWithoutRefresh(pt,i,j,0,0,0,0);
}
}
flObjs_.push_back(pt);
}
}
void CMinimap::updateRadar()
{}
void CMinimap::clickRight(tribool down, bool previousState)
{
adventureInt->handleRightClick(rcText,down);
}
void CMinimap::clickLeft(tribool down, bool previousState)
{
if (down)
addUsedEvents(MOVE);
else
removeUsedEvents(MOVE);
//ClickableL::clickLeft(down);
if (!((bool)down))
return;
double dx = (GH.current->motion.x - pos.x) / static_cast<double>(pos.w),
dy = (GH.current->motion.y - pos.y) / static_cast<double>(pos.h);
int3 newCPos;
newCPos.x = (CGI->mh->sizes.x*dx);
newCPos.y = (CGI->mh->sizes.y*dy);
newCPos.z = adventureInt->position.z;
adventureInt->centerOn(newCPos);
}
void CMinimap::hover (bool on)
{
//Hoverable::hover(on);
if (on)
adventureInt->statusbar.print(statusbarTxt);
else if (adventureInt->statusbar.current==statusbarTxt)
adventureInt->statusbar.clear();
}
void CMinimap::mouseMoved (const SDL_MouseMotionEvent & sEvent)
{
if (pressedL)
{
clickLeft(true, true);
}
}
void CMinimap::activate()
{
CIntObject::activate();
}
void CMinimap::deactivate()
{
CIntObject::deactivate();
}
std::vector<SDL_Surface*> & CMinimapSurfacesRef::map()
{
if (!ready) redraw();
return map_;
}
std::vector<SDL_Surface*> & CMinimapSurfacesRef::FoW()
{
if (!ready) redraw();
return FoW_;
}
std::vector<SDL_Surface*> & CMinimapSurfacesRef::flObjs()
{
if (!ready) redraw();
return flObjs_;
}
void CMinimapSurfacesRef::free()
{
if (ready)
{
for (int g = 0; g < map_.size(); ++g)
SDL_FreeSurface(map_[g]);
map_.clear();
for (int g = 0; g < FoW_.size(); ++g)
SDL_FreeSurface(FoW_[g]);
FoW_.clear();
for (int g = 0; g < flObjs_.size(); ++g)
SDL_FreeSurface(flObjs_[g]);
flObjs_.clear();
}
}
void CMinimap::showTile(const int3 &pos)
{
const int player = adventureInt->player;
std::vector<SDL_Surface*> &map = surfs[player].map();
std::vector<SDL_Surface*> &FoW = surfs[player].FoW();
std::vector<SDL_Surface*> &flObjs = surfs[player].flObjs();
int3 mapSizes = LOCPLINT->cb->getMapSize();
//drawing terrain
int mw = map[0]->w, mh = map[0]->h;
double wo = ((double)mw)/mapSizes.x, ho = ((double)mh)/mapSizes.y;
for (int ii=0; ii<wo; ii++)
{
for (int jj=0; jj<ho; jj++)
{
if ((pos.x*wo+ii<this->pos.w) && (pos.y*ho+jj<this->pos.h))
CSDL_Ext::SDL_PutPixelWithoutRefresh(FoW[pos.z],pos.x*wo+ii,pos.y*ho+jj,0,0,0,0);
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
if(tile)
{
if (tile->blocked && (!tile->visitable))
SDL_PutPixelWithoutRefresh(surfs[player].map()[pos.z], pos.x*wo+ii, pos.y*ho+jj, colorsBlocked[tile->tertype].r, colorsBlocked[tile->tertype].g, colorsBlocked[tile->tertype].b);
else
SDL_PutPixelWithoutRefresh(surfs[player].map()[pos.z], pos.x*wo+ii, pos.y*ho+jj, colors[tile->tertype].r, colors[tile->tertype].g, colors[tile->tertype].b);
}
}
}
//drawing flaggable objects
int woShifted = wo, hoShifted = ho; //for better minimap rendering on L-sized maps
std::vector < const CGObjectInstance * > oo = LOCPLINT->cb->getFlaggableObjects(pos);
for(size_t v=0; v<oo.size(); ++v)
{
if(!dynamic_cast< const CGHeroInstance * >(oo[v])) //heroes have been printed
{
int3 maplgp ( (pos.x*mw)/mapSizes.x, (pos.y*mh)/mapSizes.y, pos.z );
if(((int)wo) * mapSizes.x != mw && pos.x+1 < mapSizes.x)//minimap size in X is not multiple of map size in X
{
std::vector < const CGObjectInstance * > op1x = LOCPLINT->cb->getFlaggableObjects(int3(pos.x+1, pos.y, pos.z));
if(op1x.size()!=0)
{
woShifted = wo + 1;
}
else
{
woShifted = wo;
}
}
if(((int)ho) * mapSizes.y != mh && pos.y+1 < mapSizes.y) //minimap size in Y is not multiple of map size in Y
{
std::vector < const CGObjectInstance * > op1y = LOCPLINT->cb->getFlaggableObjects(int3(pos.x, pos.y+1, pos.z));
if(op1y.size()!=0)
{
hoShifted = ho + 1;
}
else
{
hoShifted = ho;
}
}
for (int ii=0; ii<woShifted; ii++) //rendering flaggable objects
{
for (int jj=0; jj<hoShifted; jj++)
{
if(oo[v]->tempOwner == 255)
SDL_PutPixelWithoutRefresh(flObjs[pos.z],maplgp.x+ii,maplgp.y+jj,graphics->neutralColor->r,
graphics->neutralColor->g,graphics->neutralColor->b);
else
SDL_PutPixelWithoutRefresh(flObjs[pos.z],maplgp.x+ii,maplgp.y+jj,graphics->playerColors[oo[v]->getOwner()].r,
graphics->playerColors[oo[v]->getOwner()].g,graphics->playerColors[oo[v]->getOwner()].b);
}
}
}
}
//flaggable objects drawn
}
void CMinimapSurfacesRef::showVisibleTiles(int level)
{
int3 mapSizes = LOCPLINT->cb->getMapSize();
for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
{
if(level>=0 && d!=level)
continue;
for(int x=0; x<mapSizes.x; ++x)
{
for(int y=0; y<mapSizes.y; ++y)
{
if(LOCPLINT->cb->isVisible(int3(x, y, d)))
{
adventureInt->minimap.showTile(int3(x, y, d));
}
}
}
}
}
void CMinimap::hideTile(const int3 &pos)
{
const int player = adventureInt->player;
std::vector<SDL_Surface*> &map = surfs[player].map();
std::vector<SDL_Surface*> &FoW = surfs[player].FoW();
int3 mapSizes = LOCPLINT->cb->getMapSize();
//drawing terrain
int mw = map[0]->w, mh = map[0]->h;
double wo = ((double)mw)/mapSizes.x, ho = ((double)mh)/mapSizes.y;
for (int ii=0; ii<wo; ii++)
{
for (int jj=0; jj<ho; jj++)
{
if ((pos.x*wo+ii<this->pos.w) && (pos.y*ho+jj<this->pos.h))
CSDL_Ext::SDL_PutPixelWithoutRefresh(FoW[pos.z],pos.x*wo+ii,pos.y*ho+jj,0,0,0);
}
}
}
CTerrainRect::CTerrainRect()
:curHoveredTile(-1,-1,-1), currentPath(NULL)
@ -769,207 +361,9 @@ void CResDataBar::showAll(SDL_Surface * to)
draw(to);
}
CInfoBar::CInfoBar()
{
pom = -1;
mode = NOTHING;
pos.x=ADVOPT.infoboxX;
pos.y=ADVOPT.infoboxY;
pos.w=194;
pos.h=186;
day = CDefHandler::giveDef("NEWDAY.DEF");
week1 = CDefHandler::giveDef("NEWWEEK1.DEF");
week2 = CDefHandler::giveDef("NEWWEEK2.DEF");
week3 = CDefHandler::giveDef("NEWWEEK3.DEF");
week4 = CDefHandler::giveDef("NEWWEEK4.DEF");
hourglass = CDefHandler::giveDef("HOURGLAS.DEF");
hourglassSand = CDefHandler::giveDef("HOURSAND.DEF");
selInfoWin = NULL;
}
CInfoBar::~CInfoBar()
{
delete day;
delete week1;
delete week2;
delete week3;
delete week4;
if(selInfoWin)
SDL_FreeSurface(selInfoWin);
}
void CInfoBar::showAll(SDL_Surface * to)
{
if (mode >= NEW_DAY && mode <= NEW_WEEK4)
{
blitAnim(mode);
}
else if(mode == ENEMY_TURN)
{
CPicture bg("ADSTATOT.bmp");
bg.convertToScreenBPP();
CAnimImage ai("CREST58", enemyTurnInfo.color, 0, 20, 51);
ai.showAll(&*bg);
int hourglassFrame = enemyTurnInfo.progress * hourglass->ourImages.size();
static int sandFrame = 0;
vstd::amin(hourglassFrame, hourglass->ourImages.size()-1);
blitAt(hourglassSand->ourImages[sandFrame++ % hourglassSand->ourImages.size()].bitmap, 99, 51, bg);
blitAt(hourglass->ourImages[hourglassFrame].bitmap, 99, 51, bg);
blitAtLoc(bg, 8, 11, to);
}
else if(selInfoWin)
{
blitAt(selInfoWin, pos.x, pos.y, to);
}
}
CDefHandler * CInfoBar::getAnim(EMode mode)
{
switch(mode)
{
case NEW_DAY:
return day;
case NEW_WEEK1:
return week1;
case NEW_WEEK2:
return week2;
case NEW_WEEK3:
return week3;
case NEW_WEEK4:
return week4;
default:
return NULL;
}
}
void CInfoBar::blitAnim(EMode mode)//0 - day, 1 - week
{
CDefHandler * anim = NULL;
std::ostringstream txt;
anim = getAnim(mode);
if(mode > NEW_DAY) //new week animation
{
txt << CGI->generaltexth->allTexts[63] << " " << LOCPLINT->cb->getDate(2);
}
else if(mode == NEW_DAY) //new day
{
txt << CGI->generaltexth->allTexts[64] << " " << LOCPLINT->cb->getDate(1);
}
blitAt(anim->ourImages[pom].bitmap,pos.x+9,pos.y+10);
printAtMiddle(txt.str(),pos.x+95,pos.y+31,FONT_MEDIUM,Colors::Cornsilk);
if (pom == anim->ourImages.size()-1)
setTimer(750);
}
void CInfoBar::newDay(int Day)
{
if(LOCPLINT->cb->getDate(1) != 1)
{
mode = NEW_DAY; //showing day
}
else
{
switch(LOCPLINT->cb->getDate(2))
{
case 1:
mode = NEW_WEEK1;
break;
case 2:
mode = NEW_WEEK2;
break;
case 3:
mode = NEW_WEEK3;
break;
case 4:
mode = NEW_WEEK4;
break;
default:
mode = NOTHING;
break;
}
}
pom = 0;
setTimer(500);
blitAnim(mode);
}
void CInfoBar::showComp(const CComponent * comp, int time/*=5000*/)
{
if(comp->type != CComponent::hero)
{
curSel = NULL;
}
SDL_Surface * b = BitmapHandler::loadBitmap("ADSTATOT.bmp");
blitAt(b,pos.x+8,pos.y+11);
CComponent* tempComp = (CComponent*)comp; //evil. TODO: remove need to move component
tempComp->moveTo(Point(pos.x+52, pos.y+54));
tempComp->showAll(screen);
printAtMiddle(comp->subtitle,pos.x+91,pos.y+158,FONT_SMALL,Colors::Cornsilk);
printAtMiddleWB(comp->description,pos.x+94,pos.y+31,FONT_SMALL,26,Colors::Cornsilk);
SDL_FreeSurface(b);
setTimer(time);
mode = SHOW_COMPONENT;
}
void CInfoBar::tick()
{
if(mode >= NEW_DAY && mode <= NEW_WEEK4) //animation
{
pom++;
if (pom >= getAnim(mode)->ourImages.size())
{
removeUsedEvents(TIME);
mode = NOTHING;
}
}
else if(mode == SHOW_COMPONENT)
{
removeUsedEvents(TIME);
mode = NOTHING;
}
if(adventureInt == GH.topInt())
redraw();
}
void CInfoBar::show(SDL_Surface * to)
{
}
void CInfoBar::deactivate()
{
CIntObject::deactivate();
mode = NOTHING;
}
void CInfoBar::updateSelection(const CGObjectInstance *obj)
{
if(obj->ID == GameConstants::HEROI_TYPE)
curSel = static_cast<const CGHeroInstance*>(obj);
else
curSel = NULL;
if(selInfoWin)
SDL_FreeSurface(selInfoWin);
selInfoWin = LOCPLINT->infoWin(obj);
}
void CInfoBar::enemyTurn(ui8 color, double progress)
{
mode = ENEMY_TURN;
enemyTurnInfo.color = color;
enemyTurnInfo.progress = progress;
redraw();
setTimer(250);
}
CAdvMapInt::CAdvMapInt()
:statusbar(ADVOPT.statusbarX,ADVOPT.statusbarY,ADVOPT.statusbarG),
CAdvMapInt::CAdvMapInt():
minimap(Rect(ADVOPT.minimapX, ADVOPT.minimapY, ADVOPT.minimapW, ADVOPT.minimapH)),
statusbar(ADVOPT.statusbarX,ADVOPT.statusbarY,ADVOPT.statusbarG),
kingOverview(CGI->generaltexth->zelp[293].first,CGI->generaltexth->zelp[293].second,
boost::bind(&CAdvMapInt::fshowOverview,this),&ADVOPT.kingOverview, SDLK_k),
@ -1000,8 +394,9 @@ nextHero(CGI->generaltexth->zelp[301].first,CGI->generaltexth->zelp[301].second,
endTurn(CGI->generaltexth->zelp[302].first,CGI->generaltexth->zelp[302].second,
boost::bind(&CAdvMapInt::fendTurn,this), &ADVOPT.endTurn, SDLK_e),
heroList(ADVOPT.hlistSize),
townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlistAD)//(5,&genRect(192,48,747,196),747,196,747,372),
heroList(ADVOPT.hlistSize, Point(ADVOPT.hlistX, ADVOPT.hlistY), ADVOPT.hlistAU, ADVOPT.hlistAD),
townList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD),
infoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192) )
{
duringAITurn = false;
state = NA;
@ -1010,7 +405,7 @@ townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlis
pos.w = screen->w;
pos.h = screen->h;
selection = NULL;
townList.fun = boost::bind(&CAdvMapInt::selectionChanged,this);
townList.onSelect = boost::bind(&CAdvMapInt::selectionChanged,this);
adventureInt=this;
bg = BitmapHandler::loadBitmap(ADVOPT.mainGraphic);
scrollingDir = 0;
@ -1020,12 +415,6 @@ townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlis
heroAnim=0;
heroAnimValHitCount=0; // hero animation frame
heroList.init();
heroList.genList();
//townList.init();
//townList.genList();
for (int g=0; g<ADVOPT.gemG.size(); ++g)
{
gems.push_back(CDefHandler::giveDef(ADVOPT.gemG[g]));
@ -1066,7 +455,7 @@ void CAdvMapInt::fswitchLevel()
underground.showAll(screenBuf);
}
updateScreen = true;
minimap.draw(screenBuf);
minimap.setLevel(position.z);
}
void CAdvMapInt::fshowQuestlog()
{
@ -1122,10 +511,11 @@ void CAdvMapInt::fsystemOptions()
void CAdvMapInt::fnextHero()
{
int next = getNextHeroIndex(heroList.selected);
auto hero = dynamic_cast<const CGHeroInstance*>(selection);
int next = getNextHeroIndex(vstd::find_pos(LOCPLINT->wanderingHeroes, hero));
if (next < 0)
return;
heroList.select(next);
select(LOCPLINT->wanderingHeroes[next], true);
}
void CAdvMapInt::fendTurn()
@ -1193,7 +583,7 @@ int CAdvMapInt::getNextHeroIndex(int startIndex)
void CAdvMapInt::updateNextHero(const CGHeroInstance *h)
{
int start = heroList.getPosOfHero(h);
int start = vstd::find_pos(LOCPLINT->wanderingHeroes, h);
int next = getNextHeroIndex(start);
if (next < 0)
{
@ -1279,9 +669,9 @@ void CAdvMapInt::showAll(SDL_Surface * to)
nextHero.showAll(to);
endTurn.showAll(to);
minimap.draw(to);
heroList.draw(to);
townList.draw(to);
minimap.showAll(to);
heroList.showAll(to);
townList.showAll(to);
updateScreen = true;
show(to);
@ -1350,7 +740,7 @@ void CAdvMapInt::show(SDL_Surface * to)
if(scrollingDir)
{
updateScreen = true;
updateMinimap=true;
minimap.redraw();
}
}
if(updateScreen)
@ -1361,31 +751,30 @@ void CAdvMapInt::show(SDL_Surface * to)
updateScreen=false;
LOCPLINT->cingconsole->showAll(to);
}
if (updateMinimap)
{
minimap.draw(to);
updateMinimap=false;
}
infoBar.show(to);
statusbar.showAll(to);
}
void CAdvMapInt::selectionChanged()
{
const CGTownInstance *to = LOCPLINT->towns[townList.selected];
const CGTownInstance *to = LOCPLINT->towns[townList.getSelectedIndex()];
select(to);
}
void CAdvMapInt::centerOn(int3 on)
{
bool switchedLevels = on.z != position.z;
on.x -= CGI->mh->frameW;
on.y -= CGI->mh->frameH;
on = LOCPLINT->repairScreenPos(on);
adventureInt->position = on;
adventureInt->updateScreen=true;
updateMinimap=true;
position = on;
updateScreen=true;
underground.setIndex(on.z,true); //change underground switch button image
if(GH.topInt() == this)
underground.redraw();
underground.redraw();
if (switchedLevels)
minimap.setLevel(position.z);
}
void CAdvMapInt::centerOn(const CGObjectInstance *obj)
@ -1599,30 +988,30 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
terrain.currentPath = NULL;
if(sel->ID==GameConstants::TOWNI_TYPE)
{
int pos = vstd::find_pos(LOCPLINT->towns,sel);
townList.selected = pos;
townList.fixPos();
auto town = dynamic_cast<const CGTownInstance*>(sel);
infoBar.showTownSelection(town, false);
townList.select(town);
heroList.select(nullptr);
updateSleepWake(NULL);
updateMoveHero(NULL);
}
else //hero selected
{
const CGHeroInstance *h = static_cast<const CGHeroInstance*>(sel);
if(LOCPLINT->getWHero(heroList.selected) != h)
{
heroList.selected = heroList.getPosOfHero(h);
heroList.fixPos();
}
auto hero = dynamic_cast<const CGHeroInstance*>(sel);
terrain.currentPath = LOCPLINT->getAndVerifyPath(h);
infoBar.showHeroSelection(hero, false);
heroList.select(hero);
townList.select(nullptr);
updateSleepWake(h);
updateMoveHero(h);
terrain.currentPath = LOCPLINT->getAndVerifyPath(hero);
updateSleepWake(hero);
updateMoveHero(hero);
}
townList.draw(screen);
heroList.draw(screen);
infoBar.updateSelection(sel);
infoBar.showAll(screen);
townList.redraw();
heroList.redraw();
}
void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
@ -1702,6 +1091,7 @@ void CAdvMapInt::startTurn()
if(LOCPLINT->cb->getCurrentPlayer() == LOCPLINT->playerID)
{
adjustActiveness(false);
minimap.setAIRadar(false);
}
}
@ -2091,8 +1481,9 @@ void CAdvMapInt::aiTurnStarted()
{
adjustActiveness(true);
CCS->musich->playMusicFromSet(CCS->musich->aiMusics);
adventureInt->minimap.redraw();
adventureInt->infoBar.enemyTurn(LOCPLINT->cb->getCurrentPlayer(), 0.5);
adventureInt->minimap.setAIRadar(true);
adventureInt->infoBar.startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
adventureInt->infoBar.showAll(screen);//force refresh on inactive object
}
void CAdvMapInt::adjustActiveness(bool aiTurnStart)
@ -2106,34 +1497,28 @@ void CAdvMapInt::adjustActiveness(bool aiTurnStart)
activate();
}
CAdventureOptions::CAdventureOptions()
CAdventureOptions::CAdventureOptions():
CWindowObject("ADVOPTS", PLAYER_COLORED)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
bg = new CPicture("ADVOPTS.bmp");
graphics->blueToPlayersAdv(bg->bg, LOCPLINT->playerID);
pos = bg->center();
exit = new CAdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
exit = new CAdventureMapButton("","",boost::bind(&CAdventureOptions::close, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
exit->assignedKeys.insert(SDLK_ESCAPE);
//scenInfo = new CAdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 24, "ADVINFO.DEF",SDLK_i);
scenInfo = new CAdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 198, "ADVINFO.DEF",SDLK_i);
scenInfo = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 198, "ADVINFO.DEF",SDLK_i);
scenInfo->callback += CAdventureOptions::showScenarioInfo;
//viewWorld = new CAdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
puzzle = new CAdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 81, "ADVPUZ.DEF");
puzzle = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 81, "ADVPUZ.DEF");
puzzle->callback += boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT);
dig = new CAdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 139, "ADVDIG.DEF");
dig = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 139, "ADVDIG.DEF");
if(const CGHeroInstance *h = adventureInt->curHero())
dig->callback += boost::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h);
else
dig->block(true);
}
CAdventureOptions::~CAdventureOptions()
{
}
void CAdventureOptions::showScenarioInfo()
{
GH.pushInt(new CScenarioInfo(LOCPLINT->cb->getMapHeader(), LOCPLINT->cb->getStartInfo()));

View File

@ -5,6 +5,7 @@
#include "SDL.h"
#include "UIFramework/CIntObjectClasses.h"
#include "GUIClasses.h"
#include "AdventureMapClasses.h"
class CDefHandler;
class CCallback;
@ -19,7 +20,7 @@ class IShipyard;
/*****************************/
/*
* CAdcmapInterface.h, part of VCMI engine
* CAdvmapInterface.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
@ -29,65 +30,15 @@ class IShipyard;
*/
/// Adventure options dialogue where you can view the world, dig, play the replay of the last turn,...
class CAdventureOptions : public CIntObject
class CAdventureOptions : public CWindowObject
{
public:
CPicture *bg;
CAdventureMapButton *exit, *viewWorld, *puzzle, *dig, *scenInfo, *replay;
CAdventureOptions();
~CAdventureOptions();
static void showScenarioInfo();
};
//Player-specific minimaps
class CMinimapSurfacesRef
{
public:
CMinimapSurfacesRef();
// see private members descriptions
std::vector< SDL_Surface* > &map();
std::vector< SDL_Surface* > &FoW();
std::vector< SDL_Surface* > &flObjs();
void free();
private:
void redraw(int level=-1);// (level==-1) => redraw all levels
void initMap(int level=-1);// (level==-1) => redraw all levels
void initFoW(int level=-1);// (level==-1) => redraw all levels
void initFlaggableObjs(int level=-1);// (level==-1) => redraw all levels
void showVisibleTiles(int level=-1);// (level==-1) => redraw all levels
private:
std::vector< SDL_Surface* > map_, FoW_, flObjs_; //one bitmap for each level (terrain, Fog of War, flaggable objects) (one for underworld, one for surface)
bool ready;
};
/// Minimap which is displayed at the right upper corner of adventure map
class CMinimap : public CIntObject
{
public:
CPicture *aiShield; //the graphic displayed during AI turn
SDL_Surface * temps;
std::map<int,SDL_Color> colors;
std::map<int,SDL_Color> colorsBlocked;
std::map<int, CMinimapSurfacesRef> surfs;
std::string statusbarTxt, rcText;
CMinimap();
~CMinimap();
void draw(SDL_Surface * to);
void updateRadar();
void clickRight(tribool down, bool previousState);
void clickLeft(tribool down, bool previousState);
void hover (bool on);
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
void activate(); // makes button active
void deactivate(); // makes button inactive (but don't deletes)
void hideTile(const int3 &pos); //puts FoW
void showTile(const int3 &pos); //removes FoW
};
/// Holds information about which tiles of the terrain are shown/not shown at the screen
class CTerrainRect
: public CIntObject
@ -112,8 +63,7 @@ public:
/// Resources bar which shows information about how many gold, crystals,... you have
/// Current date is displayed too
class CResDataBar
: public CIntObject
class CResDataBar : public CIntObject
{
public:
SDL_Surface * bg;
@ -130,45 +80,6 @@ public:
void showAll(SDL_Surface * to);
};
/// Info box which shows next week/day information, hold the current date
class CInfoBar : public CIntObject
{
enum EMode {NOTHING = -1, NEW_DAY, NEW_WEEK1, NEW_WEEK2, NEW_WEEK3, NEW_WEEK4, ____, SHOW_COMPONENT, ENEMY_TURN};
CDefHandler *day, *week1, *week2, *week3, *week4, *hourglass, *hourglassSand;
CComponent * current;
int pom;
SDL_Surface *selInfoWin; //info box for selection
CDefHandler * getAnim(EMode mode);
struct EnemyTurn
{
ui8 color;
double progress; //0-1
EnemyTurn()
{
color = 255;
progress = 0.;
}
} enemyTurnInfo;
public:
EMode mode;
const CGHeroInstance * curSel;
CInfoBar();
~CInfoBar();
void newDay(int Day); //start showing new day/week animation
void showComp(const CComponent * comp, int time=5000);
void enemyTurn(ui8 color, double progress);
void tick();
void showAll(SDL_Surface * to); // if specific==0 function draws info about selected hero/town
void blitAnim(EMode mode);//0 - day, 1 - week
void show(SDL_Surface * to);
void deactivate();
void updateSelection(const CGObjectInstance *obj);
};
/// That's a huge class which handles general adventure map actions and
/// shows the right menu(questlog, spellbook, end turn,..) from where you
/// can get to the towns and heroes.
@ -191,7 +102,7 @@ public:
enum{NA, INGAME, WAITING} state;
bool updateScreen, updateMinimap ;
bool updateScreen;
ui8 anim, animValHitCount; //animation frame
ui8 heroAnim, heroAnimValHitCount; //animation frame

View File

@ -1279,6 +1279,7 @@ void CShowableAnim::reset()
{
value = 0;
frame = first;
if (callback)
callback();
}
@ -1297,6 +1298,9 @@ void CShowableAnim::show(SDL_Surface * to)
blitImage(first, group, to);
blitImage(frame, group, to);
if ((flags & PLAY_ONCE) && frame + 1 == last)
return;
if ( ++value == frameDelay )
{
value = 0;

View File

@ -260,6 +260,7 @@ public:
VERTICAL_FLIP=4, //TODO: will be displayed rotated
USE_RLE=8, //RLE-d version, support full alpha-channel for 8-bit images
PLAYER_COLORED=16, //TODO: all loaded images will be player-colored
PLAY_ONCE=32 //play animation only once and stop at last frame
};
protected:
CAnimation anim;

View File

@ -187,7 +187,7 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
if (!(bitmap = loadBitmapFromLod(bitmaph, fname, setKey)) &&
!(bitmap = loadBitmapFromLod(bitmaph_ab, fname, setKey)) &&
!(bitmap = loadBitmapFromLod(spriteh, fname, setKey)))
tlog1<<"Failed to find file "<<fname<<"\n";
tlog0<<"Error: Failed to find file "<<fname<<"\n";
return bitmap;
}

View File

@ -918,7 +918,7 @@ void CCastleBuildings::openTownHall()
GH.pushInt(new CHallInterface(town));
}
CCastleInterface::CCastleInterface(const CGTownInstance * Town, int listPos):
CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInstance * from):
CWindowObject("", PLAYER_COLORED | BORDERED),
hall(NULL),
fort(NULL),
@ -953,13 +953,12 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, int listPos):
statusbar = new CGStatusBar(new CPicture(*panel, barRect, 9, 555, false));
resdatabar = new CResDataBar("ZRESBAR", 3, 575, 32, 2, 85, 85);
townlist = new CTownList(3, 744, 414, "IAM014", "IAM015");
townlist->fun = boost::bind(&CCastleInterface::townChange, this);
townlist->selected = vstd::find_pos(LOCPLINT->towns, Town);
townlist = new CTownList(3, Point(744, 414), "IAM014", "IAM015");
if (from)
townlist->select(from);
townlist->from = townlist->selected - listPos;
vstd::amax(townlist->from, 0);
vstd::amin(townlist->from, LOCPLINT->towns.size() - townlist->SIZE);
townlist->select(town); //this will scroll list to select current town
townlist->onSelect = boost::bind(&CCastleInterface::townChange, this);
recreateIcons();
CCS->musich->playMusic(CCS->musich->townMusics[town->subID], -1);
@ -993,12 +992,12 @@ void CCastleInterface::castleTeleport(int where)
void CCastleInterface::townChange()
{
const CGTownInstance * nt = LOCPLINT->towns[townlist->selected];
int tpos = townlist->selected - townlist->from;
if ( nt == town )
const CGTownInstance * dest = LOCPLINT->towns[townlist->getSelectedIndex()];
const CGTownInstance * town = this->town;// "this" is going to be deleted
if ( dest == town )
return;
GH.popIntTotally(this);
GH.pushInt(new CCastleInterface(nt, tpos));
GH.pushInt(new CCastleInterface(dest, town));
}
void CCastleInterface::addBuilding(int bid)
@ -1233,20 +1232,10 @@ void CCastleInterface::keyPressed( const SDL_KeyboardEvent & key )
switch(key.keysym.sym)
{
case SDLK_UP:
if(townlist->selected)
{
townlist->selected--;
townlist->from--;
townChange();
}
townlist->selectPrev();
break;
case SDLK_DOWN:
if(townlist->selected < LOCPLINT->towns.size() - 1)
{
townlist->selected++;
townlist->from++;
townChange();
}
townlist->selectNext();
break;
case SDLK_SPACE:
if(!!town->visitingHero && town->garrisonHero)
@ -1397,12 +1386,6 @@ void CBuildWindow::buyFunc()
GH.popInts(2); //we - build window and hall screen
}
void CBuildWindow::clickRight(tribool down, bool previousState)
{
if((!down || indeterminate(down)))
close();
}
std::string CBuildWindow::getTextForState(int state)
{
std::string ret;
@ -1432,9 +1415,11 @@ std::string CBuildWindow::getTextForState(int state)
return ret;
}
CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Building, int State, bool Mode):
CWindowObject("TPUBUILD", PLAYER_COLORED),
town(Town), building(Building), state(State), mode(Mode)
CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Building, int State, bool rightClick):
CWindowObject("TPUBUILD", PLAYER_COLORED | (rightClick ? RCLICK_POPUP : 0)),
town(Town),
building(Building),
state(State)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
@ -1486,11 +1471,7 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin
posY +=75;
}
if(mode)
{ //popup
addUsedEvents(RCLICK);
}
else
if(!rightClick)
{ //normal window
buy = new CAdventureMapButton(boost::str(boost::format(CGI->generaltexth->allTexts[595]) % building->Name()),
"", boost::bind(&CBuildWindow::buyFunc,this), 45, 446,"IBUY30", SDLK_RETURN);
@ -1505,8 +1486,6 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin
}
}
CBuildWindow::~CBuildWindow()
{}
std::string CFortScreen::getBgName(const CGTownInstance *town)
{

View File

@ -217,7 +217,7 @@ public:
HeroSlots *heroes;
CCastleBuildings *builds;
CCastleInterface(const CGTownInstance * Town, int listPos = 1); //c-tor
CCastleInterface(const CGTownInstance * Town, const CGTownInstance * from = nullptr); //c-tor
~CCastleInterface();
void castleTeleport(int where);
@ -269,7 +269,6 @@ class CBuildWindow: public CWindowObject
const CGTownInstance *town;
const CBuilding *building;
int state; //state - same as CHallInterface::CBuildingBox::state
bool mode; // 0 - normal (with buttons), 1 - r-click popup
CAnimImage *buildingPic;
CAdventureMapButton *buy;
@ -287,9 +286,7 @@ class CBuildWindow: public CWindowObject
void buyFunc();
public:
void clickRight(tribool down, bool previousState);
CBuildWindow(const CGTownInstance *Town, const CBuilding * building, int State, bool Mode); //c-tor
~CBuildWindow(); //d-tor
CBuildWindow(const CGTownInstance *Town, const CBuilding * building, int State, bool rightClick); //c-tor
};
//Small class to display

View File

@ -248,7 +248,7 @@ public:
};
/// List item with town
class CTownItem : public CGarrisonHolder
class CTownItem : public CIntObject, public CGarrisonHolder
{
CAnimImage *background;
CAnimImage *picture;
@ -272,7 +272,7 @@ public:
};
/// List item with hero
class CHeroItem : public CWindowWithGarrison
class CHeroItem : public CIntObject, public CWindowWithGarrison
{
const CGHeroInstance * hero;
@ -322,7 +322,7 @@ public:
};
/// Tab with all town-specific data
class CKingdTownList : public CGarrisonHolder
class CKingdTownList : public CIntObject, public CGarrisonHolder
{
private:
std::vector<CTownItem*> townItems;

View File

@ -500,13 +500,17 @@ MusicEntry::~MusicEntry()
void MusicEntry::load(musicBase::musicID ID)
{
if (music)
{
tlog5<<"Del-ing music file "<<filename<<"\n";
Mix_FreeMusic(music);
}
currentID = ID;
filename = GameConstants::DATA_DIR + "/Mp3/";
filename += owner->musics[ID];
tlog5<<"Loading music file "<<filename<<"\n";
if (music)
Mix_FreeMusic(music);
music = Mix_LoadMUS(filename.c_str());

View File

@ -136,18 +136,13 @@ void CPlayerInterface::init(CCallback * CB)
{
cb = dynamic_cast<CCallback*>(CB);
if(observerInDuelMode)
{
return;
}
if(!towns.size() && !wanderingHeroes.size())
initializeHeroTownList();
if(!adventureInt)
adventureInt = new CAdvMapInt();
if(!towns.size() && !wanderingHeroes.size())
{
recreateHeroTownList();
}
}
void CPlayerInterface::yourTurn()
{
@ -250,8 +245,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
}
adventureInt->centerOn(ho); //actualizing screen pos
adventureInt->minimap.draw(screen2);
adventureInt->heroList.draw(screen2);
adventureInt->minimap.redraw();
adventureInt->heroList.redraw();
bool directlyAttackingCreature =
CGI->mh->map->isInTheMap(details.attackedFrom)
@ -329,8 +324,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
ho->isStanding = true;
//move finished
adventureInt->minimap.draw(screen2);
adventureInt->heroList.updateMove(ho);
adventureInt->minimap.redraw();
adventureInt->heroList.update(ho);
//check if user cancelled movement
{
@ -376,13 +371,13 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
if(vstd::contains(paths, hero))
paths.erase(hero);
adventureInt->heroList.updateHList(hero);
adventureInt->heroList.update(hero);
}
void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
wanderingHeroes.push_back(hero);
adventureInt->heroList.updateHList();
adventureInt->heroList.update(hero);
}
void CPlayerInterface::openTownWindow(const CGTownInstance * town)
{
@ -392,36 +387,6 @@ void CPlayerInterface::openTownWindow(const CGTownInstance * town)
GH.pushInt(castleInt);
}
SDL_Surface * CPlayerInterface::infoWin(const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
{
if(!specific)
specific = adventureInt->selection;
assert(specific);
switch(specific->ID)
{
case GameConstants::HEROI_TYPE:
{
InfoAboutHero iah;
bool gotInfo = LOCPLINT->cb->getHeroInfo(specific, iah);
assert(gotInfo);
return graphics->drawHeroInfoWin(iah);
}
case GameConstants::TOWNI_TYPE:
case 33: // Garrison
case 219:
{
InfoAboutTown iah;
bool gotInfo = LOCPLINT->cb->getTownInfo(specific, iah);
assert(gotInfo);
return graphics->drawTownInfoWin(iah);
}
default:
return NULL;
}
}
int3 CPlayerInterface::repairScreenPos(int3 pos)
{
if(pos.x<-CGI->mh->frameW)
@ -516,6 +481,7 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
CGI->mh->printObject(town->visitingHero);
wanderingHeroes.push_back(town->visitingHero);
}
adventureInt->heroList.update();
adventureInt->updateNextHero(NULL);
if(CCastleInterface *c = castleInt)
@ -546,20 +512,18 @@ void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownIn
waitWhileDialog();
openTownWindow(town);
}
void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj, bool updateInfobox /*= true*/ )
void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(updateInfobox)
updateInfo(obj);
updateInfo(obj);
for(std::list<IShowActivatable*>::iterator i = GH.listInt.begin(); i != GH.listInt.end(); i++)
{
if((*i)->type & IShowActivatable::WITH_GARRISON)
{
CGarrisonHolder *cgh = dynamic_cast<CGarrisonHolder*>(*i);
CGarrisonHolder *cgh = dynamic_cast<CGarrisonHolder*>(*i);
if (cgh)
cgh->updateGarrisons();
}
else if(CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(*i))
if(CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(*i))
{
if(obj == cmw->hero)
cmw->garrisonChanged();
@ -593,6 +557,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
castleInt->removeBuilding(buildingID);
break;
}
adventureInt->townList.update(town);
}
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
@ -941,13 +906,13 @@ void CPlayerInterface::yourTacticPhase(int distance)
boost::this_thread::sleep(boost::posix_time::millisec(1));
}
void CPlayerInterface::showComp(const CComponent &comp)
void CPlayerInterface::showComp(const Component &comp, std::string message)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
waitWhileDialog(); //Fix for mantis #98
CCS->soundh->playSoundFromSet(CCS->soundh->pickupSounds);
adventureInt->infoBar.showComp(&comp,4000);
adventureInt->infoBar.showComponent(comp, message);
}
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID)
@ -1377,6 +1342,7 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
towns.push_back(static_cast<const CGTownInstance *>(obj));
else
towns -= obj;
adventureInt->townList.update();
}
assert(cb->getTownsInfo().size() == towns.size());
@ -1384,10 +1350,11 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
}
void CPlayerInterface::recreateHeroTownList()
void CPlayerInterface::initializeHeroTownList()
{
std::vector <const CGHeroInstance *> newWanderingHeroes;
std::vector<const CGHeroInstance*> allHeroes = cb->getHeroesInfo();
/*
std::vector <const CGHeroInstance *> newWanderingHeroes;
//applying current heroes order to new heroes info
int j;
@ -1401,13 +1368,15 @@ void CPlayerInterface::recreateHeroTownList()
//all the rest of new heroes go the end of the list
wanderingHeroes.clear();
wanderingHeroes = newWanderingHeroes;
newWanderingHeroes.clear();
newWanderingHeroes.clear();*/
for (int i = 0; i < allHeroes.size(); i++)
if (!allHeroes[i]->inTownGarrison)
wanderingHeroes += allHeroes[i];
std::vector<const CGTownInstance*> newTowns;
std::vector<const CGTownInstance*> allTowns = cb->getTownsInfo();
/*
std::vector<const CGTownInstance*> newTowns;
for (int i = 0; i < towns.size(); i++)
if ((j = vstd::find_pos(allTowns, towns[i])) >= 0)
{
@ -1417,18 +1386,12 @@ void CPlayerInterface::recreateHeroTownList()
towns.clear();
towns = newTowns;
newTowns.clear();
newTowns.clear();*/
for(int i = 0; i < allTowns.size(); i++)
towns.push_back(allTowns[i]);
adventureInt->updateNextHero(NULL);
}
const CGHeroInstance * CPlayerInterface::getWHero( int pos )
{
if(pos < 0 || pos >= wanderingHeroes.size())
return NULL;
return wanderingHeroes[pos];
if (adventureInt)
adventureInt->updateNextHero(NULL);
}
void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level)
@ -2137,24 +2100,6 @@ void CPlayerInterface::acceptTurn()
if(howManyPeople > 1)
adventureInt->startTurn();
//boost::unique_lock<boost::recursive_mutex> un(*pim);
//Select sound for day start
int totalDays = cb->getDate();
int day = cb->getDate(1);
int week = cb->getDate(2);
if (totalDays == 1)
CCS->soundh->playSound(soundBase::newDay);
else if (day != 1)
CCS->soundh->playSound(soundBase::newDay);
else if (week != 1)
CCS->soundh->playSound(soundBase::newWeek);
else
CCS->soundh->playSound(soundBase::newMonth);
adventureInt->infoBar.newDay(day);
//select first hero if available.
//TODO: check if hero is slept
if(wanderingHeroes.size())
@ -2162,6 +2107,11 @@ void CPlayerInterface::acceptTurn()
else
adventureInt->select(towns.front());
//show new day animation and sound on infobar
adventureInt->infoBar.showDate();
adventureInt->heroList.update();
adventureInt->townList.update();
adventureInt->updateNextHero(NULL);
adventureInt->showAll(screen);
@ -2209,9 +2159,10 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
{
adventureInt->infoBar.updateSelection(specific);
// if (adventureInt->selection == specific)
// adventureInt->infoBar.showAll(screen);
if (specific->ID == GameConstants::TOWNI_TYPE)
adventureInt->infoBar.showTownSelection(dynamic_cast<const CGTownInstance *>(specific), true);
else
adventureInt->infoBar.showHeroSelection(dynamic_cast<const CGHeroInstance *>(specific), true);
}
void CPlayerInterface::battleNewRoundFirst( int round )
@ -2329,13 +2280,12 @@ void CPlayerInterface::stacksErased(const StackLocation &location)
garrisonChanged(location.army);
}
#define UPDATE_IF(LOC) static_cast<const CArmedInstance*>(adventureInt->infoBar.curSel) == LOC.army.get()
void CPlayerInterface::stacksSwapped(const StackLocation &loc1, const StackLocation &loc2)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
garrisonChanged(loc1.army, UPDATE_IF(loc1));
garrisonChanged(loc1.army);
if(loc2.army != loc1.army)
garrisonChanged(loc2.army, UPDATE_IF(loc2));
garrisonChanged(loc2.army);
}
void CPlayerInterface::newStackInserted(const StackLocation &location, const CStackInstance &stack)
@ -2348,9 +2298,9 @@ void CPlayerInterface::stacksRebalanced(const StackLocation &src, const StackLoc
{
EVENT_HANDLER_CALLED_BY_CLIENT;
garrisonChanged(src.army, UPDATE_IF(src));
garrisonChanged(src.army);
if(dst.army != src.army)
garrisonChanged(dst.army, UPDATE_IF(dst));
garrisonChanged(dst.army);
}
#undef UPDATE_IF

View File

@ -103,9 +103,8 @@ public:
std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
std::vector<const CGTownInstance *> towns; //our heroes on the adventure map (not the garrisoned ones)
std::vector<const CGTownInstance *> towns; //our towns on the adventure map
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
@ -122,8 +121,7 @@ public:
} spellbookSettings;
void update();
void recreateHeroTownList();
const CGHeroInstance *getWHero(int pos); //returns NULL if position is not valid
void initializeHeroTownList();
int getLastIndex(std::string namePrefix);
//overridden funcs from CGameInterface
@ -179,7 +177,7 @@ public:
void objectRemoved(const CGObjectInstance *obj) OVERRIDE;
void gameOver(ui8 player, bool victory) OVERRIDE;
void playerStartsTurn(ui8 player) OVERRIDE; //called before yourTurn on active itnerface
void showComp(const CComponent &comp) OVERRIDE; //display component in the advmapint infobox
void showComp(const Component &comp, std::string message) OVERRIDE; //display component in the advmapint infobox
void serialize(COSer<CSaveFile> &h, const int version) OVERRIDE; //saving
void serialize(CISer<CLoadFile> &h, const int version) OVERRIDE; //loading
@ -207,7 +205,7 @@ public:
//-------------//
void showArtifactAssemblyDialog(ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList<void()> onYes, CFunctionList<void()> onNo);
void garrisonChanged(const CGObjectInstance * obj, bool updateInfobox = true);
void garrisonChanged(const CGObjectInstance * obj);
void heroKilled(const CGHeroInstance* hero);
void waitWhileDialog(bool unlockPim = true);
void waitForAllDialogs(bool unlockPim = true);
@ -217,7 +215,6 @@ public:
void redrawHeroWin(const CGHeroInstance * hero);
void openTownWindow(const CGTownInstance * town); //shows townscreen
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
SDL_Surface * infoWin(const CGObjectInstance * specific); //specific=0 => draws info about selected town/hero
void updateInfo(const CGObjectInstance * specific);
void init(CCallback * CB);
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on

View File

@ -1159,7 +1159,10 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
positions = 16;
}
if(tabType == CMenuScreen::saveGame)
{
txt = new CTextInput(Rect(32, 539, 350, 20), Point(-32, -25), "GSSTRIP.bmp", 0);
txt->filters.add(CTextInput::filenameFilter);
}
break;
case CMenuScreen::campaignList:
getFiles(toParse, GameConstants::DATA_DIR + "/Maps", "h3c"); //get all campaigns
@ -1245,7 +1248,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
if(selectedName.size())
{
if(selectedName[2] == 'M') //name starts with ./Maps instead of ./Games => there was nothing to select
txt->setText("NEWGAME");
txt->setTxt("NEWGAME");
else
selectFName(selectedName);
}
@ -1302,7 +1305,7 @@ void SelectionTab::select( int position )
slider->moveTo(slider->value + position - positions + 1);
if(txt)
txt->setText(fs::basename(curItems[py]->filename));
txt->setTxt(fs::basename(curItems[py]->filename));
onSelect(curItems[py]);
}
@ -1572,7 +1575,7 @@ void CChatBox::keyPressed(const SDL_KeyboardEvent & key)
if(key.keysym.sym == SDLK_RETURN && key.state == SDL_PRESSED && inputBox->text.size())
{
SEL->postChatMessage(inputBox->text);
inputBox->setText("");
inputBox->setTxt("");
}
else
inputBox->keyPressed(key);
@ -2690,7 +2693,7 @@ CMultiMode::CMultiMode()
bar = new CGStatusBar(new CPicture(Rect(7, 465, 440, 18), 0));//226, 472
txt = new CTextInput(Rect(19, 436, 334, 16), *bg);
txt->setText(settings["general"]["playerName"].String()); //Player
txt->setTxt(settings["general"]["playerName"].String()); //Player
btns[0] = new CAdventureMapButton(CGI->generaltexth->zelp[266], bind(&CMultiMode::openHotseat, this), 373, 78, "MUBHOT.DEF");
btns[1] = new CAdventureMapButton("Host TCP/IP game", "", bind(&CMultiMode::hostTCP, this), 373, 78 + 57*1, "MUBHOST.DEF");
@ -2740,7 +2743,7 @@ CHotSeatPlayers::CHotSeatPlayers(const std::string &firstPlayer)
cancel = new CAdventureMapButton(CGI->generaltexth->zelp[561], bind(&CGuiHandler::popIntTotally, ref(GH), this), 205, 338, "MUBCANC.DEF", SDLK_ESCAPE);
bar = new CGStatusBar(new CPicture(Rect(7, 381, 348, 18), 0));//226, 472
txt[0]->setText(firstPlayer, true);
txt[0]->setTxt(firstPlayer, true);
txt[0]->giveFocus();
}

View File

@ -72,6 +72,17 @@ public:
funcs2[i](a);
}
}
// Me wants variadic templates :(
template <typename Arg1, typename Arg2>
void operator()(Arg1 & a, Arg2 & b) const
{
std::vector<boost::function<Signature> > funcs2 = funcs; //backup
for(int i=0;i<funcs2.size(); i++)
{
if (funcs2[i])
funcs2[i](a, b);
}
}
};
template<typename Signature>

File diff suppressed because it is too large Load Diff

View File

@ -73,6 +73,9 @@ class CArtifactInstance;
class IBonusBearer;
class CArtPlace;
class CAnimImage;
struct InfoAboutArmy;
struct InfoAboutHero;
struct InfoAboutTown;
/// text + comp. + ok button
class CInfoWindow : public CSimpleWindow
@ -124,6 +127,7 @@ public:
CRClickPopup();
virtual ~CRClickPopup(); //d-tor
static CIntObject* createInfoWin(Point position, const CGObjectInstance * specific);
static void createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo());
static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT);
};
@ -156,6 +160,16 @@ public:
~CInfoPopup(); //d-tor
};
/// popup on adventure map for town\hero objects
class CInfoBoxPopup : public CWindowObject
{
Point toScreen(Point pos);
public:
CInfoBoxPopup(Point position, const CGTownInstance * town);
CInfoBoxPopup(Point position, const CGHeroInstance * hero);
CInfoBoxPopup(Point position, const CGGarrison * garr);
};
/// common popup window component
class CComponent : public virtual CIntObject
{
@ -185,8 +199,6 @@ public:
CComponent(); //c-tor
void clickRight(tribool down, bool previousState); //call-in
void show(SDL_Surface * to);
};
class CSelectableComponent : public CComponent, public CKeyShortcut
@ -206,6 +218,38 @@ public:
////////////////////////////////////////////////////////////////////////////////
/// base class for hero/town/garrison tooltips
class CArmyTooltip : public CIntObject
{
void init(const InfoAboutArmy &army);
public:
CArmyTooltip(Point pos, const InfoAboutArmy &army);
CArmyTooltip(Point pos, const CArmedInstance * army);
};
/// Class for hero tooltip. Does not have any background!
/// background for infoBox: ADSTATHR
/// background for tooltip: HEROQVBK
class CHeroTooltip : public CArmyTooltip
{
void init(const InfoAboutHero &hero);
public:
CHeroTooltip(Point pos, const InfoAboutHero &hero);
CHeroTooltip(Point pos, const CGHeroInstance * hero);
};
/// Class for town tooltip. Does not have any background!
/// background for infoBox: ADSTATCS
/// background for tooltip: TOWNQVBK
class CTownTooltip : public CArmyTooltip
{
void init(const InfoAboutTown &town);
public:
CTownTooltip(Point pos, const InfoAboutTown &town);
CTownTooltip(Point pos, const CGTownInstance * town);
};
///////////////////////////////////////////////////////////////////////////////
class CGarrisonInt;
@ -264,68 +308,18 @@ public:
void recreateSlots();
void splitClick(); //handles click on split button
void splitStacks(int am2); //TODO: comment me
void splitStacks(int amountLeft, int amountRight); //TODO: comment me
//x, y - position;
//inx - distance between slots;
//pomsur, SurOffset - UNUSED
//s1, s2 - top and bottom armies;
//removableUnits - you can take units from top;
//smallImgs - units images size 64x58 or 32x32;
//twoRows - display slots in 2 row (1st row = 4, 2nd = 3)
//twoRows - display slots in 2 row (1st row = 4 slots, 2nd = 3 slots)
CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool _removableUnits = true, bool smallImgs = false, bool _twoRows=false); //c-tor
~CGarrisonInt(); //d-tor
};
/// List of heroes which is shown at the right of the adventure map screen
class CHeroList
: public CList
{
public:
CDefHandler *mobile, *mana; //mana and movement indicators
int posmobx, posporx, posmanx, posmoby, pospory, posmany;
CHeroList(int Size); //c-tor
int getPosOfHero(const CGHeroInstance* h); //hero's position on list
void genList();
void select(int which); //call-in
void mouseMoved (const SDL_MouseMotionEvent & sEvent); //call-in
void clickLeft(tribool down, bool previousState); //call-in
void clickRight(tribool down, bool previousState); //call-in
void hover (bool on); //call-in
void keyPressed (const SDL_KeyboardEvent & key); //call-in
void updateHList(const CGHeroInstance *toRemove=NULL); //removes specific hero from the list or recreates it
void updateMove(const CGHeroInstance* which); //draws move points bar
void draw(SDL_Surface * to);
void show(SDL_Surface * to);
void showAll(SDL_Surface * to);
void init();
int size(); //how many elements do we have
};
/// List of towns which is shown at the right of the adventure map screen
class CTownList
: public CList
{
public:
boost::function<void()> fun; //function called on selection change
int posporx,pospory;
CTownList(int Size, int x, int y, std::string arrupg, std::string arrdog); //c-tor
~CTownList(); //d-tor
void genList();
void select(int which); //call-in
void selectNext(); //switches to the next town or the first one if none is selected
void mouseMoved (const SDL_MouseMotionEvent & sEvent); //call-in
void clickLeft(tribool down, bool previousState); //call-in
void clickRight(tribool down, bool previousState); //call-in
void hover (bool on); //call-in
void keyPressed (const SDL_KeyboardEvent & key); //call-in
void draw(SDL_Surface * to);
void show(SDL_Surface * to);
void showAll(SDL_Surface * to);
int size(); //how many elements do we have
};
/// draws picture with creature on background, use Animated=true to get animation
class CCreaturePic : public CIntObject
{
@ -380,26 +374,34 @@ public:
};
/// Split window where creatures can be splitted up into two single unit stacks
class CSplitWindow : public CIntObject
class CSplitWindow : public CWindowObject
{
public:
CGarrisonInt *gar;
boost::function<void(int, int)> callback;
int leftAmount;
int rightAmount;
int leftMin;
int rightMin;
CSlider *slider;
CCreaturePic *animLeft, *animRight; //creature's animation
CAdventureMapButton *ok, *cancel;
SDL_Surface *bitmap; //background
int a1, a2, c; //TODO: comment me
bool which; //which creature is selected
int last; //0/1/2 - at least one creature must be in the src/dst/both stacks; -1 - no restrictions
CSplitWindow(int cid, int max, CGarrisonInt *Owner, int Last = -1, int val=0); //c-tor; val - initial amount of second stack
~CSplitWindow(); //d-tor
void split();
void close();
void show(SDL_Surface * to);
void clickLeft(tribool down, bool previousState); //call-in
void keyPressed (const SDL_KeyboardEvent & key); //call-in
void sliderMoved(int to);
CTextInput *leftInput, *rightInput;
void setAmountText(std::string text, bool left);
void setAmount(int value, bool left);
void sliderMoved(int value);
void apply();
public:
/**
* creature - displayed creature
* callback(leftAmount, rightAmount) - function to call on close
* leftMin, rightMin - minimal amount of creatures in each stack
* leftAmount, rightAmount - amount of creatures in each stack
*/
CSplitWindow(const CCreature * creature, boost::function<void(int, int)> callback,
int leftMin, int rightMin, int leftAmount, int rightAmount);
};
/// Raised up level windowe where you can select one out of two skills
@ -896,11 +898,11 @@ public:
friend class CArtPlace;
};
class CGarrisonHolder : public virtual CIntObject
class CGarrisonHolder
{
public:
CGarrisonHolder();
virtual void updateGarrisons(){};
virtual void updateGarrisons(){}
};
class CWindowWithGarrison : public virtual CGarrisonHolder
@ -1076,7 +1078,7 @@ public:
};
/// Hill fort is the building where you can upgrade units
class CHillFortWindow : public CWindowWithGarrison
class CHillFortWindow : public CIntObject, public CWindowWithGarrison
{
public:

View File

@ -43,121 +43,6 @@ using namespace CSDL_Ext;
Graphics * graphics = NULL;
SDL_Surface * Graphics::drawHeroInfoWin(const InfoAboutHero &curh)
{
char buf[15];
blueToPlayersAdv(hInfo,curh.owner);
SDL_Surface * ret = SDL_DisplayFormat(hInfo);
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
printAt(curh.name,75,13,FONT_SMALL,Colors::Cornsilk,ret); //name
blitAt(graphics->portraitLarge[curh.portrait],11,12,ret); //portrait
//army
for (ArmyDescriptor::const_iterator i = curh.army.begin(); i!=curh.army.end();i++)
{
blitAt(graphics->smallImgs[i->second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
if(curh.details)
{
SDL_itoa((*i).second.count,buf,10);
printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,Colors::Cornsilk,ret);
}
else
{
printAtMiddle(VLC->generaltexth->arraytxt[174 + 3*(i->second.count)],slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,Colors::Cornsilk,ret);
}
}
if(curh.details)
{
for (int i = 0; i < GameConstants::PRIMARY_SKILLS; i++)
{
SDL_itoa(curh.details->primskills[i], buf, 10);
printAtMiddle(buf,84+28*i,70,FONT_SMALL,Colors::Cornsilk,ret);
}
//mana points
SDL_itoa(curh.details->mana,buf,10);
printAtMiddle(buf,167,108,FONT_TINY,Colors::Cornsilk,ret);
blitAt(morale22->ourImages[curh.details->morale+3].bitmap,14,84,ret); //luck
blitAt(luck22->ourImages[curh.details->morale+3].bitmap,14,101,ret); //morale
}
return ret;
}
SDL_Surface * Graphics::drawHeroInfoWin(const CGHeroInstance * curh)
{
InfoAboutHero iah;
iah.initFromHero(curh, true);
return drawHeroInfoWin(iah);
}
SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh)
{
InfoAboutTown iah;
iah.initFromTown(curh, true);
return drawTownInfoWin(iah);
}
SDL_Surface * Graphics::drawTownInfoWin( const InfoAboutTown & curh )
{
char buf[10];
blueToPlayersAdv(tInfo,curh.owner);
SDL_Surface * ret = SDL_DisplayFormat(tInfo);
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
printAt(curh.name,75,12,FONT_SMALL,Colors::Cornsilk,ret); //name
int pom = curh.fortLevel - 1; if(pom<0) pom = 3; //fort pic id
blitAt(forts->ourImages[pom].bitmap,115,42,ret); //fort
for (ArmyDescriptor::const_iterator i=curh.army.begin(); i!=curh.army.end();i++)
{
//if(!i->second.second)
// continue;
blitAt(graphics->smallImgs[(*i).second.type->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
if(curh.details)
{
// Show exact creature amount.
SDL_itoa((*i).second.count,buf,10);
printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,Colors::Cornsilk,ret);
}
else
{
// Show only a rough amount for creature stacks.
// TODO: Deal with case when no information at all about size shold be presented.
std::string roughAmount = curh.obj->getRoughAmount(i->first);
printAtMiddle(roughAmount,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+41,FONT_TINY,Colors::Cornsilk,ret);
}
}
//blit town icon
if (curh.tType) {
pom = curh.tType->typeID*2;
if (!curh.fortLevel)
pom += GameConstants::F_NUMBER*2;
if(curh.built)
pom++;
blitAt(bigTownPic->ourImages[pom].bitmap,13,13,ret);
}
if(curh.details)
{
//hall level icon
if((pom=curh.details->hallLevel) >= 0)
blitAt(halls->ourImages[pom].bitmap, 77, 42, ret);
if (curh.details->goldIncome >= 0) {
SDL_itoa(curh.details->goldIncome, buf, 10); //gold income
printAtMiddle(buf, 167, 70, FONT_TINY, Colors::Cornsilk, ret);
}
if(curh.details->garrisonedHero) //garrisoned hero icon
blitAt(graphics->heroInGarrison,158,87,ret);
}
return ret;
}
void Graphics::loadPaletteAndColors()
{
std::string pals = bitmaph->getTextFile("PLAYERS.PAL", FILE_OTHER);
@ -249,14 +134,6 @@ void Graphics::initializeBattleGraphics()
}
Graphics::Graphics()
{
slotsPos.push_back(std::pair<int,int>(44,82));
slotsPos.push_back(std::pair<int,int>(80,82));
slotsPos.push_back(std::pair<int,int>(116,82));
slotsPos.push_back(std::pair<int,int>(26,131));
slotsPos.push_back(std::pair<int,int>(62,131));
slotsPos.push_back(std::pair<int,int>(98,131));
slotsPos.push_back(std::pair<int,int>(134,131));
CDefHandler *smi, *smi2;
std::vector<Task> tasks; //preparing list of graphics to load

View File

@ -46,7 +46,6 @@ public:
SDL_Surface * hInfo, *tInfo; //hero and town infobox bgs
SDL_Surface *heroInGarrison; //icon for town infobox
std::vector<std::pair<int, int> > slotsPos; //creature slot positions in infoboxes
CDefEssential *luck22, *luck30, *luck42, *luck82,
*morale22, *morale30, *morale42, *morale82,
*halls, *forts, *bigTownPic;
@ -102,10 +101,6 @@ public:
void loadHeroPortraits();
void loadWallPositions();
void loadErmuToPicture();
SDL_Surface * drawHeroInfoWin(const InfoAboutHero &curh);
SDL_Surface * drawHeroInfoWin(const CGHeroInstance * curh);
SDL_Surface * drawTownInfoWin(const InfoAboutTown & curh);
SDL_Surface * drawTownInfoWin(const CGTownInstance * curh);
SDL_Surface * getPic(int ID, bool fort=true, bool builded=false); //returns small picture of town: ID=-1 - blank; -2 - border; -3 - random
void blueToPlayersAdv(SDL_Surface * sur, int player); //replaces blue interface colour with a color of player
void loadTrueType();

View File

@ -41,6 +41,8 @@ vcmiclient_SOURCES = \
./UIFramework/SDL_Extensions.cpp \
./UIFramework/SDL_Extensions.h \
./UIFramework/SDL_Pixels.h \
AdventureMapClasses.cpp \
AdventureMapClasses.h \
CAdvmapInterface.cpp \
CAdvmapInterface.h \
CAnimation.cpp \

View File

@ -72,6 +72,7 @@ am_vcmiclient_OBJECTS = vcmiclient-CCallback.$(OBJEXT) \
vcmiclient-Geometries.$(OBJEXT) \
vcmiclient-CCursorHandler.$(OBJEXT) \
vcmiclient-SDL_Extensions.$(OBJEXT) \
vcmiclient-AdventureMapClasses.$(OBJEXT) \
vcmiclient-CAdvmapInterface.$(OBJEXT) \
vcmiclient-CAnimation.$(OBJEXT) \
vcmiclient-CBitmapHandler.$(OBJEXT) \
@ -344,6 +345,8 @@ vcmiclient_SOURCES = \
./UIFramework/SDL_Extensions.cpp \
./UIFramework/SDL_Extensions.h \
./UIFramework/SDL_Pixels.h \
AdventureMapClasses.cpp \
AdventureMapClasses.h \
CAdvmapInterface.cpp \
CAdvmapInterface.h \
CAnimation.cpp \
@ -481,6 +484,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-AdventureMapClasses.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-CAdvmapInterface.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-CAnimation.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-CBattleAnimations.Po@am__quote@
@ -691,6 +695,20 @@ vcmiclient-SDL_Extensions.obj: ./UIFramework/SDL_Extensions.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -c -o vcmiclient-SDL_Extensions.obj `if test -f './UIFramework/SDL_Extensions.cpp'; then $(CYGPATH_W) './UIFramework/SDL_Extensions.cpp'; else $(CYGPATH_W) '$(srcdir)/./UIFramework/SDL_Extensions.cpp'; fi`
vcmiclient-AdventureMapClasses.o: AdventureMapClasses.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -MT vcmiclient-AdventureMapClasses.o -MD -MP -MF $(DEPDIR)/vcmiclient-AdventureMapClasses.Tpo -c -o vcmiclient-AdventureMapClasses.o `test -f 'AdventureMapClasses.cpp' || echo '$(srcdir)/'`AdventureMapClasses.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vcmiclient-AdventureMapClasses.Tpo $(DEPDIR)/vcmiclient-AdventureMapClasses.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='AdventureMapClasses.cpp' object='vcmiclient-AdventureMapClasses.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -c -o vcmiclient-AdventureMapClasses.o `test -f 'AdventureMapClasses.cpp' || echo '$(srcdir)/'`AdventureMapClasses.cpp
vcmiclient-AdventureMapClasses.obj: AdventureMapClasses.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -MT vcmiclient-AdventureMapClasses.obj -MD -MP -MF $(DEPDIR)/vcmiclient-AdventureMapClasses.Tpo -c -o vcmiclient-AdventureMapClasses.obj `if test -f 'AdventureMapClasses.cpp'; then $(CYGPATH_W) 'AdventureMapClasses.cpp'; else $(CYGPATH_W) '$(srcdir)/AdventureMapClasses.cpp'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vcmiclient-AdventureMapClasses.Tpo $(DEPDIR)/vcmiclient-AdventureMapClasses.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='AdventureMapClasses.cpp' object='vcmiclient-AdventureMapClasses.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -c -o vcmiclient-AdventureMapClasses.obj `if test -f 'AdventureMapClasses.cpp'; then $(CYGPATH_W) 'AdventureMapClasses.cpp'; else $(CYGPATH_W) '$(srcdir)/AdventureMapClasses.cpp'; fi`
vcmiclient-CAdvmapInterface.o: CAdvmapInterface.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -MT vcmiclient-CAdvmapInterface.o -MD -MP -MF $(DEPDIR)/vcmiclient-CAdvmapInterface.Tpo -c -o vcmiclient-CAdvmapInterface.o `test -f 'CAdvmapInterface.cpp' || echo '$(srcdir)/'`CAdvmapInterface.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vcmiclient-CAdvmapInterface.Tpo $(DEPDIR)/vcmiclient-CAdvmapInterface.Po

View File

@ -793,12 +793,9 @@ void SetSelection::applyCl(CClient *cl)
void ShowInInfobox::applyCl(CClient *cl)
{
CComponent sc(c);
text.toString(sc.description);
INTERFACE_CALL_IF_PRESENT(player,showComp, sc);
INTERFACE_CALL_IF_PRESENT(player,showComp, c, text.toString());
}
void AdvmapSpellCast::applyCl(CClient *cl)
{
cl->invalidatePaths();

View File

@ -120,12 +120,12 @@ void CGuiHandler::totalRedraw()
void CGuiHandler::updateTime()
{
int tv = th.getDiff();
int ms = mainFPSmng->getElapsedMilliseconds();
std::list<CIntObject*> hlp = timeinterested;
for (std::list<CIntObject*>::iterator i=hlp.begin(); i != hlp.end();i++)
{
if(!vstd::contains(timeinterested,*i)) continue;
(*i)->onTimer(tv);
(*i)->onTimer(ms);
}
}
@ -470,14 +470,18 @@ void CFramerateManager::init()
void CFramerateManager::framerateDelay()
{
ui32 currentTicks = SDL_GetTicks();
this->timeElapsed = currentTicks - this->lastticks;
timeElapsed = currentTicks - lastticks;
// FPS is higher than it should be, then wait some time
if (this->timeElapsed < this->rateticks)
if (timeElapsed < rateticks)
{
SDL_Delay(ceil(this->rateticks) - this->timeElapsed);
SDL_Delay(ceil(this->rateticks) - timeElapsed);
}
currentTicks = SDL_GetTicks();
this->fps = ceil(1000.0 / this->timeElapsed);
this->lastticks = SDL_GetTicks();
fps = ceil(1000.0 / timeElapsed);
//recalculate timeElapsed for external calls via getElapsed()
timeElapsed = currentTicks - lastticks;
lastticks = SDL_GetTicks();
}

View File

@ -34,7 +34,7 @@ public:
CFramerateManager(int rate); // initializes the manager with a given fps rate
void init(); // needs to be called directly before the main game loop to reset the internal timer
void framerateDelay(); // needs to be called every game update cycle
double getElapsedSeconds() const { return this->timeElapsed / 1000; }
ui32 getElapsedMilliseconds() const {return this->timeElapsed;}
};
// Handles GUI logic and drawing
@ -42,7 +42,6 @@ class CGuiHandler
{
public:
CFramerateManager * mainFPSmng; //to keep const framerate
CStopWatch th;
std::list<IShowActivatable *> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
IStatusBar * statusbar;

View File

@ -1,4 +1,4 @@
#include "StdInc.h"
#include "../StdInc.h"
#include "CIntObject.h"
#include "CGuiHandler.h"
#include "SDL_Extensions.h"
@ -138,7 +138,7 @@ CIntObject::CIntObject(int used_, Point pos_):
void CIntObject::setTimer(int msToTrigger)
{
if (!active & TIME )
if (!(active & TIME))
activateTimer();
toNextTick = timerDelay = msToTrigger;
used |= TIME;
@ -170,10 +170,7 @@ void CIntObject::showAll(SDL_Surface * to)
if(children[i]->recActions & SHOWALL)
children[i]->showAll(to);
}//FIXME: needed?
/*
else
show(to);*/
}
}
void CIntObject::activate()
@ -183,7 +180,10 @@ void CIntObject::activate()
if ((used | GENERAL) == active_m)
return;
else
{
tlog1 << "Warning: IntObject re-activated with mismatching used and active\n";
deactivate(); //FIXME: better to avoid such possibility at all
}
}
active_m |= GENERAL;
@ -307,14 +307,14 @@ void CIntObject::printToLoc( const std::string & text, int x, int y, EFonts font
void CIntObject::addUsedEvents(ui16 newActions)
{
if (active_m)
activate(newActions & ~used);
activate(~used & newActions);
used |= newActions;
}
void CIntObject::removeUsedEvents(ui16 newActions)
{
if (active_m)
deactivate(newActions & used);
deactivate(used & newActions);
used &= ~newActions;
}
@ -373,12 +373,12 @@ void CIntObject::addChild(CIntObject *child, bool adjustPosition /*= false*/)
{
if (vstd::contains(children, child))
{
tlog4<< "Warning: object already assigned to this parent!\n";
// tlog4<< "Warning: object already assigned to this parent!\n";
return;
}
if (child->parent_m)
{
tlog4<< "Warning: object already has parent!\n";
// tlog4<< "Warning: object already has parent!\n";
child->parent_m->removeChild(child, adjustPosition);
}
children.push_back(child);
@ -412,15 +412,20 @@ void CIntObject::drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &col
void CIntObject::redraw()
{
if (parent_m && (type & REDRAW_PARENT))
//currently most of calls come from active objects so this check won't affect them
//it should fix glitches when called by inactive elements located below active window
if (active)
{
parent_m->redraw();
}
else
{
showAll(screenBuf);
if(screenBuf != screen)
showAll(screen);
if (parent_m && (type & REDRAW_PARENT))
{
parent_m->redraw();
}
else
{
showAll(screenBuf);
if(screenBuf != screen)
showAll(screen);
}
}
}

View File

@ -5,6 +5,7 @@
#include "SDL_Extensions.h"
#include "../Graphics.h"
#include "../CAnimation.h"
#include "CCursorHandler.h"
#include "../CGameInfo.h"
#include "../../CCallback.h"
#include "../CConfigHandler.h"
@ -702,7 +703,7 @@ CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int
OBJ_CONSTRUCTION_CAPTURING_ALL;
setAmount(amount);
addUsedEvents(LCLICK);
addUsedEvents(LCLICK | KEYBOARD | WHEEL);
strongInterest = true;
@ -804,9 +805,11 @@ void CSlider::keyPressed(const SDL_KeyboardEvent & key)
switch(key.keysym.sym)
{
case SDLK_UP:
case SDLK_LEFT:
moveDest = value - 1;
break;
case SDLK_DOWN:
case SDLK_RIGHT:
moveDest = value + 1;
break;
case SDLK_PAGEUP:
@ -902,13 +905,14 @@ CIntObject * CTabbedInt::getItem()
CListBox::CListBox(CreateFunc create, DestroyFunc destroy, Point Pos, Point ItemOffset, size_t VisibleSize,
size_t TotalSize, size_t InitialPos, int Slider, Rect SliderPos):
CObjectList(create, destroy),
first(InitialPos),
totalSize(TotalSize),
itemOffset(ItemOffset)
CObjectList(create, destroy),
first(InitialPos),
totalSize(TotalSize),
itemOffset(ItemOffset),
slider(nullptr)
{
pos += Pos;
items.resize(VisibleSize, NULL);
items.resize(VisibleSize, nullptr);
if (Slider & 1)
{
@ -947,14 +951,48 @@ void CListBox::reset()
updatePositions();
}
void CListBox::resize(size_t newSize)
{
totalSize = newSize;
if (slider)
slider->setAmount(totalSize);
reset();
}
size_t CListBox::size()
{
return totalSize;
}
CIntObject * CListBox::getItem(size_t which)
{
if (which < first || which > first + items.size() || which > totalSize)
return nullptr;
size_t i=first;
for (auto iter = items.begin(); iter != items.end(); iter++, i++)
if( i == which)
return *iter;
return nullptr;
}
size_t CListBox::getIndexOf(CIntObject *item)
{
size_t i=first;
for (auto iter = items.begin(); iter != items.end(); iter++, i++)
if(*iter == item)
return i;
return size_t(-1);
}
void CListBox::scrollTo(size_t which)
{
//scroll up
if (first > which)
moveToPos(which);
//scroll down
else if (first + items.size() <= which)
moveToPos(which - items.size());
else if (first + items.size() <= which && which < totalSize)
moveToPos(which - items.size() + 1);
}
void CListBox::moveToPos(size_t which)
@ -1006,7 +1044,12 @@ void CListBox::moveToPrev()
}
}
std::list<CIntObject*> CListBox::getItems()
size_t CListBox::getPos()
{
return first;
}
const std::list<CIntObject *> &CListBox::getItems()
{
return items;
}
@ -1081,30 +1124,6 @@ std::string CStatusBar::getCurrent()
return current;
}
void CList::clickLeft(tribool down, bool previousState)
{
};
CList::CList(int Size)
:SIZE(Size)
{
addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD | MOVE);
}
void CList::fixPos()
{
if(selected < 0) //no selection, do nothing
return;
if(selected < from) //scroll up
from = selected;
else if(from + SIZE <= selected)
from = selected - SIZE + 1;
vstd::amin(from, size() - SIZE);
vstd::amax(from, 0);
draw(screen);
}
void CHoverableArea::hover (bool on)
{
if (on)
@ -1159,14 +1178,8 @@ void LRClickableAreaWText::init()
void CLabel::showAll(SDL_Surface * to)
{
CIntObject::showAll(to);
std::string *hlpText = NULL; //if NULL, text field will be used
if(ignoreLeadingWhitespace)
{
hlpText = new std::string(text);
boost::trim_left(*hlpText);
}
std::string &toPrint = hlpText ? *hlpText : text;
std::string toPrint = visibleText();
if(!toPrint.length())
return;
@ -1188,6 +1201,14 @@ CLabel::CLabel(int x, int y, EFonts Font /*= FONT_SMALL*/, EAlignment Align, con
pos.h = graphics->fonts[font]->height;
}
std::string CLabel::visibleText()
{
std::string ret = text;
if(ignoreLeadingWhitespace)
boost::trim_left(ret);
return ret;
}
void CLabel::setTxt(const std::string &Txt)
{
text = Txt;
@ -1375,6 +1396,21 @@ void CGStatusBar::calcOffset()
}
}
CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB):
CLabel(Pos.x, Pos.y, font, CENTER),
cb(CB)
{
type |= REDRAW_PARENT;
focus = false;
pos.h = Pos.h;
pos.w = Pos.w;
textOffset = Point(pos.w/2, pos.h/2);
captureAllKeys = true;
bg = nullptr;
addUsedEvents(LCLICK | KEYBOARD);
giveFocus();
}
CTextInput::CTextInput( const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList<void(const std::string &)> &CB )
:cb(CB)
{
@ -1406,11 +1442,9 @@ CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf)
giveFocus();
}
void CTextInput::showAll(SDL_Surface * to)
std::string CTextInput::visibleText()
{
CIntObject::showAll(to);
const std::string toPrint = focus ? text + "_" : text;
CSDL_Ext::printAt(toPrint, pos.x, pos.y, FONT_SMALL, Colors::Cornsilk, to);
return focus ? text + "_" : text;
}
void CTextInput::clickLeft( tribool down, bool previousState )
@ -1431,43 +1465,89 @@ void CTextInput::keyPressed( const SDL_KeyboardEvent & key )
return;
}
std::string oldText = text;
switch(key.keysym.sym)
{
case SDLK_BACKSPACE:
if(text.size())
if(!text.empty())
text.resize(text.size()-1);
break;
default:
char c = key.keysym.unicode; //TODO 16-/>8
static const std::string forbiddenChars = "<>:\"/\\|?*"; //if we are entering a filename, some special characters won't be allowed
if(!vstd::contains(forbiddenChars,c) && std::isprint(c))
text += c;
text += key.keysym.unicode; //TODO 16-/>8
break;
}
redraw();
cb(text);
filters(text, oldText);
if (text != oldText)
{
redraw();
cb(text);
}
}
void CTextInput::setText( const std::string &nText, bool callCb )
void CTextInput::setTxt( const std::string &nText, bool callCb )
{
text = nText;
redraw();
CLabel::setTxt(nText);
if(callCb)
cb(text);
}
CTextInput::~CTextInput()
{
}
bool CTextInput::captureThisEvent(const SDL_KeyboardEvent & key)
{
if(key.keysym.sym == SDLK_RETURN || key.keysym.sym == SDLK_KP_ENTER)
return false;
//this should allow all non-printable keys to go through (for example arrows)
if (key.keysym.unicode < ' ')
return false;
return true;
}
void CTextInput::filenameFilter(std::string & text, const std::string &)
{
static const std::string forbiddenChars = "<>:\"/\\|?*"; //if we are entering a filename, some special characters won't be allowed
size_t pos;
while ((pos = text.find_first_of(forbiddenChars)) != std::string::npos)
text.erase(pos, 1);
}
void CTextInput::numberFilter(std::string & text, const std::string & oldText, int minValue, int maxValue)
{
assert(minValue < maxValue);
if (text.empty())
text = "0";
size_t pos = 0;
if (text[0] == '-') //allow '-' sign as first symbol only
pos++;
while (pos < text.size())
{
if (text[pos] < '0' || text[pos] > '9')
{
text = oldText;
return; //new text is not number.
}
pos++;
}
try
{
int value = boost::lexical_cast<int>(text);
if (value < minValue)
text = boost::lexical_cast<std::string>(minValue);
else if (value > maxValue)
text = boost::lexical_cast<std::string>(maxValue);
}
catch(boost::bad_lexical_cast &)
{
//Should never happen. Unless I missed some cases
tlog0 << "Warning: failed to convert "<< text << " to number!\n";
text = oldText;
}
}
CFocusable::CFocusable()
{
focusables.push_back(this);
@ -1511,23 +1591,29 @@ void CFocusable::moveFocus()
}
CWindowObject::CWindowObject(std::string imageName, int options_, Point centerAt):
CIntObject(options_ & RCLICK_POPUP ? RCLICK : 0, Point()),
CIntObject(getUsedEvents(options_), Point()),
options(options_),
background(createBg(imageName, options & PLAYER_COLORED))
{
assert(parent == nullptr); //Safe to remove, but windows should not have parent
if (options & RCLICK_POPUP)
CCS->curh->hide();
if (background)
pos = background->center(centerAt);
}
CWindowObject::CWindowObject(std::string imageName, int options_):
CIntObject(options & RCLICK_POPUP ? RCLICK : 0, Point()),
CIntObject(getUsedEvents(options_), Point()),
options(options_),
background(createBg(imageName, options & PLAYER_COLORED))
{
assert(parent == nullptr); //Safe to remove, but windows should not have parent
if (options & RCLICK_POPUP)
CCS->curh->hide();
if (background)
pos = background->center();
}
@ -1545,6 +1631,13 @@ CPicture * CWindowObject::createBg(std::string imageName, bool playerColored)
return image;
}
int CWindowObject::getUsedEvents(int options)
{
if (options & RCLICK_POPUP)
return RCLICK;
return 0;
}
void CWindowObject::showAll(SDL_Surface *to)
{
CIntObject::showAll(to);
@ -1559,6 +1652,6 @@ void CWindowObject::close()
void CWindowObject::clickRight(tribool down, bool previousState)
{
if((!down || indeterminate(down)))
close();
close();
CCS->curh->show();
}

View File

@ -273,8 +273,18 @@ public:
//recreate all visible items
void reset();
//change or get total amount of items in the list
void resize(size_t newSize);
size_t size();
//return item with index which or null if not present
CIntObject * getItem(size_t which);
//return currently active items
std::list< CIntObject * > getItems();
const std::list< CIntObject * > & getItems();
//get index of this item. -1 if not found
size_t getIndexOf(CIntObject * item);
//scroll list to make item which visible
void scrollTo(size_t which);
@ -283,11 +293,12 @@ public:
void moveToPos(size_t which);
void moveToNext();
void moveToPrev();
size_t getPos();
};
/// Status bar which is shown at the bottom of the in-game screens
class CStatusBar
: public CIntObject, public IStatusBar
class CStatusBar : public CIntObject, public IStatusBar
{
public:
SDL_Surface * bg; //background
@ -304,9 +315,11 @@ public:
};
/// Label which shows text
class CLabel
: public virtual CIntObject
class CLabel : public virtual CIntObject
{
protected:
virtual std::string visibleText();
public:
EAlignment alignment;
EFonts font;
@ -397,46 +410,29 @@ public:
};
/// Text input box where players can enter text
class CTextInput
: public CLabel, public CFocusable
class CTextInput : public CLabel, public CFocusable
{
protected:
std::string visibleText();
public:
CFunctionList<void(const std::string &)> cb;
CFunctionList<void(std::string &, const std::string &)> filters;
void setTxt(const std::string &nText, bool callCb = false);
void setText(const std::string &nText, bool callCb = false);
CTextInput(const Rect &Pos, EFonts font, const CFunctionList<void(const std::string &)> &CB);
CTextInput(const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList<void(const std::string &)> &CB);
CTextInput(const Rect &Pos, SDL_Surface *srf = NULL);
~CTextInput();
void showAll(SDL_Surface * to) OVERRIDE;
void clickLeft(tribool down, bool previousState) OVERRIDE;
void keyPressed(const SDL_KeyboardEvent & key) OVERRIDE;
bool captureThisEvent(const SDL_KeyboardEvent & key) OVERRIDE;
};
void clickLeft(tribool down, bool previousState) override;
void keyPressed(const SDL_KeyboardEvent & key) override;
bool captureThisEvent(const SDL_KeyboardEvent & key) override;
/// Listbox UI Element
class CList : public CIntObject
{
public:
SDL_Surface * bg; //background bitmap
CDefHandler *arrup, *arrdo; //button arrows for scrolling list
SDL_Surface *empty, *selection;
SDL_Rect arrupp, arrdop; //positions of arrows
int posw, posh; //position width/height
int selected, //id of selected position, <0 if none
from;
const int SIZE; //size of list
tribool pressed; //true=up; false=down; indeterminate=none
CList(int Size = 5); //c-tor
void clickLeft(tribool down, bool previousState);
virtual void mouseMoved (const SDL_MouseMotionEvent & sEvent)=0; //call-in
virtual void genList()=0;
virtual void select(int which)=0;
virtual void draw(SDL_Surface * to)=0;
virtual int size() = 0; //how many elements do we have
void fixPos(); //scrolls list, so the selection will be visible
//Filter that will block all characters not allowed in filenames
static void filenameFilter(std::string &text, const std::string & oldText);
//Filter that will allow only input of numbers in range min-max (min-max are allowed)
//min-max should be set via something like boost::bind
static void numberFilter(std::string &text, const std::string & oldText, int minValue, int maxValue);
};
/// Shows a text by moving the mouse cursor over the object
@ -468,9 +464,10 @@ public:
/// Basic class for windows
// TODO: status bar?
class CWindowObject : public virtual CIntObject
class CWindowObject : public CIntObject
{
CPicture * createBg(std::string imageName, bool playerColored);
int getUsedEvents(int options);
int options;

View File

@ -995,7 +995,10 @@ void CSDL_Ext::SDL_PutPixelWithoutRefresh(SDL_Surface *ekran, const int & x, con
void CSDL_Ext::SDL_PutPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A /*= 255*/)
{
if(x >= 0 && x < ekran->w && y >= 0 && y < ekran->h)
const SDL_Rect & rect = ekran->clip_rect;
if(x >= rect.x && x < rect.w + rect.x
&& y >= rect.y && y < rect.h + rect.y)
SDL_PutPixelWithoutRefresh(ekran, x, y, R, G, B, A);
}

View File

@ -25,7 +25,8 @@ CCreatureHandler::CCreatureHandler()
VLC->creh = this;
// Set the faction alignments to the defaults:
// Good: Castle, Rampart, Tower // Evil: Inferno, Necropolis, Dungeon
// Good: Castle, Rampart, Tower
// Evil: Inferno, Necropolis, Dungeon
// Neutral: Stronghold, Fortess, Conflux
factionAlignments += 1, 1, 1, -1, -1, -1, 0, 0, 0;
doubledCreatures += 4, 14, 20, 28, 44, 60, 70, 72, 85, 86, 100, 104; //according to Strategija
@ -39,29 +40,29 @@ CCreatureHandler::CCreatureHandler()
int CCreature::getQuantityID(const int & quantity)
{
if (quantity<5)
return 0;
if (quantity<10)
return 1;
if (quantity<20)
if (quantity<10)
return 2;
if (quantity<50)
if (quantity<20)
return 3;
if (quantity<100)
if (quantity<50)
return 4;
if (quantity<250)
if (quantity<100)
return 5;
if (quantity<500)
if (quantity<250)
return 6;
if (quantity<1000)
if (quantity<500)
return 7;
return 8;
if (quantity<1000)
return 8;
return 9;
}
int CCreature::estimateCreatureCount(ui32 countID)
{
static const int creature_count[] = { 3, 8, 15, 35, 75, 175, 375, 750, 2500 };
static const int creature_count[] = { 0, 3, 8, 15, 35, 75, 175, 375, 750, 2500 };
if (countID > 8)
if (countID > 9)
assert("Wrong countID!");
return creature_count[countID];

View File

@ -221,7 +221,10 @@ ui64 CCreatureSet::getPower (TSlot slot) const
}
std::string CCreatureSet::getRoughAmount (TSlot slot) const
{
return VLC->generaltexth->arraytxt[174 + 3*CCreature::getQuantityID(getStackCount(slot))];
int quantity = CCreature::getQuantityID(getStackCount(slot));
if (quantity)
return VLC->generaltexth->arraytxt[174 + 3*CCreature::getQuantityID(getStackCount(slot))];
return "";
}
int CCreatureSet::stacksCount() const
@ -897,7 +900,12 @@ void CStackInstance::setArmyObj(const CArmedInstance *ArmyObj)
std::string CStackInstance::getQuantityTXT(bool capitalized /*= true*/) const
{
return VLC->generaltexth->arraytxt[174 + getQuantityID()*3 + 2 - capitalized];
int quantity = getQuantityID();
if (quantity)
return VLC->generaltexth->arraytxt[174 + quantity*3 - 1 - capitalized];
else
return "";
}
bool CStackInstance::valid(bool allowUnrandomized) const

View File

@ -137,62 +137,6 @@ public:
}
} *objCaller = NULL;
InfoAboutTown::InfoAboutTown()
{
tType = NULL;
details = NULL;
fortLevel = 0;
owner = -1;
}
InfoAboutTown::~InfoAboutTown()
{
delete details;
}
void InfoAboutTown::initFromTown( const CGTownInstance *t, bool detailed )
{
obj = t;
army = ArmyDescriptor(t->getUpperArmy(), detailed);
built = t->builded;
fortLevel = t->fortLevel();
name = t->name;
tType = t->town;
owner = t->tempOwner;
if(detailed)
{
//include details about hero
details = new Details;
details->goldIncome = t->dailyIncome();
details->customRes = vstd::contains(t->builtBuildings, 15);
details->hallLevel = t->hallLevel();
details->garrisonedHero = t->garrisonHero;
}
//TODO: adjust undetailed info about army to our count of thieves guilds
}
void InfoAboutTown::initFromGarrison(const CGGarrison *garr, bool detailed)
{
obj = garr;
fortLevel = 0;
army = ArmyDescriptor(garr, detailed);
name = VLC->generaltexth->names[33]; // "Garrison"
owner = garr->tempOwner;
built = false;
tType = NULL;
// Show detailed info only to owning player.
if(detailed)
{
details = new InfoAboutTown::Details;
details->customRes = false;
details->garrisonedHero = false;
details->goldIncome = -1;
details->hallLevel = -1;
}
}
void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst) const
{
int type = txt.first, ser = txt.second;
@ -2590,32 +2534,69 @@ std::string PlayerState::nodeName() const
// }
// }
InfoAboutHero::InfoAboutHero()
InfoAboutArmy::InfoAboutArmy():
owner(GameConstants::NEUTRAL_PLAYER)
{}
InfoAboutArmy::InfoAboutArmy(const CArmedInstance *Army, bool detailed)
{
details = NULL;
hclass = NULL;
portrait = -1;
initFromArmy(Army, detailed);
}
InfoAboutHero::InfoAboutHero( const InfoAboutHero & iah )
void InfoAboutArmy::initFromArmy(const CArmedInstance *Army, bool detailed)
{
army = ArmyDescriptor(Army, detailed);
owner = Army->tempOwner;
name = Army->getHoverText();
}
void InfoAboutHero::assign(const InfoAboutHero & iah)
{
InfoAboutArmy::operator = (iah);
details = (iah.details ? new Details(*iah.details) : NULL);
hclass = iah.hclass;
portrait = iah.portrait;
}
InfoAboutHero::InfoAboutHero():
details(nullptr),
hclass(nullptr),
portrait(-1)
{}
InfoAboutHero::InfoAboutHero(const InfoAboutHero & iah):
InfoAboutArmy()
{
assign(iah);
}
InfoAboutHero::InfoAboutHero(const CGHeroInstance *h, bool detailed)
{
initFromHero(h, detailed);
}
InfoAboutHero::~InfoAboutHero()
{
delete details;
}
void InfoAboutHero::initFromHero( const CGHeroInstance *h, bool detailed )
InfoAboutHero & InfoAboutHero::operator=(const InfoAboutHero & iah)
{
if(!h) return;
assign(iah);
return *this;
}
void InfoAboutHero::initFromHero(const CGHeroInstance *h, bool detailed)
{
if(!h)
return;
initFromArmy(h, detailed);
owner = h->tempOwner;
hclass = h->type->heroClass;
name = h->name;
portrait = h->portrait;
army = ArmyDescriptor(h, detailed);
if(detailed)
{
@ -2633,25 +2614,47 @@ void InfoAboutHero::initFromHero( const CGHeroInstance *h, bool detailed )
}
}
void InfoAboutHero::assign( const InfoAboutHero & iah )
InfoAboutTown::InfoAboutTown():
details(nullptr),
tType(nullptr),
built(0),
fortLevel(0)
{
army = iah.army;
details = (iah.details ? new Details(*iah.details) : NULL);
hclass = iah.hclass;
name = iah.name;
owner = iah.owner;
portrait = iah.portrait;
}
InfoAboutHero & InfoAboutHero::operator=( const InfoAboutHero & iah )
InfoAboutTown::InfoAboutTown(const CGTownInstance *t, bool detailed)
{
assign(iah);
return *this;
initFromTown(t, detailed);
}
InfoAboutTown::~InfoAboutTown()
{
delete details;
}
void InfoAboutTown::initFromTown(const CGTownInstance *t, bool detailed)
{
initFromArmy(t, detailed);
army = ArmyDescriptor(t->getUpperArmy(), detailed);
built = t->builded;
fortLevel = t->fortLevel();
name = t->name;
tType = t->town;
ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed) : isDetailed(detailed)
if(detailed)
{
//include details about hero
details = new Details;
details->goldIncome = t->dailyIncome();
details->customRes = vstd::contains(t->builtBuildings, 15);
details->hallLevel = t->hallLevel();
details->garrisonedHero = t->garrisonHero;
}
}
ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed)
: isDetailed(detailed)
{
for(TSlots::const_iterator i = army->Slots().begin(); i != army->Slots().end(); i++)
{
@ -2662,7 +2665,8 @@ ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed) : isDe
}
}
ArmyDescriptor::ArmyDescriptor() : isDetailed(true)
ArmyDescriptor::ArmyDescriptor()
: isDetailed(false)
{
}

View File

@ -76,55 +76,63 @@ struct ArmyDescriptor : public std::map<TSlot, CStackBasicDescriptor>
DLL_LINKAGE int getStrength() const;
};
struct DLL_LINKAGE InfoAboutHero
struct DLL_LINKAGE InfoAboutArmy
{
ui8 owner;
std::string name;
ArmyDescriptor army;
InfoAboutArmy();
InfoAboutArmy(const CArmedInstance *Army, bool detailed);
void initFromArmy(const CArmedInstance *Army, bool detailed);
};
struct DLL_LINKAGE InfoAboutHero : public InfoAboutArmy
{
private:
void assign(const InfoAboutHero & iah);
public:
struct DLL_LINKAGE Details
{
std::vector<int> primskills;
int mana, luck, morale;
std::vector<si32> primskills;
si32 mana, luck, morale;
} *details;
char owner;
const CHeroClass *hclass;
std::string name;
int portrait;
ArmyDescriptor army;
InfoAboutHero();
InfoAboutHero(const InfoAboutHero & iah);
InfoAboutHero & operator=(const InfoAboutHero & iah);
InfoAboutHero(const CGHeroInstance *h, bool detailed);
~InfoAboutHero();
InfoAboutHero & operator=(const InfoAboutHero & iah);
void initFromHero(const CGHeroInstance *h, bool detailed);
};
/// Struct which holds a int information about a town
struct DLL_LINKAGE InfoAboutTown
struct DLL_LINKAGE InfoAboutTown : public InfoAboutArmy
{
struct Details
struct DLL_LINKAGE Details
{
int hallLevel, goldIncome;
si32 hallLevel, goldIncome;
bool customRes;
bool garrisonedHero;
} *details;
const CArmedInstance * obj;
char fortLevel; //0 - none
char owner;
std::string name;
CTown *tType;
bool built;
ArmyDescriptor army; //numbers of creatures are valid only if details
si32 built;
si32 fortLevel; //0 - none
InfoAboutTown();
InfoAboutTown(const CGTownInstance *t, bool detailed);
~InfoAboutTown();
void initFromTown(const CGTownInstance *t, bool detailed);
void initFromGarrison(const CGGarrison *garr, bool detailed);
};
// typedef si32 TResourceUnit;

View File

@ -78,7 +78,7 @@ ui8 * CLodHandler::giveFile(std::string fname, LodFileType type, int * length)
result = -1;
if(result<0)
{
tlog1<<"Error in file reading: " << myDir << "/" << ourEntry.name << std::endl;
tlog1<<"Error in file reading: " << myDir << "/" << ourEntry.realName << std::endl;
delete[] outp;
return NULL;
}

View File

@ -783,7 +783,7 @@ bool CGameInfoCallback::getTownInfo( const CGObjectInstance *town, InfoAboutTown
if(town->ID == GameConstants::TOWNI_TYPE)
dest.initFromTown(static_cast<const CGTownInstance *>(town), detailed);
else if(town->ID == 33 || town->ID == 219)
dest.initFromGarrison(static_cast<const CGGarrison *>(town), detailed);
dest.initFromArmy(static_cast<const CArmedInstance *>(town), detailed);
else
return false;
return true;

View File

@ -118,5 +118,5 @@ public:
virtual void playerBlocked(int reason){}; //reason: 0 - upcoming battle
virtual void gameOver(ui8 player, bool victory){}; //player lost or won the game
virtual void playerStartsTurn(ui8 player){};
virtual void showComp(const CComponent &comp) {}; //display component in the advmapint infobox
virtual void showComp(const Component &comp, std::string message) {}; //display component in the advmapint infobox
};