diff --git a/CCallback.cpp b/CCallback.cpp index a6e4c15d1..650eb4b19 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -136,11 +136,11 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount //recruit int slot = -1; //slot ID - std::pair > parb; + std::pair > parb; for(int i=0;i<7;i++) //TODO: if there is already stack of same creatures it should be used always { - if((!t->army.slots[i].first) || (t->army.slots[i].first->idNumber == ID)) //slot is free or there is saem creature + if(((!t->army.slots[i].first) && (!t->army.slots[i].second)) || (t->army.slots[i].first == ID)) //slot is free or there is saem creature { slot = i; break; @@ -160,7 +160,7 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount } else //create new stack in the garrison { - t->army.slots[slot].first = &CGI->creh->creatures[ID]; + t->army.slots[slot].first = ID; t->army.slots[slot].second = amount; } cl->playerint[player]->garrisonChanged(obj); @@ -194,7 +194,7 @@ void CCallback::endTurn() UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos) { UpgradeInfo ret; - CCreature *base = ((CArmedInstance*)obj)->army.slots[stackPos].first; + CCreature *base = &CGI->creh->creatures[((CArmedInstance *)obj)->army.slots[stackPos].first]; if((obj->ID == 98) || ((obj->ID == 34) && static_cast(obj)->visitedTown)) { CGTownInstance * t; @@ -404,79 +404,29 @@ const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj) int CCallback::swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2) { - CCreatureSet *S1 = const_cast(getGarrison(s1)), *S2 = const_cast(getGarrison(s2)); - if (false) - { - //TODO: check if we are allowed to swap these creatures + if(s1->tempOwner != player || s2->tempOwner != player) return -1; - } - CCreature * pom = S2->slots[p2].first; - S2->slots[p2].first = S1->slots[p1].first; - S1->slots[p1].first = pom; - int pom2 = S2->slots[p2].second; - S2->slots[p2].second = S1->slots[p1].second; - S1->slots[p1].second = pom2; - - if(!S1->slots[p1].first) - S1->slots.erase(p1); - if(!S2->slots[p2].first) - S2->slots.erase(p2); - - if(s1->tempOwnerplayerint[s1->tempOwner]->garrisonChanged(s1); - if((s2->tempOwnerplayerint[s2->tempOwner]->garrisonChanged(s2); + *cl->serv << ui16(502) << ui8(1) << s1->id << ui8(p1) << s2->id << ui8(p2); return 0; } int CCallback::mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2) { - CCreatureSet *S1 = const_cast(getGarrison(s1)), *S2 = const_cast(getGarrison(s2)); - if ((S1->slots[p1].first != S2->slots[p2].first) && (true /*we are allowed to*/)) + if ((s1->tempOwner!= player || s2->tempOwner!=player)) { return -1; } - - - S2->slots[p2].second += S1->slots[p1].second; - S1->slots[p1].first = NULL; - S1->slots[p1].second = 0; - - S1->slots.erase(p1); - - if(s1->tempOwnerplayerint[s1->tempOwner]->garrisonChanged(s1); - - if((s2->tempOwnerplayerint[s2->tempOwner]->garrisonChanged(s2); + *cl->serv << ui16(502) << ui8(2) << s1->id << ui8(p1) << s2->id << ui8(p2); return 0; } int CCallback::splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val) { - if(!val) - return -1; - CCreatureSet *S1 = const_cast(getGarrison(s1)), *S2 = const_cast(getGarrison(s2)); - if ((S1->slots[p1].secondtempOwner!= player || s2->tempOwner!=player || (!val)) { return -1; } - - S2->slots[p2].first = S1->slots[p1].first; - S2->slots[p2].second = val; - S1->slots[p1].second -= val; - if(!S1->slots[p1].second) //if we've moved all creatures - S1->slots.erase(p1); - - - if(s1->tempOwnerplayerint[s1->tempOwner]->garrisonChanged(s1); - } - if((s2->tempOwnerplayerint[s2->tempOwner]->garrisonChanged(s2); - } + *cl->serv << ui16(502) << ui8(3) << s1->id << ui8(p1) << s2->id << ui8(p2) << si32(val); return 0; } diff --git a/CGameState.cpp b/CGameState.cpp index 22b2d2e41..882eeff47 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -141,6 +141,13 @@ void CGameState::apply(IPack * pack) players[h->getOwner()].fogOfWarMap[t.x][t.y][t.z] = 1; break; } + case 502: + { + SetGarrisons * n = static_cast(pack); + for(std::map::iterator i = n->garrs.begin(); i!=n->garrs.end(); i++) + static_cast(map->objects[i->first])->army = i->second; + break; + } case 1001://set object property { SetObjectProperty *p = static_cast(pack); @@ -568,7 +575,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed) } continue; } - vhi->army.slots[x-pom2].first = &(VLC->creh->creatures[pom]); + vhi->army.slots[x-pom2].first = pom; if((pom = (vhi->type->highStack[x]-vhi->type->lowStack[x])) > 0) vhi->army.slots[x-pom2].second = (ran()%pom)+vhi->type->lowStack[x]; else @@ -674,7 +681,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C curB->side2=(hero2)?(hero2->tempOwner):(-1); curB->round = -2; curB->stackActionPerformed = false; - for(std::map >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++) + for(std::map >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++) { stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size(), true)); stacks[stacks.size()-1]->ID = stacks.size()-1; @@ -729,7 +736,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C default: //fault break; } - for(std::map >::iterator i = army2->slots.begin(); i!=army2->slots.end(); i++) + for(std::map >::iterator i = army2->slots.begin(); i!=army2->slots.end(); i++) stacks.push_back(new CStack(i->second.first,i->second.second,1, stacks.size(), false)); switch(army2->slots.size()) //for defender { diff --git a/CLua.cpp b/CLua.cpp index f7800a593..85a006661 100644 --- a/CLua.cpp +++ b/CLua.cpp @@ -720,7 +720,7 @@ void CMonsterS::onHeroVisit(int objid, int heroID) DEFOS; CCreatureSet set; //TODO: zrobic secik w sposob wyrafinowany - set.slots[0] = std::pair(&VLC->creh->creatures[os->subID],((CCreatureObjInfo*)os->info)->number); + set.slots[0] = std::pair(os->subID,((CCreatureObjInfo*)os->info)->number); cb->startBattle(heroID,&set,os->pos); } std::vector CMonsterS::yourObjects() //returns IDs of objects which are handled by script diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index 8ca30f9a3..cdb9652f2 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -342,11 +342,11 @@ void CGarrisonInt::createSlots() { sup = new std::vector(7,(CGarrisonSlot *)(NULL)); for - (std::map >::const_iterator i=set1->slots.begin(); + (std::map >::const_iterator i=set1->slots.begin(); i!=set1->slots.end(); i++) { (*sup)[i->first] = - new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y,i->first, 0, 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; isize(); i++) if((*sup)[i] == NULL) @@ -356,11 +356,11 @@ void CGarrisonInt::createSlots() { sdown = new std::vector(7,(CGarrisonSlot *)(NULL)); for - (std::map >::const_iterator i=set2->slots.begin(); + (std::map >::const_iterator i=set2->slots.begin(); i!=set2->slots.end(); i++) { (*sdown)[i->first] = - new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y + 64 + intery,i->first,1, 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; isize(); i++) if((*sdown)[i] == NULL) diff --git a/client/Client.cpp b/client/Client.cpp index 769c7daff..88bbc236d 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -114,7 +114,10 @@ CClient::CClient(CConnection *con, StartInfo *si) std::cout << "\tOur checksum for the map: "<< mapa->checksum << std::endl; if(mapa->checksum != sum) + { + throw std::exception("Wrong checksum"); exit(-1); + } std::cout << "\tUsing random seed: "<state; @@ -223,6 +226,15 @@ void CClient::process(int what) mess.cv->notify_all(); break; } + case 502: + { + SetGarrisons sg; + *serv >> sg; + gs->apply(&sg); + for(std::map::iterator i = sg.garrs.begin(); i!=sg.garrs.end(); i++) + playerint[gs->map->objects[i->first]->tempOwner]->garrisonChanged(gs->map->objects[i->first]); + break; + } case 1001: { SetObjectProperty sop; diff --git a/client/Graphics.cpp b/client/Graphics.cpp index 35609d1f1..e8e5c7875 100644 --- a/client/Graphics.cpp +++ b/client/Graphics.cpp @@ -35,9 +35,9 @@ SDL_Surface * Graphics::drawHeroInfoWin(const CGHeroInstance * curh) SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255)); printAt(curh->name,75,15,GEOR13,zwykly,ret); drawPrimarySkill(curh, ret); - for (std::map >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++) + for (std::map >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++) { - blitAt(graphics->smallImgs[(*i).second.first->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret); + blitAt(graphics->smallImgs[(*i).second.first],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret); itoa((*i).second.second,buf,10); printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+39,GEORM,zwykly,ret); } @@ -64,11 +64,11 @@ SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh) blitAt(halls->ourImages[pom].bitmap,77,42,ret); itoa(curh->dailyIncome(),buf,10); printAtMiddle(buf,167,70,GEORM,zwykly,ret); - for (std::map >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++) + for (std::map >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++) { if(!i->second.first) continue; - blitAt(graphics->smallImgs[(*i).second.first->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret); + blitAt(graphics->smallImgs[(*i).second.first],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret); itoa((*i).second.second,buf,10); printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+39,GEORM,zwykly,ret); } diff --git a/client/VCMI_client.vcproj b/client/VCMI_client.vcproj index de8d21572..114c4b714 100644 --- a/client/VCMI_client.vcproj +++ b/client/VCMI_client.vcproj @@ -171,7 +171,7 @@ /> @@ -220,8 +224,10 @@ AdditionalDependencies="SDL.lib zdll.lib SDL_image.lib SDL_ttf.lib SDL_mixer.lib lua5.1.lib VCMI_lib.lib" AdditionalLibraryDirectories="G:\vcmt\repa\libs" GenerateDebugInformation="true" + Driver="0" OptimizeReferences="2" EnableCOMDATFolding="2" + LinkTimeCodeGeneration="0" TargetMachine="1" /> speedspeed; + if(VLC->creh->creatures[army.slots[h].first].speedcreh->creatures[army.slots[h].first].speed; } return sl; } diff --git a/int3.h b/int3.h index 31469933b..c6fd05b66 100644 --- a/int3.h +++ b/int3.h @@ -5,8 +5,12 @@ class CCreature; class CCreatureSet //seven combined creatures { public: - std::map > slots; - bool formation; //false - wide, true - tight + std::map > slots; //slots[slot_id]=> pair(creature_id,creature_quantity) + bool formation; //false - wide, true - tight + template void serialize(Handler &h, const int version) + { + h & slots & formation; + } }; class int3 diff --git a/lib/Connection.h b/lib/Connection.h index 6f7cd88ad..67a7fa14d 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -262,6 +262,25 @@ public: { *this >> data.first >> data.second; } + template + void saveSerializable(const std::map &data) + { + *this << ui32(data.size()); + for(std::map::const_iterator i=data.begin();i!=data.end();i++) + *this << i->first << i->second; + } + template + void loadSerializable(std::map &data) + { + ui32 length; + *this >> length; + T1 t; + for(int i=0;i> t; + *this >> data[t]; + } + } template void save(const T &data) { diff --git a/lib/NetPacks.h b/lib/NetPacks.h index ed08054fa..21a0a0d34 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -85,6 +85,16 @@ struct TryMoveHero : public CPack //501 h & id & result & start & end & movePoints & fowRevealed; } }; +struct SetGarrisons : public CPack //502 +{ + SetGarrisons(){type = 502;}; + std::map garrs; + + template void serialize(Handler &h, const int version) + { + h & garrs; + } +}; struct MetaString : public CPack //2001 helper for object scrips { std::vector strings; diff --git a/lib/VCMI_lib.vcproj b/lib/VCMI_lib.vcproj index 09f44210c..d9df4651c 100644 --- a/lib/VCMI_lib.vcproj +++ b/lib/VCMI_lib.vcproj @@ -169,11 +169,11 @@ /> - - - - - - - - - - - - - - - - - - - ins; + std::pair ins; for(int ir=0;ir32768) rettt = 65536-rettt+VLC->creh->creatures.size()-16; - ins.first = &(VLC->creh->creatures[rettt]); + ins.first = rettt; ins.second = readNormalNr(bufor,i+ir*4+2, 2); - std::pair > tt(ir,ins); + std::pair > tt(ir,ins); ret.slots.insert(tt); } i+=number*4; @@ -188,16 +188,16 @@ CCreatureSet readCreatureSet(unsigned char * bufor, int &i, int number, bool ver else { CCreatureSet ret; - std::pair ins; + std::pair ins; for(int ir=0;ir220) rettt = 256-rettt+VLC->creh->creatures.size()-16; - ins.first = &(VLC->creh->creatures[rettt]); + ins.first = rettt; ins.second = readNormalNr(bufor,i+ir*3+1, 2); - std::pair > tt(ir,ins); + std::pair > tt(ir,ins); ret.slots.insert(tt); } i+=number*3; @@ -455,7 +455,7 @@ void Mapa::initFromBytes(unsigned char * bufor) for (int ii=0;ii players, CConnection &c) sendAndApply(&tmh); break; } + case 502: //swap creatures in garrison + { + ui8 what, p1, p2; si32 id1, id2; + c >> what >> id1 >> p1 >> id2 >> p2; + CArmedInstance *s1 = static_cast(gs->map->objects[id1]), + *s2 = static_cast(gs->map->objects[id2]); + CCreatureSet *S1 = &s1->army, *S2 = &s2->army; + + if(what==1) //swap + { + int pom = S2->slots[p2].first; + S2->slots[p2].first = S1->slots[p1].first; + S1->slots[p1].first = pom; + int pom2 = S2->slots[p2].second; + S2->slots[p2].second = S1->slots[p1].second; + S1->slots[p1].second = pom2; + + if(!S1->slots[p1].first) + S1->slots.erase(p1); + if(!S2->slots[p2].first) + S2->slots.erase(p2); + } + else if(what==2)//merge + { + if(S1->slots[p1].first != S2->slots[p2].first) break; //not same creature + S2->slots[p2].second += S1->slots[p1].second; + S1->slots[p1].first = NULL; + S1->slots[p1].second = 0; + S1->slots.erase(p1); + } + else if(what==3) //split + { + si32 val; + c >> val; + if(S2->slots.find(p2) != S2->slots.end()) break; //slot not free + S2->slots[p2].first = S1->slots[p1].first; + S2->slots[p2].second = val; + S1->slots[p1].second -= val; + if(!S1->slots[p1].second) //if we've moved all creatures + S1->slots.erase(p1); + } + SetGarrisons sg; + sg.garrs[id1] = *S1; + if(s1 != s2) + sg.garrs[id2] = *S2; + sendAndApply(&sg); + break; + } default: throw std::exception("Not supported client message!"); break; @@ -241,11 +290,11 @@ void CGameHandler::init(StartInfo *si, int Seed) } int lowestSpeed(CGHeroInstance * chi) { - std::map >::iterator i = chi->army.slots.begin(); - int ret = (*i++).second.first->speed; + std::map >::iterator i = chi->army.slots.begin(); + int ret = VLC->creh->creatures[(*i++).second.first].speed; for (;i!=chi->army.slots.end();i++) { - ret = min(ret,(*i).second.first->speed); + ret = min(ret,VLC->creh->creatures[(*i).second.first].speed); } return ret; } diff --git a/server/VCMI_server.vcproj b/server/VCMI_server.vcproj index 8c2ceb0e8..34dd0ad1d 100644 --- a/server/VCMI_server.vcproj +++ b/server/VCMI_server.vcproj @@ -162,6 +162,83 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + +