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

* blocked map scrolling where dialog window is opened

* it's possible in battles to check remeaining HP of neutral stacks
* function in CGameInterface called when spell is casted. Support for the Magic Arrow from engine side.
* heroes can regain mana
* support for mistycisim and intelligence skills
* fixed leak with creating frameratekeeper every turn
* minor improvements
This commit is contained in:
Michał W. Urbańczyk 2008-10-18 11:41:24 +00:00
parent 20a6e05718
commit 9d099e8c54
17 changed files with 257 additions and 108 deletions

View File

@ -26,6 +26,7 @@
#include <boost/thread.hpp>
#include "map.h"
#include "client/CSpellWindow.h"
#include "lib/CondSh.h"
#pragma warning (disable : 4355)
extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX; //fonts
@ -1201,7 +1202,7 @@ void CAdvMapInt::update()
}
++heroAnim;
if(animValHitCount % 4)
if((animValHitCount % 4) && !LOCPLINT->showingDialog->get())
{
if(scrollingLeft)
{

View File

@ -1710,8 +1710,8 @@ void CBattleHex::clickRight(boost::logic::tribool down)
pom->defenseBonus = h->primSkills[1];
pom->luck = h->getCurrentLuck();
pom->morale = h->getCurrentMorale();
pom->currentHealth = myst.firstHPleft;
}
pom->currentHealth = myst.firstHPleft;
(new CCreInfoWindow(myst.creature->idNumber,0,myst.amount,pom,boost::function<void()>(),boost::function<void()>(),NULL))
->activate();
}

View File

@ -22,6 +22,7 @@ class CArmedInstance;
struct BattleResult;
struct BattleAttack;
struct BattleStackAttacked;
struct SpellCasted;
class CObstacle
{
int ID;
@ -74,6 +75,7 @@ public:
virtual void battleEnd(BattleResult *br){};
virtual void battleNewRound(int round){}; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
virtual void battleStackMoved(int ID, int dest){};
virtual void battleSpellCasted(SpellCasted *sc){};
virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
};

View File

@ -606,6 +606,15 @@ void CGameState::applyNL(IPack * pack)
applyNL(&br->bsa);
break;
}
case 3009:
{
SpellCasted *sc = static_cast<SpellCasted*>(pack);
CGHeroInstance *h = (sc->side) ? getHero(curB->hero2) : getHero(curB->hero1);
if(h)
h->mana -= VLC->spellh->spells[sc->id].costs[sc->skill];
//TODO: counter
break;
}
}
}
void CGameState::apply(IPack * pack)

12
CMT.cpp
View File

@ -140,13 +140,9 @@ int main(int argc, char** argv)
CGI->dobjinfo = VLC->dobjinfo;
CGI->buildh = VLC->buildh;
tlog0<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
//cgi->curh->initCursor();
//cgi->curh->showGraphicCursor();
pomtime.getDif();
cgi->curh = new CCursorHandler;
cgi->curh->initCursor();
//cgi->screenh = new CScreenHandler;
//cgi->screenh->initScreen();
tlog0<<"\tScreen handler: "<<pomtime.getDif()<<std::endl;
CAbilityHandler * abilh = new CAbilityHandler;
abilh->loadAbilities();
@ -187,7 +183,7 @@ int main(int argc, char** argv)
cgi->pathf = new CPathfinder();
tlog0<<"\tPathfinder: "<<pomtime.getDif()<<std::endl;
tlog0<<"Handlers initialization (together): "<<tmh.getDif()<<std::endl;
std::ofstream lll("client_log.txt");
std::ofstream logs("client_log.txt");
CConnection *c=NULL;
//wait until server is ready
@ -206,7 +202,7 @@ int main(int argc, char** argv)
try
{
tlog0 << "Establishing connection...\n";
c = new CConnection("127.0.0.1",portc,NAME,lll);
c = new CConnection("127.0.0.1",portc,NAME,logs);
}
catch(...)
{
@ -281,10 +277,10 @@ void processCommand(const std::string &message)
txth->init(std::string(DATA_DIR "Data" PATHSEPARATOR "H3bitmap.lod"),"data");
tlog0<<"done.\nScanning .lod file\n";
int curp=0;
std::string pattern = ".TXT";
std::string pattern = ".TXT", pom;
for(int i=0;i<txth->entries.size(); i++)
{
std::string pom = txth->entries[i].nameStr;
pom = txth->entries[i].nameStr;
if(boost::algorithm::find_last(pom,pattern))
{
txth->extractFile(std::string("Extracted_txts\\")+pom,pom);

View File

@ -961,6 +961,11 @@ CPlayerInterface::CPlayerInterface(int Player, int serial)
pim = new boost::recursive_mutex;
showingDialog = new CondSh<bool>(false);
heroMoveSpeed = 2;
//initializing framerate keeper
mainFPSmng = new FPSmanager;
SDL_initFramerate(mainFPSmng);
SDL_setFramerate(mainFPSmng, 48);
//framerate keeper initialized
}
CPlayerInterface::~CPlayerInterface()
{
@ -972,12 +977,6 @@ void CPlayerInterface::init(ICallback * CB)
cb = dynamic_cast<CCallback*>(CB);
adventureInt = new CAdvMapInt(playerID);
castleInt = NULL;
std::vector <const CGHeroInstance *> hh = cb->getHeroesInfo(false);
for(int i=0;i<hh.size();i++)
{
SDL_Surface * pom = infoWin(hh[i]);
graphics->heroWins.insert(std::pair<int,SDL_Surface*>(hh[i]->subID,pom));
}
std::vector<const CGTownInstance*> tt = cb->getTownsInfo(false);
for(int i=0;i<tt.size();i++)
{
@ -989,19 +988,25 @@ void CPlayerInterface::yourTurn()
{
LOCPLINT = this;
makingTurn = true;
for(std::map<int,SDL_Surface*>::iterator i=graphics->heroWins.begin(); i!=graphics->heroWins.end();i++) //redraw hero infoboxes
SDL_FreeSurface(i->second);
graphics->heroWins.clear();
std::vector <const CGHeroInstance *> hh = cb->getHeroesInfo(false);
for(int i=0;i<hh.size();i++)
{
SDL_Surface * pom = infoWin(hh[i]);
graphics->heroWins.insert(std::pair<int,SDL_Surface*>(hh[i]->subID,pom));
}
adventureInt->infoBar.newDay(cb->getDate(1));
if(adventureInt->heroList.items.size())
adventureInt->select(adventureInt->heroList.items[0].first);
else
adventureInt->select(adventureInt->townList.items[0]);
adventureInt->activate();
//show rest of things
//initializing framerate keeper
mainFPSmng = new FPSmanager;
SDL_initFramerate(mainFPSmng);
SDL_setFramerate(mainFPSmng, 48);
//framerate keeper initialized
timeHandler th;
th.getDif();
for(;makingTurn;) // main loop
@ -2046,7 +2051,7 @@ void CPlayerInterface::battleStart(CCreatureSet *army1, CCreatureSet *army2, int
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
curint->deactivate();
curint = new CBattleInterface(army1,army2,hero1,hero2);
curint = battleInt = new CBattleInterface(army1,army2,hero1,hero2);
curint->activate();
LOCPLINT->objsToBlit.push_back(dynamic_cast<IShowable*>(curint));
}
@ -2058,20 +2063,20 @@ void CPlayerInterface::battlefieldPrepared(int battlefieldType, std::vector<CObs
void CPlayerInterface::battleNewRound(int round) //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
dynamic_cast<CBattleInterface*>(curint)->newRound(round);
battleInt->newRound(round);
}
void CPlayerInterface::actionStarted(const BattleAction* action)
{
curAction = action;
if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))
&& static_cast<CBattleInterface*>(curint)->creAnims[action->stackNumber]->framesInGroup(20)
&& battleInt->creAnims[action->stackNumber]->framesInGroup(20)
)
{
static_cast<CBattleInterface*>(curint)->creAnims[action->stackNumber]->setType(20);
battleInt->creAnims[action->stackNumber]->setType(20);
if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //deactivating interface when move is started
{
static_cast<CBattleInterface*>(curint)->deactivate();
battleInt->deactivate();
}
}
}
@ -2081,13 +2086,13 @@ void CPlayerInterface::actionFinished(const BattleAction* action)
curAction = NULL;
if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //activating interface when move is finished
{
static_cast<CBattleInterface*>(curint)->activate();
battleInt->activate();
}
}
BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
{
CBattleInterface *b = dynamic_cast<CBattleInterface*>(curint);
CBattleInterface *b = battleInt;
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
b->stackActivated(stackID);
@ -2117,7 +2122,8 @@ void CPlayerInterface::battleResultQuited()
boost::unique_lock<boost::recursive_mutex> un(*pim);
((CBattleInterface*)curint)->resWindow->deactivate();
objsToBlit -= curint;
delete curint;
delete battleInt;
battleInt = 0;
curint = adventureInt;
adventureInt->activate();
LOCPLINT->showingDialog->setn(false);
@ -2126,30 +2132,28 @@ void CPlayerInterface::battleResultQuited()
void CPlayerInterface::battleStackMoved(int ID, int dest)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest, dest==curAction->destinationTile);
battleInt->stackMoved(ID, dest, dest==curAction->destinationTile);
}
void CPlayerInterface::battleSpellCasted(SpellCasted *sc)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
}
void CPlayerInterface::battleStackAttacked(BattleStackAttacked * bsa)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
}
void CPlayerInterface::battleAttack(BattleAttack *ba)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(ba->shot())
dynamic_cast<CBattleInterface*>(curint)->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked));
battleInt->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked));
else
dynamic_cast<CBattleInterface*>(curint)->stackAttacking( ba->stackAttacking, ba->counter() ? curAction->destinationTile : curAction->additionalInfo );
battleInt->stackAttacking( ba->stackAttacking, ba->counter() ? curAction->destinationTile : curAction->additionalInfo );
if(ba->killed())
dynamic_cast<CBattleInterface*>(curint)->stackKilled(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot());
battleInt->stackKilled(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot());
else
dynamic_cast<CBattleInterface*>(curint)->stackIsAttacked(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot());
battleInt->stackIsAttacked(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot());
}
//void CPlayerInterface::battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting)
//{
// dynamic_cast<CBattleInterface*>(curint)->stackKilled(ID, dmg, killed, IDby, byShooting);
//}
//void CPlayerInterface::battleStackIsShooting(int ID, int dest)
//{
// dynamic_cast<CBattleInterface*>(curint)->stackIsShooting(ID, dest);
//}
void CPlayerInterface::showComp(SComponent comp)
{
boost::unique_lock<boost::recursive_mutex> un(*pim);

View File

@ -15,6 +15,7 @@ class CDefEssential;
class CGHeroInstance;
class CAdvMapInt;
class CCastleInterface;
class CBattleInterface;
class CStack;
class SComponent;
class CCreature;
@ -326,6 +327,7 @@ public:
CMainInterface *curint;
CAdvMapInt * adventureInt;
CCastleInterface * castleInt;
CBattleInterface * battleInt;
FPSmanager * mainFPSmng;
IStatusBar *statusbar;
//to commucate with engine
@ -369,6 +371,8 @@ public:
void battleResultQuited();
void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
void battleStackMoved(int ID, int dest);
void battleSpellCasted(SpellCasted *sc);
void battleStackAttacked(BattleStackAttacked * bsa);
void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
@ -378,7 +382,7 @@ public:
void showComp(SComponent comp);
void openTownWindow(const CGTownInstance * town); //shows townscreen
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
SDL_Surface * infoWin(const CGObjectInstance * specific); //specific=0 => draws info about selected town/hero //TODO - gdy sie dorobi sensowna hierarchie klas ins. to wywalic tego brzydkiego void*
SDL_Surface * infoWin(const CGObjectInstance * specific); //specific=0 => draws info about selected town/hero
void handleEvent(SDL_Event * sEvent);
void handleKeyDown(SDL_Event *sEvent);
void handleKeyUp(SDL_Event *sEvent);

View File

@ -525,6 +525,17 @@ void CClient::process(int what)
gs->apply(&br);
break;
}
case 3005:
{
BattleStackAttacked bsa;
*serv >> bsa;
gs->apply(&bsa);
if(playerint.find(gs->curB->side1) != playerint.end())
playerint[gs->curB->side1]->battleStackAttacked(&bsa);
if(playerint.find(gs->curB->side2) != playerint.end())
playerint[gs->curB->side2]->battleStackAttacked(&bsa);
break;
}
case 3006:
{
BattleAttack ba;
@ -544,7 +555,7 @@ void CClient::process(int what)
case 3007:
{
*serv >> curbaction;
tlog5 << "Action started. ID: " << curbaction.actionType << ". Destination: "<< curbaction.destinationTile <<std::endl;
tlog5 << "Action started. ID: " << (int)curbaction.actionType << ". Destination: "<< curbaction.destinationTile <<std::endl;
if(playerint.find(gs->curB->side1) != playerint.end())
playerint[gs->curB->side1]->actionStarted(&curbaction);
if(playerint.find(gs->curB->side2) != playerint.end())
@ -565,6 +576,19 @@ void CClient::process(int what)
playerint[gs->curB->side2]->actionFinished(&curbaction);
break;
}
case 3009:
{
tlog5 << "Spell casted!\n";
SpellCasted sc;
*serv >> sc;
gs->apply(&sc);
//todo - apply
if(playerint.find(gs->curB->side1) != playerint.end())
playerint[gs->curB->side1]->battleSpellCasted(&sc);
if(playerint.find(gs->curB->side2) != playerint.end())
playerint[gs->curB->side2]->battleSpellCasted(&sc);
break;
}
case 9999:
break;
default:

View File

@ -24,18 +24,17 @@ using namespace CSDL_Ext;
Graphics * graphics = NULL;
SDL_Surface * Graphics::drawPrimarySkill(const CGHeroInstance *curh, SDL_Surface *ret, int from, int to)
{
char * buf = new char[10];
char buf[10];
for (int i=from;i<to;i++)
{
SDL_itoa(curh->getPrimSkillLevel(i),buf,10);
printAtMiddle(buf,84+28*i,68,GEOR13,zwykly,ret);
}
delete[] buf;
return ret;
}
SDL_Surface * Graphics::drawHeroInfoWin(const CGHeroInstance * curh)
{
char * buf = new char[10];
char buf[10];
blueToPlayersAdv(hInfo,curh->tempOwner);
SDL_Surface * ret = SDL_DisplayFormat(hInfo);
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
@ -50,14 +49,13 @@ SDL_Surface * Graphics::drawHeroInfoWin(const CGHeroInstance * curh)
blitAt(graphics->portraitLarge[curh->portrait],11,12,ret);
SDL_itoa(curh->mana,buf,10);
printAtMiddle(buf,166,109,GEORM,zwykly,ret); //mana points
delete[] buf;
blitAt(morale22->ourImages[curh->getCurrentMorale()+3].bitmap,14,84,ret);
blitAt(luck22->ourImages[curh->getCurrentLuck()+3].bitmap,14,101,ret);
return ret;
}
SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh)
{
char * buf = new char[10];
char buf[10];
blueToPlayersAdv(tInfo,curh->tempOwner);
SDL_Surface * ret = SDL_DisplayFormat(tInfo);
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
@ -87,7 +85,6 @@ SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh)
if(curh->garrisonHero)
blitAt(graphics->heroInGarrison,158,87,ret);
blitAt(bigTownPic->ourImages[pom].bitmap,13,13,ret);
delete[] buf;
return ret;
}

View File

@ -65,6 +65,7 @@
ShowProgress="0"
AdditionalLibraryDirectories="G:\vcmt\repa\libs"
GenerateDebugInformation="true"
OptimizeReferences="1"
TargetMachine="1"
Profile="true"
/>

View File

@ -235,6 +235,9 @@ extern DLL_EXPORT CLogger<5> tlog5; //gray - minor log info
{ \
tlog1 << e->what()<< std::endl; \
delete e; \
} \
catch (const std::string& e) { \
tlog1 << e << std::endl; \
}
#define HANDLE_EXCEPTIONC(COMMAND) \

View File

@ -27,6 +27,7 @@ void CDefObjInfoHandler::load()
std::istringstream inp(bitmaph->getTextFile("ZOBJCTS.TXT"));
int objNumber;
inp>>objNumber;
std::string mapStr;
for(int hh=0; hh<objNumber; ++hh)
{
CGDefInfo* nobj = new CGDefInfo();
@ -41,7 +42,6 @@ void CDefObjInfoHandler::load()
nobj->blockMap[o] = 0xff;
nobj->visitMap[o] = 0x00;
}
std::string mapStr;
inp>>mapStr;
std::reverse(mapStr.begin(), mapStr.end());
for(int v=0; v<mapStr.size(); ++v)

View File

@ -15,6 +15,7 @@ void CObjectHandler::loadObjects()
{
VLC->objh = this;
int ID=0;
tlog5 << "\t\tReading OBJNAMES \n";
std::string buf = bitmaph->getTextFile("OBJNAMES.TXT");
int it=0;
while (it<buf.length()-1)
@ -26,6 +27,7 @@ void CObjectHandler::loadObjects()
names.push_back(nobj);
}
tlog5 << "\t\tReading ADVEVENT \n";
buf = bitmaph->getTextFile("ADVEVENT.TXT");
it=0;
std::string temp;
@ -38,6 +40,7 @@ void CObjectHandler::loadObjects()
advobtxt.push_back(temp);
}
tlog5 << "\t\tReading XTRAINFO \n";
buf = bitmaph->getTextFile("XTRAINFO.TXT");
it=0;
while (it<buf.length()-1)
@ -46,6 +49,7 @@ void CObjectHandler::loadObjects()
xtrainfo.push_back(temp);
}
tlog5 << "\t\tReading MINENAME \n";
buf = bitmaph->getTextFile("MINENAME.TXT");
it=0;
while (it<buf.length()-1)
@ -54,6 +58,7 @@ void CObjectHandler::loadObjects()
mines.push_back(std::pair<std::string,std::string>(temp,""));
}
tlog5 << "\t\tReading MINEEVNT \n";
buf = bitmaph->getTextFile("MINEEVNT.TXT");
it=0;
int i=0;
@ -64,6 +69,7 @@ void CObjectHandler::loadObjects()
mines[i++].second = temp;
}
tlog5 << "\t\tReading RESTYPES \n";
buf = bitmaph->getTextFile("RESTYPES.TXT");
it=0;
while (it<buf.length()-1)
@ -72,6 +78,7 @@ void CObjectHandler::loadObjects()
restypes.push_back(temp);
}
tlog5 << "\t\tReading cregens \n";
cregens.resize(110); //TODO: hardcoded value - change
for(int i=0; i<cregens.size();i++)
cregens[i]=-1;
@ -84,6 +91,8 @@ void CObjectHandler::loadObjects()
}
ifs.close();
ifs.clear();
tlog5 << "\t\tReading ZCRGN1 \n";
buf = bitmaph->getTextFile("ZCRGN1.TXT");
it=0;
while (it<buf.length()-1)
@ -91,7 +100,7 @@ void CObjectHandler::loadObjects()
loadToIt(temp,buf,it,3);
creGens.push_back(temp);
}
tlog5 << "\t\tDone loading objects!\n";
}
bool CGObjectInstance::isHero() const
@ -252,13 +261,25 @@ int CGHeroInstance::getSightDistance() const //returns sight distance of this he
{
return 6 + getSecSkillLevel(3); //default + scouting
}
void CGHeroInstance::setPosition(int3 Pos, bool h3m) //as above, but sets position
int CGHeroInstance::manaLimit() const
{
if (h3m)
pos = Pos;
else
pos = convertPosition(Pos,true);
double modifier = 1.0;
switch(getSecSkillLevel(24)) //intelligence level
{
case 1: modifier+=0.25; break;
case 2: modifier+=0.5; break;
case 3: modifier+=1.0; break;
}
return 10*primSkills[3]*modifier;
}
//void CGHeroInstance::setPosition(int3 Pos, bool h3m) //as above, but sets position
//{
// if (h3m)
// pos = Pos;
// else
// pos = convertPosition(Pos,true);
//}
bool CGHeroInstance::canWalkOnSea() const
{

View File

@ -120,7 +120,8 @@ public:
static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest
int3 getPosition(bool h3m) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
int getSightDistance() const; //returns sight distance of this hero
void setPosition(int3 Pos, bool h3m); //as above, but sets position
int manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
//void setPosition(int3 Pos, bool h3m); //as above, but sets position
bool canWalkOnSea() const;
int getCurrentLuck() const;

View File

@ -416,7 +416,8 @@ struct BattleStackAttacked : public CPack<BattleStackAttacked>//3005
{
ui32 stackAttacked;
ui32 newAmount, newHP, killedAmount, damageAmount;
ui8 flags; //1 - is stack killed
ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown
ui32 effect; //set only if flag 2 is present
BattleStackAttacked(){flags = 0; type = 3005;};
@ -424,9 +425,13 @@ struct BattleStackAttacked : public CPack<BattleStackAttacked>//3005
{
return flags & 1;
}
bool isEffect() //if target stack was killed
{
return flags & 2;
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & stackAttacked & newAmount & newHP & flags & killedAmount & damageAmount;
h & stackAttacked & newAmount & newHP & flags & killedAmount & damageAmount & effect;
}
};
@ -468,6 +473,19 @@ struct StartAction : public CPack<StartAction>//3007
}
};
struct SpellCasted : public CPack<SpellCasted>//3009
{
ui8 side; //which hero casted spell: 0 - attacker, 1 - defender
ui32 id;
ui8 skill;
ui16 tile; //destination tile (may not be set in some global/mass spells
SpellCasted(){type = 3009;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & side & id & skill & tile;
}
};
struct ShowInInfobox : public CPack<ShowInInfobox> //107
{
ShowInInfobox(){type = 107;};

View File

@ -349,36 +349,39 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
delete battleResult.data;
}
void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, CStack *def)
{
bsa.killedAmount = bsa.damageAmount / def->creature->hitPoints;
unsigned damageFirst = bsa.damageAmount % def->creature->hitPoints;
if( def->firstHPleft <= damageFirst )
{
bsa.killedAmount++;
bsa.newHP = def->firstHPleft + def->creature->hitPoints - damageFirst;
}
else
{
bsa.newHP = def->firstHPleft - damageFirst;
}
if(def->amount <= bsa.killedAmount) //stack killed
{
bsa.newAmount = 0;
bsa.flags |= 1;
bsa.killedAmount = def->amount; //we cannot kill more creatures than we have
}
else
{
bsa.newAmount = def->amount - bsa.killedAmount;
}
}
void CGameHandler::prepareAttack(BattleAttack &bat, CStack *att, CStack *def)
{
bat.stackAttacking = att->ID;
bat.bsa.stackAttacked = def->ID;
bat.bsa.damageAmount = BattleInfo::calculateDmg(att, def, gs->getHero(att->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), gs->getHero(def->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), bat.shot());//counting dealt damage
//applying damages
bat.bsa.killedAmount = bat.bsa.damageAmount / def->creature->hitPoints;
unsigned damageFirst = bat.bsa.damageAmount % def->creature->hitPoints;
if( def->firstHPleft <= damageFirst )
{
bat.bsa.killedAmount++;
bat.bsa.newHP = def->firstHPleft + def->creature->hitPoints - damageFirst;
}
else
{
bat.bsa.newHP = def->firstHPleft - damageFirst;
}
if(def->amount <= bat.bsa.killedAmount) //stack killed
{
bat.bsa.newAmount = 0;
bat.bsa.flags |= 1;
bat.bsa.killedAmount = def->amount; //we cannot kill more creatures than we have
}
else
{
bat.bsa.newAmount = def->amount - bat.bsa.killedAmount;
}
prepareAttacked(bat.bsa,def);
}
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
{
@ -427,12 +430,13 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
tmh.result = 0;
tmh.movePoints = h->movement;
if((h->getOwner() != gs->currentPlayer) || //not turn of that hero
(distance(start,end)>=1.5) || //tiles are not neighouring
(h->movement < cost) || //lack of movement points
(t.tertype == rock) || //rock
(!h->canWalkOnSea() && t.tertype == water) ||
(t.blocked && !t.visitable) ) //tile is blocked andnot visitable
if((h->getOwner() != gs->currentPlayer) //not turn of that hero
|| (distance(start,end)>=1.5) //tiles are not neighouring
|| (h->movement < cost) //lack of movement points
|| (t.tertype == rock) //rock
|| (!h->canWalkOnSea() && t.tertype == water)
|| (t.blocked && !t.visitable) //tile is blocked andnot visitable
)
goto fail;
@ -1008,8 +1012,19 @@ upgend:
case 1: //hero casts spell
{
CGHeroInstance *h = (ba.side) ? gs->getHero(gs->curB->hero2) : gs->getHero(gs->curB->hero1);
if(!h)
{
tlog2 << "Wrong caster!\n";
goto customactionend;
}
if(ba.additionalInfo >= VLC->spellh->spells.size())
{
tlog2 << "Wrong spell id (" << ba.additionalInfo << ")!\n";
goto customactionend;
}
CSpell *s = &VLC->spellh->spells[ba.additionalInfo];
int skill = 0;
int skill = 0; //skill level
if(s->fire)
skill = std::max(skill,h->getSecSkillLevel(14));
@ -1020,15 +1035,66 @@ upgend:
if(s->earth)
skill = std::max(skill,h->getSecSkillLevel(17));
if( !vstd::contains(h->spells,ba.additionalInfo) //hero doesn't know this spell
|| (h->mana < s->costs[skill]) //not enough mana
//TODO: skill level may be different on special terrain
if( // !vstd::contains(h->spells,ba.additionalInfo) //hero doesn't know this spell
/*||*/ (h->mana < s->costs[skill]) //not enough mana
|| (ba.additionalInfo < 10) //it's adventure spell (not combat)
|| 0 )//TODO: hero has already casted a spell in this round
{
tlog2 << "Spell cannot be casted!\n";
goto customactionend;
}
sendAndApply(&StartAction(ba)); //start spell casting
//TODO: spell efects
//TODO: check resistances
SpellCasted sc;
sc.side = ba.side;
sc.id = ba.additionalInfo;
sc.skill = skill;
sc.tile = ba.destinationTile;
sendAndApply(&sc);
switch(ba.additionalInfo) //spell id
{
case 15://magic arrow
{
CStack * attacked = gs->curB->getStackT(ba.destinationTile);
if(!attacked) break;
BattleStackAttacked bsa;
bsa.flags |= 2;
bsa.effect = 64;
bsa.damageAmount = h->primSkills[2] * 10; //TODO: use skill level
bsa.stackAttacked = attacked->ID;
prepareAttacked(bsa,attacked);
sendAndApply(&bsa);
break;
}
case 53: //haste
{
break;
}
}
//TODO: spells to support possibly soon (list by Zamolxis):
/*- Magic Arrow
- Haste
- Bless
- Bloodlust
- Curse
- Dispel
- Shield
- Slow
- Stone Skin
- Lightning Bolt
- Ice Bolt
- Precision
- Blind
- Fire Wall
- Weakness
- Death Ripple */
sendDataToClients(ui16(3008)); //end casting
break;
}
@ -1198,15 +1264,15 @@ void CGameHandler::newTurn()
for(int j=0;j<RESOURCE_QUANTITY;j++)
r.res[j] = i->second.resources[j];
for (unsigned j=0;j<(*i).second.heroes.size();j++) //handle heroes
BOOST_FOREACH(CGHeroInstance *h, (*i).second.heroes)
{
NewTurn::Hero h;
h.id = (*i).second.heroes[j]->id;
h.move = valMovePoints((*i).second.heroes[j], true); //TODO: check if hero is really on the land
h.mana = (*i).second.heroes[j]->mana;
n.heroes.insert(h);
//handle estates
switch((*i).second.heroes[j]->getSecSkillLevel(13))
NewTurn::Hero hth;
hth.id = h->id;
hth.move = valMovePoints(h, true); //TODO: check if hero is really on the land
hth.mana = std::min(h->mana+1+h->getSecSkillLevel(8), h->manaLimit()); //hero regains 1 mana point + mysticism lvel
n.heroes.insert(hth);
switch(h->getSecSkillLevel(13)) //handle estates - give gols
{
case 1: //basic
r.res[6] += 125;
@ -1263,10 +1329,10 @@ void CGameHandler::run()
ui8 quantity, pom;
//ui32 seed;
(*cc) << gs->scenarioOps->mapname << gs->map->checksum << gs->seed;
(*cc) >> quantity;
(*cc) >> quantity; //how many players will be handled at that client
for(int i=0;i<quantity;i++)
{
(*cc) >> pom;
(*cc) >> pom; //read player color
gsm.lock();
connections[pom] = cc;
gsm.unlock();

View File

@ -13,6 +13,7 @@ class CCPPObjectScript;
class CScriptCallback;
struct BattleResult;
struct BattleAttack;
struct BattleStackAttacked;
template <typename T> struct CPack;
template <typename T> struct Query;
class CGHeroInstance;
@ -58,6 +59,7 @@ class CGameHandler
void moveStack(int stack, int dest);
void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void prepareAttack(BattleAttack &bat, CStack *att, CStack *def); //if last parameter is true, attack is by shooting, if false it's a melee attack
void prepareAttacked(BattleStackAttacked &bsa, CStack *def);
void checkForBattleEnd( std::vector<CStack*> &stacks );
void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 );