mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
- More commanders
- Improved finding closest tiles on battlefield
This commit is contained in:
parent
81e74f8c33
commit
96d198758c
@ -1753,6 +1753,10 @@
|
||||
"level": 0,
|
||||
"name": [ "Paladin1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
@ -1761,6 +1765,10 @@
|
||||
"level": 0,
|
||||
"name": [ "Hierophant1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
@ -1769,6 +1777,10 @@
|
||||
"level": 0,
|
||||
"name": [ "TempleGuardian1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
@ -1777,6 +1789,10 @@
|
||||
"level": 0,
|
||||
"name": [ "Succubus1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
@ -1785,6 +1801,10 @@
|
||||
"level": 0,
|
||||
"name": [ "SoulEater1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
@ -1793,6 +1813,10 @@
|
||||
"level": 0,
|
||||
"name": [ "Brute1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
@ -1801,6 +1825,10 @@
|
||||
"level": 0,
|
||||
"name": [ "OgreLeader1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
@ -1809,6 +1837,10 @@
|
||||
"level": 0,
|
||||
"name": [ "Shaman1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
@ -1817,6 +1849,10 @@
|
||||
"level": 0,
|
||||
"name": [ "AstralSpirit1" ],
|
||||
"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"
|
||||
},
|
||||
|
||||
|
@ -376,6 +376,40 @@ std::vector<BattleHex> BattleInfo::getAccessibility( const CStack * stack, bool
|
||||
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 pos;
|
||||
@ -391,23 +425,15 @@ int BattleInfo::getAvaliableHex(TCreature creID, bool attackerOwned, int initial
|
||||
|
||||
bool ac[GameConstants::BFIELD_SIZE];
|
||||
std::set<BattleHex> occupyable;
|
||||
|
||||
bool twoHex = VLC->creh->creatures[creID]->isDoubleWide();
|
||||
bool flying = VLC->creh->creatures[creID]->isFlying();// vstd::contains(VLC->creh->creatures[creID]->bonuses, Bonus::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;
|
||||
}
|
||||
getAccessibilityMap (ac, twoHex, attackerOwned, true, occupyable, flying);
|
||||
|
||||
return pos;
|
||||
if (!occupyable.size())
|
||||
return -1; //all tiles are covered
|
||||
|
||||
return getClosestTile (attackerOwned, initialPos, occupyable);
|
||||
}
|
||||
|
||||
bool BattleInfo::isStackBlocked(const CStack * stack) const
|
||||
|
@ -92,6 +92,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -946,6 +946,34 @@ ui8 CStackInstance::bearerType() const
|
||||
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()
|
||||
{
|
||||
type = NULL;
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
|
||||
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
|
||||
public:
|
||||
int idRand; //hlp variable used during loading game -> "id" placeholder for randomization
|
||||
@ -56,7 +57,7 @@ public:
|
||||
si32 magicResistance() const;
|
||||
int getCreatureID() const; //-1 if not available
|
||||
std::string getName() const; //plural or singular
|
||||
void init();
|
||||
virtual void init();
|
||||
CStackInstance();
|
||||
CStackInstance(TCreature id, TQuantity count);
|
||||
CStackInstance(const CCreature *cre, TQuantity count);
|
||||
@ -65,7 +66,7 @@ public:
|
||||
void setType(int creID);
|
||||
void setType(const CCreature *c);
|
||||
void setArmyObj(const CArmedInstance *ArmyObj);
|
||||
void giveStackExp(expType exp);
|
||||
virtual void giveStackExp(expType exp);
|
||||
bool valid(bool allowUnrandomized) const;
|
||||
ui8 bearerType() const OVERRIDE; //from CArtifactSet
|
||||
virtual std::string nodeName() const OVERRIDE; //from CBonusSystemnode
|
||||
@ -74,6 +75,7 @@ public:
|
||||
|
||||
class DLL_LINKAGE CCommanderInstance : public CStackInstance
|
||||
{
|
||||
public:
|
||||
//TODO: what if Commander is not a part of creature set?
|
||||
|
||||
//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::vector <std::pair <ui8, ui8> > secondarySkills; //ID, level
|
||||
//std::vector <CArtifactInstance *> arts;
|
||||
void init();
|
||||
CCommanderInstance();
|
||||
CCommanderInstance (TCreature id);
|
||||
~CCommanderInstance();
|
||||
|
||||
ui64 getPower() const {return 0;};
|
||||
int getExpRank() const {return 0;};
|
||||
|
@ -711,6 +711,7 @@ CGHeroInstance::CGHeroInstance()
|
||||
visitedTown = NULL;
|
||||
type = NULL;
|
||||
boat = NULL;
|
||||
commander = NULL;
|
||||
sex = 0xff;
|
||||
secSkills.push_back(std::make_pair(-1, -1));
|
||||
speciality.setNodeType(CBonusSystemNode::SPECIALITY);
|
||||
@ -773,6 +774,11 @@ void CGHeroInstance::initHero()
|
||||
}
|
||||
assert(validTypes());
|
||||
|
||||
if (GameConstants::COMMANDERS)
|
||||
{
|
||||
commander = new CCommanderInstance (VLC->creh->factionCommanders[type->heroType / 2]); //hopefully it returns town type
|
||||
}
|
||||
|
||||
hoverName = VLC->generaltexth->allTexts[15];
|
||||
boost::algorithm::replace_first(hoverName,"%s",name);
|
||||
boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name);
|
||||
|
@ -327,7 +327,7 @@ public:
|
||||
h & exp & level & name & biography & portrait & mana & secSkills & movement
|
||||
& sex & inTownGarrison & /*artifacts & artifWorn & */spells & patrol & moveDir;
|
||||
|
||||
h & type & speciality;
|
||||
h & type & speciality & commander;
|
||||
BONUS_TREE_DESERIALIZATION_FIX
|
||||
//visitied town pointer will be restored by map serialization method
|
||||
}
|
||||
|
@ -213,6 +213,7 @@ struct DLL_LINKAGE Bonus
|
||||
CAMPAIGN_BONUS,
|
||||
SPECIAL_WEEK,
|
||||
STACK_EXPERIENCE,
|
||||
COMMANDER, //TODO: consider using simply STACK_INSTANCE
|
||||
OTHER /*used for defensive stance and default value of spell level limit*/
|
||||
};
|
||||
|
||||
|
@ -85,6 +85,7 @@ void registerTypes1(Serializer &s)
|
||||
s.template registerType<CArtifact>();
|
||||
s.template registerType<CCreature>();
|
||||
s.template registerType<CStackInstance>();
|
||||
s.template registerType<CCommanderInstance>();
|
||||
s.template registerType<PlayerState>();
|
||||
s.template registerType<TeamState>();
|
||||
s.template registerType<CGameState>();
|
||||
|
@ -25,6 +25,7 @@ class CArtifactInstance;
|
||||
class CGDefInfo;
|
||||
class CGObjectInstance;
|
||||
class CGHeroInstance;
|
||||
class CCommanderInstance;
|
||||
class CGCreature;
|
||||
class CQuest;
|
||||
class CGTownInstance;
|
||||
@ -305,6 +306,7 @@ struct DLL_LINKAGE Mapa : public CMapHeader
|
||||
std::vector< ConstTransitivePtr<CGHeroInstance> > heroes;
|
||||
std::vector< ConstTransitivePtr<CGTownInstance> > towns;
|
||||
std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances; //stores all artifacts
|
||||
//std::vector< ConstTransitivePtr<CCommanderInstance> > commanders;
|
||||
//bmap<ui16, ConstTransitivePtr<CGCreature> > monsters;
|
||||
//bmap<ui16, ConstTransitivePtr<CGHeroInstance> > heroesToBeat;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user