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

- More commanders

- Improved finding closest tiles on battlefield
This commit is contained in:
DjWarmonger 2012-04-22 17:38:36 +00:00
parent 81e74f8c33
commit 96d198758c
10 changed files with 124 additions and 17 deletions

View File

@ -1753,6 +1753,10 @@
"level": 0, "level": 0,
"name": [ "Paladin1" ], "name": [ "Paladin1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 37, 0 ] ], //expert cure
"defname": "ZM174NPC.DEF" "defname": "ZM174NPC.DEF"
}, },
@ -1761,6 +1765,10 @@
"level": 0, "level": 0,
"name": [ "Hierophant1" ], "name": [ "Hierophant1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 27, 0 ] ], //expert shield
"defname": "ZM175NPC.DEF" "defname": "ZM175NPC.DEF"
}, },
@ -1769,6 +1777,10 @@
"level": 0, "level": 0,
"name": [ "TempleGuardian1" ], "name": [ "TempleGuardian1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 44, 0 ] ], //expert precision
"defname": "ZM176NPC.DEF" "defname": "ZM176NPC.DEF"
}, },
@ -1777,6 +1789,10 @@
"level": 0, "level": 0,
"name": [ "Succubus1" ], "name": [ "Succubus1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 29, 0 ] ], //expert fire shield
"defname": "ZM177NPC.DEF" "defname": "ZM177NPC.DEF"
}, },
@ -1785,6 +1801,10 @@
"level": 0, "level": 0,
"name": [ "SoulEater1" ], "name": [ "SoulEater1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 39, 0 ] ], //expert animate dead
"defname": "ZM178NPC.DEF" "defname": "ZM178NPC.DEF"
}, },
@ -1793,6 +1813,10 @@
"level": 0, "level": 0,
"name": [ "Brute1" ], "name": [ "Brute1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 46, 0 ] ], //expert stone skin
"defname": "ZM179NPC.DEF" "defname": "ZM179NPC.DEF"
}, },
@ -1801,6 +1825,10 @@
"level": 0, "level": 0,
"name": [ "OgreLeader1" ], "name": [ "OgreLeader1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 37, 0 ] ], //expert cure
"defname": "ZM180NPC.DEF" "defname": "ZM180NPC.DEF"
}, },
@ -1809,6 +1837,10 @@
"level": 0, "level": 0,
"name": [ "Shaman1" ], "name": [ "Shaman1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 53, 0 ] ], //expert haste
"defname": "ZM181NPC.DEF" "defname": "ZM181NPC.DEF"
}, },
@ -1817,6 +1849,10 @@
"level": 0, "level": 0,
"name": [ "AstralSpirit1" ], "name": [ "AstralSpirit1" ],
"faction": -1, "faction": -1,
"ability_add": [ [ "MAGIC_RESISTANCE", 5, 0, 0 ],
[ "CASTS", 1, 0, 0 ] ,
[ "CREATURE_ENCHANT_POWER", 1, 0, 0 ] ,
[ "SPELLCASTER", 3, 58, 0 ] ], //expert counterstrike
"defname": "ZM182NPC.DEF" "defname": "ZM182NPC.DEF"
}, },

View File

@ -376,6 +376,40 @@ std::vector<BattleHex> BattleInfo::getAccessibility( const CStack * stack, bool
return ret; return ret;
} }
BattleHex BattleInfo::getClosestTile (bool attackerOwned, int initialPos, std::set<BattleHex> & possibilities) const
{
std::vector<BattleHex> sortedTiles (possibilities.begin(), possibilities.end()); //set can't be sorted properly :(
BattleHex initialHex = BattleHex(initialPos);
auto compareDistance = [initialPos, initialHex](const BattleHex left, const BattleHex right) -> bool
{
return initialHex.getDistance (initialHex, left) < initialHex.getDistance (initialHex, right);
};
boost::sort (sortedTiles, compareDistance); //closest tiles at front
int closestDistance = initialHex.getDistance(initialPos, sortedTiles.front()); //sometimes closest tiles can be many hexes away
auto notClosest = [closestDistance, initialPos](const BattleHex here) -> bool
{
return closestDistance < here.getDistance (initialPos, here);
};
boost::remove_if (sortedTiles, notClosest); //only closest tiles are interesting
auto compareHorizontal = [attackerOwned](const BattleHex left, const BattleHex right) -> bool
{
if (attackerOwned)
return left.getX() > right.getX(); //find furthest right
else
return left.getX() < right.getX(); //find furthest left
};
boost::sort (sortedTiles, compareHorizontal);
return sortedTiles.front();
}
int BattleInfo::getAvaliableHex(TCreature creID, bool attackerOwned, int initialPos) const int BattleInfo::getAvaliableHex(TCreature creID, bool attackerOwned, int initialPos) const
{ {
int pos; int pos;
@ -391,23 +425,15 @@ int BattleInfo::getAvaliableHex(TCreature creID, bool attackerOwned, int initial
bool ac[GameConstants::BFIELD_SIZE]; bool ac[GameConstants::BFIELD_SIZE];
std::set<BattleHex> occupyable; std::set<BattleHex> occupyable;
bool twoHex = VLC->creh->creatures[creID]->isDoubleWide(); bool twoHex = VLC->creh->creatures[creID]->isDoubleWide();
bool flying = VLC->creh->creatures[creID]->isFlying();// vstd::contains(VLC->creh->creatures[creID]->bonuses, Bonus::FLYING); bool flying = VLC->creh->creatures[creID]->isFlying();// vstd::contains(VLC->creh->creatures[creID]->bonuses, Bonus::FLYING);
getAccessibilityMap(ac, twoHex, attackerOwned, true, occupyable, flying); getAccessibilityMap (ac, twoHex, attackerOwned, true, occupyable, flying);
for (int g = pos; (-1 < g) && (g < GameConstants::BFIELD_SIZE); )
{
if ((g % GameConstants::BFIELD_WIDTH != 0) && (g % GameConstants::BFIELD_WIDTH != GameConstants::BFIELD_WIDTH-1) && BattleInfo::isAccessible (g, ac, twoHex, attackerOwned, flying, true))
{
pos = g;
break;
}
if (attackerOwned)
++g; //probably some more sophisticated range-based iteration is needed
else
--g;
}
return pos; if (!occupyable.size())
return -1; //all tiles are covered
return getClosestTile (attackerOwned, initialPos, occupyable);
} }
bool BattleInfo::isStackBlocked(const CStack * stack) const bool BattleInfo::isStackBlocked(const CStack * stack) const

View File

@ -92,6 +92,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode
const CStack * getStackT(BattleHex tileID, bool onlyAlive = true) const; const CStack * getStackT(BattleHex tileID, bool onlyAlive = true) const;
void getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<BattleHex> & occupyable, bool flying, const CStack* stackToOmmit = NULL) const; //send pointer to at least 187 allocated bytes void getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<BattleHex> & occupyable, bool flying, const CStack* stackToOmmit = NULL) const; //send pointer to at least 187 allocated bytes
static bool isAccessible(BattleHex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS static bool isAccessible(BattleHex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS
BattleHex getClosestTile (bool attackerOwned, int initialPos, std::set<BattleHex> & possibilities) const; //TODO: vector or set? copying one to another is bad
int getAvaliableHex(TCreature creID, bool attackerOwned, int initialPos = -1) const; //find place for summon / clone effects int getAvaliableHex(TCreature creID, bool attackerOwned, int initialPos = -1) const; //find place for summon / clone effects
void makeBFS(BattleHex start, bool*accessibility, BattleHex *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying, bool fillPredecessors) const; //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result void makeBFS(BattleHex start, bool*accessibility, BattleHex *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying, bool fillPredecessors) const; //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result
std::pair< std::vector<BattleHex>, int > getPath(BattleHex start, BattleHex dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes std::pair< std::vector<BattleHex>, int > getPath(BattleHex start, BattleHex dest, bool*accessibility, bool flyingCreature, bool twoHex, bool attackerOwned); //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes

View File

@ -946,6 +946,34 @@ ui8 CStackInstance::bearerType() const
return ArtBearer::CREATURE; return ArtBearer::CREATURE;
} }
CCommanderInstance::CCommanderInstance()
{
init();
}
CCommanderInstance::CCommanderInstance (TCreature id)
{
init();
CStackInstance (id, 1); //init with single unit
name = "Commando"; //TODO - parse them
}
void CCommanderInstance::init()
{
alive = true;
experience = 0;
count = 0;
type = NULL;
idRand = -1;
_armyObj = NULL;
setNodeType (Bonus::COMMANDER);
}
CCommanderInstance::~CCommanderInstance()
{
}
CStackBasicDescriptor::CStackBasicDescriptor() CStackBasicDescriptor::CStackBasicDescriptor()
{ {
type = NULL; type = NULL;

View File

@ -28,6 +28,7 @@ public:
class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CArtifactSet class DLL_LINKAGE CStackInstance : public CBonusSystemNode, public CStackBasicDescriptor, public CArtifactSet
{ {
protected:
const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object const CArmedInstance *_armyObj; //stack must be part of some army, army must be part of some object
public: public:
int idRand; //hlp variable used during loading game -> "id" placeholder for randomization int idRand; //hlp variable used during loading game -> "id" placeholder for randomization
@ -56,7 +57,7 @@ public:
si32 magicResistance() const; si32 magicResistance() const;
int getCreatureID() const; //-1 if not available int getCreatureID() const; //-1 if not available
std::string getName() const; //plural or singular std::string getName() const; //plural or singular
void init(); virtual void init();
CStackInstance(); CStackInstance();
CStackInstance(TCreature id, TQuantity count); CStackInstance(TCreature id, TQuantity count);
CStackInstance(const CCreature *cre, TQuantity count); CStackInstance(const CCreature *cre, TQuantity count);
@ -65,7 +66,7 @@ public:
void setType(int creID); void setType(int creID);
void setType(const CCreature *c); void setType(const CCreature *c);
void setArmyObj(const CArmedInstance *ArmyObj); void setArmyObj(const CArmedInstance *ArmyObj);
void giveStackExp(expType exp); virtual void giveStackExp(expType exp);
bool valid(bool allowUnrandomized) const; bool valid(bool allowUnrandomized) const;
ui8 bearerType() const OVERRIDE; //from CArtifactSet ui8 bearerType() const OVERRIDE; //from CArtifactSet
virtual std::string nodeName() const OVERRIDE; //from CBonusSystemnode virtual std::string nodeName() const OVERRIDE; //from CBonusSystemnode
@ -74,6 +75,7 @@ public:
class DLL_LINKAGE CCommanderInstance : public CStackInstance class DLL_LINKAGE CCommanderInstance : public CStackInstance
{ {
public:
//TODO: what if Commander is not a part of creature set? //TODO: what if Commander is not a part of creature set?
//commander class is determined by its base creature //commander class is determined by its base creature
@ -81,6 +83,10 @@ class DLL_LINKAGE CCommanderInstance : public CStackInstance
std::string name; // each Commander has different name std::string name; // each Commander has different name
std::vector <std::pair <ui8, ui8> > secondarySkills; //ID, level std::vector <std::pair <ui8, ui8> > secondarySkills; //ID, level
//std::vector <CArtifactInstance *> arts; //std::vector <CArtifactInstance *> arts;
void init();
CCommanderInstance();
CCommanderInstance (TCreature id);
~CCommanderInstance();
ui64 getPower() const {return 0;}; ui64 getPower() const {return 0;};
int getExpRank() const {return 0;}; int getExpRank() const {return 0;};

View File

@ -711,6 +711,7 @@ CGHeroInstance::CGHeroInstance()
visitedTown = NULL; visitedTown = NULL;
type = NULL; type = NULL;
boat = NULL; boat = NULL;
commander = NULL;
sex = 0xff; sex = 0xff;
secSkills.push_back(std::make_pair(-1, -1)); secSkills.push_back(std::make_pair(-1, -1));
speciality.setNodeType(CBonusSystemNode::SPECIALITY); speciality.setNodeType(CBonusSystemNode::SPECIALITY);
@ -773,6 +774,11 @@ void CGHeroInstance::initHero()
} }
assert(validTypes()); assert(validTypes());
if (GameConstants::COMMANDERS)
{
commander = new CCommanderInstance (VLC->creh->factionCommanders[type->heroType / 2]); //hopefully it returns town type
}
hoverName = VLC->generaltexth->allTexts[15]; hoverName = VLC->generaltexth->allTexts[15];
boost::algorithm::replace_first(hoverName,"%s",name); boost::algorithm::replace_first(hoverName,"%s",name);
boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name); boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name);

View File

@ -327,7 +327,7 @@ public:
h & exp & level & name & biography & portrait & mana & secSkills & movement h & exp & level & name & biography & portrait & mana & secSkills & movement
& sex & inTownGarrison & /*artifacts & artifWorn & */spells & patrol & moveDir; & sex & inTownGarrison & /*artifacts & artifWorn & */spells & patrol & moveDir;
h & type & speciality; h & type & speciality & commander;
BONUS_TREE_DESERIALIZATION_FIX BONUS_TREE_DESERIALIZATION_FIX
//visitied town pointer will be restored by map serialization method //visitied town pointer will be restored by map serialization method
} }

View File

@ -213,6 +213,7 @@ struct DLL_LINKAGE Bonus
CAMPAIGN_BONUS, CAMPAIGN_BONUS,
SPECIAL_WEEK, SPECIAL_WEEK,
STACK_EXPERIENCE, STACK_EXPERIENCE,
COMMANDER, //TODO: consider using simply STACK_INSTANCE
OTHER /*used for defensive stance and default value of spell level limit*/ OTHER /*used for defensive stance and default value of spell level limit*/
}; };

View File

@ -85,6 +85,7 @@ void registerTypes1(Serializer &s)
s.template registerType<CArtifact>(); s.template registerType<CArtifact>();
s.template registerType<CCreature>(); s.template registerType<CCreature>();
s.template registerType<CStackInstance>(); s.template registerType<CStackInstance>();
s.template registerType<CCommanderInstance>();
s.template registerType<PlayerState>(); s.template registerType<PlayerState>();
s.template registerType<TeamState>(); s.template registerType<TeamState>();
s.template registerType<CGameState>(); s.template registerType<CGameState>();

View File

@ -25,6 +25,7 @@ class CArtifactInstance;
class CGDefInfo; class CGDefInfo;
class CGObjectInstance; class CGObjectInstance;
class CGHeroInstance; class CGHeroInstance;
class CCommanderInstance;
class CGCreature; class CGCreature;
class CQuest; class CQuest;
class CGTownInstance; class CGTownInstance;
@ -305,6 +306,7 @@ struct DLL_LINKAGE Mapa : public CMapHeader
std::vector< ConstTransitivePtr<CGHeroInstance> > heroes; std::vector< ConstTransitivePtr<CGHeroInstance> > heroes;
std::vector< ConstTransitivePtr<CGTownInstance> > towns; std::vector< ConstTransitivePtr<CGTownInstance> > towns;
std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances; //stores all artifacts std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances; //stores all artifacts
//std::vector< ConstTransitivePtr<CCommanderInstance> > commanders;
//bmap<ui16, ConstTransitivePtr<CGCreature> > monsters; //bmap<ui16, ConstTransitivePtr<CGCreature> > monsters;
//bmap<ui16, ConstTransitivePtr<CGHeroInstance> > heroesToBeat; //bmap<ui16, ConstTransitivePtr<CGHeroInstance> > heroesToBeat;