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

* New file: lib/HeroBonus.cpp - updated project files for MSVC

* Updated changelog
* Support for Lighthosues and Obelisks
* Bonus system extended on players 
* Army speed won't affect movement points when sailing
* Picking grail position (digging not implemented though, puzzle map only partially)
* Minor improvements
This commit is contained in:
Michał W. Urbańczyk 2010-02-10 02:56:00 +00:00
parent d0bf334394
commit 0fdbe787dc
30 changed files with 638 additions and 148 deletions

View File

@ -317,7 +317,7 @@ std::vector< std::vector< std::vector<unsigned char> > > & CCallback::getVisibil
bool CCallback::isVisible(int3 pos, int Player) const
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return gs->isVisible(pos, Player);
return gs->map->isInTheMap(pos) && gs->isVisible(pos, Player);
}
std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur) const
@ -905,6 +905,12 @@ void CCallback::calculatePaths( const CGHeroInstance *hero, CPathsInfo &out, int
gs->calculatePaths(hero, out, src, movement);
}
int3 CCallback::getGrailPos( float &outKnownRatio )
{
outKnownRatio = (float)CGObelisk::visited[player] / CGObelisk::obeliskCount;
return gs->map->grailPos;
}
InfoAboutTown::InfoAboutTown()
{
tType = NULL;

View File

@ -114,6 +114,7 @@ public:
virtual int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const =0; //when called during battle, takes into account creatures' spell cost reduction
virtual int estimateSpellDamage(const CSpell * sp) const =0; //estimates damage of given spell; returns 0 if spell causes no dmg
virtual void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)=0; //get thieves' guild info obtainable while visiting given object
virtual int3 getGrailPos(float &outKnownRatio)=0;
//hero
virtual int howManyHeroes(bool includeGarrisoned = true)const =0;
@ -247,6 +248,7 @@ public:
int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //when called during battle, takes into account creatures' spell cost reduction
int estimateSpellDamage(const CSpell * sp) const; //estimates damage of given spell; returns 0 if spell causes no dmg
void getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj); //get thieves' guild info obtainable while visiting given object
int3 getGrailPos(float &outKnownRatio); //returns pos and (via arg) percent of discovered obelisks; TODO: relies on fairness of GUI/AI... :/
std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos) const;
std::vector < const CGObjectInstance * > getVisitableObjs(int3 pos) const;

View File

@ -21,7 +21,7 @@ using namespace boost::logic;
class CCallback;
class ICallback;
class CGlobalAI;
class Component;
struct Component;
class CSelectableComponent;
struct TryMoveHero;
class CGHeroInstance;
@ -91,6 +91,7 @@ public:
virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water
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.
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void showPuzzleMap(){};
virtual void tileHidden(const std::set<int3> &pos){};
virtual void tileRevealed(const std::set<int3> &pos){};
virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard
@ -98,6 +99,7 @@ public:
virtual void centerView (int3 pos, int focusTime){};
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 playerBonusChanged(const HeroBonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
virtual void requestRealized(PackageApplied *pa){};
virtual void heroExchangeStarted(si32 hero1, si32 hero2){};
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged

View File

@ -1,3 +1,42 @@
0.75 -> 0.8
GENERAL:
* Victory and loss conditions are supported. It's now possible to win or lose the game.
* Kingdom Overview screen is now available.
* Replaced TTF fonts with original ones.
ADVENTURE MAP:
* Implemented rivers animations (thx to GrayFace).
HERO:
* Partial implementation of scholar skill (spell exchange works, but no message).
TOWN:
* New left-bottom info panel functionalities.
TOWNS:
* new town structures supported:
- Ballista Yard
- Blood Obelisk
- Dwarven Treasury
- Glyphs of Fear
- Mystic Pond
- Thieves Guild
OBJECTS:
New objects supported:
- Border gate
- Den of Thieves
- Lighthouse
- Obelisk
- Quest Guard
- Seer hut
A lot of of various bugfixes and improvements:
http://vcmi.antypika.aplus.pl/bugs/view_all_bug_page.php?filter=699
0.74 -> 0.75 (Dec 01 2009)
GENERAL:
* Implemented "main menu" in-game option.

View File

@ -2060,7 +2060,7 @@ CAdventureOptions::CAdventureOptions()
//viewWorld = new AdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN);
puzzle = new AdventureMapButton("","", boost::bind(&CGuiHandler::popIntTotally, &GH, this), 24, 81, "ADVPUZ.DEF");;
puzzle->callback += CAdventureOptions::showPuzzleMap;
puzzle->callback += boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT);
}
CAdventureOptions::~CAdventureOptions()
@ -2070,9 +2070,4 @@ CAdventureOptions::~CAdventureOptions()
void CAdventureOptions::showScenarioInfo()
{
GH.pushInt(new CScenarioInfo(LOCPLINT->cb->getMapHeader(), LOCPLINT->cb->getStartInfo()));
}
void CAdventureOptions::showPuzzleMap()
{
GH.pushInt(new CPuzzleWindow());
}
}

View File

@ -34,7 +34,6 @@ public:
CAdventureOptions();
~CAdventureOptions();
static void showScenarioInfo();
static void showPuzzleMap();
};

View File

@ -1169,6 +1169,8 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
ch = ci->town->visitingHero;
};
//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);

View File

@ -230,7 +230,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
if(makingTurn && ho->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
{
if(details.result == TryMoveHero::TELEPORTATION || details.start == details.end)
if(details.result == TryMoveHero::TELEPORTATION/* || details.start == details.end*/)
{
adventureInt->eraseCurrentPathOf(ho);
return; //teleport - no fancy moving animation
@ -1629,6 +1629,22 @@ void CPlayerInterface::gameOver(ui8 player, bool victory )
}
}
void CPlayerInterface::playerBonusChanged( const HeroBonus &bonus, bool gain )
{
}
void CPlayerInterface::showPuzzleMap()
{
waitWhileDialog();
//TODO: interface should not know the real position of Grail...
float ratio = 0;
int3 grailPos = cb->getGrailPos(ratio);
GH.pushInt(new CPuzzleWindow(grailPos, ratio));
}
void SystemOptions::setMusicVolume( int newVolume )
{
musicVolume = newVolume;

View File

@ -159,12 +159,14 @@ public:
void showShipyardDialog(const IShipyard *obj); //obj may be town or shipyard;
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, bool removableUnits, boost::function<void()> &onEnd);
void showPuzzleMap();
void tileHidden(const std::set<int3> &pos); //called when given tiles become hidden under fog of war
void tileRevealed(const std::set<int3> &pos); //called when fog of war disappears from given tiles
void newObject(const CGObjectInstance * obj);
void yourTurn();
void availableCreaturesChanged(const CGDwelling *town);
void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain);//if gain hero received bonus, else he lost it
void playerBonusChanged(const HeroBonus &bonus, bool gain);
void requestRealized(PackageApplied *pa);
void heroExchangeStarted(si32 hero1, si32 hero2);
void centerView (int3 pos, int focusTime);

View File

@ -4710,7 +4710,7 @@ CShipyardWindow::CShipyardWindow(const std::vector<si32> &cost, int state, const
printAtMiddle(CGI->generaltexth->jktexts[14], 164, 220, FONT_MEDIUM, zwykly, bg); //Resource cost:
}
CPuzzleWindow::CPuzzleWindow()
CPuzzleWindow::CPuzzleWindow(const int3 &grailPos, float discoveredRatio)
:animCount(0)
{
SDL_Surface * back = BitmapHandler::loadBitmap("PUZZLE.BMP", false);
@ -4728,19 +4728,17 @@ CPuzzleWindow::CPuzzleWindow()
//printing necessary thinks to background
CGI->mh->terrainRect
(int3(14, 15, 0), LOCPLINT->adventureInt->anim,
(grailPos, LOCPLINT->adventureInt->anim,
&LOCPLINT->cb->getVisibilityMap(), true, LOCPLINT->adventureInt->heroAnim,
background, &genRect(544, 591, 8, 8), 0, 0, true);
float discoveryRatio = 0.5f;
int faction = LOCPLINT->cb->getStartInfo()->playerInfos[LOCPLINT->serialID].castle;
std::vector<SPuzzleInfo> puzzlesToPrint;
for(int g=0; g<PUZZLES_PER_FACTION; ++g)
{
if(CGI->heroh->puzzleInfo[faction][g].whenUncovered >= PUZZLES_PER_FACTION * discoveryRatio)
if(CGI->heroh->puzzleInfo[faction][g].whenUncovered > PUZZLES_PER_FACTION * discoveredRatio)
{
puzzlesToPrint.push_back(CGI->heroh->puzzleInfo[faction][g]);
}

View File

@ -825,7 +825,7 @@ public:
void deactivate();
void show(SDL_Surface * to);
CPuzzleWindow();
CPuzzleWindow(const int3 &grailPos, float discoveredRatio);
~CPuzzleWindow();
};

View File

@ -109,9 +109,21 @@ void SetAvailableHeroes::applyCl( CClient *cl )
void GiveBonus::applyCl( CClient *cl )
{
CGHeroInstance *h = GS(cl)->getHero(hid);
if(vstd::contains(cl->playerint,h->tempOwner))
cl->playerint[h->tempOwner]->heroBonusChanged(h,h->bonuses.back(),true);
switch(who)
{
case HERO:
{
const CGHeroInstance *h = GS(cl)->getHero(id);
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroBonusChanged, h, h->bonuses.back(),true);
}
break;
case PLAYER:
{
const PlayerState *p = GS(cl)->getPlayer(id);
INTERFACE_CALL_IF_PRESENT(id, playerBonusChanged, p->bonuses.back(), true);
}
break;
}
}
void ChangeObjPos::applyFirstCl( CClient *cl )
@ -133,6 +145,25 @@ void PlayerEndsGame::applyCl( CClient *cl )
i->second->gameOver(player, victory);
}
void RemoveBonus::applyCl( CClient *cl )
{
switch(who)
{
case HERO:
{
const CGHeroInstance *h = GS(cl)->getHero(id);
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroBonusChanged, h, bonus,false);
}
break;
case PLAYER:
{
const PlayerState *p = GS(cl)->getPlayer(id);
INTERFACE_CALL_IF_PRESENT(id, playerBonusChanged, bonus, false);
}
break;
}
}
void RemoveObject::applyFirstCl( CClient *cl )
{
const CGObjectInstance *o = cl->getObj(id);
@ -635,6 +666,11 @@ void OpenWindow::applyCl(CClient *cl)
GH.pushInt( new CThievesGuildWindow(obj) );
}
break;
case PUZZLE_MAP:
{
INTERFACE_CALL_IF_PRESENT(id1, showPuzzleMap);
}
break;
}
}

View File

@ -253,4 +253,4 @@ GUISettings
ButtonEndTurn: x=1559 y=491 graphic=IAM001.DEF playerColoured=1;
};
}
}
}

View File

@ -75,9 +75,10 @@ enum ECombatInfo{ALIVE = 180, SUMMONED, CLONED, HAD_MORALE, WAITING, MOVED, DEFE
class CGameInfo;
extern CGameInfo* CGI;
#define HEROI_TYPE (34)
#define TOWNI_TYPE (98)
#define CREI_TYPE (54)
const int HEROI_TYPE = 34,
TOWNI_TYPE = 98,
CREI_TYPE = 54,
EVENTI_TYPE = 26;
const int F_NUMBER = 9; //factions (town types) quantity
const int PLAYER_LIMIT = 8; //player limit per map
@ -265,6 +266,7 @@ t1 & amax(t1 &a, const t2 &b) //assigns greater of (a, b) to a and returns maxim
return a;
}
}
template <typename t1, typename t2>
t1 & amin(t1 &a, const t2 &b) //assigns smaller of (a, b) to a and returns minimum of (a, b)
{
@ -276,6 +278,15 @@ t1 & amin(t1 &a, const t2 &b) //assigns smaller of (a, b) to a and returns minim
return a;
}
}
template <typename t1, typename t2, typename t3>
t1 & abetw(t1 &a, const t2 &b, const t3 &c) //makes a to fit the range <b, c>
{
amax(a,b);
amin(a,c);
return a;
}
#include "CConsoleHandler.h"
extern DLL_EXPORT std::ostream *logfile;
extern DLL_EXPORT CConsoleHandler *console;

View File

@ -44,6 +44,9 @@ extern boost::rand48 ran;
std::map <ui8, std::set <ui8> > CGKeys::playerKeyMap;
std::map <si32, std::vector<si32> > CGMagi::eyelist;
BankConfig CGPyramid::pyramidConfig;
ui8 CGObelisk::obeliskCount; //how many obelisks are on map
std::map<ui8, ui8> CGObelisk::visited; //map: color_id => how many obelisks has been visited
void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
{};
@ -429,7 +432,7 @@ void CGObjectInstance::giveDummyBonus(int heroID, ui8 duration) const
{
GiveBonus gbonus;
gbonus.bonus.type = HeroBonus::NONE;
gbonus.hid = heroID;
gbonus.id = heroID;
gbonus.bonus.duration = duration;
gbonus.bonus.source = HeroBonus::OBJECT;
gbonus.bonus.id = ID;
@ -563,10 +566,8 @@ bool CGHeroInstance::canWalkOnSea() const
int CGHeroInstance::getPrimSkillLevel(int id) const
{
int ret = primSkills[id];
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
if(i->type == HeroBonus::PRIMARY_SKILL && i->subtype==id)
ret += i->val;
amax(ret, id/2);//minimum value for attack and defense is 0 and for spell power and knowledge - 1
ret += valOfBonuses(HeroBonus::PRIMARY_SKILL, id);
amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
return ret;
}
ui8 CGHeroInstance::getSecSkillLevel(const int & ID) const
@ -578,13 +579,21 @@ ui8 CGHeroInstance::getSecSkillLevel(const int & ID) const
}
int CGHeroInstance::maxMovePoints(bool onLand) const
{
static const int moveForSpeed[] = { 1500, 1560, 1630, 1700, 1760, 1830, 1900, 1960, 2000 }; //first element for 3 and lower; last for 11 and more
int index = lowestSpeed(this) - 3;
amin(index, ARRAY_COUNT(moveForSpeed)-1);
amax(index, 0);
int ret = moveForSpeed[index],
bonus = valOfBonuses(HeroBonus::MOVEMENT) + (onLand ? valOfBonuses(HeroBonus::LAND_MOVEMENT) : valOfBonuses(HeroBonus::SEA_MOVEMENT));
int base = -1;
if(onLand)
{
static const int moveForSpeed[] = { 1500, 1560, 1630, 1700, 1760, 1830, 1900, 1960, 2000 }; //first element for 3 and lower; last for 11 and more
int index = lowestSpeed(this) - 3;
amin(index, ARRAY_COUNT(moveForSpeed)-1);
amax(index, 0);
base = moveForSpeed[index];
}
else
{
base = 1500; //on water base movement is always 1500 (speed of army doesn't matter)
}
int bonus = valOfBonuses(HeroBonus::MOVEMENT) + (onLand ? valOfBonuses(HeroBonus::LAND_MOVEMENT) : valOfBonuses(HeroBonus::SEA_MOVEMENT));
double modifier = 0;
if(onLand)
@ -619,7 +628,7 @@ int CGHeroInstance::maxMovePoints(bool onLand) const
break;
}
}
return int(ret + ret*modifier) + bonus;
return int(base + base*modifier) + bonus;
}
ui32 CGHeroInstance::getArtAtPos(ui16 pos) const
@ -879,15 +888,7 @@ std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentMoraleModifie
{
//TODO: check if stack is undead/mechanic/elemental => always neutrl morale
std::vector<std::pair<int,std::string> > ret;
//various morale bonuses (from buildings, artifacts, etc)
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
{
if(i->type == HeroBonus::MORALE || i->type == HeroBonus::MORALE_AND_LUCK)
{
ret.push_back(std::make_pair(i->val, i->description));
}
}
getModifiersWDescr(ret, MORALE_AFFECTING);
//leadership
if(getSecSkillLevel(6))
@ -961,42 +962,29 @@ int CGHeroInstance::getCurrentLuck( int stack/*=-1*/, bool town/*=false*/ ) cons
std::vector<std::pair<int,std::string> > mods = getCurrentLuckModifiers(stack,town);
for(int i=0; i < mods.size(); i++)
ret += mods[i].first;
if(ret > 3)
return 3;
if(ret < -3)
return -3;
abetw(ret, -3, 3);
return ret;
}
std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentLuckModifiers( int stack/*=-1*/, bool town/*=false*/ ) const
{
std::vector<std::pair<int,std::string> > ret;
//various morale bonuses (from buildings, artifacts, etc)
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
if(i->type == HeroBonus::LUCK || i->type == HeroBonus::MORALE_AND_LUCK)
ret.push_back(std::make_pair(i->val, i->description));
getModifiersWDescr(ret, LUCK_AFFECTING);
//luck skill
if(getSecSkillLevel(9))
ret.push_back(std::make_pair(getSecSkillLevel(9),VLC->generaltexth->arraytxt[73+getSecSkillLevel(9)]));
if(visitedTown)
{
if(visitedTown->subID == 1 && vstd::contains(visitedTown->builtBuildings,21)) //castle, brotherhood of sword built
ret.push_back(std::pair<int,std::string>(2,VLC->generaltexth->buildings[1][21].first + " +2"));
}
if(visitedTown && visitedTown->subID == 1 && vstd::contains(visitedTown->builtBuildings,21)) //rampart, fountain of fortune
ret.push_back(std::pair<int,std::string>(2,VLC->generaltexth->buildings[1][21].first + " +2"));
return ret;
}
const HeroBonus * CGHeroInstance::getBonus( int from, int id ) const
{
for (std::list<HeroBonus>::const_iterator i=bonuses.begin(); i!=bonuses.end(); i++)
if(i->source == from && i->id == id)
return &*i;
return NULL;
return bonuses.getBonus(from, id);
}
void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
@ -1048,26 +1036,16 @@ bool CGHeroInstance::canCastThisSpell(const CSpell * spell) const
if(!getArt(17)) //if hero has no spellbook
return false;
if(vstd::contains(spells, spell->id) //hero does not have this spell in spellbook
if(vstd::contains(spells, spell->id) //hero has this spell in spellbook
|| (spell->air && hasBonusOfType(HeroBonus::AIR_SPELLS)) // this is air spell and hero can cast all air spells
|| (spell->fire && hasBonusOfType(HeroBonus::FIRE_SPELLS)) // this is fire spell and hero can cast all fire spells
|| (spell->water && hasBonusOfType(HeroBonus::WATER_SPELLS)) // this is water spell and hero can cast all water spells
|| (spell->earth && hasBonusOfType(HeroBonus::EARTH_SPELLS)) // this is earth spell and hero can cast all earth spells
|| hasBonusOfType(HeroBonus::SPELL, spell->id)
|| hasBonusOfType(HeroBonus::SPELLS_OF_LEVEL, spell->level)
)
return true;
for(std::list<HeroBonus>::const_iterator it = bonuses.begin(); it != bonuses.end(); ++it)
{
if(it->type == HeroBonus::SPELL && it->subtype == spell->id)
{
return true;
}
if(it->type == HeroBonus::SPELLS_OF_LEVEL && it->subtype == spell->level)
{
return true;
}
}
return false;
}
@ -1165,40 +1143,15 @@ si32 CGHeroInstance::manaRegain() const
int CGHeroInstance::valOfBonuses( HeroBonus::BonusType type, int subtype /*= -1*/ ) const
{
int ret = 0;
if(subtype == -1)
{
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
if(i->type == type)
ret += i->val;
}
else
{
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
if(i->type == type && i->subtype == subtype)
ret += i->val;
}
return ret;
return bonuses.valOfBonuses(type, subtype) + ownerBonuses()->valOfBonuses(type, subtype);
}
bool CGHeroInstance::hasBonusOfType(HeroBonus::BonusType type, int subtype /*= -1*/) const
{
if(!this) //to allow calls on NULL and avoid checking duplication
return false; //if hero doesn't exist then bonus neither can
if(subtype == -1) //any subtype
{
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
if(i->type == type)
return true;
}
else //given subtype
{
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
if(i->type == type && i->subtype == subtype)
return true;
}
return false;
else
return bonuses.hasBonusOfType(type, subtype) || ownerBonuses()->hasBonusOfType(type, subtype);
}
si32 CGHeroInstance::getArtPos(int aid) const
@ -1252,6 +1205,21 @@ bool CGHeroInstance::hasArt( ui32 aid ) const
return false;
}
void CGHeroInstance::getModifiersWDescr( std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype /*= -1*/ ) const
{
bonuses.getModifiersWDescr(out, type, subtype);
ownerBonuses()->getModifiersWDescr(out, type, subtype);
}
const BonusList * CGHeroInstance::ownerBonuses() const
{
const PlayerState *p = cb->getPlayerState(tempOwner);
if(!p)
return NULL;
else
return &p->bonuses;
}
void CGDwelling::initObj()
{
switch(ID)
@ -2166,7 +2134,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
{
GiveBonus gb;
gb.bonus = HeroBonus(HeroBonus::ONE_WEEK, HeroBonus::LAND_MOVEMENT, HeroBonus::OBJECT, 600, 94, VLC->generaltexth->arraytxt[100]);
gb.hid = heroID;
gb.id = heroID;
cb->giveHeroBonus(&gb);
iw.text << VLC->generaltexth->allTexts[580];
cb->showInfoDialog(&iw);
@ -3632,7 +3600,7 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward
HeroBonus hb(HeroBonus::ONE_WEEK, (rewardType == 3 ? HeroBonus::MORALE : HeroBonus::LUCK),
HeroBonus::OBJECT, rVal, h->id, "", -1);
GiveBonus gb;
gb.hid = h->id;
gb.id = h->id;
gb.bonus = hb;
//gb.descr = "";
cb->giveHeroBonus(&gb);
@ -3752,7 +3720,7 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
InfoWindow iw;
iw.player = h->tempOwner;
GiveBonus gbonus;
gbonus.hid = h->id;
gbonus.id = h->id;
gbonus.bonus.duration = HeroBonus::ONE_BATTLE;
gbonus.bonus.source = HeroBonus::OBJECT;
gbonus.bonus.id = ID;
@ -4121,7 +4089,7 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
cb->showInfoDialog(&iw);
GiveBonus gb;
gb.bonus = HeroBonus(HeroBonus::ONE_BATTLE,HeroBonus::MORALE,HeroBonus::OBJECT,moraleDiff,id,"");
gb.hid = h->id;
gb.id = h->id;
cb->giveHeroBonus(&gb);
}
@ -4132,7 +4100,7 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
cb->showInfoDialog(&iw);
GiveBonus gb;
gb.bonus = HeroBonus(HeroBonus::ONE_BATTLE,HeroBonus::LUCK,HeroBonus::OBJECT,luckDiff,id,"");
gb.hid = h->id;
gb.id = h->id;
cb->giveHeroBonus(&gb);
}
@ -4688,7 +4656,7 @@ void CGOnceVisitable::searchTomb(const CGHeroInstance *h, ui32 accept) const
{
//ruin morale
GiveBonus gb;
gb.hid = h->id;
gb.id = 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);
@ -4912,7 +4880,7 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
{
iw.components.push_back (Component (Component::MORALE, 0 , -2, 0));
GiveBonus gbonus;
gbonus.hid = h->id;
gbonus.id = h->id;
gbonus.bonus.duration = HeroBonus::ONE_BATTLE;
gbonus.bonus.source = HeroBonus::OBJECT;
gbonus.bonus.id = ID;
@ -4931,7 +4899,7 @@ void CBank::endBattle (const CGHeroInstance *h, const BattleResult *result) cons
{
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
GiveBonus gbonus;
gbonus.hid = h->id;
gbonus.id = h->id;
gbonus.bonus.duration = HeroBonus::ONE_BATTLE;
gbonus.bonus.source = HeroBonus::OBJECT;
gbonus.bonus.id = ID;
@ -5077,7 +5045,7 @@ void CGPyramid::onHeroVisit (const CGHeroInstance * h) const
iw.components.push_back (Component (Component::LUCK, 0 , -2, 0));
GiveBonus gb;
gb.bonus = HeroBonus(HeroBonus::ONE_BATTLE,HeroBonus::LUCK,HeroBonus::OBJECT,-2,id,VLC->generaltexth->arraytxt[70]);
gb.hid = h->id;
gb.id = h->id;
cb->giveHeroBonus(&gb);
cb->showInfoDialog(&iw);
}
@ -5569,4 +5537,114 @@ void CGRefugeeCamp::reset(ui32 val)
void CGDenOfthieves::onHeroVisit (const CGHeroInstance * h) const
{
cb->showThievesGuildWindow(id);
}
void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
{
InfoWindow iw;
iw.player = h->tempOwner;
if(!hasVisited(h->tempOwner))
{
iw.text.addTxt(MetaString::ADVOB_TXT, 96);
cb->sendAndApply(&iw);
cb->setObjProperty(id,20,h->tempOwner); //increment general visited obelisks counter
OpenWindow ow;
ow.id1 = h->tempOwner;
ow.window = OpenWindow::PUZZLE_MAP;
cb->sendAndApply(&ow);
cb->setObjProperty(id,10,h->tempOwner); //mark that particular obelisk as visited
}
else
{
iw.text.addTxt(MetaString::ADVOB_TXT, 97);
cb->sendAndApply(&iw);
}
}
void CGObelisk::initObj()
{
obeliskCount++;
}
const std::string & CGObelisk::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
if(hasVisited(cb->getCurrentPlayer()))
hoverName += " " + VLC->generaltexth->allTexts[352]; //not visited
else
hoverName += " " + VLC->generaltexth->allTexts[353]; //visited
return hoverName;
}
void CGObelisk::setPropertyDer( ui8 what, ui32 val )
{
CPlayersVisited::setPropertyDer(what, val);
switch(what)
{
case 20:
assert(val < PLAYER_LIMIT);
visited[val]++;
assert(visited[val] <= obeliskCount);
break;
}
}
void CGLighthouse::onHeroVisit( const CGHeroInstance * h ) const
{
if(h->tempOwner != tempOwner)
{
ui8 oldOwner = tempOwner;
cb->setOwner(id,h->tempOwner); //not ours? flag it!
InfoWindow iw;
iw.player = h->tempOwner;
iw.text.addTxt(MetaString::ADVOB_TXT, 69);
iw.soundID = soundBase::LIGHTHOUSE;
cb->sendAndApply(&iw);
giveBonusTo(h->tempOwner);
if(oldOwner < PLAYER_LIMIT) //remove bonus from old owner
{
RemoveBonus rb(RemoveBonus::PLAYER);
rb.whoID = oldOwner;
rb.source = HeroBonus::OBJECT;
rb.id = id;
cb->sendAndApply(&rb);
}
}
}
void CGLighthouse::initObj()
{
if(tempOwner < PLAYER_LIMIT)
{
giveBonusTo(tempOwner);
}
}
const std::string & CGLighthouse::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
//TODO: owned by %s player
return hoverName;
}
void CGLighthouse::giveBonusTo( ui8 player ) const
{
GiveBonus gb(GiveBonus::PLAYER);
gb.bonus.type = HeroBonus::SEA_MOVEMENT;
gb.bonus.val = 500;
gb.id = player;
gb.bonus.duration = HeroBonus::PERMANENT;
gb.bonus.source = HeroBonus::OBJECT;
gb.bonus.id = id;
cb->sendAndApply(&gb);
}

View File

@ -70,7 +70,7 @@ public:
}
};
class CQuest
class DLL_EXPORT CQuest
{
public:
enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4,
@ -267,7 +267,7 @@ public:
}
} patrol;
std::list<HeroBonus> bonuses;
BonusList bonuses;
//////////////////////////////////////////////////////////////////////////
@ -292,9 +292,7 @@ public:
int getSightRadious() const; //sight distance (should be used if player-owned structure)
//////////////////////////////////////////////////////////////////////////
const HeroBonus *getBonus(int from, int id) const;
int valOfBonuses(HeroBonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then any
bool hasBonusOfType(HeroBonus::BonusType type, int subtype = -1) const; //determines if hero has a bonus of given type (and optionally subtype)
const std::string &getBiography() const;
bool needsLastStack()const;
unsigned int getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
@ -304,6 +302,18 @@ public:
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
bool canWalkOnSea() const;
int getCurrentLuck(int stack=-1, bool town=false) const;
const BonusList *ownerBonuses() const;
const HeroBonus *getBonus(int from, int id) const;
int valOfBonuses(HeroBonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then any
bool hasBonusOfType(HeroBonus::BonusType type, int subtype = -1) const; //determines if hero has a bonus of given type (and optionally subtype)
void getModifiersWDescr(std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype = -1) const; //out: pairs<modifier value, modifier description>
template<int N> void getModifiersWDescr(std::vector<std::pair<int,std::string> > &out, const HeroBonus::BonusType (&types)[N]) const //retreive array of types
{
for (int i = 0; i < N; i++)
getModifiersWDescr(out, types[i]);
}
std::vector<std::pair<int,std::string> > getCurrentLuckModifiers(int stack=-1, bool town=false) const; //args as above
int getCurrentMorale(int stack=-1, bool town=false) const; //if stack - position of creature, if -1 then morale for hero is calculated; town - if bonuses from town (tavern) should be considered
std::vector<std::pair<int,std::string> > getCurrentMoraleModifiers(int stack=-1, bool town=false) const; //args as above
@ -1078,6 +1088,37 @@ class DLL_EXPORT CGDenOfthieves : public CGObjectInstance
void onHeroVisit (const CGHeroInstance * h) const;
};
class DLL_EXPORT CGObelisk : public CPlayersVisited
{
public:
static ui8 obeliskCount; //how many obelisks are on map
static std::map<ui8, ui8> visited; //map: color_id => how many obelisks has been visited
void setPropertyDer (ui8 what, ui32 val);
void onHeroVisit(const CGHeroInstance * h) const;
void initObj();
const std::string & getHoverText() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CPlayersVisited&>(*this);;
}
};
class DLL_EXPORT CGLighthouse : public CGObjectInstance
{
public:
void onHeroVisit(const CGHeroInstance * h) const;
void initObj();
const std::string & getHoverText() const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CGObjectInstance&>(*this);;
}
void giveBonusTo( ui8 player ) const;
};
struct BankConfig
{
BankConfig() {level = chance = upgradeChance = combatValue = value = rewardDifficulty = easiest = 0; };

View File

@ -1280,6 +1280,45 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
scenarioOps = si;
this->map = map;
loadTownDInfos();
//pick grail location
if(map->grailPos.x < 0 || map->grailRadious) //grail not set or set within a radius around some place
{
if(!map->grailRadious) //radius not given -> anywhere on map
map->grailRadious = map->width * 2;
std::vector<int3> allowedPos;
// add all not blocked tiles in range
for (int i = 0; i < map->width ; i++)
{
for (int j = 0; j < map->height ; j++)
{
for (int k = 0; k <= map->twoLevel ; k++)
{
const TerrainTile &t = map->terrain[i][j][k];
if(!t.blocked
&& !t.visitable
&& t.tertype != TerrainTile::water
&& t.tertype != TerrainTile::rock
&& map->grailPos.dist2d(int3(i,j,k)) <= map->grailRadious)
allowedPos.push_back(int3(i,j,k));
}
}
}
//remove tiles with holes
for(unsigned int no=0; no<map->objects.size(); ++no)
if(map->objects[no]->ID == 124)
allowedPos -= map->objects[no]->pos;
if(allowedPos.size())
map->grailPos = allowedPos[ran() % allowedPos.size()];
else
tlog2 << "Warning: Grail cannot be placed, no appropriate tile found!\n";
}
//picking random factions for players
for(unsigned int i=0;i<scenarioOps->playerInfos.size();i++)
{
@ -1293,11 +1332,12 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
scenarioOps->playerInfos[i].castle = f;
}
}
//randomizing objects
for(unsigned int no=0; no<map->objects.size(); ++no)
{
randomizeObject(map->objects[no]);
if(map->objects[no]->ID==26)
if(map->objects[no]->ID==EVENTI_TYPE)
{
map->objects[no]->defInfo->handler=NULL;
}
@ -1940,7 +1980,7 @@ void CGameState::apply(CPack *pack)
applierGs->apps[typ]->applyOnGS(this,pack);
}
PlayerState * CGameState::getPlayer( ui8 color )
PlayerState * CGameState::getPlayer( ui8 color, bool verbose )
{
if(vstd::contains(players,color))
{
@ -1948,14 +1988,15 @@ PlayerState * CGameState::getPlayer( ui8 color )
}
else
{
tlog2 << "Warning: Cannot find info for player " << int(color) << std::endl;
if(verbose)
tlog2 << "Warning: Cannot find info for player " << int(color) << std::endl;
return NULL;
}
}
const PlayerState * CGameState::getPlayer( ui8 color ) const
const PlayerState * CGameState::getPlayer( ui8 color, bool verbose ) const
{
return (const_cast<CGameState *>(this))->getPlayer(color);
return (const_cast<CGameState *>(this))->getPlayer(color, verbose);
}
bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret)
@ -2163,7 +2204,7 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
node.accessible = CGPathNode::BLOCKVIS;
break;
}
else if(obj->ID != 26) //pathfinder should ignore placed events
else if(obj->ID != EVENTI_TYPE) //pathfinder should ignore placed events
{
node.accessible = CGPathNode::VISITABLE;
}

View File

@ -11,6 +11,7 @@
#include <vector>
#include <list>
#include "StackFeature.h"
#include "HeroBonus.h"
#ifdef _WIN32
#include <tchar.h>
#else
@ -117,6 +118,7 @@ public:
std::vector<CGTownInstance *> towns;
std::vector<CGHeroInstance *> availableHeroes; //heroes available in taverns
std::vector<CGDwelling *> dwellings; //used for town growth
BonusList bonuses; //player bonuses
ui8 status; //0 - in game, 1 - loser, 2 - winner <- uses EStatus enum
ui8 daysWithoutCastle;
@ -126,7 +128,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & color & serial & human & currentSelection & fogOfWarMap & resources & status;
h & heroes & towns & availableHeroes & dwellings & status & daysWithoutCastle;
h & heroes & towns & availableHeroes & dwellings & bonuses & status & daysWithoutCastle;
// ui32 size;
// if(h.saving) //write subids of available heroes
@ -405,8 +407,8 @@ public:
boost::shared_mutex *mx;
PlayerState *getPlayer(ui8 color);
const PlayerState *getPlayer(ui8 color) const;
PlayerState *getPlayer(ui8 color, bool verbose = true);
const PlayerState *getPlayer(ui8 color, bool verbose = true) const;
void init(StartInfo * si, Mapa * map, int Seed);
void loadTownDInfos();
void randomizeObject(CGObjectInstance *cur);

73
lib/HeroBonus.cpp Normal file
View File

@ -0,0 +1,73 @@
#define VCMI_DLL
#include "HeroBonus.h"
int BonusList::valOfBonuses( HeroBonus::BonusType type, int subtype /*= -1*/ ) const /*subtype -> subtype of bonus, if -1 then any */
{
if(!this) //to avoid null-checking in maany places -> no bonus list means 0 bonus value
return 0;
int ret = 0;
if(subtype == -1)
{
for(const_iterator i = begin(); i != end(); i++)
if(i->type == type)
ret += i->val;
}
else
{
for(const_iterator i = begin(); i != end(); i++)
if(i->type == type && i->subtype == subtype)
ret += i->val;
}
return ret;
}
bool BonusList::hasBonusOfType( HeroBonus::BonusType type, int subtype /*= -1*/ ) const
{
if(!this) //to avoid null-checking in maany places -> no bonus list means there is no searched bonus
return 0;
if(subtype == -1) //any subtype
{
for(const_iterator i = begin(); i != end(); i++)
if(i->type == type)
return true;
}
else //given subtype
{
for(const_iterator i = begin(); i != end(); i++)
if(i->type == type && i->subtype == subtype)
return true;
}
return false;
}
const HeroBonus * BonusList::getBonus( int from, int id ) const
{
if(!this) //to avoid null-checking in maany places -> no bonus list means bonus cannot be retreived
return NULL;
for (const_iterator i = begin(); i != end(); i++)
if(i->source == from && i->id == id)
return &*i;
return NULL;
}
void BonusList::getModifiersWDescr( std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype /*= -1 */ ) const
{
if(!this) //to avoid null-checking in maany places -> no bonus list means nothing has to be done here
return;
if(subtype == -1)
{
for(const_iterator i = begin(); i != end(); i++)
if(i->type == type)
out.push_back(std::make_pair(i->val, i->description));
}
else
{
for(const_iterator i = begin(); i != end(); i++)
if(i->type == type && i->subtype == subtype)
out.push_back(std::make_pair(i->val, i->description));
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "../global.h"
#include <string>
#include <list>
/*
* HeroBonus.h, part of VCMI engine
@ -75,6 +76,19 @@ struct DLL_EXPORT HeroBonus
{
subtype = -1;
}
// //comparison
// bool operator==(const HeroBonus &other)
// {
// return &other == this;
// //TODO: what is best logic for that?
// }
// bool operator<(const HeroBonus &other)
// {
// return &other < this;
// //TODO: what is best logic for that?
// }
template <typename Handler> void serialize(Handler &h, const int version)
{
h & duration & type & subtype & source & val & id & description;
@ -96,4 +110,23 @@ struct DLL_EXPORT HeroBonus
{
return hb.source==source && (id==0xffffff || hb.id==id);
}
};
static const HeroBonus::BonusType MORALE_AFFECTING[] = {HeroBonus::LUCK, HeroBonus::MORALE_AND_LUCK};
static const HeroBonus::BonusType LUCK_AFFECTING[] = {HeroBonus::MORALE, HeroBonus::MORALE_AND_LUCK};
typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions
class BonusList : public std::list<HeroBonus>
{
public:
int DLL_EXPORT valOfBonuses(HeroBonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then any
bool DLL_EXPORT hasBonusOfType(HeroBonus::BonusType type, int subtype = -1) const;
const DLL_EXPORT HeroBonus * getBonus( int from, int id ) const;
void DLL_EXPORT getModifiersWDescr( std::vector<std::pair<int,std::string> > &out, HeroBonus::BonusType type, int subtype = -1 ) const;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<std::list<HeroBonus>&>(*this);
}
};

View File

@ -256,4 +256,9 @@ inline TerrainTile * IGameCallback::getTile( int3 pos )
if(!gs->map->isInTheMap(pos))
return NULL;
return &gs->map->getTile(pos);
}
const PlayerState * IGameCallback::getPlayerState( int color )
{
return gs->getPlayer(color, false);
}

View File

@ -34,6 +34,7 @@ class CArtHandler;
class CArtifact;
class CArmedInstance;
struct TerrainTile;
struct PlayerState;
class DLL_EXPORT IGameCallback
{
@ -63,6 +64,7 @@ public:
virtual void getAllowedSpells(std::vector<ui16> &out, ui16 level);
virtual int3 getMapSize(); //returns size of the map
virtual TerrainTile * getTile(int3 pos);
virtual const PlayerState * getPlayerState(int color);
//do sth
virtual void changeSpells(int hid, bool give, const std::set<ui32> &spells)=0;

View File

@ -357,17 +357,24 @@ struct SetAvailableHeroes : public CPackForClient //113
struct GiveBonus : public CPackForClient //115
{
GiveBonus(){type = 115;};
GiveBonus(ui8 Who = 0)
{
who = Who;
type = 115;
}
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
ui32 hid;
enum {HERO, PLAYER};
ui8 who; //who receives bonus, uses enum above
ui32 id; //hero or player id
HeroBonus bonus;
MetaString bdescr;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & bonus & hid & bdescr;
h & bonus & id & bdescr & who;
}
};
@ -408,6 +415,34 @@ struct PlayerEndsGame : public CPackForClient //117
};
struct RemoveBonus : public CPackForClient //118
{
RemoveBonus(ui8 Who = 0)
{
who = Who;
type = 118;
}
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
enum {HERO, PLAYER};
ui8 who; //who receives bonus, uses enum above
ui32 whoID; //hero or player id
//vars to identify bonus: its source
ui8 source;
ui32 id; //source id
//used locally: copy of removed bonus
HeroBonus bonus;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & source & id & who & whoID;
}
};
struct RemoveObject : public CPackForClient //500
{
RemoveObject(){type = 500;};
@ -573,7 +608,7 @@ struct OpenWindow : public CPackForClient //517
OpenWindow(){type = 517;};
void applyCl(CClient *cl);
enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD};
enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD, PUZZLE_MAP};
ui8 window;
ui32 id1, id2;

View File

@ -186,16 +186,32 @@ DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs )
DLL_EXPORT void GiveBonus::applyGs( CGameState *gs )
{
CGHeroInstance *h = gs->getHero(hid);
h->bonuses.push_back(bonus);
BonusList *bonuses = NULL;
switch(who)
{
case HERO:
{
CGHeroInstance *h = gs->getHero(id);
assert(h);
bonuses = &h->bonuses;
}
break;
case PLAYER:
{
PlayerState *p = gs->getPlayer(id);
assert(p);
bonuses = &p->bonuses;
}
break;
}
std::string &descr = h->bonuses.back().description;
bonuses->push_back(bonus);
std::string &descr = bonuses->back().description;
if(!bdescr.message.size()
&& bonus.source == HeroBonus::OBJECT
&& (bonus.type == HeroBonus::LUCK || bonus.type == HeroBonus::MORALE || bonus.type == HeroBonus::MORALE_AND_LUCK)
&& gs->map->objects[bonus.id]->ID == 26) //it's morale/luck bonus from an event without description
&& gs->map->objects[bonus.id]->ID == EVENTI_TYPE) //it's morale/luck bonus from an event without description
{
descr = VLC->generaltexth->arraytxt[bonus.val > 0 ? 110 : 109]; //+/-%d Temporary until next battle"
boost::replace_first(descr,"%d",boost::lexical_cast<std::string>(std::abs(bonus.val)));
@ -225,6 +241,21 @@ DLL_EXPORT void PlayerEndsGame::applyGs( CGameState *gs )
p->status = victory ? 2 : 1;
}
DLL_EXPORT void RemoveBonus::applyGs( CGameState *gs )
{
std::list<HeroBonus> &bonuses = (who == HERO ? gs->getHero(whoID)->bonuses : gs->getPlayer(whoID)->bonuses);
for(std::list<HeroBonus>::iterator i = bonuses.begin(); i != bonuses.end(); i++)
{
if(i->source == source && i->id == id)
{
bonus = *i; //backup bonus (to show to interfaces later)
bonuses.erase(i);
break;
}
}
}
DLL_EXPORT void RemoveObject::applyGs( CGameState *gs )
{
CGObjectInstance *obj = gs->map->objects[id];
@ -588,6 +619,10 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
i->second.daysWithoutCastle = 0;
else
i->second.daysWithoutCastle++;
i->second.bonuses.remove_if(HeroBonus::OneDay);
if(gs->getDate(1) == 7) //new week
i->second.bonuses.remove_if(HeroBonus::OneWeek);
}
}

View File

@ -60,6 +60,8 @@ void registerTypes1(Serializer &s)
s.template registerType<CGObjectInstance>();
s.template registerType<COPWBonus>();
s.template registerType<CGDenOfthieves>();
s.template registerType<CGObelisk>();
s.template registerType<CGLighthouse>();
}
template<typename Serializer> DLL_EXPORT
@ -82,6 +84,7 @@ void registerTypes2(Serializer &s)
s.template registerType<GiveBonus>();
s.template registerType<ChangeObjPos>();
s.template registerType<PlayerEndsGame>();
s.template registerType<RemoveBonus>();
s.template registerType<RemoveObject>();
s.template registerType<TryMoveHero>();
s.template registerType<SetGarrisons>();

View File

@ -270,6 +270,10 @@
RelativePath="..\hch\CBuildingHandler.cpp"
>
</File>
<File
RelativePath="..\hch\CCampaignHandler.cpp"
>
</File>
<File
RelativePath="..\CConsoleHandler.cpp"
>
@ -314,6 +318,10 @@
RelativePath="..\hch\CTownHandler.cpp"
>
</File>
<File
RelativePath=".\HeroBonus.cpp"
>
</File>
<File
RelativePath=".\IGameCallback.cpp"
>
@ -356,6 +364,10 @@
RelativePath="..\hch\CBuildingHandler.h"
>
</File>
<File
RelativePath="..\hch\CCampaignHandler.h"
>
</File>
<File
RelativePath="..\CConsoleHandler.h"
>

View File

@ -529,6 +529,7 @@ void Mapa::addBlockVisTiles(CGObjectInstance * obj)
}
}
Mapa::Mapa(std::string filename)
:grailPos(-1, -1, -1)
{
int mapsize = 0;
@ -1318,7 +1319,7 @@ void Mapa::readDefInfo( const unsigned char * bufor, int &i)
vinya->visitDir = 0xff;
}
if(vinya->id == 26)
if(vinya->id == EVENTI_TYPE)
std::memset(vinya->blockMap,255,6);
//calculating coverageMap
@ -1353,7 +1354,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
switch(defInfo->id)
{
case 26: //for event objects
case EVENTI_TYPE: //for event objects
{
CGEvent *evnt = new CGEvent();
nobj = evnt;
@ -1648,7 +1649,6 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
i+=3;
break;
}
case 42: //lighthouse
case 220://mine (?)
{
nobj = new CGObjectInstance();
@ -1911,11 +1911,23 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
nobj = new CGDenOfthieves();
break;
}
case 57: //Obelisk
{
nobj = new CGObelisk();
break;
}
case 42: //Lighthouse
{
nobj = new CGLighthouse();
nobj->tempOwner = readNormalNr(bufor,i); i+=4;
break;
}
default: //any other object
{
nobj = new CGObjectInstance();
break;
}
} //end of main switch
nobj->pos = pos;

View File

@ -375,12 +375,13 @@ struct DLL_EXPORT Mapa : public CMapHeader
objects.resize(hlp);
}
//static structures
//static members
h & CGTeleport::objs;
h & CGTeleport::gates;
h & CGKeys::playerKeyMap;
h & CGMagi::eyelist;
h & CGPyramid::pyramidConfig;
h & CGObelisk::obeliskCount & CGObelisk::visited;
for(unsigned int i=0; i<objects.size(); i++)
{

View File

@ -301,7 +301,7 @@ void CMapHandler::initObjectRects()
}
static void processDef (CGDefInfo* def)
{
if(def->id == 26) //if it's event, return from function
if(def->id == EVENTI_TYPE)
return;
if(!def->handler) //if object has already set handler (eg. heroes) it should not be overwritten

View File

@ -856,6 +856,9 @@ void CGameHandler::newTurn()
for(std::list<HeroBonus>::iterator j = h->bonuses.begin(); j != h->bonuses.end(); j++)
if(j->type == HeroBonus::GENERATE_RESOURCE)
n.res[i->first][j->subtype] += j->val;
//TODO player bonuses
}
}
//n.res.push_back(r);
@ -1276,7 +1279,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
{
GiveBonus gs;
gs.bonus = HeroBonus(HeroBonus::ONE_BATTLE, HeroBonus::PRIMARY_SKILL, HeroBonus::OBJECT, val, -1, "", i);
gs.hid = hero2->id;
gs.id = hero2->id;
sendAndApply(&gs);
}
}
@ -1334,7 +1337,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
GiveBonus gs;
gs.bonus = HeroBonus(HeroBonus::ONE_BATTLE, HeroBonus::MAGIC_SCHOOL_SKILL, HeroBonus::OBJECT, 3, -1, "", bonusSubtype);
gs.hid = cHero->id;
gs.id = cHero->id;
sendAndApply(&gs);
}
@ -1393,7 +1396,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
GiveBonus gs;
gs.bonus = HeroBonus(HeroBonus::ONE_BATTLE, HeroBonus::BLOCK_SPELLS_ABOVE_LEVEL, HeroBonus::OBJECT, 1, -1, "", bonusSubtype);
gs.hid = cHero->id;
gs.id = cHero->id;
sendAndApply(&gs);
}
@ -1612,7 +1615,13 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
//call objects if they are visited
if(t.visitableObjects.size())
objectVisited(t.visitableObjects.back(), h);
{
//to prevent self-visiting heroes on space press
if(t.visitableObjects.back() != h)
objectVisited(t.visitableObjects.back(), h);
else if(t.visitableObjects.size() > 1)
objectVisited(*(t.visitableObjects.end()-2),h);
}
// BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects)
// {
// objectVisited(obj, h);