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

* partial support for Haste spell

* started making external settings file (will be used for support for non 800x600 screen resolutions)
* minor changes
This commit is contained in:
Michał W. Urbańczyk 2008-11-08 22:29:19 +00:00
parent ceb3cf8eae
commit a1606b2fb3
15 changed files with 422 additions and 102 deletions

View File

@ -1,32 +1,33 @@
#include "stdafx.h"
#include "AdventureMapButton.h"
#include "CAdvmapInterface.h"
#include "client/CBitmapHandler.h"
#include "CPlayerInterface.h"
#include "CCallback.h"
#include "CCastleInterface.h"
#include "CCursorHandler.h"
#include "hch/CPreGameTextHandler.h"
#include "hch/CGeneralTextHandler.h"
#include "hch/CDefHandler.h"
#include "hch/CTownHandler.h"
#include "CPathfinder.h"
#include "CGameInfo.h"
#include "SDL_Extensions.h"
#include "CCallback.h"
#include <boost/assign/std/vector.hpp>
#include "mapHandler.h"
#include "CHeroWindow.h"
#include "CMessage.h"
#include "CPathfinder.h"
#include "CPlayerInterface.h"
#include "SDL_Extensions.h"
#include "client/CBitmapHandler.h"
#include "client/CConfigHandler.h"
#include "client/CSpellWindow.h"
#include "client/Graphics.h"
#include "hch/CDefHandler.h"
#include "hch/CGeneralTextHandler.h"
#include "hch/CHeroHandler.h"
#include "hch/CObjectHandler.h"
#include "hch/CPreGameTextHandler.h"
#include "hch/CTownHandler.h"
#include "lib/CondSh.h"
#include "map.h"
#include "mapHandler.h"
#include "stdafx.h"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/replace.hpp>
#include "hch/CHeroHandler.h"
#include <sstream>
#include "AdventureMapButton.h"
#include "CHeroWindow.h"
#include "client/Graphics.h"
#include "hch/CObjectHandler.h"
#include <boost/assign/std/vector.hpp>
#include <boost/thread.hpp>
#include "map.h"
#include "client/CSpellWindow.h"
#include "lib/CondSh.h"
#include <sstream>
#pragma warning (disable : 4355)
extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX; //fonts
@ -1309,8 +1310,8 @@ void CAdvMapInt::handleRightClick(std::string text, tribool down, CIntObject * c
{
boost::algorithm::erase_all(text,"\"");
CSimpleWindow * temp = CMessage::genWindow(text,LOCPLINT->playerID);
temp->pos.x=300-(temp->pos.w/2);
temp->pos.y=300-(temp->pos.h/2);
temp->pos.x=screen->w/2-(temp->pos.w/2);
temp->pos.y=screen->h/2-(temp->pos.h/2);
temp->owner = client;
LOCPLINT->objsToBlit.push_back(temp);
}

View File

@ -426,7 +426,7 @@ void CBattleInterface::show(SDL_Surface * to)
//showing queue of stacks
if(showStackQueue)
{
int xPos = 400 - ( stacks.size() * 37 )/2;
int xPos = screen->w/2 - ( stacks.size() * 37 )/2;
int yPos = 10;
std::vector<CStack> stacksSorted;
@ -1238,7 +1238,7 @@ void CBattleInterface::spellCasted(SpellCasted * sc)
//animation angle
float angle = atan2(float(destcoord.first - srccoord.first), float(destcoord.second - srccoord.second));
//choosign animation by angle
//choosing animation by angle
if(angle > 1.50)
animToDisplay = anims[0];
else if(angle > 1.20)
@ -1272,6 +1272,9 @@ void CBattleInterface::spellCasted(SpellCasted * sc)
int b=0;
break;
}
case 53://haste
displayEffect(31,sc->tile,LOCPLINT->cb->battleGetStackByPos(sc->tile)->owner);
break;
}
}
@ -1817,8 +1820,8 @@ void CBattleHex::clickRight(boost::logic::tribool down)
const CGHeroInstance *h = myst.owner == myInterface->attackingHeroInstance->tempOwner ? myInterface->attackingHeroInstance : myInterface->defendingHeroInstance;
if(h)
{
pom->attackBonus = h->primSkills[0];
pom->defenseBonus = h->primSkills[1];
pom->attackBonus = h->getPrimSkillLevel(0);
pom->defenseBonus = h->getPrimSkillLevel(1);
pom->luck = h->getCurrentLuck();
pom->morale = h->getCurrentMorale();
pom->shotsLeft = myst.shots;

View File

@ -248,6 +248,36 @@ CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
state.insert(ALIVE);
}
ui32 CStack::speed()
{
int premy=0;
StackEffect *effect = 0;
//haste effect check
effect = getEffect(53);
if(effect)
premy += VLC->spellh->spells[effect->id].powers[effect->level];
//slow effect check
effect = getEffect(54);
if(effect)
premy -= VLC->spellh->spells[effect->id].powers[effect->level];
//prayer effect check
effect = getEffect(48);
if(effect)
premy -= VLC->spellh->spells[effect->id].powers[effect->level];
//bind effect check
effect = getEffect(72);
if(effect)
premy = -creature->speed;
return creature->speed + premy;
}
CStack::StackEffect * CStack::getEffect(ui16 id)
{
for (int i=0; i< effects.size(); i++)
if(effects[i].id == id)
return &effects[i];
return NULL;
}
CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, int notThatOne)
{
if(player<0 || player>=PLAYER_LIMIT)
@ -705,6 +735,13 @@ void CGameState::applyNL(IPack * pack)
//TODO: counter
break;
}
case 3010:
{
SetStackEffect *sc = static_cast<SetStackEffect*>(pack);
CStack *stack = curB->getStack(sc->stack);
stack->effects.push_back(sc->effect);
break;
}
}
}
void CGameState::apply(IPack * pack)

View File

@ -96,10 +96,22 @@ public:
std::set<EAbilities> abilities;
std::set<ECombatInfo> state;
struct StackEffect
{
ui16 id; //spell id
ui8 level; //skill level
ui16 turnsRemain;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & level & turnsRemain;
}
};
std::vector<StackEffect> effects;
CStack(CCreature * C, int A, int O, int I, bool AO, int S);
CStack() : creature(NULL),amount(-1),owner(255), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1), slot(255), baseAmount(-1), counterAttacks(1){};
StackEffect * getEffect(ui16 id); //effect id (SP)
ui32 speed();
template <typename Handler> void save(Handler &h, const int version)
{
h & creature->idNumber;

58
CMT.cpp
View File

@ -41,6 +41,7 @@
#include "hch/CGeneralTextHandler.h"
#include "client/Graphics.h"
#include "client/Client.h"
#include "client/CConfigHandler.h"
#include "lib/Connection.h"
#include "lib/Interprocess.h"
#include "lib/VCMI_Lib.h"
@ -59,49 +60,30 @@ int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char** argv)
#endif
{
tlog0 << "Starting... " << std::endl;
THC timeHandler tmh, total, pomtime;
CClient *client = NULL;
boost::thread *console = NULL;
if(argc>2)
{
std::cout << "Special mode without new support for console!" << std::endl;
}
else
{
logfile = new std::ofstream("VCMI_Client_log.txt");
::console = new CConsoleHandler;
*::console->cb = boost::bind(processCommand,_1,boost::ref(client));
console = new boost::thread(boost::bind(&CConsoleHandler::run,::console));
}
tlog0 << "\tConsole and logifle ready!" << std::endl;
int port;
if(argc > 1)
{
#ifdef _MSC_VER
port = _tstoi(argv[1]);
#else
port = _ttoi(argv[1]);
#endif
}
else
{
port = 3030;
tlog0 << "Port " << port << " will be used." << std::endl;
}
std::cout.flags(ios::unitbuf);
logfile = new std::ofstream("VCMI_Client_log.txt");
::console = new CConsoleHandler;
*::console->cb = boost::bind(processCommand,_1,boost::ref(client));
console = new boost::thread(boost::bind(&CConsoleHandler::run,::console));
tlog0 <<"Creating console and logfile: "<<pomtime.getDif() << std::endl;
conf.init();
tlog0 <<"Loading settings: "<<pomtime.getDif() << std::endl;
tlog0 << NAME << std::endl;
srand ( time(NULL) );
CPG=NULL;
atexit(SDL_Quit);
CGameInfo * cgi = CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler itp.)
//CLuaHandler luatest;
//luatest.test();
//CBIKHandler cb;
//cb.open("CSECRET.BIK");
tlog0 << "Starting... " << std::endl;
THC timeHandler tmh, total, pomtime;
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO)==0)
{
screen = SDL_SetVideoMode(800,600,24,SDL_SWSURFACE|SDL_DOUBLEBUF/*|SDL_FULLSCREEN*/); //initializing important global surface
screen = SDL_SetVideoMode(conf.cc.resx,conf.cc.resy,conf.cc.bpp,SDL_SWSURFACE|SDL_DOUBLEBUF|(conf.cc.fullscreen?SDL_FULLSCREEN:0)); //initializing important global surface
tlog0 <<"\tInitializing screen: "<<pomtime.getDif();
tlog0 << std::endl;
SDL_WM_SetCaption(NAME.c_str(),""); //set window title
@ -124,13 +106,13 @@ int main(int argc, char** argv)
mush->initMusics();
//audio initialized
cgi->mush = mush;
THC tlog0<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
THC tlog0<<"Initializing screen, fonts and sound handling: "<<tmh.getDif()<<std::endl;
tlog0<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
tlog0<<"Initializing screen, fonts and sound handling: "<<tmh.getDif()<<std::endl;
CDefHandler::Spriteh = cgi->spriteh = new CLodHandler();
cgi->spriteh->init("Data" PATHSEPARATOR "H3sprite.lod","Sprites");
BitmapHandler::bitmaph = cgi->bitmaph = new CLodHandler;
cgi->bitmaph->init("Data" PATHSEPARATOR "H3bitmap.lod","Data");
THC tlog0<<"Loading .lod files: "<<tmh.getDif()<<std::endl;
tlog0<<"Loading .lod files: "<<tmh.getDif()<<std::endl;
initDLL(cgi->bitmaph,::console,logfile);
CGI->arth = VLC->arth;
CGI->creh = VLC->creh;
@ -171,7 +153,7 @@ int main(int argc, char** argv)
StartInfo *options = new StartInfo(cpg->runLoop());
tmh.getDif();
////////////////////////SERVER STARTING/////////////////////////////////////////////////
char portc[10]; SDL_itoa(port,portc,10);
char portc[10]; SDL_itoa(conf.cc.port,portc,10);
intpr::shared_memory_object smo(intpr::open_or_create,"vcmi_memory",intpr::read_write);
smo.truncate(sizeof(ServerReady));
intpr::mapped_region mr(smo,intpr::read_write);
@ -203,7 +185,7 @@ int main(int argc, char** argv)
try
{
tlog0 << "Establishing connection...\n";
c = new CConnection("127.0.0.1",portc,NAME,logs);
c = new CConnection(conf.cc.server,portc,NAME,logs);
}
catch(...)
{

View File

@ -426,8 +426,8 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player, int
ret->bitmap = drawBox1(txts.first+70,txts.second+70,0);
ret->pos.h=ret->bitmap->h;
ret->pos.w=ret->bitmap->w;
ret->pos.x=400-(ret->pos.w/2);
ret->pos.y=300-(ret->pos.h/2);
ret->pos.x=screen->w/2-(ret->pos.w/2);
ret->pos.y=screen->h/2-(ret->pos.h/2);
int curh = 30; //gorny margines
blitTextOnSur(txtg,curh,ret->bitmap);
if (ret->components.size())

View File

@ -287,7 +287,8 @@ void CGarrisonSlot::show()
}
else
{
SDL_Rect jakis1 = genRect(pos.h,pos.w,owner->offx+ID*(pos.w+owner->interx),owner->offy+upg*(pos.h+owner->intery)), jakis2 = pos;
SDL_Rect jakis1 = genRect(pos.h,pos.w,owner->offx+ID*(pos.w+owner->interx),owner->offy+upg*(pos.h+owner->intery)),
jakis2 = pos;
SDL_BlitSurface(owner->sur,&jakis1,screen,&jakis2);
if(owner->splitting)
blitAt(graphics->bigImgs[-1],pos);
@ -382,7 +383,8 @@ void CGarrisonInt::createSlots()
i!=set1->slots.end(); i++)
{
(*sup)[i->first] =
new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y,i->first, 0, &CGI->creh->creatures[i->second.first],i->second.second);
new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y,i->first, 0,
&CGI->creh->creatures[i->second.first],i->second.second);
}
for(int i=0; i<sup->size(); i++)
if((*sup)[i] == NULL)
@ -396,7 +398,8 @@ void CGarrisonInt::createSlots()
i!=set2->slots.end(); i++)
{
(*sdown)[i->first] =
new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y + 64 + intery,i->first,1, &CGI->creh->creatures[i->second.first],i->second.second);
new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y + 64 + intery,i->first,1,
&CGI->creh->creatures[i->second.first],i->second.second);
}
for(int i=0; i<sup->size(); i++)
if((*sdown)[i] == NULL)
@ -464,7 +467,8 @@ void CGarrisonInt::splitStacks(int am2)
am2);
}
CGarrisonInt::CGarrisonInt(int x, int y, int inx, int iny, SDL_Surface *pomsur, int OX, int OY, const CArmedInstance *s1, const CArmedInstance *s2)
CGarrisonInt::CGarrisonInt(int x, int y, int inx, int iny, SDL_Surface *pomsur, int OX, int OY, const CArmedInstance *s1,
const CArmedInstance *s2)
:interx(inx),intery(iny),sur(pomsur),highlighted(NULL),sup(NULL),sdown(NULL),oup(s1),odown(s2),
offx(OX),offy(OY)
{
@ -2527,13 +2531,16 @@ void CHeroList::clickRight(tribool down)
}
//show popup
CInfoPopup * ip = new CInfoPopup(graphics->heroWins[items[from+ny].first->subID],LOCPLINT->current->motion.x-graphics->heroWins[items[from+ny].first->subID]->w,LOCPLINT->current->motion.y-graphics->heroWins[items[from+ny].first->subID]->h,false);
CInfoPopup * ip = new CInfoPopup(graphics->heroWins[items[from+ny].first->subID],
LOCPLINT->current->motion.x-graphics->heroWins[items[from+ny].first->subID]->w,
LOCPLINT->current->motion.y-graphics->heroWins[items[from+ny].first->subID]->h,false
);
ip->activate();
}
else
{
LOCPLINT->adventureInt->handleRightClick(CGI->preth->zelp[303].second,down,this);
LOCPLINT->adventureInt->handleRightClick(CGI->preth->zelp[304].second,down,this);
LOCPLINT->adventureInt->handleRightClick(CGI->preth->zelp[303].second,down,this);
LOCPLINT->adventureInt->handleRightClick(CGI->preth->zelp[304].second,down,this);
}
}
void CHeroList::hover (bool on)
@ -2555,8 +2562,12 @@ void CHeroList::updateHList()
}
void CHeroList::updateMove(const CGHeroInstance* which) //draws move points bar
{
int ser = LOCPLINT->cb->getHeroSerial(which);
int ser = -1;
for(int i=0; i<items.size() && ser<0; i++)
if(items[i].first->subID == which->subID)
ser = i;
ser -= from;
if(ser<0 || ser > SIZE) return;
int pom = std::min((which->movement)/100,(int)mobile->ourImages.size()-1);
blitAt(mobile->ourImages[pom].bitmap,posmobx,posmoby+ser*32); //move point
}

150
client/CConfigHandler.cpp Normal file
View File

@ -0,0 +1,150 @@
//#define BOOST_SPIRIT_DEBUG
#include "CConfigHandler.h"
#include <boost/bind.hpp>
#include <boost/spirit.hpp>
#include <fstream>
using namespace config;
using namespace boost::spirit;
CConfigHandler conf;
struct lerror
{
std::string txt;
lerror(const std::string & TXT):txt(TXT){};
void operator()() const
{
tlog1 << txt << std::endl;
}
template<typename IteratorT>
void operator()(IteratorT t1, IteratorT t2) const
{
tlog1 << txt << std::endl;
}
};
struct lerror2
{
std::string txt;
lerror2(const std::string & TXT):txt(TXT){};
template<typename IteratorT>
void operator()(IteratorT t1, IteratorT t2) const
{
std::string txt2(t1,t2);
tlog1 << txt << txt2 << std::endl;
}
};
//template <typename T, typename U>
//struct AssignInAll
//{
// std::vector<T> &items;
// U T::*pointer;
// AssignInAll(std::vector<T> &Items, U T::*Pointer)
// :items(Items),pointer(Pointer)
// {}
// void operator()(const U &as)
// {
// for(int i=0; i<items.size(); i++)
// items[i].*pointer = U;
// }
//};
struct SettingsGrammar : public grammar<SettingsGrammar>
{
template <typename ScannerT>
struct definition
{
rule<ScannerT> r, clientOption, clientOptionsSequence;
rule<ScannerT> GUIOption, GUIOptionsSequence, AdvMapOptionsSequence, AdvMapOption;
definition(SettingsGrammar const& self)
{
clientOption
= str_p("resolution=") >> (uint_p[assign_a(conf.cc.resx)] >> 'x' >> uint_p[assign_a(conf.cc.resy)] | eps_p[lerror("Wrong resolution!")])
| str_p("port=") >> (uint_p[assign_a(conf.cc.port)] | eps_p[lerror("Wrong port!")])
| str_p("bpp=") >> (uint_p[assign_a(conf.cc.bpp)] | eps_p[lerror("Wrong bpp!")])
| str_p("localInformation=") >> (uint_p[assign_a(conf.cc.localInformation)] | eps_p[lerror("Wrong localInformation!")])
| str_p("fullscreen=") >> (uint_p[assign_a(conf.cc.fullscreen)] | eps_p[lerror("Wrong fullscreen!")])
| str_p("server=") >> ( ( +digit_p >> *('.' >> +digit_p) )[assign_a(conf.cc.server)] | eps_p[lerror("Wrong server!")])
| str_p("defaultAI=") >> ((+(anychar_p - ';'))[assign_a(conf.cc.defaultAI)] | eps_p[lerror("Wrong defaultAI!")])
| (+(anychar_p - '}'))[lerror2("Unrecognized client option: ")]
;
clientOptionsSequence = *(clientOption >> (';' | eps_p[lerror("Semicolon lacking!")]));
AdvMapOption
= str_p("Buttons") >> ((ch_p('{') >> '}') | eps_p[lerror("Wrong Buttons!")])
| str_p("Minimap : ") >>
*(
( "width=" >> uint_p[assign_a(conf.gc.ac.minimap.w)]
| "height=" >> uint_p[assign_a(conf.gc.ac.minimap.h)]
| "x=" >> uint_p[assign_a(conf.gc.ac.minimap.x)]
| "y=" >> uint_p[assign_a(conf.gc.ac.minimap.y)]
)
>> *ch_p(',')
);
AdvMapOptionsSequence = *(AdvMapOption >> (';' | eps_p[lerror("Semicolon lacking!")]));
GUIOption = str_p("AdventureMap") >> (('{' >> AdvMapOptionsSequence >> '}') | eps_p[lerror("Wrong AdventureMap!")]);
GUIOptionsSequence = *(GUIOption >> (';' | eps_p[lerror("Semicolon after GUIOption lacking!")]));
r = str_p("clientSettings") >> (('{' >> clientOptionsSequence >> '}') | eps_p[lerror("Wrong clientSettings!")])
>> str_p("GUISettings") >> (('{' >> GUIOptionsSequence >> '}') | eps_p[lerror("Wrong GUISettings!")]);
#ifdef BOOST_SPIRIT_DEBUG
BOOST_SPIRIT_DEBUG_RULE(clientOption);
BOOST_SPIRIT_DEBUG_RULE(clientOptionsSequence);
BOOST_SPIRIT_DEBUG_RULE(AdvMapOption);
BOOST_SPIRIT_DEBUG_RULE(AdvMapOptionsSequence);
BOOST_SPIRIT_DEBUG_RULE(GUIOption);
BOOST_SPIRIT_DEBUG_RULE(GUIOptionsSequence);
BOOST_SPIRIT_DEBUG_RULE(r);
#endif
}
rule<ScannerT> const& start() const { return r; }
};
};
struct CommentsGrammar : public grammar<CommentsGrammar>
{
template <typename ScannerT>
struct definition
{
rule<ScannerT> comment;
definition(CommentsGrammar const& self)
{
comment = comment_p("//") | comment_p("/*","*/") | space_p;
BOOST_SPIRIT_DEBUG_RULE(comment);
}
rule<ScannerT> const& start() const { return comment; }
};
};
CConfigHandler::CConfigHandler(void)
{
}
CConfigHandler::~CConfigHandler(void)
{
}
void config::CConfigHandler::init()
{
std::vector<char> settings;
std::ifstream ifs("config/settings.txt");
if(!ifs)
{
tlog1 << "Cannot open config/settings.txt !\n";
return;
}
ifs.unsetf(std::ios::skipws); // Turn of white space skipping on the stream
std::copy(std::istream_iterator<char>(ifs),std::istream_iterator<char>(),std::back_inserter(settings));
std::vector<char>::const_iterator first = settings.begin(), last = settings.end();
SettingsGrammar sg;
BOOST_SPIRIT_DEBUG_NODE(sg);
CommentsGrammar cg;
BOOST_SPIRIT_DEBUG_NODE(cg);
parse_info<std::vector<char>::const_iterator> info = parse(first,last,sg,cg);
if(!info.hit)
tlog1 << "Cannot parse config/settings.txt file!\n";
else if(!info.full)
tlog2 << "Not entire config/settings.txt parsed!\n";
}

45
client/CConfigHandler.h Normal file
View File

@ -0,0 +1,45 @@
#pragma once
#include "../global.h"
class CAdvMapInt;
namespace config
{
struct ClientConfig
{
int resx, resy, bpp, fullscreen; //client resolution/colours
int port, localInformation;
std::string server, //server address (e.g. 127.0.0.1)
defaultAI; //dll name
};
struct AdventureMapConfig
{
struct ButtonInfo
{
std::string hoverName, //shows in statusbar when hovered
helpBox, //shows in pop-up when r-clicked
defName;
std::vector<std::string> additionalDefs;
void (CAdvMapInt::*func)(); //function in advmapint bound to that button
int x, y; //position on the screen
bool playerColoured; //if true button will be colored to main player's color (works properly only for appropriate 8bpp graphics)
};
struct Minimap
{
int x, y, w, h;
} minimap;
std::vector<ButtonInfo> buttons;
};
struct GUIOptions
{
AdventureMapConfig ac;
};
class CConfigHandler
{
public:
ClientConfig cc;
GUIOptions gc;
void init();
CConfigHandler(void);
~CConfigHandler(void);
};
}
extern config::CConfigHandler conf;

View File

@ -1,22 +1,23 @@
#include "Client.h"
#include "../lib/Connection.h"
#include "../StartInfo.h"
#include "../map.h"
#include "../CGameState.h"
#include "../CGameInfo.h"
#include "../mapHandler.h"
#include "../CCallback.h"
#include "../CPlayerInterface.h"
#include "../CConsoleHandler.h"
#include "../lib/NetPacks.h"
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include "../hch/CObjectHandler.h"
#include "../hch/CGeneralTextHandler.h"
#include "../CGameInfo.h"
#include "../CGameState.h"
#include "../CPlayerInterface.h"
#include "../StartInfo.h"
#include "../hch/CArtHandler.h"
#include <boost/thread/shared_mutex.hpp>
#include "../hch/CGeneralTextHandler.h"
#include "../hch/CObjectHandler.h"
#include "../lib/Connection.h"
#include "../lib/NetPacks.h"
#include "../lib/VCMI_Lib.h"
#include "../map.h"
#include "../mapHandler.h"
#include "CConfigHandler.h"
#include "Client.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
CSharedCond<std::set<IPack*> > mess(new std::set<IPack*>);
std::string toString(MetaString &ms)
@ -126,11 +127,7 @@ CClient::CClient(CConnection *con, StartInfo *si)
if(mapa->checksum != sum)
{
tlog1 << "Wrong map checksum!!!" << std::endl;
#ifndef __GNUC__
throw std::exception("Wrong checksum");
#else
throw std::exception();
#endif
throw std::string("Wrong checksum");
}
tlog0 << "\tUsing random seed: "<<seed << std::endl;
@ -151,7 +148,7 @@ CClient::CClient(CConnection *con, StartInfo *si)
CCallback *cb = new CCallback(gs,color,this);
if(!gs->scenarioOps->playerInfos[i].human)
{
playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,"EmptyAI.dll"));
playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,conf.cc.defaultAI));
}
else
{
@ -160,7 +157,6 @@ CClient::CClient(CConnection *con, StartInfo *si)
playerint[color]->init(cb);
}
}
//cb = CGI->consoleh->cb = new CCallback(gs,-1,this);
}
CClient::~CClient(void)
{
@ -646,7 +642,23 @@ void CClient::process(int what)
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 3010:
{
tlog5 << "Effect set!\n";
SetStackEffect sse;
*serv >> sse;
gs->apply(&sse);
SpellCasted sc;
sc.id = sse.stack;
sc.side = 3; //doesn't matter
sc.skill = sse.effect.level;
sc.tile = gs->curB->getStack(sse.stack)->position;
if(playerint.find(gs->curB->side1) != playerint.end())
playerint[gs->curB->side1]->battleSpellCasted(&sc);
if(playerint.find(gs->curB->side2) != playerint.end())

View File

@ -294,6 +294,10 @@
RelativePath="..\CCastleInterface.cpp"
>
</File>
<File
RelativePath=".\CConfigHandler.cpp"
>
</File>
<File
RelativePath=".\CCreatureAnimation.cpp"
>
@ -436,6 +440,10 @@
RelativePath="..\CCastleInterface.h"
>
</File>
<File
RelativePath=".\CConfigHandler.h"
>
</File>
<File
RelativePath=".\CCreatureAnimation.h"
>

24
config/settings.txt Normal file
View File

@ -0,0 +1,24 @@
//DO NOT EDIT!!!
//DO NOT READ!
clientSettings
{
port=3030;
resolution=800x600; // format: WxH
bpp=24; // bpp!=24 => problems
fullscreen=0; //0 - windowed mode, 1 - fullscreen
server=127.0.0.1; //use 127.0.0.1 for localhost
localInformation=2; //0 - *all* information sent from server (safest and slowest); 1 - map information sent from server; 2 - all information local-storaged
defaultAI=EmptyAI.dll;
}
GUISettings
{
//800x600 //settings specific for 800x600 resolution
//{
AdventureMap
{
Buttons
{
};
};
//};
}

View File

@ -274,7 +274,7 @@ int CGHeroInstance::manaLimit() const
case 2: modifier+=0.5; break;
case 3: modifier+=1.0; break;
}
return 10*primSkills[3]*modifier;
return 10*getPrimSkillLevel(3)*modifier;
}
//void CGHeroInstance::setPosition(int3 Pos, bool h3m) //as above, but sets position
//{
@ -312,6 +312,11 @@ int CGHeroInstance::getSecSkillLevel(const int & ID) const
}
int lowestSpeed(const CGHeroInstance * chi)
{
if(!chi->army.slots.size())
{
tlog1 << "Error! Hero " << chi->id << " ("<<chi->name<<") has no army!\n";
return 20;
}
std::map<si32,std::pair<ui32,si32> >::const_iterator i = chi->army.slots.begin();
int ret = VLC->creh->creatures[(*i++).second.first].speed;
for (;i!=chi->army.slots.end();i++)
@ -569,7 +574,7 @@ void CGHeroInstance::initHero()
if(portrait < 0)
portrait = subID;
if((!primSkills.size()) || (primSkills[0]<0))
if((!primSkills.size()) || (getPrimSkillLevel(0)<0))
{
primSkills.resize(4);
primSkills[0] = type->heroClass->initialAttack;

View File

@ -543,6 +543,17 @@ struct SpellCasted : public CPack<SpellCasted>//3009
}
};
struct SetStackEffect : public CPack<SetStackEffect> //3010
{
ui32 stack;
CStack::StackEffect effect;
SetStackEffect(){type = 3010;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & stack & effect;
}
};
struct ShowInInfobox : public CPack<ShowInInfobox> //107
{
ShowInInfobox(){type = 107;};

View File

@ -56,6 +56,19 @@ 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) );
}
int getSchoolLevel(const CGHeroInstance *h, const CSpell *s)
{
int ret = 0;
if(s->fire)
ret = std::max(ret,h->getSecSkillLevel(14));
if(s->air)
ret = std::max(ret,h->getSecSkillLevel(15));
if(s->water)
ret = std::max(ret,h->getSecSkillLevel(16));
if(s->earth)
ret = std::max(ret,h->getSecSkillLevel(17));
return ret;
}
void giveExp(BattleResult &r)
{
r.exp[0] = 0;
@ -1224,7 +1237,7 @@ upgend:
BattleStackAttacked bsa;
bsa.flags |= 2;
bsa.effect = 64;
bsa.damageAmount = h->primSkills[2] * 10; //TODO: use skill level
bsa.damageAmount = h->getPrimSkillLevel(2) * 10 + s->powers[getSchoolLevel(h,s)];
bsa.stackAttacked = attacked->ID;
prepareAttacked(bsa,attacked);
sendAndApply(&bsa);
@ -1232,6 +1245,12 @@ upgend:
}
case 53: //haste
{
SetStackEffect sse;
sse.stack = gs->curB->getStackT(ba.destinationTile)->ID;
sse.effect.id = 53;
sse.effect.level = getSchoolLevel(h,s);
sse.effect.turnsRemain = h->getPrimSkillLevel(2);
sendAndApply(&sse);
break;
}
}