diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp new file mode 100644 index 000000000..08a9a8c53 --- /dev/null +++ b/client/NetPacksClient.cpp @@ -0,0 +1,425 @@ +#include "../lib/NetPacks.h" +#include "../CCallback.h" +#include "../client/Client.h" +#include "../CPlayerInterface.h" +#include "../CGameInfo.h" +#include "../hch/CGeneralTextHandler.h" +#include "../hch/CDefObjInfoHandler.h" +#include "../hch/CHeroHandler.h" +#include "../hch/CObjectHandler.h" +#include "../lib/VCMI_Lib.h" +#include "../map.h" +#include "../hch/CSpellHandler.h" +#include "../mapHandler.h" +#include +#include +#include +#include + +//macro to avoid code duplication - calls given method with given arguments if interface for specific player is present +#define INTERFACE_CALL_IF_PRESENT(player,function,...) \ + if(vstd::contains(cl->playerint,player)) \ + cl->playerint[player]->function(__VA_ARGS__); + + +CSharedCond > mess(new std::set); + +void SetResources::applyCl( CClient *cl ) +{ + cl->playerint[player]->receivedResource(-1,-1); +} + +void SetResource::applyCl( CClient *cl ) +{ + cl->playerint[player]->receivedResource(resid,val); +} + +void SetPrimSkill::applyCl( CClient *cl ) +{ + cl->playerint[GS(cl)->getHero(id)->tempOwner]->heroPrimarySkillChanged(GS(cl)->getHero(id),which,val); +} + +void SetSecSkill::applyCl( CClient *cl ) +{ + //TODO: inform interface? +} + +void HeroVisitCastle::applyCl( CClient *cl ) +{ + if(start() && !garrison() && vstd::contains(cl->playerint,GS(cl)->getHero(hid)->tempOwner)) + { + cl->playerint[GS(cl)->getHero(hid)->tempOwner]->heroVisitsTown(GS(cl)->getHero(hid),GS(cl)->getTown(tid)); + } +} + +void ChangeSpells::applyCl( CClient *cl ) +{ + //TODO: inform interface? +} + +void SetMana::applyCl( CClient *cl ) +{ + CGHeroInstance *h = GS(cl)->getHero(hid); + if(vstd::contains(cl->playerint,h->tempOwner)) + cl->playerint[h->tempOwner]->heroManaPointsChanged(h); +} + +void SetMovePoints::applyCl( CClient *cl ) +{ + CGHeroInstance *h = GS(cl)->getHero(hid); + if(vstd::contains(cl->playerint,h->tempOwner)) + cl->playerint[h->tempOwner]->heroMovePointsChanged(h); +} + +void FoWChange::applyCl( CClient *cl ) +{ + if(!vstd::contains(cl->playerint,player)) + return; + + if(mode) + cl->playerint[player]->tileRevealed(tiles); + else + cl->playerint[player]->tileHidden(tiles); +} + +void SetAvailableHeroes::applyCl( CClient *cl ) +{ + //TODO: inform interface? +} + +void GiveBonus::applyCl( CClient *cl ) +{ + CGHeroInstance *h = GS(cl)->getHero(hid); + if(vstd::contains(cl->playerint,h->tempOwner)) + cl->playerint[h->tempOwner]->heroBonusChanged(h,h->bonuses.back(),true); +} + +void ChangeObjPos::applyFirstCl( CClient *cl ) +{ + CGObjectInstance *obj = GS(cl)->map->objects[objid]; + if(flags & 1) + CGI->mh->hideObject(obj); +} +void ChangeObjPos::applyCl( CClient *cl ) +{ + CGObjectInstance *obj = GS(cl)->map->objects[objid]; + if(flags & 1) + CGI->mh->printObject(obj); +} + +void RemoveObject::applyFirstCl( CClient *cl ) +{ + CGI->mh->hideObject(cl->getObj(id)); +} + +void RemoveObject::applyCl( CClient *cl ) +{ + CGHeroInstance *h = GS(cl)->getHero(id); + if(h) + { + if(vstd::contains(cl->playerint,h->tempOwner)) + cl->playerint[h->tempOwner]->heroKilled(h); + } +} + +void TryMoveHero::applyFirstCl( CClient *cl ) +{ + if(result>1) + CGI->mh->removeObject(GS(cl)->getHero(id)); +} + +void TryMoveHero::applyCl( CClient *cl ) +{ + HeroMoveDetails hmd(start,end,GS(cl)->getHero(id)); + hmd.style = result-1; + hmd.successful = result; + + if(result>1) + CGI->mh->printObject(hmd.ho); + int player = hmd.ho->tempOwner; + + if(vstd::contains(cl->playerint,player)) + { + cl->playerint[player]->tileRevealed(fowRevealed); + } + + //notify interfaces about move + for(std::map::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++) + { + if(i->first >= PLAYER_LIMIT) continue; + if(GS(cl)->players[i->first].fogOfWarMap[start.x-1][start.y][start.z] || GS(cl)->players[i->first].fogOfWarMap[end.x-1][end.y][end.z]) + { + i->second->heroMoved(hmd); + } + } + + //add info for callback + if(result<2) + { + mess.mx->lock(); + mess.res->insert(new TryMoveHero(*this)); + mess.mx->unlock(); + mess.cv->notify_all(); + } +} + +void SetGarrisons::applyCl( CClient *cl ) +{ + for(std::map::iterator i = garrs.begin(); i!=garrs.end(); i++) + if(vstd::contains(cl->playerint,cl->getOwner(i->first))) + cl->playerint[cl->getOwner(i->first)]->garrisonChanged(cl->getObj(i->first)); +} + +void NewStructures::applyCl( CClient *cl ) +{ + CGTownInstance *town = GS(cl)->getTown(tid); + BOOST_FOREACH(si32 id, bid) + { + if(id==13) //fort or capitol + { + town->defInfo = GS(cl)->capitols[town->subID]; + } + if(id ==7) + { + town->defInfo = GS(cl)->forts[town->subID]; + } + if(vstd::contains(cl->playerint,town->tempOwner)) + cl->playerint[town->tempOwner]->buildChanged(town,id,1); + } +} + +void SetAvailableCreatures::applyCl( CClient *cl ) +{ + CGTownInstance *t = GS(cl)->getTown(tid); + if(vstd::contains(cl->playerint,t->tempOwner)) + cl->playerint[t->tempOwner]->availableCreaturesChanged(t); +} + +void SetHeroesInTown::applyCl( CClient *cl ) +{ + CGTownInstance *t = GS(cl)->getTown(tid); + if(vstd::contains(cl->playerint,t->tempOwner)) + cl->playerint[t->tempOwner]->heroInGarrisonChange(t); +} + +void SetHeroArtifacts::applyCl( CClient *cl ) +{ + CGHeroInstance *t = GS(cl)->getHero(hid); + if(vstd::contains(cl->playerint,t->tempOwner)) + cl->playerint[t->tempOwner]->heroArtifactSetChanged(t); +} + +void HeroRecruited::applyCl( CClient *cl ) +{ + CGHeroInstance *h = GS(cl)->map->heroes.back(); + if(h->subID != hid) + { + tlog1 << "Something wrong with hero recruited!\n"; + } + + CGI->mh->initHeroDef(h); + if(vstd::contains(cl->playerint,h->tempOwner)) + { + cl->playerint[h->tempOwner]->heroCreated(h); + cl->playerint[h->tempOwner]->heroInGarrisonChange(GS(cl)->getTown(tid)); + } +} + +void GiveHero::applyCl( CClient *cl ) +{ + CGHeroInstance *h = GS(cl)->getHero(id); + CGI->mh->initHeroDef(h); + CGI->mh->printObject(h); + cl->playerint[h->tempOwner]->heroCreated(h); +} + +void GiveHero::applyFirstCl( CClient *cl ) +{ + CGI->mh->hideObject(GS(cl)->getHero(id)); +} + +void InfoWindow::applyCl( CClient *cl ) +{ + std::vector comps; + for(size_t i=0;iplayerint,player)) + cl->playerint[player]->showInfoDialog(str,comps); + else + tlog2 << "We received InfoWindow for not our player...\n"; +} + +void HeroLevelUp::applyCl( CClient *cl ) +{ + CGHeroInstance *h = GS(cl)->getHero(heroid); + if(vstd::contains(cl->playerint,h->tempOwner)) + { + boost::function callback = boost::function(boost::bind(&CCallback::selectionMade,LOCPLINT->cb,_1,id)); + cl->playerint[h->tempOwner]->heroGotLevel((const CGHeroInstance *)h,(int)primskill,skills, callback); + } +} + +void SelectionDialog::applyCl( CClient *cl ) +{ + std::vector comps; + for(size_t i=0; i < components.size(); ++i) { + comps.push_back(&components[i]); + } + std::string str = toString(text); + if(vstd::contains(cl->playerint,player)) + cl->playerint[player]->showSelDialog(str,comps,id); + else + tlog2 << "We received SelectionDialog for not our player...\n"; +} + +void YesNoDialog::applyCl( CClient *cl ) +{ + std::vector comps; + for(size_t i=0; i < components.size(); ++i) { + comps.push_back(&components[i]); + } + std::string str = toString(text); + if(vstd::contains(cl->playerint,player)) + cl->playerint[player]->showYesNoDialog(str,comps,id); + else + tlog2 << "We received YesNoDialog for not our player...\n"; +} + +void BattleStart::applyCl( CClient *cl ) +{ + if(vstd::contains(cl->playerint,info->side1)) + cl->playerint[info->side1]->battleStart(&info->army1, &info->army2, info->tile, GS(cl)->getHero(info->hero1), GS(cl)->getHero(info->hero2), 0); + + if(vstd::contains(cl->playerint,info->side2)) + cl->playerint[info->side2]->battleStart(&info->army1, &info->army2, info->tile, GS(cl)->getHero(info->hero1), GS(cl)->getHero(info->hero2), 1); +} + +void BattleNextRound::applyCl( CClient *cl ) +{ + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->battleNewRound(round); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->battleNewRound(round); +} + +void BattleSetActiveStack::applyCl( CClient *cl ) +{ + int owner = GS(cl)->curB->getStack(stack)->owner; + if(vstd::contains(cl->playerint,owner)) + boost::thread(boost::bind(&CClient::waitForMoveAndSend,cl,owner)); +} + +void BattleResult::applyFirstCl( CClient *cl ) +{ + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->battleEnd(this); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->battleEnd(this); +} + +void BattleStackMoved::applyFirstCl( CClient *cl ) +{ + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->battleStackMoved(stack,tile); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->battleStackMoved(stack,tile); +} + +void BattleStackAttacked::applyCl( CClient *cl ) +{ + + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->battleStackAttacked(this); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->battleStackAttacked(this); +} + +void BattleAttack::applyFirstCl( CClient *cl ) +{ + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->battleAttack(this); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->battleAttack(this); +} + +void BattleAttack::applyCl( CClient *cl ) +{ + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->battleStackAttacked(&bsa); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->battleStackAttacked(&bsa); +} + +void StartAction::applyFirstCl( CClient *cl ) +{ + cl->curbaction = new BattleAction(ba); + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->actionStarted(&ba); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->actionStarted(&ba); +} + +void SpellCasted::applyCl( CClient *cl ) +{ + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->battleSpellCasted(this); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->battleSpellCasted(this); +} + +void SetStackEffect::applyCl( CClient *cl ) +{ + SpellCasted sc; + sc.id = effect.id; + sc.side = 3; //doesn't matter + sc.skill = effect.level; + sc.tile = GS(cl)->curB->getStack(stack)->position; + if(cl->playerint.find(GS(cl)->curB->side1) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side1]->battleSpellCasted(&sc); + if(cl->playerint.find(GS(cl)->curB->side2) != cl->playerint.end()) + cl->playerint[GS(cl)->curB->side2]->battleSpellCasted(&sc); +} + +CGameState* CPackForClient::GS( CClient *cl ) +{ + return cl->gs; +} + +void EndAction::applyCl( CClient *cl ) +{ + INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side1,actionFinished,cl->curbaction); + INTERFACE_CALL_IF_PRESENT(GS(cl)->curB->side2,actionFinished,cl->curbaction); + + delete cl->curbaction; + cl->curbaction = NULL; +} + +void SystemMessage::applyCl( CClient *cl ) +{ + tlog4 << "System message from server: " << text << std::endl; +} + +void YourTurn::applyCl( CClient *cl ) +{ + boost::thread(boost::bind(&CGameInterface::yourTurn,cl->playerint[player])); +} + + +void PlayerMessage::applyCl(CClient *cl) +{ + tlog4 << "Player "<<(int)player<<" sends a message: " << text << std::endl; +} + +void ShowInInfobox::applyCl(CClient *cl) +{ + SComponent sc(c); + sc.description = toString(text); + if(cl->playerint[player]->human) + { + static_cast(cl->playerint[player])->showComp(sc); + } +} \ No newline at end of file diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp new file mode 100644 index 000000000..f9c50e1a5 --- /dev/null +++ b/lib/NetPacksLib.cpp @@ -0,0 +1,480 @@ +#define VCMI_DLL +#include "../lib/NetPacks.h" +#include "../hch/CGeneralTextHandler.h" +#include "../hch/CDefObjInfoHandler.h" +#include "../hch/CHeroHandler.h" +#include "../hch/CObjectHandler.h" +#include "../lib/VCMI_Lib.h" +#include "../map.h" +#include "../hch/CSpellHandler.h" +#include +#include +#include +#include + +DLL_EXPORT void SetResource::applyGs( CGameState *gs ) +{ + gs->players[player].resources[resid] = val; +} + +DLL_EXPORT void SetResources::applyGs( CGameState *gs ) +{ + for(int i=0;iplayers[player].resources[i] = res[i]; +} + +DLL_EXPORT void SetPrimSkill::applyGs( CGameState *gs ) +{ + CGHeroInstance *hero = gs->getHero(id); + if(which <4) + { + if(abs) + hero->primSkills[which] = val; + else + hero->primSkills[which] += val; + } + else if(which == 4) //XP + { + if(abs) + hero->exp = val; + else + hero->exp += val; + } +} + +DLL_EXPORT void SetSecSkill::applyGs( CGameState *gs ) +{ + CGHeroInstance *hero = gs->getHero(id); + if(hero->getSecSkillLevel(which) == 0) + { + hero->secSkills.push_back(std::pair(which, val)); + } + else + { + for(unsigned i=0;isecSkills.size();i++) + { + if(hero->secSkills[i].first == which) + { + if(abs) + hero->secSkills[i].second = val; + else + hero->secSkills[i].second += val; + } + } + } +} + +DLL_EXPORT void HeroVisitCastle::applyGs( CGameState *gs ) +{ + CGHeroInstance *h = gs->getHero(hid); + CGTownInstance *t = gs->getTown(tid); + if(start()) + { + if(garrison()) + { + t->garrisonHero = h; + h->visitedTown = t; + h->inTownGarrison = true; + } + else + { + t->visitingHero = h; + h->visitedTown = t; + h->inTownGarrison = false; + } + } + else + { + if(garrison()) + { + t->garrisonHero = NULL; + h->visitedTown = NULL; + h->inTownGarrison = false; + } + else + { + t->visitingHero = NULL; + h->visitedTown = NULL; + h->inTownGarrison = false; + } + } +} + +DLL_EXPORT void ChangeSpells::applyGs( CGameState *gs ) +{ + CGHeroInstance *hero = gs->getHero(hid); + + if(learn) + BOOST_FOREACH(ui32 sid, spells) + hero->spells.insert(sid); + else + BOOST_FOREACH(ui32 sid, spells) + hero->spells.erase(sid); +} + +DLL_EXPORT void SetMana::applyGs( CGameState *gs ) +{ + CGHeroInstance *hero = gs->getHero(hid); + hero->mana = val; +} + +DLL_EXPORT void SetMovePoints::applyGs( CGameState *gs ) +{ + CGHeroInstance *hero = gs->getHero(hid); + hero->movement = val; +} + +DLL_EXPORT void FoWChange::applyGs( CGameState *gs ) +{ + BOOST_FOREACH(int3 t, tiles) + gs->players[player].fogOfWarMap[t.x][t.y][t.z] = mode; +} + +DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs ) +{ + gs->players[player].availableHeroes.clear(); + + CGHeroInstance *h = (hid1>=0 ? gs->hpool.heroesPool[hid1] : NULL); + gs->players[player].availableHeroes.push_back(h); + if(h && flags & 1) + { + h->army.slots.clear(); + h->army.slots[0] = std::pair(VLC->creh->nameToID[h->type->refTypeStack[0]],1); + } + + h = (hid2>=0 ? gs->hpool.heroesPool[hid2] : NULL); + gs->players[player].availableHeroes.push_back(h); + if(flags & 2) + { + h->army.slots.clear(); + h->army.slots[0] = std::pair(VLC->creh->nameToID[h->type->refTypeStack[0]],1); + } +} + +DLL_EXPORT void GiveBonus::applyGs( CGameState *gs ) +{ + CGHeroInstance *h = gs->getHero(hid); + h->bonuses.push_back(bonus); + h->bonuses.back().description = toString(bdescr); +} + +DLL_EXPORT void ChangeObjPos::applyGs( CGameState *gs ) +{ + CGObjectInstance *obj = gs->map->objects[objid]; + if(!obj) + { + tlog1 << "Wrong ChangeObjPos: object " << objid << " doesn't exist!\n"; + return; + } + gs->map->removeBlockVisTiles(obj); + obj->pos = nPos; + gs->map->addBlockVisTiles(obj); +} + +DLL_EXPORT void RemoveObject::applyGs( CGameState *gs ) +{ + CGObjectInstance *obj = gs->map->objects[id]; + if(obj->ID==HEROI_TYPE) + { + CGHeroInstance *h = static_cast(obj); + std::vector::iterator nitr = std::find(gs->map->heroes.begin(), gs->map->heroes.end(),h); + gs->map->heroes.erase(nitr); + int player = h->tempOwner; + nitr = std::find(gs->players[player].heroes.begin(), gs->players[player].heroes.end(), h); + gs->players[player].heroes.erase(nitr); + if(h->visitedTown) + { + if(h->inTownGarrison) + h->visitedTown->garrisonHero = NULL; + else + h->visitedTown->visitingHero = NULL; + h->visitedTown = NULL; + } + + //TODO: add to the pool? + } + gs->map->objects[id] = NULL; + + //unblock tiles + if(obj->defInfo) + { + gs->map->removeBlockVisTiles(obj); + } +} + +void TryMoveHero::applyGs( CGameState *gs ) +{ + CGHeroInstance *h = gs->getHero(id); + h->movement = movePoints; + if(start!=end && result) + { + gs->map->removeBlockVisTiles(h); + h->pos = end; + gs->map->addBlockVisTiles(h); + } + BOOST_FOREACH(int3 t, fowRevealed) + gs->players[h->getOwner()].fogOfWarMap[t.x][t.y][t.z] = 1; +} + +DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs ) +{ + for(std::map::iterator i = garrs.begin(); i!=garrs.end(); i++) + { + CArmedInstance *ai = static_cast(gs->map->objects[i->first]); + ai->army = i->second; + if(ai->ID==TOWNI_TYPE && (static_cast(ai))->garrisonHero) //if there is a hero in garrison then we must update also his army + const_cast((static_cast(ai))->garrisonHero)->army = i->second; + else if(ai->ID==HEROI_TYPE) + { + CGHeroInstance *h = static_cast(ai); + if(h->visitedTown && h->inTownGarrison) + h->visitedTown->army = i->second; + } + } +} + +DLL_EXPORT void NewStructures::applyGs( CGameState *gs ) +{ + CGTownInstance*t = gs->getTown(tid); + BOOST_FOREACH(si32 id,bid) + t->builtBuildings.insert(id); + t->builded = builded; +} + +DLL_EXPORT void SetAvailableCreatures::applyGs( CGameState *gs ) +{ + gs->getTown(tid)->strInfo.creatures = creatures; +} + +DLL_EXPORT void SetHeroesInTown::applyGs( CGameState *gs ) +{ + CGTownInstance *t = gs->getTown(tid); + + CGHeroInstance *v = gs->getHero(visiting), + *g = gs->getHero(garrison); + + t->visitingHero = v; + t->garrisonHero = g; + if(v) + { + v->visitedTown = t; + v->inTownGarrison = false; + gs->map->addBlockVisTiles(v); + } + if(g) + { + g->visitedTown = t; + g->inTownGarrison = true; + gs->map->removeBlockVisTiles(g); + } +} + +DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs ) +{ + CGHeroInstance *h = gs->getHero(hid); + h->artifacts = artifacts; + h->artifWorn = artifWorn; +} + +DLL_EXPORT void HeroRecruited::applyGs( CGameState *gs ) +{ + CGHeroInstance *h = gs->hpool.heroesPool[hid]; + CGTownInstance *t = gs->getTown(tid); + h->setOwner(player); + h->pos = tile; + h->movement = h->maxMovePoints(true); + + gs->hpool.heroesPool.erase(hid); + if(h->id < 0) + { + h->id = gs->map->objects.size(); + gs->map->objects.push_back(h); + } + else + gs->map->objects[h->id] = h; + + h->initHeroDefInfo(); + gs->map->heroes.push_back(h); + gs->players[h->tempOwner].heroes.push_back(h); + gs->map->addBlockVisTiles(h); + t->visitingHero = h; + h->visitedTown = t; + h->inTownGarrison = false; +} + +DLL_EXPORT void GiveHero::applyGs( CGameState *gs ) +{ + CGHeroInstance *h = gs->getHero(id); + gs->map->removeBlockVisTiles(h,true); + h->setOwner(player); + h->movement = h->maxMovePoints(true); + h->initHeroDefInfo(); + gs->map->heroes.push_back(h); + gs->players[h->tempOwner].heroes.push_back(h); + gs->map->addBlockVisTiles(h); + h->inTownGarrison = false; +} + +DLL_EXPORT void NewTurn::applyGs( CGameState *gs ) +{ + gs->day = day; + BOOST_FOREACH(NewTurn::Hero h, heroes) //give mana/movement point + { + static_cast(gs->map->objects[h.id])->movement = h.move; + static_cast(gs->map->objects[h.id])->mana = h.mana; + } + + BOOST_FOREACH(SetResources h, res) //give resources + h.applyGs(gs); + + BOOST_FOREACH(SetAvailableCreatures h, cres) //set available creatures in towns + h.applyGs(gs); + + if(resetBuilded) //reset amount of structures set in this turn in towns + BOOST_FOREACH(CGTownInstance* t, gs->map->towns) + t->builded = 0; + + BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes) + h->bonuses.remove_if(HeroBonus::OneDay); + + if(gs->getDate(1) == 7) //new week + BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes) + h->bonuses.remove_if(HeroBonus::OneWeek); +} + +DLL_EXPORT void SetObjectProperty::applyGs( CGameState *gs ) +{ + CGObjectInstance *obj = gs->map->objects[id]; + if(!obj) + tlog1 << "Wrong object ID - property cannot be set!\n"; + else + obj->setProperty(what,val); +} + +DLL_EXPORT void SetHoverName::applyGs( CGameState *gs ) +{ + gs->map->objects[id]->hoverName = toString(name); +} + +DLL_EXPORT void HeroLevelUp::applyGs( CGameState *gs ) +{ + gs->getHero(heroid)->level = level; +} + +DLL_EXPORT void BattleStart::applyGs( CGameState *gs ) +{ + gs->curB = info; +} + +DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs ) +{ + gs->curB->castedSpells[0] = gs->curB->castedSpells[1] = 0; + gs->curB->round = round; + + BOOST_FOREACH(CStack *s, gs->curB->stacks) + { + s->state -= DEFENDING; + s->state -= WAITING; + s->state -= MOVED; + s->state -= HAD_MORALE; + s->counterAttacks = 1; + } +} + +DLL_EXPORT void BattleSetActiveStack::applyGs( CGameState *gs ) +{ + gs->curB->activeStack = stack; + CStack *st = gs->curB->getStack(stack); + if(vstd::contains(st->state,MOVED)) //if stack is moving second time this turn it must had a high morale bonus + st->state.insert(HAD_MORALE); +} + +void BattleResult::applyqGs( CGameState *gs ) +{ + for(unsigned i=0;icurB->stacks.size();i++) + delete gs->curB->stacks[i]; + + //remove any "until next battle" bonuses + CGHeroInstance *h; + h = gs->getHero(gs->curB->hero1); + if(h) + h->bonuses.remove_if(HeroBonus::OneBattle); + h = gs->getHero(gs->curB->hero2); + if(h) + h->bonuses.remove_if(HeroBonus::OneBattle); + + delete gs->curB; + gs->curB = NULL; +} + +void BattleStackMoved::applyqGs( CGameState *gs ) +{ + gs->curB->getStack(stack)->position = tile; +} + +DLL_EXPORT void BattleStackAttacked::applyGs( CGameState *gs ) +{ + CStack * at = gs->curB->getStack(stackAttacked); + at->amount = newAmount; + at->firstHPleft = newHP; + if(killed()) + at->state -= ALIVE; +} + +DLL_EXPORT void BattleAttack::applyGs( CGameState *gs ) +{ + CStack *attacker = gs->curB->getStack(stackAttacking); + if(counter()) + attacker->counterAttacks--; + if(shot()) + attacker->shots--; + bsa.applyGs(gs); +} + +DLL_EXPORT void StartAction::applyGs( CGameState *gs ) +{ + CStack *st = gs->curB->getStack(ba.stackNumber); + switch(ba.actionType) + { + case 3: + st->state.insert(DEFENDING); + break; + case 8: + st->state.insert(WAITING); + break; + case 2: case 6: case 7: case 9: case 10: case 11: + st->state.insert(MOVED); + break; + } +} + +DLL_EXPORT void SpellCasted::applyGs( CGameState *gs ) +{ + CGHeroInstance *h = (side) ? gs->getHero(gs->curB->hero2) : gs->getHero(gs->curB->hero1); + if(h) + { + h->mana -= VLC->spellh->spells[id].costs[skill]; + if(h->mana < 0) h->mana = 0; + } + if(side >= 0 && side < 2) + { + gs->curB->castedSpells[side]++; + } +} + +DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs ) +{ + CStack *s = gs->curB->getStack(stack); + s->effects.push_back(effect); +} + +DLL_EXPORT void YourTurn::applyGs( CGameState *gs ) +{ + gs->currentPlayer = player; +} + + +DLL_EXPORT void SetSelection::applyGs( CGameState *gs ) +{ + gs->players[player].currentSelection = id; +} \ No newline at end of file diff --git a/lib/RegisterTypes.cpp b/lib/RegisterTypes.cpp new file mode 100644 index 000000000..513dbe698 --- /dev/null +++ b/lib/RegisterTypes.cpp @@ -0,0 +1,19 @@ +#define VCMI_DLL +#include "Connection.h" +#include "NetPacks.h" +#include "VCMI_Lib.h" +#include "../hch./CObjectHandler.h" +#include "../hch/CHeroHandler.h" +#include "../hch/CTownHandler.h" +#include "RegisterTypes.h" + + +void foofoofoo() +{ + //never called function to force instantation of templates + int *ccc = NULL; + registerTypes((CISer&)*ccc); + registerTypes((COSer&)*ccc); + registerTypes((CSaveFile&)*ccc); + registerTypes((CLoadFile&)*ccc); +} \ No newline at end of file diff --git a/lib/RegisterTypes.h b/lib/RegisterTypes.h new file mode 100644 index 000000000..cb25e1b45 --- /dev/null +++ b/lib/RegisterTypes.h @@ -0,0 +1,85 @@ +#pragma once +//templates for registering object types + +//first set of types - derivatives of CGObjectInstance +template DLL_EXPORT void registerTypes1(Serializer &s) +{ + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); +} + + +//second set of types - derivatives of CPack (network VCMI packages) +template DLL_EXPORT void registerTypes2(Serializer &s) +{ + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); + s.registerType(); +} + +//register all +template DLL_EXPORT void registerTypes(Serializer &s) +{ + registerTypes1(s); + registerTypes2(s); +} \ No newline at end of file