diff --git a/CCallback.cpp b/CCallback.cpp index 650eb4b19..bddd033b7 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -112,7 +112,7 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount //verify bool found = false; typedef std::pair Parka; - for(std::map::iterator av=t->strInfo.creatures.begin();av!=t->strInfo.creatures.end();av++) + for(std::map::iterator av=t->strInfo.creatures.begin();av!=t->strInfo.creatures.end();av++) { if( ( found = (ID == t->town->basicCreatures[av->first]) ) //creature is available among basic cretures || (found = (ID == t->town->upgradedCreatures[av->first])) )//creature is available among upgraded cretures @@ -172,11 +172,9 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount bool CCallback::dismissCreature(const CArmedInstance *obj, int stackPos) { - if((player>=0) && obj->tempOwner != player) + if(((player>=0) && obj->tempOwner != player) || obj->army.slots.size()<2) return false; - CArmedInstance *ob = const_cast(obj); - ob->army.slots.erase(stackPos); - cl->playerint[player]->garrisonChanged(obj); + *cl->serv << ui16(503) << obj->id << ui8(stackPos); return true; } bool CCallback::upgradeCreature(const CArmedInstance *obj, int stackPos, int newID) @@ -202,7 +200,7 @@ UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos) t = static_cast(const_cast(obj)); else t = static_cast(obj)->visitedTown; - for(std::set::iterator i=t->builtBuildings.begin(); i!=t->builtBuildings.end(); i++) + for(std::set::iterator i=t->builtBuildings.begin(); i!=t->builtBuildings.end(); i++) { if( (*i) >= 37 && (*i) < 44 ) //upgraded creature dwelling { @@ -283,7 +281,7 @@ int CCallback::getResourceAmount(int type) { return gs->players[player].resources[type]; } -std::vector CCallback::getResourceAmount() +std::vector CCallback::getResourceAmount() { return gs->players[player].resources; } @@ -472,31 +470,19 @@ bool CCallback::swapArifacts(const CGHeroInstance * hero1, bool worn1, int pos1, return true; } -bool CCallback::buildBuilding(const CGTownInstance *town, int buildingID) +bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID) { CGTownInstance * t = const_cast(town); - CBuilding *b = CGI->buildh->buildings[t->subID][buildingID]; - if(0/*not allowed*/)//TODO: check if we are allowed to build + if(town->tempOwner!=player) return false; - - if(buildingID>36) //upg dwelling - { - if(t->getHordeLevel(0) == (buildingID-37)) - t->builtBuildings.insert(19); - else if(t->getHordeLevel(1) == (buildingID-37)) - t->builtBuildings.insert(25); - } - else if(buildingID >= 30) //bas. dwelling - { - t->strInfo.creatures[buildingID-30] = CGI->creh->creatures[t->town->basicCreatures[buildingID-30]].growth; - } - - t->builtBuildings.insert(buildingID); + CBuilding *b = CGI->buildh->buildings[t->subID][buildingID]; for(int i=0;i<7;i++) - gs->players[player].resources[i]-=b->resources[i]; - t->builded++; - cl->playerint[player]->buildChanged(town,buildingID,1); + if(b->resources[i] > gs->players[player].resources[i]) + return false; //lack of resources + + *cl->serv << ui16(504) << town->id << buildingID; +//TODO: check if we are allowed to build return true; } diff --git a/CCallback.h b/CCallback.h index c755ccb1e..19c1df86a 100644 --- a/CCallback.h +++ b/CCallback.h @@ -107,7 +107,7 @@ public: int splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val); bool dismissHero(const CGHeroInstance * hero); bool swapArifacts(const CGHeroInstance * hero1, bool worn1, int pos1, const CGHeroInstance * hero2, bool worn2, int pos2); - bool buildBuilding(const CGTownInstance *town, int buildingID); + bool buildBuilding(const CGTownInstance *town, si32 buildingID); void recruitCreatures(const CGObjectInstance *obj, int ID, int amount); bool dismissCreature(const CArmedInstance *obj, int stackPos); bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1); @@ -119,7 +119,7 @@ public: std::vector< std::vector< std::vector > > & getVisibilityMap(); //returns visibility map (TODO: make it const) const CGHeroInstance * getHeroInfo(int player, int val, bool mode); //mode = 0 -> val = serial; mode = 1 -> val = ID int getResourceAmount(int type); - std::vector getResourceAmount(); + std::vector getResourceAmount(); int howManyHeroes(); const CGTownInstance * getTownInfo(int val, bool mode); //mode = 0 -> val = serial; mode = 1 -> val = ID std::vector < const CGTownInstance *> getTownsInfo(bool onlyOur=true); diff --git a/CCastleInterface.cpp b/CCastleInterface.cpp index f404293fc..aba56f1d0 100644 --- a/CCastleInterface.cpp +++ b/CCastleInterface.cpp @@ -533,7 +533,7 @@ void CCastleInterface::recreateBuildings() std::set< std::pair > s; //group - id - for (std::set::const_iterator i=town->builtBuildings.begin();i!=town->builtBuildings.end();i++) + for (std::set::const_iterator i=town->builtBuildings.begin();i!=town->builtBuildings.end();i++) { if(CGI->townh->structures.find(town->subID) != CGI->townh->structures.end()) //we have info about structures in this town { diff --git a/CGameState.cpp b/CGameState.cpp index 882eeff47..6f269d7be 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -128,6 +128,13 @@ void CGameState::apply(IPack * pack) players[sr->player].resources[sr->resid] = sr->val; break; } + case 104: + { + SetResources *sr = static_cast(pack); + for(int i=0;sr->res.size();i++) + players[sr->player].resources[i] = sr->res[i]; + break; + } case 501://hero try-move { TryMoveHero * n = static_cast(pack); @@ -148,6 +155,21 @@ void CGameState::apply(IPack * pack) static_cast(map->objects[i->first])->army = i->second; break; } + case 503: + { + SetStrInfo *ssi = static_cast(pack); + static_cast(map->objects[ssi->tid])->strInfo.creatures = ssi->cres; + break; + } + case 504: + { + NewStructures *ns = static_cast(pack); + CGTownInstance*t = static_cast(map->objects[ns->tid]); + BOOST_FOREACH(si32 bid,ns->bid) + t->builtBuildings.insert(bid); + t->builded = ns->builded; + break; + } case 1001://set object property { SetObjectProperty *p = static_cast(pack); diff --git a/CGameState.h b/CGameState.h index 0d01d6db2..73ccd8c32 100644 --- a/CGameState.h +++ b/CGameState.h @@ -33,9 +33,9 @@ namespace boost struct DLL_EXPORT PlayerState { public: - int color, serial; - std::vector > > fogOfWarMap; //true - visible, false - hidden - std::vector resources; + ui8 color, serial; + std::vector > > fogOfWarMap; //true - visible, false - hidden + std::vector resources; std::vector heroes; std::vector towns; PlayerState():color(-1){}; diff --git a/CMT.cpp b/CMT.cpp index 9c637e9fa..a59361428 100644 --- a/CMT.cpp +++ b/CMT.cpp @@ -31,7 +31,6 @@ #include "hch/CHeroHandler.h" #include "hch/CCreatureHandler.h" #include "hch/CSpellHandler.h" -#include "hch/CBuildingHandler.h" #include "hch/CMusicHandler.h" #include "hch/CLodHandler.h" #include "hch/CDefHandler.h" @@ -106,6 +105,7 @@ int _tmain(int argc, _TCHAR* argv[]) CGI->heroh = VLC->heroh; CGI->objh = VLC->objh; CGI->dobjinfo = VLC->dobjinfo; + CGI->buildh = VLC->buildh; THC std::cout<<"Initializing VCMI_Lib: "<spellh = spellh; THC std::cout<<"\tSpell handler: "<loadBuildings(); - cgi->buildh = buildh; - THC std::cout<<"\tBuilding handler: "<pathf = new CPathfinder(); THC std::cout<<"\tPathfinder: "<screenh->updateScreen(); + + pim->lock(); + int tv = th.getDif(); for (int i=0;ishow(); + pim->unlock(); //SDL_Flip(screen); CSDL_Ext::update(screen); SDL_Delay(5); //give time for other apps @@ -1137,6 +1146,7 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details) //initializing objects and performing first step of move CGHeroInstance * ho = details.ho; //object representing this hero int3 hp = details.src; + boost::unique_lock un(*pim); if (!details.successful) { ho->moveDir = getDir(details.src,details.dst); @@ -1878,6 +1888,7 @@ void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownIn } void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj) { + boost::unique_lock un(*pim); if(obj->ID == 34) //hero { const CGHeroInstance * hh; @@ -1922,6 +1933,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, return; if(castleInt->town!=town) return; + boost::unique_lock un(*pim); switch(what) { case 1: diff --git a/CPlayerInterface.h b/CPlayerInterface.h index b529faeaf..9ec210c0b 100644 --- a/CPlayerInterface.h +++ b/CPlayerInterface.h @@ -25,6 +25,11 @@ class CCreatureSet; class CGObjectInstance; class CSlider; +namespace boost +{ + class mutex; +}; + class IShowable { public: @@ -292,6 +297,7 @@ class CPlayerInterface : public CGameInterface { public: //minor interfaces + boost::mutex *pim; bool makingTurn; SDL_Event * current; IActivable *curint; @@ -356,6 +362,7 @@ public: void showInfoDialog(std::string text, std::vector & components); CPlayerInterface(int Player, int serial);//c-tor + ~CPlayerInterface();//d-tor }; class CStatusBar : public CIntObject, public IStatusBar diff --git a/client/Client.cpp b/client/Client.cpp index 88bbc236d..b2642cd2e 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -11,6 +11,7 @@ #include "../lib/NetPacks.h" #include #include +#include #include "../hch/CObjectHandler.h" #include "../hch/CGeneralTextHandler.h" #include "../hch/CArtHandler.h" @@ -190,6 +191,15 @@ void CClient::process(int what) playerint[iw.player]->showInfoDialog(toString(iw.text),comps); break; } + case 104: + { + SetResources sr; + *serv >> sr; + std::cout << "Set amount of resources of player "<<(unsigned)sr.player<apply(&sr); + playerint[sr.player]->receivedResource(-1,-1); + break; + } case 501: //hero movement response - we have to notify interfaces and callback { TryMoveHero *th = new TryMoveHero; //will be deleted by callback after processing @@ -235,6 +245,23 @@ void CClient::process(int what) playerint[gs->map->objects[i->first]->tempOwner]->garrisonChanged(gs->map->objects[i->first]); break; } + case 503: + { + SetStrInfo ssi; + *serv >> ssi; + gs->apply(&ssi); + //TODO: notify interfaces + break; + } + case 504: + { + NewStructures ns; + *serv >> ns; + gs->apply(&ns); + BOOST_FOREACH(si32 bid, ns.bid) + playerint[gs->map->objects[ns.tid]->tempOwner]->buildChanged(static_cast(gs->map->objects[ns.tid]),bid,1); + break; + } case 1001: { SetObjectProperty sop; diff --git a/hch/CBuildingHandler.cpp b/hch/CBuildingHandler.cpp index 3d74bedf4..50c020d27 100644 --- a/hch/CBuildingHandler.cpp +++ b/hch/CBuildingHandler.cpp @@ -28,6 +28,7 @@ unsigned int readNr(std::string &in, unsigned int &it) CBuilding * readBg(std::string &buf, unsigned int& it) { CBuilding * nb = new CBuilding(); + nb->resources.resize(RESOURCE_QUANTITY); for(int res=0;res<7;res++) nb->resources[res] = readNr(buf,it); nb->refName = readTo(buf,it,'\n'); diff --git a/hch/CBuildingHandler.h b/hch/CBuildingHandler.h index e28fd9898..00941d42c 100644 --- a/hch/CBuildingHandler.h +++ b/hch/CBuildingHandler.h @@ -2,13 +2,14 @@ #define CBUILDINGHANDLER_H #include "../global.h" #include +#include //enum EbuildingType {NEUTRAL=-1, CASTLE, RAMPART, TOWER, INFERNO, NECROPOLIS, DUNGEON, STRONGHOLD, FORTRESS, CONFLUX}; class DLL_EXPORT CBuilding //a typical building encountered in every castle ;] { public: std::string name; std::string refName; //reference name, for identification - int resources[7]; + std::vector resources; std::string description; //EbuildingType type; //type of building (occures in many castles or is specific for one castle) //bool isDwelling; //true, if this building is a dwelling diff --git a/hch/CCreatureHandler.cpp b/hch/CCreatureHandler.cpp index 2a45a811a..02b418d38 100644 --- a/hch/CCreatureHandler.cpp +++ b/hch/CCreatureHandler.cpp @@ -45,13 +45,13 @@ bool CCreature::isFlying() { return boost::algorithm::find_first(abilityRefs, "FLYING_ARMY"); } -int CCreature::maxAmount(const std::vector &res) const //how many creatures can be bought +si32 CCreature::maxAmount(const std::vector &res) const //how many creatures can be bought { int ret = 2147483645; int resAmnt = std::min(res.size(),cost.size()); for(int i=0;i &res) const; //how many creatures can be bought + si32 maxAmount(const std::vector &res) const; //how many creatures can be bought static int getQuantityID(int quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion }; diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index 3e2929587..578e5ece3 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -140,12 +140,17 @@ public: const CGHeroInstance * garrisonHero, *visitingHero; int identifier; //special identifier from h3m (only > RoE maps) int alignment; - std::set forbiddenBuildings, builtBuildings; + std::set forbiddenBuildings, builtBuildings; std::vector possibleSpells, obligatorySpells, availableSpells; struct StrInfo { - std::map creatures; //level - available amount + std::map creatures; //level - available amount + + template void serialize(Handler &h, const int version) + { + h & creatures; + } } strInfo; std::set events; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 21a0a0d34..257d20b9d 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -71,6 +71,17 @@ struct SetResource : public CPack //102 h & player & resid & val; } }; +struct SetResources : public CPack //104 +{ + SetResources(){type = 104;}; + ui8 player; + std::vector res; //res[resid] => res amount + + template void serialize(Handler &h, const int version) + { + h & player & res; + } +}; struct TryMoveHero : public CPack //501 { TryMoveHero(){type = 501;}; @@ -95,6 +106,29 @@ struct SetGarrisons : public CPack //502 h & garrs; } }; +struct SetStrInfo : public CPack //503 +{ + SetStrInfo(){type = 503;}; + si32 tid; + std::map cres; + + template void serialize(Handler &h, const int version) + { + h & tid & cres; + } +}; +struct NewStructures : public CPack //504 +{ + NewStructures(){type = 504;}; + si32 tid; + std::set bid; + si16 builded; + + template void serialize(Handler &h, const int version) + { + h & tid & bid & builded; + } +}; struct MetaString : public CPack //2001 helper for object scrips { std::vector strings; diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index f1f7bb40e..c6e208609 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -7,6 +7,7 @@ #include "../hch/CHeroHandler.h" #include "../hch/CObjectHandler.h" #include "../hch/CTownHandler.h" +#include "../hch/CBuildingHandler.h" class CLodHandler; LibClasses * VLC = NULL; CLodHandler * bitmaph=NULL; @@ -45,6 +46,10 @@ DLL_EXPORT void initDLL(CLodHandler *b) VLC->dobjinfo = new CDefObjInfoHandler; VLC->dobjinfo->load(); THC std::cout<<"\tDef information handler: "<buildh = new CBuildingHandler; + VLC->buildh->loadBuildings(); + THC std::cout<<"\tBuilding handler: "< #include -std::set convertBuildings(const std::set h3m, int castleID) +std::set convertBuildings(const std::set h3m, int castleID) { std::map mapa; - std::set ret; + std::set ret; std::ifstream b5("config/buildings5.txt"); while(!b5.eof()) { @@ -20,7 +20,7 @@ std::set convertBuildings(const std::set h3m, int castleID) mapa[a]=b; } - for(std::set::const_iterator i=h3m.begin();i!=h3m.end();i++) + for(std::set::const_iterator i=h3m.begin();i!=h3m.end();i++) { if(mapa[*i]>=0) ret.insert(mapa[*i]); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 506068df9..b2c132669 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -13,6 +13,7 @@ #include "../CLua.h" #include "../hch/CObjectHandler.h" #include "../hch/CTownHandler.h" +#include "../hch/CBuildingHandler.h" #include "../hch/CHeroHandler.h" #include "boost/date_time/posix_time/posix_time_types.hpp" //no i/o just types #include "../lib/VCMI_Lib.h" @@ -223,6 +224,61 @@ void CGameHandler::handleConnection(std::set players, CConnection &c) if(s1 != s2) sg.garrs[id2] = *S2; sendAndApply(&sg); + break; + } + case 503: + { + si32 id; + ui8 pos; + c >> id >> pos; + CArmedInstance *s1 = static_cast(gs->map->objects[id]); + s1->army.slots.erase(pos); + SetGarrisons sg; + sg.garrs[id] = s1->army; + sendAndApply(&sg); + break; + } + case 504: + { + si32 tid, bid; + c >> tid >> bid; + CGTownInstance * t = static_cast(gs->map->objects[tid]); + CBuilding * b = VLC->buildh->buildings[t->subID][bid]; + for(int i=0;iresources[i] > gs->players[t->tempOwner].resources[i]) + break; //no res + //TODO: check requirements + //TODO: check if building isn't forbidden + + NewStructures ns; + ns.tid = tid; + if(bid>36) //upg dwelling + { + if(t->getHordeLevel(0) == (bid-37)) + ns.bid.insert(19); + else if(t->getHordeLevel(1) == (bid-37)) + ns.bid.insert(25); + } + else if(bid >= 30) //bas. dwelling + { + SetStrInfo ssi; + ssi.tid = tid; + ssi.cres = t->strInfo.creatures; + ssi.cres[bid-30] = VLC->creh->creatures[t->town->basicCreatures[bid-30]].growth; + sendAndApply(&ssi); + } + + ns.bid.insert(bid); + ns.builded = t->builded + 1; + sendAndApply(&ns); + + SetResources sr; + sr.player = t->tempOwner; + sr.res = gs->players[t->tempOwner].resources; + for(int i=0;i<7;i++) + sr.res[i]-=b->resources[i]; + sendAndApply(&sr); + break; } default: diff --git a/server/CScriptCallback.cpp b/server/CScriptCallback.cpp index 69581f6fd..483c5ff5c 100644 --- a/server/CScriptCallback.cpp +++ b/server/CScriptCallback.cpp @@ -121,7 +121,7 @@ int CScriptCallback::getSelectedHero() // ret = ((CGHeroInstance*)(LOCPLINT->adventureInt->selection.selected))->subID; //else // ret = -1;; - return ret; + return -1; } int CScriptCallback::getDate(int mode) {