From 2d01e002840ee42ca3f863527c36c1a80c701060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Sat, 18 Oct 2008 23:20:48 +0000 Subject: [PATCH] Added some kind of simple chatting functionality through console. Implemented several WoG cheats equivalents: * woggaladriel -> vcmiainur * wogoliphaunt -> vcminoldor * wogshadowfax -> vcminahar * wogeyeofsauron -> vcmieagles * wogisengard -> vcmiformenos * wogsaruman -> vcmiistari * wogpathofthedead -> vcmiangband Minor changes. --- CAdvmapInterface.cpp | 6 +-- CAdvmapInterface.h | 4 +- CCallback.cpp | 5 ++ CCallback.h | 2 + CGameInterface.h | 6 ++- CGameState.cpp | 21 ++++++++ CGameState.h | 3 +- CMT.cpp | 12 +++-- CPlayerInterface.cpp | 55 +++++++++++++++----- CPlayerInterface.h | 6 ++- client/Client.cpp | 47 ++++++++++++++++- client/Client.h | 8 +-- lib/NetPacks.h | 31 ++++++++++++ server/CGameHandler.cpp | 108 +++++++++++++++++++++++++++++++++++++++- server/CVCMIServer.cpp | 2 +- 15 files changed, 283 insertions(+), 33 deletions(-) diff --git a/CAdvmapInterface.cpp b/CAdvmapInterface.cpp index 7f52ee329..bda4bc981 100644 --- a/CAdvmapInterface.cpp +++ b/CAdvmapInterface.cpp @@ -272,7 +272,7 @@ void CMinimap::deactivate() ClickableR::deactivate(); Hoverable::deactivate(); } -void CMinimap::showTile(int3 pos) +void CMinimap::showTile(const int3 &pos) { int mw = map[0]->w, mh = map[0]->h; double wo = ((double)mw)/CGI->mh->sizes.x, ho = ((double)mh)/CGI->mh->sizes.y; @@ -282,11 +282,10 @@ void CMinimap::showTile(int3 pos) { if ((pos.x*wo+iipos.w) && (pos.y*ho+jjpos.h)) CSDL_Ext::SDL_PutPixel(FoW[pos.z],pos.x*wo+ii,pos.y*ho+jj,0,0,0,0,0); - } } } -void CMinimap::hideTile(int3 pos) +void CMinimap::hideTile(const int3 &pos) { } CTerrainRect::CTerrainRect():currentPath(NULL) @@ -1331,6 +1330,7 @@ int3 CAdvMapInt::verifyPos(int3 ver) void CAdvMapInt::select(const CArmedInstance *sel ) { + LOCPLINT->cb->setSelection(sel); centerOn(sel->pos); selection = sel; if(sel->ID==98) diff --git a/CAdvmapInterface.h b/CAdvmapInterface.h index cbe5cbd45..44ad7d0e1 100644 --- a/CAdvmapInterface.h +++ b/CAdvmapInterface.h @@ -37,8 +37,8 @@ public: void mouseMoved (const SDL_MouseMotionEvent & sEvent); void activate(); // makes button active void deactivate(); // makes button inactive (but don't deletes) - void hideTile(int3 pos); //puts FoW - void showTile(int3 pos); //removes FoW + void hideTile(const int3 &pos); //puts FoW + void showTile(const int3 &pos); //removes FoW }; class CTerrainRect : public ClickableL, public ClickableR, public Hoverable, public virtual CIntObject, public KeyInterested, diff --git a/CCallback.cpp b/CCallback.cpp index 753a89b01..7edaf4216 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -622,4 +622,9 @@ void CCallback::setFormation(const CGHeroInstance * hero, bool tight) { const_cast(hero)->army.formation = tight; *cl->serv << ui16(512) << hero->id << ui8(tight); +} + +void CCallback::setSelection(const CArmedInstance * obj) +{ + *cl->serv << ui16(514) << obj->id; } \ No newline at end of file diff --git a/CCallback.h b/CCallback.h index 60ee27f8a..b6da96b63 100644 --- a/CCallback.h +++ b/CCallback.h @@ -43,6 +43,7 @@ public: virtual void buyArtifact(const CGHeroInstance *hero, int aid)=0; //used to buy artifacts in towns (including spell book in the guild and war machines in blacksmith) virtual void trade(int mode, int id1, int id2, int val1)=0; //mode==0: sell val1 units of id1 resource for id2 resiurce virtual void setFormation(const CGHeroInstance * hero, bool tight)=0; + virtual void setSelection(const CArmedInstance * obj)=0; //get info virtual bool verifyPath(CPath * path, bool blockSea)const =0; @@ -125,6 +126,7 @@ public: void buyArtifact(const CGHeroInstance *hero, int aid); void trade(int mode, int id1, int id2, int val1); void setFormation(const CGHeroInstance * hero, bool tight); + void setSelection(const CArmedInstance * obj); //get info bool verifyPath(CPath * path, bool blockSea) const; diff --git a/CGameInterface.h b/CGameInterface.h index de7cf294a..7a074d6da 100644 --- a/CGameInterface.h +++ b/CGameInterface.h @@ -55,14 +55,16 @@ public: virtual void heroKilled(const CGHeroInstance*){}; virtual void heroMoved(const HeroMoveDetails & details){}; virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val){}; + virtual void heroManaPointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after spell casts + virtual void heroMovePointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after movement virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){}; virtual void init(ICallback * CB){}; virtual void receivedResource(int type, int val){}; virtual void showInfoDialog(std::string &text, const std::vector &components){}; virtual void showSelDialog(std::string &text, const std::vector &components, ui32 askID){}; virtual void showYesNoDialog(std::string &text, const std::vector &components, ui32 askID){}; - virtual void tileHidden(int3 pos){}; - virtual void tileRevealed(int3 pos){}; + virtual void tileHidden(const std::set &pos){}; + virtual void tileRevealed(const std::set &pos){}; virtual void yourTurn(){}; virtual void availableCreaturesChanged(const CGTownInstance *town){}; diff --git a/CGameState.cpp b/CGameState.cpp index 0f85f77c0..658ded96c 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -407,6 +407,27 @@ void CGameState::applyNL(IPack * pack) hero->spells.erase(sid); break; } + case 110: + { + SetMana *rh = static_cast(pack); + CGHeroInstance *hero = getHero(rh->hid); + hero->mana = rh->val; + break; + } + case 111: + { + SetMovePoints *rh = static_cast(pack); + CGHeroInstance *hero = getHero(rh->hid); + hero->movement = rh->val; + break; + } + case 112: + { + FoWChange *rh = static_cast(pack); + BOOST_FOREACH(int3 t, rh->tiles) + players[rh->player].fogOfWarMap[t.x][t.y][t.z] = rh->mode; + break; + } case 500: { RemoveObject *rh = static_cast(pack); diff --git a/CGameState.h b/CGameState.h index 120b8c1d1..ab802973b 100644 --- a/CGameState.h +++ b/CGameState.h @@ -42,11 +42,12 @@ struct DLL_EXPORT PlayerState { public: ui8 color, serial; + ui32 currentSelection; //id of hero/town, 0xffffffff if none std::vector > > fogOfWarMap; //true - visible, false - hidden std::vector resources; std::vector heroes; std::vector towns; - PlayerState():color(-1){}; + PlayerState():color(-1),currentSelection(0xffffffff){}; }; struct DLL_EXPORT BattleInfo diff --git a/CMT.cpp b/CMT.cpp index dcf1d4713..63ea49969 100644 --- a/CMT.cpp +++ b/CMT.cpp @@ -52,13 +52,14 @@ std::queue events; boost::mutex eventsM; TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16; namespace intpr = boost::interprocess; -void processCommand(const std::string &message); +void processCommand(const std::string &message, CClient *&client); #ifndef __GNUC__ int _tmain(int argc, _TCHAR* argv[]) #else int main(int argc, char** argv) #endif { + CClient *client = NULL; boost::thread *console = NULL; if(argc>2) { @@ -68,7 +69,7 @@ int main(int argc, char** argv) { logfile = new std::ofstream("VCMI_Client_log.txt"); ::console = new CConsoleHandler; - *::console->cb = &processCommand; + *::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; @@ -212,6 +213,7 @@ int main(int argc, char** argv) } THC tlog0<<"\tConnecting to the server: "<serv && client->serv->connected) //send to server + { + *client->serv << ui16(513) << message; + } } diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index a3365fdb1..c56527893 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -37,6 +37,12 @@ #include #include #include +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif using namespace boost::assign; using namespace CSDL_Ext; @@ -1905,11 +1911,24 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int adventureInt->infoBar.draw(); return; } - +void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero) +{ + boost::unique_lock un(*pim); + SDL_FreeSurface(graphics->heroWins[hero->subID]);//TODO: moznaby zmieniac jedynie fragment bitmapy zwiazany z dana umiejetnoscia + graphics->heroWins[hero->subID] = infoWin(hero); //a nie przerysowywac calosc. Troche roboty, obecnie chyba nie wartej swieczki. + if (adventureInt->selection == hero) + adventureInt->infoBar.draw(); +} +void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero) +{ + boost::unique_lock un(*pim); + if(adventureInt == curint) + adventureInt->heroList.draw(); +} void CPlayerInterface::receivedResource(int type, int val) { boost::unique_lock un(*pim); - if(!curint->subInt) + if(curint==adventureInt || curint==castleInt) adventureInt->resdatabar.draw(); } @@ -1987,8 +2006,8 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj) SDL_FreeSurface(graphics->heroWins[hh->subID]); graphics->heroWins[hh->subID] = infoWin(hh); } - CHeroWindow * hw = dynamic_cast(curint->subInt); - if(hw) + CHeroWindow * hw = adventureInt->heroWindow; + if(hw == curint->subInt) { hw->garInt->recreateSlots(); hw->garInt->show(); @@ -2019,6 +2038,8 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj) LOCPLINT->castleInt->garr->recreateSlots(); } } + if(curint == adventureInt) + adventureInt->infoBar.draw(); } void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished { @@ -2068,23 +2089,25 @@ void CPlayerInterface::battleNewRound(int round) //called at the beggining of ea void CPlayerInterface::actionStarted(const BattleAction* action) { + boost::unique_lock un(*pim); curAction = action; if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber))) && battleInt->creAnims[action->stackNumber]->framesInGroup(20) ) { battleInt->creAnims[action->stackNumber]->setType(20); - if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //deactivating interface when move is started + } + //if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //deactivating interface when move is started { battleInt->deactivate(); } } -} void CPlayerInterface::actionFinished(const BattleAction* action) { + boost::unique_lock un(*pim); curAction = NULL; - if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //activating interface when move is finished + //if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //activating interface when move is finished { battleInt->activate(); } @@ -2238,15 +2261,21 @@ void CPlayerInterface::removeObjToBlit(IShowable* obj) (std::find(objsToBlit.begin(),objsToBlit.end(),obj)); //delete obj; } -void CPlayerInterface::tileRevealed(int3 pos) +void CPlayerInterface::tileRevealed(const std::set &pos) { boost::unique_lock un(*pim); - adventureInt->minimap.showTile(pos); + for(std::set::const_iterator i=pos.begin(); i!=pos.end();i++) + adventureInt->minimap.showTile(*i); + if(curint == adventureInt) + adventureInt->minimap.draw(); } -void CPlayerInterface::tileHidden(int3 pos) +void CPlayerInterface::tileHidden(const std::set &pos) { boost::unique_lock un(*pim); - adventureInt->minimap.hideTile(pos); + for(std::set::const_iterator i=pos.begin(); i!=pos.end();i++) + adventureInt->minimap.hideTile(*i); + if(curint == adventureInt) + adventureInt->minimap.draw(); } void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero) { @@ -2440,8 +2469,8 @@ void CHeroList::select(int which) LOCPLINT->adventureInt->terrain.currentPath = items[which].second; draw(); LOCPLINT->adventureInt->townList.draw(); - LOCPLINT->adventureInt->infoBar.draw(NULL); + LOCPLINT->cb->setSelection(items[which].first); } void CHeroList::clickLeft(tribool down) { @@ -2592,7 +2621,7 @@ void CHeroList::updateMove(const CGHeroInstance* which) //draws move points bar { int ser = LOCPLINT->cb->getHeroSerial(which); ser -= from; - int pom = (which->movement)/100; + int pom = std::min((which->movement)/100,(int)mobile->ourImages.size()-1); blitAt(mobile->ourImages[pom].bitmap,posmobx,posmoby+ser*32); //move point } void CHeroList::draw() diff --git a/CPlayerInterface.h b/CPlayerInterface.h index 4fd73d0a8..2e50c831b 100644 --- a/CPlayerInterface.h +++ b/CPlayerInterface.h @@ -353,13 +353,15 @@ public: void heroKilled(const CGHeroInstance* hero); void heroMoved(const HeroMoveDetails & details); void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val); + void heroManaPointsChanged(const CGHeroInstance * hero); + void heroMovePointsChanged(const CGHeroInstance * hero); void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town); void receivedResource(int type, int val); void showInfoDialog(std::string &text, const std::vector &components); void showSelDialog(std::string &text, const std::vector &components, ui32 askID); void showYesNoDialog(std::string &text, const std::vector &components, ui32 askID); - void tileHidden(int3 pos); - void tileRevealed(int3 pos); + void tileHidden(const std::set &pos); + void tileRevealed(const std::set &pos); void yourTurn(); void availableCreaturesChanged(const CGTownInstance *town); //for battles diff --git a/client/Client.cpp b/client/Client.cpp index e6973f17d..a2ea958de 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -264,6 +264,42 @@ void CClient::process(int what) gs->apply(&vc); break; } + case 110: + { + SetMana sm; + *serv >> sm; + tlog5 << "Setting mana value of hero "<apply(&sm); + CGHeroInstance *h = gs->getHero(sm.hid); + if(vstd::contains(playerint,h->tempOwner)) + playerint[h->tempOwner]->heroManaPointsChanged(h); + break; + } + case 111: + { + SetMovePoints smp; + *serv >> smp; + tlog5 << "Setting movement points of hero "<apply(&smp); + CGHeroInstance *h = gs->getHero(smp.hid); + if(vstd::contains(playerint,h->tempOwner)) + playerint[h->tempOwner]->heroMovePointsChanged(h); + break; + } + case 112: + { + FoWChange fc; + *serv >> fc; + tlog5 << "Changing FoW of player "<<(int)fc.player<apply(&fc); + if(!vstd::contains(playerint,fc.player)) + break; + if(fc.mode) + playerint[fc.player]->tileRevealed(fc.tiles); + else + playerint[fc.player]->tileHidden(fc.tiles); + break; + } case 500: { RemoveObject rh; @@ -299,8 +335,7 @@ void CClient::process(int what) if(playerint[player]) { - for(std::set::iterator i=th->fowRevealed.begin(); i != th->fowRevealed.end(); i++) - playerint[player]->tileRevealed(*i); + playerint[player]->tileRevealed(th->fowRevealed); //std::for_each(th->fowRevealed.begin(),th->fowRevealed.end(),boost::bind(&CGameInterface::tileRevealed,playerint[player],_1)); } @@ -395,6 +430,14 @@ void CClient::process(int what) playerint[t->tempOwner]->heroArtifactSetChanged(t); break; } + case 513: + { + ui8 color; + std::string message; + *serv >> color >> message; + tlog4 << "Player "<<(int)color<<" sends a message: " << message << std::endl; + break; + } case 1001: { SetObjectProperty sop; diff --git a/client/Client.h b/client/Client.h index c6c597836..885b9c4e0 100644 --- a/client/Client.h +++ b/client/Client.h @@ -6,7 +6,8 @@ class CGameState; class CGameInterface; class CConnection; class CCallback; - +class CClient; +void processCommand(const std::string &message, CClient *&client); namespace boost { class mutex; @@ -50,6 +51,7 @@ public: void process(int what); void run(); - friend class CCallback; - friend class CScriptCallback; + friend class CCallback; //handling players actions + friend class CScriptCallback; //for objects scripts + friend void processCommand(const std::string &message, CClient *&client); //handling console }; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 246a0f0ea..5ef2249e9 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -109,6 +109,37 @@ struct ChangeSpells : public CPack //109 h & learn & hid & spells; } }; + +struct SetMana : public CPack //110 +{ + SetMana(){type = 110;}; + ui32 hid, val; + + template void serialize(Handler &h, const int version) + { + h & val & hid; + } +}; +struct SetMovePoints : public CPack //111 +{ + SetMovePoints(){type = 111;}; + ui32 hid, val; + + template void serialize(Handler &h, const int version) + { + h & val & hid; + } +}; +struct FoWChange : public CPack //112 +{ + FoWChange(){type = 112;}; + std::set tiles; + ui8 player, mode; //mode==0 - hide, mode==1 - reveal + template void serialize(Handler &h, const int version) + { + h & tiles & player; + } +}; struct RemoveObject : public CPack //500 { RemoveObject(){type = 500;}; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ef3d767e4..375ae3f98 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -899,6 +899,112 @@ upgend: gs->getHero(hid)->army.formation = formation; break; } + case 513: + { + std::string message; + c >> message; + bool cheated=true; + sendDataToClients(ui16(513)); + sendDataToClients(ui8(*players.begin())); + sendDataToClients(message); + if(message == "vcmiistari") //give all spells and 999 mana + { + SetMana sm; + ChangeSpells cs; + cs.learn = 1; + for(int i=0;ispellh->spells.size();i++) + cs.spells.insert(i); + sm.hid = cs.hid = gs->players[*players.begin()].currentSelection; + sm.val = 999; + if(gs->getHero(cs.hid)) + { + sendAndApply(&cs); + sendAndApply(&sm); + } + } + else if(message == "vcmiainur") //gives 5 archangels into each slot + { + SetGarrisons sg; + CGHeroInstance *hero = gs->getHero(gs->players[*players.begin()].currentSelection); + if(!hero) break; + sg.garrs[hero->id] = hero->army; + for(int i=0;i<7;i++) + if(!vstd::contains(sg.garrs[hero->id].slots,i)) + sg.garrs[hero->id].slots[i] = std::pair(13,5); + sendAndApply(&sg); + } + else if(message == "vcmiangband") //gives 10 black knightinto each slot + { + SetGarrisons sg; + CGHeroInstance *hero = gs->getHero(gs->players[*players.begin()].currentSelection); + if(!hero) break; + sg.garrs[hero->id] = hero->army; + for(int i=0;i<7;i++) + if(!vstd::contains(sg.garrs[hero->id].slots,i)) + sg.garrs[hero->id].slots[i] = std::pair(66,10); + sendAndApply(&sg); + } + else if(message == "vcminoldor") //all war machines + { + CGHeroInstance *hero = gs->getHero(gs->players[*players.begin()].currentSelection); + if(!hero) break; + SetHeroArtifacts sha; + sha.hid = hero->id; + sha.artifacts = hero->artifacts; + sha.artifWorn = hero->artifWorn; + sha.artifWorn[13] = 4; + sha.artifWorn[14] = 5; + sha.artifWorn[15] = 6; + sendAndApply(&sha); + } + else if(message == "vcminahar") //1000000 movement points + { + CGHeroInstance *hero = gs->getHero(gs->players[*players.begin()].currentSelection); + if(!hero) break; + SetMovePoints smp; + smp.hid = hero->id; + smp.val = 1000000; + sendAndApply(&smp); + } + else if(message == "vcmiformenos") //give resources + { + SetResources sr; + sr.player = *players.begin(); + sr.res = gs->players[sr.player].resources; + for(int i=0;i<7;i++) + sr.res[i] += 100; + sr.res[6] += 19900; + sendAndApply(&sr); + } + else if(message == "vcmieagles") //reveal FoW + { + FoWChange fc; + fc.player = *players.begin(); + for(int i=0;imap->width;i++) + for(int j=0;jmap->height;j++) + for(int k=0;kmap->twoLevel+1;k++) + if(!gs->players[fc.player].fogOfWarMap[i][j][k]) + fc.tiles.insert(int3(i,j,k)); + sendAndApply(&fc); + } + else + cheated = false; + if(cheated) + { + message = "CHEATER!!!"; + sendDataToClients(ui16(513)); + sendDataToClients(ui8(*players.begin())); + sendDataToClients(message); + } + break; + } + case 514: + { + ui32 id; + c >> id; + gs->players[*players.begin()].currentSelection = id; + break; + } case 2001: { ui32 qid, answer; @@ -1269,7 +1375,7 @@ void CGameHandler::newTurn() NewTurn::Hero hth; hth.id = h->id; hth.move = valMovePoints(h, true); //TODO: check if hero is really on the land - hth.mana = std::min(h->mana+1+h->getSecSkillLevel(8), h->manaLimit()); //hero regains 1 mana point + mysticism lvel + hth.mana = std::max(h->mana,std::min(h->mana+1+h->getSecSkillLevel(8), h->manaLimit())); //hero regains 1 mana point + mysticism lvel n.heroes.insert(hth); switch(h->getSecSkillLevel(13)) //handle estates - give gols diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index e6fb04078..4f1a7e064 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -156,7 +156,7 @@ int main(int argc, char** argv) { logfile = new std::ofstream("VCMI_Server_log.txt"); console = new CConsoleHandler; - boost::thread t(boost::bind(&CConsoleHandler::run,::console)); + //boost::thread t(boost::bind(&CConsoleHandler::run,::console)); if(argc > 1) { #ifdef _MSC_VER