mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Fixes for adventure AI: battles where AI is the attacker should work, fixed drawing AI heroes under FoW.
Restructured thread structure: no new thread on yourturn, instead of that introduced update() method called by thread dispatching GUI events. Further changes are planned.
This commit is contained in:
parent
e05c73d6ea
commit
01831e912a
@ -39,7 +39,7 @@ ui8 side; //who made this action: false - left, true - right player
|
||||
*/
|
||||
CBattleLogic::CBattleLogic(ICallback *cb, CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side) :
|
||||
m_iCurrentTurn(-2),
|
||||
m_bIsAttacker(false),
|
||||
m_bIsAttacker(!side),
|
||||
m_cb(cb),
|
||||
m_army1(army1),
|
||||
m_army2(army2),
|
||||
@ -261,7 +261,7 @@ BattleAction CBattleLogic::MakeDecision(int stackID)
|
||||
MakeStatistics(stackID);
|
||||
|
||||
list<int> creatures;
|
||||
int additionalInfo;
|
||||
int additionalInfo = 0; //?
|
||||
|
||||
if (m_bEnemyDominates)
|
||||
{
|
||||
|
@ -710,138 +710,140 @@ void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
|
||||
int turns = pnode->turns;
|
||||
amin(turns, 3);
|
||||
|
||||
if(LOCPLINT->adventureInt->selection->ID == TOWNI_TYPE)
|
||||
if(LOCPLINT->adventureInt->selection)
|
||||
{
|
||||
if(obj)
|
||||
if(LOCPLINT->adventureInt->selection->ID == TOWNI_TYPE)
|
||||
{
|
||||
if(obj->ID == TOWNI_TYPE)
|
||||
if(obj)
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 3);
|
||||
if(obj->ID == TOWNI_TYPE)
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 3);
|
||||
}
|
||||
else if(obj->ID == HEROI_TYPE)
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 2);
|
||||
}
|
||||
}
|
||||
else if(obj->ID == HEROI_TYPE)
|
||||
else
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 2);
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(LOCPLINT->adventureInt->selection->ID == HEROI_TYPE)
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
}
|
||||
else if(LOCPLINT->adventureInt->selection->ID == HEROI_TYPE)
|
||||
{
|
||||
const CGHeroInstance *h = static_cast<const CGHeroInstance *>(LOCPLINT->adventureInt->selection);
|
||||
if(obj)
|
||||
{
|
||||
if(obj->ID == HEROI_TYPE)
|
||||
const CGHeroInstance *h = static_cast<const CGHeroInstance *>(LOCPLINT->adventureInt->selection);
|
||||
if(obj)
|
||||
{
|
||||
if(obj->tempOwner != LOCPLINT->playerID) //enemy hero TODO: allies
|
||||
if(obj->ID == HEROI_TYPE)
|
||||
{
|
||||
if(obj->tempOwner != LOCPLINT->playerID) //enemy hero TODO: allies
|
||||
{
|
||||
if(accessible)
|
||||
CGI->curh->changeGraphic(0, 5 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
else //our hero
|
||||
{
|
||||
if(LOCPLINT->adventureInt->selection == obj)
|
||||
CGI->curh->changeGraphic(0, 2);
|
||||
else if(accessible)
|
||||
CGI->curh->changeGraphic(0, 8 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 2);
|
||||
}
|
||||
}
|
||||
else if(obj->ID == TOWNI_TYPE)
|
||||
{
|
||||
if(obj->tempOwner != LOCPLINT->playerID) //enemy town TODO: allies
|
||||
{
|
||||
if(accessible) {
|
||||
const CGTownInstance* townObj = dynamic_cast<const CGTownInstance*>(obj);
|
||||
|
||||
// Show movement cursor for unguarded enemy towns, otherwise attack cursor.
|
||||
if (townObj && townObj->army.slots.empty())
|
||||
CGI->curh->changeGraphic(0, 9 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 5 + turns*6);
|
||||
|
||||
} else {
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
}
|
||||
else //our town
|
||||
{
|
||||
if(accessible)
|
||||
CGI->curh->changeGraphic(0, 9 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 3);
|
||||
}
|
||||
}
|
||||
else if(obj->ID == 54) //monster
|
||||
{
|
||||
if(accessible)
|
||||
CGI->curh->changeGraphic(0, 5 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
else //our hero
|
||||
else if(obj->ID == 8) //boat
|
||||
{
|
||||
if(LOCPLINT->adventureInt->selection == obj)
|
||||
CGI->curh->changeGraphic(0, 2);
|
||||
else if(accessible)
|
||||
CGI->curh->changeGraphic(0, 8 + turns*6);
|
||||
if(accessible)
|
||||
CGI->curh->changeGraphic(0, 6 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 2);
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
}
|
||||
else if(obj->ID == TOWNI_TYPE)
|
||||
{
|
||||
if(obj->tempOwner != LOCPLINT->playerID) //enemy town TODO: allies
|
||||
else if (obj->ID == 33 || obj->ID == 219) // Garrison
|
||||
{
|
||||
if(accessible) {
|
||||
const CGTownInstance* townObj = dynamic_cast<const CGTownInstance*>(obj);
|
||||
if (accessible) {
|
||||
const CGGarrison* garrObj = dynamic_cast<const CGGarrison*>(obj);
|
||||
|
||||
// Show movement cursor for unguarded enemy towns, otherwise attack cursor.
|
||||
if (townObj && townObj->army.slots.empty())
|
||||
CGI->curh->changeGraphic(0, 9 + turns*6);
|
||||
else
|
||||
// Show battle cursor for guarded enemy garrisons, otherwise movement cursor.
|
||||
if (garrObj && garrObj->tempOwner != LOCPLINT->playerID
|
||||
&& !garrObj->army.slots.empty())
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 5 + turns*6);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 9 + turns*6);
|
||||
}
|
||||
} else {
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
}
|
||||
else //our town
|
||||
else
|
||||
{
|
||||
if(accessible)
|
||||
CGI->curh->changeGraphic(0, 9 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 3);
|
||||
}
|
||||
}
|
||||
else if(obj->ID == 54) //monster
|
||||
{
|
||||
if(accessible)
|
||||
CGI->curh->changeGraphic(0, 5 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
else if(obj->ID == 8) //boat
|
||||
{
|
||||
if(accessible)
|
||||
CGI->curh->changeGraphic(0, 6 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
else if (obj->ID == 33 || obj->ID == 219) // Garrison
|
||||
{
|
||||
if (accessible) {
|
||||
const CGGarrison* garrObj = dynamic_cast<const CGGarrison*>(obj);
|
||||
|
||||
// Show battle cursor for guarded enemy garrisons, otherwise movement cursor.
|
||||
if (garrObj && garrObj->tempOwner != LOCPLINT->playerID
|
||||
&& !garrObj->army.slots.empty())
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 5 + turns*6);
|
||||
if(pnode->land)
|
||||
CGI->curh->changeGraphic(0, 9 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 28 + turns);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGI->curh->changeGraphic(0, 9 + turns*6);
|
||||
}
|
||||
} else {
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else //no objs
|
||||
{
|
||||
if(accessible)
|
||||
{
|
||||
if(pnode->land)
|
||||
CGI->curh->changeGraphic(0, 9 + turns*6);
|
||||
{
|
||||
if(LOCPLINT->cb->getTileInfo(h->getPosition(false))->tertype != TerrainTile::water)
|
||||
CGI->curh->changeGraphic(0, 4 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 7 + turns*6); //anchor
|
||||
}
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 28 + turns);
|
||||
CGI->curh->changeGraphic(0, 6 + turns*6);
|
||||
}
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
}
|
||||
else //no objs
|
||||
{
|
||||
if(accessible)
|
||||
{
|
||||
if(pnode->land)
|
||||
{
|
||||
if(LOCPLINT->cb->getTileInfo(h->getPosition(false))->tertype != TerrainTile::water)
|
||||
CGI->curh->changeGraphic(0, 4 + turns*6);
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 7 + turns*6); //anchor
|
||||
}
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 6 + turns*6);
|
||||
}
|
||||
else
|
||||
CGI->curh->changeGraphic(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//tlog1 << "Tile " << pom << ": Turns=" << (int)pnode->turns <<" Move:=" << pnode->moveRemains <</* " (from " << ")" << */std::endl;
|
||||
}
|
||||
void CTerrainRect::hover(bool on)
|
||||
@ -1515,7 +1517,6 @@ townList(ADVOPT.tlistSize,ADVOPT.tlistX,ADVOPT.tlistY,ADVOPT.tlistAU,ADVOPT.tlis
|
||||
pos.x = pos.y = 0;
|
||||
pos.w = screen->w;
|
||||
pos.h = screen->h;
|
||||
active = 0;
|
||||
selection = NULL;
|
||||
townList.fun = boost::bind(&CAdvMapInt::selectionChanged,this);
|
||||
LOCPLINT->adventureInt=this;
|
||||
@ -1631,14 +1632,14 @@ void CAdvMapInt::fnextHero()
|
||||
void CAdvMapInt::fendTurn()
|
||||
{
|
||||
LOCPLINT->makingTurn = false;
|
||||
LOCPLINT->cb->endTurn();
|
||||
}
|
||||
|
||||
void CAdvMapInt::activate()
|
||||
{
|
||||
if(active++)
|
||||
if(isActive())
|
||||
{
|
||||
tlog1 << "Error: advmapint already active...\n";
|
||||
active--;
|
||||
return;
|
||||
}
|
||||
screenBuf = screen;
|
||||
@ -1689,12 +1690,6 @@ void CAdvMapInt::deactivate()
|
||||
infoBar.mode=-1;
|
||||
|
||||
LOCPLINT->cingconsole->deactivate();
|
||||
|
||||
if(--active)
|
||||
{
|
||||
tlog1 << "Error: advmapint still active...\n";
|
||||
deactivate();
|
||||
}
|
||||
}
|
||||
void CAdvMapInt::showAll(SDL_Surface *to)
|
||||
{
|
||||
@ -1807,16 +1802,16 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
|
||||
switch(k)
|
||||
{
|
||||
case SDLK_i:
|
||||
if(active)
|
||||
if(isActive())
|
||||
CAdventureOptions::showScenarioInfo();
|
||||
return;
|
||||
case SDLK_s:
|
||||
if(active)
|
||||
if(isActive())
|
||||
GH.pushInt(new CSelectionScreen(saveGame));
|
||||
return;
|
||||
case SDLK_SPACE: //space - try to revisit current object with selected hero
|
||||
{
|
||||
if(!active)
|
||||
if(!isActive())
|
||||
return;
|
||||
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance*>(selection);
|
||||
if(h && key.state == SDL_PRESSED)
|
||||
@ -1829,7 +1824,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
|
||||
return;
|
||||
case SDLK_RETURN:
|
||||
{
|
||||
if(!active || !selection || key.state != SDL_PRESSED)
|
||||
if(!isActive() || !selection || key.state != SDL_PRESSED)
|
||||
return;
|
||||
if(selection->ID == HEROI_TYPE)
|
||||
LOCPLINT->openHeroWindow(static_cast<const CGHeroInstance*>(selection));
|
||||
@ -1883,7 +1878,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
|
||||
k = arrowToNum(SDLKey(k));
|
||||
}
|
||||
|
||||
if(!active || LOCPLINT->ctrlPressed())//ctrl makes arrow move screen, not hero
|
||||
if(!isActive() || LOCPLINT->ctrlPressed())//ctrl makes arrow move screen, not hero
|
||||
break;
|
||||
|
||||
k -= SDLK_KP0 + 1;
|
||||
@ -2003,7 +1998,7 @@ void CAdvMapInt::select(const CArmedInstance *sel )
|
||||
void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
|
||||
{
|
||||
//adventure map scrolling with mouse
|
||||
if(!SDL_GetKeyState(NULL)[SDLK_LCTRL] && active)
|
||||
if(!SDL_GetKeyState(NULL)[SDLK_LCTRL] && isActive())
|
||||
{
|
||||
if(sEvent.x<15)
|
||||
{
|
||||
@ -2040,6 +2035,11 @@ void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
|
||||
}
|
||||
}
|
||||
|
||||
bool CAdvMapInt::isActive()
|
||||
{
|
||||
return active & ~CIntObject.KEYBOARD;
|
||||
}
|
||||
|
||||
CAdventureOptions::CAdventureOptions()
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
@ -138,7 +138,7 @@ public:
|
||||
~CAdvMapInt();
|
||||
|
||||
int3 position; //top left corner of visible map part
|
||||
int player, active;
|
||||
int player;
|
||||
|
||||
|
||||
enum{LEFT=1, RIGHT=2, UP=4, DOWN=8};
|
||||
@ -202,5 +202,6 @@ public:
|
||||
void handleRightClick(std::string text, tribool down, CIntObject * client);
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
bool isActive();
|
||||
};
|
||||
#endif // __CADVMAPINTERFACE_H__
|
||||
|
@ -2327,13 +2327,13 @@ void CBattleInterface::hexLclicked(int whichOne)
|
||||
giveCommand(9,whichOne,activeStack);
|
||||
}
|
||||
}
|
||||
else if(dest->owner != attackingHeroInstance->tempOwner
|
||||
else if(dest->owner != actSt->owner
|
||||
&& LOCPLINT->cb->battleCanShoot(activeStack, whichOne) ) //shooting
|
||||
{
|
||||
CGI->curh->changeGraphic(1, 6); //cursor should be changed
|
||||
giveCommand(7,whichOne,activeStack);
|
||||
}
|
||||
else if(dest->owner != attackingHeroInstance->tempOwner) //attacking
|
||||
else if(dest->owner != actSt->owner) //attacking
|
||||
{
|
||||
const CStack * actStack = LOCPLINT->cb->battleGetStackByID(activeStack);
|
||||
int attackFromHex = -1; //hex from which we will attack chosen stack
|
||||
|
@ -69,7 +69,7 @@ static CClient *client;
|
||||
SDL_Surface *screen = NULL, //main screen surface
|
||||
*screen2 = NULL,//and hlp surface (used to store not-active interfaces layer)
|
||||
*screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
|
||||
static boost::thread *hhh;
|
||||
static boost::thread *mainGUIThread;
|
||||
|
||||
SystemOptions GDefaultOptions;
|
||||
VCMIDirs GVCMIDirs;
|
||||
@ -214,8 +214,8 @@ int main(int argc, char** argv)
|
||||
|
||||
CGI->musich->playMusic(musicBase::mainMenu, -1);
|
||||
|
||||
new CGPreGame; //will set CGP pointer to itself
|
||||
hhh = new boost::thread(&CGPreGame::run, CGP);
|
||||
GH.curInt = new CGPreGame; //will set CGP pointer to itself
|
||||
mainGUIThread = new boost::thread(&CGuiHandler::run, boost::ref(GH));
|
||||
listenForEvents();
|
||||
|
||||
return 0;
|
||||
@ -472,18 +472,18 @@ static void listenForEvents()
|
||||
{
|
||||
if (client)
|
||||
client->stop();
|
||||
if (hhh) {
|
||||
CGP->terminate = true;
|
||||
hhh->join();
|
||||
delete hhh;
|
||||
hhh = NULL;
|
||||
if (mainGUIThread)
|
||||
{
|
||||
GH.terminate = true;
|
||||
mainGUIThread->join();
|
||||
delete mainGUIThread;
|
||||
mainGUIThread = NULL;
|
||||
}
|
||||
delete console;
|
||||
console = NULL;
|
||||
SDL_Delay(750);
|
||||
SDL_Quit();
|
||||
tlog0 << "Ending...\n";
|
||||
|
||||
break;
|
||||
}
|
||||
else if(LOCPLINT && ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
|
||||
@ -501,9 +501,12 @@ static void listenForEvents()
|
||||
delete ev;
|
||||
continue;
|
||||
}
|
||||
else if (ev->type == SDL_USEREVENT && ev->user.code == 2) {
|
||||
else if (ev->type == SDL_USEREVENT && ev->user.code == 2)
|
||||
{
|
||||
client->stop();
|
||||
delete ev;
|
||||
|
||||
GH.curInt = CGP;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -517,6 +520,7 @@ static void listenForEvents()
|
||||
|
||||
void startGame(StartInfo * options)
|
||||
{
|
||||
GH.curInt =NULL;
|
||||
if(gOnlyAI)
|
||||
{
|
||||
for (size_t i =0; i < options->playerInfos.size(); i++)
|
||||
@ -534,22 +538,18 @@ void startGame(StartInfo * options)
|
||||
SDL_PushEvent(&ev);
|
||||
}
|
||||
|
||||
CClient cl;
|
||||
client = new CClient;
|
||||
if(options->mode == 0) //new game
|
||||
{
|
||||
cl.newGame(NULL, options);
|
||||
client->newGame(NULL, options);
|
||||
}
|
||||
else //load game
|
||||
{
|
||||
std::string fname = options->mapname;
|
||||
boost::algorithm::erase_last(fname,".vlgm1");
|
||||
cl.loadGame(fname);
|
||||
client->loadGame(fname);
|
||||
}
|
||||
|
||||
client = &cl;
|
||||
CGI->musich->stopMusic();
|
||||
client->run();
|
||||
LOCPLINT->terminate_cond.waitUntil(true);
|
||||
client->endGame();
|
||||
client = NULL;
|
||||
client->connectionHandler = new boost::thread(&CClient::run, client);
|
||||
}
|
||||
|
@ -40,6 +40,8 @@
|
||||
#include <cmath>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
@ -102,12 +104,16 @@ CPlayerInterface::CPlayerInterface(int Player, int serial)
|
||||
cingconsole = new CInGameConsole;
|
||||
terminate = false;
|
||||
terminate_cond.set(false);
|
||||
firstCall = 1; //if loading will be overwritten in serialize
|
||||
autosaveCount = 0;
|
||||
}
|
||||
CPlayerInterface::~CPlayerInterface()
|
||||
{
|
||||
delete pim;
|
||||
delete showingDialog;
|
||||
delete mainFPSmng;
|
||||
if(adventureInt->active & CIntObject::KEYBOARD)
|
||||
adventureInt->deactivateKeys();
|
||||
delete adventureInt;
|
||||
delete cingconsole;
|
||||
|
||||
@ -135,90 +141,58 @@ void CPlayerInterface::init(ICallback * CB)
|
||||
}
|
||||
void CPlayerInterface::yourTurn()
|
||||
{
|
||||
try
|
||||
LOCPLINT = this;
|
||||
makingTurn = true;
|
||||
|
||||
if(firstCall)
|
||||
{
|
||||
LOCPLINT = this;
|
||||
makingTurn = true;
|
||||
|
||||
static bool firstCall = true;
|
||||
static int autosaveCount = 0;
|
||||
|
||||
if(firstCall)
|
||||
firstCall = false;
|
||||
else
|
||||
LOCPLINT->cb->save("Autosave_" + boost::lexical_cast<std::string>(autosaveCount++ + 1));
|
||||
|
||||
autosaveCount %= 5;
|
||||
|
||||
for(std::map<int,SDL_Surface*>::iterator i=graphics->heroWins.begin(); i!=graphics->heroWins.end();i++) //redraw hero infoboxes
|
||||
SDL_FreeSurface(i->second);
|
||||
graphics->heroWins.clear();
|
||||
std::vector <const CGHeroInstance *> hh = cb->getHeroesInfo(false);
|
||||
for(int i=0;i<hh.size();i++)
|
||||
{
|
||||
SDL_Surface * pom = infoWin(hh[i]);
|
||||
graphics->heroWins.insert(std::pair<int,SDL_Surface*>(hh[i]->subID,pom));
|
||||
}
|
||||
|
||||
/* TODO: This isn't quite right. First day in game should play
|
||||
* NEWDAY. And we don't play NEWMONTH. */
|
||||
int day = cb->getDate(1);
|
||||
if (day != 1)
|
||||
CGI->soundh->playSound(soundBase::newDay);
|
||||
else
|
||||
CGI->soundh->playSound(soundBase::newWeek);
|
||||
|
||||
adventureInt->infoBar.newDay(day);
|
||||
|
||||
//select first hero if available.
|
||||
//TODO: check if hero is slept
|
||||
if(wanderingHeroes.size())
|
||||
adventureInt->select(wanderingHeroes[0]);
|
||||
else
|
||||
adventureInt->select(adventureInt->townList.items[0]);
|
||||
|
||||
adventureInt->showAll(screen);
|
||||
autosaveCount = getLastIndex("Autosave_");
|
||||
GH.pushInt(adventureInt);
|
||||
adventureInt->activateKeys();
|
||||
|
||||
while(makingTurn) // main loop
|
||||
if(firstCall > 0) //new game, not laoded
|
||||
{
|
||||
if (terminate)
|
||||
break;
|
||||
|
||||
pim->lock();
|
||||
|
||||
//if there are any waiting dialogs, show them
|
||||
if(dialogs.size() && !showingDialog->get())
|
||||
{
|
||||
showingDialog->set(true);
|
||||
GH.pushInt(dialogs.front());
|
||||
dialogs.pop_front();
|
||||
}
|
||||
|
||||
GH.updateTime();
|
||||
GH.handleEvents();
|
||||
|
||||
if(!adventureInt->active && adventureInt->scrollingDir) //player forces map scrolling though interface is disabled
|
||||
GH.totalRedraw();
|
||||
else
|
||||
GH.simpleRedraw();
|
||||
|
||||
CGI->curh->draw1();
|
||||
CSDL_Ext::update(screen);
|
||||
CGI->curh->draw2();
|
||||
pim->unlock();
|
||||
SDL_framerateDelay(mainFPSmng);
|
||||
int index = getLastIndex("Newgame_Autosave_");
|
||||
index %= SAVES_COUNT;
|
||||
cb->save("Newgame_Autosave_" + boost::lexical_cast<std::string>(index + 1));
|
||||
}
|
||||
firstCall = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOCPLINT->cb->save("Autosave_" + boost::lexical_cast<std::string>(autosaveCount++ + 1));
|
||||
autosaveCount %= 5;
|
||||
}
|
||||
|
||||
adventureInt->deactivateKeys();
|
||||
GH.popInt(adventureInt);
|
||||
for(std::map<int,SDL_Surface*>::iterator i=graphics->heroWins.begin(); i!=graphics->heroWins.end();i++) //redraw hero infoboxes
|
||||
SDL_FreeSurface(i->second);
|
||||
graphics->heroWins.clear();
|
||||
std::vector <const CGHeroInstance *> hh = cb->getHeroesInfo(false);
|
||||
for(int i=0;i<hh.size();i++)
|
||||
{
|
||||
SDL_Surface * pom = infoWin(hh[i]);
|
||||
graphics->heroWins.insert(std::pair<int,SDL_Surface*>(hh[i]->subID,pom));
|
||||
}
|
||||
|
||||
cb->endTurn();
|
||||
} HANDLE_EXCEPTION;
|
||||
/* TODO: This isn't quite right. First day in game should play
|
||||
* NEWDAY. And we don't play NEWMONTH. */
|
||||
int day = cb->getDate(1);
|
||||
if (day != 1)
|
||||
CGI->soundh->playSound(soundBase::newDay);
|
||||
else
|
||||
CGI->soundh->playSound(soundBase::newWeek);
|
||||
|
||||
if (terminate)
|
||||
terminate_cond.set(true);
|
||||
adventureInt->infoBar.newDay(day);
|
||||
|
||||
//select first hero if available.
|
||||
//TODO: check if hero is slept
|
||||
if(wanderingHeroes.size())
|
||||
adventureInt->select(wanderingHeroes[0]);
|
||||
else
|
||||
adventureInt->select(adventureInt->townList.items[0]);
|
||||
|
||||
adventureInt->showAll(screen);
|
||||
|
||||
GH.curInt = this;
|
||||
}
|
||||
|
||||
inline void subRect(const int & x, const int & y, const int & z, const SDL_Rect & r, const int & hid)
|
||||
@ -1338,6 +1312,7 @@ void CPlayerInterface::serialize( CISer<CLoadFile> &h, const int version )
|
||||
{
|
||||
serializeTempl(h,version);
|
||||
sysOpts.apply();
|
||||
firstCall = -1;
|
||||
}
|
||||
|
||||
void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
|
||||
@ -1526,7 +1501,7 @@ void CPlayerInterface::centerView (int3 pos, int focusTime)
|
||||
LOCPLINT->adventureInt->centerOn (pos);
|
||||
if(focusTime)
|
||||
{
|
||||
bool activeAdv = (GH.topInt() == adventureInt && adventureInt->active);
|
||||
bool activeAdv = (GH.topInt() == adventureInt && adventureInt->isActive());
|
||||
if(activeAdv)
|
||||
adventureInt->deactivate();
|
||||
|
||||
@ -1551,6 +1526,64 @@ bool CPlayerInterface::ctrlPressed() const
|
||||
return SDL_GetKeyState(NULL)[SDLK_LCTRL] || SDL_GetKeyState(NULL)[SDLK_RCTRL];
|
||||
}
|
||||
|
||||
void CPlayerInterface::update()
|
||||
{
|
||||
pim->lock();
|
||||
|
||||
//if there are any waiting dialogs, show them
|
||||
if(dialogs.size() && !showingDialog->get())
|
||||
{
|
||||
showingDialog->set(true);
|
||||
GH.pushInt(dialogs.front());
|
||||
dialogs.pop_front();
|
||||
}
|
||||
|
||||
GH.updateTime();
|
||||
GH.handleEvents();
|
||||
|
||||
if(!adventureInt->isActive() && adventureInt->scrollingDir) //player forces map scrolling though interface is disabled
|
||||
GH.totalRedraw();
|
||||
else
|
||||
GH.simpleRedraw();
|
||||
|
||||
CGI->curh->draw1();
|
||||
CSDL_Ext::update(screen);
|
||||
CGI->curh->draw2();
|
||||
|
||||
pim->unlock();
|
||||
|
||||
SDL_framerateDelay(mainFPSmng);
|
||||
}
|
||||
|
||||
int CPlayerInterface::getLastIndex( std::string namePrefix)
|
||||
{
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::algorithm;
|
||||
|
||||
std::map<std::time_t, int> dates; //save number => datestamp
|
||||
|
||||
directory_iterator enddir;
|
||||
for (directory_iterator dir(DATA_DIR "/Games"); dir!=enddir; dir++)
|
||||
{
|
||||
if(is_regular(dir->status()))
|
||||
{
|
||||
std::string name = dir->path().leaf();
|
||||
if(starts_with(name, namePrefix) && ends_with(name, ".vlgm1"))
|
||||
{
|
||||
char nr = name[namePrefix.size()];
|
||||
if(std::isdigit(nr))
|
||||
{
|
||||
dates[last_write_time(dir->path())] = boost::lexical_cast<int>(nr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(dates.size())
|
||||
return (--dates.end())->second; //return latest file number
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SystemOptions::setMusicVolume( int newVolume )
|
||||
{
|
||||
musicVolume = newVolume;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include "GUIBase.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define sprintf_s snprintf
|
||||
@ -106,7 +107,7 @@ struct SystemOptions
|
||||
|
||||
extern SystemOptions GDefaultOptions; //defined and inited in CMT.cpp, stores default settings loaded with application
|
||||
|
||||
class CPlayerInterface : public CGameInterface
|
||||
class CPlayerInterface : public CGameInterface, public IUpdateable
|
||||
{
|
||||
public:
|
||||
//minor interfaces
|
||||
@ -114,6 +115,9 @@ public:
|
||||
|
||||
boost::recursive_mutex *pim;
|
||||
bool makingTurn; //if player is already making his turn
|
||||
int firstCall; // -1 - just loaded game; 1 - just started game; 0 otherwise
|
||||
int autosaveCount;
|
||||
static const int SAVES_COUNT = 5;
|
||||
|
||||
SystemOptions sysOpts;
|
||||
|
||||
@ -131,8 +135,11 @@ public:
|
||||
|
||||
|
||||
std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
|
||||
|
||||
void update();
|
||||
void recreateWanderingHeroes();
|
||||
const CGHeroInstance *getWHero(int pos); //returns NULL if position is not valid
|
||||
int getLastIndex(std::string namePrefix);
|
||||
|
||||
//overloaded funcs from CGameInterface
|
||||
void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
|
||||
|
@ -122,38 +122,11 @@ void CMenuScreen::moveTo( CMenuScreen *next )
|
||||
GH.pushInt(next);
|
||||
}
|
||||
|
||||
void CGPreGame::run()
|
||||
{
|
||||
GH.handleEvents();
|
||||
|
||||
while(!terminate)
|
||||
{
|
||||
if (GH.listInt.size() == 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CGI->videoh->open("ACREDIT.SMK");
|
||||
#else
|
||||
CGI->videoh->open("ACREDIT.SMK", true, false);
|
||||
#endif
|
||||
GH.pushInt(scrs[mainMenu]);
|
||||
}
|
||||
|
||||
CGI->curh->draw1();
|
||||
SDL_Flip(screen);
|
||||
CGI->curh->draw2();
|
||||
SDL_Delay(20); //give time for other apps
|
||||
GH.topInt()->show(screen);
|
||||
GH.updateTime();
|
||||
GH.handleEvents();
|
||||
}
|
||||
}
|
||||
|
||||
CGPreGame::CGPreGame()
|
||||
{
|
||||
GH.defActionsDef = 63;
|
||||
CGP = this;
|
||||
mainbg = BitmapHandler::loadBitmap("ZPIC1005.bmp");
|
||||
terminate = false;
|
||||
|
||||
for(int i = 0; i < ARRAY_COUNT(scrs); i++)
|
||||
scrs[i] = new CMenuScreen((EState)i);
|
||||
@ -193,6 +166,26 @@ void CGPreGame::disposeGraphics()
|
||||
SDL_FreeSurface(nTown);
|
||||
}
|
||||
|
||||
void CGPreGame::update()
|
||||
{
|
||||
if (GH.listInt.size() == 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CGI->videoh->open("ACREDIT.SMK");
|
||||
#else
|
||||
CGI->videoh->open("ACREDIT.SMK", true, false);
|
||||
#endif
|
||||
GH.pushInt(scrs[mainMenu]);
|
||||
}
|
||||
|
||||
CGI->curh->draw1();
|
||||
SDL_Flip(screen);
|
||||
CGI->curh->draw2();
|
||||
GH.topInt()->show(screen);
|
||||
GH.updateTime();
|
||||
GH.handleEvents();
|
||||
}
|
||||
|
||||
CSelectionScreen::CSelectionScreen( EState Type )
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
@ -212,7 +212,7 @@ public:
|
||||
~CScenarioInfo();
|
||||
};
|
||||
|
||||
class CGPreGame : public CIntObject
|
||||
class CGPreGame : public CIntObject, public IUpdateable
|
||||
{
|
||||
public:
|
||||
SDL_Surface *mainbg;
|
||||
@ -222,10 +222,9 @@ public:
|
||||
CDefHandler *bonuses;
|
||||
CDefHandler *victory, *loss;
|
||||
|
||||
bool terminate;
|
||||
|
||||
CGPreGame();
|
||||
~CGPreGame();
|
||||
void update();
|
||||
void run();
|
||||
void openSel(EState type);
|
||||
void loadGraphics();
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
|
||||
void CClient::init()
|
||||
{
|
||||
connectionHandler = NULL;
|
||||
pathInfo = NULL;
|
||||
applier = new CCLApplier;
|
||||
IObjectInterface::cb = this;
|
||||
@ -124,17 +125,14 @@ void CClient::waitForMoveAndSend(int color)
|
||||
}HANDLE_EXCEPTION
|
||||
tlog1 << "We should not be here!" << std::endl;
|
||||
}
|
||||
|
||||
void CClient::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
CPack *pack;
|
||||
while(1)
|
||||
while(!terminate)
|
||||
{
|
||||
if (terminate) {
|
||||
break;
|
||||
}
|
||||
|
||||
//get the package from the server
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(*serv->rmx);
|
||||
@ -143,7 +141,8 @@ void CClient::run()
|
||||
tlog5 << "\treceived server message of type " << typeid(*pack).name() << std::endl;
|
||||
}
|
||||
|
||||
if (terminate) {
|
||||
if (terminate)
|
||||
{
|
||||
delete pack;
|
||||
break;
|
||||
}
|
||||
@ -174,6 +173,7 @@ void CClient::stop()
|
||||
// Tell the network thread and interface thread to reach a stable state
|
||||
terminate = true;
|
||||
LOCPLINT->terminate = true;
|
||||
endGame();
|
||||
}
|
||||
|
||||
void CClient::save(const std::string & fname)
|
||||
@ -190,6 +190,10 @@ void CClient::save(const std::string & fname)
|
||||
void CClient::endGame()
|
||||
{
|
||||
tlog0 << "\n\nEnding current game!" << std::endl;
|
||||
GH.curInt = NULL;
|
||||
GH.topInt()->deactivate();
|
||||
GH.listInt.clear();
|
||||
GH.objsToBlit.clear();
|
||||
|
||||
delete CGI->mh;
|
||||
CGI->mh = NULL;
|
||||
@ -197,6 +201,7 @@ void CClient::endGame()
|
||||
delete CGI->state;
|
||||
CGI->state = NULL;
|
||||
|
||||
LOCPLINT = NULL;
|
||||
while (!playerint.empty())
|
||||
{
|
||||
delete playerint.begin()->second;
|
||||
@ -208,7 +213,8 @@ void CClient::endGame()
|
||||
delete cb;
|
||||
}
|
||||
|
||||
if (serv) {
|
||||
if (serv)
|
||||
{
|
||||
tlog3 << "Connection has been requested to be closed.\n";
|
||||
boost::unique_lock<boost::mutex>(*serv->wmx);
|
||||
*serv << &CloseServer();
|
||||
@ -219,6 +225,10 @@ void CClient::endGame()
|
||||
serv = NULL;
|
||||
tlog3 << "Our socket has been closed." << std::endl;
|
||||
}
|
||||
|
||||
connectionHandler->join();
|
||||
delete connectionHandler;
|
||||
connectionHandler = NULL;
|
||||
}
|
||||
|
||||
void CClient::loadGame( const std::string & fname )
|
||||
|
@ -81,7 +81,8 @@ public:
|
||||
void run();
|
||||
void stop();
|
||||
|
||||
bool terminate; // tell to terminate
|
||||
bool terminate; // tell to terminate
|
||||
boost::thread *connectionHandler; //thread running run() method
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//from IGameCallback
|
||||
|
@ -331,6 +331,32 @@ void CGuiHandler::fakeMouseMove()
|
||||
handleMoveInterested(sme);
|
||||
}
|
||||
|
||||
void CGuiHandler::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while(!terminate)
|
||||
{
|
||||
if(curInt)
|
||||
curInt->update();
|
||||
SDL_Delay(20); //give time for other apps
|
||||
}
|
||||
} HANDLE_EXCEPTION
|
||||
}
|
||||
|
||||
CGuiHandler::CGuiHandler()
|
||||
:lastClick(-500, -500)
|
||||
{
|
||||
curInt = NULL;
|
||||
current = NULL;
|
||||
terminate = false;
|
||||
}
|
||||
|
||||
CGuiHandler::~CGuiHandler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CIntObject::activateLClick()
|
||||
{
|
||||
GH.lclickable.push_front(this);
|
||||
@ -462,6 +488,8 @@ CIntObject::CIntObject()
|
||||
pos.y = parent->pos.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
void CIntObject::show( SDL_Surface * to )
|
||||
|
@ -287,6 +287,13 @@ public:
|
||||
virtual ~IShowActivable(){}; //d-tor
|
||||
};
|
||||
|
||||
class IUpdateable
|
||||
{
|
||||
public:
|
||||
virtual void update()=0;
|
||||
virtual ~IUpdateable(){}; //d-tor
|
||||
};
|
||||
|
||||
class CIntObject : public IShowActivable //interface object
|
||||
{
|
||||
public:
|
||||
@ -440,10 +447,15 @@ public:
|
||||
std::vector<IShowable*> objsToBlit;
|
||||
|
||||
SDL_Event * current; //current event
|
||||
IUpdateable *curInt;
|
||||
|
||||
Point lastClick;
|
||||
unsigned lastClickTime;
|
||||
bool terminate;
|
||||
|
||||
CGuiHandler();
|
||||
~CGuiHandler();
|
||||
void run();
|
||||
void totalRedraw(); //forces total redraw (using showAll)
|
||||
void simpleRedraw(); //update only top interface and draw background from buffer
|
||||
void popInt(IShowActivable *top); //removes given interface from the top and activates next
|
||||
|
@ -150,7 +150,18 @@ void RemoveObject::applyCl( CClient *cl )
|
||||
void TryMoveHero::applyFirstCl( CClient *cl )
|
||||
{
|
||||
CGHeroInstance *h = GS(cl)->getHero(id);
|
||||
if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK)
|
||||
|
||||
//check if playerint will have the knowledge about movement - if not, directly update maphandler
|
||||
for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
|
||||
{
|
||||
if(i->first >= PLAYER_LIMIT)
|
||||
continue;
|
||||
PlayerState &p = GS(cl)->players[i->first];
|
||||
if((p.fogOfWarMap[start.x-1][start.y][start.z] || p.fogOfWarMap[end.x-1][end.y][end.z]) && p.human)
|
||||
humanKnows = true;
|
||||
}
|
||||
|
||||
if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK || !humanKnows)
|
||||
CGI->mh->removeObject(h);
|
||||
|
||||
|
||||
@ -179,11 +190,17 @@ void TryMoveHero::applyCl( CClient *cl )
|
||||
for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
|
||||
{
|
||||
if(i->first >= PLAYER_LIMIT) continue;
|
||||
if(GS(cl)->players[i->first].fogOfWarMap[start.x-1][start.y][start.z] || GS(cl)->players[i->first].fogOfWarMap[end.x-1][end.y][end.z])
|
||||
PlayerState &p = GS(cl)->players[i->first];
|
||||
if(p.fogOfWarMap[start.x-1][start.y][start.z] || p.fogOfWarMap[end.x-1][end.y][end.z])
|
||||
{
|
||||
i->second->heroMoved(*this);
|
||||
}
|
||||
}
|
||||
|
||||
if(!humanKnows) //maphandler didn't get update from playerint, do it now
|
||||
{ //TODO: restructure nicely
|
||||
CGI->mh->printObject(h);
|
||||
}
|
||||
}
|
||||
|
||||
void SetGarrisons::applyCl( CClient *cl )
|
||||
@ -538,7 +555,7 @@ void PlayerBlocked::applyCl( CClient *cl )
|
||||
|
||||
void YourTurn::applyCl( CClient *cl )
|
||||
{
|
||||
boost::thread(boost::bind(&CGameInterface::yourTurn,cl->playerint[player]));
|
||||
INTERFACE_CALL_IF_PRESENT(player,yourTurn);
|
||||
}
|
||||
|
||||
void SaveGame::applyCl(CClient *cl)
|
||||
|
@ -187,7 +187,8 @@ void CLodHandler::init(std::string lodFile, std::string dirName)
|
||||
|
||||
LOD.open(lodFile.c_str(), std::ios::in | std::ios::binary);
|
||||
|
||||
if (!LOD.is_open()) {
|
||||
if (!LOD.is_open())
|
||||
{
|
||||
tlog1 << "Cannot open " << lodFile << std::endl;
|
||||
return;
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ struct RemoveObject : public CPackForClient //500
|
||||
};
|
||||
struct TryMoveHero : public CPackForClient //501
|
||||
{
|
||||
TryMoveHero(){type = 501;};
|
||||
TryMoveHero(){type = 501;humanKnows=false;};
|
||||
void applyFirstCl(CClient *cl);
|
||||
void applyCl(CClient *cl);
|
||||
void applyGs(CGameState *gs);
|
||||
@ -420,6 +420,8 @@ struct TryMoveHero : public CPackForClient //501
|
||||
int3 start, end;
|
||||
std::set<int3> fowRevealed; //revealed tiles
|
||||
|
||||
bool humanKnows; //used locally during applying to client
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & id & result & start & end & movePoints & fowRevealed;
|
||||
|
Loading…
Reference in New Issue
Block a user