mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Version for development release 0.73c
* version set to 0.73c, bumped save format version, updated changelog * new stack queue for higher resolutions (needs new graphics!) * improved stack ordering during battle * many minor fixes * temporarily disabled AI
This commit is contained in:
parent
14ee503056
commit
ee3c318ed9
@ -816,6 +816,7 @@ void CGeniusAI::yourTurn()
|
||||
static boost::mutex mutex;
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
m_cb->waitTillRealize = true;
|
||||
m_cb->endTurn();
|
||||
static int seed = rand();
|
||||
srand(seed);
|
||||
if(m_cb->getDate()==1)
|
||||
@ -843,7 +844,6 @@ void CGeniusAI::yourTurn()
|
||||
objective->fulfill(*this,trueGameState);
|
||||
|
||||
seed = rand();
|
||||
m_cb->endTurn();
|
||||
|
||||
m_cb->waitTillRealize = false;
|
||||
}
|
||||
|
78
ChangeLog
78
ChangeLog
@ -1,4 +1,80 @@
|
||||
0.72 -> 0.73 (1 Aug 2009) as for r1044
|
||||
0.73 -> 0.74
|
||||
GENERAL:
|
||||
* Scenario Information window
|
||||
* Save Game window
|
||||
* VCMI window should start centered
|
||||
* support for Necromancy and Ballistics secondary skills
|
||||
* new artifacts supported, including those improving Necromancy, Legion Statue parts, Shackles of War and most of combination artifacts (but not combining)
|
||||
* Ellipsis won't be split when breaking text on several lines
|
||||
* split button will be grayed out when no creature is selected
|
||||
* a few fixes for shipyard window
|
||||
|
||||
ADVENTURE INTERFACE:
|
||||
* Cursor shows if tile is accesible and how many turns away
|
||||
* moving hero with arrow keys / numpad
|
||||
* fixed Next Hero button behaviour
|
||||
* fixed Surface/Underground switch button in higher resolutions
|
||||
|
||||
BATTLES:
|
||||
* partial siege support
|
||||
* new stack queue for higher resolutions (graphics made by Dru, thx!)
|
||||
* 'Q' pressing toggles the queue displaying (so it can be enabled/disabled it with single key press)
|
||||
* more creatures special abilities supported
|
||||
* stack
|
||||
* fixed crashes occuring on attacking two hex creatures from back
|
||||
* even large stack numbers will fit the boxes
|
||||
* shooters attacking twice (like Grand Elves) won't attack twice in melee
|
||||
* ballista can shoot even if there's an enemy creature next to it
|
||||
* improved obstacles placement, so they'll better fit hexes (thx to Ivan!)
|
||||
* selecting attack directions works as in H3
|
||||
* estimating damage that will be dealt while choosing stack to be attacked
|
||||
* modified the positioning of battle effects, they should look about right now.
|
||||
* after selecting a spell during combat, l-click is locked for any action other than casting.
|
||||
* new spells supported:
|
||||
- Anti-Magic
|
||||
- Cure
|
||||
- Resurrection
|
||||
- Animate Dead
|
||||
- Counterstrike
|
||||
- Berserk
|
||||
- Hypnotize
|
||||
- Blind
|
||||
- Fire Elemental
|
||||
- Earth Elemental
|
||||
- Water Elemental
|
||||
- Air Elemental
|
||||
- Remove obstacle
|
||||
|
||||
TOWNS:
|
||||
* enemy castle can be taken over
|
||||
* garrisoned hero can buy a spellbook
|
||||
* Lookout Tower supported
|
||||
* heroes available in tavern sould be always different
|
||||
* ship bought in town will be correctly placed
|
||||
|
||||
HERO WINDOW:
|
||||
* war machines cannot be unequiped
|
||||
|
||||
PREGAME:
|
||||
* sorting: a second click on the column header sorts in descending order.
|
||||
* advanced options tab: r-click popups for selected town, hero and bonus
|
||||
* starting scenario / game by double click
|
||||
* arrows in options tab are hidden when not available
|
||||
* subtitles for choosen hero/town/bonus in pregame
|
||||
|
||||
OBJECTS:
|
||||
* fixed pairing Subterranean Gates
|
||||
New objects supported:
|
||||
- Borderguard & Keymaster Tent
|
||||
- Cartographer
|
||||
- Creature banks
|
||||
- Eye of the Magi & Hut of the Magi
|
||||
- Garrison
|
||||
- Stables
|
||||
- Pandora Box
|
||||
|
||||
|
||||
0.72 -> 0.73 (1 Aug 2009)
|
||||
GENERAL:
|
||||
* infowindow popup will be completely on screen
|
||||
* fixed possible crash with in game console
|
||||
|
@ -1729,7 +1729,8 @@ void CAdvMapInt::centerOn(int3 on)
|
||||
LOCPLINT->adventureInt->updateScreen=true;
|
||||
updateMinimap=true;
|
||||
underground.curimg = on.z; //change underground switch button image
|
||||
underground.redraw();
|
||||
if(GH.topInt() == this)
|
||||
underground.redraw();
|
||||
}
|
||||
void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
|
||||
{
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "../hch/CVideoHandler.h"
|
||||
#include "../hch/CTownHandler.h"
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#ifndef __GNUC__
|
||||
const double M_PI = 3.14159265358979323846;
|
||||
#else
|
||||
@ -100,7 +101,7 @@ bool CBattleAnimation::isEarliest(bool perStackConcurrency)
|
||||
|
||||
CReverseAnim * revAnim = dynamic_cast<CReverseAnim *>(stAnim);
|
||||
|
||||
if(revAnim && stAnim->stackID == thAnim->stackID && revAnim->priority)
|
||||
if(revAnim && thAnim && stAnim && stAnim->stackID == thAnim->stackID && revAnim->priority)
|
||||
return false;
|
||||
|
||||
if(it->first)
|
||||
@ -545,7 +546,8 @@ bool CBattleStackMoved::init()
|
||||
}
|
||||
//unit reversed
|
||||
|
||||
owner->moveSh = CGI->soundh->playSound(movedStack->creature->sounds.move, -1);
|
||||
if(owner->moveSh <= 0)
|
||||
owner->moveSh = CGI->soundh->playSound(movedStack->creature->sounds.move, -1);
|
||||
|
||||
//step shift calculation
|
||||
posX = owner->creAnims[stackID]->pos.x, posY = owner->creAnims[stackID]->pos.y; // for precise calculations ;]
|
||||
@ -630,6 +632,12 @@ void CBattleStackMoved::endAnim()
|
||||
owner->creAnims[stackID]->pos.y = coords.second;
|
||||
}
|
||||
|
||||
if(owner->moveSh >= 0)
|
||||
{
|
||||
CGI->soundh->stopSound(owner->moveSh);
|
||||
owner->moveSh = -1;
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
@ -727,8 +735,6 @@ void CBattleMoveEnd::endAnim()
|
||||
owner->creAnims[stackID]->setType(2); //resetting to default
|
||||
|
||||
CGI->curh->show();
|
||||
CGI->soundh->stopSound(owner->moveSh);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
@ -1011,13 +1017,29 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
|
||||
: attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), stackToActivate(-1),
|
||||
mouseHoveredStack(-1), previouslyHoveredHex(-1), currentlyHoveredHex(-1), spellDestSelectMode(false),
|
||||
spellToCast(NULL), givenCommand(NULL), myTurn(false), resWindow(NULL), animIDhelper(0),
|
||||
showStackQueue(false), moveStarted(false), moveSh(-1), siegeH(NULL), bresult(NULL)
|
||||
moveStarted(false), moveSh(-1), siegeH(NULL), bresult(NULL), queue(NULL)
|
||||
{
|
||||
ObjectConstruction h__l__p(this);
|
||||
|
||||
animsAreDisplayed.setn(false);
|
||||
pos = myRect;
|
||||
strongInterest = true;
|
||||
givenCommand = new CondSh<BattleAction *>(NULL);
|
||||
|
||||
//create stack queue
|
||||
bool embedQueue = screen->h < 700;
|
||||
queue = new CStackQueue(embedQueue);
|
||||
if(!embedQueue && settings.showQueue)
|
||||
{
|
||||
pos.y += queue->pos.h / 2; //center whole window
|
||||
queue->moveTo(Point(pos.x, pos.y - queue->pos.h));
|
||||
// queue->pos.x = pos.x;
|
||||
// queue->pos.y = pos.y - queue->pos.h;
|
||||
// pos.h += queue->pos.h;
|
||||
// center();
|
||||
}
|
||||
queue->update();
|
||||
|
||||
//preparing siege info
|
||||
const CGTownInstance * town = LOCPLINT->cb->battleGetDefendedTown();
|
||||
if(town)
|
||||
@ -1239,6 +1261,7 @@ CBattleInterface::~CBattleInterface()
|
||||
|
||||
delete attackingHero;
|
||||
delete defendingHero;
|
||||
delete queue;
|
||||
|
||||
SDL_FreeSurface(cellBorder);
|
||||
SDL_FreeSurface(cellShade);
|
||||
@ -1297,6 +1320,8 @@ void CBattleInterface::activate()
|
||||
attackingHero->activate();
|
||||
if(defendingHero)
|
||||
defendingHero->activate();
|
||||
if(settings.showQueue)
|
||||
queue->activate();
|
||||
|
||||
LOCPLINT->cingconsole->activate();
|
||||
}
|
||||
@ -1323,6 +1348,8 @@ void CBattleInterface::deactivate()
|
||||
attackingHero->deactivate();
|
||||
if(defendingHero)
|
||||
defendingHero->deactivate();
|
||||
if(settings.showQueue)
|
||||
queue->deactivate();
|
||||
|
||||
LOCPLINT->cingconsole->deactivate();
|
||||
}
|
||||
@ -1337,6 +1364,7 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
SDL_Rect buf;
|
||||
SDL_GetClipRect(to, &buf);
|
||||
SDL_SetClipRect(to, &pos);
|
||||
|
||||
//printing background and hexes
|
||||
if(activeStack != -1 && creAnims[activeStack]->getType() != 0) //show everything with range
|
||||
{
|
||||
@ -1492,11 +1520,6 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
{
|
||||
activateStack();
|
||||
}
|
||||
if(pendingAnims.size() == 0 && bresult != NULL)
|
||||
{
|
||||
displayBattleFinished();
|
||||
}
|
||||
|
||||
//anims ended
|
||||
animsAreDisplayed.setn(false);
|
||||
}
|
||||
@ -1531,53 +1554,6 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
SDL_BlitSurface(bitmapToBlit, NULL, to, &genRect(bitmapToBlit->h, bitmapToBlit->w, pos.x + it->x, pos.y + it->y));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//showing queue of stacks
|
||||
if(showStackQueue)
|
||||
{
|
||||
const int QUEUE_SIZE = 10;
|
||||
|
||||
int xPos = screen->w/2 - ( stacks.size() * 37 )/2;
|
||||
int yPos = (screen->h - 600)/2 + 10;
|
||||
|
||||
std::vector<const CStack *> stacksSorted;
|
||||
// const CStack *curStack = LOCPLINT->cb->battleGetStackByID(activeStack);
|
||||
// if(curStack)
|
||||
// stacksSorted.push_back(curStack);
|
||||
LOCPLINT->cb->getStackQueue(stacksSorted, QUEUE_SIZE);
|
||||
|
||||
|
||||
for(size_t b=0; b < stacksSorted.size(); ++b)
|
||||
{
|
||||
const CStack * s = stacksSorted[b];
|
||||
SDL_BlitSurface(graphics->smallImgs[-2], NULL, to, &genRect(32, 32, xPos, yPos));
|
||||
|
||||
//printing colored border
|
||||
for(int xFrom = xPos-1; xFrom<xPos+33; ++xFrom)
|
||||
{
|
||||
for(int yFrom = yPos-1; yFrom<yPos+33; ++yFrom)
|
||||
{
|
||||
if(xFrom == xPos-1 || xFrom == xPos+32 || yFrom == yPos-1 || yFrom == yPos+32)
|
||||
{
|
||||
SDL_Color pc;
|
||||
if(s->owner != 255)
|
||||
{
|
||||
pc = graphics->playerColors[s->owner];
|
||||
}
|
||||
else
|
||||
{
|
||||
pc = *graphics->neutralColor;
|
||||
}
|
||||
CSDL_Ext::SDL_PutPixelWithoutRefresh(to, xFrom, yFrom, pc.r, pc.g, pc.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
//colored border printed
|
||||
SDL_BlitSurface(graphics->smallImgs[s->creature->idNumber], NULL, to, &genRect(32, 32, xPos, yPos));
|
||||
xPos += 37;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetClipRect(to, &buf); //restoring previous clip_rect
|
||||
|
||||
@ -1594,15 +1570,35 @@ void CBattleInterface::show(SDL_Surface * to)
|
||||
//showing in-game console
|
||||
LOCPLINT->cingconsole->show(to);
|
||||
|
||||
Rect posWithQueue = Rect(pos.x, pos.y, 800, 600);
|
||||
|
||||
if(settings.showQueue)
|
||||
{
|
||||
if(!queue->embedded)
|
||||
{
|
||||
posWithQueue.y -= queue->pos.h;
|
||||
posWithQueue.h += queue->pos.h;
|
||||
}
|
||||
|
||||
//showing queue
|
||||
if(!bresult)
|
||||
queue->showAll(to);
|
||||
}
|
||||
|
||||
//printing border around interface
|
||||
if(screen->w != 800 || screen->h !=600)
|
||||
CMessage::drawBorder(LOCPLINT->playerID,to,828,628,pos.x-14,pos.y-15);
|
||||
{
|
||||
CMessage::drawBorder(LOCPLINT->playerID,to,posWithQueue.w + 28, posWithQueue.h + 28, posWithQueue.x-14, posWithQueue.y-15);
|
||||
}
|
||||
}
|
||||
void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key)
|
||||
{
|
||||
if(key.keysym.sym == SDLK_q)
|
||||
if(key.keysym.sym == SDLK_q && key.state == SDL_PRESSED)
|
||||
{
|
||||
showStackQueue = key.state==SDL_PRESSED;
|
||||
if(settings.showQueue) //hide queue
|
||||
hideQueue();
|
||||
else
|
||||
showQueue();
|
||||
}
|
||||
else if(key.keysym.sym == SDLK_ESCAPE && spellDestSelectMode)
|
||||
{
|
||||
@ -2121,7 +2117,7 @@ void CBattleInterface::newRound(int number)
|
||||
|
||||
void CBattleInterface::giveCommand(ui8 action, ui16 tile, ui32 stack, si32 additional)
|
||||
{
|
||||
if(!LOCPLINT->cb->battleGetStackByID(stack))
|
||||
if(!LOCPLINT->cb->battleGetStackByID(stack) && action != 1 && action != 4 && action != 5)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -2406,7 +2402,9 @@ void CBattleInterface::stackIsShooting(int ID, int dest)
|
||||
void CBattleInterface::battleFinished(const BattleResult& br)
|
||||
{
|
||||
bresult = &br;
|
||||
//animsAreDisplayed.waitUntil(false);
|
||||
LOCPLINT->pim->unlock();
|
||||
animsAreDisplayed.waitUntil(false);
|
||||
LOCPLINT->pim->lock();
|
||||
displayBattleFinished();
|
||||
}
|
||||
|
||||
@ -2602,6 +2600,7 @@ int CBattleInterface::getAnimSpeed() const
|
||||
void CBattleInterface::activateStack()
|
||||
{
|
||||
activeStack = stackToActivate;
|
||||
queue->update();
|
||||
stackToActivate = -1;
|
||||
myTurn = true;
|
||||
redrawBackgroundWithHexes(activeStack);
|
||||
@ -2899,6 +2898,51 @@ void CBattleInterface::projectileShowHelper(SDL_Surface * to)
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::endAction(const BattleAction* action)
|
||||
{
|
||||
//if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //activating interface when move is finished
|
||||
{
|
||||
activate();
|
||||
}
|
||||
if(action->actionType == 1)
|
||||
{
|
||||
if(action->side)
|
||||
defendingHero->setPhase(0);
|
||||
else
|
||||
attackingHero->setPhase(0);
|
||||
}
|
||||
if(action->actionType == 2 && creAnims[action->stackNumber]->getType() != 2) //walk or walk & attack
|
||||
{
|
||||
pendingAnims.push_back(std::make_pair(new CBattleMoveEnd(this, action->stackNumber, action->destinationTile), false));
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::hideQueue()
|
||||
{
|
||||
settings.showQueue = false;
|
||||
//if(queue->active)
|
||||
queue->deactivate();
|
||||
|
||||
if(!queue->embedded)
|
||||
{
|
||||
moveBy(Point(0, -queue->pos.h / 2));
|
||||
GH.totalRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::showQueue()
|
||||
{
|
||||
settings.showQueue = true;
|
||||
//if(!queue->active)
|
||||
queue->activate();
|
||||
|
||||
if(!queue->embedded)
|
||||
{
|
||||
moveBy(Point(0, +queue->pos.h / 2));
|
||||
GH.totalRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleHero::show(SDL_Surface *to)
|
||||
{
|
||||
//animation of flag
|
||||
@ -3706,3 +3750,119 @@ void CBattleInterface::SiegeHelper::printPartOfWall(SDL_Surface * to, int what)
|
||||
blitAt(walls[what], pos.x, pos.y, to);
|
||||
}
|
||||
}
|
||||
|
||||
void CStackQueue::update()
|
||||
{
|
||||
stacksSorted.clear();
|
||||
LOCPLINT->cb->getStackQueue(stacksSorted, QUEUE_SIZE);
|
||||
for (int i = 0; i < QUEUE_SIZE ; i++)
|
||||
{
|
||||
stackBoxes[i]->setStack(stacksSorted[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CStackQueue::CStackQueue(bool Embedded)
|
||||
:embedded(Embedded)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
if(embedded)
|
||||
{
|
||||
box = NULL;
|
||||
bg = NULL;
|
||||
pos.w = QUEUE_SIZE * 37;
|
||||
pos.h = 32; //height of small creature img
|
||||
pos.x = screen->w/2 - pos.w/2;
|
||||
pos.y = (screen->h - 600)/2 + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
box = BitmapHandler::loadBitmap("CHRROP.pcx");
|
||||
bg = BitmapHandler::loadBitmap("DIBOXPI.pcx");
|
||||
pos.w = 600;
|
||||
pos.h = bg->h;
|
||||
}
|
||||
|
||||
stackBoxes.resize(QUEUE_SIZE);
|
||||
for (int i = 0; i < QUEUE_SIZE; i++)
|
||||
{
|
||||
stackBoxes[i] = new StackBox(box);
|
||||
stackBoxes[i]->pos.x += 6 + (embedded ? 37 : 79)*i;
|
||||
}
|
||||
}
|
||||
|
||||
CStackQueue::~CStackQueue()
|
||||
{
|
||||
SDL_FreeSurface(box);
|
||||
}
|
||||
|
||||
void CStackQueue::showAll( SDL_Surface *to )
|
||||
{
|
||||
if(bg)
|
||||
{
|
||||
for (int w = 0; w < pos.w; w += bg->w)
|
||||
{
|
||||
blitAtLoc(bg, w, 0, to);
|
||||
}
|
||||
}
|
||||
CIntObject::showAll(to);
|
||||
}
|
||||
|
||||
void CStackQueue::StackBox::showAll( SDL_Surface *to )
|
||||
{
|
||||
assert(my);
|
||||
if(bg)
|
||||
{
|
||||
graphics->blueToPlayersAdv(bg, my->owner);
|
||||
//SDL_UpdateRect(bg, 0, 0, 0, 0);
|
||||
blitAt(bg, pos, to);
|
||||
blitAt(graphics->bigImgs[my->creature->idNumber], pos.x +9, pos.y + 1, to);
|
||||
printAtMiddleLoc(makeNumberShort(my->amount), pos.w/2, pos.h - 12, FONT_MEDIUM, zwykly, to);
|
||||
}
|
||||
else
|
||||
{
|
||||
blitAt(graphics->smallImgs[-2], pos, to);
|
||||
blitAt(graphics->smallImgs[my->creature->idNumber], pos, to);
|
||||
const SDL_Color &ownerColor = (my->owner == 255 ? *graphics->neutralColor : graphics->playerColors[my->owner]);
|
||||
CSDL_Ext::drawBorder(to, pos, int3(ownerColor.r, ownerColor.g, ownerColor.b));
|
||||
printAtMiddleLoc(makeNumberShort(my->amount), pos.w/2, pos.h - 8, FONT_TINY, zwykly, to);
|
||||
}
|
||||
}
|
||||
|
||||
void CStackQueue::StackBox::setStack( const CStack *nStack )
|
||||
{
|
||||
my = nStack;
|
||||
}
|
||||
|
||||
CStackQueue::StackBox::StackBox(SDL_Surface *BG)
|
||||
:bg(BG), my(NULL)
|
||||
{
|
||||
if(bg)
|
||||
{
|
||||
pos.w = bg->w;
|
||||
pos.h = bg->h;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.w = pos.h = 32;
|
||||
}
|
||||
|
||||
pos.y += 2;
|
||||
}
|
||||
|
||||
CStackQueue::StackBox::~StackBox()
|
||||
{
|
||||
}
|
||||
|
||||
void CStackQueue::StackBox::hover( bool on )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BattleSettings::BattleSettings()
|
||||
{
|
||||
printCellBorders = true;
|
||||
printStackRange = true;
|
||||
animSpeed = 2;
|
||||
printMouseShadow = true;
|
||||
showQueue = true;
|
||||
}
|
@ -316,22 +316,16 @@ public:
|
||||
|
||||
struct BattleSettings
|
||||
{
|
||||
BattleSettings()
|
||||
{
|
||||
printCellBorders = true;
|
||||
printStackRange = true;
|
||||
animSpeed = 2;
|
||||
printMouseShadow = true;
|
||||
}
|
||||
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 <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & printCellBorders & printStackRange & animSpeed & printMouseShadow;
|
||||
h & printCellBorders & printStackRange & animSpeed & printMouseShadow & showQueue;
|
||||
}
|
||||
};
|
||||
|
||||
@ -343,6 +337,37 @@ struct SBattleEffect
|
||||
int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim
|
||||
};
|
||||
|
||||
class CStackQueue : public CIntObject
|
||||
{
|
||||
class StackBox : public CIntObject
|
||||
{
|
||||
public:
|
||||
const CStack *my;
|
||||
SDL_Surface *bg;
|
||||
|
||||
void hover (bool on);
|
||||
void showAll(SDL_Surface *to);
|
||||
void setStack(const CStack *nStack);
|
||||
StackBox(SDL_Surface *BG);
|
||||
~StackBox();
|
||||
};
|
||||
|
||||
public:
|
||||
static const int QUEUE_SIZE = 10;
|
||||
const bool embedded;
|
||||
std::vector<const CStack *> stacksSorted;
|
||||
std::vector<StackBox *> stackBoxes;
|
||||
|
||||
SDL_Surface *box;
|
||||
SDL_Surface *bg;
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
CStackQueue(bool Embedded);
|
||||
~CStackQueue();
|
||||
void update();
|
||||
//void showAll(SDL_Surface *to);
|
||||
};
|
||||
|
||||
class CBattleInterface : public CIntObject
|
||||
{
|
||||
private:
|
||||
@ -351,6 +376,7 @@ private:
|
||||
* bWait, * bDefence, * bConsoleUp, * bConsoleDown;
|
||||
CBattleConsole * console;
|
||||
CBattleHero * attackingHero, * defendingHero; //fighting heroes
|
||||
CStackQueue *queue;
|
||||
CCreatureSet * army1, * army2; //fighting armies
|
||||
CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
|
||||
std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
||||
@ -428,7 +454,6 @@ public:
|
||||
CondSh<BattleAction *> *givenCommand; //data != NULL if we have i.e. moved current unit
|
||||
bool myTurn; //if true, interface is active (commands can be ordered
|
||||
CBattleResultWindow * resWindow; //window of end of battle
|
||||
bool showStackQueue; //if true, queue of stacks will be shown
|
||||
|
||||
bool moveStarted; //if true, the creature that is already moving is going to make its first step
|
||||
int moveSh; // sound handler used when moving a unit
|
||||
@ -471,6 +496,9 @@ public:
|
||||
void battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks
|
||||
void castThisSpell(int spellID); //called when player has chosen a spell from spellbook
|
||||
void displayEffect(ui32 effect, int destTile); //displays effect of a spell on the battlefield; affected: true - attacker. false - defender
|
||||
void endAction(const BattleAction* action);
|
||||
void hideQueue();
|
||||
void showQueue();
|
||||
|
||||
friend class CBattleHex;
|
||||
friend class CBattleResultWindow;
|
||||
|
@ -524,6 +524,8 @@ void CCastleInterface::close()
|
||||
{
|
||||
if(town->visitingHero)
|
||||
LOCPLINT->adventureInt->select(town->visitingHero);
|
||||
else
|
||||
LOCPLINT->adventureInt->select(town);
|
||||
LOCPLINT->castleInt = NULL;
|
||||
GH.popIntTotally(this);
|
||||
CGI->musich->stopMusic(5000);
|
||||
@ -906,6 +908,7 @@ void CCastleInterface::recreateBuildings()
|
||||
}
|
||||
|
||||
//ship in shipyard
|
||||
bool isThereShip = false;
|
||||
if(vstd::contains(town->builtBuildings,6))
|
||||
{
|
||||
std::vector <const CGObjectInstance *> vobjs = LOCPLINT->cb->getVisitableObjs(town->bestLocation());
|
||||
@ -914,6 +917,7 @@ void CCastleInterface::recreateBuildings()
|
||||
Structure * st = CGI->townh->structures[town->subID][20];
|
||||
buildings.push_back(new CBuildingRect(st));
|
||||
s.insert(std::pair<int,int>(st->group,st->ID));
|
||||
isThereShip = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -943,26 +947,35 @@ void CCastleInterface::recreateBuildings()
|
||||
}
|
||||
}
|
||||
//code for the shipyard in the Castle
|
||||
else if((town->subID == 0) && (town->builtBuildings.find(6)!=town->builtBuildings.end()))
|
||||
else if(town->subID == 0)
|
||||
{
|
||||
CBuildingRect *shipyard = NULL;
|
||||
for(size_t i=0;i<buildings.size();i++)
|
||||
int shipID = 0;
|
||||
if(isThereShip)
|
||||
shipID = 20;
|
||||
else if(vstd::contains(town->builtBuildings, 6))
|
||||
shipID = 6;
|
||||
|
||||
if(shipID)
|
||||
{
|
||||
if(buildings[i]->str->ID==6)
|
||||
CBuildingRect *shipyard = NULL;
|
||||
for(size_t i=0;i<buildings.size();i++)
|
||||
{
|
||||
shipyard=buildings[i];
|
||||
break;
|
||||
if(buildings[i]->str->ID==shipID)
|
||||
{
|
||||
shipyard=buildings[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(town->builtBuildings.find(8)!=town->builtBuildings.end()) //there is citadel
|
||||
{
|
||||
shipyard->offset = 1;
|
||||
shipyard->max = shipyard->def->ourImages.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
shipyard->offset = 0;
|
||||
shipyard->max = 1;
|
||||
}
|
||||
}
|
||||
if(town->builtBuildings.find(8)!=town->builtBuildings.end()) //there is citadel
|
||||
{
|
||||
shipyard->offset = 1;
|
||||
shipyard->max = shipyard->def->ourImages.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
shipyard->offset = 0;
|
||||
shipyard->max = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1085,22 +1085,7 @@ void CPlayerInterface::actionFinished(const BattleAction* action)
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
delete curAction;
|
||||
curAction = NULL;
|
||||
//if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //activating interface when move is finished
|
||||
{
|
||||
battleInt->activate();
|
||||
}
|
||||
if(action->actionType == 1)
|
||||
{
|
||||
if(action->side)
|
||||
battleInt->defendingHero->setPhase(0);
|
||||
else
|
||||
battleInt->attackingHero->setPhase(0);
|
||||
}
|
||||
if(action->actionType == 2 && battleInt->creAnims[action->stackNumber]->getType() != 2) //walk or walk & attack
|
||||
{
|
||||
battleInt->pendingAnims.push_back(std::make_pair(new CBattleMoveEnd(battleInt, action->stackNumber, action->destinationTile), false));
|
||||
}
|
||||
|
||||
battleInt->endAction(action);
|
||||
}
|
||||
|
||||
BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
|
||||
|
@ -631,6 +631,20 @@ const Rect & CIntObject::center()
|
||||
return center(pos);
|
||||
}
|
||||
|
||||
void CIntObject::moveBy( const Point &p, bool propagate /*= true*/ )
|
||||
{
|
||||
pos.x += p.x;
|
||||
pos.y += p.y;
|
||||
if(propagate)
|
||||
for(size_t i = 0; i < children.size(); i++)
|
||||
children[i]->moveBy(p, propagate);
|
||||
}
|
||||
|
||||
void CIntObject::moveTo( const Point &p, bool propagate /*= true*/ )
|
||||
{
|
||||
moveBy(Point(p.x - pos.x, p.y - pos.y), propagate);
|
||||
}
|
||||
|
||||
CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free )
|
||||
{
|
||||
bg = BG;
|
||||
@ -647,8 +661,15 @@ CPicture::CPicture( const std::string &bmpname, int x, int y )
|
||||
freeSurf = true;;
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
pos.w = bg->w;
|
||||
pos.h = bg->h;
|
||||
if(bg)
|
||||
{
|
||||
pos.w = bg->w;
|
||||
pos.h = bg->h;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.w = pos.h = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CPicture::~CPicture()
|
||||
@ -659,7 +680,8 @@ CPicture::~CPicture()
|
||||
|
||||
void CPicture::showAll( SDL_Surface * to )
|
||||
{
|
||||
blitAt(bg, pos, to);
|
||||
if(bg)
|
||||
blitAt(bg, pos, to);
|
||||
}
|
||||
|
||||
ObjectConstruction::ObjectConstruction( CIntObject *obj )
|
||||
|
@ -191,6 +191,10 @@ struct Rect : public SDL_Rect
|
||||
y -= p.y;
|
||||
return *this;
|
||||
}
|
||||
template<typename T> Rect operator-(const T &t)
|
||||
{
|
||||
return Rect(x + t.x, y + t.y, w, h);
|
||||
}
|
||||
Rect operator&(const Rect &p) const //rect intersection
|
||||
{
|
||||
bool intersect = true;
|
||||
@ -355,6 +359,8 @@ public:
|
||||
bool isItInLoc(const SDL_Rect &rect, const Point &p);
|
||||
const Rect & center(const Rect &r); //sets pos so that r will be in the center of screen, returns new position
|
||||
const Rect & center(); //centers when pos.w and pos.h are set, returns new position
|
||||
void moveBy(const Point &p, bool propagate = true);
|
||||
void moveTo(const Point &p, bool propagate = true);
|
||||
};
|
||||
|
||||
//class for binding keys to left mouse button clicks
|
||||
|
@ -1885,7 +1885,7 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, co
|
||||
max = new AdventureMapButton(CGI->generaltexth->zelp[553],boost::bind(&CRecruitmentWindow::Max,this),pos.x+134,pos.y+313,"IRCBTNS.DEF",SDLK_m);
|
||||
buy = new AdventureMapButton(CGI->generaltexth->zelp[554],boost::bind(&CRecruitmentWindow::Buy,this),pos.x+212,pos.y+313,"IBY6432.DEF",SDLK_RETURN);
|
||||
cancel = new AdventureMapButton(CGI->generaltexth->zelp[555],boost::bind(&CRecruitmentWindow::Cancel,this),pos.x+290,pos.y+313,"ICN6432.DEF",SDLK_ESCAPE);
|
||||
slider = new CSlider(pos.x+176,pos.y+279,135,boost::bind(&CRecruitmentWindow::sliderMoved,this, _1),1,0,0,true);
|
||||
slider = new CSlider(pos.x+176,pos.y+279,135,boost::bind(&CRecruitmentWindow::sliderMoved,this, _1),0,0,0,true);
|
||||
|
||||
initCres();
|
||||
|
||||
@ -1990,7 +1990,7 @@ CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner, int Last, int
|
||||
ok = new AdventureMapButton("","",boost::bind(&CSplitWindow::split,this),pos.x+20,pos.y+263,"IOK6432.DEF",SDLK_RETURN);
|
||||
cancel = new AdventureMapButton("","",boost::bind(&CSplitWindow::close,this),pos.x+214,pos.y+263,"ICN6432.DEF",SDLK_ESCAPE);
|
||||
int sliderPositions = max - (last>=0) - (last==2);
|
||||
slider = new CSlider(pos.x+21,pos.y+194,257,boost::bind(&CSplitWindow::sliderMoved,this,_1),1,sliderPositions,val,true);
|
||||
slider = new CSlider(pos.x+21,pos.y+194,257,boost::bind(&CSplitWindow::sliderMoved,this,_1),0,sliderPositions,val,true);
|
||||
a1 = max-val;
|
||||
a2 = val;
|
||||
anim = new CCreaturePic(&CGI->creh->creatures[cid]);
|
||||
@ -2875,7 +2875,7 @@ CSystemOptionsWindow::~CSystemOptionsWindow()
|
||||
|
||||
void CSystemOptionsWindow::bquitf()
|
||||
{
|
||||
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[578], std::vector<SComponent*>(), boost::bind(exit, 0), boost::bind(&CSystemOptionsWindow::activate, this), false);
|
||||
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[578], std::vector<SComponent*>(), boost::bind(exit, 0), 0, false);
|
||||
}
|
||||
|
||||
void CSystemOptionsWindow::breturnf()
|
||||
|
@ -527,10 +527,11 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, int player)
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i=0; i<32; ++i)
|
||||
{
|
||||
sur->format->palette->colors[224+i] = palette[i];
|
||||
}
|
||||
SDL_SetColors(sur, palette, 224, 32);
|
||||
//for(int i=0; i<32; ++i)
|
||||
//{
|
||||
// sur->format->palette->colors[224+i] = palette[i];
|
||||
//}
|
||||
}
|
||||
else if(sur->format->BitsPerPixel == 24) //should never happen in general
|
||||
{
|
||||
|
@ -829,7 +829,7 @@ void CSDL_Ext::update(SDL_Surface * what)
|
||||
if(what)
|
||||
SDL_UpdateRect(what, 0, 0, what->w, what->h);
|
||||
}
|
||||
void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, int3 color)
|
||||
void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color)
|
||||
{
|
||||
for(int i=0;i<w;i++)
|
||||
{
|
||||
@ -842,6 +842,12 @@ void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, int3 co
|
||||
SDL_PutPixelWithoutRefresh(sur,x+w-1,y+i,color.x,color.y,color.z);
|
||||
}
|
||||
}
|
||||
|
||||
void CSDL_Ext::drawBorder( SDL_Surface * sur, const SDL_Rect &r, const int3 &color )
|
||||
{
|
||||
drawBorder(sur, r.x, r.y, r.w, r.h, color);
|
||||
}
|
||||
|
||||
void CSDL_Ext::setPlayerColor(SDL_Surface * sur, unsigned char player)
|
||||
{
|
||||
if(player==254)
|
||||
|
@ -124,7 +124,8 @@ namespace CSDL_Ext
|
||||
void printAtMiddleWB(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, bool refrsh = false);
|
||||
|
||||
void update(SDL_Surface * what = screen); //updates whole surface (default - main screen)
|
||||
void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, int3 color);
|
||||
void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color);
|
||||
void drawBorder(SDL_Surface * sur, const SDL_Rect &r, const int3 &color);
|
||||
void setPlayerColor(SDL_Surface * sur, unsigned char player); //sets correct color of flags; -1 for neutral
|
||||
std::string processStr(std::string str, std::vector<std::string> & tor); //replaces %s in string
|
||||
SDL_Surface * newSurface(int w, int h, SDL_Surface * mod=screen); //creates new surface, with flags/format same as in surface given
|
||||
|
@ -167,7 +167,7 @@ Names_of_Units_DEFS_in_order_of_ID
|
||||
165 ZM165GD.DEF
|
||||
166 ZM166GD.DEF
|
||||
167 ZM167GD.DEF
|
||||
168 ZM168GD.DEF
|
||||
168 ZM168DG.DEF
|
||||
169 ZM169ZL.DEF
|
||||
170 ZM170SW.DEF
|
||||
171 ZM171SR.DEF
|
||||
|
@ -14,6 +14,7 @@ CASTLE 0
|
||||
37
|
||||
16
|
||||
6
|
||||
20
|
||||
18
|
||||
19
|
||||
34
|
||||
|
@ -7,6 +7,9 @@ GROUP
|
||||
3
|
||||
4
|
||||
GROUP
|
||||
6
|
||||
20
|
||||
GROUP
|
||||
7
|
||||
8
|
||||
9
|
||||
|
@ -160,6 +160,7 @@
|
||||
+ 117 SPELL_DAMAGE_REDUCTION 95 -1 0 //diamond golems reduce dmg from spells
|
||||
+ 121 LEVEL_SPELL_IMMUNITY 5 0 0 //magic elementals are immune to all spells
|
||||
+ 123 DOUBLE_WIDE 0 0 0 //ice elemental should be treated as double-wide
|
||||
- 133 FLYING //Crystal Dragons do not fly
|
||||
+ 140 DOUBLE_WIDE 0 0 0 //boar should be treated as double-wide
|
||||
+ 142 DOUBLE_WIDE 0 0 0 //nomads should be treated as double-wide
|
||||
+ 144 FULL_HP_REGENERATION 0 0 0 //troll
|
||||
|
2
global.h
2
global.h
@ -20,7 +20,7 @@ typedef boost::int8_t si8; //signed int 8 bits (1 byte)
|
||||
#define THC
|
||||
#endif
|
||||
|
||||
#define NAME_VER ("VCMI 0.73b")
|
||||
#define NAME_VER ("VCMI 0.73c")
|
||||
extern std::string NAME; //full name
|
||||
extern std::string NAME_AFFIX; //client / server
|
||||
#define CONSOLE_LOGGING_LEVEL 5
|
||||
|
@ -1582,7 +1582,7 @@ int3 CGTownInstance::getSightCenter() const
|
||||
|
||||
void CGTownInstance::getOutOffsets( std::vector<int3> &offsets ) const
|
||||
{
|
||||
offsets += int3(-1,3,0), int3(-3,3,0);
|
||||
offsets += int3(-1,2,0), int3(-3,2,0);
|
||||
}
|
||||
|
||||
void CGTownInstance::fightOver( const CGHeroInstance *h, BattleResult *result ) const
|
||||
|
@ -661,36 +661,36 @@ std::pair< std::vector<int>, int > BattleInfo::getPath(int start, int dest, bool
|
||||
return std::make_pair(path, dist[dest]);
|
||||
}
|
||||
|
||||
int CStack::valOfFeatures(StackFeature::ECombatFeatures type, int subtype) const
|
||||
int CStack::valOfFeatures(StackFeature::ECombatFeatures type, int subtype, int turn) const
|
||||
{
|
||||
int ret = 0;
|
||||
if(subtype == -1024) //any subtype
|
||||
{
|
||||
for(std::vector<StackFeature>::const_iterator i=features.begin(); i != features.end(); i++)
|
||||
if(i->type == type)
|
||||
if(i->type == type && (!turn || i->turnsRemain > turn))
|
||||
ret += i->value;
|
||||
}
|
||||
else //given subtype
|
||||
{
|
||||
for(std::vector<StackFeature>::const_iterator i=features.begin(); i != features.end(); i++)
|
||||
if(i->type == type && i->subtype == subtype)
|
||||
if(i->type == type && i->subtype == subtype && (!turn || i->turnsRemain > turn))
|
||||
ret += i->value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CStack::hasFeatureOfType(StackFeature::ECombatFeatures type, int subtype) const
|
||||
bool CStack::hasFeatureOfType(StackFeature::ECombatFeatures type, int subtype, int turn) const
|
||||
{
|
||||
if(subtype == -1024) //any subtype
|
||||
{
|
||||
for(std::vector<StackFeature>::const_iterator i=features.begin(); i != features.end(); i++)
|
||||
if(i->type == type)
|
||||
if(i->type == type && (!turn || i->turnsRemain > turn))
|
||||
return true;
|
||||
}
|
||||
else //given subtype
|
||||
{
|
||||
for(std::vector<StackFeature>::const_iterator i=features.begin(); i != features.end(); i++)
|
||||
if(i->type == type && i->subtype == subtype)
|
||||
if(i->type == type && i->subtype == subtype && (!turn || i->turnsRemain > turn))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -712,19 +712,19 @@ CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
|
||||
state.insert(ALIVE);
|
||||
}
|
||||
|
||||
ui32 CStack::Speed() const
|
||||
ui32 CStack::Speed( int turn /*= 0*/ ) const
|
||||
{
|
||||
if(hasFeatureOfType(StackFeature::SIEGE_WEAPON)) //war machnes cannot move
|
||||
if(hasFeatureOfType(StackFeature::SIEGE_WEAPON, -1024, turn)) //war machnes cannot move
|
||||
return 0;
|
||||
|
||||
int speed = creature->speed;
|
||||
|
||||
speed += valOfFeatures(StackFeature::SPEED_BONUS);
|
||||
speed += valOfFeatures(StackFeature::SPEED_BONUS, -1024, turn);
|
||||
|
||||
int percentBonus = 0;
|
||||
for(int g=0; g<features.size(); ++g)
|
||||
{
|
||||
if(features[g].type == StackFeature::SPEED_BONUS)
|
||||
if(features[g].type == StackFeature::SPEED_BONUS, -1024, turn)
|
||||
{
|
||||
percentBonus += features[g].additionalInfo;
|
||||
}
|
||||
@ -748,11 +748,12 @@ ui32 CStack::Speed() const
|
||||
return speed;
|
||||
}
|
||||
|
||||
const CStack::StackEffect * CStack::getEffect(ui16 id) const
|
||||
const CStack::StackEffect * CStack::getEffect( ui16 id, int turn /*= 0*/ ) const
|
||||
{
|
||||
for (unsigned int i=0; i< effects.size(); i++)
|
||||
if(effects[i].id == id)
|
||||
return &effects[i];
|
||||
if(!turn || effects[i].turnsRemain > turn)
|
||||
return &effects[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -838,22 +839,25 @@ ui16 CStack::MaxHealth() const
|
||||
return creature->hitPoints + valOfFeatures(StackFeature::HP_BONUS);
|
||||
}
|
||||
|
||||
bool CStack::willMove() const
|
||||
bool CStack::willMove(int turn /*= 0*/) const
|
||||
{
|
||||
return !vstd::contains(state, DEFENDING)
|
||||
&& !moved()
|
||||
&& canMove();
|
||||
return ( turn ? true : !vstd::contains(state, DEFENDING) )
|
||||
&& !moved(turn)
|
||||
&& canMove(turn);
|
||||
}
|
||||
|
||||
bool CStack::canMove() const
|
||||
bool CStack::canMove( int turn /*= 0*/ ) const
|
||||
{
|
||||
return alive()
|
||||
&& ! hasFeatureOfType(StackFeature::NOT_ACTIVE); //eg. Ammo Cart
|
||||
&& !hasFeatureOfType(StackFeature::NOT_ACTIVE, -1024, turn); //eg. Ammo Cart
|
||||
}
|
||||
|
||||
bool CStack::moved() const
|
||||
bool CStack::moved( int turn /*= 0*/ ) const
|
||||
{
|
||||
return vstd::contains(state, MOVED);
|
||||
if(!turn)
|
||||
return vstd::contains(state, MOVED);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, std::map<ui32,CGHeroInstance *> &available) const
|
||||
@ -2150,6 +2154,15 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
|
||||
int cost = getMovementCost(hero, cp->coord, dp.coord, movement);
|
||||
int remains = movement - cost;
|
||||
|
||||
if(remains < 0)
|
||||
{
|
||||
//occurs rarely, when hero with low movepoints tries to go leave the road
|
||||
turn++;
|
||||
movement = hero->maxMovePoints(ct.tertype != TerrainTile::water);
|
||||
cost = getMovementCost(hero, cp->coord, dp.coord, movement); //cost must be updated, movement points changed :(
|
||||
remains = movement - cost;
|
||||
}
|
||||
|
||||
if(dp.turns==0xff //we haven't been here before
|
||||
|| dp.turns > turn
|
||||
|| (dp.turns >= turn && dp.moveRemains < remains)) //this route is faster
|
||||
@ -2760,7 +2773,7 @@ bool CGameState::battleCanShoot(int ID, int dest)
|
||||
const CStack * BattleInfo::getNextStack() const
|
||||
{
|
||||
std::vector<const CStack *> hlp;
|
||||
getStackQueue(hlp, 1, 2);
|
||||
getStackQueue(hlp, 1, -1);
|
||||
|
||||
if(hlp.size())
|
||||
return hlp[0];
|
||||
@ -2768,7 +2781,7 @@ const CStack * BattleInfo::getNextStack() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const CStack *takeStack(std::vector<const CStack *> &st, int &curside)
|
||||
static const CStack *takeStack(std::vector<const CStack *> &st, int &curside, int turn)
|
||||
{
|
||||
const CStack *ret = NULL;
|
||||
unsigned i, //fastest stack
|
||||
@ -2782,7 +2795,7 @@ static const CStack *takeStack(std::vector<const CStack *> &st, int &curside)
|
||||
return NULL;
|
||||
|
||||
const CStack *fastest = st[i], *other = NULL;
|
||||
int bestSpeed = fastest->Speed();
|
||||
int bestSpeed = fastest->Speed(turn);
|
||||
|
||||
if(fastest->attackerOwned != curside)
|
||||
{
|
||||
@ -2793,7 +2806,7 @@ static const CStack *takeStack(std::vector<const CStack *> &st, int &curside)
|
||||
for(j = i + 1; j < st.size(); j++)
|
||||
{
|
||||
if(!st[j]) continue;
|
||||
if(st[j]->attackerOwned != curside || st[j]->Speed() != bestSpeed)
|
||||
if(st[j]->attackerOwned != curside || st[j]->Speed(turn) != bestSpeed)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2804,7 +2817,7 @@ static const CStack *takeStack(std::vector<const CStack *> &st, int &curside)
|
||||
else
|
||||
{
|
||||
other = st[j];
|
||||
if(other->Speed() != bestSpeed)
|
||||
if(other->Speed(turn) != bestSpeed)
|
||||
ret = fastest;
|
||||
else
|
||||
ret = other;
|
||||
@ -2821,43 +2834,55 @@ static const CStack *takeStack(std::vector<const CStack *> &st, int &curside)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, int mode, int lastMoved ) const
|
||||
void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, int turn /*= 0*/, int lastMoved /*= -1*/ ) const
|
||||
{
|
||||
//we'll split creatures with remaining movement to 4 parts
|
||||
std::vector<const CStack *> phase[4]; //0 - turrets/catapult, 1 - normal (unmoved) creatures, other war machines, 2 - waited cres that had morale, 3 - rest of waited cres
|
||||
int toMove = 0; //how many stacks still has move
|
||||
const CStack *active = getStack(activeStack);
|
||||
|
||||
//active stack hasn't taken any action yet - must be placed at the beginning of queue, no matter what
|
||||
if(!turn && active && active->willMove() && !vstd::contains(active->state, WAITING))
|
||||
{
|
||||
out.push_back(active);
|
||||
if(out.size() == howMany)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for(unsigned int i=0; i<stacks.size(); ++i)
|
||||
{
|
||||
const CStack * const s = stacks[i];
|
||||
if(mode != 1 && s->willMove()
|
||||
|| mode == 1 && s->canMove())
|
||||
if(turn <= 0 && !s->willMove() //we are considering current round and stack won't move
|
||||
|| turn > 0 && !s->canMove(turn) //stack won't be able to move in later rounds
|
||||
|| turn <= 0 && s == active) //it's active stack already added at the beginning of queue
|
||||
{
|
||||
int p = -1; //in which phase this tack will move?
|
||||
if(!mode && vstd::contains(s->state, WAITING))
|
||||
{
|
||||
if(vstd::contains(s->state, HAD_MORALE))
|
||||
p = 2;
|
||||
else
|
||||
p = 3;
|
||||
}
|
||||
else if(vstd::contains(s->state, StackFeature::SIEGE_WEAPON) //catapult and turrets are first
|
||||
&& (s->creature->idNumber == 145 || s->creature->idNumber == 149))
|
||||
{
|
||||
p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = 1;
|
||||
}
|
||||
|
||||
phase[p].push_back(s);
|
||||
toMove++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int p = -1; //in which phase this tack will move?
|
||||
if(turn <= 0 && vstd::contains(s->state, WAITING)) //consider waiting state only for ongoing round
|
||||
{
|
||||
if(vstd::contains(s->state, HAD_MORALE))
|
||||
p = 2;
|
||||
else
|
||||
p = 3;
|
||||
}
|
||||
else if(s->creature->idNumber == 145 || s->creature->idNumber == 149) //catapult and turrets are first
|
||||
{
|
||||
p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = 1;
|
||||
}
|
||||
|
||||
phase[p].push_back(s);
|
||||
toMove++;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
std::sort(phase[i].begin(), phase[i].end(), CMP_stack(i));
|
||||
std::sort(phase[i].begin(), phase[i].end(), CMP_stack(i, turn > 0 ? turn : 0));
|
||||
|
||||
for(size_t i = 0; i < phase[0].size() && i < howMany; i++)
|
||||
out.push_back(phase[0][i]);
|
||||
@ -2867,12 +2892,12 @@ void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, i
|
||||
|
||||
if(lastMoved == -1)
|
||||
{
|
||||
const CStack *current = getStack(activeStack);
|
||||
if(current)
|
||||
if(active)
|
||||
{
|
||||
lastMoved = !current->attackerOwned;
|
||||
if(!current->willMove() || mode == 2)
|
||||
lastMoved = !lastMoved;
|
||||
if(out.size() && out.front() == active)
|
||||
lastMoved = active->attackerOwned;
|
||||
else
|
||||
lastMoved = active->attackerOwned;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2883,14 +2908,14 @@ void BattleInfo::getStackQueue( std::vector<const CStack *> &out, int howMany, i
|
||||
int pi = 1;
|
||||
while(out.size() < howMany)
|
||||
{
|
||||
const CStack *hlp = takeStack(phase[pi], lastMoved);
|
||||
const CStack *hlp = takeStack(phase[pi], lastMoved, turn);
|
||||
if(!hlp)
|
||||
{
|
||||
pi++;
|
||||
if(pi > 3)
|
||||
{
|
||||
if(mode != 2)
|
||||
getStackQueue(out, howMany, 1, lastMoved);
|
||||
//if(turn != 2)
|
||||
getStackQueue(out, howMany, turn + 1, lastMoved);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3003,7 +3028,7 @@ bool CMP_stack::operator()( const CStack* a, const CStack* b )
|
||||
//TODO? turrets order
|
||||
case 1: //fastest first, upper slot first
|
||||
{
|
||||
int as = a->Speed(), bs = b->Speed();
|
||||
int as = a->Speed(turn), bs = b->Speed(turn);
|
||||
if(as != bs)
|
||||
return as > bs;
|
||||
else
|
||||
@ -3013,7 +3038,7 @@ bool CMP_stack::operator()( const CStack* a, const CStack* b )
|
||||
//TODO: should be replaced with order of receiving morale!
|
||||
case 3: //fastest last, upper slot first
|
||||
{
|
||||
int as = a->Speed(), bs = b->Speed();
|
||||
int as = a->Speed(turn), bs = b->Speed(turn);
|
||||
if(as != bs)
|
||||
return as < bs;
|
||||
else
|
||||
@ -3026,9 +3051,10 @@ bool CMP_stack::operator()( const CStack* a, const CStack* b )
|
||||
|
||||
}
|
||||
|
||||
CMP_stack::CMP_stack( int Phase /*= 1*/ )
|
||||
CMP_stack::CMP_stack( int Phase /*= 1*/, int Turn )
|
||||
{
|
||||
phase = Phase;
|
||||
turn = Turn;
|
||||
}
|
||||
|
||||
PlayerState::PlayerState()
|
||||
|
@ -138,7 +138,7 @@ struct DLL_EXPORT BattleInfo
|
||||
& castSpells & si;
|
||||
}
|
||||
const CStack * getNextStack() const; //which stack will have turn after current one
|
||||
void getStackQueue(std::vector<const CStack *> &out, int howMany, int mode = 0, int lastMoved = -1) const; //returns stack in order of their movement action
|
||||
void getStackQueue(std::vector<const CStack *> &out, int howMany, int turn = 0, int lastMoved = -1) const; //returns stack in order of their movement action
|
||||
CStack * getStack(int stackID, bool onlyAlive = true);
|
||||
const CStack * getStack(int stackID, bool onlyAlive = true) const;
|
||||
CStack * getStackT(int tileID, bool onlyAlive = true);
|
||||
@ -191,17 +191,17 @@ public:
|
||||
};
|
||||
std::vector<StackEffect> effects;
|
||||
|
||||
int valOfFeatures(StackFeature::ECombatFeatures type, int subtype = -1024) const;//subtype -> subtype of bonus, if -1024 then any
|
||||
bool hasFeatureOfType(StackFeature::ECombatFeatures type, int subtype = -1024) const; //determines if stack has a bonus of given type (and optionally subtype)
|
||||
int valOfFeatures(StackFeature::ECombatFeatures type, int subtype = -1024, int turn = 0) const;//subtype -> subtype of bonus, if -1024 then any
|
||||
bool hasFeatureOfType(StackFeature::ECombatFeatures type, int subtype = -1024, int turn = 0) const; //determines if stack has a bonus of given type (and optionally subtype)
|
||||
|
||||
CStack(CCreature * C, int A, int O, int I, bool AO, int S); //c-tor
|
||||
CStack() : ID(-1), creature(NULL), amount(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1) {} //c-tor
|
||||
const StackEffect * getEffect(ui16 id) const; //effect id (SP)
|
||||
const StackEffect * getEffect(ui16 id, int turn = 0) const; //effect id (SP)
|
||||
ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
|
||||
bool willMove() const; //if stack has remaining move this turn
|
||||
bool moved() const; //if stack was already moved this turn
|
||||
bool canMove() const; //if stack can move
|
||||
ui32 Speed() const; //get speed of creature with all modificators
|
||||
bool willMove(int turn = 0) const; //if stack has remaining move this turn
|
||||
bool moved(int turn = 0) const; //if stack was already moved this turn
|
||||
bool canMove(int turn = 0) const; //if stack can move
|
||||
ui32 Speed(int turn = 0) const; //get speed of creature with all modificators
|
||||
si8 Morale() const; //get morale of stack with all modificators
|
||||
si8 Luck() const; //get luck of stack with all modificators
|
||||
si32 Attack() const; //get attack of stack with all modificators
|
||||
@ -236,10 +236,11 @@ public:
|
||||
class DLL_EXPORT CMP_stack
|
||||
{
|
||||
int phase; //rules of which phase will be used
|
||||
int turn;
|
||||
public:
|
||||
|
||||
bool operator ()(const CStack* a, const CStack* b);
|
||||
CMP_stack(int Phase = 1);
|
||||
CMP_stack(int Phase = 1, int Turn = 0);
|
||||
};
|
||||
|
||||
struct UpgradeInfo
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
const ui32 version = 708;
|
||||
const ui32 version = 709;
|
||||
class CConnection;
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <fstream>
|
||||
#include <boost/system/system_error.hpp>
|
||||
|
||||
/*
|
||||
* CGameHandler.cpp, part of VCMI engine
|
||||
@ -623,6 +624,11 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
||||
pack = NULL;
|
||||
}
|
||||
}
|
||||
catch(boost::system::system_error &e) //for boost errors just log, not crash - probably client shut down connection
|
||||
{
|
||||
tlog1 << e.what() << std::endl;
|
||||
end2 = true;
|
||||
}
|
||||
HANDLE_EXCEPTION(end2 = true);
|
||||
handleConEnd:
|
||||
tlog1 << "Ended handling connection\n";
|
||||
@ -637,6 +643,9 @@ int CGameHandler::moveStack(int stack, int dest)
|
||||
CStack *curStack = gs->curB->getStack(stack),
|
||||
*stackAtEnd = gs->curB->getStackT(dest);
|
||||
|
||||
assert(curStack);
|
||||
assert(dest < BFIELD_SIZE);
|
||||
|
||||
//initing necessary tables
|
||||
bool accessibility[BFIELD_SIZE];
|
||||
std::vector<int> accessible = gs->curB->getAccessibility(curStack->ID, false);
|
||||
@ -1393,7 +1402,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
|
||||
//OR hero is on land and dest is water and (there is not present only one object - boat)
|
||||
if((t.tertype == TerrainTile::rock || (t.blocked && !t.visitable))
|
||||
&& complain("Cannot move hero, destination tile is blocked!")
|
||||
|| (!h->boat && !h->canWalkOnSea() && t.tertype == TerrainTile::water && (t.visitableObjects.size() != 1 || t.visitableObjects.front()->ID != 8))
|
||||
|| (!h->boat && !h->canWalkOnSea() && t.tertype == TerrainTile::water && (t.visitableObjects.size() != 1 || (t.visitableObjects.front()->ID != 8 && t.visitableObjects.front()->ID != HEROI_TYPE))) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land)
|
||||
&& complain("Cannot move hero, destination tile is on water!")
|
||||
|| (h->boat && t.tertype != TerrainTile::water && t.blocked)
|
||||
&& complain("Cannot disembark hero, tile is blocked!")
|
||||
|
@ -258,6 +258,11 @@ int main(int argc, char** argv)
|
||||
server.start();
|
||||
}
|
||||
io_service.run();
|
||||
} HANDLE_EXCEPTION
|
||||
}
|
||||
catch(boost::system::system_error &e) //for boost errors just log, not crash - probably client shut down connection
|
||||
{
|
||||
tlog1 << e.what() << std::endl;
|
||||
end2 = true;
|
||||
}HANDLE_EXCEPTION
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user