1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

* compiles under MSVC (haven't I broken anything on gcc?)

* half-done support for battles
This commit is contained in:
Michał W. Urbańczyk 2008-08-04 15:56:36 +00:00
parent 038dd90517
commit a15ffb06e6
28 changed files with 899 additions and 308 deletions

View File

@ -22,6 +22,7 @@
#include "CHeroWindow.h"
#include "client/Graphics.h"
#include "hch/CObjectHandler.h"
#include <boost/thread.hpp>
#include "map.h"
#pragma warning (disable : 4355)
extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX; //fonts
@ -283,7 +284,9 @@ void CTerrainRect::clickLeft(tribool down)
if ( (currentPath->endPos()) == mp)
{ //move
CPath sended(*currentPath); //temporary path - engine will operate on it
LOCPLINT->pim->unlock();
mres = LOCPLINT->cb->moveHero( ((const CGHeroInstance*)LOCPLINT->adventureInt->selection.selected)->type->ID,&sended,1,0);
LOCPLINT->pim->lock();
if(!mres)
{
delete currentPath;

View File

@ -14,7 +14,7 @@
#include "client/Graphics.h"
#include <queue>
#include <sstream>
#include "lib/CondSh.h"
#ifndef __GNUC__
const double M_PI = 3.14159265358979323846;
#else
@ -30,6 +30,7 @@ SDL_Surface * CBattleInterface::cellBorder, * CBattleInterface::cellShade;
CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2)
: printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), givenCommand(NULL), attackingInfo(NULL), myTurn(false)
{
givenCommand = new CondSh<BattleAction *>(NULL);
//initializing armies
this->army1 = army1;
this->army2 = army2;
@ -169,6 +170,7 @@ CBattleInterface::~CBattleInterface()
delete bConsoleUp;
delete bConsoleDown;
delete console;
delete givenCommand;
delete attackingHero;
delete defendingHero;
@ -391,9 +393,7 @@ void CBattleInterface::bSurrenderf()
void CBattleInterface::bFleef()
{
BattleAction * ba = new BattleAction;
ba->actionType = 4;
givenCommand = ba;
giveCommand(4,0,0);
}
void CBattleInterface::bAutofightf()
@ -410,10 +410,7 @@ void CBattleInterface::bWaitf()
void CBattleInterface::bDefencef()
{
BattleAction * ba = new BattleAction;
ba->actionType = 3;
ba->stackNumber = activeStack;
givenCommand = ba;
giveCommand(3,0,activeStack);
}
void CBattleInterface::bConsoleUpf()
@ -482,7 +479,7 @@ void CBattleInterface::stackKilled(int ID, int dmg, int killed, int IDby, bool b
void CBattleInterface::stackActivated(int number)
{
givenCommand = NULL;
//givenCommand = NULL;
activeStack = number;
shadedHexes = LOCPLINT->cb->battleGetAvailableHexes(number);
myTurn = true;
@ -791,6 +788,16 @@ void CBattleInterface::newRound(int number)
console->addText(CGI->generaltexth->allTexts[412]);
}
void CBattleInterface::giveCommand(ui8 action, ui16 tile, ui32 stack)
{
BattleAction * ba = new BattleAction(); //to be deleted by engine
ba->actionType = action;
ba->destinationTile = tile;
ba->stackNumber = stack;
givenCommand->setn(ba);
myTurn = false;
}
void CBattleInterface::hexLclicked(int whichOne)
{
if((whichOne%17)!=0 && (whichOne%17)!=16) //if player is trying to attack enemey unit or move creature stack
@ -802,28 +809,16 @@ void CBattleInterface::hexLclicked(int whichOne)
//LOCPLINT->cb->battleGetCreature();
if(atCre==-1) //normal move action
{
BattleAction * ba = new BattleAction(); //to be deleted by engine
ba->actionType = 2;
ba->destinationTile = whichOne;
ba->stackNumber = activeStack;
givenCommand = ba;
giveCommand(2,whichOne,activeStack);
}
else if(LOCPLINT->cb->battleGetStackByID(atCre)->owner != attackingHeroInstance->tempOwner
&& LOCPLINT->cb->battleCanShoot(activeStack, whichOne)) //shooting
{
BattleAction * ba = new BattleAction(); //to be deleted by engine
ba->actionType = 7;
ba->destinationTile = whichOne;
ba->stackNumber = activeStack;
givenCommand = ba;
giveCommand(7,whichOne,activeStack);
}
else if(LOCPLINT->cb->battleGetStackByID(atCre)->owner != attackingHeroInstance->tempOwner) //attacking
{
BattleAction * ba = new BattleAction(); //to be deleted by engine
ba->actionType = 6;
ba->destinationTile = whichOne;
ba->stackNumber = activeStack;
givenCommand = ba;
giveCommand(6,whichOne,activeStack);
}
}
}

View File

@ -9,6 +9,7 @@ class CDefHandler;
class CStack;
class CCallback;
class AdventureMapButton;
template <typename T> struct CondSh;
class CBattleHero : public IShowable, public CIntObject
{
@ -112,7 +113,7 @@ private:
};
std::list<SProjectileInfo> projectiles;
void projectileShowHelper(SDL_Surface * to=NULL); //prints projectiles present on the battlefield
void giveCommand(ui8 action, ui16 tile, ui32 stack);
public:
CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2); //c-tor
~CBattleInterface(); //d-tor
@ -122,7 +123,7 @@ public:
CBattleHex bfield[187]; //11 lines, 17 hexes on each
std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
static SDL_Surface * cellBorder, * cellShade;
BattleAction * givenCommand; //true if we have i.e. moved current unit
CondSh<BattleAction *> *givenCommand; //data != NULL if we have i.e. moved current unit
bool myTurn; //if true, interface is active (commands can be ordered
//button handle funcs:

View File

@ -18,6 +18,12 @@
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include "lib/NetPacks.h"
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
extern CSharedCond<std::set<IPack*> > mess;
HeroMoveDetails::HeroMoveDetails(int3 Src, int3 Dst, CGHeroInstance*Ho)

View File

@ -3,6 +3,7 @@
#include "global.h"
#include <set>
#include <vector>
#include "lib/BattleAction.h"
BOOST_TRIBOOL_THIRD_STATE(outOfRange)
using namespace boost::logic;
@ -18,21 +19,13 @@ class CGTownInstance;
class CGObjectInstance;
class CCreatureSet;
class CArmedInstance;
struct BattleResult;
class CObstacle
{
int ID;
int position;
//TODO: add some kind of the blockmap
};
struct BattleAction
{
bool side; //who made this action: false - left, true - right player
int stackNumber;//stack ID, -1 left hero, -2 right hero,
int actionType; // 0 = Cancel BattleAction 1 = Hero cast a spell 2 = Walk 3 = Defend 4 = Retreat from the battle 5 = Surrender 6 = Walk and Attack 7 = Shoot 8 = Wait 9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons)
int destinationTile;
int additionalInfo; // e.g. spell number if type is 1 || 10
};
struct StackState
{
@ -65,13 +58,13 @@ public:
virtual void garrisonChanged(const CGObjectInstance * obj){};
virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
//battle call-ins
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 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
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 actionStarted(BattleAction action){};//occurs BEFORE every action taken by any stack or by the hero
virtual void actionFinished(BattleAction action){};//occurs AFTER every action taken by any stack or by the hero
virtual BattleAction activeStack(int stackID)=0; //called when it's turn of that stack
virtual void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CArmedInstance *hero1, CArmedInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner){};
virtual void battleEnd(BattleResult *br){};
virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)=0;
virtual void battleStackAttacking(int ID, int dest)=0;
virtual void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting)=0;

View File

@ -18,14 +18,6 @@
#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
boost::rand48 ran;
class CMP_stack
{
public:
bool operator ()(const CStack* a, const CStack* b)
{
return (a->creature->speed)>(b->creature->speed);
}
} cmpst ;
CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
{
@ -135,6 +127,26 @@ void CGameState::apply(IPack * pack)
players[sr->player].resources[i] = sr->res[i];
break;
}
case 105:
{
SetPrimSkill *sr = static_cast<SetPrimSkill*>(pack);
CGHeroInstance *hero = getHero(sr->id);
if(sr->which <4)
{
if(sr->abs)
hero->primSkills[sr->which] = sr->val;
else
hero->primSkills[sr->which] += sr->val;
}
else if(sr->which == 4) //XP
{
if(sr->abs)
hero->exp = sr->val;
else
hero->exp += sr->val;
}
break;
}
case 500:
{
RemoveHero *rh = static_cast<RemoveHero*>(pack);
@ -198,6 +210,35 @@ void CGameState::apply(IPack * pack)
map->objects[p->id]->*point = p->val;
break;
}
case 3000:
{
BattleStart * bs = static_cast<BattleStart*>(pack);
curB = bs->info;
break;
}
case 3001:
{
BattleNextRound *ns = static_cast<BattleNextRound*>(pack);
curB->round = ns->round;
break;
}
case 3002:
{
BattleSetActiveStack *ns = static_cast<BattleSetActiveStack*>(pack);
curB->activeStack = ns->stack;
break;
}
case 3003:
{
BattleResult *br = static_cast<BattleResult*>(pack);
//TODO: give exp, artifacts to winner, decrease armies (casualties)
for(unsigned i=0;i<curB->stacks.size();i++)
delete curB->stacks[i];
delete curB;
curB = NULL;
}
//case 1002://set hover name
// {
// SetHoverName * shn = static_cast<SetHoverName*>(pack);
@ -228,6 +269,12 @@ int CGameState::pickHero(int owner)
}
return h;
}
CGHeroInstance *CGameState::getHero(int objid)
{
if(objid<0 || objid>=map->objects.size())
return NULL;
return static_cast<CGHeroInstance *>(map->objects[objid]);
}
std::pair<int,int> CGameState::pickObject(CGObjectInstance *obj)
{
switch(obj->ID)
@ -460,7 +507,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
{
day = 0;
seed = Seed;
ran.seed((int32_t)seed);
ran.seed((boost::int32_t)seed);
scenarioOps = si;
this->map = map;

View File

@ -47,29 +47,53 @@ public:
struct DLL_EXPORT BattleInfo
{
int side1, side2;
int round, activeStack;
int siege; // = 0 ordinary battle = 1 a siege with a Fort = 2 a siege with a Citadel = 3 a siege with a Castle
ui8 side1, side2;
si32 round, activeStack;
ui8 siege; // = 0 ordinary battle = 1 a siege with a Fort = 2 a siege with a Citadel = 3 a siege with a Castle
int3 tile; //for background and bonuses
CGHeroInstance *hero1, *hero2;
CCreatureSet * army1, * army2;
si32 hero1, hero2;
CCreatureSet army1, army2;
std::vector<CStack*> stacks;
bool stackActionPerformed; //true if current stack has been moved
template <typename Handler> void serialize(Handler &h, const int version)
{
h & side1 & side2 & round & activeStack & siege & tile & stacks & army1 & army2 & hero1 & hero2;
}
};
class DLL_EXPORT CStack
{
public:
int ID; //unique ID of stack
ui32 ID; //unique ID of stack
CCreature * creature;
int amount;
int firstHPleft; //HP of first creature in stack
int owner;
bool attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
int position; //position on battlefield
bool alive; //true if it is alive
ui32 amount;
ui32 firstHPleft; //HP of first creature in stack
ui8 owner;
ui8 attackerOwned; //if true, this stack is owned by attakcer (this one from left hand side of battle)
ui16 position; //position on battlefield
ui8 alive; //true if it is alive
CStack(CCreature * C, int A, int O, int I, bool AO);
CStack() : creature(NULL),amount(-1),owner(255), alive(true), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1){};
template <typename Handler> void save(Handler &h, const int version)
{
h & creature->idNumber;
}
template <typename Handler> void load(Handler &h, const int version)
{
ui32 id;
h & id;
creature = &VLC->creh->creatures[id];
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & ID & amount & firstHPleft & owner & attackerOwned & position & alive;
if(h.saving)
save(h,version);
else
load(h,version);
}
};
class DLL_EXPORT CGameState
@ -94,6 +118,8 @@ private:
std::pair<int,int> pickObject(CGObjectInstance *obj);
int pickHero(int owner);
CGHeroInstance *getHero(int objid);
void battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2);
bool battleMoveCreatureStack(int ID, int dest);
bool battleAttackCreatureStack(int ID, int dest);

171
CLua.cpp
View File

@ -77,10 +77,6 @@ void CLua::open(std::string initpath)
// temp += initpath;
// throw std::exception(temp.c_str());
//}
}
void CLua::registerCLuaCallback()
{
@ -113,10 +109,6 @@ void CLua::findFS(std::string fname)
// lua_settop(is, 0);
// throw new std::exception((fname + ": function not defined").c_str()); // the call is not defined
//}
}
#undef LST
@ -153,10 +145,6 @@ void CLuaObjectScript::newObject(int objid)
// throw new std::exception(("Failed to call "+genFN("newObject",os->ID)+" function in lua script.").c_str());
//}
//lua_settop(is, 0);
return;
}
void CLuaObjectScript::onHeroVisit(int objid, int heroID)
@ -170,10 +158,6 @@ void CLuaObjectScript::onHeroVisit(int objid, int heroID)
// throw new std::exception(("Failed to call "+genFN("heroVisit",os->ID)+" function in lua script.").c_str());
//}
//lua_settop(is, 0);
}
//std::string CLuaObjectScript::hoverText(int objid)
//{
@ -295,30 +279,33 @@ void CVisitableOPH::onNAHeroVisit(int objid, int heroID, bool alreadyVisited)
case 61:
case 32:
{
//cb->changePrimSkill(heroID,w,vvv);
//std::vector<SComponent*> weko;
//weko.push_back(new SComponent(SComponent::primskill,w,vvv));
//cb->showInfoDialog(cb->getHeroOwner(heroID),VLC->objh->advobtxt[ot],&weko);
//break;
cb->changePrimSkill(heroID,w,vvv);
InfoWindow iw;
iw.components.push_back(Component(0,w,vvv,0));
iw.text << std::pair<ui8,ui32>(11,ot);
iw.player = cb->getHeroOwner(heroID);
cb->showInfoDialog(&iw);
break;
}
case 100:
case 100: //give 1000 exp
{
//cb->changePrimSkill(heroID,w,vvv);
//std::vector<SComponent*> weko;
//weko.push_back(new SComponent(SComponent::experience,0,vvv));
//cb->showInfoDialog(cb->getHeroOwner(heroID),VLC->objh->advobtxt[ot],&weko);
//break;
cb->changePrimSkill(heroID,w,vvv);
InfoWindow iw;
iw.components.push_back(Component(0,4,vvv,0));
iw.player = cb->getHeroOwner(heroID);
iw.text << std::pair<ui8,ui32>(11,ot);
cb->showInfoDialog(&iw);
break;
}
}
}
else
{
ot++;
//cb->showInfoDialog(cb->getHeroOwner(heroID),VLC->objh->advobtxt[ot],&std::vector<SComponent*>());
InfoWindow iw;
iw.player = cb->getHeroOwner(heroID);
iw.text << std::pair<ui8,ui32>(11,ot);
cb->showInfoDialog(&iw);
}
}
@ -336,46 +323,6 @@ std::vector<int> CVisitableOPH::yourObjects()
void CVisitableOPW::onNAHeroVisit(int objid, int heroID, bool alreadyVisited)
{
DEFOS;
int mid;
switch (os->ID)
{
@ -518,15 +465,6 @@ void CMines::onHeroVisit(int objid, int heroID)
iw.player = h->tempOwner;
iw.components.push_back(Component(2,os->subID,vv,-1));
cb->showInfoDialog(&iw);
}
std::vector<int> CMines::yourObjects()
{
@ -585,33 +523,42 @@ void CPickable::onHeroVisit(int objid, int heroID)
}
case 79:
{
////TODO: handle guards (when battles are finished)
//CResourceObjInfo * t2 = static_cast<CResourceObjInfo *>(os->info);
//int val;
//if(t2->amount)
// val = t2->amount;
//else
//{
// switch(os->subID)
// {
// case 6:
// val = 500 + (rand()%6)*100;
// break;
// case 0: case 2:
// val = 6 + (rand()%5);
// break;
// default:
// val = 3 + (rand()%3);
// break;
// }
//}
//if(t2->message.length())
// cb->showInfoDialog(cb->getHeroOwner(heroID),t2->message,&std::vector<SComponent*>());
//SComponent ccc(SComponent::resource,os->subID,val);
//ccc.description = VLC->objh->advobtxt[113];
//boost::algorithm::replace_first(ccc.description,"%s",VLC->objh->restypes[os->subID]);
//cb->giveResource(cb->getHeroOwner(heroID),os->subID,val);
//cb->showCompInfo(cb->getHeroOwner(heroID),&ccc);
//TODO: handle guards (when battles are finished)
CResourceObjInfo * t2 = static_cast<CResourceObjInfo *>(os->info);
int val;
if(t2->amount)
val = t2->amount;
else
{
switch(os->subID)
{
case 6:
val = 500 + (rand()%6)*100;
break;
case 0: case 2:
val = 6 + (rand()%5);
break;
default:
val = 3 + (rand()%3);
break;
}
}
if(t2->message.length())
{
InfoWindow iw;
iw.player = cb->getHero(heroID)->tempOwner;
iw.text << t2->message;
cb->showInfoDialog(&iw);
}
cb->giveResource(cb->getHeroOwner(heroID),os->subID,val);
ShowInInfobox sii;
sii.player = cb->getHeroOwner(heroID);
sii.c = Component(2,os->subID,val,0);
sii.text << std::pair<ui8,ui32>(11,113);
sii.text.replacements.push_back(VLC->objh->restypes[os->subID]);
cb->showCompInfo(&sii);
break;
}
case 101:
@ -672,10 +619,6 @@ void CPickable::chosen(int which)
//for (int i=0;i<tempStore.size();i++)
// delete tempStore[i];
//tempStore.clear();
}
std::vector<int> CPickable::yourObjects() //returns IDs of objects which are handled by script
@ -797,8 +740,8 @@ void CMonsterS::onHeroVisit(int objid, int heroID)
DEFOS;
CCreatureSet set;
//TODO: zrobic secik w sposob wyrafinowany
set.slots[0] = std::pair<ui32,si32>(os->subID,((CCreatureObjInfo*)os->info)->number);
cb->startBattle(heroID,&set,os->pos);
set.slots[0] = std::pair<ui32,si32>(os->subID,amounts[objid]);
cb->startBattle(heroID,set,os->pos);
}
std::vector<int> CMonsterS::yourObjects() //returns IDs of objects which are handled by script
{

66
CMT.cpp
View File

@ -1,6 +1,6 @@
// CMT.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdafx.h"
#include <cmath>
#include <string>
#include <vector>
@ -10,11 +10,11 @@
#include "SDL_ttf.h"
#include "SDL_mixer.h"
#include "SDL_Extensions.h"
#include "SDL_framerate.h"
#include "CGameInfo.h"
#include "SDL_framerate.h"
#include "CGameInfo.h"
#include "mapHandler.h"
#include "global.h"
#include "CPreGame.h"
#include "CPreGame.h"
#include "CConsoleHandler.h"
#include "CCursorHandler.h"
#include "CPathfinder.h"
@ -42,15 +42,15 @@
std::string NAME = NAME_VER + std::string(" (client)");
DLL_EXPORT void initDLL(CLodHandler *b);
SDL_Surface * screen, * screen2;
extern SDL_Surface * CSDL_Ext::std32bppSurface;
extern SDL_Surface * CSDL_Ext::std32bppSurface;
std::queue<SDL_Event> events;
boost::mutex eventsM;
TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
boost::mutex eventsM;
TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
#ifndef __GNUC__
int _tmain(int argc, _TCHAR* argv[])
#else
#else
int main(int argc, _TCHAR* argv[])
#endif
#endif
{
std::cout.flags(ios::unitbuf);
std::cout << NAME << std::endl;
@ -59,7 +59,7 @@ int main(int argc, _TCHAR* argv[])
atexit(SDL_Quit);
CGameInfo * cgi = CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler itp.)
//CLuaHandler luatest;
//luatest.test();
//luatest.test();
//CBIKHandler cb;
//cb.open("CSECRET.BIK");
std::cout << "Starting... " << std::endl;
@ -73,7 +73,7 @@ int main(int argc, _TCHAR* argv[])
int rmask = 0xff000000;int gmask = 0x00ff0000;int bmask = 0x0000ff00;int amask = 0x000000ff;
#else
int rmask = 0x000000ff; int gmask = 0x0000ff00; int bmask = 0x00ff0000; int amask = 0xff000000;
#endif
#endif
CSDL_Ext::std32bppSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32, rmask, gmask, bmask, amask);
THC std::cout<<"\tInitializing minors: "<<pomtime.getDif()<<std::endl;
TTF_Init();
@ -81,30 +81,30 @@ int main(int argc, _TCHAR* argv[])
GEOR13 = TTF_OpenFont("Fonts\\georgia.ttf",13);
GEOR16 = TTF_OpenFont("Fonts\\georgia.ttf",16);
GEORXX = TTF_OpenFont("Fonts\\tnrb.ttf",22);
GEORM = TTF_OpenFont("Fonts\\georgia.ttf",10);
GEORM = TTF_OpenFont("Fonts\\georgia.ttf",10);
atexit(TTF_Quit);
THC std::cout<<"\tInitializing fonts: "<<pomtime.getDif()<<std::endl;
CMusicHandler * mush = new CMusicHandler; //initializing audio
mush->initMusics();
//audio initialized
//audio initialized
cgi->consoleh = new CConsoleHandler;
cgi->mush = mush;
THC std::cout<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"Initializing screen, fonts and sound handling: "<<tmh.getDif()<<std::endl;
CDefHandler::Spriteh = cgi->spriteh = new CLodHandler();
cgi->spriteh->init("Data\\H3sprite.lod","Sprites");
BitmapHandler::bitmaph = cgi->bitmaph = new CLodHandler;
cgi->bitmaph->init("Data\\H3bitmap.lod","Data");
THC std::cout<<"Loading .lod files: "<<tmh.getDif()<<std::endl;
initDLL(cgi->bitmaph);
initDLL(cgi->bitmaph);
CGI->arth = VLC->arth;
CGI->creh = VLC->creh;
CGI->townh = VLC->townh;
CGI->heroh = VLC->heroh;
CGI->objh = VLC->objh;
CGI->dobjinfo = VLC->dobjinfo;
CGI->buildh = VLC->buildh;
THC std::cout<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
CGI->buildh = VLC->buildh;
THC std::cout<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
//cgi->curh->initCursor();
//cgi->curh->showGraphicCursor();
pomtime.getDif();
@ -112,11 +112,11 @@ int main(int argc, _TCHAR* argv[])
cgi->curh->initCursor();
//cgi->screenh = new CScreenHandler;
//cgi->screenh->initScreen();
THC std::cout<<"\tScreen handler: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"\tScreen handler: "<<pomtime.getDif()<<std::endl;
CAbilityHandler * abilh = new CAbilityHandler;
abilh->loadAbilities();
cgi->abilh = abilh;
THC std::cout<<"\tAbility handler: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"\tAbility handler: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"Preparing first handlers: "<<tmh.getDif()<<std::endl;
pomtime.getDif();
graphics = new Graphics();
@ -130,35 +130,35 @@ int main(int argc, _TCHAR* argv[])
CMessage::init();
cgi->generaltexth = new CGeneralTextHandler;
cgi->generaltexth->load();
THC std::cout<<"Preparing more handlers: "<<tmh.getDif()<<std::endl;
THC std::cout<<"Preparing more handlers: "<<tmh.getDif()<<std::endl;
CPreGame * cpg = new CPreGame(); //main menu and submenus
THC std::cout<<"Initialization CPreGame (together): "<<tmh.getDif()<<std::endl;
THC std::cout<<"Initialization of VCMI (togeter): "<<total.getDif()<<std::endl;
cpg->mush = mush;
StartInfo *options = new StartInfo(cpg->runLoop());
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
boost::thread servthr(boost::bind(system,"VCMI_server.exe > server_log.txt")); //runs server executable;
//TODO: will it work on non-windows platforms?
THC tmh.getDif();pomtime.getDif();//reset timers
THC tmh.getDif();pomtime.getDif();//reset timers
CSpellHandler * spellh = new CSpellHandler;
spellh->loadSpells();
cgi->spellh = spellh;
THC std::cout<<"\tSpell handler: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"\tSpell handler: "<<pomtime.getDif()<<std::endl;
cgi->pathf = new CPathfinder();
THC std::cout<<"\tPathfinder: "<<pomtime.getDif()<<std::endl;
cgi->consoleh->runConsole();
THC std::cout<<"\tCallback and console: "<<pomtime.getDif()<<std::endl;
THC std::cout<<"Handlers initialization (together): "<<tmh.getDif()<<std::endl;
THC std::cout<<"Handlers initialization (together): "<<tmh.getDif()<<std::endl;
std::ofstream lll("client_log.txt");
CConnection *c = new CConnection("localhost","3030",NAME,lll);
THC std::cout<<"\tConnecting to the server: "<<tmh.getDif()<<std::endl;
THC std::cout<<"\tConnecting to the server: "<<tmh.getDif()<<std::endl;
CClient cl(c,options);
boost::thread t(boost::bind(&CClient::run,&cl));
boost::thread t(boost::bind(&CClient::run,&cl));
SDL_Event ev;
while(1) //main SDL events loop
{
SDL_WaitEvent(&ev);
if(ev.type==SDL_QUIT)
if(ev.type==SDL_QUIT)
{
t.interrupt();
exit(0);
@ -166,24 +166,24 @@ int main(int argc, _TCHAR* argv[])
eventsM.lock();
events.push(ev);
eventsM.unlock();
}
}
///claculating FoWs for minimap
/****************************Minimaps' FoW******************************************/
//for(int g=0; g<cgi->playerint.size(); ++g)
//{
// if(!cgi->playerint[g]->human)
// continue;
// CMinimap & mm = ((CPlayerInterface*)cgi->playerint[g])->adventureInt->minimap;
// CMinimap & mm = ((CPlayerInterface*)cgi->playerint[g])->adventureInt->minimap;
// int mw = mm.map[0]->w, mh = mm.map[0]->h,
// wo = mw/CGI->mh->sizes.x, ho = mh/CGI->mh->sizes.y;
// wo = mw/CGI->mh->sizes.x, ho = mh/CGI->mh->sizes.y;
// for(int d=0; d<cgi->mh->map->twoLevel+1; ++d)
// {
// SDL_Surface * pt = CSDL_Ext::newSurface(mm.pos.w, mm.pos.h, CSDL_Ext::std32bppSurface);
// SDL_Surface * pt = CSDL_Ext::newSurface(mm.pos.w, mm.pos.h, CSDL_Ext::std32bppSurface);
// for (int i=0; i<mw; i++)
// {
// for (int j=0; j<mh; j++)
// {
// int3 pp( ((i*CGI->mh->sizes.x)/mw), ((j*CGI->mh->sizes.y)/mh), d );
// int3 pp( ((i*CGI->mh->sizes.x)/mw), ((j*CGI->mh->sizes.y)/mh), d );
// if ( !((CPlayerInterface*)cgi->playerint[g])->cb->isVisible(pp) )
// {
// CSDL_Ext::SDL_PutPixelWithoutRefresh(pt,i,j,0,0,0);
@ -192,7 +192,7 @@ int main(int argc, _TCHAR* argv[])
// }
// CSDL_Ext::update(pt);
// mm.FoW.push_back(pt);
// }
// }
//}
}
else

View File

@ -33,6 +33,7 @@
#include "client/Graphics.h"
#include "map.h"
#include "lib/NetPacks.h"
#include "lib/CondSh.h"
using namespace CSDL_Ext;
extern TTF_Font * GEOR16;
@ -564,7 +565,10 @@ SComponent::SComponent(Etype Type, int Subtype, int Val)
SComponent::SComponent(const Component &c)
{
init((Etype)c.id,c.subtype,c.val);
if(c.id==0 && c.subtype==4)
init(experience,0,c.val);
else
init((Etype)c.id,c.subtype,c.val);
switch(c.id)
{
case resource:
@ -1142,6 +1146,7 @@ int getDir(int3 src, int3 dst)
}
void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
{
boost::unique_lock<boost::mutex> un(*pim);
//initializing objects and performing first step of move
CGHeroInstance * ho = details.ho; //object representing this hero
int3 hp = details.src;
@ -1487,7 +1492,7 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
//CGI->screenh->updateScreen();
++LOCPLINT->adventureInt->animValHitCount; //for animations
if(LOCPLINT->adventureInt->animValHitCount == 4)
if(LOCPLINT->adventureInt->animValHitCount == 8)
{
LOCPLINT->adventureInt->animValHitCount = 0;
++LOCPLINT->adventureInt->anim;
@ -1946,8 +1951,9 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
}
}
void CPlayerInterface::battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, tribool side) //called by engine when battle starts; side=0 - left, side=1 - right
void CPlayerInterface::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
{
boost::unique_lock<boost::mutex> un(*pim);
curint->deactivate();
curint = new CBattleInterface(army1,army2,hero1,hero2);
curint->activate();
@ -1974,45 +1980,27 @@ void CPlayerInterface::actionFinished(BattleAction action)//occurs AFTER every a
BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
{
unsigned char showCount = 0;
dynamic_cast<CBattleInterface*>(curint)->stackActivated(stackID);
while(!dynamic_cast<CBattleInterface*>(curint)->givenCommand) //while current unit can perform an action
CBattleInterface *b = dynamic_cast<CBattleInterface*>(curint);
{
++showCount;
SDL_Event sEvent;
while (SDL_PollEvent(&sEvent)) //wait for event...
{
LOCPLINT->handleEvent(&sEvent);
}
if(showCount%2==0)
for(int i=0;i<objsToBlit.size();i++)
objsToBlit[i]->show();
//SDL_Flip(screen);
CSDL_Ext::update(screen);
/*timeHandler th;
th.getDif();
int tv = th.getDif();
for (int i=0;i<((CBattleInterface*)this->curint)->timeinterested.size();i++)
{
if (timeinterested[i]->toNextTick>=0)
timeinterested[i]->toNextTick-=tv;
if (timeinterested[i]->toNextTick<0)
timeinterested[i]->tick();
}*/
SDL_Delay(1); //give time for other apps
SDL_framerateDelay(mainFPSmng);
boost::unique_lock<boost::mutex> un(*pim);
b->stackActivated(stackID);
}
BattleAction ret = *(dynamic_cast<CBattleInterface*>(curint)->givenCommand);
delete dynamic_cast<CBattleInterface*>(curint)->givenCommand;
dynamic_cast<CBattleInterface*>(curint)->givenCommand = NULL;
dynamic_cast<CBattleInterface*>(curint)->myTurn = false;
//wait till BattleInterface sets its command
boost::unique_lock<boost::mutex> lock(b->givenCommand->mx);
while(!b->givenCommand->data)
b->givenCommand->cond.wait(lock);
//tidy up
BattleAction ret = *(b->givenCommand->data);
delete b->givenCommand->data;
//return command
return ret;
}
void CPlayerInterface::battleEnd(CCreatureSet * army1, CCreatureSet * army2, CArmedInstance *hero1, CArmedInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner)
void CPlayerInterface::battleEnd(BattleResult *br)
{
boost::unique_lock<boost::mutex> un(*pim);
dynamic_cast<CBattleInterface*>(curint)->deactivate();
LOCPLINT->objsToBlit.erase(std::find(LOCPLINT->objsToBlit.begin(),LOCPLINT->objsToBlit.end(),dynamic_cast<IShowable*>(curint)));
delete dynamic_cast<CBattleInterface*>(curint);
@ -2047,6 +2035,7 @@ void CPlayerInterface::battleStackIsShooting(int ID, int dest)
void CPlayerInterface::showComp(SComponent comp)
{
boost::unique_lock<boost::mutex> un(*pim);
adventureInt->infoBar.showComp(&comp,4000);
}

View File

@ -333,13 +333,13 @@ public:
void garrisonChanged(const CGObjectInstance * obj);
void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
//for battles
void battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::logic::tribool side); //called by engine when battle starts; side=0 - left, side=1 - right
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
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 actionStarted(BattleAction action);//occurs BEFORE every action taken by any stack or by the hero
void actionFinished(BattleAction action);//occurs AFTER every action taken by any stack or by the hero
BattleAction activeStack(int stackID); //called when it's turn of that stack
void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CArmedInstance *hero1, CArmedInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner);
void battleEnd(BattleResult *br);
void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving);
void battleStackAttacking(int ID, int dest);
void battleStackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting);

View File

@ -22,7 +22,12 @@
extern SDL_Surface * screen;
extern SDL_Color tytulowy, tlo, zwykly ;
extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM;
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
SDL_Rect genRect(int hh, int ww, int xx, int yy);
SDL_Color genRGB(int r, int g, int b, int a=0);
//void printAt(std::string text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen);

View File

@ -16,6 +16,7 @@
#include "../hch/CGeneralTextHandler.h"
#include "../hch/CArtHandler.h"
#include <boost/thread/shared_mutex.hpp>
#include "../lib/VCMI_Lib.h"
CSharedCond<std::set<IPack*> > mess(new std::set<IPack*>);
std::string toString(MetaString &ms)
@ -208,6 +209,25 @@ void CClient::process(int what)
playerint[sr.player]->receivedResource(-1,-1);
break;
}
case 105:
{
SetPrimSkill sps;
*serv >> sps;
std::cout << "Changing hero primary skill"<<std::endl;
gs->apply(&sps);
playerint[gs->getHero(sps.id)->tempOwner]->heroPrimarySkillChanged(gs->getHero(sps.id),sps.which,sps.val);
break;
}
case 107:
{
ShowInInfobox sii;
*serv >> sii;
SComponent sc(sii.c);
sc.description = toString(sii.text);
if(playerint[sii.player]->human)
static_cast<CPlayerInterface*>(playerint[sii.player])->showComp(sc);
break;
}
case 500:
{
RemoveHero rh;
@ -297,6 +317,59 @@ void CClient::process(int what)
gs->mx->lock();
gs->map->objects[shn.id]->hoverName = toString(shn.name);
gs->mx->unlock();
break;
}
case 3000:
{
BattleStart bs;
*serv >> bs; //uses new to allocate memory for battleInfo - must be deleted when battle is over
std::cout << "Starting battle!" <<std::endl;
gs->apply(&bs);
if(playerint.find(gs->curB->side1) != playerint.end())
playerint[gs->curB->side1]->battleStart(&gs->curB->army1, &gs->curB->army2, gs->curB->tile, gs->getHero(gs->curB->hero1), gs->getHero(gs->curB->hero2), 0);
if(playerint.find(gs->curB->side2) != playerint.end())
playerint[gs->curB->side2]->battleStart(&gs->curB->army1, &gs->curB->army2, gs->curB->tile, gs->getHero(gs->curB->hero1), gs->getHero(gs->curB->hero2), 1);
break;
}
case 3001:
{
BattleNextRound bnr;
*serv >> bnr;
std::cout << "Round nr " << bnr.round <<std::endl;
gs->apply(&bnr);
//tell players about next round
if(playerint.find(gs->curB->side1) != playerint.end())
playerint[gs->curB->side1]->battleNewRound(bnr.round);
if(playerint.find(gs->curB->side2) != playerint.end())
playerint[gs->curB->side2]->battleNewRound(bnr.round);
break;
}
case 3002:
{
BattleSetActiveStack sas;
*serv >> sas;
std::cout << "Active stack: " << sas.stack <<std::endl;
gs->apply(&sas);
boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,gs->curB->stacks[sas.stack]->owner));
break;
}
case 3003:
{
BattleResult br;
*serv >> br;
std::cout << "Battle ends. Winner: " << (unsigned)br.winner<< ". Type of end: "<< (unsigned)br.result <<std::endl;
if(playerint.find(gs->curB->side1) != playerint.end())
playerint[gs->curB->side1]->battleEnd(&br);
if(playerint.find(gs->curB->side2) != playerint.end())
playerint[gs->curB->side2]->battleEnd(&br);
gs->apply(&br);
break;
}
case 9999:
@ -310,6 +383,11 @@ void CClient::process(int what)
break;
}
}
void CClient::waitForMoveAndSend(int color)
{
BattleAction ba = playerint[color]->activeStack(gs->curB->activeStack);
*serv << ui16(3002) << ba;
}
void CClient::run()
{
try

View File

@ -38,6 +38,8 @@ class CClient
CGameState *gs;
std::map<ui8,CGameInterface *> playerint;
CConnection *serv;
void waitForMoveAndSend(int color);
public:
CClient(void);
CClient(CConnection *con, StartInfo *si);

View File

@ -15,6 +15,12 @@
#include "../hch/CLodHandler.h"
using namespace boost::assign;
using namespace CSDL_Ext;
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
Graphics * graphics = NULL;
SDL_Surface * Graphics::drawPrimarySkill(const CGHeroInstance *curh, SDL_Surface *ret, int from, int to)
{

View File

@ -21,7 +21,7 @@ public:
std::string abilityText; //description of abilities
std::string abilityRefs; //references to abilities, in textformat
std::string animDefName;
int idNumber;
ui32 idNumber;
int faction; //-1 = neutral
///animation info

View File

@ -6,6 +6,32 @@
#include "../lib/VCMI_Lib.h"
extern CLodHandler * bitmaph;
void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
CHeroClass::CHeroClass()
{
skillLimit = 8;
}
CHeroClass::~CHeroClass()
{
}
int CHeroClass::chooseSecSkill(std::set<int> possibles) //picks secondary skill out from given possibilities
{
if(possibles.size()==1)
return *possibles.begin();
int totalProb = 0;
for(std::set<int>::iterator i=possibles.begin(); i!=possibles.end(); i++)
{
totalProb += proSec[*i];
}
int ran = rand()%totalProb;
for(std::set<int>::iterator i=possibles.begin(); i!=possibles.end(); i++)
{
ran -= proSec[*i];
if(ran<0)
return *i;
}
}
CHeroHandler::~CHeroHandler()
{}
void CHeroHandler::loadPortraits()

View File

@ -3,7 +3,7 @@
#include "../global.h"
#include <string>
#include <vector>
#include <set>
class CHeroClass;
class CDefHandler;
class CGameInfo;
@ -26,6 +26,7 @@ public:
class DLL_EXPORT CHeroClass
{
public:
ui32 skillLimit; //how many secondary skills can hero learn
std::string name;
float aggression;
int initialAttack, initialDefence, initialPower, initialKnowledge;
@ -34,6 +35,9 @@ public:
int selectionProbability[9]; //probability of selection in towns
std::vector<int> terrCosts; //default costs of going through terrains: dirt, sand, grass, snow, swamp, rough, subterrain, lava, water, rock; -1 means terrain is imapassable
CDefHandler * moveAnim; //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing
int chooseSecSkill(std::set<int> possibles); //picks secondary skill out from given possibilities
CHeroClass();
~CHeroClass();
};
class DLL_EXPORT CHeroHandler

View File

@ -84,7 +84,7 @@ public:
// 765
bool isStanding;
CHero * type;
int exp; //experience point
ui32 exp; //experience point
int level; //current level of hero
std::string name; //may be custom
std::string biography; //may be custom

13
lib/BattleAction.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
struct BattleAction
{
ui8 side; //who made this action: false - left, true - right player
ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
ui8 actionType; // 0 = Cancel BattleAction 1 = Hero cast a spell 2 = Walk 3 = Defend 4 = Retreat from the battle 5 = Surrender 6 = Walk and Attack 7 = Shoot 8 = Wait 9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons)
ui16 destinationTile;
ui16 additionalInfo; // e.g. spell number if type is 1 || 10
template <typename Handler> void serialize(Handler &h, const int version)
{
h & side & stackNumber & actionType & destinationTile & additionalInfo;
}
};

13
lib/CondSh.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include <boost/thread.hpp>
template <typename T> struct CondSh
{
T data;
boost::condition_variable cond;
boost::mutex mx;
CondSh(){};
CondSh(T t){data = t;};
void set(T t){mx.lock();data=t;mx.unlock();}; //set data
void setn(T t){mx.lock();data=t;mx.unlock();cond.notify_all();}; //set data and notify
T get(){boost::unique_lock<boost::mutex> lock(mx); return data;};
};

View File

@ -6,14 +6,14 @@
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/thread.hpp>
const int version = 63;
class CConnection;
@ -44,6 +44,7 @@ enum SerializationLvl
{
Wrong=0,
Primitive,
Pointer,
Serializable
};
@ -64,6 +65,10 @@ struct SerializationLevel
boost::is_array<T>,
mpl::int_<Primitive>,
//else
typename mpl::eval_if<
boost::is_pointer<T>,
mpl::int_<Pointer>,
//else
typename mpl::eval_if<
boost::is_enum<T>,
mpl::int_<Primitive>,
@ -72,6 +77,7 @@ struct SerializationLevel
>
>
>
>
>::type type;
static const int value = SerializationLevel::type::value;
};
@ -79,7 +85,8 @@ struct SerializationLevel
template <typename Serializer> class DLL_EXPORT COSer
{
public:
COSer(){};
bool saving;
COSer(){saving=true;};
Serializer * This()
{
return static_cast<Serializer*>(this);
@ -100,7 +107,8 @@ public:
template <typename Serializer> class DLL_EXPORT CISer
{
public:
CISer(){};
bool saving;
CISer(){saving = false;};
Serializer * This()
{
return static_cast<Serializer*>(this);
@ -144,6 +152,22 @@ struct LoadPrimitive
}
};
template<typename Ser,typename T>
struct SavePointer
{
static void invoke(Ser &s, const T &data)
{
s.savePointer(data);
}
};
template<typename Ser,typename T>
struct LoadPointer
{
static void invoke(Ser &s, T &data)
{
s.loadPointer(data);
}
};
template<typename Ser,typename T>
struct LoadSerializable
{
static void invoke(Ser &s, T &data)
@ -203,8 +227,20 @@ public:
void loadSerializable(T &data)
{
data.serialize(*static_cast<CISer<CConnection>*>(this),version);
}
template <typename T>
void savePointer(const T &data)
{
*this << *data;
}
template <typename T>
void loadPointer(T &data)
{
std::cout<<"Allocating memory for pointer!"<<std::endl;
typedef boost::remove_pointer<T>::type npT;
data = new npT;
*this >> *data;
}
template <typename T>
void saveSerializable(const std::vector<T> &data)
{
@ -283,11 +319,15 @@ public:
typename mpl::eval_if< mpl::equal_to<SerializationLevel<T>,mpl::int_<Primitive> >,
mpl::identity<SavePrimitive<CConnection,T> >,
//else if
typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Pointer> >,
mpl::identity<SavePointer<CConnection,T> >,
//else if
typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Serializable> >,
mpl::identity<SaveSerializable<CConnection,T> >,
//else
mpl::identity<SaveWrong<CConnection,T> >
>
>
>::type typex;
typex::invoke(*this, data);
}
@ -300,11 +340,15 @@ public:
typename mpl::eval_if< mpl::equal_to<SerializationLevel<T>,mpl::int_<Primitive> >,
mpl::identity<LoadPrimitive<CConnection,T> >,
//else if
typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Pointer> >,
mpl::identity<LoadPointer<CConnection,T> >,
//else if
typename mpl::eval_if<mpl::equal_to<SerializationLevel<T>,mpl::int_<Serializable> >,
mpl::identity<LoadSerializable<CConnection,T> >,
//else
mpl::identity<LoadWrong<CConnection,T> >
>
>
>::type typex;
typex::invoke(*this, data);
}
@ -330,9 +374,9 @@ public:
~CConnection(void);
};
template<>
template<> DLL_EXPORT
void CConnection::saveSerializable<std::string>(const std::string &data);
template <>
template <>DLL_EXPORT
void CConnection::loadSerializable<std::string>(std::string &data);

View File

@ -82,6 +82,18 @@ struct SetResources : public CPack<SetResources> //104
h & player & res;
}
};
struct SetPrimSkill : public CPack<SetPrimSkill> //105
{
SetPrimSkill(){type = 105;};
ui8 abs; //0 - changes by value; 1 - sets to value
si32 id;
ui16 which, val;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & abs & id & which & val;
}
};
struct RemoveHero : public CPack<RemoveHero> //500
{
RemoveHero(){type = 500;};
@ -225,4 +237,79 @@ struct SetHoverName : public CPack<SetHoverName>//1002
{
h & id & name;
}
};
};
struct HeroLevelUp : public CPack<HeroLevelUp>//2000
{
si32 id;
ui8 primskill, level;
std::set<ui16> skills;
HeroLevelUp(){type = 2000;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & primskill & level & skills;
}
};
struct BattleInfo;
struct BattleStart : public CPack<BattleStart>//3000
{
BattleInfo * info;
BattleStart(){type = 3000;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & info;
}
};
struct BattleNextRound : public CPack<BattleNextRound>//3001
{
si32 round;
BattleNextRound(){type = 3001;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & round;
}
};
struct BattleSetActiveStack : public CPack<BattleSetActiveStack>//3002
{
ui32 stack;
BattleSetActiveStack(){type = 3002;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & stack;
}
};
struct BattleResult : public CPack<BattleResult>//3003
{
ui8 result; //0 - normal victory; 1 - escape; 2 - surrender
ui8 winner; //0 - attacker, 1 - defender, [2 - draw (should be possible?)]
std::set<std::pair<ui32,si32> > s1, s2; //first => casualties of attackers - set of pairs crid<>number
ui32 exp[2]; //exp for attacker and defender
std::set<ui32> artifacts; //artifacts taken from loser to winner
BattleResult(){type = 3003;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & result & winner & s1 & s2 & exp & artifacts;
}
};
struct ShowInInfobox : public CPack<ShowInInfobox> //107
{
ShowInInfobox(){type = 107;};
ui8 player;
Component c;
MetaString text;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & player & c & text;
}
};

View File

@ -319,6 +319,10 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\BattleAction.h"
>
</File>
<File
RelativePath="..\hch\CAmbarCendamo.h"
>
@ -355,6 +359,10 @@
RelativePath="..\hch\CObjectHandler.h"
>
</File>
<File
RelativePath=".\CondSh.h"
>
</File>
<File
RelativePath=".\Connection.h"
>

View File

@ -17,14 +17,36 @@
#include "../hch/CHeroHandler.h"
#include "boost/date_time/posix_time/posix_time_types.hpp" //no i/o just types
#include "../lib/VCMI_Lib.h"
#include <boost/thread.hpp>
#include "../lib/CondSh.h"
#include <boost/thread/xtime.hpp>
extern bool end2;
bool makingTurn;
#include "../lib/BattleAction.h"
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#define NEW_ROUND BattleNextRound bnr;\
bnr.round = gs->curB->round + 1;\
sendAndApply(&bnr);
boost::condition_variable cTurn;
boost::mutex mTurn;
boost::shared_mutex gsm;
CondSh<bool> battleMadeAction;
CondSh<BattleResult *> battleResult(NULL);
class CMP_stack
{
public:
bool operator ()(const CStack* a, const CStack* b)
{
return (a->creature->speed)>(b->creature->speed);
}
} cmpst ;
double distance(int3 a, int3 b)
{
return std::sqrt( (double)(a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
@ -51,6 +73,268 @@ void CGameHandler::handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObj
cppscripts.insert(script);
}
void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
{
SetPrimSkill sps;
sps.id = ID;
sps.which = which;
sps.abs = abs;
sps.val = val;
sendAndApply(&sps);
if(which==4)
{
CGHeroInstance *hero = static_cast<CGHeroInstance *>(gs->map->objects[ID]);
if(hero->exp >= VLC->heroh->reqExp(hero->level+1)) //new level
{
//hero->level++;
//give prim skill
std::cout << hero->name <<" got level "<<hero->level<<std::endl;
int r = rand()%100, pom=0, x=0;
int std::pair<int,int>::*g = (hero->level>9) ? (&std::pair<int,int>::second) : (&std::pair<int,int>::first);
for(;x<PRIMARY_SKILLS;x++)
{
pom += hero->type->heroClass->primChance[x].*g;
if(r<pom)
break;
}
std::cout << "Bohater dostaje umiejetnosc pierwszorzedna " << x << " (wynik losowania "<<r<<")"<<std::endl;
SetPrimSkill sps;
sps.id = ID;
sps.which = x;
sps.abs = false;
sps.val = 1;
sendAndApply(&sps);
hero->primSkills[x]++;
std::set<ui16> choice;
std::set<int> basicAndAdv, expert, none;
for(int i=0;i<SKILL_QUANTITY;i++) none.insert(i);
for(unsigned i=0;i<hero->secSkills.size();i++)
{
if(hero->secSkills[i].second < 2)
basicAndAdv.insert(hero->secSkills[i].first);
else
expert.insert(hero->secSkills[i].first);
none.erase(hero->secSkills[i].first);
}
if(hero->secSkills.size() < hero->type->heroClass->skillLimit) //free skill slot
{
choice.insert(hero->type->heroClass->chooseSecSkill(none)); //new skill
}
else
{
int s = hero->type->heroClass->chooseSecSkill(basicAndAdv);
choice.insert(s);
basicAndAdv.erase(s);
}
if(basicAndAdv.size())
{
choice.insert(hero->type->heroClass->chooseSecSkill(basicAndAdv)); //new skill
}
else if(hero->secSkills.size() < hero->type->heroClass->skillLimit)
{
choice.insert(hero->type->heroClass->chooseSecSkill(none)); //new skill
}
}
//TODO - powiadomic interfejsy, sprawdzic czy nie ma awansu itp
}
}
void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2)
{
BattleInfo *curB = new BattleInfo;
//battle start
{
battleResult.set(NULL);
std::vector<CStack*> & stacks = (curB->stacks);
curB->army1=army1;
curB->army2=army2;
curB->hero1=(hero1)?(hero1->id):(-1);
curB->hero2=(hero1)?(hero1->id):(-1);
curB->side1=(hero1)?(hero1->tempOwner):(-1);
curB->side2=(hero2)?(hero2->tempOwner):(-1);
curB->round = -2;
curB->activeStack = -1;
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
{
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true));
stacks[stacks.size()-1]->ID = stacks.size()-1;
}
//initialization of positions
switch(army1.slots.size()) //for attacker
{
case 0:
break;
case 1:
stacks[0]->position = 86; //6
break;
case 2:
stacks[0]->position = 35; //3
stacks[1]->position = 137; //9
break;
case 3:
stacks[0]->position = 35; //3
stacks[1]->position = 86; //6
stacks[2]->position = 137; //9
break;
case 4:
stacks[0]->position = 1; //1
stacks[1]->position = 69; //5
stacks[2]->position = 103; //7
stacks[3]->position = 171; //11
break;
case 5:
stacks[0]->position = 1; //1
stacks[1]->position = 35; //3
stacks[2]->position = 86; //6
stacks[3]->position = 137; //9
stacks[4]->position = 171; //11
break;
case 6:
stacks[0]->position = 1; //1
stacks[1]->position = 35; //3
stacks[2]->position = 69; //5
stacks[3]->position = 103; //7
stacks[4]->position = 137; //9
stacks[5]->position = 171; //11
break;
case 7:
stacks[0]->position = 1; //1
stacks[1]->position = 35; //3
stacks[2]->position = 69; //5
stacks[3]->position = 86; //6
stacks[4]->position = 103; //7
stacks[5]->position = 137; //9
stacks[6]->position = 171; //11
break;
default: //fault
break;
}
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false));
switch(army2.slots.size()) //for defender
{
case 0:
break;
case 1:
stacks[0+army1.slots.size()]->position = 100; //6
break;
case 2:
stacks[0+army1.slots.size()]->position = 49; //3
stacks[1+army1.slots.size()]->position = 151; //9
break;
case 3:
stacks[0+army1.slots.size()]->position = 49; //3
stacks[1+army1.slots.size()]->position = 100; //6
stacks[2+army1.slots.size()]->position = 151; //9
break;
case 4:
stacks[0+army1.slots.size()]->position = 15; //1
stacks[1+army1.slots.size()]->position = 83; //5
stacks[2+army1.slots.size()]->position = 117; //7
stacks[3+army1.slots.size()]->position = 185; //11
break;
case 5:
stacks[0+army1.slots.size()]->position = 15; //1
stacks[1+army1.slots.size()]->position = 49; //3
stacks[2+army1.slots.size()]->position = 100; //6
stacks[3+army1.slots.size()]->position = 151; //9
stacks[4+army1.slots.size()]->position = 185; //11
break;
case 6:
stacks[0+army1.slots.size()]->position = 15; //1
stacks[1+army1.slots.size()]->position = 49; //3
stacks[2+army1.slots.size()]->position = 83; //5
stacks[3+army1.slots.size()]->position = 117; //7
stacks[4+army1.slots.size()]->position = 151; //9
stacks[5+army1.slots.size()]->position = 185; //11
break;
case 7:
stacks[0+army1.slots.size()]->position = 15; //1
stacks[1+army1.slots.size()]->position = 49; //3
stacks[2+army1.slots.size()]->position = 83; //5
stacks[3+army1.slots.size()]->position = 100; //6
stacks[4+army1.slots.size()]->position = 117; //7
stacks[5+army1.slots.size()]->position = 151; //9
stacks[6+army1.slots.size()]->position = 185; //11
break;
default: //fault
break;
}
for(unsigned g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
{
if((stacks[g]->position%17)==1 && stacks[g]->creature->isDoubleWide())
{
stacks[g]->position += 1;
}
else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide())
{
stacks[g]->position -= 1;
}
}
std::stable_sort(stacks.begin(),stacks.end(),cmpst);
//block engaged players
if(hero1->tempOwner<PLAYER_LIMIT)
states[hero1->tempOwner] += 10;
if(hero2 && hero2->tempOwner<PLAYER_LIMIT)
states[hero2->tempOwner] += 10;
//send info about battles
BattleStart bs;
bs.info = curB;
sendAndApply(&bs);
NEW_ROUND;
}
//tactic round
{
NEW_ROUND;
if( (hero1 && hero1->getSecSkillLevel(19)>=0) ||
( hero2 && hero2->getSecSkillLevel(19)>=0) )//someone has tactics
{
//TODO: tactic round (round -1)
}
}
//main loop
while(!battleResult.get()) //till the end of the battle ;]
{
NEW_ROUND;
std::vector<CStack*> & stacks = (gs->curB->stacks);
const BattleInfo & curB = *gs->curB;
//stack loop
for(unsigned i=0;i<stacks.size() && !battleResult.get();i++)
{
if(!stacks[i]->alive) continue;//indicates imposiibility of making action for this dead unit
BattleSetActiveStack sas;
sas.stack = i;
sendAndApply(&sas);
//wait for response about battle action
boost::unique_lock<boost::mutex> lock(battleMadeAction.mx);
while(!battleMadeAction.data)
battleMadeAction.cond.wait(lock);
}
}
//end battle, remove all info, free memory
sendAndApply(battleResult.data);
delete battleResult.data;
//for(int i=0;i<stacks.size();i++)
// delete stacks[i];
//delete curB;
//curB = NULL;
}
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
{
try
@ -65,7 +349,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
case 100: //my interface ended its turn
{
mTurn.lock();
makingTurn = false;
states[gs->currentPlayer] = 0;
mTurn.unlock();
cTurn.notify_all();
break;
@ -290,6 +574,47 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
sr.res[i]-=b->resources[i];
sendAndApply(&sr);
break;
}
case 3002:
{
BattleAction ba;
c >> ba;
switch(ba.actionType)
{
case 2: //walk
{
//battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
break;
}
case 3: //defend
{
break;
}
case 4: //retreat/flee
{
//TODO: check if fleeing is possible (e.g. enemy may have Shackles of War)
//TODO: calculate casualties
//TODO: remove retreating hero from map and place it in recrutation list
BattleResult *br = new BattleResult;
br->result = 1;
battleResult.set(br);
break;
}
case 6: //walk or attack
{
//battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
//battleAttackCreatureStack(ba.stackNumber, ba.destinationTile);
break;
}
case 7: //shoot
{
//battleShootCreatureStack(ba.stackNumber, ba.destinationTile);
break;
}
}
battleMadeAction.setn(true);
//sprawdzic czy po tej akcji ktoras strona nie wygrala bitwy
break;
}
default:
@ -490,12 +815,12 @@ void CGameHandler::run()
for(std::map<ui8,PlayerState>::iterator i = gs->players.begin(); i != gs->players.end(); i++)
{
if((i->second.towns.size()==0 && i->second.heroes.size()==0) || i->second.color<0 || i->first>=PLAYER_LIMIT ) continue; //players has not towns/castle - loser
makingTurn = true;
states[i->first] = 1;
gs->currentPlayer = i->first;
*connections[i->first] << ui16(100) << i->first;
//wait till turn is done
boost::unique_lock<boost::mutex> lock(mTurn);
while(makingTurn && !end2)
while(states[i->first] && !end2)
{
boost::posix_time::time_duration p;
p= boost::posix_time::seconds(1);
@ -503,7 +828,6 @@ void CGameHandler::run()
time.sec = static_cast<boost::xtime::xtime_sec_t>(p.total_seconds());
cTurn.timed_wait(lock,time);
}
}
}
}

View File

@ -10,7 +10,7 @@ struct StartInfo;
class CCPPObjectScript;
class CScriptCallback;
template <typename T> struct CPack;
class CGHeroInstance;
class CGameHandler
{
@ -19,10 +19,14 @@ class CGameHandler
//std::map<int, std::map<std::string, CObjectScript*> > objscr; //non-C++ scripts
CVCMIServer *s;
std::map<int,CConnection*> connections;
std::map<int,CConnection*> connections; //player color -> connection to clinet with interface of that player
std::map<int,int> states; //player color -> player state
std::set<CConnection*> conns;
void handleCPPObjS(std::map<int,CCPPObjectScript*> * mapa, CCPPObjectScript * script);
void changePrimSkill(int ID, int which, int val, bool abs=false);
void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2); //use hero=NULL for no hero
public:
CGameHandler(void);
@ -33,9 +37,9 @@ public:
{
for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)
{
(*i)->rmx->lock();
(*i)->wmx->lock();
**i << info->getType() << *info->This();
(*i)->rmx->unlock();
(*i)->wmx->unlock();
}
}
template <typename T>void sendAndApply(CPack<T> * info)

View File

@ -8,6 +8,8 @@
#include "../hch/CTownHandler.h"
#include "../hch/CHeroHandler.h"
#include "../lib/NetPacks.h"
#include "../lib/VCMI_Lib.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
CScriptCallback::CScriptCallback(void)
@ -48,37 +50,9 @@ int3 CScriptCallback::getPos(CGObjectInstance * ob)
{
return ob->pos;
}
void CScriptCallback::changePrimSkill(int ID, int which, int val)
{
//CGHeroInstance * hero = gh->gs->map->getHero(ID,0);
//if (which<PRIMARY_SKILLS)
//{
// hero->primSkills[which]+=val;
// sv->playerint[hero->getOwner()]->heroPrimarySkillChanged(hero, which, val);
//}
//else if (which==4)
//{
// hero->exp+=val;
// if(hero->exp >= CGI->heroh->reqExp(hero->level+1)) //new level
// {
// hero->level++;
// std::cout << hero->name <<" got level "<<hero->level<<std::endl;
// int r = rand()%100, pom=0, x=0;
// int std::pair<int,int>::*g = (hero->level>9) ? (&std::pair<int,int>::second) : (&std::pair<int,int>::first);
// for(;x<PRIMARY_SKILLS;x++)
// {
// pom += hero->type->heroClass->primChance[x].*g;
// if(r<pom)
// break;
// }
// std::cout << "Bohater dostaje umiejetnosc pierwszorzedna " << x << " (wynik losowania "<<r<<")"<<std::endl;
// hero->primSkills[x]++;
// //TODO: dac dwie umiejetnosci 2-rzedne to wyboru
// }
// //TODO - powiadomic interfejsy, sprawdzic czy nie ma awansu itp
//}
void CScriptCallback::changePrimSkill(int ID, int which, int val, bool abs)
{
gh->changePrimSkill(ID, which, val, abs);
}
int CScriptCallback::getHeroOwner(int heroID)
@ -116,7 +90,7 @@ void CScriptCallback::showSelDialog(int player, std::string text, std::vector<CS
}
int CScriptCallback::getSelectedHero()
{
int ret;
//int ret;
//if (LOCPLINT->adventureInt->selection.type == HEROI_TYPE)
// ret = ((CGHeroInstance*)(LOCPLINT->adventureInt->selection.selected))->subID;
//else
@ -135,11 +109,9 @@ void CScriptCallback::giveResource(int player, int which, int val)
sr.val = (gh->gs->players[player].resources[which]+val);
gh->sendAndApply(&sr);
}
void CScriptCallback::showCompInfo(int player, SComponent * comp)
void CScriptCallback::showCompInfo(ShowInInfobox * comp)
{
//CPlayerInterface * i = dynamic_cast<CPlayerInterface*>(sv->playerint[player]);
//if(i)
// i->showComp(*comp);
gh->sendToAllClients(comp);
}
void CScriptCallback::heroVisitCastle(int obj, int heroID)
{
@ -195,11 +167,12 @@ void CScriptCallback::giveHeroArtifact(int artid, int hid, int position) //pos==
void CScriptCallback::startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) //use hero=NULL for no hero
{
//gh->gs->battle(army1,army2,tile,hero1,hero2);
boost::thread(boost::bind(&CGameHandler::startBattle,gh,*(CCreatureSet *)army1,*(CCreatureSet *)army2,tile,(CGHeroInstance *)hero1,(CGHeroInstance *)hero2));
}
void CScriptCallback::startBattle(int heroID, CCreatureSet * army, int3 tile) //for hero<=>neutral army
void CScriptCallback::startBattle(int heroID, CCreatureSet army, int3 tile) //for hero<=>neutral army
{
//CGHeroInstance* h = gh->gs->map->getHero(heroID,0);
CGHeroInstance* h = const_cast<CGHeroInstance*>(getHero(heroID));
startBattle(&h->army,&army,tile,h,NULL);
//gh->gs->battle(&h->army,army,tile,h,NULL);
}
void CLuaCallback::registerFuncs(lua_State * L)

View File

@ -15,6 +15,7 @@ class CGameState;
struct lua_State;
struct MetaString;
struct InfoWindow;
struct ShowInInfobox;
class CScriptCallback
{
CScriptCallback(void);
@ -35,16 +36,16 @@ public:
void setBlockVis(int objid, bool bv);
void setOwner(int objid, ui8 owner);
void setHoverName(int objid, MetaString * name);
void changePrimSkill(int ID, int which, int val);
void changePrimSkill(int ID, int which, int val, bool abs=false);
void showInfoDialog(InfoWindow *iw);
void showSelDialog(int player, std::string text, std::vector<CSelectableComponent*>*components, IChosen * asker);
void giveResource(int player, int which, int val);
void showCompInfo(int player, SComponent * comp);
void showCompInfo(ShowInInfobox * comp);
void heroVisitCastle(int obj, int heroID);
void stopHeroVisitCastle(int obj, int heroID);
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack
void startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2); //use hero=NULL for no hero
void startBattle(int heroID, CCreatureSet * army, int3 tile); //for hero<=>neutral army
void startBattle(int heroID, CCreatureSet army, int3 tile); //for hero<=>neutral army
//friends
friend class CGameHandler;