1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

- Implemented Portal of Summoning (Dungeon)

This commit is contained in:
Ivan Savenko 2010-07-10 16:50:23 +00:00
parent b1a916fb15
commit bb7615309f
11 changed files with 148 additions and 77 deletions

View File

@ -64,12 +64,12 @@ void CCallback::selectionMade(int selection, int asker)
QueryReply pack(asker,selection);
*cl->serv << &pack;
}
void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)
void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level/*=-1*/)
{
if(player!=obj->tempOwner && obj->ID != 106)
return;
RecruitCreatures pack(obj->id,ID,amount);
RecruitCreatures pack(obj->id,ID,amount,level);
sendRequest(&pack);
}

View File

@ -80,7 +80,7 @@ public:
//town
virtual void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero)=0;
virtual bool buildBuilding(const CGTownInstance *town, si32 buildingID)=0;
virtual void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)=0;
virtual void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level=-1)=0;
virtual bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1)=0; //if newID==-1 then best possible upgrade will be made
virtual void swapGarrisonHero(const CGTownInstance *town)=0;
@ -221,7 +221,7 @@ public:
bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2);
bool assembleArtifacts(const CGHeroInstance * hero, ui16 artifactSlot, bool assemble, ui32 assembleTo);
bool buildBuilding(const CGTownInstance *town, si32 buildingID);
void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount);
void recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level=-1);
bool dismissCreature(const CArmedInstance *obj, int stackPos);
bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1);
void endTurn();

View File

@ -754,7 +754,15 @@ void CCastleInterface::buildingClicked(int building)
break;
/*Dungeon*/ case 5: //Portal of Summoning
tlog4<<"Portal of Summoning not handled\n";
if (town->creatures[CREATURES_PER_TOWN].second.empty())
{//extra dwelling has no creatures in it. no external dwellinngs
LOCPLINT->showInfoDialog(CGI->generaltexth->tcommands[30], std::vector<SComponent*>(), soundBase::sound_todo);
}
else
{
GH.pushInt(new CRecruitmentWindow(town, CREATURES_PER_TOWN, town,
boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2,CREATURES_PER_TOWN), -87));
}
break;
/*Stronghold*/ case 6: //Ballista Yard
enterBlacksmith(4);
@ -1147,22 +1155,24 @@ void CCastleInterface::recreateIcons()
crid = town->town->basicCreatures[i];
}
if (crid>=0)
creainfo.push_back(new CCreaInfo(crid,bid));
creainfo.push_back(new CCreaInfo(crid,(bid-30)%CREATURES_PER_TOWN));
}
if(town->subID == 5 && vstd::contains(town->builtBuildings, 22) && //we have Portal of Summoning
!town->creatures[CREATURES_PER_TOWN].second.empty()) // with some creatures in it
creainfo.push_back(new CCreaInfo(town->creatures[CREATURES_PER_TOWN].second[0], CREATURES_PER_TOWN));
}
CCastleInterface::CCreaInfo::~CCreaInfo()
{
}
CCastleInterface::CCreaInfo::CCreaInfo(int CRID, int BID)
CCastleInterface::CCreaInfo::CCreaInfo(int CRID, int LVL)
{
used = LCLICK | RCLICK | HOVER;
CCastleInterface * ci=LOCPLINT->castleInt;
bid = BID;
level = LVL;
crid = CRID;
int i = (bid-30)%CREATURES_PER_TOWN;
pos.x = ci->pos.x+14+(55*(i%4));
pos.y = (i>3)?(507+ci->pos.y):(459+ci->pos.y);
pos.x = ci->pos.x+14+(55*(level%4));
pos.y = (level>3)?(507+ci->pos.y):(459+ci->pos.y);
pos.w = 48;
pos.h = 48;
}
@ -1178,13 +1188,14 @@ void CCastleInterface::CCreaInfo::hover(bool on)
else
GH.statusbar->clear();
}
void CCastleInterface::CCreaInfo::clickLeft(tribool down, bool previousState)
{
if(previousState && (!down))
{
LOCPLINT->castleInt->showRecruitmentWindow(bid);
LOCPLINT->castleInt->showRecruitmentWindow(level+37);
}
};
}
int CCastleInterface::CCreaInfo::AddToString(std::string from, std::string & to, int numb)
{
@ -1193,7 +1204,7 @@ int CCastleInterface::CCreaInfo::AddToString(std::string from, std::string & to,
boost::algorithm::replace_first(from,"%+d", "+"+boost::lexical_cast<std::string>(numb));
to+="\n"+from;
return numb;
};
}
void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
{
@ -1202,7 +1213,6 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
CCastleInterface * ci=LOCPLINT->castleInt;
std::set<si32> bld =ci->town->builtBuildings;
int summ=0, cnt=0;
int level=(bid-30)%CREATURES_PER_TOWN;
std::string descr=CGI->generaltexth->allTexts[589];//Growth of creature is number
boost::algorithm::replace_first(descr,"%s",CGI->creh->creatures[crid]->nameSing);
boost::algorithm::replace_first(descr,"%d", boost::lexical_cast<std::string>(
@ -1212,47 +1222,50 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
summ = CGI->creh->creatures[crid]->growth;
boost::algorithm::replace_first(descr,"%d", boost::lexical_cast<std::string>(summ));
if ( bld.find(9)!=bld.end())//castle +100% to basic
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][9]->Name()+" %+d",descr,summ);
else if ( bld.find(8)!=bld.end())//else if citadel+50% to basic
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][8]->Name()+" %+d",descr,summ/2);
if(ci->town->town->hordeLvl[0]==level)//horde, x to summ
if((bld.find(18)!=bld.end()) || (bld.find(19)!=bld.end()))
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][18]->Name()+" %+d",descr,
CGI->creh->creatures[crid]->hordeGrowth);
if(ci->town->town->hordeLvl[1]==level)//horde, x to summ
if((bld.find(24)!=bld.end()) || (bld.find(25)!=bld.end()))
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][24]->Name()+" %+d",descr,
CGI->creh->creatures[crid]->hordeGrowth);
cnt = 0;
for (std::vector<CGDwelling*>::const_iterator it = CGI->state->players[ci->town->tempOwner].dwellings.begin();
it !=CGI->state->players[ci->town->tempOwner].dwellings.end(); ++it)
if (CGI->creh->creatures[ci->town->town->basicCreatures[level]]->idNumber == (*it)->creatures[0].second[0])
cnt++;//external dwellings count to summ
summ+=AddToString(CGI->generaltexth->allTexts[591],descr,cnt);
const CGHeroInstance * ch = ci->town->garrisonHero;
for (cnt = 0; cnt<2; cnt++) // "loop" to avoid copy-pasting code
if ( level>=0 && level<CREATURES_PER_TOWN)
{
if(ch)
if ( bld.find(9)!=bld.end())//castle +100% to basic
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][9]->Name()+" %+d",descr,summ);
else if ( bld.find(8)!=bld.end())//else if citadel+50% to basic
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][8]->Name()+" %+d",descr,summ/2);
if(ci->town->town->hordeLvl[0]==level)//horde, x to summ
if((bld.find(18)!=bld.end()) || (bld.find(19)!=bld.end()))
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][18]->Name()+" %+d",descr,
CGI->creh->creatures[crid]->hordeGrowth);
if(ci->town->town->hordeLvl[1]==level)//horde, x to summ
if((bld.find(24)!=bld.end()) || (bld.find(25)!=bld.end()))
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][24]->Name()+" %+d",descr,
CGI->creh->creatures[crid]->hordeGrowth);
cnt = 0;
for (std::vector<CGDwelling*>::const_iterator it = CGI->state->players[ci->town->tempOwner].dwellings.begin();
it !=CGI->state->players[ci->town->tempOwner].dwellings.end(); ++it)
if (CGI->creh->creatures[ci->town->town->basicCreatures[level]]->idNumber == (*it)->creatures[0].second[0])
cnt++;//external dwellings count to summ
summ+=AddToString(CGI->generaltexth->allTexts[591],descr,cnt);
const CGHeroInstance * ch = ci->town->garrisonHero;
for (cnt = 0; cnt<2; cnt++) // "loop" to avoid copy-pasting code
{
for(std::list<Bonus>::const_iterator i=ch->bonuses.begin(); i != ch->bonuses.end(); i++)
if(i->type == Bonus::CREATURE_GROWTH && i->subtype == level)
if (i->source == Bonus::ARTIFACT)
summ+=AddToString(CGI->arth->artifacts[i->id]->Name()+" %+d",descr,i->val);
if(ch)
{
for(std::list<Bonus>::const_iterator i=ch->bonuses.begin(); i != ch->bonuses.end(); i++)
if(i->type == Bonus::CREATURE_GROWTH && i->subtype == level)
if (i->source == Bonus::ARTIFACT)
summ+=AddToString(CGI->arth->artifacts[i->id]->Name()+" %+d",descr,i->val);
};
ch = ci->town->visitingHero;
};
ch = ci->town->visitingHero;
};
//TODO player bonuses
//TODO player bonuses
if(bld.find(26)!=bld.end()) //grail - +50% to ALL growth
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][26]->Name()+" %+d",descr,summ/2);
if(bld.find(26)!=bld.end()) //grail - +50% to ALL growth
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][26]->Name()+" %+d",descr,summ/2);
}
CInfoPopup *mess = new CInfoPopup();//creating popup
mess->free = true;
@ -1268,7 +1281,7 @@ void CCastleInterface::CCreaInfo::show(SDL_Surface * to)
{
blitAt(graphics->smallImgs[crid],pos.x+8,pos.y,to);
std::ostringstream oss;
oss << '+' << LOCPLINT->castleInt->town->creatureGrowth((bid-30)%CREATURES_PER_TOWN);
oss << '+' << LOCPLINT->castleInt->town->creatureGrowth(level);
CSDL_Ext::printAtMiddle(oss.str(),pos.x+24,pos.y+40,FONT_SMALL,zwykly,to);
}
@ -1366,7 +1379,7 @@ CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building )
building-=7;
int level = building-30;
assert(level >= 0 && level <= 6);
assert(level >= 0 && level < town->creatures.size());
//std::vector<std::pair<int,int > > crs;
//int amount = town->creatures[level].first;
@ -1377,7 +1390,7 @@ CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building )
// crs.push_back(std::make_pair((int)cres[i],amount));
//CRecruitmentWindow *rw = new CRecruitmentWindow(crs,boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2));
CRecruitmentWindow *rw = new CRecruitmentWindow(town, level, town, boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2), -87);
CRecruitmentWindow *rw = new CRecruitmentWindow(town, level, town, boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2,level), -87);
GH.pushInt(rw);
return rw;
}

View File

@ -77,8 +77,8 @@ class CCastleInterface : public CWindowWithGarrison
class CCreaInfo : public CIntObject
{
public:
int crid,bid;
CCreaInfo(int CRID, int BID); //c-tor
int crid,level;
CCreaInfo(int CRID, int LVL); //c-tor
~CCreaInfo();//d-tor
int AddToString(std::string from, std::string & to, int numb);
void hover(bool on);

View File

@ -1085,7 +1085,7 @@ void CKingdomInterface::CTownItem::CCreaPlace::clickLeft(tribool down, bool prev
if (!down && previousState && town)
{
GH.pushInt (new CRecruitmentWindow(town, type, town, boost::bind
(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2)));
(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2, type)));
}
}

View File

@ -1197,7 +1197,7 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const C
{
waitWhileDialog();
boost::unique_lock<boost::recursive_mutex> un(*pim);
CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2));
CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2, -1));
GH.pushInt(cr);
}

View File

@ -1758,6 +1758,9 @@ int CGTownInstance::getHordeLevel(const int & HID) const//HID - 0 or 1; returns
}
int CGTownInstance::creatureGrowth(const int & level) const
{
if (level<0 || level >=CREATURES_PER_TOWN)
return 0;
int ret = VLC->creh->creatures[town->basicCreatures[level]]->growth;
switch(fortLevel())
{
@ -1922,7 +1925,10 @@ void CGTownInstance::initObj()
blockVisit = true;
hoverName = name + ", " + town->Name();
creatures.resize(CREATURES_PER_TOWN);
if (subID == 5)
creatures.resize(CREATURES_PER_TOWN+1);//extra dwelling for Dungeon
else
creatures.resize(CREATURES_PER_TOWN);
for (int i = 0; i < CREATURES_PER_TOWN; i++)
{
if(creatureDwelling(i,false))
@ -1930,15 +1936,16 @@ void CGTownInstance::initObj()
if(creatureDwelling(i,true))
creatures[i].second.push_back(town->upgradedCreatures[i]);
}
switch (subID)
{ //add new visitable objects
case 0:
bonusingBuildings.push_back (new COPWBonus(21, this)); //Stables
break;
case 2: case 3: case 5: case 6:
case 5:
bonusingBuildings.push_back (new COPWBonus(21, this)); //Vortex
case 2: case 3: case 6:
bonusingBuildings.push_back (new CTownBonus(23, this));
if (subID == 5)
bonusingBuildings.push_back (new COPWBonus(21, this)); //Vortex
break;
case 7:
bonusingBuildings.push_back (new CTownBonus(17, this));

View File

@ -1316,14 +1316,14 @@ struct RazeStructure : public BuildStructure
struct RecruitCreatures : public CPackForServer
{
RecruitCreatures(){};
RecruitCreatures(si32 TID, si32 CRID, si32 Amount):tid(TID),crid(CRID),amount(Amount){};
RecruitCreatures(si32 TID, si32 CRID, si32 Amount, si32 Level):tid(TID),crid(CRID),amount(Amount),level(Level){};
si32 tid; //town id
ui32 crid, amount;//creature ID and amount
si32 level;//dwelling level to buy from, -1 if any
bool applyGh(CGameHandler *gh);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & tid & crid & amount;
h & tid & crid & amount & level;
}
};

View File

@ -928,6 +928,33 @@ static bool evntCmp(const CMapEvent *a, const CMapEvent *b)
return *a < *b;
}
void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=false)
{// bool forced = true - if creature should be replaced, if false - only if no creature was set
if (forced || town->creatures[CREATURES_PER_TOWN].second.empty())//we need to change creature
{
SetAvailableCreatures ssi;
ssi.tid = town->id;
ssi.creatures = town->creatures;
ssi.creatures[CREATURES_PER_TOWN].second.clear();//remove old one
std::vector<CGDwelling *> dwellings = gs->getPlayer(town->tempOwner)->dwellings;
if (dwellings.empty())//no dwellings - just remove
{
sendAndApply(&ssi);
return;
}
ui32 dwellpos = rand()%dwellings.size();//take random dwelling
ui32 creapos = rand()%dwellings[dwellpos]->creatures.size();//for multi-creature dwellings like Golem Factory
ui32 creature = dwellings[dwellpos]->creatures[creapos].second[0];
ssi.creatures[CREATURES_PER_TOWN].first = VLC->creh->creatures[creature]->growth;
ssi.creatures[CREATURES_PER_TOWN].second.push_back(creature);
sendAndApply(&ssi);
}
}
void CGameHandler::newTurn()
{
tlog5 << "Turn " << gs->day+1 << std::endl;
@ -1023,6 +1050,9 @@ void CGameHandler::newTurn()
ui8 player = (*j)->tempOwner;
if(gs->getDate(1)==7) //first day of week
{
if ((*j)->subID == 5 && vstd::contains((*j)->builtBuildings, 22))
setPortalDwelling(*j, true);//set creatures for Portal of Summoning
if ((**j).subID == 1 && gs->getDate(0) && player < PLAYER_LIMIT && vstd::contains((**j).builtBuildings, 22))//dwarven treasury
n.res[player][6] += hadGold[player]/10; //give 10% of starting gold
@ -1856,10 +1886,11 @@ bool CGameHandler::teleportHero(si32 hid, si32 dstid, ui8 source, ui8 asker/* =
&& complain("Cannot teleport hero to town without Castle gate in it"))
return false;
int3 pos = t->visitablePos();
pos.x++;//FIXME: get correct visitable position
pos.x++;//FIXME: get visitable position in more correct way (if any)
stopHeroVisitCastle(from->id, hid);
moveHero(hid,pos,1);
heroVisitCastle(dstid, hid);
return true;
}
void CGameHandler::setOwner(int objid, ui8 owner)
@ -1869,14 +1900,28 @@ void CGameHandler::setOwner(int objid, ui8 owner)
sendAndApply(&sop);
winLoseHandle(1<<owner | 1<<oldOwner);
if(owner < PLAYER_LIMIT && getTown(objid) && !gs->getPlayer(owner)->towns.size()) //player lost last town
if(owner < PLAYER_LIMIT && getTown(objid)) //town captured
{
InfoWindow iw;
iw.player = oldOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated.
sendAndApply(&iw);
const CGTownInstance * town = getTown(objid);
if (town->subID == 5 && vstd::contains(town->builtBuildings, 22))
setPortalDwelling(town);
if (!gs->getPlayer(owner)->towns.size())//player lost last town
{
InfoWindow iw;
iw.player = oldOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 6); //%s, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated.
sendAndApply(&iw);
}
}
const CGObjectInstance * obj = getObj(objid);
if ((obj->id == 17 || obj->id == 20 ) && gs->getPlayer(owner)->dwellings.size()==1 )//first dwelling captured
BOOST_FOREACH(const CGTownInstance *t, gs->getPlayer(owner)->towns)
if (t->subID == 5 && vstd::contains(t->builtBuildings, 22))
setPortalDwelling(t);//set initial creatures for all portals of summoning
}
void CGameHandler::setHoverName(int objid, MetaString* name)
{
SetHoverName shn(objid, *name);
@ -2570,6 +2615,10 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid )
gb.bonus.id = 17;
sendAndApply(&gb);
}
else if ( t->subID == 5 && bid == 22 )
{
setPortalDwelling(t);
}
ns.bid.insert(bid);
ns.builded = t->builded + 1;
@ -2634,7 +2683,7 @@ void CGameHandler::sendMessageToAll( const std::string &message )
sendToAllClients(&sm);
}
bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 fromLvl )
{
const CGDwelling *dw = static_cast<CGDwelling*>(gs->map->objects[objid]);
const CArmedInstance *dst = NULL;
@ -2654,12 +2703,13 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
//verify
bool found = false;
int level = -1;
int level = 0;
typedef std::pair<const int,int> Parka;
for(level = 0; level < dw->creatures.size(); level++) //iterate through all levels
for(; level < dw->creatures.size(); level++) //iterate through all levels
{
if ( (fromLvl != -1) && ( level !=fromLvl ) )
continue;
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

View File

@ -155,6 +155,7 @@ public:
void changeObjPos(int objid, int3 newPos, ui8 flags);
void useScholarSkill(si32 hero1, si32 hero2);
void heroExchange(si32 hero1, si32 hero2);
void setPortalDwelling(const CGTownInstance * town, bool forced);
//////////////////////////////////////////////////////////////////////////
void init(StartInfo *si, int Seed);
@ -179,7 +180,7 @@ public:
bool swapArtifacts(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, ui16 destSlot);
bool garrisonSwap(si32 tid);
bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
bool recruitCreatures(si32 objid, ui32 crid, ui32 cram);
bool recruitCreatures(si32 objid, ui32 crid, ui32 cram, si32 level);
bool buildStructure(si32 tid, si32 bid);
bool razeStructure(si32 tid, si32 bid);
bool disbandCreature( si32 id, ui8 pos );

View File

@ -86,7 +86,7 @@ bool BuildStructure::applyGh( CGameHandler *gh )
bool RecruitCreatures::applyGh( CGameHandler *gh )
{
return gh->recruitCreatures(tid,crid,amount);
return gh->recruitCreatures(tid,crid,amount,level);
}
bool UpgradeCreature::applyGh( CGameHandler *gh )