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

Partially done support for external creature dwellings.

This commit is contained in:
Michał W. Urbańczyk 2009-07-06 19:41:27 +00:00
parent 2f73b6cd1e
commit b551f6a72b
18 changed files with 306 additions and 163 deletions

View File

@ -28,6 +28,7 @@ struct TryMoveHero;
class CGHeroInstance;
class CGTownInstance;
class CGObjectInstance;
class CGDwelling;
class CCreatureSet;
class CArmedInstance;
struct BattleResult;
@ -81,6 +82,7 @@ public:
virtual void init(ICallback * CB){};
virtual void receivedResource(int type, int val){};
virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID){};
virtual void showRecruitmentDialog(const CGDwelling *dwelling, int level){}
//virtual void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){};
//virtual void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){};
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.

View File

@ -932,15 +932,19 @@ void CCastleInterface::recreateBuildings()
CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building )
{
if(building>36)
if(building>36) //upg dwelling
building-=7;
int level = building-30;
assert(level >= 0 && level <= 6);
std::vector<std::pair<int,int > > crs;
int amount = (const_cast<CGTownInstance*>(town))->strInfo.creatures[building-30]; //trzeba odconstowac, bo inaczej operator [] by sypal :(
int amount = town->creatures[level].first;
if(town->builtBuildings.find(building+7) != town->builtBuildings.end()) //check if there is an upgraded building
crs.push_back(std::make_pair(town->town->upgradedCreatures[building-30],amount));
const std::vector<ui32> &cres = town->creatures[level].second;
crs.push_back(std::make_pair(town->town->basicCreatures[building-30],amount));
for(size_t i = 0; i < cres.size(); i++)
crs.push_back(std::make_pair((int)cres[i],amount));
CRecruitmentWindow *rw = new CRecruitmentWindow(crs,boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2));
LOCPLINT->pushInt(rw);
@ -1436,7 +1440,7 @@ void CFortScreen::draw( CCastleInterface * owner, bool first)
printAtMiddle(CGI->buildh->buildings[owner->town->subID][30+i+upgraded*7]->Name(),positions[i].x+79,positions[i].y+100,GEOR13,zwykly,bg); //dwelling name
if(present) //if creature is present print avail able quantity
{
SDL_itoa(owner->town->strInfo.creatures.find(i)->second,buf,10);
SDL_itoa(owner->town->creatures[i].first,buf,10);
printAtMiddle(CGI->generaltexth->allTexts[217] + buf,positions[i].x+79,positions[i].y+118,GEOR13,zwykly,bg);
}
blitAt(icons,positions[i].x+261,positions[i].y+3,bg);

View File

@ -122,7 +122,7 @@ void init()
tlog0<<"Screen handler: "<<pomtime.getDif()<<std::endl;
pomtime.getDif();
graphics = new Graphics();
graphics->loadHeroAnim();
graphics->loadHeroAnims();
tlog0<<"\tMain graphics: "<<tmh.getDif()<<std::endl;
tlog0<<"Initializing game graphics: "<<tmh.getDif()<<std::endl;

View File

@ -1756,3 +1756,16 @@ const CGHeroInstance * CPlayerInterface::getWHero( int pos )
return NULL;
return wanderingHeroes[pos];
}
void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int level)
{
std::vector<std::pair<int,int> > cres;
for(int i = 0; i < dwelling->creatures.size(); i++)
{
if(i == level || level < 0)
for(size_t j = 0; j < dwelling->creatures[i].second.size(); j++)
cres.push_back( std::make_pair(dwelling->creatures[i].second[j],dwelling->creatures[i].first));
}
CRecruitmentWindow *cr = new CRecruitmentWindow(cres, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2));
pushInt(cr);
}

View File

@ -134,8 +134,7 @@ public:
void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
void receivedResource(int type, int val);
void showInfoDialog(const std::string &text, const std::vector<Component*> &components, int soundID);
//void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID);
//void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID);
void showRecruitmentDialog(const CGDwelling *dwelling, int level);
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd);
void tileHidden(const std::set<int3> &pos); //called when given tiles become hidden under fog of war

View File

@ -305,32 +305,42 @@ void Graphics::loadHeroPortraits()
}
of.close();
}
void Graphics::loadHeroAnim()
void Graphics::loadHeroAnims()
{
heroAnims.resize(F_NUMBER * 2);
std::vector<std::pair<int,int> > rotations; //first - group number to be rotated1, second - group number after rotation1
rotations += std::make_pair(6,10), std::make_pair(7,11), std::make_pair(8,12), std::make_pair(1,13),
std::make_pair(2,14), std::make_pair(3,15);
for(size_t i=0; i<heroAnims.size(); ++i)
for(size_t i=0; i<F_NUMBER * 2; ++i)
{
std::ostringstream nm;
nm << "AH" << std::setw(2) << std::setfill('0') << i << "_.DEF";
loadHeroAnim(nm.str(), rotations, &Graphics::heroAnims);
std::string name = nm.str();
heroAnims[i] = CDefHandler::giveDefEss(name);
}
loadHeroAnim("AB01_.DEF", rotations, &Graphics::boatAnims);
loadHeroAnim("AB02_.DEF", rotations, &Graphics::boatAnims);
loadHeroAnim("AB03_.DEF", rotations, &Graphics::boatAnims);
}
void Graphics::loadHeroAnim( const std::string &name, const std::vector<std::pair<int,int> > &rotations, std::vector<CDefEssential *> Graphics::*dst )
{
CDefEssential *anim = CDefHandler::giveDefEss(name);
heroAnims.push_back(anim);
int pom = 0; //how many groups has been rotated
for(int o=7; pom<6; ++o)
{
for(int p=0;p<6;p++)
{
if(heroAnims[i]->ourImages[o].groupNumber==rotations[p].first)
if(anim->ourImages[o].groupNumber == rotations[p].first)
{
for(int e=0; e<8; ++e)
{
Cimage nci;
nci.bitmap = CSDL_Ext::rotate01(heroAnims[i]->ourImages[o+e].bitmap);
nci.bitmap = CSDL_Ext::rotate01(anim->ourImages[o+e].bitmap);
nci.groupNumber = rotations[p].second;
nci.imName = std::string();
heroAnims[i]->ourImages.push_back(nci);
anim->ourImages.push_back(nci);
if(pom>2) //we need only one frame for groups 13/14/15
break;
}
@ -344,10 +354,9 @@ void Graphics::loadHeroAnim()
}
}
}
for(size_t ff=0; ff<heroAnims[i]->ourImages.size(); ++ff)
for(size_t ff=0; ff<anim->ourImages.size(); ++ff)
{
CSDL_Ext::alphaTransform(heroAnims[i]->ourImages[ff].bitmap);
}
CSDL_Ext::alphaTransform(anim->ourImages[ff].bitmap);
}
}

View File

@ -48,6 +48,7 @@ public:
CDefEssential * smallIcons, *resources32; //resources 32x32
CDefEssential * flags;
std::vector<CDefEssential *> heroAnims; // [class id: 0 - 17] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing
std::vector<CDefEssential *> boatAnims; // [boat type: 0 - 3] //added group 10: up - left, 11 - left and 12 - left down // 13 - up-left standing; 14 - left standing; 15 - left down standing
//creatures
std::map<int,SDL_Surface*> smallImgs; //creature ID -> small 32x32 img of creature; //ID=-2 is for blank (black) img; -1 for the border
std::map<int,SDL_Surface*> bigImgs; //creature ID -> big 58x64 img of creature; //ID=-2 is for blank (black) img; -1 for the border
@ -69,7 +70,8 @@ public:
void loadPaletteAndColors();
void loadHeroFlags();
void loadHeroFlags(std::pair<std::vector<CDefEssential *> Graphics::*, std::vector<const char *> > &pr, bool mode);
void loadHeroAnim();
void loadHeroAnims();
void loadHeroAnim(const std::string &name, const std::vector<std::pair<int,int> > &rotations, std::vector<CDefEssential *> Graphics::*dst);
void loadHeroPortraits();
SDL_Surface * drawHeroInfoWin(const CGHeroInstance * curh);
SDL_Surface * drawPrimarySkill(const CGHeroInstance *curh, SDL_Surface *ret, int from=0, int to=PRIMARY_SKILLS);

View File

@ -459,11 +459,27 @@ void ShowInInfobox::applyCl(CClient *cl)
}
}
void HeroExchange::applyFirstCl(CClient *cl)
void OpenWindow::applyFirstCl(CClient *cl)
{
}
void HeroExchange::applyCl(CClient *cl)
void OpenWindow::applyCl(CClient *cl)
{
cl->playerint[player]->heroExchangeStarted(hero1, hero2);
switch(window)
{
case EXCHANGE_WINDOW:
{
const CGHeroInstance *h = cl->getHero(id1);
const CGObjectInstance *h2 = cl->getHero(id2);
assert(h && h2);
INTERFACE_CALL_IF_PRESENT(h->tempOwner,heroExchangeStarted, id1, id2);
}
break;
case RECRUITMENT_FIRST:
{
const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl->getObj(id1));
INTERFACE_CALL_IF_PRESENT(dw->tempOwner,showRecruitmentDialog, dw, 0);
}
}
}

View File

@ -903,6 +903,77 @@ si32 CGHeroInstance::getArtPos(int aid) const
return -1;
}
void CGDwelling::initObj()
{
switch(ID)
{
case 17:
creatures.resize(1);
creatures[0].second.push_back(VLC->objh->cregens[subID]);
break;
case 20:
creatures.resize(4);
if(subID == 1) // Elemental Conflux
{
creatures[0].second.push_back(32); //Stone Golem
creatures[1].second.push_back(33); //Iron Golem
creatures[2].second.push_back(116); //Gold Golem
creatures[3].second.push_back(117); //Diamond Golem
}
else if(subID == 1) //Golem Factory
{
creatures[0].second.push_back(112); //Air Elemental
creatures[1].second.push_back(113); //Earth Elemental
creatures[2].second.push_back(114); //Fire Elemental
creatures[3].second.push_back(115); //Water Elemental
}
else
{
assert(0);
}
break;
default:
assert(0);
break;
}
}
void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
{
if(h->tempOwner != tempOwner)
cb->setOwner(id, h->tempOwner);
OpenWindow ow;
ow.id1 = id;
ow.id2 = id;
ow.window = OpenWindow::RECRUITMENT_FIRST;
cb->sendAndApply(&ow);
}
void CGDwelling::newTurn() const
{
if(cb->getDate(1) != 1) //not first day of week
return;
bool change = false;
SetAvailableCreatures sac;
sac.creatures = creatures;
sac.tid = id;
for (size_t i = 0; i < creatures.size(); i++)
{
if(creatures[i].second.size())
{
sac.creatures[i].first += VLC->creh->creatures[creatures[i].second[0]].growth;
change = true;
}
}
if(change)
cb->sendAndApply(&sac);
}
int CGTownInstance::getSightRadious() const //returns sight distance
{
return 5;
@ -1042,6 +1113,15 @@ void CGTownInstance::initObj()
MetaString ms;
ms << name << ", " << town->Name();
hoverName = toString(ms);
creatures.resize(CREATURES_PER_TOWN);
for (int i = 0; i < CREATURES_PER_TOWN; i++)
{
if(creatureDwelling(i,false))
creatures[i].second.push_back(town->basicCreatures[i]);
if(creatureDwelling(i,true))
creatures[i].second.push_back(town->upgradedCreatures[i]);
}
}
int3 CGTownInstance::getSightCenter() const
@ -2144,17 +2224,6 @@ const std::string & CGWitchHut::getHoverText() const
return hoverName;
}
void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
{
}
void CGDwelling::initObj()
{
}
void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
{
bool visited = h->getBonus(HeroBonus::OBJECT,ID);

View File

@ -284,7 +284,22 @@ public:
void onHeroVisit(const CGHeroInstance * h) const;
};
class DLL_EXPORT CGTownInstance : public CArmedInstance
class DLL_EXPORT CGDwelling : public CArmedInstance
{
public:
std::vector<std::pair<ui32, std::vector<ui32> > > creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount>
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CArmedInstance&>(*this) & creatures;
}
void initObj();
void onHeroVisit(const CGHeroInstance * h) const;
void newTurn() const;
};
class DLL_EXPORT CGTownInstance : public CGDwelling
{
public:
CTown * town;
@ -298,15 +313,15 @@ public:
std::vector<ui32> possibleSpells, obligatorySpells;
std::vector<std::vector<ui32> > spells; //spells[level] -> vector of spells, first will be available in guild
struct StrInfo
{
std::map<si32,ui32> creatures; //level - available amount
//struct StrInfo
//{
// std::map<si32,ui32> creatures; //level - available amount
template <typename Handler> void serialize(Handler &h, const int version)
{
h & creatures;
}
} strInfo;
// template <typename Handler> void serialize(Handler &h, const int version)
// {
// h & creatures;
// }
//} strInfo;
std::set<CCastleEvent> events;
//////////////////////////////////////////////////////////////////////////
@ -316,7 +331,7 @@ public:
{
h & static_cast<CArmedInstance&>(*this);
h & name & builded & destroyed & identifier & alignment & forbiddenBuildings & builtBuildings
& possibleSpells & obligatorySpells & spells & strInfo & events;
& possibleSpells & obligatorySpells & spells & /*strInfo & */events;
ui8 standardType = (&VLC->townh->towns[subID] == town);
h & standardType;
@ -666,19 +681,6 @@ public:
}
};
class DLL_EXPORT CGDwelling : public CGObjectInstance //teleports and subterranean gates
{
public:
static std::map<int,std::map<int, std::vector<int> > > objs; //map[ID][subID] => vector of ids
void onHeroVisit(const CGHeroInstance * h) const;
void initObj();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);
}
};
class DLL_EXPORT CGBonusingObject : public CGObjectInstance //objects giving bonuses to luck/morale/movement
{
public:

View File

@ -1343,11 +1343,12 @@ int CGameState::battleGetBattlefieldType(int3 tile)
else if(tile==int3() && !curB)
return -1;
std::vector <CGObjectInstance*> & objs = map->objects;
const std::vector <CGObjectInstance*> & objs = map->objects;
for(int g=0; g<objs.size(); ++g)
{
if( objs[g]->pos.x - tile.x < 0 || objs[g]->pos.x - tile.x >= 8 || tile.y - objs[g]->pos.y + 5 < 0 || tile.y - objs[g]->pos.y + 5 >=6 ||
!objs[g]->coveringAt(objs[g]->pos.x - tile.x, tile.y - objs[g]->pos.y + 5)
if( !objs[g] || objs[g]->pos.x - tile.x < 0 || objs[g]->pos.x - tile.x >= 8
|| tile.y - objs[g]->pos.y + 5 < 0 || tile.y - objs[g]->pos.y + 5 >=6
|| !objs[g]->coveringAt(objs[g]->pos.x - tile.x, tile.y - objs[g]->pos.y + 5)
) //look only for objects covering given tile
continue;
switch(objs[g]->ID)

View File

@ -409,7 +409,7 @@ struct SetAvailableCreatures : public CPackForClient //506
DLL_EXPORT void applyGs(CGameState *gs);
si32 tid;
std::map<si32,ui32> creatures;
std::vector<std::pair<ui32, std::vector<ui32> > > creatures;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -480,19 +480,20 @@ struct GiveHero : public CPackForClient //516
}
};
struct HeroExchange : public CPackForClient //517
struct OpenWindow : public CPackForClient //517
{
HeroExchange(){type = 517;};
OpenWindow(){type = 517;};
void applyFirstCl(CClient *cl);
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
si32 hero1, hero2; //heroes for exchange
ui8 player;
enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL};
ui8 window;
ui32 id1, id2;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & hero1 & hero2 & player;
h & window & id1 & id2;
}
};

View File

@ -278,7 +278,7 @@ DLL_EXPORT void NewStructures::applyGs( CGameState *gs )
DLL_EXPORT void SetAvailableCreatures::applyGs( CGameState *gs )
{
gs->getTown(tid)->strInfo.creatures = creatures;
gs->getTown(tid)->creatures = creatures;
}
DLL_EXPORT void SetHeroesInTown::applyGs( CGameState *gs )
@ -418,7 +418,7 @@ DLL_EXPORT void GiveHero::applyGs( CGameState *gs )
h->inTownGarrison = false;
}
DLL_EXPORT void HeroExchange::applyGs(CGameState *gs)
DLL_EXPORT void OpenWindow::applyGs(CGameState *gs)
{
}

View File

@ -93,7 +93,7 @@ void registerTypes2(Serializer &s)
s.template registerType<SetStackEffect>();
s.template registerType<StacksInjured>();
s.template registerType<ShowInInfobox>();
s.template registerType<HeroExchange>();
s.template registerType<OpenWindow>();
s.template registerType<SaveGame>();
s.template registerType<SetSelection>();

View File

@ -1672,6 +1672,12 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
break;
}
case 17: case 18: case 19: case 20: //dwellings
{
nobj = new CGDwelling();
nobj->setOwner(bufor[i++]);
i+=3;
break;
}
case 42: //lighthouse
case 87: //shipyard
case 220://mine (?)
@ -1759,7 +1765,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
}
case 217:
{
nobj = new CGObjectInstance();
nobj = new CGDwelling();
CCreGenObjInfo * spec = new CCreGenObjInfo;
spec->player = readNormalNr(bufor,i); i+=4;
spec->identifier = readNormalNr(bufor,i); i+=4;
@ -1779,7 +1785,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
}
case 216:
{
nobj = new CGObjectInstance();
nobj = new CGDwelling();
CCreGen2ObjInfo * spec = new CCreGen2ObjInfo;
spec->player = readNormalNr(bufor,i); i+=4;
spec->identifier = readNormalNr(bufor,i); i+=4;
@ -1801,7 +1807,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
}
case 218:
{
nobj = new CGObjectInstance();
nobj = new CGDwelling();
CCreGen3ObjInfo * spec = new CCreGen3ObjInfo;
spec->player = bufor[i]; ++i;
i+=3;

View File

@ -773,17 +773,21 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, std::vector< st
SDL_Rect pp = objects[h].second;
pp.h = sr.h;
pp.w = sr.w;
const CGHeroInstance * themp = (dynamic_cast<const CGHeroInstance*>(objects[h].first));
if(themp && themp->moveDir && !themp->isStanding && themp->ID!=62) //last condition - this is not prison
const CGHeroInstance * themp = (objects[h].first->ID != HEROI_TYPE
? NULL
: static_cast<const CGHeroInstance*>(objects[h].first));
if(themp && themp->moveDir) //it's hero
{
int imgVal = 8;
SDL_Surface * tb;
if(themp->type==NULL)
continue;
std::vector<Cimage> & iv = graphics->heroAnims[themp->type->heroType]->ourImages;
if(!themp->isStanding) //hero is moving
{
size_t gg;
for(gg=0; gg<iv.size(); ++gg)
{
@ -798,15 +802,8 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, std::vector< st
sr.y-=16;
SDL_BlitSurface(graphics->flags4[themp->getOwner()]->ourImages[gg+heroAnim%imgVal+35].bitmap, &pp, extSurf, &sr);
}
else if(themp && themp->moveDir && themp->isStanding && themp->ID!=62) //last condition - this is not prison)
else //hero stands still
{
int imgVal = 8;
SDL_Surface * tb;
if(themp->type==NULL)
continue;
std::vector<Cimage> & iv = graphics->heroAnims[themp->type->heroType]->ourImages;
size_t gg;
for(gg=0; gg < iv.size(); ++gg)
{
@ -829,7 +826,8 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, std::vector< st
SDL_BlitSurface(graphics->flags4[themp->getOwner()]->ourImages[ getHeroFrameNum(themp->moveDir, !themp->isStanding) *8+(heroAnim/4)%imgVal].bitmap, NULL, extSurf, &bufr);
}
}
else
}
else //blit object
{
const CGObjectInstance *obj = objects[h].first;
const std::vector<Cimage> &ourImages = obj->defInfo->handler->ourImages;

View File

@ -709,14 +709,14 @@ void CGameHandler::newTurn()
{
SetAvailableCreatures sac;
sac.tid = (**j).id;
sac.creatures = (**j).strInfo.creatures;
sac.creatures = (**j).creatures;
for(int k=0;k<CREATURES_PER_TOWN;k++) //creature growths
{
if((**j).creatureDwelling(k))//there is dwelling (k-level)
{
sac.creatures[k] += (**j).creatureGrowth(k);
sac.creatures[k].first += (**j).creatureGrowth(k);
if(!gs->getDate(0)) //first day of game: use only basic growths
amin(sac.creatures[k], VLC->creh->creatures[(*j)->town->basicCreatures[k]].growth);
amin(sac.creatures[k].first, VLC->creh->creatures[(*j)->town->basicCreatures[k]].growth);
}
}
n.cres.push_back(sac);
@ -1203,7 +1203,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
{
if (obj->blockVisit)
{
obj->onHeroVisit(h);
objectVisited(obj, h);
}
}
tlog5 << "Blocking visit at " << hmpos << std::endl;
@ -1224,7 +1224,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
//call objects if they are visited
BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects)
{
obj->onHeroVisit(h);
objectVisited(obj, h);
}
}
tlog5 << "Movement end!\n";
@ -1449,10 +1449,10 @@ void CGameHandler::heroExchange(si32 hero1, si32 hero2)
if(player1 == player2)
{
HeroExchange hex;
hex.hero1 = hero1;
hex.hero2 = hero2;
hex.player = player1;
OpenWindow hex;
hex.window = OpenWindow::EXCHANGE_WINDOW;
hex.id1 = hero1;
hex.id2 = hero2;
sendAndApply(&hex);
}
}
@ -1679,8 +1679,8 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid )
{
SetAvailableCreatures ssi;
ssi.tid = tid;
ssi.creatures = t->strInfo.creatures;
ssi.creatures[bid-30] = VLC->creh->creatures[t->town->basicCreatures[bid-30]].growth;
ssi.creatures = t->creatures;
ssi.creatures[bid-30].first = VLC->creh->creatures[t->town->basicCreatures[bid-30]].growth;
sendAndApply(&ssi);
}
@ -1715,26 +1715,41 @@ void CGameHandler::sendMessageToAll( const std::string &message )
bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
{
si32 ser = -1;
CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[objid]);
const CGDwelling *dw = static_cast<CGDwelling*>(gs->map->objects[objid]);
const CArmedInstance *dst = NULL;
if(dw->ID == TOWNI_TYPE)
dst = dw;
else if(dw->ID == 17 || dw->ID == 20) //advmap dwelling
dst = getHero(gs->getPlayer(dw->tempOwner)->currentSelection); //TODO: check if current hero is really visiting dwelling
assert(dw && dst);
//verify
bool found = false;
int level = -1;
typedef std::pair<const int,int> Parka;
for(std::map<si32,ui32>::iterator av = t->strInfo.creatures.begin(); av!=t->strInfo.creatures.end(); av++)
for(level = 0; level < dw->creatures.size(); level++) //iterate through all levels
{
if( ( found = (crid == t->town->basicCreatures[av->first]) ) //creature is available among basic cretures
|| (found = (crid == t->town->upgradedCreatures[av->first])) )//creature is available among upgraded cretures
const std::pair<ui32, std::vector<ui32> > &cur = dw->creatures[level]; //current level info <amount, list of cr. ids>
int i = 0;
for(; i < cur.second.size(); i++) //look for crid among available creatures list on current level
if(cur.second[i] == crid)
break;
if(i < cur.second.size())
{
cram = std::min(cram,av->second); //reduce recruited amount up to available amount
ser = av->first;
found = true;
cram = std::min(cram, cur.first); //reduce recruited amount up to available amount
break;
}
}
int slot = t->army.getSlotFor(crid);
int slot = dst->army.getSlotFor(crid);
if(!found && complain("Cannot recruit: no such creatures!")
|| cram > VLC->creh->creatures[crid].maxAmount(gs->getPlayer(t->tempOwner)->resources) && complain("Cannot recruit: lack of resources!")
|| cram > VLC->creh->creatures[crid].maxAmount(gs->getPlayer(dst->tempOwner)->resources) && complain("Cannot recruit: lack of resources!")
|| cram<=0 && complain("Cannot recruit: cram <= 0!")
|| slot<0 && complain("Cannot recruit: no available slot!"))
{
@ -1743,24 +1758,24 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
//recruit
SetResources sr;
sr.player = t->tempOwner;
sr.player = dst->tempOwner;
for(int i=0;i<RESOURCE_QUANTITY;i++)
sr.res[i] = gs->getPlayer(t->tempOwner)->resources[i] - (VLC->creh->creatures[crid].cost[i] * cram);
sr.res[i] = gs->getPlayer(dst->tempOwner)->resources[i] - (VLC->creh->creatures[crid].cost[i] * cram);
SetAvailableCreatures sac;
sac.tid = objid;
sac.creatures = t->strInfo.creatures;
sac.creatures[ser] -= cram;
sac.creatures = dw->creatures;
sac.creatures[level].first -= cram;
SetGarrisons sg;
sg.garrs[objid] = t->army;
if(sg.garrs[objid].slots.find(slot) == sg.garrs[objid].slots.end()) //take a free slot
sg.garrs[dst->id] = dst->army;
if(sg.garrs[dst->id].slots.find(slot) == sg.garrs[dst->id].slots.end()) //take a free slot
{
sg.garrs[objid].slots[slot] = std::make_pair(crid,cram);
sg.garrs[dst->id].slots[slot] = std::make_pair(crid,cram);
}
else //add creatures to a already existing stack
{
sg.garrs[objid].slots[slot].second += cram;
sg.garrs[dst->id].slots[slot].second += cram;
}
sendAndApply(&sr);
sendAndApply(&sac);
@ -2667,3 +2682,8 @@ bool CGameHandler::isAllowedExchange( int id1, int id2 )
return false;
}
void CGameHandler::objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h )
{
obj->onHeroVisit(h);
}

View File

@ -156,6 +156,7 @@ public:
void close();
void handleTimeEvents();
bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true
void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h );
template <typename Handler> void serialize(Handler &h, const int version)
{