From 307c20e7dc46cd4c11d1257e2ee281f8cd0467f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Thu, 24 Sep 2009 13:23:52 +0000 Subject: [PATCH] * fixed crash on clicking on the map frame * battle settings will be stored * fixed calculating battle casualties * fixed crash when clicking on enemy stack without moving mouse when we receive action * fixed issue when splitting stack to the hero with only one creatures --- AI/GeniusAI/CGeniusAI.cpp | 2 +- client/CAdvmapInterface.cpp | 15 +++- client/CBattleInterface.cpp | 162 ++++++++++++++++++++++++++---------- client/CBattleInterface.h | 18 +--- client/CPlayerInterface.cpp | 77 +++++------------ client/CPlayerInterface.h | 31 +++---- client/GUIBase.cpp | 34 +++++--- client/GUIBase.h | 4 +- client/GUIClasses.cpp | 29 ++++--- hch/CObjectHandler.cpp | 7 +- lib/CGameState.cpp | 14 ++-- lib/CGameState.h | 2 +- lib/NetPacks.h | 2 +- server/CGameHandler.cpp | 4 +- 14 files changed, 225 insertions(+), 176 deletions(-) diff --git a/AI/GeniusAI/CGeniusAI.cpp b/AI/GeniusAI/CGeniusAI.cpp index 08706ed26..ae2f6b14b 100644 --- a/AI/GeniusAI/CGeniusAI.cpp +++ b/AI/GeniusAI/CGeniusAI.cpp @@ -1029,7 +1029,7 @@ void CGeniusAI::battleEnd(BattleResult *br) case 2: std::cout << "It's a draw." << std::endl;break; }; cout << "lost "; - for(std::set >::iterator i = br->casualties[0].begin(); i !=br->casualties[0].end();i++) + for(std::map::iterator i = br->casualties[0].begin(); i !=br->casualties[0].end();i++) cout << i->second << " " << VLC->creh->creatures[i->first].namePl << endl; delete m_battleLogic; diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index 0c13cc4ec..83f7bdc5b 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -471,7 +471,7 @@ void CTerrainRect::clickLeft(tribool down, bool previousState) if ((down==false) || indeterminate(down)) return; int3 mp = whichTileIsIt(); - if ((mp.x<0) || (mp.y<0)) + if (mp.x<0 || mp.y<0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y) return; std::vector < const CGObjectInstance * > bobjs = LOCPLINT->cb->getBlockingObjs(mp), //blocking objects at tile @@ -660,11 +660,20 @@ void CTerrainRect::clickRight(tribool down, bool previousState) } void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent) { - int3 pom=LOCPLINT->adventureInt->verifyPos(whichTileIsIt(sEvent.x,sEvent.y)); - if (pom!=curHoveredTile) + int3 tHovered = whichTileIsIt(sEvent.x,sEvent.y); + int3 pom = LOCPLINT->adventureInt->verifyPos(tHovered); + + if(tHovered != pom) //tile outside the map + { + CGI->curh->changeGraphic(0, 0); + return; + } + + if (pom != curHoveredTile) curHoveredTile=pom; else return; + std::vector temp = LOCPLINT->cb->getObjDescriptions(pom); if (temp.size()) { diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index 0a4b622c2..59b7e4862 100644 --- a/client/CBattleInterface.cpp +++ b/client/CBattleInterface.cpp @@ -47,7 +47,6 @@ extern SDL_Surface * screen; extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16; extern SDL_Color zwykly; -BattleSettings CBattleInterface::settings; CondSh CBattleInterface::animsAreDisplayed; struct CMP_stack2 @@ -481,7 +480,7 @@ void CDefenceAnim::nextFrame() if(!owner->creAnims[stackID]->onLastFrameInGroup()) { - if( owner->creAnims[stackID]->getType() == 5 && (owner->animCount+1)%(4/CBattleInterface::settings.animSpeed)==0 + if( owner->creAnims[stackID]->getType() == 5 && (owner->animCount+1)%(4/LOCPLINT->sysOpts.animSpeed)==0 && !owner->creAnims[stackID]->onLastFrameInGroup() ) { owner->creAnims[stackID]->incrementFrame(); @@ -694,7 +693,7 @@ void CBattleMoveStart::nextFrame() } else { - if((owner->animCount+1)%(4/CBattleInterface::settings.animSpeed)==0) + if((owner->animCount+1)%(4/LOCPLINT->sysOpts.animSpeed)==0) owner->creAnims[stackID]->incrementFrame(); } } @@ -1047,7 +1046,7 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C //create stack queue bool embedQueue = screen->h < 700; queue = new CStackQueue(embedQueue); - if(!embedQueue && settings.showQueue) + if(!embedQueue && LOCPLINT->sysOpts.showQueue) { pos.y += queue->pos.h / 2; //center whole window queue->moveTo(Point(pos.x, pos.y - queue->pos.h)); @@ -1306,21 +1305,24 @@ CBattleInterface::~CBattleInterface() void CBattleInterface::setPrintCellBorders(bool set) { - settings.printCellBorders = set; + LOCPLINT->sysOpts.printCellBorders = set; + LOCPLINT->sysOpts.settingsChanged(); redrawBackgroundWithHexes(activeStack); GH.totalRedraw(); } void CBattleInterface::setPrintStackRange(bool set) { - settings.printStackRange = set; + LOCPLINT->sysOpts.printStackRange = set; + LOCPLINT->sysOpts.settingsChanged(); redrawBackgroundWithHexes(activeStack); GH.totalRedraw(); } void CBattleInterface::setPrintMouseShadow(bool set) { - settings.printMouseShadow = set; + LOCPLINT->sysOpts.printMouseShadow = set; + LOCPLINT->sysOpts.settingsChanged(); } void CBattleInterface::activate() @@ -1345,7 +1347,7 @@ void CBattleInterface::activate() attackingHero->activate(); if(defendingHero) defendingHero->activate(); - if(settings.showQueue) + if(LOCPLINT->sysOpts.showQueue) queue->activate(); LOCPLINT->cingconsole->activate(); @@ -1373,7 +1375,7 @@ void CBattleInterface::deactivate() attackingHero->deactivate(); if(defendingHero) defendingHero->deactivate(); - if(settings.showQueue) + if(LOCPLINT->sysOpts.showQueue) queue->deactivate(); LOCPLINT->cingconsole->deactivate(); @@ -1399,7 +1401,7 @@ void CBattleInterface::show(SDL_Surface * to) { //showing background blitAt(background, pos.x, pos.y, to); - if(settings.printCellBorders) + if(LOCPLINT->sysOpts.printCellBorders) { CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, to, &pos); } @@ -1436,7 +1438,7 @@ void CBattleInterface::show(SDL_Surface * to) std::set shaded = spToCast.rangeInHexes(b, schoolLevel); for(std::set::iterator it = shaded.begin(); it != shaded.end(); ++it) //for spells with range greater then one hex { - if(settings.printMouseShadow && (*it % BFIELD_WIDTH != 0) && (*it % BFIELD_WIDTH != 16)) + if(LOCPLINT->sysOpts.printMouseShadow && (*it % BFIELD_WIDTH != 0) && (*it % BFIELD_WIDTH != 16)) { int x = 14 + ((*it/BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(*it%BFIELD_WIDTH) + pos.x; int y = 86 + 42 * (*it/BFIELD_WIDTH) + pos.y; @@ -1444,7 +1446,7 @@ void CBattleInterface::show(SDL_Surface * to) } } } - else if(settings.printMouseShadow) //when not casting spell + else if(LOCPLINT->sysOpts.printMouseShadow) //when not casting spell { int x = 14 + ((b/BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(b%BFIELD_WIDTH) + pos.x; int y = 86 + 42 * (b/BFIELD_WIDTH) + pos.y; @@ -1479,7 +1481,7 @@ void CBattleInterface::show(SDL_Surface * to) int x = ((obstacles[b].pos/BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(obstacles[b].pos%BFIELD_WIDTH) + pos.x + shift.first; int y = 86 + 42 * (obstacles[b].pos/BFIELD_WIDTH) + pos.y + shift.second; std::vector &images = idToObstacle[obstacles[b].ID]->ourImages; //reference to animation of obstacle - blitAt(images[((animCount+1)/(4/settings.animSpeed))%images.size()].bitmap, x, y, to); + blitAt(images[((animCount+1)/(4/LOCPLINT->sysOpts.animSpeed))%images.size()].bitmap, x, y, to); } //showing hero animations @@ -1597,7 +1599,7 @@ void CBattleInterface::show(SDL_Surface * to) Rect posWithQueue = Rect(pos.x, pos.y, 800, 600); - if(settings.showQueue) + if(LOCPLINT->sysOpts.showQueue) { if(!queue->embedded) { @@ -1622,10 +1624,12 @@ void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key) { if(key.keysym.sym == SDLK_q && key.state == SDL_PRESSED) { - if(settings.showQueue) //hide queue + if(LOCPLINT->sysOpts.showQueue) //hide queue hideQueue(); else showQueue(); + + LOCPLINT->sysOpts.settingsChanged(); } else if(key.keysym.sym == SDLK_ESCAPE && spellDestSelectMode) { @@ -2154,9 +2158,20 @@ void CBattleInterface::giveCommand(ui8 action, ui16 tile, ui32 stack, si32 addit ba->destinationTile = tile; ba->stackNumber = stack; ba->additionalInfo = additional; - givenCommand->setn(ba); + + //some basic validations + switch(action) + { + case 6: + assert(LOCPLINT->cb->battleGetStackByPos(additional)); //stack to attack must exist + case 2: case 7: case 9: + assert(tile < BFIELD_SIZE); + break; + } + myTurn = false; activeStack = -1; + givenCommand->setn(ba); } bool CBattleInterface::isTileAttackable(const int & number) const @@ -2616,20 +2631,23 @@ void CBattleInterface::displayEffect(ui32 effect, int destTile) void CBattleInterface::setAnimSpeed(int set) { - settings.animSpeed = set; + LOCPLINT->sysOpts.animSpeed = set; + LOCPLINT->sysOpts.settingsChanged(); } int CBattleInterface::getAnimSpeed() const { - return settings.animSpeed; + return LOCPLINT->sysOpts.animSpeed; + LOCPLINT->sysOpts.settingsChanged(); } void CBattleInterface::activateStack() { activeStack = stackToActivate; - queue->update(); stackToActivate = -1; myTurn = true; + queue->update(); + GH.fakeMouseMove(); redrawBackgroundWithHexes(activeStack); bWait->block(vstd::contains(LOCPLINT->cb->battleGetStackByID(activeStack)->state,WAITING)); //block waiting button if stack has been already waiting @@ -2648,7 +2666,7 @@ void CBattleInterface::activateStack() float CBattleInterface::getAnimSpeedMultiplier() const { - switch(settings.animSpeed) + switch(LOCPLINT->sysOpts.animSpeed) { case 1: return 3.5f; @@ -2679,7 +2697,7 @@ void CBattleInterface::showAliveStack(int ID, const std::map & stac const CStack &curStack = stacks.find(ID)->second; int animType = creAnims[ID]->getType(); - int affectingSpeed = settings.animSpeed; + int affectingSpeed = LOCPLINT->sysOpts.animSpeed; if(animType == 1 || animType == 2) //standing stacks should not stand faster :) affectingSpeed = 2; if(animType == 3 || animType == 7 || animType == 8 || animType == 9 || animType == 10 || animType == 11 || animType == 12 || animType == 13) //defend & attack should be slower @@ -2836,10 +2854,10 @@ void CBattleInterface::redrawBackgroundWithHexes(int activeStack) //preparating background graphic with hexes and shaded hexes blitAt(background, 0, 0, backgroundWithHexes); - if(settings.printCellBorders) + if(LOCPLINT->sysOpts.printCellBorders) CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, backgroundWithHexes, NULL); - if(settings.printStackRange) + if(LOCPLINT->sysOpts.printStackRange) { for(size_t m=0; mactive) - queue->deactivate(); + LOCPLINT->sysOpts.showQueue = false; + + queue->deactivate(); if(!queue->embedded) { @@ -2959,9 +2977,9 @@ void CBattleInterface::hideQueue() void CBattleInterface::showQueue() { - settings.showQueue = true; - //if(!queue->active) - queue->activate(); + LOCPLINT->sysOpts.showQueue = true; + + queue->activate(); if(!queue->embedded) { @@ -2970,6 +2988,75 @@ void CBattleInterface::showQueue() } } +void CBattleInterface::startAction(const BattleAction* action) +{ + const CStack *stack = LOCPLINT->cb->battleGetStackByID(action->stackNumber); + + if(stack) + { + queue->update(); + } + else + { + assert(action->actionType == 1); //only cast spell is valid action without acting stack number + } + + if(action->actionType == 2 + || (action->actionType == 6 && action->destinationTile != stack->position)) + { + moveStarted = true; + if(creAnims[action->stackNumber]->framesInGroup(20)) + { + pendingAnims.push_back(std::make_pair(new CBattleMoveStart(this, action->stackNumber), false)); + } + } + + + deactivate(); + + char txt[400]; + + if(action->actionType == 1) + { + if(action->side) + defendingHero->setPhase(4); + else + attackingHero->setPhase(4); + return; + } + if(!stack) + { + tlog1<<"Something wrong with stackNumber in actionStarted. Stack number: "<stackNumber<actionType) + { + case 3: //defend + txtid = 120; + break; + case 8: //wait + txtid = 136; + break; + case 11: //bad morale + txtid = -34; //negative -> no separate singular/plural form + displayEffect(30,stack->position); + break; + } + + if(txtid > 0 && stack->amount != 1) + txtid++; //move to plural text + else if(txtid < 0) + txtid = -txtid; + + if(txtid) + { + sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(), (stack->amount != 1) ? stack->creature->namePl.c_str() : stack->creature->nameSing.c_str(), 0); + console->addText(txt); + } +} + void CBattleHero::show(SDL_Surface *to) { //animation of flag @@ -3441,7 +3528,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect { int xPos = 235 - (br.casualties[step].size()*32 + (br.casualties[step].size() - 1)*10)/2; //increment by 42 with each picture int yPos = 344 + step*97; - for(std::set >::const_iterator it=br.casualties[step].begin(); it!=br.casualties[step].end(); ++it) + for(std::map::const_iterator it=br.casualties[step].begin(); it!=br.casualties[step].end(); ++it) { blitAt(graphics->smallImgs[it->first], xPos, yPos, background); std::ostringstream amount; @@ -3554,11 +3641,11 @@ CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInt graphics->blueToPlayersAdv(background, LOCPLINT->playerID); viewGrid = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintCellBorders, owner, true), boost::bind(&CBattleInterface::setPrintCellBorders, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[427].first)(3,CGI->generaltexth->zelp[427].first), CGI->generaltexth->zelp[427].second, false, "sysopchk.def", NULL, 185, 140, false); - viewGrid->select(owner->settings.printCellBorders); + viewGrid->select(LOCPLINT->sysOpts.printCellBorders); movementShadow = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintStackRange, owner, true), boost::bind(&CBattleInterface::setPrintStackRange, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[428].first)(3,CGI->generaltexth->zelp[428].first), CGI->generaltexth->zelp[428].second, false, "sysopchk.def", NULL, 185, 173, false); - movementShadow->select(owner->settings.printStackRange); + movementShadow->select(LOCPLINT->sysOpts.printStackRange); mouseShadow = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintMouseShadow, owner, true), boost::bind(&CBattleInterface::setPrintMouseShadow, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[429].first)(3,CGI->generaltexth->zelp[429].first), CGI->generaltexth->zelp[429].second, false, "sysopchk.def", NULL, 185, 207, false); - mouseShadow->select(owner->settings.printMouseShadow); + mouseShadow->select(LOCPLINT->sysOpts.printMouseShadow); animSpeeds = new CHighlightableButtonsGroup(0); animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[422].first),CGI->generaltexth->zelp[422].second, "sysopb9.def",188, 309, 1); @@ -3891,13 +3978,4 @@ CStackQueue::StackBox::~StackBox() void CStackQueue::StackBox::hover( bool on ) { -} - -BattleSettings::BattleSettings() -{ - printCellBorders = true; - printStackRange = true; - animSpeed = 2; - printMouseShadow = true; - showQueue = true; } \ No newline at end of file diff --git a/client/CBattleInterface.h b/client/CBattleInterface.h index 37514c5e8..d9e25b436 100644 --- a/client/CBattleInterface.h +++ b/client/CBattleInterface.h @@ -314,21 +314,6 @@ public: void show(SDL_Surface * to = 0); }; -struct BattleSettings -{ - BattleSettings(); - bool printCellBorders; //if true, cell borders will be printed - bool printStackRange; //if true,range of active stack will be printed - int animSpeed; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest - bool printMouseShadow; //if true, hex under mouse will be shaded - bool showQueue; - - template void serialize(Handler &h, const int version) - { - h & printCellBorders & printStackRange & animSpeed & printMouseShadow & showQueue; - } -}; - struct SBattleEffect { int x, y; //position on the screen @@ -442,7 +427,6 @@ public: ~CBattleInterface(); //d-tor //std::vector timeinterested; //animation handling - static BattleSettings settings; void setPrintCellBorders(bool set); //if true, cell borders will be printed void setPrintStackRange(bool set); //if true,range of active stack will be printed void setPrintMouseShadow(bool set); //if true, hex under mouse will be shaded @@ -480,6 +464,7 @@ public: void clickRight(tribool down, bool previousState); //call-ins + void startAction(const BattleAction* action); void newStack(int stackID); //new stack appeared on battlefield void stackRemoved(int stackID); //stack disappeared from batlefiled //void stackKilled(int ID, int dmg, int killed, int IDby, bool byShooting); //stack has been killed (but corpses remain) @@ -500,7 +485,6 @@ public: void endAction(const BattleAction* action); void hideQueue(); void showQueue(); - friend class CBattleHex; friend class CBattleResultWindow; friend class CPlayerInterface; diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 73d34e5ca..6ecbb2419 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1024,60 +1024,7 @@ void CPlayerInterface::actionStarted(const BattleAction* action) { boost::unique_lock un(*pim); curAction = new BattleAction(*action); - if( (action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber))) ) - { - battleInt->moveStarted = true; - if(battleInt->creAnims[action->stackNumber]->framesInGroup(20)) - { - battleInt->pendingAnims.push_back(std::make_pair(new CBattleMoveStart(battleInt, action->stackNumber), false)); - } - } - - - battleInt->deactivate(); - - const CStack *stack = cb->battleGetStackByID(action->stackNumber); - char txt[400]; - - if(action->actionType == 1) - { - if(action->side) - battleInt->defendingHero->setPhase(4); - else - battleInt->attackingHero->setPhase(4); - return; - } - if(!stack) - { - tlog1<<"Something wrong with stackNumber in actionStarted. Stack number: "<stackNumber<actionType) - { - case 3: //defend - txtid = 120; - break; - case 8: //wait - txtid = 136; - break; - case 11: //bad morale - txtid = -34; //negative -> no separate singular/plural form - battleInt->displayEffect(30,stack->position); - break; - } - - if(txtid > 0 && stack->amount != 1) - txtid++; //move to plural text - else if(txtid < 0) - txtid = -txtid; - - if(txtid) - { - sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(), (stack->amount != 1) ? stack->creature->namePl.c_str() : stack->creature->nameSing.c_str(), 0); - LOCPLINT->battleInt->console->addText(txt); - } + battleInt->startAction(action); } void CPlayerInterface::actionFinished(const BattleAction* action) @@ -1377,7 +1324,6 @@ template void CPlayerInterface::serializeTempl( Handler &h, c { h & playerID & serialID; h & sysOpts; - h & CBattleInterface::settings; } void CPlayerInterface::serialize( COSer &h, const int version ) @@ -1632,7 +1578,24 @@ void SystemOptions::settingsChanged() void SystemOptions::apply() { - CGI->musich->setVolume(musicVolume); - CGI->soundh->setVolume(soundVolume); + if(CGI->musich->getVolume() != musicVolume) + CGI->musich->setVolume(musicVolume); + if(CGI->soundh->getVolume() != soundVolume) + CGI->soundh->setVolume(soundVolume); + settingsChanged(); } + +SystemOptions::SystemOptions() +{ + heroMoveSpeed = 2; + mapScrollingSpeed = 2; + musicVolume = 88; + soundVolume = 88; + + printCellBorders = true; + printStackRange = true; + animSpeed = 2; + printMouseShadow = true; + showQueue = true; +} \ No newline at end of file diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index bf6eda5f9..9b7619249 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -74,32 +74,33 @@ namespace boost struct SystemOptions { - ui8 heroMoveSpeed; //speed of player's hero movement - //TODO: enemy hero speed + + ui8 heroMoveSpeed;/*, enemyMoveSpeed*/ //speed of player's hero movement ui8 mapScrollingSpeed; //map scrolling speed ui8 musicVolume, soundVolume; - //TODO: rest of system options - template void serialize(Handler &h, const int version) - { - h & heroMoveSpeed & mapScrollingSpeed & musicVolume & soundVolume; - } - - SystemOptions() - { - heroMoveSpeed = 2; - mapScrollingSpeed = 2; - musicVolume = 88; - soundVolume = 88; - } + //battle settings + ui8 printCellBorders; //if true, cell borders will be printed + ui8 printStackRange; //if true,range of active stack will be printed + ui8 animSpeed; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest + ui8 printMouseShadow; //if true, hex under mouse will be shaded + ui8 showQueue; + SystemOptions(); void setHeroMoveSpeed(int newSpeed); //set for the member above void setMapScrollingSpeed(int newSpeed); //set the member above void setMusicVolume(int newVolume); void setSoundVolume(int newVolume); void settingsChanged(); //updates file with "default" settings for next running of application void apply(); + + template void serialize(Handler &h, const int version) + { + h & heroMoveSpeed & mapScrollingSpeed & musicVolume & soundVolume; + + h & printCellBorders & printStackRange & animSpeed & printMouseShadow & showQueue; + } }; extern SystemOptions GDefaultOptions; //defined and inited in CMT.cpp, stores default settings loaded with application diff --git a/client/GUIBase.cpp b/client/GUIBase.cpp index e870e6e29..b59a4d186 100644 --- a/client/GUIBase.cpp +++ b/client/GUIBase.cpp @@ -292,16 +292,7 @@ void CGuiHandler::handleMouseMotion(SDL_Event *sEvent) hlp[i]->hovered = true; } - - //sending active, MotionInterested objects mouseMoved() call - std::list miCopy = motioninterested; - for(std::list::iterator i=miCopy.begin(); i != miCopy.end();i++) - { - if ((*i)->strongInterest || isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y)) - { - (*i)->mouseMoved(sEvent->motion); - } - } + handleMoveInterested(sEvent->motion); } void CGuiHandler::simpleRedraw() @@ -312,6 +303,29 @@ void CGuiHandler::simpleRedraw() objsToBlit.back()->show(screen); //blit active interface/window } +void CGuiHandler::handleMoveInterested( const SDL_MouseMotionEvent & motion ) +{ + //sending active, MotionInterested objects mouseMoved() call + std::list miCopy = motioninterested; + for(std::list::iterator i=miCopy.begin(); i != miCopy.end();i++) + { + if ((*i)->strongInterest || isItIn(&(*i)->pos, motion.x, motion.y)) + { + (*i)->mouseMoved(motion); + } + } +} + +void CGuiHandler::fakeMouseMove() +{ + SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0}; + int x, y; + sme.state = SDL_GetMouseState(&x, &y); + sme.x = x; + sme.y = y; + handleMoveInterested(sme); +} + void CIntObject::activateLClick() { GH.lclickable.push_front(this); diff --git a/client/GUIBase.h b/client/GUIBase.h index 066e215c6..1053d0d39 100644 --- a/client/GUIBase.h +++ b/client/GUIBase.h @@ -453,9 +453,9 @@ public: void updateTime(); //handles timeInterested void handleEvents(); //takes events from queue and calls interested objects void handleEvent(SDL_Event *sEvent); - void handleMouseMotion(SDL_Event *sEvent); - + void handleMoveInterested( const SDL_MouseMotionEvent & motion ); + void fakeMouseMove(); ui8 defActionsDef; //default auto actions ui8 captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list std::list createdObj; //stack of objs being created diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 8c1dcc92a..c06ff74c4 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -222,7 +222,8 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) refr = true; delete pom2; } - else { + else + { // Only allow certain moves if troops aren't removable. if (owner->removableUnits || (upg == 0 && (owner->highlighted->upg == 1 && !creature)) @@ -244,12 +245,13 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) int last = -1; if(upg != owner->highlighted->upg) //not splitting within same army { - if(owner->highlighted->getObj()->army.slots.size() == 1 + if(owner->highlighted->getObj()->army.slots.size() == 1 //we're splitting away the last stack && owner->highlighted->getObj()->needsLastStack() ) { last = 0; } - if(getObj()->army.slots.size() == 1 + if(getObj()->army.slots.size() == 1 //destination army can't be emptied, unless we're rebalancing two stacks of same creature + && owner->highlighted->creature == creature && getObj()->needsLastStack() ) { last += 2; @@ -276,7 +278,8 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) owner->highlighted->ID,ID); } } - else { // Highlight + else // Highlight + { if(creature) owner->highlighted = this; show(screen2); @@ -2829,24 +2832,24 @@ CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface std::swap(backToMap->imgs[0][0], backToMap->imgs[0][1]); heroMoveSpeed = new CHighlightableButtonsGroup(0); - heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[349].first),CGI->generaltexth->zelp[349].second, "sysopb1.def", 187, 134, 1); - heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[350].first),CGI->generaltexth->zelp[350].second, "sysopb2.def", 235, 134, 2); - heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[351].first),CGI->generaltexth->zelp[351].second, "sysopb3.def", 283, 134, 4); - heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[352].first),CGI->generaltexth->zelp[352].second, "sysopb4.def", 331, 134, 8); + heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[349].second),CGI->generaltexth->zelp[349].second, "sysopb1.def", 187, 134, 1); + heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[350].second),CGI->generaltexth->zelp[350].second, "sysopb2.def", 235, 134, 2); + heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[351].second),CGI->generaltexth->zelp[351].second, "sysopb3.def", 283, 134, 4); + heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[352].second),CGI->generaltexth->zelp[352].second, "sysopb4.def", 331, 134, 8); heroMoveSpeed->select(owner->sysOpts.heroMoveSpeed, 1); heroMoveSpeed->onChange = boost::bind(&SystemOptions::setHeroMoveSpeed, &owner->sysOpts, _1); mapScrollSpeed = new CHighlightableButtonsGroup(0); - mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[357].first),CGI->generaltexth->zelp[357].second, "sysopb9.def", 187, 267, 1); - mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[358].first),CGI->generaltexth->zelp[358].second, "sysob10.def", 251, 267, 2); - mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[359].first),CGI->generaltexth->zelp[359].second, "sysob11.def", 315, 267, 4); + mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[357].second),CGI->generaltexth->zelp[357].second, "sysopb9.def", 187, 267, 1); + mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[358].second),CGI->generaltexth->zelp[358].second, "sysob10.def", 251, 267, 2); + mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[359].second),CGI->generaltexth->zelp[359].second, "sysob11.def", 315, 267, 4); mapScrollSpeed->select(owner->sysOpts.mapScrollingSpeed, 1); mapScrollSpeed->onChange = boost::bind(&SystemOptions::setMapScrollingSpeed, &owner->sysOpts, _1); musicVolume = new CHighlightableButtonsGroup(0, true); for(int i=0; i<10; ++i) { - musicVolume->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[326+i].first),CGI->generaltexth->zelp[326+i].second, "syslb.def", 188 + 19*i, 416, i*11); + musicVolume->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[326+i].second),CGI->generaltexth->zelp[326+i].second, "syslb.def", 188 + 19*i, 416, i*11); } musicVolume->select(CGI->musich->getVolume(), 1); musicVolume->onChange = boost::bind(&SystemOptions::setMusicVolume, &owner->sysOpts, _1); @@ -2854,7 +2857,7 @@ CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface effectsVolume = new CHighlightableButtonsGroup(0, true); for(int i=0; i<10; ++i) { - effectsVolume->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[336+i].first),CGI->generaltexth->zelp[336+i].second, "syslb.def", 188 + 19*i, 482, i*11); + effectsVolume->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[336+i].second),CGI->generaltexth->zelp[336+i].second, "syslb.def", 188 + 19*i, 482, i*11); } effectsVolume->select(CGI->soundh->getVolume(), 1); effectsVolume->onChange = boost::bind(&SystemOptions::setSoundVolume, &owner->sysOpts, _1); diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 815e112ce..57d5eda62 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -1054,11 +1054,11 @@ std::pair CGHeroInstance::calculateNecromancy (BattleResult &battleR if (necromancyLevel > 0) { double necromancySkill = necromancyLevel*0.1 + valOfBonuses(HeroBonus::SECONDARY_SKILL_PREMY, 12)/100.0; - const std::set > &casualties = battleResult.casualties[!battleResult.winner]; + const std::map &casualties = battleResult.casualties[!battleResult.winner]; ui32 raisedUnits = 0; // Get lost enemy hit points convertible to units. - for (std::set >::const_iterator it = casualties.begin(); it != casualties.end(); it++) + for (std::map::const_iterator it = casualties.begin(); it != casualties.end(); it++) raisedUnits += VLC->creh->creatures[it->first].hitPoints*it->second; raisedUnits *= necromancySkill; @@ -1071,7 +1071,8 @@ std::pair CGHeroInstance::calculateNecromancy (BattleResult &battleR // Make room for new units. int slot = army.getSlotFor(raisedUnitType->idNumber); - if (slot == -1) { + if (slot == -1) + { // If there's no room for unit, try it's upgraded version 2/3rds the size. raisedUnitType = &VLC->creh->creatures[*raisedUnitType->upgrades.begin()]; raisedUnits = (raisedUnits*2)/3; diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 3e1412696..a2e53fb8d 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -2493,18 +2493,14 @@ ui32 BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, co return range.first; } -void BattleInfo::calculateCasualties( std::set > *casualties ) const +void BattleInfo::calculateCasualties( std::map *casualties ) const { for(unsigned int i=0; ialive()) - { - casualties[!stacks[i]->attackerOwned].insert(std::pair(stacks[i]->creature->idNumber,stacks[i]->baseAmount)); - } - else if(stacks[i]->amount != stacks[i]->baseAmount) - { - casualties[!stacks[i]->attackerOwned].insert(std::pair(stacks[i]->creature->idNumber,stacks[i]->baseAmount - stacks[i]->amount)); - } + const CStack * const st = stacks[i]; + si32 killed = (st->alive() ? st->baseAmount - st->amount : st->baseAmount); + amax(killed, 0); + casualties[!st->attackerOwned][st->creature->idNumber] += killed; } } diff --git a/lib/CGameState.h b/lib/CGameState.h index a212fe3f9..bda03f5a2 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -154,7 +154,7 @@ struct DLL_EXPORT BattleInfo static std::vector neighbouringTiles(int hex); static ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge); //charge - number of hexes travelled before attack (for champion's jousting) static std::pair calculateDmgRange(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge); //charge - number of hexes travelled before attack (for champion's jousting); returns pair - void calculateCasualties(std::set > *casualties) const; + void calculateCasualties(std::map *casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount) std::set getAttackedCreatures(const CSpell * s, const CGHeroInstance * caster, int destinationTile); //calculates stack affected by given spell static int calculateSpellDuration(const CSpell * spell, const CGHeroInstance * caster); CStack * generateNewStack(const CGHeroInstance * owner, int creatureID, int amount, int stackID, bool attackerOwned, int slot, int /*TerrainTile::EterrainType*/ terrain, int position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield diff --git a/lib/NetPacks.h b/lib/NetPacks.h index a3b7fb0bd..98001c6c9 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -807,7 +807,7 @@ struct BattleResult : public CPackForClient//3003 ui8 result; //0 - normal victory; 1 - escape; 2 - surrender ui8 winner; //0 - attacker, 1 - defender, [2 - draw (should be possible?)] - std::set > casualties[2]; //first => casualties of attackers - set of pairs crid<>number + std::map casualties[2]; //first => casualties of attackers - map crid => number ui32 exp[2]; //exp for attacker and defender std::set artifacts; //artifacts taken from loser to winner diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index b0620e7e3..5fe0e15f9 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -95,7 +95,7 @@ static void giveExp(BattleResult &r) { r.exp[0] = 0; r.exp[1] = 0; - for(std::set >::iterator i = r.casualties[!r.winner].begin(); i!=r.casualties[!r.winner].end(); i++) + for(std::map::iterator i = r.casualties[!r.winner].begin(); i!=r.casualties[!r.winner].end(); i++) { r.exp[r.winner] += VLC->creh->creatures[i->first].hitPoints * i->second; } @@ -1406,7 +1406,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255* && complain("Cannot move hero, destination tile is on water!") || (h->boat && t.tertype != TerrainTile::water && t.blocked) && complain("Cannot disembark hero, tile is blocked!") - || (!h->movement && dst != h->pos) + || (h->movement < cost && dst != h->pos) && complain("Hero don't have any movement points left!") || states.checkFlag(h->tempOwner, &PlayerStatus::engagedIntoBattle) && complain("Cannot move hero during the battle"))