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

* magic well support

* improvements in the recruitment window
* improvements for pregame  
[cf http://vcmi.antypika.aplus.pl/forum/viewtopic.php?t=97 issues 12-15 and 21 - 22]
* minor changes
This commit is contained in:
Michał W. Urbańczyk 2009-02-06 11:15:39 +00:00
parent 72bc53a1b9
commit 05b3e3215c
16 changed files with 203 additions and 70 deletions

View File

@ -40,6 +40,13 @@ AdventureMapButton::AdventureMapButton( const std::string &Name, const std::stri
pom[0] = Name;
init(Callback, pom, HelpBox, info->playerColoured, info->defName, &info->additionalDefs, info->x, info->y, key);
}
AdventureMapButton::AdventureMapButton( const std::pair<std::string, std::string> help, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key/*=0*/, std::vector<std::string> * add /*= NULL*/, bool playerColoredButton /*= false */ )
{
std::map<int,std::string> pom;
pom[0] = help.first;
init(Callback, pom, help.second, playerColoredButton, defName, add, x, y, key);
}
void AdventureMapButton::clickLeft (tribool down)
{
if(blocked)
@ -79,7 +86,7 @@ void AdventureMapButton::hover (bool on)
std::string *name = (vstd::contains(hoverTexts,state))
? (&hoverTexts[state])
: (vstd::contains(hoverTexts,0) ? (&hoverTexts[0]) : NULL);
if(name) //if there is no name, there is nohing to display also
if(name && !blocked) //if there is no name, there is nohing to display also
{
if (LOCPLINT->curint == static_cast<CMainInterface*>(LOCPLINT->battleInt)) //for battle buttons
{

View File

@ -29,6 +29,7 @@ public:
AdventureMapButton(); //c-tor
AdventureMapButton( const std::map<int,std::string> &, const std::string &HelpBox, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
AdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
AdventureMapButton( const std::pair<std::string, std::string> help, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
AdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList<void()> &Callback, config::ButtonInfo *info, int key=0);//c-tor
//AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ=false, std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor

View File

@ -434,7 +434,6 @@ CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, con
}
}
void CGameState::applyNL(IPack * pack)
{
switch(pack->getType())
@ -455,6 +454,11 @@ void CGameState::applyNL(IPack * pack)
if(n->resetBuilded) //reset amount of structures set in this turn in towns
BOOST_FOREACH(CGTownInstance* t, map->towns)
t->builded = 0;
BOOST_FOREACH(CGHeroInstance *h, map->heroes)
h->bonuses.remove_if(HeroBonus::OneDay);
if(getDate(1) == 7) //new week
BOOST_FOREACH(CGHeroInstance *h, map->heroes)
h->bonuses.remove_if(HeroBonus::OneDay);
break;
}
case 102: //set resource amount

View File

@ -2372,6 +2372,7 @@ void CPlayerInterface::availableCreaturesChanged( const CGTownInstance *town )
void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const HeroBonus &bonus, bool gain )
{
if(bonus.type == HeroBonus::NONE) return;
boost::unique_lock<boost::recursive_mutex> un(*pim);
redrawHeroWin(hero);
}
@ -2989,6 +2990,7 @@ void CRecrutationWindow::Cancel()
}
void CRecrutationWindow::sliderMoved(int to)
{
buy->block(!to);
}
void CRecrutationWindow::clickLeft(tribool down)
{
@ -3045,6 +3047,7 @@ void CRecrutationWindow::activate()
max->activate();
cancel->activate();
slider->activate();
LOCPLINT->statusbar = bar;
}
void CRecrutationWindow::deactivate()
{
@ -3089,6 +3092,7 @@ void CRecrutationWindow::show(SDL_Surface * to)
curx += 120;
}
c++;
bar->show();
}
CRecrutationWindow::CRecrutationWindow(const std::vector<std::pair<int,int> > &Creatures, const boost::function<void(int,int)> &Recruit) //creatures - pairs<creature_ID,amount>
:recruit(Recruit)
@ -3115,6 +3119,10 @@ CRecrutationWindow::CRecrutationWindow(const std::vector<std::pair<int,int> > &C
pos.y = screen->h/2 - bitmap->h/2;
pos.w = bitmap->w;
pos.h = bitmap->h;
bar = new CStatusBar(pos.x+8, pos.y+370, "APHLFTRT.bmp", 471);
max = new AdventureMapButton(CGI->generaltexth->zelp[553],boost::bind(&CRecrutationWindow::Max,this),pos.x+134,pos.y+313,"IRCBTNS.DEF",SDLK_m);
buy = new AdventureMapButton(CGI->generaltexth->zelp[554],boost::bind(&CRecrutationWindow::Buy,this),pos.x+212,pos.y+313,"IBY6432.DEF",SDLK_RETURN);
cancel = new AdventureMapButton(CGI->generaltexth->zelp[555],boost::bind(&CRecrutationWindow::Cancel,this),pos.x+290,pos.y+313,"ICN6432.DEF",SDLK_ESCAPE);
slider = new CSlider(pos.x+176,pos.y+279,135,boost::bind(&CRecrutationWindow::sliderMoved,this, _1),1,std::min(amounts[0],creatures[0].amount),0,true);
std::string pom;
printAtMiddle(CGI->generaltexth->allTexts[346],113,231,GEOR13,zwykly,bitmap); //cost per troop t
@ -3144,14 +3152,12 @@ CRecrutationWindow::CRecrutationWindow(const std::vector<std::pair<int,int> > &C
curx += 120;
}
max = new AdventureMapButton("","",boost::bind(&CRecrutationWindow::Max,this),pos.x+134,pos.y+313,"IRCBTNS.DEF",SDLK_m);
buy = new AdventureMapButton("","",boost::bind(&CRecrutationWindow::Buy,this),pos.x+212,pos.y+313,"IBY6432.DEF",SDLK_RETURN);
cancel = new AdventureMapButton("","",boost::bind(&CRecrutationWindow::Cancel,this),pos.x+290,pos.y+313,"ICN6432.DEF",SDLK_ESCAPE);
if(!creatures[0].amount)
if(!creatures[0].amount || !amounts[0])
{
max->block(true);
buy->block(true);
slider->block(true);
}
//buy->block(true); //not needed, will be blocked by initing slider on 0
}
CRecrutationWindow::~CRecrutationWindow()
{
@ -3164,6 +3170,7 @@ CRecrutationWindow::~CRecrutationWindow()
delete cancel;
SDL_FreeSurface(bitmap);
delete slider;
delete bar;
}
CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner)

View File

@ -527,6 +527,7 @@ public:
CSlider *slider;
AdventureMapButton *max, *buy, *cancel;
SDL_Surface *bitmap;
CStatusBar *bar;
int which; //which creature is active
void close();

View File

@ -38,6 +38,48 @@ CPreGame * CPG;
namespace fs = boost::filesystem;
namespace s = CSDL_Ext;
int getNextCastle(int current, PlayerInfo * ourInf, bool next=true) //next=flase => previous castle
{
int dir = next ? 1 : -1;
if (current==-2) //no castle - no change
return current;
else if (current==-1) //random => first/last available
{
int pom = (next) ? (0) : (F_NUMBER-1); // last or first
for (;pom>=0 && pom<F_NUMBER;pom+=dir)
{
if (((int)pow((double)2,pom))&ourInf->allowedFactions)
{
current=pom;
break;
}
else continue;
}
}
else // next/previous available
{
for (;;)
{
current+=dir;
if (((int)pow((double)2,(int)current))&ourInf->allowedFactions)
{
break;
}
if (current>=F_NUMBER || current<0)
{
double p1 = log((double)ourInf->allowedFactions)/log(2.0f)+0.000001f;
double check = p1-((int)p1);
if (check < 0.001)
current=(int)p1;
else
current=-1;
break;
}
}
}
return current;
}
HighButton::HighButton( SDL_Rect Pos, CDefHandler* Imgs, bool Sel, int id)
{
type=0;
@ -441,6 +483,7 @@ int Options::nextAllowedHero(int min, int max, int incl, int dir) //incl 0 - wla
}
return -1;
}
void Options::OptionSwitch::press(bool down)
{
HighButton::press(down);
@ -452,50 +495,21 @@ void Options::OptionSwitch::press(bool down)
{
case -1: //castle change
{
int oCas = ourOpt->castle;
if (ourOpt->castle==-2) //no castle - no change
return;
else if (ourOpt->castle==-1) //random => first/last available
{
int pom = (left) ? (F_NUMBER-1) : (0); // last or first
for (;pom>=0 && pom<F_NUMBER;pom+=dir)
{
if (((int)pow((double)2,pom))&ourInf->allowedFactions)
{
ourOpt->castle=pom;
break;
}
else continue;
}
}
else // next/previous available
{
for (;;)
{
ourOpt->castle+=dir;
if (((int)pow((double)2,(int)ourOpt->castle))&ourInf->allowedFactions)
{
break;
}
if (ourOpt->castle>=F_NUMBER || ourOpt->castle<0)
{
double p1 = log((double)ourInf->allowedFactions)/log(2.0f)+0.000001f;
double check = p1-((int)p1);
if (check < 0.001)
ourOpt->castle=(int)p1;
else
ourOpt->castle=-1;
break;
}
}
}
int nCas = getNextCastle(ourOpt->castle,ourInf,!left);
if (oCas!=ourOpt->castle) //changed castle
if (nCas!=ourOpt->castle) //changed castle
{
ourOpt->hero=-1;
ourOpt->bonus = brandom;
CPG->ourOptions->showIcon(0,serialID,false);
CPG->ourOptions->showIcon(1,serialID,false);
ourOpt->castle = nCas;
if(ourOpt->hero != -2)
{
ourOpt->hero=-1;
CPG->ourOptions->showIcon(0,serialID,false);
}
if(ourOpt->bonus==bresource)
{
ourOpt->bonus = brandom;
CPG->ourOptions->showIcon(1,serialID,false);
}
}
break;
}
@ -754,18 +768,29 @@ void Options::show()
poptions.push_back(new PlayerOptions(playersSoFar,i));
poptions[poptions.size()-1]->nr=playersSoFar;
poptions[poptions.size()-1]->color=(Ecolor)i;
poptions[poptions.size()-1]->Cleft.show();
poptions[poptions.size()-1]->Cright.show();
poptions[poptions.size()-1]->Hleft.show();
poptions[poptions.size()-1]->Hright.show();
if(CPG->ret.playerInfos[playersSoFar].hero != -2)
{
poptions[poptions.size()-1]->Hleft.show();
poptions[poptions.size()-1]->Hright.show();
CPG->btns.push_back(&poptions[poptions.size()-1]->Hleft);
CPG->btns.push_back(&poptions[poptions.size()-1]->Hright);
}
if(getNextCastle(CPG->ret.playerInfos[playersSoFar].castle,&ms.ourMaps[ms.selected].players[i]) != CPG->ret.playerInfos[playersSoFar].castle)
{
poptions[poptions.size()-1]->Cleft.show();
poptions[poptions.size()-1]->Cright.show();
CPG->btns.push_back(&poptions[poptions.size()-1]->Cleft);
CPG->btns.push_back(&poptions[poptions.size()-1]->Cright);
}
poptions[poptions.size()-1]->Bleft.show();
poptions[poptions.size()-1]->Bright.show();
CPG->btns.push_back(&poptions[poptions.size()-1]->Cleft);
CPG->btns.push_back(&poptions[poptions.size()-1]->Cright);
CPG->btns.push_back(&poptions[poptions.size()-1]->Hleft);
CPG->btns.push_back(&poptions[poptions.size()-1]->Hright);
CPG->btns.push_back(&poptions[poptions.size()-1]->Bleft);
CPG->btns.push_back(&poptions[poptions.size()-1]->Bright);
CSDL_Ext::printAtMiddle(CPG->ret.playerInfos[playersSoFar].name,111,137+playersSoFar*50,GEOR13,zwykly);
if (ms.ourMaps[ms.selected].players[i].canHumanPlay)
{
@ -1289,7 +1314,7 @@ void MapSel::select(int which, bool updateMapsList, bool forceSettingsUpdate)
}
pset.heroPortrait=-1;
if (!
((curVector()[which].players[i].generateHeroAtMainTown
(((curVector()[which].players[i].generateHeroAtMainTown || curVector()[which].version==RoE)
&& curVector()[which].players[i].hasMainTown)
|| curVector()[which].players[i].p8)
)

View File

@ -15,6 +15,7 @@ TOWN INTERFACE:
OBJECTS:
New objects supported:
* Magic Well
* Faerie Ring
* Swan Pond
* Idol of Fortune

View File

@ -87,6 +87,7 @@ public:
void moveHero(int hid, int3 pos, bool instant){};
void giveHeroBonus(GiveBonus * bonus){};
void setMovePoints(SetMovePoints * smp){};
void setManaPoints(int hid, int val){};
//////////////////////////////////////////////////////////////////////////
friend class CCallback; //handling players actions
friend void processCommand(const std::string &message, CClient *&client); //handling console

View File

@ -1719,6 +1719,49 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
}
const std::string & CGBonusingObject::getHoverText() const
{
const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
hoverName = VLC->generaltexth->names[ID];
if(h)
{
if(!h->getBonus(HeroBonus::OBJECT,ID))
hoverName += " " + VLC->generaltexth->allTexts[353]; //not visited
else
hoverName += " " + VLC->generaltexth->allTexts[352]; //visited
}
return hoverName;
}
void CGMagicWell::onHeroVisit( const CGHeroInstance * h ) const
{
int message;
InfoWindow iw;
iw.player = h->tempOwner;
if(h->getBonus(HeroBonus::OBJECT,ID)) //has already visited Well today
{
message = 78;
}
else if(h->mana < h->manaLimit())
{
GiveBonus gbonus;
gbonus.bonus.type = HeroBonus::NONE;
gbonus.hid = h->id;
gbonus.bonus.duration = HeroBonus::ONE_DAY;
gbonus.bonus.source = HeroBonus::OBJECT;
gbonus.bonus.id = ID;
cb->giveHeroBonus(&gbonus);
cb->setManaPoints(h->id,h->manaLimit());
message = 77;
}
else
{
message = 79;
}
iw.text << std::pair<ui8,ui32>(11,message); //"A second drink at the well in one day will not help you."
cb->showInfoDialog(&iw);
}
const std::string & CGMagicWell::getHoverText() const
{
const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
hoverName = VLC->generaltexth->names[ID];

View File

@ -623,6 +623,19 @@ public:
}
};
class DLL_EXPORT CGMagicWell : public CGObjectInstance //objects giving bonuses to luck/morale/movement
{
public:
void onHeroVisit(const CGHeroInstance * h) const;
const std::string & getHoverText() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);
}
};
class DLL_EXPORT CObjectHandler

View File

@ -23,4 +23,17 @@ struct DLL_EXPORT HeroBonus
{
h & duration & type & source & val & id & description;
}
};
static bool OneDay(const HeroBonus &hb)
{
return hb.duration==HeroBonus::ONE_DAY;
}
static bool OneWeek(const HeroBonus &hb)
{
return hb.duration==HeroBonus::ONE_WEEK;
}
static bool OneBattle(const HeroBonus &hb)
{
return hb.duration==HeroBonus::ONE_BATTLE;
}
};

View File

@ -59,5 +59,6 @@ public:
virtual void moveHero(int hid, int3 pos, bool instant)=0;
virtual void giveHeroBonus(GiveBonus * bonus)=0;
virtual void setMovePoints(SetMovePoints * smp)=0;
virtual void setManaPoints(int hid, int val)=0;
};
#endif // __IGAMECALLBACK_H__

17
map.cpp
View File

@ -1790,6 +1790,11 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
nobj = new CGBonusingObject();
break;
}
case 49: //Magic Well
{
nobj = new CGMagicWell();
break;
}
case 214: //hero placeholder
{
i+=3; //TODO: handle it more properly
@ -1830,13 +1835,11 @@ void Mapa::readEvents( unsigned char * bufor, int &i )
{
ne.message +=bufor[i]; ++i;
}
ne.wood = readNormalNr(bufor,i); i+=4;
ne.mercury = readNormalNr(bufor,i); i+=4;
ne.ore = readNormalNr(bufor,i); i+=4;
ne.sulfur = readNormalNr(bufor,i); i+=4;
ne.crystal = readNormalNr(bufor,i); i+=4;
ne.gems = readNormalNr(bufor,i); i+=4;
ne.gold = readNormalNr(bufor,i); i+=4;
ne.resources.resize(RESOURCE_QUANTITY);
for(int k=0; k < 7; k++)
{
ne.resources[k] = readNormalNr(bufor,i); i+=4;
}
ne.players = bufor[i]; ++i;
if(version>AB)
{

12
map.h
View File

@ -7,6 +7,7 @@
#include <vector>
#include <map>
#include <set>
#include <list>
#include "global.h"
#ifndef _MSC_VER
#include "hch/CObjectHandler.h"
@ -185,15 +186,15 @@ class DLL_EXPORT CMapEvent
{
public:
std::string name, message;
si32 wood, mercury, ore, sulfur, crystal, gems, gold; //gained / taken resources
std::vector<si32> resources; //gained / taken resources
ui8 players; //affected players
ui8 humanAffected;
ui8 computerAffected;
ui32 firstOccurence;
ui32 nextOccurence; //after nextOccurance day event will occure; if it it 0, event occures only one time;
ui32 nextOccurence; //after nextOccurance day event will occur; if it it 0, event occures only one time;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & name & message & wood & mercury & ore & sulfur & crystal & gems & gold
h & name & message & resources
& players & humanAffected & computerAffected & firstOccurence & nextOccurence;
}
};
@ -296,7 +297,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
std::vector<ui8> allowedArtifact; //allowedArtifact[artifact_ID] - if the artifact is allowed
std::vector<ui8> allowedAbilities; //allowedAbilities[ability_ID] - if the ability is allowed
std::vector<ui8> allowedHeroes; //allowedHeroes[hero_ID] - if the hero is allowed
std::vector<CMapEvent> events;
std::list<CMapEvent> events;
int3 grailPos;
int grailRadious;
@ -506,6 +507,9 @@ struct DLL_EXPORT Mapa : public CMapHeader
case 31: //Fountain of Youth
SERIALIZE(CGBonusingObject);
break;
case 49: //Magic Well
SERIALIZE(CGMagicWell);
break;
default:
SERIALIZE(CGObjectInstance);
}

View File

@ -2459,4 +2459,12 @@ void CGameHandler::giveHeroBonus( GiveBonus * bonus )
void CGameHandler::setMovePoints( SetMovePoints * smp )
{
sendAndApply(smp);
}
void CGameHandler::setManaPoints( int hid, int val )
{
SetMana sm;
sm.hid = hid;
sm.val = val;
sendAndApply(&sm);
}

View File

@ -105,6 +105,7 @@ public:
void moveHero(int hid, int3 pos, bool instant);
void giveHeroBonus(GiveBonus * bonus);
void setMovePoints(SetMovePoints * smp);
void setManaPoints(int hid, int val);
//////////////////////////////////////////////////////////////////////////
void init(StartInfo *si, int Seed);