mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
* Final commit
This commit is contained in:
51
client/BattleInterface/CAttackAnimation.cpp
Normal file
51
client/BattleInterface/CAttackAnimation.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "StdInc.h"
|
||||
#include "CAttackAnimation.h"
|
||||
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CCreatureAnimation.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../../CCallback.h"
|
||||
|
||||
void CAttackAnimation::nextFrame()
|
||||
{
|
||||
if(myAnim()->getType() != group)
|
||||
myAnim()->setType(group);
|
||||
|
||||
if(myAnim()->onFirstFrameInGroup())
|
||||
{
|
||||
if(shooting)
|
||||
CCS->soundh->playSound(battle_sound(attackingStack->getCreature(), shoot));
|
||||
else
|
||||
CCS->soundh->playSound(battle_sound(attackingStack->getCreature(), attack));
|
||||
}
|
||||
else if(myAnim()->onLastFrameInGroup())
|
||||
{
|
||||
myAnim()->setType(CCreatureAnim::HOLDING);
|
||||
endAnim();
|
||||
return; //execution of endAnim deletes this !!!
|
||||
}
|
||||
}
|
||||
|
||||
bool CAttackAnimation::checkInitialConditions()
|
||||
{
|
||||
return isEarliest(false);
|
||||
}
|
||||
|
||||
CAttackAnimation::CAttackAnimation(CBattleInterface *_owner, const CStack *attacker, SHexField _dest, const CStack *defender)
|
||||
: CBattleStackAnimation(_owner, attacker), dest(_dest), attackedStack(defender), attackingStack(attacker)
|
||||
{
|
||||
|
||||
assert(attackingStack && "attackingStack is NULL in CBattleAttack::CBattleAttack !\n");
|
||||
if(attackingStack->getCreature()->idNumber != 145) //catapult is allowed to attack not-creature
|
||||
{
|
||||
assert(attackedStack && "attackedStack is NULL in CBattleAttack::CBattleAttack !\n");
|
||||
}
|
||||
else //catapult can attack walls only
|
||||
{
|
||||
assert(owner->curInt->cb->battleGetWallUnderHex(_dest) >= 0);
|
||||
}
|
||||
attackingStackPosBeforeReturn = attackingStack->position;
|
||||
}
|
||||
35
client/BattleInterface/CAttackAnimation.h
Normal file
35
client/BattleInterface/CAttackAnimation.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "CBattleStackAnimation.h"
|
||||
#include "../CAnimation.h"
|
||||
#include "../../lib/SHexField.h"
|
||||
|
||||
class CBattleInterface;
|
||||
class CStack;
|
||||
|
||||
/*
|
||||
* CAttackAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// This class is responsible for managing the battle attack animation
|
||||
class CAttackAnimation : public CBattleStackAnimation
|
||||
{
|
||||
protected:
|
||||
SHexField dest; //attacked hex
|
||||
bool shooting;
|
||||
CCreatureAnim::EAnimType group; //if shooting is true, print this animation group
|
||||
const CStack *attackedStack;
|
||||
const CStack *attackingStack;
|
||||
int attackingStackPosBeforeReturn; //for stacks with return_after_strike feature
|
||||
public:
|
||||
void nextFrame();
|
||||
bool checkInitialConditions();
|
||||
|
||||
CAttackAnimation(CBattleInterface *_owner, const CStack *attacker, SHexField _dest, const CStack *defender);
|
||||
};
|
||||
49
client/BattleInterface/CBattleAnimation.cpp
Normal file
49
client/BattleInterface/CBattleAnimation.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "StdInc.h"
|
||||
#include "CBattleAnimation.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "CSpellEffectAnimation.h"
|
||||
#include "CReverseAnimation.h"
|
||||
|
||||
void CBattleAnimation::endAnim()
|
||||
{
|
||||
for(std::list<std::pair<CBattleAnimation *, bool> >::iterator it = owner->pendingAnims.begin(); it != owner->pendingAnims.end(); ++it)
|
||||
{
|
||||
if(it->first == this)
|
||||
{
|
||||
it->first = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool CBattleAnimation::isEarliest(bool perStackConcurrency)
|
||||
{
|
||||
int lowestMoveID = owner->animIDhelper + 5;
|
||||
CBattleStackAnimation * thAnim = dynamic_cast<CBattleStackAnimation *>(this);
|
||||
CSpellEffectAnimation * thSen = dynamic_cast<CSpellEffectAnimation *>(this);
|
||||
|
||||
for(std::list<std::pair<CBattleAnimation *, bool> >::iterator it = owner->pendingAnims.begin(); it != owner->pendingAnims.end(); ++it)
|
||||
{
|
||||
CBattleStackAnimation * stAnim = dynamic_cast<CBattleStackAnimation *>(it->first);
|
||||
CSpellEffectAnimation * sen = dynamic_cast<CSpellEffectAnimation *>(it->first);
|
||||
if(perStackConcurrency && stAnim && thAnim && stAnim->stack->ID != thAnim->stack->ID)
|
||||
continue;
|
||||
|
||||
if(sen && thSen && sen != thSen && perStackConcurrency)
|
||||
continue;
|
||||
|
||||
CReverseAnimation * revAnim = dynamic_cast<CReverseAnimation *>(stAnim);
|
||||
|
||||
if(revAnim && thAnim && stAnim && stAnim->stack->ID == thAnim->stack->ID && revAnim->priority)
|
||||
return false;
|
||||
|
||||
if(it->first)
|
||||
vstd::amin(lowestMoveID, it->first->ID);
|
||||
}
|
||||
return (ID == lowestMoveID) || (lowestMoveID == (owner->animIDhelper + 5));
|
||||
}
|
||||
|
||||
CBattleAnimation::CBattleAnimation(CBattleInterface * _owner)
|
||||
: owner(_owner), ID(_owner->animIDhelper++)
|
||||
{}
|
||||
30
client/BattleInterface/CBattleAnimation.h
Normal file
30
client/BattleInterface/CBattleAnimation.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
class CBattleInterface;
|
||||
|
||||
/*
|
||||
* CBattleAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Base class of battle animations
|
||||
class CBattleAnimation
|
||||
{
|
||||
protected:
|
||||
CBattleInterface * owner;
|
||||
public:
|
||||
virtual bool init()=0; //to be called - if returned false, call again until returns true
|
||||
virtual void nextFrame()=0; //call every new frame
|
||||
virtual void endAnim(); //to be called mostly internally; in this class it removes animation from pendingAnims list
|
||||
|
||||
bool isEarliest(bool perStackConcurrency); //determines if this animation is earliest of all
|
||||
|
||||
ui32 ID; //unique identifier
|
||||
|
||||
CBattleAnimation(CBattleInterface * _owner);
|
||||
};
|
||||
84
client/BattleInterface/CBattleConsole.cpp
Normal file
84
client/BattleInterface/CBattleConsole.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "StdInc.h"
|
||||
#include "CBattleConsole.h"
|
||||
#include "../SDL_Extensions.h"
|
||||
|
||||
CBattleConsole::CBattleConsole() : lastShown(-1), alterTxt(""), whoSetAlter(0)
|
||||
{
|
||||
}
|
||||
|
||||
CBattleConsole::~CBattleConsole()
|
||||
{
|
||||
texts.clear();
|
||||
}
|
||||
|
||||
void CBattleConsole::show(SDL_Surface * to)
|
||||
{
|
||||
if(ingcAlter.size())
|
||||
{
|
||||
CSDL_Ext::printAtMiddleWB(ingcAlter, pos.x + pos.w/2, pos.y + 11, FONT_SMALL, 80, zwykly, to);
|
||||
}
|
||||
else if(alterTxt.size())
|
||||
{
|
||||
CSDL_Ext::printAtMiddleWB(alterTxt, pos.x + pos.w/2, pos.y + 11, FONT_SMALL, 80, zwykly, to);
|
||||
}
|
||||
else if(texts.size())
|
||||
{
|
||||
if(texts.size()==1)
|
||||
{
|
||||
CSDL_Ext::printAtMiddleWB(texts[0], pos.x + pos.w/2, pos.y + 11, FONT_SMALL, 80, zwykly, to);
|
||||
}
|
||||
else
|
||||
{
|
||||
CSDL_Ext::printAtMiddleWB(texts[lastShown-1], pos.x + pos.w/2, pos.y + 11, FONT_SMALL, 80, zwykly, to);
|
||||
CSDL_Ext::printAtMiddleWB(texts[lastShown], pos.x + pos.w/2, pos.y + 27, FONT_SMALL, 80, zwykly, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CBattleConsole::addText(const std::string & text)
|
||||
{
|
||||
if(text.size()>70)
|
||||
return false; //text too long!
|
||||
int firstInToken = 0;
|
||||
for(size_t i = 0; i < text.size(); ++i) //tokenize
|
||||
{
|
||||
if(text[i] == 10)
|
||||
{
|
||||
texts.push_back( text.substr(firstInToken, i-firstInToken) );
|
||||
firstInToken = i+1;
|
||||
}
|
||||
}
|
||||
|
||||
texts.push_back( text.substr(firstInToken, text.size()) );
|
||||
lastShown = texts.size()-1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBattleConsole::eraseText(ui32 pos)
|
||||
{
|
||||
if(pos < texts.size())
|
||||
{
|
||||
texts.erase(texts.begin() + pos);
|
||||
if(lastShown == texts.size())
|
||||
--lastShown;
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleConsole::changeTextAt(const std::string & text, ui32 pos)
|
||||
{
|
||||
if(pos >= texts.size()) //no such pos
|
||||
return;
|
||||
texts[pos] = text;
|
||||
}
|
||||
|
||||
void CBattleConsole::scrollUp(ui32 by)
|
||||
{
|
||||
if(lastShown > static_cast<int>(by))
|
||||
lastShown -= by;
|
||||
}
|
||||
|
||||
void CBattleConsole::scrollDown(ui32 by)
|
||||
{
|
||||
if(lastShown + by < texts.size())
|
||||
lastShown += by;
|
||||
}
|
||||
35
client/BattleInterface/CBattleConsole.h
Normal file
35
client/BattleInterface/CBattleConsole.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GUIBase.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
|
||||
/*
|
||||
* CBattleConsole.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Class which shows the console at the bottom of the battle screen and manages the text of the console
|
||||
class CBattleConsole : public CIntObject
|
||||
{
|
||||
private:
|
||||
std::vector< std::string > texts; //a place where texts are stored
|
||||
int lastShown; //last shown line of text
|
||||
public:
|
||||
std::string alterTxt; //if it's not empty, this text is displayed
|
||||
std::string ingcAlter; //alternative text set by in-game console - very important!
|
||||
int whoSetAlter; //who set alter text; 0 - battle interface or none, 1 - button
|
||||
CBattleConsole(); //c-tor
|
||||
~CBattleConsole(); //d-tor
|
||||
void show(SDL_Surface *to = 0);
|
||||
bool addText(const std::string &text); //adds text at the last position; returns false if failed (e.g. text longer than 70 characters)
|
||||
void eraseText(ui32 pos); //erases added text at position pos
|
||||
void changeTextAt(const std::string &text, ui32 pos); //if we have more than pos texts, pos-th is changed to given one
|
||||
void scrollUp(ui32 by = 1); //scrolls console up by 'by' positions
|
||||
void scrollDown(ui32 by = 1); //scrolls console up by 'by' positions
|
||||
};
|
||||
153
client/BattleInterface/CBattleHero.cpp
Normal file
153
client/BattleInterface/CBattleHero.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#include "StdInc.h"
|
||||
#include "CBattleHero.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CDefHandler.h"
|
||||
#include "../CCursorHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../SDL_Extensions.h"
|
||||
#include "../CSpellWindow.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../CConfigHandler.h"
|
||||
|
||||
void CBattleHero::show(SDL_Surface *to)
|
||||
{
|
||||
//animation of flag
|
||||
if(flip)
|
||||
{
|
||||
SDL_Rect temp_rect = genRect(
|
||||
flag->ourImages[flagAnim].bitmap->h,
|
||||
flag->ourImages[flagAnim].bitmap->w,
|
||||
pos.x + 61,
|
||||
pos.y + 39);
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(
|
||||
flag->ourImages[flagAnim].bitmap,
|
||||
NULL,
|
||||
screen,
|
||||
&temp_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_Rect temp_rect = genRect(
|
||||
flag->ourImages[flagAnim].bitmap->h,
|
||||
flag->ourImages[flagAnim].bitmap->w,
|
||||
pos.x + 72,
|
||||
pos.y + 39);
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(
|
||||
flag->ourImages[flagAnim].bitmap,
|
||||
NULL,
|
||||
screen,
|
||||
&temp_rect);
|
||||
}
|
||||
++flagAnimCount;
|
||||
if(flagAnimCount%4==0)
|
||||
{
|
||||
++flagAnim;
|
||||
flagAnim %= flag->ourImages.size();
|
||||
}
|
||||
//animation of hero
|
||||
int tick=-1;
|
||||
for(size_t i = 0; i < dh->ourImages.size(); ++i)
|
||||
{
|
||||
if(dh->ourImages[i].groupNumber==phase)
|
||||
++tick;
|
||||
if(tick==image)
|
||||
{
|
||||
SDL_Rect posb = pos;
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(dh->ourImages[i].bitmap, NULL, to, &posb);
|
||||
if(phase != 4 || nextPhase != -1 || image < 4)
|
||||
{
|
||||
if(flagAnimCount%2==0)
|
||||
{
|
||||
++image;
|
||||
}
|
||||
if(dh->ourImages[(i+1)%dh->ourImages.size()].groupNumber!=phase) //back to appropriate frame
|
||||
{
|
||||
image = 0;
|
||||
}
|
||||
}
|
||||
if(phase == 4 && nextPhase != -1 && image == 7)
|
||||
{
|
||||
phase = nextPhase;
|
||||
nextPhase = -1;
|
||||
image = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleHero::activate()
|
||||
{
|
||||
activateLClick();
|
||||
}
|
||||
void CBattleHero::deactivate()
|
||||
{
|
||||
deactivateLClick();
|
||||
}
|
||||
|
||||
void CBattleHero::setPhase(int newPhase)
|
||||
{
|
||||
if(phase != 4)
|
||||
{
|
||||
phase = newPhase;
|
||||
image = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextPhase = newPhase;
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleHero::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(myOwner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if(!down && myHero != NULL && myOwner->myTurn && myOwner->curInt->cb->battleCanCastSpell()) //check conditions
|
||||
{
|
||||
for(int it=0; it<GameConstants::BFIELD_SIZE; ++it) //do nothing when any hex is hovered - hero's animation overlaps battlefield
|
||||
{
|
||||
if(myOwner->bfield[it].hovered && myOwner->bfield[it].strictHovered)
|
||||
return;
|
||||
}
|
||||
CCS->curh->changeGraphic(0,0);
|
||||
|
||||
CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), myHero, myOwner->curInt);
|
||||
GH.pushInt(spellWindow);
|
||||
}
|
||||
}
|
||||
|
||||
CBattleHero::CBattleHero(const std::string & defName, int phaseG, int imageG, bool flipG, ui8 player, const CGHeroInstance * hero, const CBattleInterface * owner): flip(flipG), myHero(hero), myOwner(owner), phase(phaseG), nextPhase(-1), image(imageG), flagAnim(0), flagAnimCount(0)
|
||||
{
|
||||
dh = CDefHandler::giveDef( defName );
|
||||
for(size_t i = 0; i < dh->ourImages.size(); ++i) //transforming images
|
||||
{
|
||||
if(flip)
|
||||
{
|
||||
SDL_Surface * hlp = CSDL_Ext::rotate01(dh->ourImages[i].bitmap);
|
||||
SDL_FreeSurface(dh->ourImages[i].bitmap);
|
||||
dh->ourImages[i].bitmap = hlp;
|
||||
}
|
||||
CSDL_Ext::alphaTransform(dh->ourImages[i].bitmap);
|
||||
}
|
||||
|
||||
if(flip)
|
||||
flag = CDefHandler::giveDef("CMFLAGR.DEF");
|
||||
else
|
||||
flag = CDefHandler::giveDef("CMFLAGL.DEF");
|
||||
|
||||
//coloring flag and adding transparency
|
||||
for(size_t i = 0; i < flag->ourImages.size(); ++i)
|
||||
{
|
||||
CSDL_Ext::alphaTransform(flag->ourImages[i].bitmap);
|
||||
graphics->blueToPlayersAdv(flag->ourImages[i].bitmap, player);
|
||||
}
|
||||
}
|
||||
|
||||
CBattleHero::~CBattleHero()
|
||||
{
|
||||
delete dh;
|
||||
delete flag;
|
||||
}
|
||||
39
client/BattleInterface/CBattleHero.h
Normal file
39
client/BattleInterface/CBattleHero.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GUIBase.h"
|
||||
|
||||
class CBattleInterface;
|
||||
class CDefHandler;
|
||||
class CGHeroInstance;
|
||||
struct SDL_Surface;
|
||||
|
||||
/*
|
||||
* CBattleHero.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Hero battle animation
|
||||
class CBattleHero : public CIntObject
|
||||
{
|
||||
public:
|
||||
bool flip; //false if it's attacking hero, true otherwise
|
||||
CDefHandler *dh, *flag; //animation and flag
|
||||
const CGHeroInstance *myHero; //this animation's hero instance
|
||||
const CBattleInterface *myOwner; //battle interface to which this animation is assigned
|
||||
int phase; //stage of animation
|
||||
int nextPhase; //stage of animation to be set after current phase is fully displayed
|
||||
int image; //frame of animation
|
||||
ui8 flagAnim, flagAnimCount; //for flag animation
|
||||
void show(SDL_Surface *to); //prints next frame of animation to to
|
||||
void activate();
|
||||
void deactivate();
|
||||
void setPhase(int newPhase); //sets phase of hero animation
|
||||
void clickLeft(tribool down, bool previousState); //call-in
|
||||
CBattleHero(const std::string &defName, int phaseG, int imageG, bool filpG, ui8 player, const CGHeroInstance *hero, const CBattleInterface *owner); //c-tor
|
||||
~CBattleHero(); //d-tor
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
256
client/BattleInterface/CBattleInterface.h
Normal file
256
client/BattleInterface/CBattleInterface.h
Normal file
@@ -0,0 +1,256 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../GUIBase.h"
|
||||
#include "../../lib/CCreatureSet.h"
|
||||
#include "../../lib/ConstTransitivePtr.h" //may be reundant
|
||||
#include "../CAnimation.h"
|
||||
#include "SStackAttackedInfo.h"
|
||||
#include "CHexFieldControl.h"
|
||||
#include "CShootingAnimation.h"
|
||||
#include "../../lib/SHexField.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
/*
|
||||
* CBattleInterface.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class CLabel;
|
||||
class CCreatureSet;
|
||||
class CGHeroInstance;
|
||||
class CDefHandler;
|
||||
class CStack;
|
||||
class CCallback;
|
||||
class AdventureMapButton;
|
||||
class CHighlightableButton;
|
||||
class CHighlightableButtonsGroup;
|
||||
struct BattleResult;
|
||||
struct BattleSpellCast;
|
||||
struct CObstacleInstance;
|
||||
template <typename T> struct CondSh;
|
||||
struct SetStackEffect;;
|
||||
struct BattleAction;
|
||||
class CGTownInstance;
|
||||
struct CatapultAttack;
|
||||
class CBattleInterface;
|
||||
struct SCatapultSProjectileInfo;
|
||||
struct BattleTriggerEffect;
|
||||
class CBattleAnimation;
|
||||
class CBattleHero;
|
||||
class CBattleConsole;
|
||||
class CBattleResultWindow;
|
||||
class CStackQueue;
|
||||
|
||||
/// Class which manages the locked hex fields that are blocked e.g. by obstacles
|
||||
class CBattleObstacle
|
||||
{
|
||||
std::vector<int> lockedHexes;
|
||||
};
|
||||
|
||||
/// Struct for battle effect animation e.g. morale, prayer, armageddon, bless,...
|
||||
struct SBattleEffect
|
||||
{
|
||||
int x, y; //position on the screen
|
||||
int frame, maxFrame;
|
||||
CDefHandler * anim; //animation to display
|
||||
int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim
|
||||
};
|
||||
|
||||
/// Small struct which is needed for drawing the parabolic trajectory of the catapult cannon
|
||||
struct SCatapultSProjectileInfo
|
||||
{
|
||||
const double facA, facB, facC;
|
||||
const int fromX, toX;
|
||||
|
||||
SCatapultSProjectileInfo() : facA(0), facB(0), facC(0), fromX(0), toX(0) { };
|
||||
SCatapultSProjectileInfo(double factorA, double factorB, double factorC, int fromXX, int toXX) : facA(factorA), facB(factorB), facC(factorC),
|
||||
fromX(fromXX), toX(toXX) { };
|
||||
|
||||
double calculateY(double x);
|
||||
};
|
||||
|
||||
/// Big class which handles the overall battle interface actions and it is also responsible for
|
||||
/// drawing everything correctly.
|
||||
class CBattleInterface : public CIntObject
|
||||
{
|
||||
enum SpellSelectionType
|
||||
{
|
||||
ANY_LOCATION = 0, FRIENDLY_CREATURE, HOSTILE_CREATURE, ANY_CREATURE, OBSTACLE, TELEPORT, NO_LOCATION = -1, STACK_SPELL_CANCELLED = -2
|
||||
};
|
||||
private:
|
||||
SDL_Surface * background, * menu, * amountNormal, * amountNegative, * amountPositive, * amountEffNeutral, * cellBorders, * backgroundWithHexes;
|
||||
AdventureMapButton * bOptions, * bSurrender, * bFlee, * bAutofight, * bSpell,
|
||||
* bWait, * bDefence, * bConsoleUp, * bConsoleDown, *btactNext, *btactEnd;
|
||||
CBattleConsole * console;
|
||||
CBattleHero * attackingHero, * defendingHero; //fighting heroes
|
||||
CStackQueue *queue;
|
||||
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
||||
const CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
|
||||
std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
||||
std::map< int, CDefHandler * > idToProjectile; //projectiles of creatures (creatureID, defhandler)
|
||||
std::map< int, CDefHandler * > idToObstacle; //obstacles located on the battlefield
|
||||
std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation>
|
||||
ui8 animCount;
|
||||
const CStack * activeStack; //number of active stack; NULL - no one
|
||||
const CStack * stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; NULL of none
|
||||
void activateStack(); //sets activeStack to stackToActivate etc.
|
||||
int mouseHoveredStack; //stack hovered by mouse; if -1 -> none
|
||||
time_t lastMouseHoveredStackAnimationTime; // time when last mouse hovered animation occurred
|
||||
static const time_t HOVER_ANIM_DELTA;
|
||||
std::vector<SHexField> occupyableHexes, //hexes available for active stack
|
||||
attackableHexes; //hexes attackable by active stack
|
||||
bool stackCountOutsideHexes[GameConstants::BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back
|
||||
int previouslyHoveredHex; //number of hex that was hovered by the cursor a while ago
|
||||
int currentlyHoveredHex; //number of hex that is supposed to be hovered (for a while it may be inappropriately set, but will be renewed soon)
|
||||
int attackingHex; //hex from which the stack would perform attack with current cursor
|
||||
double getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group
|
||||
std::map<int, int> standingFrame; //number of frame in standing animation by stack ID, helps in showing 'random moves'
|
||||
|
||||
CPlayerInterface *tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
|
||||
bool tacticsMode;
|
||||
bool stackCanCastSpell; //if true, active stack could possibly cats some target spell
|
||||
bool spellDestSelectMode; //if true, player is choosing destination for his spell
|
||||
SpellSelectionType spellSelMode;
|
||||
BattleAction * spellToCast; //spell for which player is choosing destination
|
||||
ui32 creatureSpellToCast;
|
||||
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
||||
|
||||
void showAliveStack(const CStack *stack, SDL_Surface * to); //helper function for function show
|
||||
void showAliveStacks(std::vector<const CStack *> *aliveStacks, int hex, std::vector<const CStack *> *flyingStacks, SDL_Surface *to); // loops through all stacks at a given hex position
|
||||
void showPieceOfWall(SDL_Surface * to, int hex, const std::vector<const CStack*> & stacks); //helper function for show
|
||||
void showObstacles(std::multimap<SHexField, int> *hexToObstacle, std::vector<CObstacleInstance> &obstacles, int hex, SDL_Surface *to); // show all obstacles at a given hex position
|
||||
void redrawBackgroundWithHexes(const CStack * activeStack);
|
||||
void printConsoleAttacked(const CStack * defender, int dmg, int killed, const CStack * attacker, bool Multiple);
|
||||
|
||||
std::list<SProjectileInfo> projectiles; //projectiles flying on battlefield
|
||||
void projectileShowHelper(SDL_Surface * to); //prints projectiles present on the battlefield
|
||||
void giveCommand(ui8 action, SHexField tile, ui32 stack, si32 additional=-1);
|
||||
bool isTileAttackable(const SHexField & number) const; //returns true if tile 'number' is neighboring any tile from active stack's range or is one of these tiles
|
||||
bool blockedByObstacle(SHexField hex) const;
|
||||
bool isCatapultAttackable(SHexField hex) const; //returns true if given tile can be attacked by catapult
|
||||
|
||||
std::list<SBattleEffect> battleEffects; //different animations to display on the screen like spell effects
|
||||
|
||||
/// Class which is responsible for drawing the wall of a siege during battle
|
||||
class SiegeHelper
|
||||
{
|
||||
private:
|
||||
static std::string townTypeInfixes[GameConstants::F_NUMBER]; //for internal use only - to build filenames
|
||||
SDL_Surface* walls[18];
|
||||
const CBattleInterface * owner;
|
||||
public:
|
||||
const CGTownInstance * town; //besieged town
|
||||
|
||||
SiegeHelper(const CGTownInstance * siegeTown, const CBattleInterface * _owner); //c-tor
|
||||
~SiegeHelper(); //d-tor
|
||||
|
||||
//filename getters
|
||||
std::string getSiegeName(ui16 what, ui16 additInfo = 1) const; //what: 0 - background, 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall, 5 - below gate, 6 - over gate, 7 - upper wall, 8 - uppert tower, 9 - gate, 10 - gate arch, 11 - bottom static wall, 12 - upper static wall, 13 - moat, 14 - mlip, 15 - keep creature cover, 16 - bottom turret creature cover, 17 - upper turret creature cover; additInfo: 1 - intact, 2 - damaged, 3 - destroyed
|
||||
|
||||
void printPartOfWall(SDL_Surface * to, int what);//what: 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall, 5 - below gate, 6 - over gate, 7 - upper wall, 8 - uppert tower, 9 - gate, 10 - gate arch, 11 - bottom static wall, 12 - upper static wall, 15 - keep creature cover, 16 - bottom turret creature cover, 17 - upper turret creature cover
|
||||
|
||||
friend class CBattleInterface;
|
||||
} * siegeH;
|
||||
|
||||
CPlayerInterface * attackerInt, * defenderInt; //because LOCPLINT is not enough in hotSeat
|
||||
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
|
||||
public:
|
||||
CPlayerInterface * curInt; //current player interface
|
||||
std::list<std::pair<CBattleAnimation *, bool> > pendingAnims; //currently displayed animations <anim, initialized>
|
||||
void addNewAnim(CBattleAnimation * anim); //adds new anim to pendingAnims
|
||||
ui32 animIDhelper; //for giving IDs for animations
|
||||
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
|
||||
|
||||
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen); //c-tor
|
||||
~CBattleInterface(); //d-tor
|
||||
|
||||
//std::vector<TimeInterested*> timeinterested; //animation handling
|
||||
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
|
||||
void setAnimSpeed(int set); //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
|
||||
int getAnimSpeed() const; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
|
||||
|
||||
CHexFieldControl bfield[GameConstants::BFIELD_SIZE]; //11 lines, 17 hexes on each
|
||||
//std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
|
||||
SDL_Surface * cellBorder, * cellShade;
|
||||
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 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
|
||||
|
||||
//button handle funcs:
|
||||
void bOptionsf();
|
||||
void bSurrenderf();
|
||||
void bFleef();
|
||||
void reallyFlee(); //performs fleeing without asking player
|
||||
void reallySurrender(); //performs surrendering without asking player
|
||||
void bAutofightf();
|
||||
void bSpellf();
|
||||
void bWaitf();
|
||||
void bDefencef();
|
||||
void bConsoleUpf();
|
||||
void bConsoleDownf();
|
||||
void bTacticNextStack();
|
||||
void bEndTacticPhase();
|
||||
//end of button handle funcs
|
||||
//napisz tu klase odpowiadajaca za wyswietlanie bitwy i obsluge uzytkownika, polecenia ma przekazywac callbackiem
|
||||
void activate();
|
||||
void deactivate();
|
||||
void show(SDL_Surface * to);
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void mouseMoved(const SDL_MouseMotionEvent &sEvent);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
|
||||
//call-ins
|
||||
void startAction(const BattleAction* action);
|
||||
void newStack(const CStack * stack); //new stack appeared on battlefield
|
||||
void stackRemoved(int stackID); //stack disappeared from batlefiled
|
||||
void stackActivated(const CStack * stack); //active stack has been changed
|
||||
void stackMoved(const CStack * stack, std::vector<SHexField> destHex, int distance); //stack with id number moved to destHex
|
||||
void waitForAnims();
|
||||
void stacksAreAttacked(std::vector<SStackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
||||
void stackAttacking(const CStack * attacker, SHexField dest, const CStack * attacked, bool shooting); //called when stack with id ID is attacking something on hex dest
|
||||
void newRoundFirst( int round );
|
||||
void newRound(int number); //caled when round is ended; number is the number of round
|
||||
void hexLclicked(int whichOne); //hex only call-in
|
||||
void stackIsCatapulting(const CatapultAttack & ca); //called when a stack is attacking walls
|
||||
void battleFinished(const BattleResult& br); //called when battle is finished - battleresult window should be printed
|
||||
const BattleResult * bresult; //result of a battle; if non-zero then display when all animations end
|
||||
void displayBattleFinished(); //displays battle result
|
||||
void spellCast(const BattleSpellCast * sc); //called when a hero casts a spell
|
||||
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 battleTriggerEffect(const BattleTriggerEffect & bte);
|
||||
void setBattleCursor(const int myNumber); //really complex and messy
|
||||
void endAction(const BattleAction* action);
|
||||
void hideQueue();
|
||||
void showQueue();
|
||||
|
||||
|
||||
friend class CPlayerInterface;
|
||||
friend class AdventureMapButton;
|
||||
friend class CInGameConsole;
|
||||
|
||||
friend class CBattleResultWindow;
|
||||
friend class CBattleHero;
|
||||
friend class CSpellEffectAnimation;
|
||||
friend class CBattleStackAnimation;
|
||||
friend class CReverseAnimation;
|
||||
friend class CDefenceAnimation;
|
||||
friend class CMovementAnimation;
|
||||
friend class CMovementStartAnimation;
|
||||
friend class CAttackAnimation;
|
||||
friend class CMeleeAttackAnimation;
|
||||
friend class CShootingAnimation;
|
||||
friend class CHexFieldControl;
|
||||
};
|
||||
73
client/BattleInterface/CBattleOptionsWindow.cpp
Normal file
73
client/BattleInterface/CBattleOptionsWindow.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#include "StdInc.h"
|
||||
#include "CBattleOptionsWindow.h"
|
||||
|
||||
#include "CBattleInterface.h"
|
||||
#include "../GUIBase.h"
|
||||
#include "../GUIClasses.h"
|
||||
#include "../AdventureMapButton.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
|
||||
CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner): myInt(owner)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
pos = position;
|
||||
background = new CPicture("comopbck.bmp");
|
||||
background->colorize(owner->curInt->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, 25, 56, false);
|
||||
viewGrid->select(owner->curInt->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, 25, 89, false);
|
||||
movementShadow->select(owner->curInt->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, 25, 122, false);
|
||||
mouseShadow->select(owner->curInt->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", 28, 225, 1);
|
||||
animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[423].first),CGI->generaltexth->zelp[423].second, "sysob10.def", 92, 225, 2);
|
||||
animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[424].first),CGI->generaltexth->zelp[424].second, "sysob11.def",156, 225, 4);
|
||||
animSpeeds->select(owner->getAnimSpeed(), 1);
|
||||
animSpeeds->onChange = boost::bind(&CBattleInterface::setAnimSpeed, owner, _1);
|
||||
|
||||
setToDefault = new AdventureMapButton (CGI->generaltexth->zelp[393], boost::bind(&CBattleOptionsWindow::bDefaultf,this), 246, 359, "codefaul.def");
|
||||
setToDefault->swappedImages = true;
|
||||
setToDefault->update();
|
||||
exit = new AdventureMapButton (CGI->generaltexth->zelp[392], boost::bind(&CBattleOptionsWindow::bExitf,this), 357, 359, "soretrn.def",SDLK_RETURN);
|
||||
exit->swappedImages = true;
|
||||
exit->update();
|
||||
|
||||
//creating labels
|
||||
labels.push_back(new CLabel(242, 32, FONT_BIG, CENTER, tytulowy, CGI->generaltexth->allTexts[392]));//window title
|
||||
labels.push_back(new CLabel(122, 214, FONT_MEDIUM, CENTER, tytulowy, CGI->generaltexth->allTexts[393]));//animation speed
|
||||
labels.push_back(new CLabel(122, 293, FONT_MEDIUM, CENTER, tytulowy, CGI->generaltexth->allTexts[394]));//music volume
|
||||
labels.push_back(new CLabel(122, 359, FONT_MEDIUM, CENTER, tytulowy, CGI->generaltexth->allTexts[395]));//effects' volume
|
||||
labels.push_back(new CLabel(353, 66, FONT_MEDIUM, CENTER, tytulowy, CGI->generaltexth->allTexts[396]));//auto - combat options
|
||||
labels.push_back(new CLabel(353, 265, FONT_MEDIUM, CENTER, tytulowy, CGI->generaltexth->allTexts[397]));//creature info
|
||||
|
||||
//auto - combat options
|
||||
labels.push_back(new CLabel(283, 86, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[398]));//creatures
|
||||
labels.push_back(new CLabel(283, 116, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[399]));//spells
|
||||
labels.push_back(new CLabel(283, 146, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[400]));//catapult
|
||||
labels.push_back(new CLabel(283, 176, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[151]));//ballista
|
||||
labels.push_back(new CLabel(283, 206, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[401]));//first aid tent
|
||||
|
||||
//creature info
|
||||
labels.push_back(new CLabel(283, 285, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[402]));//all stats
|
||||
labels.push_back(new CLabel(283, 315, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[403]));//spells only
|
||||
|
||||
//general options
|
||||
labels.push_back(new CLabel(61, 57, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[404]));
|
||||
labels.push_back(new CLabel(61, 90, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[405]));
|
||||
labels.push_back(new CLabel(61, 123, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[406]));
|
||||
labels.push_back(new CLabel(61, 156, FONT_MEDIUM, TOPLEFT, zwykly, CGI->generaltexth->allTexts[407]));
|
||||
}
|
||||
|
||||
void CBattleOptionsWindow::bDefaultf()
|
||||
{
|
||||
}
|
||||
|
||||
void CBattleOptionsWindow::bExitf()
|
||||
{
|
||||
GH.popIntTotally(this);
|
||||
}
|
||||
39
client/BattleInterface/CBattleOptionsWindow.h
Normal file
39
client/BattleInterface/CBattleOptionsWindow.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GUIBase.h"
|
||||
|
||||
class CBattleInterface;
|
||||
class CPicture;
|
||||
class AdventureMapButton;
|
||||
class CHighlightableButton;
|
||||
class CHighlightableButtonsGroup;
|
||||
class CLabel;
|
||||
struct SDL_Rect;
|
||||
|
||||
/*
|
||||
* CBattleOptionsWindow.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Class which manages the battle options window
|
||||
class CBattleOptionsWindow : public CIntObject
|
||||
{
|
||||
private:
|
||||
CBattleInterface *myInt;
|
||||
CPicture *background;
|
||||
AdventureMapButton *setToDefault, *exit;
|
||||
CHighlightableButton *viewGrid, *movementShadow, *mouseShadow;
|
||||
CHighlightableButtonsGroup *animSpeeds;
|
||||
|
||||
std::vector<CLabel*> labels;
|
||||
public:
|
||||
CBattleOptionsWindow(const SDL_Rect &position, CBattleInterface *owner); //c-tor
|
||||
|
||||
void bDefaultf(); //default button callback
|
||||
void bExitf(); //exit button callback
|
||||
};
|
||||
216
client/BattleInterface/CBattleResultWindow.cpp
Normal file
216
client/BattleInterface/CBattleResultWindow.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
#include "StdInc.h"
|
||||
#include "CBattleResultWindow.h"
|
||||
|
||||
#include "CBattleInterface.h"
|
||||
#include "../AdventureMapButton.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../SDL_Extensions.h"
|
||||
#include "../CBitmapHandler.h"
|
||||
|
||||
CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect & pos, CBattleInterface * _owner)
|
||||
: owner(_owner)
|
||||
{
|
||||
this->pos = pos;
|
||||
background = BitmapHandler::loadBitmap("CPRESULT.BMP", true);
|
||||
graphics->blueToPlayersAdv(background, owner->curInt->playerID);
|
||||
SDL_Surface * pom = SDL_ConvertSurface(background, screen->format, screen->flags);
|
||||
SDL_FreeSurface(background);
|
||||
background = pom;
|
||||
exit = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleResultWindow::bExitf,this), 384 + pos.x, 505 + pos.y, "iok6432.def", SDLK_RETURN);
|
||||
exit->borderColor = Colors::MetallicGold;
|
||||
exit->borderEnabled = true;
|
||||
|
||||
if(br.winner==0) //attacker won
|
||||
{
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[410], 59, 124, FONT_SMALL, zwykly, background);
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[411], 408, 124, FONT_SMALL, zwykly, background);
|
||||
}
|
||||
else //if(br.winner==1)
|
||||
{
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[411], 59, 124, FONT_SMALL, zwykly, background);
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[410], 412, 124, FONT_SMALL, zwykly, background);
|
||||
}
|
||||
|
||||
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[407], 232, 302, FONT_BIG, tytulowy, background);
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[408], 232, 332, FONT_BIG, zwykly, background);
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[409], 237, 428, FONT_BIG, zwykly, background);
|
||||
|
||||
std::string attackerName, defenderName;
|
||||
|
||||
if(owner->attackingHeroInstance) //a hero attacked
|
||||
{
|
||||
SDL_Rect temp_rect = genRect(64, 58, 21, 38);
|
||||
SDL_BlitSurface(graphics->portraitLarge[owner->attackingHeroInstance->portrait], NULL, background, &temp_rect);
|
||||
//setting attackerName
|
||||
attackerName = owner->attackingHeroInstance->name;
|
||||
}
|
||||
else //a monster attacked
|
||||
{
|
||||
int bestMonsterID = -1;
|
||||
ui32 bestPower = 0;
|
||||
for(TSlots::const_iterator it = owner->army1->Slots().begin(); it!=owner->army1->Slots().end(); ++it)
|
||||
{
|
||||
if(it->second->type->AIValue > bestPower)
|
||||
{
|
||||
bestPower = it->second->type->AIValue;
|
||||
bestMonsterID = it->second->type->idNumber;
|
||||
}
|
||||
}
|
||||
SDL_Rect temp_rect = genRect(64, 58, 21, 38);
|
||||
SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &temp_rect);
|
||||
//setting attackerName
|
||||
attackerName = CGI->creh->creatures[bestMonsterID]->namePl;
|
||||
}
|
||||
if(owner->defendingHeroInstance) //a hero defended
|
||||
{
|
||||
SDL_Rect temp_rect = genRect(64, 58, 392, 38);
|
||||
SDL_BlitSurface(graphics->portraitLarge[owner->defendingHeroInstance->portrait], NULL, background, &temp_rect);
|
||||
//setting defenderName
|
||||
defenderName = owner->defendingHeroInstance->name;
|
||||
}
|
||||
else //a monster defended
|
||||
{
|
||||
int bestMonsterID = -1;
|
||||
ui32 bestPower = 0;
|
||||
for(TSlots::const_iterator it = owner->army2->Slots().begin(); it!=owner->army2->Slots().end(); ++it)
|
||||
{
|
||||
if( it->second->type->AIValue > bestPower)
|
||||
{
|
||||
bestPower = it->second->type->AIValue;
|
||||
bestMonsterID = it->second->type->idNumber;
|
||||
}
|
||||
}
|
||||
SDL_Rect temp_rect = genRect(64, 58, 392, 38);
|
||||
SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &temp_rect);
|
||||
//setting defenderName
|
||||
defenderName = CGI->creh->creatures[bestMonsterID]->namePl;
|
||||
}
|
||||
|
||||
//printing attacker and defender's names
|
||||
CSDL_Ext::printAt(attackerName, 89, 37, FONT_SMALL, zwykly, background);
|
||||
CSDL_Ext::printTo(defenderName, 381, 53, FONT_SMALL, zwykly, background);
|
||||
//printing casualities
|
||||
for(int step = 0; step < 2; ++step)
|
||||
{
|
||||
if(br.casualties[step].size()==0)
|
||||
{
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[523], 235, 360 + 97*step, FONT_SMALL, zwykly, background);
|
||||
}
|
||||
else
|
||||
{
|
||||
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::map<ui32,si32>::const_iterator it=br.casualties[step].begin(); it!=br.casualties[step].end(); ++it)
|
||||
{
|
||||
blitAt(graphics->smallImgs[it->first], xPos, yPos, background);
|
||||
std::ostringstream amount;
|
||||
amount<<it->second;
|
||||
CSDL_Ext::printAtMiddle(amount.str(), xPos+16, yPos + 42, FONT_SMALL, zwykly, background);
|
||||
xPos += 42;
|
||||
}
|
||||
}
|
||||
}
|
||||
//printing result description
|
||||
bool weAreAttacker = (owner->curInt->playerID == owner->attackingHeroInstance->tempOwner);
|
||||
if((br.winner == 0 && weAreAttacker) || (br.winner == 1 && !weAreAttacker)) //we've won
|
||||
{
|
||||
int text=-1;
|
||||
switch(br.result)
|
||||
{
|
||||
case 0: text = 304; break;
|
||||
case 1: text = 303; break;
|
||||
case 2: text = 302; break;
|
||||
}
|
||||
|
||||
CCS->musich->playMusic(musicBase::winBattle);
|
||||
CCS->videoh->open(VIDEO_WIN);
|
||||
std::string str = CGI->generaltexth->allTexts[text];
|
||||
|
||||
const CGHeroInstance * ourHero = weAreAttacker? owner->attackingHeroInstance : owner->defendingHeroInstance;
|
||||
if (ourHero)
|
||||
{
|
||||
str += CGI->generaltexth->allTexts[305];
|
||||
boost::algorithm::replace_first(str,"%s",ourHero->name);
|
||||
boost::algorithm::replace_first(str,"%d",boost::lexical_cast<std::string>(br.exp[weAreAttacker?0:1]));
|
||||
}
|
||||
CSDL_Ext::printAtMiddleWB(str, 235, 235, FONT_SMALL, 55, zwykly, background);
|
||||
}
|
||||
else // we lose
|
||||
{
|
||||
switch(br.result)
|
||||
{
|
||||
case 0: //normal victory
|
||||
{
|
||||
CCS->musich->playMusic(musicBase::loseCombat);
|
||||
CCS->videoh->open(VIDEO_LOSE_BATTLE_START);
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[311], 235, 235, FONT_SMALL, zwykly, background);
|
||||
break;
|
||||
}
|
||||
case 1: //flee
|
||||
{
|
||||
CCS->musich->playMusic(musicBase::retreatBattle);
|
||||
CCS->videoh->open(VIDEO_RETREAT_START);
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[310], 235, 235, FONT_SMALL, zwykly, background);
|
||||
break;
|
||||
}
|
||||
case 2: //surrender
|
||||
{
|
||||
CCS->musich->playMusic(musicBase::surrenderBattle);
|
||||
CCS->videoh->open(VIDEO_SURRENDER);
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[309], 235, 220, FONT_SMALL, zwykly, background);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CBattleResultWindow::~CBattleResultWindow()
|
||||
{
|
||||
SDL_FreeSurface(background);
|
||||
}
|
||||
|
||||
void CBattleResultWindow::activate()
|
||||
{
|
||||
owner->curInt->showingDialog->set(true);
|
||||
exit->activate();
|
||||
}
|
||||
|
||||
void CBattleResultWindow::deactivate()
|
||||
{
|
||||
exit->deactivate();
|
||||
}
|
||||
|
||||
void CBattleResultWindow::show(SDL_Surface *to)
|
||||
{
|
||||
//evaluating to
|
||||
if(!to)
|
||||
to = screen;
|
||||
|
||||
CCS->videoh->update(107, 70, background, false, true);
|
||||
|
||||
SDL_BlitSurface(background, NULL, to, &pos);
|
||||
exit->showAll(to);
|
||||
}
|
||||
|
||||
void CBattleResultWindow::bExitf()
|
||||
{
|
||||
if(LOCPLINT->cb->getStartInfo()->mode == StartInfo::DUEL)
|
||||
{
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
CPlayerInterface * intTmp = owner->curInt;
|
||||
GH.popInts(2); //first - we; second - battle interface
|
||||
intTmp->showingDialog->setn(false);
|
||||
CCS->videoh->close();
|
||||
}
|
||||
37
client/BattleInterface/CBattleResultWindow.h
Normal file
37
client/BattleInterface/CBattleResultWindow.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GUIBase.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
class AdventureMapButton;
|
||||
class CBattleInterface;
|
||||
struct SDL_Rect;
|
||||
struct BattleResult;
|
||||
|
||||
/*
|
||||
* CBattleResultWindow.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Class which is responsible for showing the battle result window
|
||||
class CBattleResultWindow : public CIntObject
|
||||
{
|
||||
private:
|
||||
SDL_Surface *background;
|
||||
AdventureMapButton *exit;
|
||||
CBattleInterface *owner;
|
||||
public:
|
||||
CBattleResultWindow(const BattleResult &br, const SDL_Rect &pos, CBattleInterface *_owner); //c-tor
|
||||
~CBattleResultWindow(); //d-tor
|
||||
|
||||
void bExitf(); //exit button callback
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
void show(SDL_Surface * to = 0);
|
||||
};
|
||||
57
client/BattleInterface/CBattleStackAnimation.cpp
Normal file
57
client/BattleInterface/CBattleStackAnimation.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "StdInc.h"
|
||||
#include "CBattleStackAnimation.h"
|
||||
|
||||
#include "CBattleInterface.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
|
||||
CBattleStackAnimation::CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack)
|
||||
: CBattleAnimation(_owner), stack(_stack)
|
||||
{
|
||||
}
|
||||
|
||||
bool CBattleStackAnimation::isToReverseHlp(SHexField hexFrom, SHexField hexTo, bool curDir)
|
||||
{
|
||||
int fromMod = hexFrom % GameConstants::BFIELD_WIDTH;
|
||||
int fromDiv = hexFrom / GameConstants::BFIELD_WIDTH;
|
||||
int toMod = hexTo % GameConstants::BFIELD_WIDTH;
|
||||
|
||||
if(curDir && fromMod < toMod)
|
||||
return false;
|
||||
else if(curDir && fromMod > toMod)
|
||||
return true;
|
||||
else if(curDir && fromMod == toMod)
|
||||
{
|
||||
return fromDiv % 2 == 0;
|
||||
}
|
||||
else if(!curDir && fromMod < toMod)
|
||||
return true;
|
||||
else if(!curDir && fromMod > toMod)
|
||||
return false;
|
||||
else if(!curDir && fromMod == toMod)
|
||||
{
|
||||
return fromDiv % 2 == 1;
|
||||
}
|
||||
tlog1 << "Catastrope in CBattleStackAnimation::isToReverse!" << std::endl;
|
||||
return false; //should never happen
|
||||
}
|
||||
|
||||
bool CBattleStackAnimation::isToReverse(SHexField hexFrom, SHexField hexTo, bool curDir, bool toDoubleWide, bool toDir)
|
||||
{
|
||||
if(hexTo < 0) //turret
|
||||
return false;
|
||||
|
||||
if(toDoubleWide)
|
||||
{
|
||||
return isToReverseHlp(hexFrom, hexTo, curDir) &&
|
||||
(toDir ? isToReverseHlp(hexFrom, hexTo-1, curDir) : isToReverseHlp(hexFrom, hexTo+1, curDir) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return isToReverseHlp(hexFrom, hexTo, curDir);
|
||||
}
|
||||
}
|
||||
|
||||
CCreatureAnimation* CBattleStackAnimation::myAnim()
|
||||
{
|
||||
return owner->creAnims[stack->ID];
|
||||
}
|
||||
31
client/BattleInterface/CBattleStackAnimation.h
Normal file
31
client/BattleInterface/CBattleStackAnimation.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "CBattleAnimation.h"
|
||||
#include "../../lib/SHexField.h"
|
||||
|
||||
class CStack;
|
||||
class CBattleInterface;
|
||||
class CCreatureAnimation;
|
||||
|
||||
/*
|
||||
* CBattleStackAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Sub-class which is responsible for managing the battle stack animation.
|
||||
class CBattleStackAnimation : public CBattleAnimation
|
||||
{
|
||||
public:
|
||||
const CStack * stack; //id of stack whose animation it is
|
||||
|
||||
CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack);
|
||||
static bool isToReverseHlp(SHexField hexFrom, SHexField hexTo, bool curDir); //helper for isToReverse
|
||||
static bool isToReverse(SHexField hexFrom, SHexField hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir); //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
|
||||
|
||||
CCreatureAnimation *myAnim(); //animation for our stack
|
||||
};
|
||||
139
client/BattleInterface/CDefenceAnimation.cpp
Normal file
139
client/BattleInterface/CDefenceAnimation.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
#include "StdInc.h"
|
||||
#include "CDefenceAnimation.h"
|
||||
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CCreatureAnimation.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "CReverseAnimation.h"
|
||||
#include "CAttackAnimation.h"
|
||||
#include "CShootingAnimation.h"
|
||||
|
||||
bool CDefenceAnimation::init()
|
||||
{
|
||||
//checking initial conditions
|
||||
|
||||
//if(owner->creAnims[stackID]->getType() != 2)
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
if(attacker == NULL && owner->battleEffects.size() > 0)
|
||||
return false;
|
||||
|
||||
ui32 lowestMoveID = owner->animIDhelper + 5;
|
||||
for(std::list<std::pair<CBattleAnimation *, bool> >::iterator it = owner->pendingAnims.begin(); it != owner->pendingAnims.end(); ++it)
|
||||
{
|
||||
CDefenceAnimation * defAnim = dynamic_cast<CDefenceAnimation *>(it->first);
|
||||
if(defAnim && defAnim->stack->ID != stack->ID)
|
||||
continue;
|
||||
|
||||
CAttackAnimation * attAnim = dynamic_cast<CAttackAnimation *>(it->first);
|
||||
if(attAnim && attAnim->stack->ID != stack->ID)
|
||||
continue;
|
||||
|
||||
if(attacker != NULL)
|
||||
{
|
||||
int attackerAnimType = owner->creAnims[attacker->ID]->getType();
|
||||
if( attackerAnimType == 11 && attackerAnimType == 12 && attackerAnimType == 13 && owner->creAnims[attacker->ID]->getFrame() < attacker->getCreature()->attackClimaxFrame )
|
||||
return false;
|
||||
}
|
||||
|
||||
CReverseAnimation * animAsRev = dynamic_cast<CReverseAnimation *>(it->first);
|
||||
|
||||
if(animAsRev && animAsRev->priority)
|
||||
return false;
|
||||
|
||||
if(it->first)
|
||||
vstd::amin(lowestMoveID, it->first->ID);
|
||||
}
|
||||
if(ID > lowestMoveID)
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
//reverse unit if necessary
|
||||
if(attacker && isToReverse(stack->position, attacker->position, owner->creDir[stack->ID], attacker->doubleWide(), owner->creDir[attacker->ID]))
|
||||
{
|
||||
owner->addNewAnim(new CReverseAnimation(owner, stack, stack->position, true));
|
||||
return false;
|
||||
}
|
||||
//unit reversed
|
||||
|
||||
if(byShooting) //delay hit animation
|
||||
{
|
||||
for(std::list<SProjectileInfo>::const_iterator it = owner->projectiles.begin(); it != owner->projectiles.end(); ++it)
|
||||
{
|
||||
if(it->creID == attacker->getCreature()->idNumber)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//initializing
|
||||
if(killed)
|
||||
{
|
||||
CCS->soundh->playSound(battle_sound(stack->getCreature(), killed));
|
||||
myAnim()->setType(CCreatureAnim::DEATH); //death
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: this block doesn't seems correct if the unit is defending.
|
||||
CCS->soundh->playSound(battle_sound(stack->getCreature(), wince));
|
||||
myAnim()->setType(CCreatureAnim::HITTED); //getting hit
|
||||
}
|
||||
|
||||
return true; //initialized successfuly
|
||||
}
|
||||
|
||||
void CDefenceAnimation::nextFrame()
|
||||
{
|
||||
if(!killed && myAnim()->getType() != CCreatureAnim::HITTED)
|
||||
{
|
||||
myAnim()->setType(CCreatureAnim::HITTED);
|
||||
}
|
||||
|
||||
if(!myAnim()->onLastFrameInGroup())
|
||||
{
|
||||
if( myAnim()->getType() == CCreatureAnim::DEATH && (owner->animCount+1)%(4/owner->curInt->sysOpts.animSpeed)==0
|
||||
&& !myAnim()->onLastFrameInGroup() )
|
||||
{
|
||||
myAnim()->incrementFrame();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
endAnim();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CDefenceAnimation::endAnim()
|
||||
{
|
||||
//restoring animType
|
||||
|
||||
if(myAnim()->getType() == CCreatureAnim::HITTED)
|
||||
myAnim()->setType(CCreatureAnim::HOLDING);
|
||||
|
||||
//printing info to console
|
||||
|
||||
//if(attacker!=NULL)
|
||||
// owner->printConsoleAttacked(stack, dmg, amountKilled, attacker);
|
||||
|
||||
//const CStack * attacker = owner->curInt->cb->battleGetStackByID(IDby, false);
|
||||
//const CStack * attacked = owner->curInt->cb->battleGetStackByID(stackID, false);
|
||||
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
CDefenceAnimation::CDefenceAnimation(SStackAttackedInfo _attackedInfo, CBattleInterface * _owner)
|
||||
: CBattleStackAnimation(_owner, _attackedInfo.defender), dmg(_attackedInfo.dmg),
|
||||
amountKilled(_attackedInfo.amountKilled), attacker(_attackedInfo.attacker), byShooting(_attackedInfo.byShooting),
|
||||
killed(_attackedInfo.killed)
|
||||
{
|
||||
}
|
||||
34
client/BattleInterface/CDefenceAnimation.h
Normal file
34
client/BattleInterface/CDefenceAnimation.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "CBattleStackAnimation.h"
|
||||
#include "SStackAttackedInfo.h"
|
||||
|
||||
class CStack;
|
||||
|
||||
/*
|
||||
* CDefenceAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Animation of a defending unit
|
||||
class CDefenceAnimation : public CBattleStackAnimation
|
||||
{
|
||||
private:
|
||||
//std::vector<SSStackAttackedInfo> attackedInfos;
|
||||
int dmg; //damage dealt
|
||||
int amountKilled; //how many creatures in stack has been killed
|
||||
const CStack * attacker; //attacking stack
|
||||
bool byShooting; //if true, stack has been attacked by shooting
|
||||
bool killed; //if true, stack has been killed
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CDefenceAnimation(SStackAttackedInfo _attackedInfo, CBattleInterface * _owner);
|
||||
};
|
||||
27
client/BattleInterface/CDummyAnimation.cpp
Normal file
27
client/BattleInterface/CDummyAnimation.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "StdInc.h"
|
||||
#include "CDummyAnimation.h"
|
||||
|
||||
#include "CBattleInterface.h"
|
||||
|
||||
bool CDummyAnimation::init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDummyAnimation::nextFrame()
|
||||
{
|
||||
counter++;
|
||||
if(counter > howMany)
|
||||
endAnim();
|
||||
}
|
||||
|
||||
void CDummyAnimation::endAnim()
|
||||
{
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
CDummyAnimation::CDummyAnimation(CBattleInterface * _owner, int howManyFrames) : CBattleAnimation(_owner), counter(0), howMany(howManyFrames)
|
||||
{
|
||||
}
|
||||
28
client/BattleInterface/CDummyAnimation.h
Normal file
28
client/BattleInterface/CDummyAnimation.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "CBattleAnimation.h"
|
||||
|
||||
class CBattleInterface;
|
||||
|
||||
/*
|
||||
* CDummyAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class CDummyAnimation : public CBattleAnimation
|
||||
{
|
||||
private:
|
||||
int counter;
|
||||
int howMany;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CDummyAnimation(CBattleInterface *_owner, int howManyFrames);
|
||||
};
|
||||
147
client/BattleInterface/CHexFieldControl.cpp
Normal file
147
client/BattleInterface/CHexFieldControl.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
#include "StdInc.h"
|
||||
#include "CHexFieldControl.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../SDL_Extensions.h"
|
||||
#include "../GUIClasses.h"
|
||||
#include "CBattleConsole.h"
|
||||
|
||||
Point CHexFieldControl::getXYUnitAnim(const int & hexNum, const bool & attacker, const CStack * stack, const CBattleInterface * cbi)
|
||||
{
|
||||
Point ret(-500, -500); //returned value
|
||||
if(stack && stack->position < 0) //creatures in turrets
|
||||
{
|
||||
switch(stack->position)
|
||||
{
|
||||
case -2: //keep
|
||||
ret = graphics->wallPositions[cbi->siegeH->town->town->typeID][17];
|
||||
break;
|
||||
case -3: //lower turret
|
||||
ret = graphics->wallPositions[cbi->siegeH->town->town->typeID][18];
|
||||
break;
|
||||
case -4: //upper turret
|
||||
ret = graphics->wallPositions[cbi->siegeH->town->town->typeID][19];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.y = -139 + 42 * (hexNum/GameConstants::BFIELD_WIDTH); //counting y
|
||||
//counting x
|
||||
if(attacker)
|
||||
{
|
||||
ret.x = -160 + 22 * ( ((hexNum/GameConstants::BFIELD_WIDTH) + 1)%2 ) + 44 * (hexNum % GameConstants::BFIELD_WIDTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.x = -219 + 22 * ( ((hexNum/GameConstants::BFIELD_WIDTH) + 1)%2 ) + 44 * (hexNum % GameConstants::BFIELD_WIDTH);
|
||||
}
|
||||
//shifting position for double - hex creatures
|
||||
if(stack && stack->doubleWide())
|
||||
{
|
||||
if(attacker)
|
||||
{
|
||||
ret.x -= 44;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.x += 45;
|
||||
}
|
||||
}
|
||||
}
|
||||
//returning
|
||||
return ret +CPlayerInterface::battleInt->pos;
|
||||
}
|
||||
void CHexFieldControl::activate()
|
||||
{
|
||||
activateHover();
|
||||
activateMouseMove();
|
||||
activateLClick();
|
||||
activateRClick();
|
||||
}
|
||||
|
||||
void CHexFieldControl::deactivate()
|
||||
{
|
||||
deactivateHover();
|
||||
deactivateMouseMove();
|
||||
deactivateLClick();
|
||||
deactivateRClick();
|
||||
}
|
||||
|
||||
void CHexFieldControl::hover(bool on)
|
||||
{
|
||||
hovered = on;
|
||||
//Hoverable::hover(on);
|
||||
if(!on && setAlterText)
|
||||
{
|
||||
myInterface->console->alterTxt = std::string();
|
||||
setAlterText = false;
|
||||
}
|
||||
}
|
||||
|
||||
CHexFieldControl::CHexFieldControl() : setAlterText(false), myNumber(-1), accessible(true), hovered(false), strictHovered(false), myInterface(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void CHexFieldControl::mouseMoved(const SDL_MouseMotionEvent &sEvent)
|
||||
{
|
||||
if(myInterface->cellShade)
|
||||
{
|
||||
if(CSDL_Ext::SDL_GetPixel(myInterface->cellShade, sEvent.x-pos.x, sEvent.y-pos.y) == 0) //hovered pixel is outside hex
|
||||
{
|
||||
strictHovered = false;
|
||||
}
|
||||
else //hovered pixel is inside hex
|
||||
{
|
||||
strictHovered = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(hovered && strictHovered) //print attacked creature to console
|
||||
{
|
||||
const CStack * attackedStack = myInterface->curInt->cb->battleGetStackByPos(myNumber);
|
||||
if(myInterface->console->alterTxt.size() == 0 &&attackedStack != NULL &&
|
||||
attackedStack->owner != myInterface->curInt->playerID &&
|
||||
attackedStack->alive())
|
||||
{
|
||||
char tabh[160];
|
||||
const std::string & attackedName = attackedStack->count == 1 ? attackedStack->getCreature()->nameSing : attackedStack->getCreature()->namePl;
|
||||
sprintf(tabh, CGI->generaltexth->allTexts[220].c_str(), attackedName.c_str());
|
||||
myInterface->console->alterTxt = std::string(tabh);
|
||||
setAlterText = true;
|
||||
}
|
||||
}
|
||||
else if(setAlterText)
|
||||
{
|
||||
myInterface->console->alterTxt = std::string();
|
||||
setAlterText = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CHexFieldControl::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if(!down && hovered && strictHovered) //we've been really clicked!
|
||||
{
|
||||
myInterface->hexLclicked(myNumber);
|
||||
}
|
||||
}
|
||||
|
||||
void CHexFieldControl::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
const CStack * myst = myInterface->curInt->cb->battleGetStackByPos(myNumber); //stack info
|
||||
if(hovered && strictHovered && myst!=NULL)
|
||||
{
|
||||
|
||||
if(!myst->alive()) return;
|
||||
if(down)
|
||||
{
|
||||
GH.pushInt(createCreWindow(myst));
|
||||
}
|
||||
}
|
||||
}
|
||||
40
client/BattleInterface/CHexFieldControl.h
Normal file
40
client/BattleInterface/CHexFieldControl.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GUIBase.h"
|
||||
|
||||
class CBattleInterface;
|
||||
class CStack;
|
||||
struct SDL_MouseMotionEvent;
|
||||
|
||||
/*
|
||||
* CHexFieldControl.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Class which stands for a single hex field on a battlefield
|
||||
class CHexFieldControl : public CIntObject
|
||||
{
|
||||
private:
|
||||
bool setAlterText; //if true, this hex has set alternative text in console and will clean it
|
||||
public:
|
||||
ui32 myNumber; //number of hex in commonly used format
|
||||
bool accessible; //if true, this hex is accessible for units
|
||||
//CStack * ourStack;
|
||||
bool hovered, strictHovered; //for determining if hex is hovered by mouse (this is different problem than hex's graphic hovering)
|
||||
CBattleInterface * myInterface; //interface that owns me
|
||||
static Point getXYUnitAnim(const int &hexNum, const bool &attacker, const CStack *creature, const CBattleInterface *cbi); //returns (x, y) of left top corner of animation
|
||||
|
||||
//for user interactions
|
||||
void hover (bool on);
|
||||
void activate();
|
||||
void deactivate();
|
||||
void mouseMoved (const SDL_MouseMotionEvent &sEvent);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
CHexFieldControl();
|
||||
};
|
||||
95
client/BattleInterface/CMeleeAttackAnimation.cpp
Normal file
95
client/BattleInterface/CMeleeAttackAnimation.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "StdInc.h"
|
||||
#include "CMeleeAttackAnimation.h"
|
||||
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CCreatureAnimation.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "CReverseAnimation.h"
|
||||
|
||||
bool CMeleeAttackAnimation::init()
|
||||
{
|
||||
if( !CAttackAnimation::checkInitialConditions() )
|
||||
return false;
|
||||
|
||||
//if(owner->creAnims[stackID]->getType()!=2)
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
if(!attackingStack || myAnim()->getType() == 5)
|
||||
{
|
||||
endAnim();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool toReverse = isToReverse(attackingStackPosBeforeReturn, dest, owner->creDir[stack->ID], attackedStack->doubleWide(), owner->creDir[attackedStack->ID]);
|
||||
|
||||
if(toReverse)
|
||||
{
|
||||
|
||||
owner->addNewAnim(new CReverseAnimation(owner, stack, attackingStackPosBeforeReturn, true));
|
||||
return false;
|
||||
}
|
||||
//reversed
|
||||
|
||||
shooting = false;
|
||||
|
||||
static const CCreatureAnim::EAnimType mutPosToGroup[] = {CCreatureAnim::ATTACK_UP, CCreatureAnim::ATTACK_UP,
|
||||
CCreatureAnim::ATTACK_FRONT, CCreatureAnim::ATTACK_DOWN, CCreatureAnim::ATTACK_DOWN, CCreatureAnim::ATTACK_FRONT};
|
||||
|
||||
int revShiftattacker = (attackingStack->attackerOwned ? -1 : 1);
|
||||
|
||||
int mutPos = SHexField::mutualPosition(attackingStackPosBeforeReturn, dest);
|
||||
if(mutPos == -1 && attackingStack->doubleWide())
|
||||
{
|
||||
mutPos = SHexField::mutualPosition(attackingStackPosBeforeReturn + revShiftattacker, attackedStack->position);
|
||||
}
|
||||
if (mutPos == -1 && attackedStack->doubleWide())
|
||||
{
|
||||
mutPos = SHexField::mutualPosition(attackingStackPosBeforeReturn, attackedStack->occupiedHex());
|
||||
}
|
||||
if (mutPos == -1 && attackedStack->doubleWide() && attackingStack->doubleWide())
|
||||
{
|
||||
mutPos = SHexField::mutualPosition(attackingStackPosBeforeReturn + revShiftattacker, attackedStack->occupiedHex());
|
||||
}
|
||||
|
||||
|
||||
switch(mutPos) //attack direction
|
||||
{
|
||||
case 0: case 1: case 2: case 3: case 4: case 5:
|
||||
group = mutPosToGroup[mutPos];
|
||||
break;
|
||||
default:
|
||||
tlog1<<"Critical Error! Wrong dest in stackAttacking! dest: "<<dest<<" attacking stack pos: "<<attackingStackPosBeforeReturn<<" mutual pos: "<<mutPos<<std::endl;
|
||||
group = CCreatureAnim::ATTACK_FRONT;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMeleeAttackAnimation::nextFrame()
|
||||
{
|
||||
/*for(std::list<std::pair<CBattleAnimation *, bool> >::const_iterator it = owner->pendingAnims.begin(); it != owner->pendingAnims.end(); ++it)
|
||||
{
|
||||
CBattleMoveStart * anim = dynamic_cast<CBattleMoveStart *>(it->first);
|
||||
CReverseAnim * anim2 = dynamic_cast<CReverseAnim *>(it->first);
|
||||
if( (anim && anim->stackID == stackID) || (anim2 && anim2->stackID == stackID ) )
|
||||
return;
|
||||
}*/
|
||||
|
||||
CAttackAnimation::nextFrame();
|
||||
}
|
||||
|
||||
void CMeleeAttackAnimation::endAnim()
|
||||
{
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
CMeleeAttackAnimation::CMeleeAttackAnimation(CBattleInterface * _owner, const CStack * attacker, SHexField _dest, const CStack * _attacked)
|
||||
: CAttackAnimation(_owner, attacker, _dest, _attacked)
|
||||
{
|
||||
}
|
||||
28
client/BattleInterface/CMeleeAttackAnimation.h
Normal file
28
client/BattleInterface/CMeleeAttackAnimation.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "CAttackAnimation.h"
|
||||
|
||||
|
||||
class CBattleInterface;
|
||||
class CStack;
|
||||
|
||||
/*
|
||||
* CMeleeAttackAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Hand-to-hand attack
|
||||
class CMeleeAttackAnimation : public CAttackAnimation
|
||||
{
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CMeleeAttackAnimation(CBattleInterface *_owner, const CStack *attacker, SHexField _dest, const CStack *_attacked);
|
||||
};
|
||||
176
client/BattleInterface/CMovementAnimation.cpp
Normal file
176
client/BattleInterface/CMovementAnimation.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "StdInc.h"
|
||||
#include "CMovementAnimation.h"
|
||||
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CCreatureAnimation.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "CReverseAnimation.h"
|
||||
#include "CMovementEndAnimation.h"
|
||||
#include "CHexFieldControl.h"
|
||||
|
||||
bool CMovementAnimation::init()
|
||||
{
|
||||
if( !isEarliest(false) )
|
||||
return false;
|
||||
|
||||
//a few useful variables
|
||||
steps = static_cast<int>(myAnim()->framesInGroup(CCreatureAnim::MOVING) * owner->getAnimSpeedMultiplier() - 1);
|
||||
if(steps == 0) //this creature seems to have no move animation so we can end it immediately
|
||||
{
|
||||
endAnim();
|
||||
return false;
|
||||
}
|
||||
whichStep = 0;
|
||||
int hexWbase = 44, hexHbase = 42;
|
||||
const CStack * movedStack = stack;
|
||||
if(!movedStack || myAnim()->getType() == 5)
|
||||
{
|
||||
endAnim();
|
||||
return false;
|
||||
}
|
||||
//bool twoTiles = movedStack->doubleWide();
|
||||
|
||||
Point begPosition = CHexFieldControl::getXYUnitAnim(curStackPos, movedStack->attackerOwned, movedStack, owner);
|
||||
Point endPosition = CHexFieldControl::getXYUnitAnim(nextHex, movedStack->attackerOwned, movedStack, owner);
|
||||
|
||||
int mutPos = SHexField::mutualPosition(curStackPos, nextHex);
|
||||
|
||||
//reverse unit if necessary
|
||||
if((begPosition.x > endPosition.x) && owner->creDir[stack->ID] == true)
|
||||
{
|
||||
owner->addNewAnim(new CReverseAnimation(owner, stack, curStackPos, true));
|
||||
return false;
|
||||
}
|
||||
else if ((begPosition.x < endPosition.x) && owner->creDir[stack->ID] == false)
|
||||
{
|
||||
owner->addNewAnim(new CReverseAnimation(owner, stack, curStackPos, true));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(myAnim()->getType() != CCreatureAnim::MOVING)
|
||||
{
|
||||
myAnim()->setType(CCreatureAnim::MOVING);
|
||||
}
|
||||
//unit reversed
|
||||
|
||||
// if(owner->moveSh <= 0)
|
||||
// owner->moveSh = CCS->soundh->playSound(battle_sound(movedStack->getCreature(), move), -1);
|
||||
|
||||
//step shift calculation
|
||||
posX = myAnim()->pos.x, posY = myAnim()->pos.y; // for precise calculations ;]
|
||||
if(mutPos == -1 && movedStack->hasBonusOfType(Bonus::FLYING))
|
||||
{
|
||||
steps *= distance;
|
||||
steps /= 2; //to make animation faster
|
||||
|
||||
stepX = (endPosition.x - begPosition.x) / static_cast<double>(steps);
|
||||
stepY = (endPosition.y - begPosition.y) / static_cast<double>(steps);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(mutPos)
|
||||
{
|
||||
case 0:
|
||||
stepX = -1.0 * (hexWbase / (2.0 * steps));
|
||||
stepY = -1.0 * (hexHbase / (static_cast<double>(steps)));
|
||||
break;
|
||||
case 1:
|
||||
stepX = hexWbase / (2.0 * steps);
|
||||
stepY = -1.0 * hexHbase / (static_cast<double>(steps));
|
||||
break;
|
||||
case 2:
|
||||
stepX = hexWbase / static_cast<double>(steps);
|
||||
stepY = 0.0;
|
||||
break;
|
||||
case 3:
|
||||
stepX = hexWbase / (2.0 * steps);
|
||||
stepY = hexHbase / static_cast<double>(steps);
|
||||
break;
|
||||
case 4:
|
||||
stepX = -1.0 * hexWbase / (2.0 * steps);
|
||||
stepY = hexHbase / static_cast<double>(steps);
|
||||
break;
|
||||
case 5:
|
||||
stepX = -1.0 * hexWbase / static_cast<double>(steps);
|
||||
stepY = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//step shifts calculated
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMovementAnimation::nextFrame()
|
||||
{
|
||||
//moving instructions
|
||||
posX += stepX;
|
||||
myAnim()->pos.x = static_cast<Sint16>(posX);
|
||||
posY += stepY;
|
||||
myAnim()->pos.y = static_cast<Sint16>(posY);
|
||||
|
||||
// Increments step count and check if we are finished with current animation
|
||||
++whichStep;
|
||||
if(whichStep == steps)
|
||||
{
|
||||
// Sets the position of the creature animation sprites
|
||||
Point coords = CHexFieldControl::getXYUnitAnim(nextHex, owner->creDir[stack->ID], stack, owner);
|
||||
myAnim()->pos = coords;
|
||||
|
||||
// true if creature haven't reached the final destination hex
|
||||
if ((nextPos + 1) < destTiles.size())
|
||||
{
|
||||
// update the next hex field which has to be reached by the stack
|
||||
nextPos++;
|
||||
curStackPos = nextHex;
|
||||
nextHex = destTiles[nextPos];
|
||||
|
||||
// update position of double wide creatures
|
||||
bool twoTiles = stack->doubleWide();
|
||||
if(twoTiles && bool(stack->attackerOwned) && (owner->creDir[stack->ID] != bool(stack->attackerOwned) )) //big attacker creature is reversed
|
||||
myAnim()->pos.x -= 44;
|
||||
else if(twoTiles && (! bool(stack->attackerOwned) ) && (owner->creDir[stack->ID] != bool(stack->attackerOwned) )) //big defender creature is reversed
|
||||
myAnim()->pos.x += 44;
|
||||
|
||||
// re-init animation
|
||||
for(std::list<std::pair<CBattleAnimation *, bool> >::iterator it = owner->pendingAnims.begin(); it != owner->pendingAnims.end(); ++it)
|
||||
{
|
||||
if (it->first == this)
|
||||
{
|
||||
it->second = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
endAnim();
|
||||
}
|
||||
}
|
||||
|
||||
void CMovementAnimation::endAnim()
|
||||
{
|
||||
const CStack * movedStack = stack;
|
||||
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
if(movedStack)
|
||||
owner->addNewAnim(new CMovementEndAnimation(owner, stack, nextHex));
|
||||
|
||||
|
||||
if(owner->moveSh >= 0)
|
||||
{
|
||||
CCS->soundh->stopSound(owner->moveSh);
|
||||
owner->moveSh = -1;
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
CMovementAnimation::CMovementAnimation(CBattleInterface *_owner, const CStack *_stack, std::vector<SHexField> _destTiles, int _distance)
|
||||
: CBattleStackAnimation(_owner, _stack), destTiles(_destTiles), nextPos(0), distance(_distance), stepX(0.0), stepY(0.0)
|
||||
{
|
||||
curStackPos = stack->position;
|
||||
nextHex = destTiles.front();
|
||||
}
|
||||
37
client/BattleInterface/CMovementAnimation.h
Normal file
37
client/BattleInterface/CMovementAnimation.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "CBattleStackAnimation.h"
|
||||
|
||||
|
||||
class CBattleInterface;
|
||||
class CStack;
|
||||
|
||||
/*
|
||||
* CMovementAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Move animation of a creature
|
||||
class CMovementAnimation : public CBattleStackAnimation
|
||||
{
|
||||
private:
|
||||
std::vector<SHexField> destTiles; //destination
|
||||
SHexField nextHex;
|
||||
ui32 nextPos;
|
||||
int distance;
|
||||
double stepX, stepY; //how far stack is moved in one frame
|
||||
double posX, posY;
|
||||
int steps, whichStep;
|
||||
int curStackPos; //position of stack before move
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CMovementAnimation(CBattleInterface *_owner, const CStack *_stack, std::vector<SHexField> _destTiles, int _distance);
|
||||
};
|
||||
52
client/BattleInterface/CMovementEndAnimation.cpp
Normal file
52
client/BattleInterface/CMovementEndAnimation.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "StdInc.h"
|
||||
#include "CMovementEndAnimation.h"
|
||||
|
||||
#include "../CCreatureAnimation.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../CCursorHandler.h"
|
||||
|
||||
bool CMovementEndAnimation::init()
|
||||
{
|
||||
if( !isEarliest(true) )
|
||||
return false;
|
||||
|
||||
if(!stack || myAnim()->framesInGroup(CCreatureAnim::MOVE_END) == 0 ||
|
||||
myAnim()->getType() == CCreatureAnim::DEATH)
|
||||
{
|
||||
endAnim();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CCS->soundh->playSound(battle_sound(stack->getCreature(), endMoving));
|
||||
|
||||
myAnim()->setType(CCreatureAnim::MOVE_END);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMovementEndAnimation::nextFrame()
|
||||
{
|
||||
if(myAnim()->onLastFrameInGroup())
|
||||
{
|
||||
endAnim();
|
||||
}
|
||||
}
|
||||
|
||||
void CMovementEndAnimation::endAnim()
|
||||
{
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
if(myAnim()->getType() != CCreatureAnim::DEATH)
|
||||
myAnim()->setType(CCreatureAnim::HOLDING); //resetting to default
|
||||
|
||||
CCS->curh->show();
|
||||
delete this;
|
||||
}
|
||||
|
||||
CMovementEndAnimation::CMovementEndAnimation(CBattleInterface * _owner, const CStack * _stack, SHexField destTile)
|
||||
: CBattleStackAnimation(_owner, _stack), destinationTile(destTile)
|
||||
{
|
||||
}
|
||||
30
client/BattleInterface/CMovementEndAnimation.h
Normal file
30
client/BattleInterface/CMovementEndAnimation.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "CBattleStackAnimation.h"
|
||||
|
||||
|
||||
class CBattleInterface;
|
||||
class CStack;
|
||||
|
||||
/*
|
||||
* CMovementEndAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Move end animation of a creature
|
||||
class CMovementEndAnimation : public CBattleStackAnimation
|
||||
{
|
||||
private:
|
||||
SHexField destinationTile;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CMovementEndAnimation(CBattleInterface *_owner, const CStack *_stack, SHexField destTile);
|
||||
};
|
||||
52
client/BattleInterface/CMovementStartAnimation.cpp
Normal file
52
client/BattleInterface/CMovementStartAnimation.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "StdInc.h"
|
||||
#include "CMovementStartAnimation.h"
|
||||
|
||||
#include "../CMusicHandler.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CCreatureAnimation.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
|
||||
bool CMovementStartAnimation::init()
|
||||
{
|
||||
if( !isEarliest(false) )
|
||||
return false;
|
||||
|
||||
|
||||
if(!stack || myAnim()->getType() == 5)
|
||||
{
|
||||
CMovementStartAnimation::endAnim();
|
||||
return false;
|
||||
}
|
||||
|
||||
CCS->soundh->playSound(battle_sound(stack->getCreature(), startMoving));
|
||||
myAnim()->setType(CCreatureAnim::MOVE_START);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMovementStartAnimation::nextFrame()
|
||||
{
|
||||
if(myAnim()->onLastFrameInGroup())
|
||||
{
|
||||
endAnim();
|
||||
}
|
||||
else
|
||||
{
|
||||
if((owner->animCount+1)%(4/owner->curInt->sysOpts.animSpeed)==0)
|
||||
myAnim()->incrementFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void CMovementStartAnimation::endAnim()
|
||||
{
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
CMovementStartAnimation::CMovementStartAnimation(CBattleInterface * _owner, const CStack * _stack)
|
||||
: CBattleStackAnimation(_owner, _stack)
|
||||
{
|
||||
}
|
||||
27
client/BattleInterface/CMovementStartAnimation.h
Normal file
27
client/BattleInterface/CMovementStartAnimation.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "CBattleStackAnimation.h"
|
||||
|
||||
class CBattleInterface;
|
||||
class CStack;
|
||||
|
||||
/*
|
||||
* CMovementStartAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Move start animation of a creature
|
||||
class CMovementStartAnimation : public CBattleStackAnimation
|
||||
{
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CMovementStartAnimation(CBattleInterface *_owner, const CStack *_stack);
|
||||
};
|
||||
100
client/BattleInterface/CReverseAnimation.cpp
Normal file
100
client/BattleInterface/CReverseAnimation.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "StdInc.h"
|
||||
#include "CReverseAnimation.h"
|
||||
|
||||
#include "../CCreatureAnimation.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "CHexFieldControl.h"
|
||||
|
||||
bool CReverseAnimation::init()
|
||||
{
|
||||
if(myAnim() == NULL || myAnim()->getType() == 5)
|
||||
{
|
||||
endAnim();
|
||||
|
||||
return false; //there is no such creature
|
||||
}
|
||||
|
||||
if(!priority && !isEarliest(false))
|
||||
return false;
|
||||
|
||||
if(myAnim()->framesInGroup(CCreatureAnim::TURN_R))
|
||||
myAnim()->setType(CCreatureAnim::TURN_R);
|
||||
else
|
||||
setupSecondPart();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CReverseAnimation::nextFrame()
|
||||
{
|
||||
if(partOfAnim == 1) //first part of animation
|
||||
{
|
||||
if(myAnim()->onLastFrameInGroup())
|
||||
{
|
||||
partOfAnim = 2;
|
||||
}
|
||||
}
|
||||
else if(partOfAnim == 2)
|
||||
{
|
||||
if(!secondPartSetup)
|
||||
{
|
||||
setupSecondPart();
|
||||
}
|
||||
if(myAnim()->onLastFrameInGroup())
|
||||
{
|
||||
endAnim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CReverseAnimation::endAnim()
|
||||
{
|
||||
CBattleAnimation::endAnim();
|
||||
if( stack->alive() )//don't do that if stack is dead
|
||||
myAnim()->setType(CCreatureAnim::HOLDING);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
CReverseAnimation::CReverseAnimation(CBattleInterface * _owner, const CStack * stack, SHexField dest, bool _priority)
|
||||
: CBattleStackAnimation(_owner, stack), partOfAnim(1), secondPartSetup(false), hex(dest), priority(_priority)
|
||||
{
|
||||
}
|
||||
|
||||
void CReverseAnimation::setupSecondPart()
|
||||
{
|
||||
owner->creDir[stack->ID] = !owner->creDir[stack->ID];
|
||||
|
||||
if(!stack)
|
||||
{
|
||||
endAnim();
|
||||
return;
|
||||
}
|
||||
|
||||
Point coords = CHexFieldControl::getXYUnitAnim(hex, owner->creDir[stack->ID], stack, owner);
|
||||
myAnim()->pos.x = coords.x;
|
||||
//creAnims[stackID]->pos.y = coords.second;
|
||||
|
||||
if(stack->doubleWide())
|
||||
{
|
||||
if(stack->attackerOwned)
|
||||
{
|
||||
if(!owner->creDir[stack->ID])
|
||||
myAnim()->pos.x -= 44;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(owner->creDir[stack->ID])
|
||||
myAnim()->pos.x += 44;
|
||||
}
|
||||
}
|
||||
|
||||
secondPartSetup = true;
|
||||
|
||||
if(myAnim()->framesInGroup(CCreatureAnim::TURN_L))
|
||||
myAnim()->setType(CCreatureAnim::TURN_L);
|
||||
else
|
||||
endAnim();
|
||||
}
|
||||
34
client/BattleInterface/CReverseAnimation.h
Normal file
34
client/BattleInterface/CReverseAnimation.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "CBattleStackAnimation.h"
|
||||
|
||||
|
||||
class CStack;
|
||||
|
||||
/*
|
||||
* CReverseAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Class responsible for animation of stack chaning direction (left <-> right)
|
||||
class CReverseAnimation : public CBattleStackAnimation
|
||||
{
|
||||
private:
|
||||
int partOfAnim; //1 - first, 2 - second
|
||||
bool secondPartSetup;
|
||||
SHexField hex;
|
||||
public:
|
||||
bool priority; //true - high, false - low
|
||||
bool init();
|
||||
void nextFrame();
|
||||
|
||||
void setupSecondPart();
|
||||
void endAnim();
|
||||
|
||||
CReverseAnimation(CBattleInterface *_owner, const CStack *stack, SHexField dest, bool _priority);
|
||||
};
|
||||
192
client/BattleInterface/CShootingAnimation.cpp
Normal file
192
client/BattleInterface/CShootingAnimation.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
#include "StdInc.h"
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include "CShootingAnimation.h"
|
||||
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CCreatureAnimation.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "CMovementStartAnimation.h"
|
||||
#include "CReverseAnimation.h"
|
||||
#include "CSpellEffectAnimation.h"
|
||||
#include "CHexFieldControl.h"
|
||||
|
||||
bool CShootingAnimation::init()
|
||||
{
|
||||
if( !CAttackAnimation::checkInitialConditions() )
|
||||
return false;
|
||||
|
||||
const CStack * shooter = attackingStack;
|
||||
|
||||
if(!shooter || myAnim()->getType() == 5)
|
||||
{
|
||||
endAnim();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the projectile animation
|
||||
|
||||
double projectileAngle; //in radians; if positive, projectiles goes up
|
||||
double straightAngle = 0.2; //maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absoulte value)
|
||||
int fromHex = shooter->position;
|
||||
projectileAngle = atan2(static_cast<double>(abs(dest - fromHex) / GameConstants::BFIELD_WIDTH), static_cast<double>(abs(dest - fromHex) % GameConstants::BFIELD_WIDTH));
|
||||
if(fromHex < dest)
|
||||
projectileAngle = -projectileAngle;
|
||||
|
||||
// Get further info about the shooter e.g. relative pos of projectile to unit.
|
||||
// If the creature id is 149 then it's a arrow tower which has no additional info so get the
|
||||
// actual arrow tower shooter instead.
|
||||
const CCreature *shooterInfo = shooter->getCreature();
|
||||
if (shooterInfo->idNumber == 149)
|
||||
{
|
||||
int creID = CGI->creh->factionToTurretCreature[owner->siegeH->town->town->typeID];
|
||||
shooterInfo = CGI->creh->creatures[creID];
|
||||
}
|
||||
|
||||
SProjectileInfo spi;
|
||||
spi.creID = shooter->getCreature()->idNumber;
|
||||
spi.stackID = shooter->ID;
|
||||
spi.reverse = !shooter->attackerOwned;
|
||||
|
||||
spi.step = 0;
|
||||
spi.frameNum = 0;
|
||||
if(vstd::contains(CGI->creh->idToProjectileSpin, shooterInfo->idNumber))
|
||||
spi.spin = CGI->creh->idToProjectileSpin[shooterInfo->idNumber];
|
||||
else
|
||||
{
|
||||
tlog2 << "Warning - no projectile spin for spi.creID " << shooterInfo->idNumber << std::endl;
|
||||
spi.spin = false;
|
||||
}
|
||||
|
||||
Point xycoord = CHexFieldControl::getXYUnitAnim(shooter->position, true, shooter, owner);
|
||||
Point destcoord;
|
||||
|
||||
|
||||
// The "master" point where all projectile positions relate to.
|
||||
static const Point projectileOrigin(181, 252);
|
||||
|
||||
if (attackedStack)
|
||||
{
|
||||
destcoord = CHexFieldControl::getXYUnitAnim(dest, false, attackedStack, owner);
|
||||
destcoord.x += 250; destcoord.y += 210; //TODO: find a better place to shoot
|
||||
|
||||
// Calculate projectile start position. Offsets are read out of the CRANIM.TXT.
|
||||
if (projectileAngle > straightAngle)
|
||||
{
|
||||
//upper shot
|
||||
spi.x = xycoord.x + projectileOrigin.x + shooterInfo->upperRightMissleOffsetX;
|
||||
spi.y = xycoord.y + projectileOrigin.y + shooterInfo->upperRightMissleOffsetY;
|
||||
}
|
||||
else if (projectileAngle < -straightAngle)
|
||||
{
|
||||
//lower shot
|
||||
spi.x = xycoord.x + projectileOrigin.x + shooterInfo->lowerRightMissleOffsetX;
|
||||
spi.y = xycoord.y + projectileOrigin.y + shooterInfo->lowerRightMissleOffsetY;
|
||||
}
|
||||
else
|
||||
{
|
||||
//straight shot
|
||||
spi.x = xycoord.x + projectileOrigin.x + shooterInfo->rightMissleOffsetX;
|
||||
spi.y = xycoord.y + projectileOrigin.y + shooterInfo->rightMissleOffsetY;
|
||||
}
|
||||
|
||||
double animSpeed = 23.0 * owner->getAnimSpeed(); // flight speed of projectile
|
||||
spi.lastStep = static_cast<int>(sqrt(static_cast<double>((destcoord.x - spi.x) * (destcoord.x - spi.x) + (destcoord.y - spi.y) * (destcoord.y - spi.y))) / animSpeed);
|
||||
if(spi.lastStep == 0)
|
||||
spi.lastStep = 1;
|
||||
spi.dx = (destcoord.x - spi.x) / spi.lastStep;
|
||||
spi.dy = (destcoord.y - spi.y) / spi.lastStep;
|
||||
spi.catapultInfo = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Catapult attack
|
||||
// These are the values for equations of this kind: f(x) = ax^2 + bx + c
|
||||
static const std::vector<SCatapultSProjectileInfo*> trajectoryCurves = boost::assign::list_of<SCatapultSProjectileInfo*>(new SCatapultSProjectileInfo(4.309, -3.198, 569.2, -296, 182))
|
||||
(new SCatapultSProjectileInfo(4.710, -3.11, 558.68, -258, 175))(new SCatapultSProjectileInfo(5.056, -3.003, 546.9, -236, 174))
|
||||
(new SCatapultSProjectileInfo(4.760, -2.74, 526.47, -216, 215))(new SCatapultSProjectileInfo(4.288, -2.496, 508.98, -223, 274))
|
||||
(new SCatapultSProjectileInfo(3.683, -3.018, 558.39, -324, 176))(new SCatapultSProjectileInfo(2.884, -2.607, 528.95, -366, 312))
|
||||
(new SCatapultSProjectileInfo(3.783, -2.364, 501.35, -227, 318));
|
||||
|
||||
static std::map<int, int> hexToCurve = boost::assign::map_list_of<int, int>(29, 0)(62, 1)(95, 2)(130, 3)(182, 4)(12, 5)(50, 6)(183, 7);
|
||||
|
||||
std::map<int, int>::iterator it = hexToCurve.find(dest.hex);
|
||||
|
||||
if (it == hexToCurve.end())
|
||||
{
|
||||
tlog1 << "For the hex position " << dest.hex << " is no curve defined.";
|
||||
endAnim();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int curveID = it->second;
|
||||
spi.catapultInfo = trajectoryCurves[curveID];
|
||||
double animSpeed = 3.318 * owner->getAnimSpeed();
|
||||
spi.lastStep = static_cast<int>((spi.catapultInfo->toX - spi.catapultInfo->fromX) / animSpeed);
|
||||
spi.dx = animSpeed;
|
||||
spi.dy = 0;
|
||||
spi.x = xycoord.x + projectileOrigin.x + shooterInfo->rightMissleOffsetX + 17.;
|
||||
spi.y = xycoord.y + projectileOrigin.y + shooterInfo->rightMissleOffsetY + 10.;
|
||||
|
||||
// Add explosion anim
|
||||
int xEnd = static_cast<int>(spi.x + spi.lastStep * spi.dx);
|
||||
int yEnd = static_cast<int>(spi.catapultInfo->calculateY(xEnd));
|
||||
owner->addNewAnim( new CSpellEffectAnimation(owner, "SGEXPL.DEF", xEnd - 126, yEnd - 105));
|
||||
}
|
||||
}
|
||||
|
||||
// Set starting frame
|
||||
if(spi.spin)
|
||||
{
|
||||
spi.frameNum = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double pi = boost::math::constants::pi<double>();
|
||||
spi.frameNum = static_cast<int>(((pi / 2.0 - projectileAngle) / (2.0 * pi) + 1/(static_cast<double>(2*(owner->idToProjectile[spi.creID]->ourImages.size()-1)))) * (owner->idToProjectile[spi.creID]->ourImages.size()-1));
|
||||
}
|
||||
|
||||
// Set projectile animation start delay which is specified in frames
|
||||
spi.animStartDelay = shooterInfo->attackClimaxFrame;
|
||||
owner->projectiles.push_back(spi);
|
||||
|
||||
//attack animation
|
||||
|
||||
shooting = true;
|
||||
|
||||
if(projectileAngle > straightAngle) //upper shot
|
||||
group = CCreatureAnim::SHOOT_UP;
|
||||
else if(projectileAngle < -straightAngle) //lower shot
|
||||
group = CCreatureAnim::SHOOT_DOWN;
|
||||
else //straight shot
|
||||
group = CCreatureAnim::SHOOT_FRONT;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CShootingAnimation::nextFrame()
|
||||
{
|
||||
for(std::list<std::pair<CBattleAnimation *, bool> >::const_iterator it = owner->pendingAnims.begin(); it != owner->pendingAnims.end(); ++it)
|
||||
{
|
||||
CMovementStartAnimation * anim = dynamic_cast<CMovementStartAnimation *>(it->first);
|
||||
CReverseAnimation * anim2 = dynamic_cast<CReverseAnimation *>(it->first);
|
||||
if( (anim && anim->stack->ID == stack->ID) || (anim2 && anim2->stack->ID == stack->ID && anim2->priority ) )
|
||||
return;
|
||||
}
|
||||
|
||||
CAttackAnimation::nextFrame();
|
||||
}
|
||||
|
||||
void CShootingAnimation::endAnim()
|
||||
{
|
||||
CBattleAnimation::endAnim();
|
||||
delete this;
|
||||
}
|
||||
|
||||
CShootingAnimation::CShootingAnimation(CBattleInterface * _owner, const CStack * attacker, SHexField _dest, const CStack * _attacked, bool _catapult, int _catapultDmg)
|
||||
: CAttackAnimation(_owner, attacker, _dest, _attacked), catapultDamage(_catapultDmg), catapult(_catapult)
|
||||
{
|
||||
|
||||
}
|
||||
49
client/BattleInterface/CShootingAnimation.h
Normal file
49
client/BattleInterface/CShootingAnimation.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "CAttackAnimation.h"
|
||||
#include "../../lib/SHexField.h"
|
||||
|
||||
class CBattleInterface;
|
||||
class CStack;
|
||||
struct SCatapultSProjectileInfo;
|
||||
|
||||
/*
|
||||
* CShootingAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Small struct which contains information about the position and the velocity of a projectile
|
||||
struct SProjectileInfo
|
||||
{
|
||||
double x, y; //position on the screen
|
||||
double dx, dy; //change in position in one step
|
||||
int step, lastStep; //to know when finish showing this projectile
|
||||
int creID; //ID of creature that shot this projectile
|
||||
int stackID; //ID of stack
|
||||
int frameNum; //frame to display form projectile animation
|
||||
bool spin; //if true, frameNum will be increased
|
||||
int animStartDelay; //how many times projectile must be attempted to be shown till it's really show (decremented after hit)
|
||||
bool reverse; //if true, projectile will be flipped by vertical asix
|
||||
SCatapultSProjectileInfo *catapultInfo; // holds info about the parabolic trajectory of the cannon
|
||||
};
|
||||
|
||||
/// Shooting attack
|
||||
class CShootingAnimation : public CAttackAnimation
|
||||
{
|
||||
private:
|
||||
int catapultDamage;
|
||||
bool catapult;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
//last param only for catapult attacks
|
||||
CShootingAnimation(CBattleInterface *_owner, const CStack *attacker,
|
||||
SHexField _dest, const CStack *_attacked, bool _catapult = false, int _catapultDmg = 0);
|
||||
};
|
||||
181
client/BattleInterface/CSpellEffectAnimation.cpp
Normal file
181
client/BattleInterface/CSpellEffectAnimation.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
#include "StdInc.h"
|
||||
#include "CSpellEffectAnimation.h"
|
||||
|
||||
#include "../Graphics.h"
|
||||
#include "CBattleInterface.h"
|
||||
#include "../CDefHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../SDL_Extensions.h"
|
||||
|
||||
//effect animation
|
||||
bool CSpellEffectAnimation::init()
|
||||
{
|
||||
if(!isEarliest(true))
|
||||
return false;
|
||||
|
||||
if(effect == 12) //armageddon
|
||||
{
|
||||
if(effect == -1 || graphics->battleACToDef[effect].size() != 0)
|
||||
{
|
||||
CDefHandler * anim;
|
||||
if(customAnim.size())
|
||||
anim = CDefHandler::giveDef(customAnim);
|
||||
else
|
||||
anim = CDefHandler::giveDef(graphics->battleACToDef[effect][0]);
|
||||
|
||||
if (Vflip)
|
||||
{
|
||||
for (size_t v = 0; v < anim->ourImages.size(); ++v)
|
||||
{
|
||||
CSDL_Ext::VflipSurf(anim->ourImages[v].bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i * anim->width < owner->pos.w ; ++i)
|
||||
{
|
||||
for(int j=0; j * anim->height < owner->pos.h ; ++j)
|
||||
{
|
||||
SBattleEffect be;
|
||||
be.effectID = ID;
|
||||
be.anim = CDefHandler::giveDef(graphics->battleACToDef[effect][0]);
|
||||
if (Vflip)
|
||||
{
|
||||
for (size_t v = 0; v < be.anim->ourImages.size(); ++v)
|
||||
{
|
||||
CSDL_Ext::VflipSurf(be.anim->ourImages[v].bitmap);
|
||||
}
|
||||
}
|
||||
be.frame = 0;
|
||||
be.maxFrame = be.anim->ourImages.size();
|
||||
be.x = i * anim->width + owner->pos.x;
|
||||
be.y = j * anim->height + owner->pos.y;
|
||||
|
||||
owner->battleEffects.push_back(be);
|
||||
}
|
||||
}
|
||||
}
|
||||
else //there is nothing to play
|
||||
{
|
||||
endAnim();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else // Effects targeted at a specific creature/hex.
|
||||
{
|
||||
if(effect == -1 || graphics->battleACToDef[effect].size() != 0)
|
||||
{
|
||||
const CStack* destStack = owner->curInt->cb->battleGetStackByPos(destTile, false);
|
||||
Rect &tilePos = owner->bfield[destTile].pos;
|
||||
SBattleEffect be;
|
||||
be.effectID = ID;
|
||||
if(customAnim.size())
|
||||
be.anim = CDefHandler::giveDef(customAnim);
|
||||
else
|
||||
be.anim = CDefHandler::giveDef(graphics->battleACToDef[effect][0]);
|
||||
|
||||
if (Vflip)
|
||||
{
|
||||
for (size_t v = 0; v < be.anim->ourImages.size(); ++v)
|
||||
{
|
||||
CSDL_Ext::VflipSurf(be.anim->ourImages[v].bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
be.frame = 0;
|
||||
be.maxFrame = be.anim->ourImages.size();
|
||||
if(effect == 1)
|
||||
be.maxFrame = 3;
|
||||
|
||||
switch (effect)
|
||||
{
|
||||
case -1:
|
||||
be.x = x;
|
||||
be.y = y;
|
||||
break;
|
||||
case 0: // Prayer and Lightning Bolt.
|
||||
case 1:
|
||||
// Position effect with it's bottom center touching the bottom center of affected tile(s).
|
||||
be.x = tilePos.x + tilePos.w/2 - be.anim->width/2;
|
||||
be.y = tilePos.y + tilePos.h - be.anim->height;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Position effect with it's center touching the top center of affected tile(s).
|
||||
be.x = tilePos.x + tilePos.w/2 - be.anim->width/2;
|
||||
be.y = tilePos.y - be.anim->height/2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Correction for 2-hex creatures.
|
||||
if (destStack != NULL && destStack->doubleWide())
|
||||
be.x += (destStack->attackerOwned ? -1 : 1)*tilePos.w/2;
|
||||
|
||||
owner->battleEffects.push_back(be);
|
||||
}
|
||||
else //there is nothing to play
|
||||
{
|
||||
endAnim();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//battleEffects
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSpellEffectAnimation::nextFrame()
|
||||
{
|
||||
//notice: there may be more than one effect in owner->battleEffects correcponding to this animation (ie. armageddon)
|
||||
for(std::list<SBattleEffect>::iterator it = owner->battleEffects.begin(); it != owner->battleEffects.end(); ++it)
|
||||
{
|
||||
if(it->effectID == ID)
|
||||
{
|
||||
++(it->frame);
|
||||
|
||||
if(it->frame == it->maxFrame)
|
||||
{
|
||||
endAnim();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->x += dx;
|
||||
it->y += dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSpellEffectAnimation::endAnim()
|
||||
{
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
std::vector<std::list<SBattleEffect>::iterator> toDel;
|
||||
|
||||
for(std::list<SBattleEffect>::iterator it = owner->battleEffects.begin(); it != owner->battleEffects.end(); ++it)
|
||||
{
|
||||
if(it->effectID == ID)
|
||||
{
|
||||
toDel.push_back(it);
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t b = 0; b < toDel.size(); ++b)
|
||||
{
|
||||
delete toDel[b]->anim;
|
||||
owner->battleEffects.erase(toDel[b]);
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, SHexField _destTile, int _dx, int _dy, bool _Vflip)
|
||||
:CBattleAnimation(_owner), effect(_effect), destTile(_destTile), customAnim(""), dx(_dx), dy(_dy), Vflip(_Vflip)
|
||||
{
|
||||
}
|
||||
|
||||
CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx, int _dy, bool _Vflip)
|
||||
:CBattleAnimation(_owner), effect(-1), destTile(0), customAnim(_customAnim), x(_x), y(_y), dx(_dx), dy(_dy), Vflip(_Vflip)
|
||||
{
|
||||
}
|
||||
35
client/BattleInterface/CSpellEffectAnimation.h
Normal file
35
client/BattleInterface/CSpellEffectAnimation.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "CBattleAnimation.h"
|
||||
#include "../../lib/SHexField.h"
|
||||
|
||||
class CBattleInterface;
|
||||
|
||||
/*
|
||||
* CSpellEffectAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// This class manages a spell effect animation
|
||||
class CSpellEffectAnimation : public CBattleAnimation
|
||||
{
|
||||
private:
|
||||
ui32 effect;
|
||||
SHexField destTile;
|
||||
std::string customAnim;
|
||||
int x, y, dx, dy;
|
||||
bool Vflip;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CSpellEffectAnimation(CBattleInterface *_owner, ui32 _effect, SHexField _destTile, int _dx = 0, int _dy = 0, bool _Vflip = false);
|
||||
CSpellEffectAnimation(CBattleInterface *_owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false);
|
||||
};
|
||||
125
client/BattleInterface/CStackQueue.cpp
Normal file
125
client/BattleInterface/CStackQueue.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "StdInc.h"
|
||||
#include "CStackQueue.h"
|
||||
|
||||
#include "CBattleInterface.h"
|
||||
#include "../../lib/BattleState.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../SDL_Extensions.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../../CCallback.h"
|
||||
|
||||
void CStackQueue::update()
|
||||
{
|
||||
stacksSorted.clear();
|
||||
owner->curInt->cb->getStackQueue(stacksSorted, QUEUE_SIZE);
|
||||
for (int i = 0; i < QUEUE_SIZE ; i++)
|
||||
{
|
||||
stackBoxes[i]->setStack(stacksSorted[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CStackQueue::CStackQueue(bool Embedded, CBattleInterface * _owner)
|
||||
:embedded(Embedded), owner(_owner)
|
||||
{
|
||||
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 )
|
||||
{
|
||||
blitBg(to);
|
||||
|
||||
CIntObject::showAll(to);
|
||||
}
|
||||
|
||||
void CStackQueue::blitBg( SDL_Surface * to )
|
||||
{
|
||||
if(bg)
|
||||
{
|
||||
for (int w = 0; w < pos.w; w += bg->w)
|
||||
{
|
||||
blitAtLoc(bg, w, 0, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CStackQueue::StackBox::showAll( SDL_Surface *to )
|
||||
{
|
||||
assert(my);
|
||||
if(bg)
|
||||
{
|
||||
graphics->blueToPlayersAdv(bg, my->owner);
|
||||
//SDL_UpdateRect(bg, 0, 0, 0, 0);
|
||||
SDL_Rect temp_rect = genRect(bg->h, bg->w, pos.x, pos.y);
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(bg, NULL, to, &temp_rect);
|
||||
//blitAt(bg, pos, to);
|
||||
blitAt(graphics->bigImgs[my->getCreature()->idNumber], pos.x +9, pos.y + 1, to);
|
||||
printAtMiddleLoc(makeNumberShort(my->count), pos.w/2, pos.h - 12, FONT_MEDIUM, zwykly, to);
|
||||
}
|
||||
else
|
||||
{
|
||||
blitAt(graphics->smallImgs[-2], pos, to);
|
||||
blitAt(graphics->smallImgs[my->getCreature()->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->count), 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)
|
||||
:my(NULL), bg(BG)
|
||||
{
|
||||
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 )
|
||||
{
|
||||
|
||||
}
|
||||
51
client/BattleInterface/CStackQueue.h
Normal file
51
client/BattleInterface/CStackQueue.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GUIBase.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
class CStack;
|
||||
class CBattleInterface;
|
||||
|
||||
/*
|
||||
* CStackQueue.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Shows the stack queue
|
||||
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;
|
||||
CBattleInterface * owner;
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
CStackQueue(bool Embedded, CBattleInterface * _owner);
|
||||
~CStackQueue();
|
||||
void update();
|
||||
void blitBg( SDL_Surface * to );
|
||||
//void showAll(SDL_Surface *to);
|
||||
};
|
||||
25
client/BattleInterface/SStackAttackedInfo.h
Normal file
25
client/BattleInterface/SStackAttackedInfo.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
class CStack;
|
||||
|
||||
/*
|
||||
* SStackAttackedInfo.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
||||
struct SStackAttackedInfo
|
||||
{
|
||||
const CStack * defender; //attacked stack
|
||||
int dmg; //damage dealt
|
||||
int amountKilled; //how many creatures in stack has been killed
|
||||
const CStack * attacker; //attacking stack
|
||||
bool byShooting; //if true, stack has been attacked by shooting
|
||||
bool killed; //if true, stack has been killed
|
||||
bool rebirth; //if true, play rebirth animation after all
|
||||
};
|
||||
@@ -1,597 +0,0 @@
|
||||
#ifndef __CBATTLEINTERFACE_H__
|
||||
#define __CBATTLEINTERFACE_H__
|
||||
|
||||
#include "../global.h"
|
||||
#include <list>
|
||||
#include "GUIBase.h"
|
||||
#include "../lib/CCreatureSet.h"
|
||||
#include "../lib/ConstTransitivePtr.h" //may be reundant
|
||||
#include "CAnimation.h"
|
||||
|
||||
/*
|
||||
* CBattleInterface.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class CLabel;
|
||||
class CCreatureSet;
|
||||
class CGHeroInstance;
|
||||
class CDefHandler;
|
||||
class CStack;
|
||||
class CCallback;
|
||||
class AdventureMapButton;
|
||||
class CHighlightableButton;
|
||||
class CHighlightableButtonsGroup;
|
||||
struct BattleResult;
|
||||
struct BattleSpellCast;
|
||||
struct CObstacleInstance;
|
||||
template <typename T> struct CondSh;
|
||||
struct SetStackEffect;;
|
||||
struct BattleAction;
|
||||
class CGTownInstance;
|
||||
struct CatapultAttack;
|
||||
class CBattleInterface;
|
||||
struct CatapultProjectileInfo;
|
||||
struct BattleTriggerEffect;
|
||||
|
||||
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
||||
struct SStackAttackedInfo
|
||||
{
|
||||
const CStack * defender; //attacked stack
|
||||
int dmg; //damage dealt
|
||||
int amountKilled; //how many creatures in stack has been killed
|
||||
const CStack * attacker; //attacking stack
|
||||
bool byShooting; //if true, stack has been attacked by shooting
|
||||
bool killed; //if true, stack has been killed
|
||||
bool rebirth; //if true, play rebirth animation after all
|
||||
};
|
||||
|
||||
/// Small struct which contains information about the position and the velocity of a projectile
|
||||
struct SProjectileInfo
|
||||
{
|
||||
double x, y; //position on the screen
|
||||
double dx, dy; //change in position in one step
|
||||
int step, lastStep; //to know when finish showing this projectile
|
||||
int creID; //ID of creature that shot this projectile
|
||||
int stackID; //ID of stack
|
||||
int frameNum; //frame to display form projectile animation
|
||||
bool spin; //if true, frameNum will be increased
|
||||
int animStartDelay; //how many times projectile must be attempted to be shown till it's really show (decremented after hit)
|
||||
bool reverse; //if true, projectile will be flipped by vertical asix
|
||||
CatapultProjectileInfo *catapultInfo; // holds info about the parabolic trajectory of the cannon
|
||||
};
|
||||
|
||||
|
||||
/// Base class of battle animations
|
||||
class CBattleAnimation
|
||||
{
|
||||
protected:
|
||||
CBattleInterface * owner;
|
||||
public:
|
||||
virtual bool init()=0; //to be called - if returned false, call again until returns true
|
||||
virtual void nextFrame()=0; //call every new frame
|
||||
virtual void endAnim(); //to be called mostly internally; in this class it removes animation from pendingAnims list
|
||||
|
||||
bool isEarliest(bool perStackConcurrency); //determines if this animation is earliest of all
|
||||
|
||||
unsigned int ID; //unique identifier
|
||||
|
||||
CBattleAnimation(CBattleInterface * _owner);
|
||||
};
|
||||
|
||||
class CDummyAnim : public CBattleAnimation
|
||||
{
|
||||
private:
|
||||
int counter;
|
||||
int howMany;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CDummyAnim(CBattleInterface * _owner, int howManyFrames);
|
||||
};
|
||||
|
||||
/// This class manages a spell effect animation
|
||||
class CSpellEffectAnim : public CBattleAnimation
|
||||
{
|
||||
private:
|
||||
ui32 effect;
|
||||
THex destTile;
|
||||
std::string customAnim;
|
||||
int x, y, dx, dy;
|
||||
bool Vflip;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CSpellEffectAnim(CBattleInterface * _owner, ui32 _effect, THex _destTile, int _dx = 0, int _dy = 0, bool _Vflip = false);
|
||||
CSpellEffectAnim(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false);
|
||||
};
|
||||
|
||||
/// Sub-class which is responsible for managing the battle stack animation.
|
||||
class CBattleStackAnimation : public CBattleAnimation
|
||||
{
|
||||
public:
|
||||
const CStack * stack; //id of stack whose animation it is
|
||||
|
||||
CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack);
|
||||
static bool isToReverseHlp(THex hexFrom, THex hexTo, bool curDir); //helper for isToReverse
|
||||
static bool isToReverse(THex hexFrom, THex hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir); //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
|
||||
|
||||
CCreatureAnimation *myAnim(); //animation for our stack
|
||||
};
|
||||
|
||||
/// Class responsible for animation of stack chaning direction (left <-> right)
|
||||
class CReverseAnim : public CBattleStackAnimation
|
||||
{
|
||||
private:
|
||||
int partOfAnim; //1 - first, 2 - second
|
||||
bool secondPartSetup;
|
||||
THex hex;
|
||||
public:
|
||||
bool priority; //true - high, false - low
|
||||
bool init();
|
||||
void nextFrame();
|
||||
|
||||
void setupSecondPart();
|
||||
void endAnim();
|
||||
|
||||
CReverseAnim(CBattleInterface * _owner, const CStack * stack, THex dest, bool _priority);
|
||||
};
|
||||
|
||||
/// Animation of a defending unit
|
||||
class CDefenceAnim : public CBattleStackAnimation
|
||||
{
|
||||
private:
|
||||
//std::vector<SStackAttackedInfo> attackedInfos;
|
||||
int dmg; //damage dealt
|
||||
int amountKilled; //how many creatures in stack has been killed
|
||||
const CStack * attacker; //attacking stack
|
||||
bool byShooting; //if true, stack has been attacked by shooting
|
||||
bool killed; //if true, stack has been killed
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CDefenceAnim(SStackAttackedInfo _attackedInfo, CBattleInterface * _owner);
|
||||
};
|
||||
|
||||
/// Move animation of a creature
|
||||
class CBattleStackMoved : public CBattleStackAnimation
|
||||
{
|
||||
private:
|
||||
std::vector<THex> destTiles; //destination
|
||||
THex nextHex;
|
||||
int nextPos;
|
||||
int distance;
|
||||
float stepX, stepY; //how far stack is moved in one frame
|
||||
float posX, posY;
|
||||
int steps, whichStep;
|
||||
int curStackPos; //position of stack before move
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CBattleStackMoved(CBattleInterface * _owner, const CStack * _stack, std::vector<THex> _destTiles, int _distance);
|
||||
};
|
||||
|
||||
/// Move start animation of a creature
|
||||
class CBattleMoveStart : public CBattleStackAnimation
|
||||
{
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CBattleMoveStart(CBattleInterface * _owner, const CStack * _stack);
|
||||
};
|
||||
|
||||
/// Move end animation of a creature
|
||||
class CBattleMoveEnd : public CBattleStackAnimation
|
||||
{
|
||||
private:
|
||||
THex destinationTile;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CBattleMoveEnd(CBattleInterface * _owner, const CStack * _stack, THex destTile);
|
||||
};
|
||||
|
||||
/// This class is responsible for managing the battle attack animation
|
||||
class CBattleAttack : public CBattleStackAnimation
|
||||
{
|
||||
protected:
|
||||
THex dest; //atacked hex
|
||||
bool shooting;
|
||||
CCreatureAnim::EAnimType group; //if shooting is true, print this animation group
|
||||
const CStack * attackedStack;
|
||||
const CStack * attackingStack;
|
||||
int attackingStackPosBeforeReturn; //for stacks with return_after_strike feature
|
||||
public:
|
||||
void nextFrame();
|
||||
|
||||
bool checkInitialConditions();
|
||||
|
||||
|
||||
CBattleAttack(CBattleInterface * _owner, const CStack * attacker, THex _dest, const CStack * defender);
|
||||
};
|
||||
|
||||
/// Hand-to-hand attack
|
||||
class CMeleeAttack : public CBattleAttack
|
||||
{
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CMeleeAttack(CBattleInterface * _owner, const CStack * attacker, THex _dest, const CStack * _attacked);
|
||||
};
|
||||
|
||||
/// Shooting attack
|
||||
class CShootingAnim : public CBattleAttack
|
||||
{
|
||||
private:
|
||||
int catapultDamage;
|
||||
bool catapult;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
|
||||
CShootingAnim(CBattleInterface * _owner, const CStack * attacker, THex _dest, const CStack * _attacked, bool _catapult = false, int _catapultDmg = 0); //last param only for catapult attacks
|
||||
};
|
||||
|
||||
//end of battle animation handlers
|
||||
|
||||
/// Hero battle animation
|
||||
class CBattleHero : public CIntObject
|
||||
{
|
||||
public:
|
||||
bool flip; //false if it's attacking hero, true otherwise
|
||||
CDefHandler * dh, *flag; //animation and flag
|
||||
const CGHeroInstance * myHero; //this animation's hero instance
|
||||
const CBattleInterface * myOwner; //battle interface to which this animation is assigned
|
||||
int phase; //stage of animation
|
||||
int nextPhase; //stage of animation to be set after current phase is fully displayed
|
||||
int image; //frame of animation
|
||||
unsigned char flagAnim, flagAnimCount; //for flag animation
|
||||
void show(SDL_Surface * to); //prints next frame of animation to to
|
||||
void activate();
|
||||
void deactivate();
|
||||
void setPhase(int newPhase); //sets phase of hero animation
|
||||
void clickLeft(tribool down, bool previousState); //call-in
|
||||
CBattleHero(const std::string & defName, int phaseG, int imageG, bool filpG, unsigned char player, const CGHeroInstance * hero, const CBattleInterface * owner); //c-tor
|
||||
~CBattleHero(); //d-tor
|
||||
};
|
||||
|
||||
/// Class which stands for a single hex field on a battlefield
|
||||
class CBattleHex : public CIntObject
|
||||
{
|
||||
private:
|
||||
bool setAlterText; //if true, this hex has set alternative text in console and will clean it
|
||||
public:
|
||||
unsigned int myNumber; //number of hex in commonly used format
|
||||
bool accessible; //if true, this hex is accessible for units
|
||||
//CStack * ourStack;
|
||||
bool hovered, strictHovered; //for determining if hex is hovered by mouse (this is different problem than hex's graphic hovering)
|
||||
CBattleInterface * myInterface; //interface that owns me
|
||||
static Point getXYUnitAnim(const int & hexNum, const bool & attacker, const CStack * creature, const CBattleInterface * cbi); //returns (x, y) of left top corner of animation
|
||||
//for user interactions
|
||||
void hover (bool on);
|
||||
void activate();
|
||||
void deactivate();
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
CBattleHex();
|
||||
};
|
||||
|
||||
/// Class which manages the locked hex fields that are blocked e.g. by obstacles
|
||||
class CBattleObstacle
|
||||
{
|
||||
std::vector<int> lockedHexes;
|
||||
};
|
||||
|
||||
/// Class which shows the console at the bottom of the battle screen and manages the text of the console
|
||||
class CBattleConsole : public CIntObject
|
||||
{
|
||||
private:
|
||||
std::vector< std::string > texts; //a place where texts are stored
|
||||
int lastShown; //last shown line of text
|
||||
public:
|
||||
std::string alterTxt; //if it's not empty, this text is displayed
|
||||
std::string ingcAlter; //alternative text set by in-game console - very important!
|
||||
int whoSetAlter; //who set alter text; 0 - battle interface or none, 1 - button
|
||||
CBattleConsole(); //c-tor
|
||||
~CBattleConsole(); //d-tor
|
||||
void show(SDL_Surface * to = 0);
|
||||
bool addText(const std::string & text); //adds text at the last position; returns false if failed (e.g. text longer than 70 characters)
|
||||
void eraseText(unsigned int pos); //erases added text at position pos
|
||||
void changeTextAt(const std::string & text, unsigned int pos); //if we have more than pos texts, pos-th is changed to given one
|
||||
void scrollUp(unsigned int by = 1); //scrolls console up by 'by' positions
|
||||
void scrollDown(unsigned int by = 1); //scrolls console up by 'by' positions
|
||||
};
|
||||
|
||||
/// Class which is responsible for showing the battle result window
|
||||
class CBattleResultWindow : public CIntObject
|
||||
{
|
||||
private:
|
||||
SDL_Surface * background;
|
||||
AdventureMapButton * exit;
|
||||
CBattleInterface * owner;
|
||||
public:
|
||||
CBattleResultWindow(const BattleResult & br, const SDL_Rect & pos, CBattleInterface * _owner); //c-tor
|
||||
~CBattleResultWindow(); //d-tor
|
||||
|
||||
void bExitf(); //exit button callback
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
void show(SDL_Surface * to = 0);
|
||||
};
|
||||
|
||||
/// Class which manages the battle options window
|
||||
class CBattleOptionsWindow : public CIntObject
|
||||
{
|
||||
private:
|
||||
CBattleInterface * myInt;
|
||||
CPicture * background;
|
||||
AdventureMapButton * setToDefault, * exit;
|
||||
CHighlightableButton * viewGrid, * movementShadow, * mouseShadow;
|
||||
CHighlightableButtonsGroup * animSpeeds;
|
||||
|
||||
std::vector<CLabel*> labels;
|
||||
public:
|
||||
CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface * owner); //c-tor
|
||||
|
||||
void bDefaultf(); //dafault button callback
|
||||
void bExitf(); //exit button callback
|
||||
};
|
||||
|
||||
/// Struct for battle effect animation e.g. morale, prayer, armageddon, bless,...
|
||||
struct SBattleEffect
|
||||
{
|
||||
int x, y; //position on the screen
|
||||
int frame, maxFrame;
|
||||
CDefHandler * anim; //animation to display
|
||||
int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim
|
||||
};
|
||||
|
||||
/// Shows the stack queue
|
||||
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;
|
||||
CBattleInterface * owner;
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
CStackQueue(bool Embedded, CBattleInterface * _owner);
|
||||
~CStackQueue();
|
||||
void update();
|
||||
void blitBg( SDL_Surface * to );
|
||||
//void showAll(SDL_Surface *to);
|
||||
};
|
||||
|
||||
/// Small struct which is needed for drawing the parabolic trajectory of the catapult cannon
|
||||
struct CatapultProjectileInfo
|
||||
{
|
||||
const double facA, facB, facC;
|
||||
const int fromX, toX;
|
||||
|
||||
CatapultProjectileInfo() : facA(0), facB(0), facC(0), fromX(0), toX(0) { };
|
||||
CatapultProjectileInfo(double factorA, double factorB, double factorC, int fromXX, int toXX) : facA(factorA), facB(factorB), facC(factorC),
|
||||
fromX(fromXX), toX(toXX) { };
|
||||
|
||||
double calculateY(double x);
|
||||
};
|
||||
|
||||
/// Big class which handles the overall battle interface actions and it is also responsible for
|
||||
/// drawing everything correctly.
|
||||
class CBattleInterface : public CIntObject
|
||||
{
|
||||
enum SpellSelectionType
|
||||
{
|
||||
ANY_LOCATION = 0, FRIENDLY_CREATURE, HOSTILE_CREATURE, ANY_CREATURE, OBSTACLE, TELEPORT, NO_LOCATION = -1, STACK_SPELL_CANCELLED = -2
|
||||
};
|
||||
private:
|
||||
SDL_Surface * background, * menu, * amountNormal, * amountNegative, * amountPositive, * amountEffNeutral, * cellBorders, * backgroundWithHexes;
|
||||
AdventureMapButton * bOptions, * bSurrender, * bFlee, * bAutofight, * bSpell,
|
||||
* bWait, * bDefence, * bConsoleUp, * bConsoleDown, *btactNext, *btactEnd;
|
||||
CBattleConsole * console;
|
||||
CBattleHero * attackingHero, * defendingHero; //fighting heroes
|
||||
CStackQueue *queue;
|
||||
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
||||
const CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
|
||||
std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
||||
std::map< int, CDefHandler * > idToProjectile; //projectiles of creatures (creatureID, defhandler)
|
||||
std::map< int, CDefHandler * > idToObstacle; //obstacles located on the battlefield
|
||||
std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation>
|
||||
unsigned char animCount;
|
||||
const CStack * activeStack; //number of active stack; NULL - no one
|
||||
const CStack * stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; NULL of none
|
||||
void activateStack(); //sets activeStack to stackToActivate etc.
|
||||
int mouseHoveredStack; //stack hovered by mouse; if -1 -> none
|
||||
time_t lastMouseHoveredStackAnimationTime; // time when last mouse hovered animation occurred
|
||||
static const time_t HOVER_ANIM_DELTA;
|
||||
std::vector<THex> occupyableHexes, //hexes available for active stack
|
||||
attackableHexes; //hexes attackable by active stack
|
||||
bool stackCountOutsideHexes[BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back
|
||||
int previouslyHoveredHex; //number of hex that was hovered by the cursor a while ago
|
||||
int currentlyHoveredHex; //number of hex that is supposed to be hovered (for a while it may be inappropriately set, but will be renewed soon)
|
||||
int attackingHex; //hex from which the stack would perform attack with current cursor
|
||||
float getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group
|
||||
std::map<int, int> standingFrame; //number of frame in standing animation by stack ID, helps in showing 'random moves'
|
||||
|
||||
CPlayerInterface *tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
|
||||
bool tacticsMode;
|
||||
bool stackCanCastSpell; //if true, active stack could possibly cats some target spell
|
||||
bool spellDestSelectMode; //if true, player is choosing destination for his spell
|
||||
SpellSelectionType spellSelMode;
|
||||
BattleAction * spellToCast; //spell for which player is choosing destination
|
||||
TSpell creatureSpellToCast;
|
||||
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
||||
|
||||
void showAliveStack(const CStack *stack, SDL_Surface * to); //helper function for function show
|
||||
void showAliveStacks(std::vector<const CStack *> *aliveStacks, int hex, std::vector<const CStack *> *flyingStacks, SDL_Surface *to); // loops through all stacks at a given hex position
|
||||
void showPieceOfWall(SDL_Surface * to, int hex, const std::vector<const CStack*> & stacks); //helper function for show
|
||||
void showObstacles(std::multimap<THex, int> *hexToObstacle, std::vector<CObstacleInstance> &obstacles, int hex, SDL_Surface *to); // show all obstacles at a given hex position
|
||||
void redrawBackgroundWithHexes(const CStack * activeStack);
|
||||
void printConsoleAttacked(const CStack * defender, int dmg, int killed, const CStack * attacker, bool Multiple);
|
||||
|
||||
std::list<SProjectileInfo> projectiles; //projectiles flying on battlefield
|
||||
void projectileShowHelper(SDL_Surface * to); //prints projectiles present on the battlefield
|
||||
void giveCommand(ui8 action, THex tile, ui32 stack, si32 additional=-1);
|
||||
bool isTileAttackable(const THex & number) const; //returns true if tile 'number' is neighboring any tile from active stack's range or is one of these tiles
|
||||
bool blockedByObstacle(THex hex) const;
|
||||
bool isCatapultAttackable(THex hex) const; //returns true if given tile can be attacked by catapult
|
||||
|
||||
std::list<SBattleEffect> battleEffects; //different animations to display on the screen like spell effects
|
||||
|
||||
/// Class which is responsible for drawing the wall of a siege during battle
|
||||
class SiegeHelper
|
||||
{
|
||||
private:
|
||||
static std::string townTypeInfixes[F_NUMBER]; //for internal use only - to build filenames
|
||||
SDL_Surface * walls[18];
|
||||
const CBattleInterface * owner;
|
||||
public:
|
||||
const CGTownInstance * town; //besieged town
|
||||
|
||||
SiegeHelper(const CGTownInstance * siegeTown, const CBattleInterface * _owner); //c-tor
|
||||
~SiegeHelper(); //d-tor
|
||||
|
||||
//filename getters
|
||||
std::string getSiegeName(ui16 what, ui16 additInfo = 1) const; //what: 0 - background, 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall, 5 - below gate, 6 - over gate, 7 - upper wall, 8 - uppert tower, 9 - gate, 10 - gate arch, 11 - bottom static wall, 12 - upper static wall, 13 - moat, 14 - mlip, 15 - keep creature cover, 16 - bottom turret creature cover, 17 - upper turret creature cover; additInfo: 1 - intact, 2 - damaged, 3 - destroyed
|
||||
|
||||
void printPartOfWall(SDL_Surface * to, int what);//what: 1 - background wall, 2 - keep, 3 - bottom tower, 4 - bottom wall, 5 - below gate, 6 - over gate, 7 - upper wall, 8 - uppert tower, 9 - gate, 10 - gate arch, 11 - bottom static wall, 12 - upper static wall, 15 - keep creature cover, 16 - bottom turret creature cover, 17 - upper turret creature cover
|
||||
|
||||
friend class CBattleInterface;
|
||||
} * siegeH;
|
||||
|
||||
CPlayerInterface * attackerInt, * defenderInt; //because LOCPLINT is not enough in hotSeat
|
||||
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
|
||||
public:
|
||||
CPlayerInterface * curInt; //current player interface
|
||||
std::list<std::pair<CBattleAnimation *, bool> > pendingAnims; //currently displayed animations <anim, initialized>
|
||||
void addNewAnim(CBattleAnimation * anim); //adds new anim to pendingAnims
|
||||
unsigned int animIDhelper; //for giving IDs for animations
|
||||
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
|
||||
|
||||
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen); //c-tor
|
||||
~CBattleInterface(); //d-tor
|
||||
|
||||
//std::vector<TimeInterested*> timeinterested; //animation handling
|
||||
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
|
||||
void setAnimSpeed(int set); //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
|
||||
int getAnimSpeed() const; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
|
||||
|
||||
CBattleHex bfield[BFIELD_SIZE]; //11 lines, 17 hexes on each
|
||||
//std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
|
||||
SDL_Surface * cellBorder, * cellShade;
|
||||
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 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
|
||||
|
||||
//button handle funcs:
|
||||
void bOptionsf();
|
||||
void bSurrenderf();
|
||||
void bFleef();
|
||||
void reallyFlee(); //performs fleeing without asking player
|
||||
void reallySurrender(); //performs surrendering without asking player
|
||||
void bAutofightf();
|
||||
void bSpellf();
|
||||
void bWaitf();
|
||||
void bDefencef();
|
||||
void bConsoleUpf();
|
||||
void bConsoleDownf();
|
||||
void bTacticNextStack();
|
||||
void bEndTacticPhase();
|
||||
//end of button handle funcs
|
||||
//napisz tu klase odpowiadajaca za wyswietlanie bitwy i obsluge uzytkownika, polecenia ma przekazywac callbackiem
|
||||
void activate();
|
||||
void deactivate();
|
||||
void show(SDL_Surface * to);
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void mouseMoved(const SDL_MouseMotionEvent &sEvent);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
|
||||
//call-ins
|
||||
void startAction(const BattleAction* action);
|
||||
void newStack(const CStack * stack); //new stack appeared on battlefield
|
||||
void stackRemoved(int stackID); //stack disappeared from batlefiled
|
||||
void stackActivated(const CStack * stack); //active stack has been changed
|
||||
void stackMoved(const CStack * stack, std::vector<THex> destHex, int distance); //stack with id number moved to destHex
|
||||
void waitForAnims();
|
||||
void stacksAreAttacked(std::vector<SStackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
|
||||
void stackAttacking(const CStack * attacker, THex dest, const CStack * attacked, bool shooting); //called when stack with id ID is attacking something on hex dest
|
||||
void newRoundFirst( int round );
|
||||
void newRound(int number); //caled when round is ended; number is the number of round
|
||||
void hexLclicked(int whichOne); //hex only call-in
|
||||
void stackIsCatapulting(const CatapultAttack & ca); //called when a stack is attacking walls
|
||||
void battleFinished(const BattleResult& br); //called when battle is finished - battleresult window should be printed
|
||||
const BattleResult * bresult; //result of a battle; if non-zero then display when all animations end
|
||||
void displayBattleFinished(); //displays battle result
|
||||
void spellCast(const BattleSpellCast * sc); //called when a hero casts a spell
|
||||
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 battleTriggerEffect(const BattleTriggerEffect & bte);
|
||||
void setBattleCursor(const int myNumber); //really complex and messy
|
||||
void endAction(const BattleAction* action);
|
||||
void hideQueue();
|
||||
void showQueue();
|
||||
friend class CBattleHex;
|
||||
friend class CBattleResultWindow;
|
||||
friend class CPlayerInterface;
|
||||
friend class AdventureMapButton;
|
||||
friend class CInGameConsole;
|
||||
friend class CReverseAnim;
|
||||
friend class CBattleStackAnimation;
|
||||
friend class CBattleAnimation;
|
||||
friend class CDefenceAnim;
|
||||
friend class CBattleStackMoved;
|
||||
friend class CBattleMoveStart;
|
||||
friend class CBattleMoveEnd;
|
||||
friend class CBattleAttack;
|
||||
friend class CMeleeAttack;
|
||||
friend class CShootingAnim;
|
||||
friend class CSpellEffectAnim;
|
||||
friend class CBattleHero;
|
||||
};
|
||||
|
||||
#endif // __CBATTLEINTERFACE_H__
|
||||
2
client/StdInc.cpp
Normal file
2
client/StdInc.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
// Creates the precompiled header
|
||||
#include "StdInc.h"
|
||||
325
client/StdInc.h
Normal file
325
client/StdInc.h
Normal file
@@ -0,0 +1,325 @@
|
||||
#pragma once
|
||||
|
||||
// Standard include file
|
||||
// Should be treated as a precompiled header file in the compiler settings
|
||||
// We generate a .PCH file for every project due to simplicity and some annoying bugs in VisualStudio
|
||||
// This file shouldn't be changed, except if there is a important header file which is missing.
|
||||
|
||||
/*
|
||||
* StdInc.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <cstdio>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#include "../tchar_amigaos4.h"
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <cstdlib>
|
||||
|
||||
//filesystem version 3 causes problems (and it's default as of boost 1.46)
|
||||
#define BOOST_FILESYSTEM_VERSION 2
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
// Integral data types
|
||||
typedef boost::uint64_t ui64; //unsigned int 64 bits (8 bytes)
|
||||
typedef boost::uint32_t ui32; //unsigned int 32 bits (4 bytes)
|
||||
typedef boost::uint16_t ui16; //unsigned int 16 bits (2 bytes)
|
||||
typedef boost::uint8_t ui8; //unsigned int 8 bits (1 byte)
|
||||
typedef boost::int64_t si64; //signed int 64 bits (8 bytes)
|
||||
typedef boost::int32_t si32; //signed int 32 bits (4 bytes)
|
||||
typedef boost::int16_t si16; //signed int 16 bits (2 bytes)
|
||||
typedef boost::int8_t si8; //signed int 8 bits (1 byte)
|
||||
|
||||
// Import + Export macro declarations
|
||||
#ifdef _WIN32
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define DLL_EXPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define DLL_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DLL_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define DLL_IMPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define DLL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef VCMI_DLL
|
||||
#define DLL_LINKAGE DLL_EXPORT
|
||||
#else
|
||||
#define DLL_LINKAGE DLL_IMPORT
|
||||
#endif
|
||||
|
||||
|
||||
//a normal std::map with a const operator[] for sanity
|
||||
template<typename KeyT, typename ValT>
|
||||
class bmap : public std::map<KeyT, ValT>
|
||||
{
|
||||
public:
|
||||
const ValT & operator[](KeyT key) const
|
||||
{
|
||||
return find(key)->second;
|
||||
}
|
||||
ValT & operator[](KeyT key)
|
||||
{
|
||||
return static_cast<std::map<KeyT, ValT> &>(*this)[key];
|
||||
}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<std::map<KeyT, ValT> &>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
namespace vstd
|
||||
{
|
||||
//returns true if container c contains item i
|
||||
template <typename Container, typename Item>
|
||||
bool contains(const Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i) != c.end();
|
||||
}
|
||||
|
||||
//returns true if map c contains item i
|
||||
template <typename V, typename Item, typename Item2>
|
||||
bool contains(const std::map<Item,V> & c, const Item2 &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns true if bmap c contains item i
|
||||
template <typename V, typename Item, typename Item2>
|
||||
bool contains(const bmap<Item,V> & c, const Item2 &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns true if unordered set c contains item i
|
||||
template <typename Item>
|
||||
bool contains(const boost::unordered_set<Item> & c, const Item &i)
|
||||
{
|
||||
return c.find(i)!=c.end();
|
||||
}
|
||||
|
||||
//returns position of first element in vector c equal to s, if there is no such element, -1 is returned
|
||||
template <typename T1, typename T2>
|
||||
int find_pos(const std::vector<T1> & c, const T2 &s)
|
||||
{
|
||||
for(size_t i=0; i < c.size(); ++i)
|
||||
if(c[i] == s)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Func(T1,T2) must say if these elements matches
|
||||
template <typename T1, typename T2, typename Func>
|
||||
int find_pos(const std::vector<T1> & c, const T2 &s, const Func &f)
|
||||
{
|
||||
for(size_t i=0; i < c.size(); ++i)
|
||||
if(f(c[i],s))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//returns iterator to the given element if present in container, end() if not
|
||||
template <typename Container, typename Item>
|
||||
typename Container::iterator find(Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i);
|
||||
}
|
||||
|
||||
//returns const iterator to the given element if present in container, end() if not
|
||||
template <typename Container, typename Item>
|
||||
typename Container::const_iterator find(const Container & c, const Item &i)
|
||||
{
|
||||
return std::find(c.begin(),c.end(),i);
|
||||
}
|
||||
|
||||
//removes element i from container c, returns false if c does not contain i
|
||||
template <typename Container, typename Item>
|
||||
typename Container::size_type operator-=(Container &c, const Item &i)
|
||||
{
|
||||
typename Container::iterator itr = find(c,i);
|
||||
if(itr == c.end())
|
||||
return false;
|
||||
c.erase(itr);
|
||||
return true;
|
||||
}
|
||||
|
||||
//assigns greater of (a, b) to a and returns maximum of (a, b)
|
||||
template <typename t1, typename t2>
|
||||
t1 &amax(t1 &a, const t2 &b)
|
||||
{
|
||||
if(a >= b)
|
||||
return a;
|
||||
else
|
||||
{
|
||||
a = b;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
//assigns smaller of (a, b) to a and returns minimum of (a, b)
|
||||
template <typename t1, typename t2>
|
||||
t1 &amin(t1 &a, const t2 &b)
|
||||
{
|
||||
if(a <= b)
|
||||
return a;
|
||||
else
|
||||
{
|
||||
a = b;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
//makes a to fit the range <b, c>
|
||||
template <typename t1, typename t2, typename t3>
|
||||
t1 &abetween(t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
amax(a,b);
|
||||
amin(a,c);
|
||||
return a;
|
||||
}
|
||||
|
||||
//checks if a is between b and c
|
||||
template <typename t1, typename t2, typename t3>
|
||||
bool isbetween(const t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
return a > b && a < c;
|
||||
}
|
||||
|
||||
//checks if a is within b and c
|
||||
template <typename t1, typename t2, typename t3>
|
||||
bool iswithin(const t1 &a, const t2 &b, const t3 &c)
|
||||
{
|
||||
return a >= b && a <= c;
|
||||
}
|
||||
|
||||
template <typename t1, typename t2>
|
||||
struct assigner
|
||||
{
|
||||
public:
|
||||
t1 &op1;
|
||||
t2 op2;
|
||||
assigner(t1 &a1, const t2 & a2)
|
||||
:op1(a1), op2(a2)
|
||||
{}
|
||||
void operator()()
|
||||
{
|
||||
op1 = op2;
|
||||
}
|
||||
};
|
||||
|
||||
// Assigns value a2 to a1. The point of time of the real operation can be controlled
|
||||
// with the () operator.
|
||||
template <typename t1, typename t2>
|
||||
assigner<t1,t2> assigno(t1 &a1, const t2 &a2)
|
||||
{
|
||||
return assigner<t1,t2>(a1,a2);
|
||||
}
|
||||
|
||||
//deleted pointer and sets it to NULL
|
||||
template <typename T>
|
||||
void clear_pointer(T* &ptr)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = NULL;
|
||||
}
|
||||
}
|
||||
using vstd::operator-=;
|
||||
|
||||
// can be used for counting arrays
|
||||
template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N];
|
||||
#define ARRAY_COUNT(arr) (sizeof(_ArrayCountObj(arr)))
|
||||
|
||||
//for explicit overrides
|
||||
#ifdef _MSC_VER
|
||||
#define OVERRIDE override
|
||||
#else
|
||||
#define OVERRIDE //is there any working counterpart?
|
||||
#endif
|
||||
|
||||
//XXX pls dont - 'debug macros' are usually more trouble than it's worth
|
||||
#define HANDLE_EXCEPTION \
|
||||
catch (const std::exception& e) { \
|
||||
tlog1 << e.what() << std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::exception * e) \
|
||||
{ \
|
||||
tlog1 << e->what()<< std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::string& e) { \
|
||||
tlog1 << e << std::endl; \
|
||||
throw; \
|
||||
}
|
||||
|
||||
#define HANDLE_EXCEPTIONC(COMMAND) \
|
||||
catch (const std::exception& e) { \
|
||||
COMMAND; \
|
||||
tlog1 << e.what() << std::endl; \
|
||||
throw; \
|
||||
} \
|
||||
catch (const std::string &e) \
|
||||
{ \
|
||||
COMMAND; \
|
||||
tlog1 << e << std::endl; \
|
||||
throw; \
|
||||
}
|
||||
|
||||
|
||||
#include "../lib/CLogger.h"
|
||||
Reference in New Issue
Block a user