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

1.Support for Keymaster Tent & Borderguard, Eye & Hut of The Magi, Stables.

2.Partially done support for creature banks. ToDo: load config file, start battle with surrounding enemies
3.Attempt to increase hero exp capacity. You may ignore it at the moment.
4.Fixed negative countdown in timeHandler.
This commit is contained in:
DjWarmonger 2009-08-11 07:50:29 +00:00
parent 575840f641
commit 4653396d76
19 changed files with 647 additions and 29 deletions

View File

@ -76,7 +76,7 @@ public:
virtual void heroCreated(const CGHeroInstance*){}; virtual void heroCreated(const CGHeroInstance*){};
virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
virtual void heroInGarrisonChange(const CGTownInstance *town){}; virtual void heroInGarrisonChange(const CGTownInstance *town){};
//virtual void heroKilled(const CGHeroInstance*){}; virtual void heroKilled(const CGHeroInstance*){};
virtual void heroMoved(const TryMoveHero & details){}; virtual void heroMoved(const TryMoveHero & details){};
virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val){}; 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 heroManaPointsChanged(const CGHeroInstance * hero){} //not called at the beginning of turn and after spell casts
@ -93,6 +93,7 @@ public:
virtual void tileRevealed(const std::set<int3> &pos){}; virtual void tileRevealed(const std::set<int3> &pos){};
virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard
virtual void yourTurn(){}; virtual void yourTurn(){};
virtual void centerView (int3 pos){};
virtual void availableCreaturesChanged(const CGDwelling *town){}; virtual void availableCreaturesChanged(const CGDwelling *town){};
virtual void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain){};//if gain hero received bonus, else he lost it virtual void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
virtual void requestRealized(PackageApplied *pa){}; virtual void requestRealized(PackageApplied *pa){};

View File

@ -1545,6 +1545,11 @@ void CPlayerInterface::newObject( const CGObjectInstance * obj )
} }
} }
void CPlayerInterface::centerView (int3 pos)
{
LOCPLINT->adventureInt->centerOn (pos);
}
void CPlayerInterface::objectRemoved( const CGObjectInstance *obj ) void CPlayerInterface::objectRemoved( const CGObjectInstance *obj )
{ {
if(obj->ID == HEROI_TYPE && obj->tempOwner == playerID) if(obj->ID == HEROI_TYPE && obj->tempOwner == playerID)

View File

@ -157,6 +157,7 @@ public:
void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain);//if gain hero received bonus, else he lost it void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain);//if gain hero received bonus, else he lost it
void requestRealized(PackageApplied *pa); void requestRealized(PackageApplied *pa);
void heroExchangeStarted(si32 hero1, si32 hero2); void heroExchangeStarted(si32 hero1, si32 hero2);
void centerView (int3 pos);
void objectPropertyChanged(const SetObjectProperty * sop); void objectPropertyChanged(const SetObjectProperty * sop);
void objectRemoved(const CGObjectInstance *obj); void objectRemoved(const CGObjectInstance *obj);
void serialize(COSer<CSaveFile> &h, const int version); //saving void serialize(COSer<CSaveFile> &h, const int version); //saving
@ -179,7 +180,6 @@ public:
void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks); //called when stacks are healed / resurrected void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks); //called when stacks are healed / resurrected
void battleNewStackAppeared(int stackID); //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned void battleNewStackAppeared(int stackID); //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
//-------------// //-------------//
void heroKilled(const CGHeroInstance* hero); void heroKilled(const CGHeroInstance* hero);
void waitWhileDialog(); void waitWhileDialog();

View File

@ -96,6 +96,7 @@ public:
ui32 showBlockingDialog(BlockingDialog *iw){return 0;}; //synchronous version of above ui32 showBlockingDialog(BlockingDialog *iw){return 0;}; //synchronous version of above
void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb){}; void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb){};
void giveResource(int player, int which, int val){}; void giveResource(int player, int which, int val){};
void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet *creatures){};
void showCompInfo(ShowInInfobox * comp){}; void showCompInfo(ShowInInfobox * comp){};
void heroVisitCastle(int obj, int heroID){}; void heroVisitCastle(int obj, int heroID){};
void stopHeroVisitCastle(int obj, int heroID){}; void stopHeroVisitCastle(int obj, int heroID){};

View File

@ -550,6 +550,17 @@ void OpenWindow::applyCl(CClient *cl)
} }
void CenterView::applyCl(CClient *cl)
{
int3 pos = (cl->getObj(id))->pos;
INTERFACE_CALL_IF_PRESENT (player, centerView, pos);
}
void TakeYourTime::applyCl(CClient *cl)
{
SDL_Delay(time);
}
void NewObject::applyCl(CClient *cl) void NewObject::applyCl(CClient *cl)
{ {
const CGObjectInstance *obj = cl->getObj(id); const CGObjectInstance *obj = cl->getObj(id);

View File

@ -378,7 +378,7 @@ void CHeroHandler::initHeroClasses()
loadNativeTerrains(); loadNativeTerrains();
} }
unsigned int CHeroHandler::level(unsigned int experience) unsigned int CHeroHandler::level(ui64 experience)
{ {
int i; int i;
if(experience <= expPerLevel.back()) if(experience <= expPerLevel.back())
@ -393,7 +393,7 @@ unsigned int CHeroHandler::level(unsigned int experience)
} }
} }
unsigned int CHeroHandler::reqExp(unsigned int level) ui64 CHeroHandler::reqExp(unsigned int level)
{ {
if(!level) if(!level)
return 0; return 0;
@ -404,6 +404,14 @@ unsigned int CHeroHandler::reqExp(unsigned int level)
} }
else else
{ {
ui64 exp = expPerLevel[expPerLevel.size()-1];
level-=(expPerLevel.size()-1);
while(level>0)
{
--level;
exp*=1.2;
}
return exp;
return reqExp(level - 1) + (reqExp(level - 1) - reqExp(level - 2)) * 1.2; //inefficient but follows exactly H3 values return reqExp(level - 1) + (reqExp(level - 1) - reqExp(level - 2)) * 1.2; //inefficient but follows exactly H3 values
} }
} }

View File

@ -113,8 +113,8 @@ public:
void loadObstacles(); //loads info about obstacles void loadObstacles(); //loads info about obstacles
unsigned int level(unsigned int experience); //calculates level corresponding to given experience amount unsigned int level(ui64 experience); //calculates level corresponding to given experience amount
unsigned int reqExp(unsigned int level); //calculates experience resuired for given level ui64 reqExp(unsigned int level); //calculates experience resuired for given level
void loadHeroes(); void loadHeroes();
void loadHeroClasses(); void loadHeroClasses();

View File

@ -38,7 +38,25 @@ IGameCallback * IObjectInterface::cb = NULL;
DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode); DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
extern CLodHandler * bitmaph; extern CLodHandler * bitmaph;
extern boost::rand48 ran; extern boost::rand48 ran;
std::map <ui8, std::set <ui8> > CGKeys::playerKeyMap;
std::map <si32, std::vector<CGMagi>> CGMagi::eyelist;
std::map <ui32, std::vector <BankConfig>> banksInfo; //[index][preset], TODO: load it
struct BankConfig
{
BankConfig() {chance = upgradeChance = combatValue = value = rewardDifficulty = easiest = 0; };
//std::string name;
ui8 chance;
ui8 upgradeChance;
std::vector< std::pair <ui16, ui32>> guards;
ui32 combatValue;
std::map<ui8, si32> resources;
std::vector< std::pair <ui16, ui32>> creatures;
std::map<ui8, ui16> artifacts;
ui32 value;
ui32 rewardDifficulty; //?
ui16 easiest; //?
};
void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
{}; {};
@ -1666,6 +1684,25 @@ int CArmedInstance::getArmyStrength() const
return ret; return ret;
} }
/*const std::string & CGCreature::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
hoverName += "\n Power rating: ";
float ratio = ((float)getArmyStrength() / cb->getSelectedHero(cb->getCurrentPlayer())->getTotalStrength());
if (ratio < 0.1) hoverName += "Effortless";
else if (ratio < 0.3) hoverName += "Very Weak";
else if (ratio < 0.6) hoverName += "Weak";
else if (ratio < 0.9) hoverName += "A bit weaker";
else if (ratio < 1.1) hoverName += "Equal";
else if (ratio < 1.3) hoverName += "A bit stronger";
else if (ratio < 1.8) hoverName += "Strong";
else if (ratio < 2.5) hoverName += "Very Strong";
else if (ratio < 4) hoverName += "Challenging";
else if (ratio < 8) hoverName += "Overpowering";
else if (ratio < 20) hoverName += "Deadly";
else hoverName += "Impossible";
return hoverName;
}*/
void CGCreature::onHeroVisit( const CGHeroInstance * h ) const void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
{ {
int action = takenAction(h); int action = takenAction(h);
@ -2634,10 +2671,17 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
gbonus.bdescr << std::pair<ui8,ui32>(6,103); gbonus.bdescr << std::pair<ui8,ui32>(6,103);
bonusMove = 400; bonusMove = 400;
break; break;
case 94: //Stables TODO: upgrade Cavaliers
sound = soundBase::horse20;
messageID = 137;
gbonus.bonus.type = HeroBonus::LAND_MOVEMENT;
gbonus.bonus.val = 600;
gbonus.bdescr << std::pair<ui8,ui32>(6, 100);
break;
} }
if(visited) if(visited)
{ {
if(ID==64 || ID==96 || ID==56 || ID == 52) if(ID==64 || ID==96 || ID==56 || ID==52 || ID==94)
messageID--; messageID--;
else else
messageID++; messageID++;
@ -3386,24 +3430,369 @@ void CGOnceVisitable::searchTomb(const CGHeroInstance *h, ui32 accept) const
cb->giveHeroArtifact(bonusType,h->id,-2); cb->giveHeroArtifact(bonusType,h->id,-2);
} }
if(!h->getBonus(HeroBonus::OBJECT,ID)) //we don't have modifier from this object yet
{
//ruin morale
GiveBonus gb;
gb.hid = h->id;
gb.bonus = HeroBonus(HeroBonus::ONE_BATTLE,HeroBonus::MORALE,HeroBonus::OBJECT,-3,id,"");
gb.bdescr.addTxt(MetaString::ARRAY_TXT,104); //Warrior Tomb Visited -3
cb->giveHeroBonus(&gb);
}
cb->showInfoDialog(&iw);
//add player to the visitors (for visited tooltop)
cb->setObjProperty(id,10,h->getOwner());
} }
} }
void CBank::initObj()
{
index = 0;
switch (ID) //find apriopriate key
{
case 16: //bank
index = subID; break;
case 24: //derelict ship
index = 8;
case 25: //utopia
index = 10; break;
case 84: //crypt
index = 9; break;
case 85: //shipwreck
index = 7; break;
}
bc = NULL;
daycounter = 0;
multiplier = 1;
}
void CBank::reset()
{
int val1 = ran()%100;
int chance = 0;
for (ui8 i = 1; i <= banksInfo[index].size(); i++)
{
if (val1 < (chance += banksInfo[index][i].chance))
cb->setObjProperty (id, 13, i);
}
artifacts.clear();
for (ui8 i = 1; i <= 4; i++)
{
for (ui8 j = 1; j <= bc->artifacts[i]; j++)
cb->setObjProperty (id, 18, i);
}
}
void CBank::setPropertyDer (ui8 what, ui32 val)
{
switch (what)
{
case 11: //daycounter
daycounter++;
break;
case 12: //multiplier
multiplier *= ((float)val)/100;
break;
case 13: //bank preset
bc = &banksInfo[index][val];
break;
case 18: //Artifacts
{
std::vector<CArtifact*> arts;
switch (val)
{
case 1:
cb->getAllowed (arts, CArtifact::ART_TREASURE);
break;
case 2:
cb->getAllowed (arts, CArtifact::ART_MINOR);
break;
case 3:
cb->getAllowed (arts, CArtifact::ART_MAJOR);
break;
case 4:
cb->getAllowed (arts, CArtifact::ART_RELIC);
break;
}
artifacts.push_back (arts[ran() % arts.size()]->id);
}
break;
}
}
void CBank::newTurn()
{
if (bc == NULL)
{
if (daycounter >= 28 || cb->getDate(0) == 1)
{
reset();
daycounter = 0;
if (ID == 24 && cb->getDate(0) > 1)
{
artifacts.clear(); //derelict ships are usable only once
}
}
else
daycounter++;
}
}
void CBank::onHeroVisit (const CGHeroInstance * h) const
{
if (bc != NULL)
{
int banktext = 0;
switch (ID)
{
case 16: //generic bank
banktext = 32;
break;
case 24:
banktext = 41;
break;
case 25: //utopia
banktext = 47;
break;
case 84: //crypt
banktext = 119;
break;
case 85: //shipwreck
banktext = 122;
break;
}
BlockingDialog bd (true, false);
bd.player = h->getOwner();
bd.soundID = soundBase::DANGER;
std::string desc = VLC->generaltexth->allTexts[banktext];
boost::algorithm::replace_first (desc, "%s", VLC->generaltexth->names[ID]);
bd.text << desc;
cb->showBlockingDialog (&bd, boost::bind (&CBank::fightGuards, this, h, _1));
}
else
{
InfoWindow iw;
if (ID == 85)
iw.components.push_back (Component (Component::MORALE, 0 , -2, 0));
iw.soundID = soundBase::GRAVEYARD;
iw.player = h->getOwner();
iw.text.addTxt (MetaString::ADVOB_TXT, 33);
cb->showInfoDialog(&iw);
}
}
void CBank::fightGuards (const CGHeroInstance * h, ui32 accept) const
{
if (accept)
{
int upgraded = 0;
if (ran()%100 < bc->upgradeChance) upgraded = 1;
CCreatureSet ourArmy;
switch (bc->guards.size())
{
case 1:
for (int i = 1; i <= 5; i++)
ourArmy.setCreature (i, bc->guards[1].first + upgraded, bc->guards[1].second / 5 );
break;
case 4:
{
std::vector< std::pair <ui16, ui32>>::const_iterator it;
for (it = bc->guards.begin(); it != bc->guards.end(); it++)
ourArmy.setCreature (ourArmy.slots.size() + 1, it->first, it->second );
}
break;
default:
tlog1 << "Error: Unexpected army data: " << bc->guards.size() <<" items found";
return;
}
//TODO: start combat
}
}
void CBank::endBattle (const BattleResult *result)
{
if (result->winner == 0)
{
int textID = -1;
InfoWindow iw;
switch (ID)
{
case 16: //generic bank
textID = 34;
break;
case 24: //derelict ship
if (bc->resources.size() != 0)
textID = 43;
else
{
textID = 42;
iw.components.push_back (Component (Component::MORALE, 0 , -2, 0));
}
break;
case 25: //utopia
textID = 47;
break;
case 84: //crypt
textID = 121;
break;
case 85: //shipwreck
if (bc->resources.size() != 0)
textID = 124;
else
{
textID = 123;
}
break;
}
iw.text.addTxt (MetaString::ADVOB_TXT, textID);
iw.player = cb->getCurrentPlayer();
for (std::map<ui8, si32>::iterator it = bc->resources.begin(); it != bc->resources.end(); it++)
{
iw.components.push_back (Component (Component::RESOURCE, it->first, it->second, 0));
cb->giveResource (cb->getCurrentPlayer(), it->first, it->second);
}
for (std::vector<si32>::iterator it = artifacts.begin(); it != artifacts.end(); it++)
{
iw.components.push_back (Component (Component::ARTIFACT, *it, 0, 0));
iw.text.addReplacement (MetaString::ART_NAMES, *it);
cb->giveHeroArtifact (*it, cb->getSelectedHero() ,-2);
}
CCreatureSet ourArmy;
for (std::vector< std::pair <ui16, ui32>>::iterator it = bc->creatures.begin(); it != bc->creatures.end(); it++)
{
int slot = ourArmy.getSlotFor (it->second);
ourArmy.slots[slot] = *it; //assuming we're not going to add multiple stacks of same creature
}
cb->giveCreatures (id, cb->getHero (cb->getSelectedHero()), &ourArmy);
bc = NULL;
}
else
reset();
}
void CGKeys::setPropertyDer (ui8 what, ui32 val) //101-108 - enable key for player 1-8
{
if (what >= 101 && what <= (100 + PLAYER_LIMIT))
playerKeyMap.find(what-101)->second.insert(val);
}
bool CGKeys::wasMyColorVisited (int player) const
{
if (vstd::contains(playerKeyMap[player], subID)) //creates set if it's not there
return true;
else
return false;
}
const std::string & CGKeymasterTent::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
if (wasMyColorVisited (cb->getCurrentPlayer()) )//TODO: use local player, not current
hoverName += "\n" + VLC->generaltexth->allTexts[352];
else
hoverName += "\n" + VLC->generaltexth->allTexts[353];
return hoverName;
}
void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
{
InfoWindow iw;
iw.soundID = soundBase::CAVEHEAD;
iw.player = h->getOwner();
if (!wasMyColorVisited (h->getOwner()) )
{
cb->setObjProperty(id, h->tempOwner+101, subID);
iw.text << std::pair<ui8,ui32>(11,19);
}
else
iw.text << std::pair<ui8,ui32>(11,20);
cb->showInfoDialog(&iw);
}
void CGBorderGuard::initObj()
{
blockVisit = true;
}
const std::string & CGBorderGuard::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
if (wasMyColorVisited (cb->getCurrentPlayer()) )//TODO: use local player, not current
hoverName += "\n" + VLC->generaltexth->allTexts[352];
else
hoverName += "\n" + VLC->generaltexth->allTexts[353];
return hoverName;
}
void CGBorderGuard::onHeroVisit( const CGHeroInstance * h ) const
{
if (wasMyColorVisited (h->getOwner()) )
{
BlockingDialog bd (true, false);
bd.player = h->getOwner();
bd.soundID = soundBase::QUEST;
bd.text.addTxt (MetaString::ADVOB_TXT, 17);
cb->showBlockingDialog (&bd, boost::bind (&CGBorderGuard::openGate, this, h, _1));
}
else
{
InfoWindow iw;
iw.player = h->getOwner();
iw.soundID = soundBase::CAVEHEAD;
iw.text << std::pair<ui8,ui32>(11,18);
cb->showInfoDialog (&iw);
}
}
void CGBorderGuard::openGate(const CGHeroInstance *h, ui32 accept) const
{
if (accept)
cb->removeObject(id);
}
void CGBorderGate::onHeroVisit( const CGHeroInstance * h ) const //TODO: passability
{
InfoWindow iw;
iw.player = h->getOwner();
if (!wasMyColorVisited (h->getOwner()) )
{
iw.text << std::pair<ui8,ui32>(11,18);
cb->showInfoDialog(&iw);
}
}
void CGMagi::initObj()
{
if (ID == 27)
{
blockVisit = true;
eyelist[subID].push_back (*this);
}
}
void CGMagi::onHeroVisit(const CGHeroInstance * h) const
{
if (ID == 37)
{
InfoWindow iw;
CenterView cv;
FoWChange fw;
cv.player = iw.player = fw.player = h->tempOwner;
iw.soundID = soundBase::LIGHTHOUSE;
iw.player = h->tempOwner;
iw.text.addTxt (MetaString::ADVOB_TXT, 61);
cb->showInfoDialog(&iw);
fw.mode = 1;
TakeYourTime tyt;
std::vector<CGMagi>::iterator it;
for (it = eyelist[subID].begin() ; it < eyelist[subID].end(); it++)
{
cb->getTilesInRange (fw.tiles, it->pos, 5, h->tempOwner, 1);
cb->sendAndApply(&fw);
cv.id = it->id;
cb->sendAndApply(&cv);
tyt.time = 2000;
cb->sendAndApply(&tyt);
}
cv.id = h->id;
cb->sendAndApply(&cv);
}
else if (ID == 27)
{
InfoWindow iw;
iw.player = h->tempOwner;
iw.text.addTxt (MetaString::ADVOB_TXT, 48);
cb->showInfoDialog(&iw);
}
}
void CGBoat::initObj() void CGBoat::initObj()
{ {
hero = NULL; hero = NULL;

View File

@ -42,6 +42,7 @@ class CGDefInfo;
class CSpecObjInfo; class CSpecObjInfo;
struct TerrainTile; struct TerrainTile;
struct InfoWindow; struct InfoWindow;
struct BankConfig;
class CGBoat; class CGBoat;
class DLL_EXPORT CCastleEvent class DLL_EXPORT CCastleEvent
@ -211,7 +212,7 @@ public:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
CHero * type; CHero * type;
ui32 exp; //experience point ui64 exp; //experience point
si32 level; //current level of hero si32 level; //current level of hero
std::string name; //may be custom std::string name; //may be custom
std::string biography; //if custom std::string biography; //if custom
@ -474,6 +475,7 @@ public:
void fight(const CGHeroInstance *h) const; void fight(const CGHeroInstance *h) const;
void onHeroVisit(const CGHeroInstance * h) const; void onHeroVisit(const CGHeroInstance * h) const;
//const std::string & getHoverText() const;
void flee( const CGHeroInstance * h ) const; void flee( const CGHeroInstance * h ) const;
void endBattle(BattleResult *result) const; void endBattle(BattleResult *result) const;
@ -759,6 +761,54 @@ public:
} }
}; };
class DLL_EXPORT CGKeys : public CGObjectInstance //Base class for Keymaster and guards, ToDo Border Gate
{
public:
static std::map <ui8, std::set <ui8> > playerKeyMap; //[players][keysowned]
//SubID 0 - lightblue, 1 - green, 2 - red, 3 - darkblue, 4 - brown, 5 - purple, 6 - white, 7 - black
void setPropertyDer (ui8 what, ui32 val);
bool wasMyColorVisited (int player) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);
}
};
class DLL_EXPORT CGKeymasterTent : public CGKeys
{
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 CGBorderGuard : public CGKeys
{
public:
void initObj();
const std::string & getHoverText() const;
void onHeroVisit(const CGHeroInstance * h) const;
void openGate(const CGHeroInstance *h, ui32 accept) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);
h & blockVisit;
}
};
class DLL_EXPORT CGBorderGate : public CGBorderGuard //not fully imlemented, waiting for garrison
{
public:
void onHeroVisit(const CGHeroInstance * h) const;
};
class DLL_EXPORT CGBoat : public CGObjectInstance class DLL_EXPORT CGBoat : public CGObjectInstance
{ {
public: public:
@ -778,7 +828,8 @@ public:
} }
}; };
class DLL_EXPORT CGOnceVisitable : public CPlayersVisited //wagon, corpse, lean to, warriors tomb class DLL_EXPORT CGOnceVisitable
: public CPlayersVisited //wagon, corpse, lean to, warriors tomb
{ {
public: public:
ui8 artOrRes; //0 - nothing; 1 - artifact; 2 - resource ui8 artOrRes; //0 - nothing; 1 - artifact; 2 - resource
@ -797,6 +848,30 @@ public:
} }
}; };
class DLL_EXPORT CBank : public CArmedInstance
{
public:
int index; //banks have unusal numbering - see ZCRBANK.txt and initObj()
BankConfig *bc;
ui8 multiplier; //for improved banks script, in percent
std::vector<si32> artifacts; //fixed and deterministic
mutable ui32 daycounter;
void initObj();
void setPropertyDer (ui8 what, ui32 val);
void reset();
void newTurn();
void onHeroVisit (const CGHeroInstance * h) const;
void fightGuards (const CGHeroInstance *h, ui32 accept) const;
void endBattle (const BattleResult *result);
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);
h & index & multiplier & artifacts & daycounter;
}
};
class CGShipyard : public CGObjectInstance, public IShipyard class CGShipyard : public CGObjectInstance, public IShipyard
{ {
public: public:
@ -819,4 +894,17 @@ public:
class DLL_EXPORT CGMagi : public CGObjectInstance
{
public:
static std::map <si32, std::vector<CGMagi>> eyelist; //[subID][id], supports multiple sets as in H5
void initObj();
void onHeroVisit(const CGHeroInstance * h) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);
}
};
#endif // __COBJECTHANDLER_H__ #endif // __COBJECTHANDLER_H__

8
int3.h
View File

@ -18,8 +18,14 @@ class CCreature;
class CCreatureSet //seven combined creatures class CCreatureSet //seven combined creatures
{ {
public: public:
std::map<si32,std::pair<ui32,si32> > slots; //slots[slot_id]=> pair(creature_id,creature_quantity) std::map<si32, std::pair<ui32,si32>> slots; //slots[slot_id]=> pair(creature_id,creature_quantity)
bool formation; //false - wide, true - tight bool formation; //false - wide, true - tight
bool setCreature (si32 slot, ui32 type, si32 quantity) //slots 1 to 7
{
slots.find(slot)->second = std::pair<ui32,si32>(type, quantity); //brutal force
if (slots.size() > 7) return false;
else return true;
}
si32 getSlotFor(ui32 creature, ui32 slotsAmount=7) const //returns -1 if no slot available si32 getSlotFor(ui32 creature, ui32 slotsAmount=7) const //returns -1 if no slot available
{ {
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i=slots.begin(); i!=slots.end(); ++i) for(std::map<si32,std::pair<ui32,si32> >::const_iterator i=slots.begin(); i!=slots.end(); ++i)

View File

@ -72,6 +72,7 @@ public:
virtual ui32 showBlockingDialog(BlockingDialog *iw) =0; //synchronous version of above //TODO: virtual ui32 showBlockingDialog(BlockingDialog *iw) =0; //synchronous version of above //TODO:
virtual void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window virtual void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
virtual void giveResource(int player, int which, int val)=0; virtual void giveResource(int player, int which, int val)=0;
virtual void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet *creatures)=0;
virtual void showCompInfo(ShowInInfobox * comp)=0; virtual void showCompInfo(ShowInInfobox * comp)=0;
virtual void heroVisitCastle(int obj, int heroID)=0; virtual void heroVisitCastle(int obj, int heroID)=0;
virtual void stopHeroVisitCastle(int obj, int heroID)=0; virtual void stopHeroVisitCastle(int obj, int heroID)=0;

View File

@ -1296,4 +1296,37 @@ struct SetSelection : public CPackForClient, public CPackForServer //514
} }
}; };
struct TakeYourTime : public CPackForClient//515
{
TakeYourTime(){CPackForClient::type = 515;};
DLL_EXPORT void applyGs(CGameState *gs);
void applyCl(CClient *cl);
bool applyGh(CGameHandler *gh);
ui8 player;
ui32 time;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & time & player;
}
};
struct CenterView : public CPackForClient//516
{
CenterView(){CPackForClient::type = 516;};
DLL_EXPORT void applyGs(CGameState *gs);
void applyCl(CClient *cl);
bool applyGh(CGameHandler *gh);
ui8 player;
si32 id;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & player;
}
};
#endif //__NETPACKS_H__ #endif //__NETPACKS_H__

View File

@ -1001,8 +1001,16 @@ DLL_EXPORT void YourTurn::applyGs( CGameState *gs )
gs->currentPlayer = player; gs->currentPlayer = player;
} }
DLL_EXPORT void SetSelection::applyGs( CGameState *gs ) DLL_EXPORT void SetSelection::applyGs( CGameState *gs )
{ {
gs->getPlayer(player)->currentSelection = id; gs->getPlayer(player)->currentSelection = id;
} }
DLL_EXPORT void CenterView::applyGs( CGameState *gs )
{
gs->getPlayer(player)->currentSelection = id;
}
DLL_EXPORT void TakeYourTime::applyGs( CGameState *gs )
{
}

View File

@ -42,9 +42,14 @@ void registerTypes1(Serializer &s)
s.template registerType<CGBonusingObject>(); s.template registerType<CGBonusingObject>();
s.template registerType<CGMagicWell>(); s.template registerType<CGMagicWell>();
s.template registerType<CGObservatory>(); s.template registerType<CGObservatory>();
s.template registerType<CGKeys>();
s.template registerType<CGKeymasterTent>();
s.template registerType<CGBorderGuard>();
s.template registerType<CGBoat>(); s.template registerType<CGBoat>();
s.template registerType<CGMagi>();
s.template registerType<CGSirens>(); s.template registerType<CGSirens>();
s.template registerType<CGOnceVisitable>(); s.template registerType<CGOnceVisitable>();
s.template registerType<CBank>();
s.template registerType<CGShipyard>(); s.template registerType<CGShipyard>();
s.template registerType<CGObjectInstance>(); s.template registerType<CGObjectInstance>();
} }
@ -105,6 +110,8 @@ void registerTypes2(Serializer &s)
s.template registerType<SaveGame>(); s.template registerType<SaveGame>();
s.template registerType<SetSelection>(); s.template registerType<SetSelection>();
s.template registerType<PlayerMessage>(); s.template registerType<PlayerMessage>();
s.template registerType<TakeYourTime>();
s.template registerType<CenterView>();
} }
template<typename Serializer> DLL_EXPORT template<typename Serializer> DLL_EXPORT

View File

@ -101,6 +101,8 @@ static EDefType getDefType(CGDefInfo * a)
return ARTIFACT_DEF; //handled return ARTIFACT_DEF; //handled
case 6: case 6:
return PANDORA_DEF; //hanled return PANDORA_DEF; //hanled
case 10:
return EVENTOBJ_DEF; //???
case 26: case 26:
return EVENTOBJ_DEF; //handled return EVENTOBJ_DEF; //handled
case 33: case 33:
@ -135,7 +137,7 @@ static EDefType getDefType(CGDefInfo * a)
return WITCHHUT_DEF; //handled return WITCHHUT_DEF; //handled
case 214: case 214:
return HEROPLACEHOLDER_DEF; //partially handled return HEROPLACEHOLDER_DEF; //partially handled
case 215: case 215: case 9: //???
return BORDERGUARD_DEF; //handled by analogy to seer huts ;] return BORDERGUARD_DEF; //handled by analogy to seer huts ;]
case 216: case 216:
return CREGEN2_DEF; //handled return CREGEN2_DEF; //handled
@ -1852,6 +1854,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
case 31: //Fountain of Youth case 31: //Fountain of Youth
case 11: //Buoy case 11: //Buoy
case 52: //Mermaid case 52: //Mermaid
case 94: //Stables
{ {
nobj = new CGBonusingObject(); nobj = new CGBonusingObject();
break; break;
@ -1895,6 +1898,31 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
{ {
i+=3; //TODO: handle it more properly i+=3; //TODO: handle it more properly
} }
case 10: //Keymaster
{
nobj = new CGKeymasterTent();
break;
}
case 9: //Border Guard
{
nobj = new CGBorderGuard();
break;
}
case 212: //Border Gate
{
nobj = new CGBorderGate();
break;
}
case 27: case 37: //Eye and Hut of Magi
{
nobj = new CGMagi();
break;
}
case 16: case 24: case 25: case 84: case 85: //treasure bank
{
nobj = new CBank();
break;
}
default: default:
nobj = new CGObjectInstance(); nobj = new CGObjectInstance();
} //end of main switch } //end of main switch

View File

@ -406,6 +406,8 @@ struct DLL_EXPORT Mapa : public CMapHeader
} }
h & CGTeleport::objs; h & CGTeleport::objs;
h & CGKeys::playerKeyMap;
h & CGMagi::eyelist;
for(int i=0; i<objects.size(); i++) for(int i=0; i<objects.size(); i++)
{ {

View File

@ -1431,6 +1431,35 @@ void CGameHandler::giveResource(int player, int which, int val)
sr.val = gs->players.find(player)->second.resources[which]+val; sr.val = gs->players.find(player)->second.resources[which]+val;
sendAndApply(&sr); sendAndApply(&sr);
} }
void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet *creatures)
{
CCreatureSet heroArmy = h->army;
while(creatures)
{
int slot = heroArmy.getSlotFor(creatures->slots.begin()->second.first);
if(slot < 0)
break;
heroArmy.slots[slot].first = creatures->slots.begin()->second.first;
heroArmy.slots[slot].second += creatures->slots.begin()->second.second;
creatures->slots.erase(creatures->slots.begin());
}
if(!creatures) //all creatures can be moved to hero army - do that
{
SetGarrisons sg;
sg.garrs[h->id] = heroArmy;
sendAndApply(&sg);
}
else //show garrison window and let player pick creatures
{
SetGarrisons sg;
sg.garrs[objid] = *creatures;
sendAndApply(&sg);
showGarrisonDialog(objid, h->id, 0);
return;
}
}
void CGameHandler::showCompInfo(ShowInInfobox * comp) void CGameHandler::showCompInfo(ShowInInfobox * comp)
{ {
sendToAllClients(comp); sendToAllClients(comp);

View File

@ -115,6 +115,7 @@ public:
ui32 showBlockingDialog(BlockingDialog *iw); //synchronous version of above ui32 showBlockingDialog(BlockingDialog *iw); //synchronous version of above
void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb); void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb);
void giveResource(int player, int which, int val); void giveResource(int player, int which, int val);
void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet *creatures);
void showCompInfo(ShowInInfobox * comp); void showCompInfo(ShowInInfobox * comp);
void heroVisitCastle(int obj, int heroID); void heroVisitCastle(int obj, int heroID);
void stopHeroVisitCastle(int obj, int heroID); void stopHeroVisitCastle(int obj, int heroID);

View File

@ -21,7 +21,7 @@ public:
long getDif(){long ret=clock()-last;last=clock();return ret;}; long getDif(){long ret=clock()-last;last=clock();return ret;};
void update(){last=clock();}; void update(){last=clock();};
void remember(){mem=clock();}; void remember(){mem=clock();};
long memDif(){return mem-clock();}; long memDif(){return clock()-mem;};
}; };