mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Rewritten handling mouse movement over hex and l-clicking hex into one procedure. That way the tooltip and cursor are always accurate, because they're set by the same routing that selects action. Having that logic duplicated in two methods was unmaintainable. [though the new one is still monstrous...] By the way fixed numerous issues, including:
* #785 and parts of #760 * first aid tent can heal only creatures that suffered damage * war machines can't be healed by tent * creatures casting spells won't try to cast them during tactic phase * console tooltips for first aid tent * console tooltips for teleport spell * cursor is reset to pointer when action is requested * fixed a few other missing or wrong tooltips/cursors Implemented opening creature window by l-clicking on stack. Master Genie's spell is picked by server, not client. Minor changes.
This commit is contained in:
parent
e046f06421
commit
a9af0da0ab
File diff suppressed because it is too large
Load Diff
@ -130,7 +130,7 @@ private:
|
||||
bool spellDestSelectMode; //if true, player is choosing destination for his spell
|
||||
SpellSelectionType spellSelMode;
|
||||
BattleAction * spellToCast; //spell for which player is choosing destination
|
||||
ui32 creatureSpellToCast;
|
||||
si32 creatureSpellToCast;
|
||||
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
||||
|
||||
void showAliveStack(const CStack *stack, SDL_Surface * to); //helper function for function show
|
||||
@ -144,7 +144,6 @@ private:
|
||||
void projectileShowHelper(SDL_Surface * to); //prints projectiles present on the battlefield
|
||||
void giveCommand(ui8 action, BattleHex tile, ui32 stack, si32 additional=-1);
|
||||
bool isTileAttackable(const BattleHex & number) const; //returns true if tile 'number' is neighboring any tile from active stack's range or is one of these tiles
|
||||
bool blockedByObstacle(BattleHex hex) const;
|
||||
bool isCatapultAttackable(BattleHex hex) const; //returns true if given tile can be attacked by catapult
|
||||
|
||||
std::list<BattleEffect> battleEffects; //different animations to display on the screen like spell effects
|
||||
@ -243,12 +242,15 @@ public:
|
||||
void castThisSpell(int spellID); //called when player has chosen a spell from spellbook
|
||||
void displayEffect(ui32 effect, int destTile); //displays effect of a spell on the battlefield; affected: true - attacker. false - defender
|
||||
void battleTriggerEffect(const BattleTriggerEffect & bte);
|
||||
void setBattleCursor(const int myNumber); //really complex and messy
|
||||
void setBattleCursor(const int myNumber); //really complex and messy, sets attackingHex
|
||||
void endAction(const BattleAction* action);
|
||||
void hideQueue();
|
||||
void showQueue();
|
||||
SpellSelectionType selectionTypeByPositiveness(const CSpell & spell);
|
||||
|
||||
void handleHex(BattleHex myNumber, int eventType);
|
||||
|
||||
BattleHex fromWhichHexAttack(BattleHex myNumber);
|
||||
|
||||
friend class CPlayerInterface;
|
||||
friend class CAdventureMapButton;
|
||||
|
@ -527,9 +527,6 @@ CCreInfoWindow::CCreInfoWindow(const CStackInstance &stack, bool LClicked, boost
|
||||
|
||||
dismiss = new CAdventureMapButton("", CGI->generaltexth->zelp[445].second, dialog, 21, 237, "IVIEWCR2",SDLK_d);
|
||||
}
|
||||
|
||||
ok = new CAdventureMapButton("", CGI->generaltexth->zelp[445].second,
|
||||
boost::bind(&CCreInfoWindow::close,this), 216, 237, "IOKAY.DEF", SDLK_RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -612,9 +609,15 @@ void CCreInfoWindow::init(const CCreature *creature, const CBonusSystemNode *sta
|
||||
luck->set(stackNode);
|
||||
|
||||
if(!LClicked)
|
||||
{
|
||||
abilityText = new CLabel(17, 231, FONT_SMALL, TOPLEFT, Colors::Cornsilk, creature->abilityText);
|
||||
}
|
||||
else
|
||||
{
|
||||
abilityText = NULL;
|
||||
ok = new CAdventureMapButton("", CGI->generaltexth->zelp[445].second,
|
||||
boost::bind(&CCreInfoWindow::close,this), 216, 237, "IOKAY.DEF", SDLK_RETURN);
|
||||
}
|
||||
|
||||
//if we are displying window fo r stack in battle, there are several more things that we need to display
|
||||
if(const CStack *battleStack = dynamic_cast<const CStack*>(stackNode))
|
||||
@ -639,10 +642,10 @@ void CCreInfoWindow::clickRight(tribool down, bool previousState)
|
||||
close();
|
||||
}
|
||||
|
||||
CIntObject * createCreWindow(const CStack *s)
|
||||
CIntObject * createCreWindow(const CStack *s, bool lclick/* = false*/)
|
||||
{
|
||||
if(settings["general"]["classicCreatureWindow"].Bool())
|
||||
return new CCreInfoWindow(*s);
|
||||
return new CCreInfoWindow(*s, lclick);
|
||||
else
|
||||
return new CCreatureWindow(*s, CCreatureWindow::BATTLE);
|
||||
}
|
||||
|
@ -130,6 +130,6 @@ public:
|
||||
void show(SDL_Surface * to);
|
||||
};
|
||||
|
||||
CIntObject *createCreWindow(const CStack *s);
|
||||
CIntObject *createCreWindow(const CStack *s, bool lclick = false);
|
||||
CIntObject *createCreWindow(int Cid, int Type, int creatureCount);
|
||||
CIntObject *createCreWindow(const CStackInstance *s, int type, boost::function<void()> Upg = 0, boost::function<void()> Dsm = 0, UpgradeInfo *ui = NULL);
|
||||
|
@ -16,6 +16,17 @@ struct SDL_Surface;
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ECursor
|
||||
{
|
||||
enum ECursorTypes { ADVENTURE, COMBAT, DEFAULT, SPELLBOOK };
|
||||
|
||||
enum EBattleCursors { COMBAT_BLOCKED, COMBAT_MOVE, COMBAT_FLY, COMBAT_SHOOT,
|
||||
COMBAT_HERO, COMBAT_QUERY, COMBAT_POINTER,
|
||||
//various attack frames
|
||||
COMBAT_SHOOT_PENALTY = 15, COMBAT_SHOOT_CATAPULT, COMBAT_HEAL,
|
||||
COMBAT_SACRIFICE, COMBAT_TELEPORT};
|
||||
}
|
||||
|
||||
/// handles mouse cursor
|
||||
class CCursorHandler
|
||||
{
|
||||
|
@ -82,4 +82,9 @@ void BattleHex::checkAndPush(int tile, std::vector<BattleHex> & ret)
|
||||
if( tile>=0 && tile<GameConstants::BFIELD_SIZE && (tile%GameConstants::BFIELD_WIDTH != (GameConstants::BFIELD_WIDTH - 1))
|
||||
&& (tile%GameConstants::BFIELD_WIDTH != 0) )
|
||||
ret.push_back(BattleHex(tile));
|
||||
}
|
||||
|
||||
bool BattleHex::isAvailable() const
|
||||
{
|
||||
return isValid() && getX() > 0 && getX() < GameConstants::BFIELD_WIDTH-1;
|
||||
}
|
@ -106,4 +106,5 @@ struct DLL_LINKAGE BattleHex
|
||||
}
|
||||
static void checkAndPush(int tile, std::vector<BattleHex> & ret);
|
||||
|
||||
bool isAvailable() const; //valid position not in first or last column
|
||||
};
|
@ -1948,6 +1948,31 @@ ESpellCastProblem::ESpellCastProblem BattleInfo::battleCanCastThisSpellHere( int
|
||||
if(moreGeneralProblem != ESpellCastProblem::OK)
|
||||
return moreGeneralProblem;
|
||||
|
||||
if(spell->getTargetType() == CSpell::OBSTACLE && !isObstacleOnTile(dest))
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
|
||||
|
||||
//get dead stack if we cast resurrection or animate dead
|
||||
const CStack * stackUnder = getStackT(dest, false);
|
||||
|
||||
if(spell->isRisingSpell())
|
||||
{
|
||||
if(!stackUnder || stackUnder->alive())
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
if(spell->id == Spells::ANIMATE_DEAD && !stackUnder->hasBonusOfType(Bonus::UNDEAD))
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
if(spell->getTargetType() == CSpell::CREATURE)
|
||||
{
|
||||
if(!stackUnder)
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
if(spell->isNegative() && stackUnder->owner == player)
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
if(spell->isPositive() && stackUnder->owner != player)
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
|
||||
|
||||
if (mode != ECastingMode::CREATURE_ACTIVE_CASTING && mode != ECastingMode::ENCHANTER_CASTING)
|
||||
return battleIsImmune(getHero(player), spell, mode, dest);
|
||||
else
|
||||
@ -2333,6 +2358,18 @@ int BattleInfo::getIdForNewStack() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BattleInfo::isObstacleOnTile(BattleHex tile) const
|
||||
{
|
||||
std::set<BattleHex> coveredHexes;
|
||||
BOOST_FOREACH(const CObstacleInstance &obs, obstacles)
|
||||
{
|
||||
std::vector<BattleHex> blocked = VLC->heroh->obstacles.find(obs.ID)->second.getBlocked(obs.pos);
|
||||
for(size_t w = 0; w < blocked.size(); ++w)
|
||||
coveredHexes.insert(blocked[w]);
|
||||
}
|
||||
return vstd::contains(coveredHexes, tile);
|
||||
}
|
||||
|
||||
CStack::CStack(const CStackInstance *Base, int O, int I, bool AO, int S)
|
||||
: base(Base), ID(I), owner(O), slot(S), attackerOwned(AO),
|
||||
counterAttacks(1)
|
||||
@ -2861,6 +2898,13 @@ bool CStack::isValidTarget(bool allowDead/* = false*/) const /*alive non-turret
|
||||
return (alive() || allowDead) && position.isValid();
|
||||
}
|
||||
|
||||
bool CStack::canBeHealed() const
|
||||
{
|
||||
return firstHPleft != MaxHealth()
|
||||
&& alive()
|
||||
&& !hasBonusOfType(Bonus::SIEGE_WEAPON);
|
||||
}
|
||||
|
||||
bool CMP_stack::operator()( const CStack* a, const CStack* b )
|
||||
{
|
||||
switch(phase)
|
||||
|
@ -96,6 +96,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode
|
||||
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::vector<BattleHex> getAccessibility(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable = NULL) const; //returns vector of accessible tiles (taking into account the creature range)
|
||||
|
||||
bool isObstacleOnTile(BattleHex tile) const;
|
||||
bool isStackBlocked(const CStack * stack) const; //returns true if there is neighboring enemy stack
|
||||
|
||||
ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool deathBlow, bool ballistaDoubleDmg); //charge - number of hexes travelled before attack (for champion's jousting)
|
||||
@ -188,6 +189,7 @@ public:
|
||||
bool ableToRetaliate() const; //if stack can retaliate after attacked
|
||||
bool moved(int turn = 0) const; //if stack was already moved this turn
|
||||
bool canMove(int turn = 0) const; //if stack can move
|
||||
bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines
|
||||
ui32 Speed(int turn = 0, bool useBind = false) const; //get speed of creature with all modificators
|
||||
si32 magicResistance() const; //include aura of resistance
|
||||
static void stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse);
|
||||
|
@ -215,6 +215,11 @@ bool CSpell::isNegative() const
|
||||
return positiveness == NEGATIVE;
|
||||
}
|
||||
|
||||
bool CSpell::isRisingSpell() const
|
||||
{
|
||||
return vstd::contains(VLC->spellh->risingSpells, id);
|
||||
}
|
||||
|
||||
static bool startsWithX(const std::string &s)
|
||||
{
|
||||
return s.size() && s[0] == 'x';
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
|
||||
bool isPositive() const;
|
||||
bool isNegative() const;
|
||||
bool isRisingSpell() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -133,7 +133,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCreatureCastT
|
||||
return gs->curB->battleCanCastThisSpellHere(player, spell, ECastingMode::CREATURE_ACTIVE_CASTING, destination);
|
||||
}
|
||||
|
||||
TSpell CBattleInfoCallback::battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode)
|
||||
si32 CBattleInfoCallback::battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
@ -199,11 +199,11 @@ int CBattleInfoCallback::battleGetBattlefieldType()
|
||||
return gs->curB->battlefieldType;
|
||||
}
|
||||
|
||||
int CBattleInfoCallback::battleGetObstaclesAtTile(BattleHex tile) //returns bitfield
|
||||
{
|
||||
//TODO - write
|
||||
return -1;
|
||||
}
|
||||
// int CBattleInfoCallback::battleGetObstaclesAtTile(BattleHex tile) //returns bitfield
|
||||
// {
|
||||
// //TODO - write
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
std::vector<CObstacleInstance> CBattleInfoCallback::battleGetAllObstacles()
|
||||
{
|
||||
@ -405,6 +405,13 @@ const CGHeroInstance * CBattleInfoCallback::battleGetFightingHero(ui8 side) cons
|
||||
return gs->curB->heroes[side];
|
||||
}
|
||||
|
||||
bool CBattleInfoCallback::battleIsBlockedByObstacle(BattleHex tile)
|
||||
{
|
||||
if(!gs->curB)
|
||||
return 0;
|
||||
|
||||
return gs->curB->isObstacleOnTile(tile);
|
||||
}
|
||||
|
||||
|
||||
CGameState *const CPrivilagedInfoCallback::gameState ()
|
||||
|
@ -94,7 +94,8 @@ public:
|
||||
|
||||
//battle
|
||||
int battleGetBattlefieldType(); // 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
||||
int battleGetObstaclesAtTile(BattleHex tile); //returns bitfield
|
||||
//int battleGetObstaclesAtTile(BattleHex tile); //returns bitfield
|
||||
bool battleIsBlockedByObstacle(BattleHex tile);
|
||||
std::vector<CObstacleInstance> battleGetAllObstacles(); //returns all obstacles on the battlefield
|
||||
const CStack * battleGetStackByID(int ID, bool onlyAlive = true); //returns stack info by given ID
|
||||
const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true); //returns stack info by given pos
|
||||
@ -110,7 +111,7 @@ public:
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell); //determines if given spell can be casted (and returns problem description)
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell, BattleHex destination); //if hero can cast spell here
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination); //determines if creature can cast a spell here
|
||||
ui32 battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode);
|
||||
si32 battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode);
|
||||
bool battleCanFlee(); //returns true if caller can flee from the battle
|
||||
int battleGetSurrenderCost(); //returns cost of surrendering battle, -1 if surrendering is not possible
|
||||
const CGTownInstance * battleGetDefendedTown(); //returns defended town if current battle is a siege, NULL instead
|
||||
@ -121,6 +122,10 @@ public:
|
||||
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //returns hero corresponding to given side (0 - attacker, 1 - defender)
|
||||
si8 battleHasDistancePenalty(const CStack * stack, BattleHex destHex); //checks if given stack has distance penalty
|
||||
si8 battleHasWallPenalty(const CStack * stack, BattleHex destHex); //checks if given stack has wall penalty
|
||||
si8 battleHasShootingPenalty(const CStack * stack, BattleHex destHex)
|
||||
{
|
||||
return battleHasDistancePenalty(stack, destHex) || battleHasWallPenalty(stack, destHex);
|
||||
}
|
||||
si8 battleCanTeleportTo(const CStack * stack, BattleHex destHex, int telportLevel); //checks if teleportation of given stack to given position can take place
|
||||
si8 battleGetTacticDist(); //returns tactic distance for calling player or 0 if player is not in tactic phase
|
||||
ui8 battleGetMySide(); //return side of player in battle (attacker/defender)
|
||||
|
@ -3367,19 +3367,29 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
int spellID = ba.additionalInfo;
|
||||
BattleHex destination(ba.destinationTile);
|
||||
|
||||
int spellLvl = 0;
|
||||
Bonus * bonus = stack->getBonus(Selector::typeSubtype(Bonus::SPELLCASTER, spellID));
|
||||
if (bonus)
|
||||
vstd::amax(spellLvl, bonus->val);
|
||||
bonus = stack->getBonus(Selector::type(Bonus::RANDOM_SPELLCASTER));
|
||||
if (bonus)
|
||||
vstd::amax(spellLvl, bonus->val);
|
||||
vstd::amin (spellLvl, 3);
|
||||
const Bonus *randSpellcaster = stack->getBonus(Selector::type(Bonus::RANDOM_SPELLCASTER));
|
||||
const Bonus * spellcaster = stack->getBonus(Selector::typeSubtype(Bonus::SPELLCASTER, spellID));
|
||||
|
||||
int casterSide = gs->curB->whatSide(stack->owner);
|
||||
const CGHeroInstance * secHero = gs->curB->getHero(gs->curB->theOtherPlayer(stack->owner));
|
||||
//TODO special bonus for genies ability
|
||||
if(randSpellcaster && battleGetRandomStackSpell(stack, CBattleInfoCallback::RANDOM_AIMED) < 0)
|
||||
spellID = battleGetRandomStackSpell(stack, CBattleInfoCallback::RANDOM_GENIE);
|
||||
|
||||
handleSpellCasting(spellID, spellLvl, destination, casterSide, stack->owner, NULL, secHero, 0, ECastingMode::CREATURE_ACTIVE_CASTING, stack);
|
||||
if(spellID < 0)
|
||||
complain("That stack can't cast spells!");
|
||||
else
|
||||
{
|
||||
int spellLvl = 0;
|
||||
if (spellcaster)
|
||||
vstd::amax(spellLvl, spellcaster->val);
|
||||
if (randSpellcaster)
|
||||
vstd::amax(spellLvl, randSpellcaster->val);
|
||||
vstd::amin (spellLvl, 3);
|
||||
|
||||
int casterSide = gs->curB->whatSide(stack->owner);
|
||||
const CGHeroInstance * secHero = gs->curB->getHero(gs->curB->theOtherPlayer(stack->owner));
|
||||
|
||||
handleSpellCasting(spellID, spellLvl, destination, casterSide, stack->owner, NULL, secHero, 0, ECastingMode::CREATURE_ACTIVE_CASTING, stack);
|
||||
}
|
||||
|
||||
sendAndApply(&end_action);
|
||||
break;
|
||||
|
@ -80,7 +80,7 @@ struct CasualtiesAfterBattle
|
||||
void takeFromArmy(CGameHandler *gh);
|
||||
};
|
||||
|
||||
class CGameHandler : public IGameCallback
|
||||
class CGameHandler : public IGameCallback, CBattleInfoCallback
|
||||
{
|
||||
private:
|
||||
void makeStackDoNothing(const CStack * next);
|
||||
|
Loading…
Reference in New Issue
Block a user